Bug 16390 – __traits not accepted where a type is expected
Status
RESOLVED
Resolution
FIXED
Severity
minor
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-08-15T13:15:47Z
Last change time
2020-03-21T03:56:37Z
Keywords
spec
Assigned to
No Owner
Creator
Lodovico Giaretta
Comments
Comment #0 by lodovico — 2016-08-15T13:15:47Z
For example, this does not work:
template ParentType(T)
{
alias ParentType = __traits(parent, T);
}
This leads to awkward workarounds:
template ParentType(T)
{
alias ParentType = AliasSeq!(__traits(parent, T))[0];
}
Comment #1 by b2.temp — 2016-08-15T16:06:43Z
This is really common to use typeof() on the result of a __traits()
template ParentType(T)
{
alias ParentType = typeof(__traits(parent, T));
}
Comment #2 by lodovico — 2016-08-15T17:26:24Z
(In reply to b2.temp from comment #1)
> This is really common to use typeof() on the result of a __traits()
>
> template ParentType(T)
> {
> alias ParentType = typeof(__traits(parent, T));
> }
If this was meant to be a workaround, it doesn't seem to work for me (the trait returns a type, while typeof expects an expression).
If it was meant to be another situation where __traits should be allowed but are not, it looks like they are currently allowed inside typeof.
Comment #3 by b2.temp — 2016-08-15T18:27:39Z
(In reply to Lodovico Giaretta from comment #2)
> (In reply to b2.temp from comment #1)
> If this was meant to be a workaround, it doesn't seem to work for me (the
> trait returns a type, while typeof expects an expression).
>
> If it was meant to be another situation where __traits should be allowed but
> are not, it looks like they are currently allowed inside typeof.
Yes, second case, sorry. It clearly doesn't work with the parent __traits.
Comment #4 by issues.dlang — 2016-08-15T19:23:19Z
Similarly,
template members(T)
{
alias members = __traits(allMembers, T);
}
doesn't work, whereas
template members(T)
{
alias members = AliasSeq!(__traits(allMembers, T));
}
does. And that's even more bizarre when you consider not only that AliasSeq is supposed to be equivalent to the "tuple" that the compiler uses for stuff like the result of __traits(allMembers, T), but this code
import std.meta;
template members(T)
{
alias members = AliasSeq!(__traits(allMembers, T));
}
struct S
{
int i;
string s;
}
void main()
{
pragma(msg, __traits(allMembers, S));
pragma(msg, AliasSeq!(__traits(allMembers, S)));
pragma(msg, members!S);
}
prints
tuple("i", "s")
tuple("i", "s")
tuple("i", "s")
meaning that all 3 are equivalent as far as pragma(msg, ...) is concerned. And changing main to
pragma(msg, typeof(__traits(allMembers, S)));
pragma(msg, typeof(AliasSeq!(__traits(allMembers, S))));
pragma(msg, typeof(members!S));
results in
(string, string)
(string, string)
(string, string)
So, it really seems like the fact that the result of __traits can't be aliased is a bug. And if it's not a bug, then it's an unnecessary (and confusing) inconsistency, and IMHO, it really should be fixed.