mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
Fix issue 21243 - Allow lambdas to return auto ref
This commit is contained in:
parent
462affc6e6
commit
dda09ee7b3
4 changed files with 94 additions and 5 deletions
|
@ -3759,9 +3759,9 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
|
|||
// backend
|
||||
bool deferToObj;
|
||||
|
||||
extern (D) this(const ref Loc loc, const ref Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null)
|
||||
extern (D) this(const ref Loc loc, const ref Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null, StorageClass storage_class = STC.undefined_)
|
||||
{
|
||||
super(loc, endloc, null, STC.undefined_, type);
|
||||
super(loc, endloc, null, storage_class, type);
|
||||
this.ident = id ? id : Id.empty;
|
||||
this.tok = tok;
|
||||
this.fes = fes;
|
||||
|
@ -3775,7 +3775,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
|
|||
{
|
||||
//printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
|
||||
assert(!s);
|
||||
auto f = new FuncLiteralDeclaration(loc, endloc, type.syntaxCopy(), tok, fes, ident);
|
||||
auto f = new FuncLiteralDeclaration(loc, endloc, type.syntaxCopy(), tok, fes, ident, storage_class & STC.auto_);
|
||||
f.treq = treq; // don't need to copy
|
||||
FuncDeclaration.syntaxCopy(f);
|
||||
return f;
|
||||
|
|
|
@ -4856,6 +4856,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
token.value == TOK.identifier && peekNext() == TOK.goesTo ||
|
||||
token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(peek(&token)), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
|
||||
token.value == TOK.auto_ && peekNext() == TOK.ref_ &&
|
||||
peekNext2() == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(peek(peek(&token))), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
|
||||
)
|
||||
{
|
||||
|
@ -4867,6 +4871,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
// identifier => expression
|
||||
// ref (parameters) { statements... }
|
||||
// ref (parameters) => expression
|
||||
// auto ref (parameters) { statements... }
|
||||
// auto ref (parameters) => expression
|
||||
|
||||
s = parseFunctionLiteral();
|
||||
|
||||
|
@ -4994,7 +5000,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
case TOK.delegate_:
|
||||
save = token.value;
|
||||
nextToken();
|
||||
if (token.value == TOK.ref_)
|
||||
if (token.value == TOK.auto_)
|
||||
{
|
||||
nextToken();
|
||||
if (token.value == TOK.ref_)
|
||||
{
|
||||
// function auto ref (parameters) { statements... }
|
||||
// delegate auto ref (parameters) { statements... }
|
||||
stc = STC.auto_ | STC.ref_;
|
||||
nextToken();
|
||||
}
|
||||
else
|
||||
error("`auto` can only be used as part of `auto ref` for function literal return values");
|
||||
}
|
||||
else if (token.value == TOK.ref_)
|
||||
{
|
||||
// function ref (parameters) { statements... }
|
||||
// delegate ref (parameters) { statements... }
|
||||
|
@ -5022,6 +5041,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
}
|
||||
goto case TOK.leftParenthesis;
|
||||
|
||||
case TOK.auto_:
|
||||
{
|
||||
nextToken();
|
||||
if (token.value == TOK.ref_)
|
||||
{
|
||||
// auto ref (parameters) => expression
|
||||
// auto ref (parameters) { statements... }
|
||||
stc = STC.auto_ | STC.ref_;
|
||||
nextToken();
|
||||
}
|
||||
else
|
||||
error("`auto` can only be used as part of `auto ref` for function literal return values");
|
||||
goto case TOK.leftParenthesis;
|
||||
}
|
||||
case TOK.ref_:
|
||||
{
|
||||
// ref (parameters) => expression
|
||||
|
@ -5074,7 +5107,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
|
||||
auto tf = new AST.TypeFunction(parameterList, tret, linkage, stc);
|
||||
tf = cast(AST.TypeFunction)tf.addSTC(stc);
|
||||
auto fd = new AST.FuncLiteralDeclaration(loc, Loc.initial, tf, save, null);
|
||||
auto fd = new AST.FuncLiteralDeclaration(loc, Loc.initial, tf, save, null, null, stc & STC.auto_);
|
||||
|
||||
if (token.value == TOK.goesTo)
|
||||
{
|
||||
|
@ -8384,6 +8417,22 @@ LagainStc:
|
|||
e = parseNewExp(null);
|
||||
break;
|
||||
|
||||
case TOK.auto_:
|
||||
{
|
||||
if (peekNext() == TOK.ref_ && peekNext2() == TOK.leftParenthesis)
|
||||
{
|
||||
Token* tk = peekPastParen(peek(peek(&token)));
|
||||
if (skipAttributes(tk, &tk) && (tk.value == TOK.goesTo || tk.value == TOK.leftCurly))
|
||||
{
|
||||
// auto ref (arguments) => expression
|
||||
// auto ref (arguments) { statements... }
|
||||
goto case_delegate;
|
||||
}
|
||||
}
|
||||
nextToken();
|
||||
error("found `%s` when expecting `ref` and function literal following `auto`", token.toChars());
|
||||
goto Lerr;
|
||||
}
|
||||
case TOK.ref_:
|
||||
{
|
||||
if (peekNext() == TOK.leftParenthesis)
|
||||
|
|
21
compiler/test/compilable/test21243.d
Normal file
21
compiler/test/compilable/test21243.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Parsing - expressions
|
||||
auto a = auto ref (int x) => x;
|
||||
auto b = auto ref (int x) { return x; };
|
||||
auto c = function auto ref (int x) { return x; };
|
||||
auto d = delegate auto ref (int x) { return x; };
|
||||
|
||||
// Parsing - aliases
|
||||
alias e = auto ref (int x) => x;
|
||||
alias f = auto ref (int x) { return x; };
|
||||
alias g = function auto ref (int x) { return x; };
|
||||
alias h = delegate auto ref (int x) { return x; };
|
||||
|
||||
// Semantic
|
||||
void test()
|
||||
{
|
||||
alias fun(alias x) = auto ref () => x;
|
||||
int n = 123;
|
||||
auto _ = fun!123();
|
||||
static assert(!__traits(compiles, &fun!123())); // rvalue
|
||||
fun!n() = 456; // lvalue
|
||||
}
|
19
compiler/test/fail_compilation/fail21243.d
Normal file
19
compiler/test/fail_compilation/fail21243.d
Normal file
|
@ -0,0 +1,19 @@
|
|||
/+ TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto`
|
||||
fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int`
|
||||
fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)`
|
||||
fail_compilation/fail21243.d(16): Error: declaration expected, not `)`
|
||||
fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
fail_compilation/fail21243.d(18): Error: basic type expected, not `(`
|
||||
fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`)
|
||||
fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases
|
||||
fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration
|
||||
fail_compilation/fail21243.d(18): Error: declaration expected, not `=>`
|
||||
fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values
|
||||
---
|
||||
+/
|
||||
auto a = auto (int x) => x;
|
||||
auto b = function auto (int x) { return x; };
|
||||
alias c = auto (int x) => x;
|
||||
alias d = function auto (int x) { return x; };
|
Loading…
Add table
Add a link
Reference in a new issue