Does `is` expression with template alias need fixing.

Elfstone elfstone at yeah.net
Wed Mar 22 07:19:58 UTC 2023


On Tuesday, 21 March 2023 at 07:51:50 UTC, FeepingCreature wrote:
> On Saturday, 18 March 2023 at 01:15:35 UTC, Elfstone wrote:
>>
>> I'll perhaps try to read the compiler code someday, for now it 
>> sounds to me like a matter of whether people want to fix the 
>> bug or not, even if it involves fundamental redesign of the 
>> frontend, or an extra pass to scan for unresolvable cases by 
>> design.
>>
>> The compiler must at some point know that Foo is an alias, and 
>> that a particular param of isInstanceOf will be expanded to 
>> something inside `is(...)`. Store that info if not already, 
>> report an error when Foo is passed to isInstanceOf.
>
> To explain the mechanism:
>
> The compiler knows what the template parameters are that are 
> used to instantiate a `struct` that lives inside a template, 
> because this information is stored *with the struct*. It can do 
> this because - and only because! - the struct lives *uniquely* 
> inside one particular template instantiation. That is, you can 
> recover template parameters for precisely two cases, 
> [structs](https://github.com/dlang/dmd/blob/v2.102.2/compiler/src/dmd/dtemplate.d#L4312) and [classes](https://github.com/dlang/dmd/blob/v2.102.2/compiler/src/dmd/dtemplate.d#L4450):
>
> ```
> template Foo(T) {
>   struct Foo { }
> }
> ```
>
> You can do this because, and *only* because, the lexical parent 
> of `struct Foo` is `template Foo` with a given `T`. Template 
> parameter recovery works for types that have the property of 
> uniquely storing a lexical parent; it does not work for any 
> types that don't have this property.
>
> This cannot ever work:
>
> ```
> template identity(int i) { enum identity = i; }
>
> void foo() {
>     enum five = identity!5;
>     static assert(is(five == identity!y, int y) && y == 5);
> }
> ```
>
> It cannot work because `five` does not lexically reference 
> `identity` as a parent, because `five` is an int, and int is 
> not a type that is or can be uniquely associated with the 
> `identity` template.
>
> What you want needs a fundamentally new language feature; 
> something like typeclasses. Now there's an argument to be made 
> to add typeclasses to the language, they would make ranges a 
> lot more swanky for instance, but it's just not a matter of 
> making template inference marginally more powerful.

Wow, I didn't know this too wouldn't work. So 
`isInstanceOf!(identity, five)` will also yield `false`. But I 
can understand because like you said there's no way to infer `y`, 
unless 5 is somehow stored with `five`, which is just an `int`. 
It's quite different from `Matrix!(float, 3, 1)`.

I wouldn't call what I want a new feature, but a fix to this 
gaping hole in the language design (or implementation). People 
would expect an alias works the same as the original symbol, at 
least people need not care if they are using an alias from std 
(`Regex`), as long as the compiler will generate a warning where 
an alias might cause problems.


More information about the Digitalmars-d mailing list