Possibly a unification bug in the type checker

Nickolay Bukreyev buknik95 at ya.ru
Fri Dec 29 19:50:35 UTC 2023


```d
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:

```d
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][is] or [template-parameter deduction][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][is-sum-type]:

```d
enum bool isSumType(T) = is(T : SumType!Args, Args...);
```

(This should be `is(immutable T : immutable SumType!Args, 
Args...)`: we use `immutable` to [erase][qualifiers] 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][discovery] by Andrey Zherikov and me.

[is]: https://dlang.org/spec/expression.html#is-parameter-list
[deduction]: 
https://dlang.org/spec/template.html#argument_deduction
[is-sum-type]: 
https://github.com/dlang/phobos/blob/v2.106.0/std/sumtype.d#L1583
[qualifiers]: 
https://dlang.org/spec/const3.html#combining_qualifiers
[discovery]: 
https://github.com/andrey-zherikov/argparse/pull/143#discussion_r1434251705


More information about the Digitalmars-d mailing list