diff --git a/src/dmd/dscope.d b/src/dmd/dscope.d index 199567ea4658..c980eb971504 100644 --- a/src/dmd/dscope.d +++ b/src/dmd/dscope.d @@ -60,6 +60,7 @@ enum SCOPE free = 0x8000, /// is on free list fullinst = 0x10000, /// fully instantiate templates + alias_ = 0x20000, /// inside alias declaration. } // Flags that are carried along with a scope push() diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index b73b8ae40d67..a2c4b6439c3d 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -6299,18 +6299,12 @@ Laftersemantic: void aliasSemantic(AliasDeclaration ds, Scope* sc) { //printf("AliasDeclaration::semantic() %s\n", ds.toChars()); - if (ds.type && ds.type.ty == Ttraits) - { - // TypeTraits is not a valid type, it's semantic is called manually to - // have either a symbol or a valid type to alias. - TypeTraits tt = cast(TypeTraits) ds.type; - tt.inAliasDeclaration = true; - if (Type t = typeSemantic(tt, tt.loc, sc)) - ds.type = t; - else if (tt.sym) - ds.aliassym = tt.sym; - tt.inAliasDeclaration = false; - } + + // TypeTraits needs to know if it's located in an AliasDeclaration + sc.flags |= SCOPE.alias_; + scope(exit) + sc.flags &= ~SCOPE.alias_; + if (ds.aliassym) { auto fd = ds.aliassym.isFuncLiteralDeclaration(); diff --git a/src/dmd/mtype.d b/src/dmd/mtype.d index 1935b5f7836f..9db12f7e879f 100644 --- a/src/dmd/mtype.d +++ b/src/dmd/mtype.d @@ -5103,8 +5103,6 @@ extern (C++) final class TypeTraits : Type TraitsExp exp; /// After `typeSemantic` the symbol when `exp` doesn't represent a type. Dsymbol sym; - /// Indicates wether we are in an alias or not. - bool inAliasDeclaration; final extern (D) this(const ref Loc loc, TraitsExp exp) { diff --git a/src/dmd/mtype.h b/src/dmd/mtype.h index 45e9066e7161..4b034ef285bd 100644 --- a/src/dmd/mtype.h +++ b/src/dmd/mtype.h @@ -626,8 +626,6 @@ class TypeTraits : public Type TraitsExp *exp; /// The symbol when exp doesn't represent a type. Dsymbol *sym; - /// Indicates wether we are in an alias or not. - bool inAliasDeclaration; Type *syntaxCopy(); d_uns64 size(const Loc &loc); diff --git a/src/dmd/typesem.d b/src/dmd/typesem.d index 6d80a7f7de67..17a5603cd8fa 100644 --- a/src/dmd/typesem.d +++ b/src/dmd/typesem.d @@ -1645,6 +1645,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) if (mtype.ty == Terror) return mtype; + const inAlias = (sc.flags & SCOPE.alias_) != 0; if (mtype.exp.ident != Id.allMembers && mtype.exp.ident != Id.derivedMembers && mtype.exp.ident != Id.getMember && @@ -1658,7 +1659,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) { 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]); + mtype.exp.ident.toChars, ctxt[inAlias]); mtype.ty = Terror; return mtype; } @@ -1693,8 +1694,31 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) mtype.sym = (cast(ScopeExp)e).sds; break; case TOK.tuple: - mtype.sym = new TupleDeclaration(e.loc, - Identifier.generateId("__aliastup"), cast(Objects*) e.toTupleExp.exps); + TupleExp te = e.toTupleExp(); + Objects* elems = new Objects(te.exps.dim); + foreach (i; 0 .. elems.dim) + { + auto src = (*te.exps)[i]; + switch (src.op) + { + case TOK.type: + (*elems)[i] = (cast(TypeExp)src).type; + break; + case TOK.dotType: + (*elems)[i] = (cast(DotTypeExp)src).sym.isType(); + break; + case TOK.overloadSet: + (*elems)[i] = (cast(OverExp)src).type; + break; + default: + if (auto sym = isDsymbol(src)) + (*elems)[i] = sym; + else + (*elems)[i] = src; + } + } + TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems); + mtype.sym = td; break; case TOK.dotType: result = (cast(DotTypeExp)e).sym.isType(); @@ -1712,7 +1736,7 @@ extern(C++) Type typeSemantic(Type t, Loc loc, Scope* sc) if (result) result = result.addMod(mtype.mod); - if (!mtype.inAliasDeclaration && !result) + if (!inAlias && !result) { if (!global.errors) .error(mtype.loc, "`%s` does not give a valid type", mtype.toChars); @@ -2913,6 +2937,16 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, Expression* pe, Type* pt, Ds } } + void visitTraits(TypeTraits tt) + { + if (Type t = typeSemantic(tt, loc, sc)) + returnType(t); + else if (tt.sym) + returnSymbol(tt.sym); + else + return returnError(); + } + switch (mt.ty) { default: visitType (mt); break; @@ -2924,6 +2958,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, Expression* pe, Type* pt, Ds case Ttypeof: visitTypeof (cast(TypeTypeof)mt); break; case Treturn: visitReturn (cast(TypeReturn)mt); break; case Tslice: visitSlice (cast(TypeSlice)mt); break; + case Ttraits: visitTraits (cast(TypeTraits)mt); break; } } diff --git a/test/runnable/e7804.d b/test/runnable/e7804.d index fe8230303043..d32531055f54 100644 --- a/test/runnable/e7804.d +++ b/test/runnable/e7804.d @@ -155,3 +155,25 @@ void main() (new Two).test(); (new SingleSymTuple).test(); } + +/* https://issues.dlang.org/show_bug.cgi?id=19708 */ +struct Foo19708 {} +struct Bar19708 {} +template Baz19708(T) { struct Baz19708{T t;} } +int symbol19708; + +@Foo19708 @Bar19708 @Baz19708 @symbol19708 int bar19708; + +alias TR19708 = __traits(getAttributes, bar19708); +alias TRT = __traits(getAttributes, bar19708)[2]; + +TR19708[0] a119708; +TR19708[1] a219708; +alias A3 = TRT!int; + +alias C19708 = TR19708[0]; +alias D19708 = TR19708[1]; +C19708 c1; +D19708 d1; + +static assert(__traits(isSame, TR19708[3], symbol19708));