From d27061f6dabf99255dd677595bed1d9a97ec135e Mon Sep 17 00:00:00 2001 From: metagn Date: Tue, 3 Sep 2024 06:45:08 +0300 Subject: [PATCH] fix segfault with gensym node instantiation (#24050) fixes #24048 Generic lambdas get instantiated via `replaceTypesInBody` which calls `replaceTypeVarsN` on the body of the lambda. This body can contain sym nodes of gensym symbols generated by macros, which have `nil` type. But a piece of code in `replaceTypeVarsN` checks whether the type of a symbol is equal to `void` without checking if it's `nil` first, which causes a segfault. Now it also checks that the type of the symbol isn't `nil` for it to be `void`. --- compiler/semtypinst.nim | 3 ++- tests/generics/tgensyminst.nim | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/generics/tgensyminst.nim diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 47fdc162d0cc..c2599c6f7a16 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -290,7 +290,8 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0; expectedType: PT replaceTypeVarsS(cl, n.sym, result.typ) else: replaceTypeVarsS(cl, n.sym, replaceTypeVarsT(cl, n.sym.typ)) - if result.sym.typ.kind == tyVoid: + # sym type can be nil if was gensym created by macro, see #24048 + if result.sym.typ != nil and result.sym.typ.kind == tyVoid: # don't add the 'void' field result = newNodeI(nkRecList, n.info) of nkRecWhen: diff --git a/tests/generics/tgensyminst.nim b/tests/generics/tgensyminst.nim new file mode 100644 index 000000000000..3f30188d8b3d --- /dev/null +++ b/tests/generics/tgensyminst.nim @@ -0,0 +1,29 @@ +# issue #24048 + +import macros + +proc map(fn: proc(val: int): void) = fn(1) + +# This works fine, and is the exact same function call as what's +# generated by the macro `aBug`. +map proc(val: auto): void = + let variable = 123 + +macro aBug() = + # 1. let sym = ident("variable") + let sym = genSym(nskLet, "variable") + let letStmt = newLetStmt(sym, newLit(123)) + + let lambda = newProc( + params = @[ + ident("void"), + newIdentDefs(ident("val"), ident("auto")), + # 2. newIdentDefs(ident("val"), ident("int")), + ], + body = newStmtList(letStmt), + procType = nnkLambda + ) + + result = newCall(bindSym("map"), lambda) + +aBug()