Bug 19420 – [master] TypeTrait semantic fails for non static aggregate members
Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-11-21T21:13:38Z
Last change time
2018-11-26T14:42:39Z
Assigned to
No Owner
Creator
Basile-z
Comments
Comment #0 by b2.temp — 2018-11-21T21:13:38Z
With DMD ~master
---
alias Seq(T...) = T;
class One
{
int foo;
void test()
{
alias p1 = Seq!(__traits(getMember, this, "foo"))[0];
alias p2 = __traits(getMember, this, "foo");
static assert(__traits(isSame, p1, p2));
}
}
void main(){}
---
gives:
----
Error: static assert: `__traits(isSame, foo, int)` is false
----
with the new syntax `foo` is replaced by to its type:
TypeTrait semantic tries getSymbol() on the trait. If this fails, it calls getType() which takes the type of the expression when this expression is not a type.
There's something missing to transform the trait in dsymbol before it falls back to getType()
Comment #1 by b2.temp — 2018-11-22T08:34:49Z
When i think to what AliasSeq does maybe that the semantic for TypeTrait should always create a tuple and let the aliasSemantic() do its job on this tuple, without adding any pre-processing...
Comment #2 by b2.temp — 2018-11-22T08:45:14Z
(In reply to Basile B. from comment #1)
> When i think to what AliasSeq does maybe that the semantic for TypeTrait
> should always create a tuple and let the aliasSemantic() do its job on this
> tuple, without adding any pre-processing...
This but only when within an AliasDeclaration. Not sure if this would work when the __trait expression is used in place of a type (cast, var decl, etc)...
Comment #3 by b2.temp — 2018-11-22T10:46:39Z
This works for fixing this bug but then type solving from a __traits() that's inside an alias is broken:
```
override void visit(TypeTraits mtype)
{
import dmd.traits : semanticTraits;
result = null;
if (mtype.ty == Terror)
{
result = mtype;
return;
}
if (mtype.exp.ident != Id.allMembers &&
mtype.exp.ident != Id.derivedMembers &&
mtype.exp.ident != Id.getMember &&
mtype.exp.ident != Id.parent &&
mtype.exp.ident != Id.getOverloads &&
mtype.exp.ident != Id.getVirtualFunctions &&
mtype.exp.ident != Id.getVirtualMethods &&
mtype.exp.ident != Id.getAttributes &&
mtype.exp.ident != Id.getUnitTests)
{
static immutable (const(char)*)[2] ctxt = ["as type", "in alias"];
.error(mtype.loc, "trait `%s` is either invalid or not supported %s",
mtype.exp.ident.toChars, ctxt[mtype.inAliasDeclaration]);
result = mtype;
mtype.ty = Terror;
return;
}
if (Expression e = semanticTraits(mtype.exp, sc))
{
if (mtype.inAliasDeclaration)
{
Dsymbol aliased;
if (TupleExp te = e.toTupleExp)
{
aliased = new TupleDeclaration(mtype.loc,
Identifier.generateId("__aliastupmulti"), cast(Objects*) te.exps);
}
else
{
Objects* exps = new Objects(1);
(*exps)[0] = e;
TupleDeclaration td = new TupleDeclaration(mtype.loc,
Identifier.generateId("__aliastupsingle"), exps);
aliased = td;
}
AliasDeclaration ad = new AliasDeclaration(mtype.loc,
Identifier.generateId("__aliastup"), aliased);
aliasSemantic(ad, sc);
mtype.sym = ad.aliassym ? ad.aliassym.toAlias2() : null;
result = ad.type ? ad.type : new TypeError();
}
else if (Type t = getType(e))
{
result = t.addMod(mtype.mod);
}
else result = new TypeError();
}
if (!mtype.inAliasDeclaration && !result)
{
if (!global.errors)
.error(mtype.loc, "`%s` does not give a valid type", mtype.toChars);
result = mtype;
mtype.ty = Terror;
}
}
```
so when __aliastupsingleN represents a type. At this point it's a put them in the right order game.
Comment #4 by razvan.nitu1305 — 2018-11-22T13:58:17Z