Thread overview
[Issue 19303] hasMember fails to recognize member (interaction with mixin template)
Oct 12, 2018
Luís Marques
Nov 28, 2018
Eduard Staniloiu
Nov 28, 2018
Eduard Staniloiu
Nov 28, 2018
Eduard Staniloiu
Mar 21, 2021
Boris Carvajal
Dec 17, 2022
Iain Buclaw
October 12, 2018
https://issues.dlang.org/show_bug.cgi?id=19303

Luís Marques <luis@luismarques.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Hardware|x86                         |All
                 OS|Mac OS X                    |All
           Severity|enhancement                 |normal

--
November 28, 2018
https://issues.dlang.org/show_bug.cgi?id=19303

Eduard Staniloiu <edi33416@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |edi33416@gmail.com

--- Comment #1 from Eduard Staniloiu <edi33416@gmail.com> ---
This is most definitely a compiler bug which seems to be related/triggered my the template mixin, as `std.traits.hasMember` only calls the equivalent `__traits(hasMember, T, memberName)` compiler trait.

As a workaround, you can use
static assert(__traits(hasMember, P, "ElementType")); // passes


Also, weirdly enough, swapping the mixin instantiation with the `static if` block in `Port`, will pass the initial assert

```
struct Port(SomeSignal)
{
    static if(hasMember!(SomeSignal, "ElementType"))
        alias ElementType = SomeSignal.ElementType;

    mixin SignalOps;
}

void main()
{
    ...
    static assert(hasMember!(P, "ElementType")); // OK
    static assert(__traits(hasMember, P, "ElementType")); // OK
}
```

You can check this on https://run.dlang.io/is/6aXcGq

--
November 28, 2018
https://issues.dlang.org/show_bug.cgi?id=19303

--- Comment #2 from Eduard Staniloiu <edi33416@gmail.com> ---
What is even weirder, if you define your own `hasMember` wrapper, that works just fine with the initial definition of Port

```
enum hasM(T, string name) = __traits(hasMember, T, name);

static assert(hasM!(P, "ElementType")); // ok
```

As reflected by https://run.dlang.io/is/pKYL9B

--
November 28, 2018
https://issues.dlang.org/show_bug.cgi?id=19303

Eduard Staniloiu <edi33416@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|phobos                      |dmd

--
March 21, 2021
https://issues.dlang.org/show_bug.cgi?id=19303

Boris Carvajal <boris2.9@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |boris2.9@gmail.com

--- Comment #3 from Boris Carvajal <boris2.9@gmail.com> ---
There are 2 issues here:

1) Currently, DMD can't see forward references that are declared inside subsequent declaration scopes (things like 'static if' or 'static foreach'), this is hard to solve because the compiler could jump to a later scope looking for what it needs but that scope could also need something from the previous, a chicken and egg problem.

2) Template instances are cached, if the first instance of 'hasMember!(S,
ElementType")' evaluates to false, it will always return false.

Code:
---
enum hasM(T, string name) = __traits(hasMember, T, name);

struct S
{
    // ElementType is not yet defined so it evaluates to false and the
    // pragma(hasM) below will print false.
    // Commenting out this 'static if' will make the pragma(hasM) print true
    // because the three pragmas are evaluated much later than 'struct S'.
    static if(hasM!(S, "ElementType")) { }

    static if(1)
        alias ElementType = int;
}

void main()
{
    pragma(msg, S.ElementType); // int
    pragma(msg, hasM!(S, "ElementType")); // depends on the first instantiation
    pragma(msg, __traits(hasMember, S, "ElementType"));  // true
}
---

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=19303

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--