struct A(T) { }
pragma(msg, is(const A!int == A!int)); // false
pragma(msg, is(const A!int == A!T, T)); // true
Intuitively, const A!int
cannot be == A!T
for any T
, but DMD insists it is. If you are curious, it infers T
to be int
.
The same happens with the implicit-convertibility check, though we need an indirection to observe it:
struct B(T) { int* p; }
pragma(msg, is(const B!int: B!int)); // false
pragma(msg, is(const B!int: B!T, T)); // true
So, if a TemplateParameterList is present, the type checker ignores all qualifiers (even shared
) on both LHS and RHS. The spec does not mention such behavior in either is
expressions or template-parameter deduction.
I wonder if it is a bug or a deliberate decision. If former, fixing it can potentially break a lot of code dependent on the buggy behavior (so yet another -preview
?..). For example, std.sumtype
is affected:
enum bool isSumType(T) = is(T : SumType!Args, Args...);
(This should be is(immutable T : immutable SumType!Args, Args...)
: we use immutable
to erase other qualifiers.)
If it was intended to work this way, then IMO it’s a huge gotcha that should be described in the docs. If so, could somebody explain why it was designed such?
Discovered by Andrey Zherikov and me.