Skip to content

Commit

Permalink
fix Issue 12421 - Allow simpler syntax for lambda template declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Aug 24, 2015
1 parent 05ed192 commit 445e173
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 9 deletions.
22 changes: 22 additions & 0 deletions src/declaration.d
Expand Up @@ -560,6 +560,28 @@ public:
//printf("AliasDeclaration::semantic() %s\n", toChars());
if (aliassym)
{
auto fd = aliassym.isFuncLiteralDeclaration();
auto td = aliassym.isTemplateDeclaration();
if (fd || td && td.literal)
{
if (fd && fd.semanticRun >= PASSsemanticdone)
return;

Expression e = new FuncExp(loc, aliassym);
e = e.semantic(sc);
if (e.op == TOKfunction)
{
FuncExp fe = cast(FuncExp)e;
aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd;
}
else
{
aliassym = null;
type = Type.terror;
}
return;
}

if (aliassym.isTemplateInstance())
aliassym.semantic(sc);
return;
Expand Down
49 changes: 40 additions & 9 deletions src/parse.d
Expand Up @@ -3848,16 +3848,45 @@ public:
if (token.value == TOKlparen)
tpl = parseTemplateParameterList();
check(TOKassign);
storage_class = STCundefined;
link = linkage;
structalign = 0;
udas = null;
parseStorageClasses(storage_class, link, structalign, udas);
if (udas)
error("user defined attributes not allowed for %s declarations", Token.toChars(tok));
t = parseType();
Declaration v = new AliasDeclaration(loc, ident, t);

Declaration v;
if (token.value == TOKfunction ||
token.value == TOKdelegate ||
token.value == TOKlparen &&
skipAttributes(peekPastParen(&token), &tk) &&
(tk.value == TOKgoesto || tk.value == TOKlcurly) ||
token.value == TOKlcurly ||
token.value == TOKidentifier && peekNext() == TOKgoesto
)
{
// function (parameters) { statements... }
// delegate (parameters) { statements... }
// (parameters) { statements... }
// (parameters) => expression
// { statements... }
// identifier => expression

Dsymbol s = parseFunctionLiteral();
v = new AliasDeclaration(loc, ident, s);
}
else
{
// StorageClasses type

storage_class = STCundefined;
link = linkage;
structalign = 0;
udas = null;
parseStorageClasses(storage_class, link, structalign, udas);

if (udas)
error("user defined attributes not allowed for %s declarations", Token.toChars(tok));

t = parseType();
v = new AliasDeclaration(loc, ident, t);
}
v.storage_class = storage_class;

Dsymbol s = v;
if (tpl)
{
Expand All @@ -3873,6 +3902,7 @@ public:
s = new LinkDeclaration(link, a2);
}
a.push(s);

switch (token.value)
{
case TOKsemicolon:
Expand Down Expand Up @@ -3902,6 +3932,7 @@ public:
}
return a;
}

// alias StorageClasses type ident;
}
else if (token.value == TOKtypedef)
Expand Down
55 changes: 55 additions & 0 deletions test/runnable/funclit.d
Expand Up @@ -1069,6 +1069,60 @@ void test11774()
f11774!int(dg);
}

/***************************************************/
// 12421

void test12421()
{
void test(string decl, bool polymorphic = true)()
{
// parse AliasDeclaration in Statement
mixin("alias f = " ~ decl ~ ";");
assert(f(1) == 1);
static if (polymorphic)
assert(f("s") == "s");

// parse AliasDeclaration in DeclDefs
mixin("template X() { alias g = " ~ decl ~ "; }");
alias g = X!().g;
assert(g(1) == 1);
static if (polymorphic)
assert(g("s") == "s");
}

test!(q{ x => x });
test!(q{ ( x) => x });
test!(q{ (int x) => x }, false);

test!(q{ ( x){ return x; } });
test!(q{ (int x){ return x; } }, false);

test!(q{ function ( x) => x });
test!(q{ function (int x) => x }, false);
test!(q{ function int ( x) => x }, false);
test!(q{ function int (int x) => x }, false);

test!(q{ delegate ( x) => x });
test!(q{ delegate (int x) => x }, false);
test!(q{ delegate int ( x) => x }, false);
test!(q{ delegate int (int x) => x }, false);

test!(q{ function ( x){ return x; } });
test!(q{ function (int x){ return x; } }, false);
test!(q{ function int ( x){ return x; } }, false);
test!(q{ function int (int x){ return x; } }, false);

test!(q{ delegate ( x){ return x; } });
test!(q{ delegate (int x){ return x; } }, false);
test!(q{ delegate int ( x){ return x; } }, false);
test!(q{ delegate int (int x){ return x; } }, false);

// This is problematic case, and should be disallowed in the future.
alias f = x => y;
int y = 10;
assert(f(1) == 10);;
}

/***************************************************/
// 12508

Expand Down Expand Up @@ -1171,6 +1225,7 @@ int main()
test10928();
test11661();
test11774();
test12421();
test12508();
test13879();

Expand Down

0 comments on commit 445e173

Please sign in to comment.