Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/dmd/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
18 changes: 6 additions & 12 deletions src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 0 additions & 2 deletions src/dmd/mtype.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 0 additions & 2 deletions src/dmd/mtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
43 changes: 39 additions & 4 deletions src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand All @@ -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;
}
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}

Expand Down
22 changes: 22 additions & 0 deletions test/runnable/e7804.d
Original file line number Diff line number Diff line change
Expand Up @@ -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));