You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In the code quoted below, there is an inconsistency between these two lines:
pragma(msg, P.ElementType);static assert(hasMember!(P, "ElementType"));
The pragma correctly prints the P.ElementType, but the hasMember assert fails. The interaction with the mixin template suggests this might be a compiler bug, but for now I'm only marking this as a Phobos bug. A workaround would be appreciated.
--
import std.traits;
void main()
{
alias V = Vec!Bool;
alias P = Port!(V);
pragma(msg, P.ElementType);
static assert(hasMember!(P, "ElementType"));
}
mixin template SignalOps()
{
static if(hasMember!(typeof(this), "ElementType")) { }
}
struct Bool {}
struct Port(SomeSignal)
{
mixin SignalOps;
static if(hasMember!(SomeSignal, "ElementType")) alias ElementType = SomeSignal.ElementType;
}
struct Vec(SomeSignal)
{
alias ElementType = SomeSignal;
}
The text was updated successfully, but these errors were encountered:
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
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
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
}
---
Luís Marques (@luismarques) reported this on 2018-10-12T13:59:40Z
Transferred from https://issues.dlang.org/show_bug.cgi?id=19303
CC List
Description
In the code quoted below, there is an inconsistency between these two lines: pragma(msg, P.ElementType); static assert(hasMember!(P, "ElementType")); The pragma correctly prints the P.ElementType, but the hasMember assert fails. The interaction with the mixin template suggests this might be a compiler bug, but for now I'm only marking this as a Phobos bug. A workaround would be appreciated. -- import std.traits; void main() { alias V = Vec!Bool; alias P = Port!(V); pragma(msg, P.ElementType); static assert(hasMember!(P, "ElementType")); } mixin template SignalOps() { static if(hasMember!(typeof(this), "ElementType")) { } } struct Bool {} struct Port(SomeSignal) { mixin SignalOps; static if(hasMember!(SomeSignal, "ElementType")) alias ElementType = SomeSignal.ElementType; } struct Vec(SomeSignal) { alias ElementType = SomeSignal; }The text was updated successfully, but these errors were encountered: