Bug 22697 – Segfault when accessing a recursive lambda declared inside a function generated with a mixin template

Status
NEW
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2022-01-22T13:44:20Z
Last change time
2024-12-13T19:20:33Z
Keywords
backend, ice-on-valid-code
Assigned to
No Owner
Creator
João Lourenço
Moved to GitHub: dmd#20042 →

Attachments

IDFilenameSummaryContent-TypeSize
1840backtrace.txt.gzUnedited stack trace (14MB uncompressed)application/gzip729816

Comments

Comment #0 by jlourenco5691 — 2022-01-22T13:44:20Z
When passing a recursive lambda function to a mixin template, that lambda cannot be accessed inside a function generated by the same mixin template. ``` mixin template mix(alias fun) { auto foo(Args...)(Args args) { return fun(args); } } void main() { mixin mix!((size_t n) { alias self = __traits(parent, {}); if (n < 2) return n; else return self(n - 1) + self(n - 2); }); foo(1).writeln; } ``` This example causes the compiler to segfault. This same example works with ldc. If instead of a lambda a named function is used the code works as intended. A reduced example: ``` mixin template mix(alias fun) { auto foo() { return fun; } } void main() { mixin mix!((size_t n) { alias self = __traits(parent, {}); }); } ```
Comment #1 by jlourenco5691 — 2022-01-22T13:56:10Z
(DMD) breaks in: DMD64 D Compiler v2.098.1 (LDC) works in: the LLVM D compiler (1.28.1)
Comment #2 by snarwin+bugzilla — 2022-01-22T16:51:50Z
Created attachment 1840 Unedited stack trace (14MB uncompressed) The segfault is the result of stack overflow due to infinite recursion. When attempting to generate the object file, the following sequence of function calls occurs in a loop: --- StatementPrettyPrintVisitor::visit(ExpStatement*) at src/dmd/hdrgen.d:171 ExpStatement::accept(Visitor*) at src/dmd/statement.d:477 StatementPrettyPrintVisitor::visit(CompoundStatement*) at src/dmd/hdrgen.d:195 CompoundStatement::accept(Visitor*) at src/dmd/statement.d:620 void dmd.hdrgen.statementToBuffer(dmd.statement.Statement, dmd.common.outbuffer.OutBuffer*, dmd.hdrgen.HdrGenState*) at src/dmd/hdrgen.d:136 DsymbolPrettyPrintVisitor::bodyToBuffer(FuncDeclaration*) at src/dmd/hdrgen.d:1629 DsymbolPrettyPrintVisitor::visit(FuncLiteralDeclaration*) at src/dmd/hdrgen.d:1681 FuncLiteralDeclaration::accept(Visitor*) at src/dmd/func.d:3633 void dmd.hdrgen.dsymbolToBuffer(dmd.dsymbol.Dsymbol, dmd.common.outbuffer.OutBuffer*, dmd.hdrgen.HdrGenState*) at src/dmd/hdrgen.d:797 --- The stack trace prior to entering the loop is as follows: --- ExpressionPrettyPrintVisitor::visit(FuncExp*) at src/dmd/hdrgen.d:2196 FuncExp::accept(Visitor*) at src/dmd/expression.d:4056 void dmd.hdrgen.expressionToBuffer(dmd.expression.Expression, dmd.common.outbuffer.OutBuffer*, dmd.hdrgen.HdrGenState*) at src/dmd/hdrgen.d:3289 void dmd.hdrgen.expToBuffer(dmd.expression.Expression, dmd.parse.PREC, dmd.common.outbuffer.OutBuffer*, dmd.hdrgen.HdrGenState*) at src/dmd/hdrgen.d:3322 void dmd.hdrgen.objectToBuffer(dmd.root.rootobject.RootObject, dmd.common.outbuffer.OutBuffer*, dmd.hdrgen.HdrGenState*) at src/dmd/hdrgen.d:3471 void dmd.hdrgen.tiargsToBuffer(dmd.dtemplate.TemplateInstance, dmd.common.outbuffer.OutBuffer*, dmd.hdrgen.HdrGenState*) at src/dmd/hdrgen.d:3444 DsymbolPrettyPrintVisitor::visit(TemplateInstance*) at src/dmd/hdrgen.d:1299 void dmd.hdrgen.toCBufferInstance(const dmd.common.outbuffer.OutBuffer*, bool) (qualifyTypes=true, buf=0x7fffffffc7d0, ti=0x7ffff7b1fcf0) at src/dmd/hdrgen.d:2790 TemplateInstance::toPrettyCharsHelper() at src/dmd/dtemplate.d:5974 Dsymbol::toPrettyChars(bool) at src/dmd/dsymbol.d:748 FuncDeclaration::toPrettyChars(bool) at src/dmd/func.d:1207 toSymbol::ToSymbol::visit(FuncDeclaration*) at src/dmd/tocsym.d:343 FuncDeclaration::accept(Visitor*) at src/dmd/func.d:2685 toSymbol(Dsymbol*) at src/dmd/tocsym.d:464 FuncDeclaration_toObjFile(FuncDeclaration*, bool) at src/dmd/glue.d:733 toObjFile::ToObjFile::visit(FuncDeclaration*) at src/dmd/toobj.d:311 FuncDeclaration::accept(Visitor*) at src/dmd/func.d:2685 toObjFile(Dsymbol*, bool) at src/dmd/toobj.d:1008 FuncDeclaration_toObjFile(FuncDeclaration*, bool) at src/dmd/glue.d:1263 toObjFile::ToObjFile::visit(FuncDeclaration*) at src/dmd/toobj.d:311 FuncDeclaration::accept(Visitor*) at src/dmd/func.d:2685 toObjFile(Dsymbol*, bool) at src/dmd/toobj.d:1008 genObjFile(Module*, bool) at src/dmd/glue.d:518 void dmd.glue.generateCodeAndWrite(dmd.dmodule.Module[], const(char)*[], const(char)[], const(char)[], bool, bool, bool, bool, bool) at src/dmd/glue.d:120 int dmd.mars.tryMain(ulong, const(char)**, ref dmd.globals.Param) at src/dmd/mars.d:581 D main at src/dmd/mars.d:1002 --- This stack trace was generated using gdb with a debug build of DMD master, commit 1199d3978. Some details have been omitted from the exceprts included in this comment. For the full, unedited stack trace, please see the attached file `backtrace.txt.gz`.
Comment #3 by robert.schadek — 2024-12-13T19:20:33Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20042 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB