Skip to content
Open
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
18 changes: 9 additions & 9 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -4324,15 +4324,13 @@ struct ASTBase
}
}

extern (C++) class TypeTraits : Type
extern (C++) class TypeTraits : TypeQualified
{
TraitsExp exp;
Loc loc;

extern (D) this(Loc loc, TraitsExp exp)
{
super(Tident);
this.loc = loc;
super(Ttraits, loc);
this.exp = exp;
}

Expand All @@ -4345,21 +4343,20 @@ struct ASTBase
{
TraitsExp te = exp.syntaxCopy();
TypeTraits tt = new TypeTraits(loc, te);
tt.syntaxCopyHelper(this);
tt.mod = mod;
return tt;
}
}

extern (C++) final class TypeMixin : Type
extern (C++) final class TypeMixin : TypeQualified
{
Loc loc;
Expressions* exps;
RootObject obj;

extern (D) this(Loc loc, Expressions* exps)
{
super(Tmixin);
this.loc = loc;
super(Tmixin, loc);
this.exps = exps;
}

Expand All @@ -4379,7 +4376,10 @@ struct ASTBase
return a;
}

return new TypeMixin(loc, arraySyntaxCopy(exps));
auto tm = new TypeMixin(loc, arraySyntaxCopy(exps));
tm.syntaxCopyHelper(this);
tm.mod = mod;
return tm;
}

override void accept(Visitor v)
Expand Down
24 changes: 12 additions & 12 deletions compiler/src/dmd/mtype.d
Original file line number Diff line number Diff line change
Expand Up @@ -1535,18 +1535,16 @@ extern (C++) final class TypeDelegate : TypeNext
*
* The point is to allow AliasDeclarationY to use `__traits()`, see $(LINK https://issues.dlang.org/show_bug.cgi?id=7804).
*/
extern (C++) final class TypeTraits : Type
extern (C++) final class TypeTraits : TypeQualified
{
Loc loc;
/// The expression to resolve as type or symbol.
TraitsExp exp;
/// Cached type/symbol after semantic analysis.
RootObject obj;

final extern (D) this(Loc loc, TraitsExp exp) @safe
final extern (D) this(Loc loc, TraitsExp exp) nothrow @safe
{
super(Ttraits);
this.loc = loc;
super(Ttraits, loc);
this.exp = exp;
}

Expand All @@ -1559,6 +1557,7 @@ extern (C++) final class TypeTraits : Type
{
TraitsExp te = exp.syntaxCopy();
TypeTraits tt = new TypeTraits(loc, te);
tt.syntaxCopyHelper(this);
tt.mod = mod;
return tt;
}
Expand All @@ -1574,16 +1573,14 @@ extern (C++) final class TypeTraits : Type
*
* Semantic analysis will convert it to a real type.
*/
extern (C++) final class TypeMixin : Type
extern (C++) final class TypeMixin : TypeQualified
{
Loc loc;
Expressions* exps;
RootObject obj; // cached result of semantic analysis.

extern (D) this(Loc loc, Expressions* exps) @safe
extern (D) this(Loc loc, Expressions* exps) nothrow @safe
{
super(Tmixin);
this.loc = loc;
super(Tmixin, loc);
this.exps = exps;
}

Expand All @@ -1594,7 +1591,10 @@ extern (C++) final class TypeMixin : Type

override TypeMixin syntaxCopy()
{
return new TypeMixin(loc, Expression.arraySyntaxCopy(exps));
auto tm = new TypeMixin(loc, Expression.arraySyntaxCopy(exps));
tm.syntaxCopyHelper(this);
tm.mod = mod;
return tm;
}

override void accept(Visitor v)
Expand All @@ -1613,7 +1613,7 @@ extern (C++) abstract class TypeQualified : Type
// representing ident.ident!tiargs.ident. ... etc.
Objects idents;

final extern (D) this(TY ty, Loc loc)
final extern (D) this(TY ty, Loc loc) @safe nothrow
{
super(ty);
this.loc = loc;
Expand Down
71 changes: 70 additions & 1 deletion compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -1817,6 +1817,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
* mixin Foo!(args);
* mixin a.b.c!(args).Foo!(args);
* mixin typeof(expr).identifier!(args);
* mixin typeof(expr)[index];
* mixin mixin(...);
* mixin __traits(...);
* mixin Foo!(args) identifier;
* mixin identifier = Foo!(args);
*/
Expand Down Expand Up @@ -1849,8 +1852,61 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
if (token.value == TOK.typeof_)
{
tqual = parseTypeof();
while (token.value == TOK.leftBracket)
{
nextToken();
tqual.addIndex(parseAssignExp());
check(TOK.rightBracket);
}
Comment thread
0-v-0 marked this conversation as resolved.
check(TOK.dot);
}
else if (token.value == TOK.mixin_)
{
loc = token.loc;
nextToken();
if (token.value != TOK.leftParenthesis)
error(token.loc, "found `%s` when expecting `%s` following `mixin`", token.toChars(), Token.toChars(TOK.leftParenthesis));
auto exps = parseArguments();
tqual = new AST.TypeMixin(loc, exps);
while (token.value == TOK.leftBracket)
{
nextToken();
tqual.addIndex(parseAssignExp());
check(TOK.rightBracket);
}
if (token.value == TOK.dot)
nextToken();
else
goto Lmixin;
}
else if (token.value == TOK.traits)
{
if (AST.TraitsExp te = cast(AST.TraitsExp) parsePrimaryExp())
{
if (te.ident)
{
tqual = new AST.TypeTraits(token.loc, te);
while (token.value == TOK.leftBracket)
{
nextToken();
tqual.addIndex(parseAssignExp());
check(TOK.rightBracket);
}
if (token.value == TOK.dot)
nextToken();
else
goto Lmixin;
}
}
if (!tqual)
{
error("traits expected");
id = Id.empty;
nextToken();
goto Lmixin;
}
}

if (token.value != TOK.identifier)
{
error("identifier expected, not `%s`", token.toChars());
Expand All @@ -1861,6 +1917,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
nextToken();
}

Lmixin:
while (1)
{
tiargs = null;
Expand All @@ -1878,14 +1935,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
tqual.addInst(tempinst);
tiargs = null;
}
else
else if (id)
{
if (!tqual)
tqual = new AST.TypeIdentifier(loc, id);
else
tqual.addIdent(id);
}

while (token.value == TOK.leftBracket)
{
nextToken();
if (!tqual)
{
error("identifier expected before `[`");
tqual = new AST.TypeIdentifier(loc, Id.empty);
}
tqual.addIndex(parseAssignExp());
check(TOK.rightBracket);
}

if (token.value != TOK.dot)
break;

Expand Down
15 changes: 15 additions & 0 deletions compiler/test/compilable/test21356.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
struct A
{
mixin template Foo() {}
}

alias AliasSeq(A...) = A;

alias thing = AliasSeq!(A);

mixin thing[0].Foo;
mixin typeof(thing)[0].Foo;

mixin template M() {}
mixin mixin("M");
mixin __traits(getMember, A, "Foo");
Loading