Connecting two pointers/slices of class handles results in weird error messages and behavior. @safe: // disables constant folding! bool condValue; bool cond() { return condValue; }; class Base { } class Derived : Base { } Base base; Derived derived; static this() { base = new Base; derived = new Derived; condValue = false; } Base[] baseArr; Derived[] derivedArr; In this setup, the expression auto arr = cond() ? baseArr : derivedArr; gives the error message Error: incompatible types for (baseArr) : (derivedArr): Base[] and Derived[] while clearly const(Base)[] is the best common type. If this is not liked, void*[] is another option. Explicitly casting `derivedArr` to `const(Base)[]` solves that. It hinders type inference and usage of `auto`, but fortunately, it won't do actual harm. Creating pointers is no issue. Base* basePtr = &base; Derived* derivedPtr = &derived; Connecting them in a tenery expression gives an undescriptive error message: Error: cannot implicitly convert expression [..] of type Base* to Base* This is useless while the type should be const(Base)*. Surprisingly, this statement compiles: *(cond() ? basePtr : derivedPtr) = new Base(); Note that cond() returns false, i.e. derivedPtr now points to a Base object. Note that this is @safe code.
The same is true for interfaces: interface I { } interface A : I { } bool condValue; bool cond() { return condValue; } pragma(msg, typeof(cond() ? &a : cond() ? &b : &i)); // I* I* iPtr = cond() ? &a : &i; // fails with error message: cannot assign I* to I* const(I)* iPtr = cond() ? &a : &i; // succeeds (cond() ? a : i) = i; // succeeds and breaks @safe
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19533 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB