Give the following code example
```
struct S
{
void foo(const ref S rhs)
{
alias thisMember = __traits(getMember, this, "x");
alias rhsMember = __traits(getMember, rhs, "x");
pragma(msg, thisMember.stringof);
pragma(msg, rhsMember.stringof);
pragma(msg, __traits(getMember, rhs, "x").stringof);
}
int x;
}
```
This outputs
```
this.x
this.x
rhs.x
```
As you can see, `rhsMember.stringof` evaluates to `this.x` instead of `rhs.x`
Comment #3 by razvan.nitu1305 — 2019-04-04T12:46:08Z
I think that this code should error. Aliases can be made to types or symbols, however you are trying to alias an expression. For example, simply trying:
alias tmp = rhs.x;
will result in a compilation error. I don't see how that code can be accepted without redefining the notion of traits. As for the implementation of TypeTraits, I think it was a mistake to allow all traits to be used as types. As you can see, some traits cannot be types. This bug report is an example of how the the type system is bypassed via TypeTraits: the expression returned by __traits is wrapped in a TypeTraits, therefore the compiler thinks it's okay to alias it.
Comment #4 by b2.temp — 2019-04-04T14:52:49Z
I wont fix the issue since it's assigned but just a few words to clarify the problem:
1. The wrong symbol is return because of a call to `getDsymbolWithoutExp()` (https://github.com/dlang/dmd/blob/93b4b99b0b024d238b223e73804c1d0c01ee42ec/src/dmd/typesem.d#L1637)
2. After this call, a type is returned from the `TraitExp`, always, even when the `TraitsExp` doesn't represent a `Type`. That's because `getType()` returns the type of the expression when the expression itself doesn't represents/wraps a `Type`.
The fix would consist into detecting the invalid stuff beforehand
---
if (Expression e = semanticTraits(mtype.exp, sc))
{
if (TupleExp te = e.toTupleExp)
mtype.sym = new TupleDeclaration(mtype.loc,
Identifier.generateId("__aliastup"), cast(Objects*) te.exps);
else if (Dsymbol ds = getDsymbol(e))
mtype.sym = ds;
// detect invalid cases such as 19786 here at worst
// if you reach this point with smthg like issue 19786 it's too late
else if (Dsymbol ds = getDsymbolWithoutExpCtx(e))
mtype.sym = ds;
// if you reach this point with an invalid case it's too late
else if (Type t = getType(e))
result = t.addMod(mtype.mod);
}
---
Note in reaction to previous comment, `rhs` is not an expression, it's a `VarDeclaration`, so a symbol.
Comment #5 by razvan.nitu1305 — 2019-04-04T15:14:58Z
(In reply to Basile-z from comment #4)
> I wont fix the issue since it's assigned but just a few words to clarify the
> problem:
>
> 1. The wrong symbol is return because of a call to `getDsymbolWithoutExp()`
> (https://github.com/dlang/dmd/blob/93b4b99b0b024d238b223e73804c1d0c01ee42ec/
> src/dmd/typesem.d#L1637)
>
> 2. After this call, a type is returned from the `TraitExp`, always, even
> when the `TraitsExp` doesn't represent a `Type`. That's because `getType()`
> returns the type of the expression when the expression itself doesn't
> represents/wraps a `Type`.
>
> The fix would consist into detecting the invalid stuff beforehand
>
Fixing this specific case is trivial, but fixing the general case is more complicated because there are a lot of corner cases (expressions that might or might no be convertible to symbols/types).
> ---
> if (Expression e = semanticTraits(mtype.exp, sc))
> {
> if (TupleExp te = e.toTupleExp)
> mtype.sym = new TupleDeclaration(mtype.loc,
> Identifier.generateId("__aliastup"), cast(Objects*) te.exps);
> else if (Dsymbol ds = getDsymbol(e))
> mtype.sym = ds;
>
> // detect invalid cases such as 19786 here at worst
>
> // if you reach this point with smthg like issue 19786 it's too late
> else if (Dsymbol ds = getDsymbolWithoutExpCtx(e))
> mtype.sym = ds;
>
> // if you reach this point with an invalid case it's too late
> else if (Type t = getType(e))
> result = t.addMod(mtype.mod);
> }
> ---
>
> Note in reaction to previous comment, `rhs` is not an expression, it's a
> `VarDeclaration`, so a symbol.
`rhs.x` is an expression, a DotVarExp. x is the var declaration that is returned and the this is implicitly added by the compiler in both cases.
Comment #6 by b2.temp — 2019-04-11T13:24:47Z
I have an excellent news. Si I was rewriting TypeTraits semantic, decomposing all possible Expressions kinds wit the idea to filter out the invalid cases and then realized that TypeTraits semantic is not the issue **at all**.
IN the original report, if you use the old way, i.e `AliasSeq`, then the same problem occurs, see https://run.dlang.io/is/PGzqGp.
The bug more likely lies in __traits semantic.
Sorry if my comment lead you in the wrong direction and good luck with the fix.