Skip to content

Commit 948b36f

Browse files
AayushMainali-Githubthewilsonator
authored andcommitted
Fix Issue 23326 - Lambda missing parens in generated D import file
Arrow => literals parse with an AssignExpression body, so hdrgen must parenthesize them when used as a call callee; otherwise the call is absorbed into the lambda body in .di output.
1 parent aa971d3 commit 948b36f

2 files changed

Lines changed: 49 additions & 11 deletions

File tree

compiler/src/dmd/hdrgen.d

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,19 +1879,10 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
18791879
if (!hgs.errorMsg)
18801880
tf.attributesApply(&printAttribute);
18811881

1882-
CompoundStatement cs = f.fbody.isCompoundStatement();
1883-
Statement s1;
1884-
if (f.semanticRun >= PASS.semantic3done && cs)
1885-
{
1886-
s1 = (*cs.statements)[cs.statements.length - 1];
1887-
}
1888-
else
1889-
s1 = !cs ? f.fbody : null;
1890-
ReturnStatement rs = s1 ? s1.endsWithReturnStatement() : null;
1891-
if (rs && rs.exp)
1882+
if (auto result = arrowFuncLiteralResult(f))
18921883
{
18931884
buf.put(" => ");
1894-
rs.exp.expressionToBuffer(buf, hgs);
1885+
result.expressionToBuffer(buf, hgs);
18951886
}
18961887
else
18971888
{
@@ -3863,6 +3854,28 @@ private void expressionToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState
38633854
expressionPrettyPrint(e, buf, hgs);
38643855
}
38653856

3857+
/**************************************************
3858+
* Returns the expression result if `f` is printed with `=>` syntax, otherwise `null`.
3859+
*
3860+
* Arrow function literals have an AssignExpression body, so they bind less tightly
3861+
* than postfix operators and must be parenthesized when used as a call callee etc.
3862+
*/
3863+
private Expression arrowFuncLiteralResult(FuncLiteralDeclaration f)
3864+
{
3865+
if (!f.fbody)
3866+
return null;
3867+
3868+
CompoundStatement cs = f.fbody.isCompoundStatement();
3869+
Statement s1;
3870+
if (f.semanticRun >= PASS.semantic3done && cs)
3871+
s1 = (*cs.statements)[cs.statements.length - 1];
3872+
else
3873+
s1 = !cs ? f.fbody : null;
3874+
3875+
ReturnStatement rs = s1 ? s1.endsWithReturnStatement() : null;
3876+
return rs && rs.exp ? rs.exp : null;
3877+
}
3878+
38663879
// to be called if e could be loweredFrom another expression instead of acessing precedence[e.op] directly
38673880
private PREC expPrecedence(ref HdrGenState hgs, Expression e)
38683881
{
@@ -3877,6 +3890,13 @@ private PREC expPrecedence(ref HdrGenState hgs, Expression e)
38773890
if (ne.loweredFrom)
38783891
e = ne.loweredFrom;
38793892
}
3893+
// https://github.com/dlang/dmd/issues/23326
3894+
// Arrow lambdas are not true primaries; treat like assign-level expressions for paren insertion.
3895+
if (auto fe = e.isFuncExp())
3896+
{
3897+
if (fe.fd && arrowFuncLiteralResult(fe.fd))
3898+
return PREC.assign;
3899+
}
38803900
return precedence[e.op];
38813901
}
38823902

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
REQUIRED_ARGS: -o- -Hf${RESULTS_DIR}/compilable/header23326.di
3+
OUTPUT_FILES: ${RESULTS_DIR}/compilable/header23326.di
4+
5+
TEST_OUTPUT:
6+
---
7+
=== ${RESULTS_DIR}/compilable/header23326.di
8+
// D import file generated from 'compilable/header23326.d'
9+
enum i = ((x) => x * 2)(3);
10+
enum j = ((x) => x * 2)(4);
11+
extern typeof(((x) => x * 2)(5)) d;
12+
---
13+
*/
14+
15+
// https://github.com/dlang/dmd/issues/23326
16+
enum i = (x => x * 2)(3);
17+
enum j = ((x) => x * 2)(4);
18+
auto d = (x => x * 2)(5);

0 commit comments

Comments
 (0)