From 680a13a142e08782a111635a6f1692292d4f3354 Mon Sep 17 00:00:00 2001 From: metagn Date: Tue, 17 Sep 2024 15:01:48 +0300 Subject: fix segfault in effect tracking for sym node with nil type (#24114) fixes #24112 Sym nodes in templates that could be open are [given `nil` type](https://github.com/nim-lang/Nim/blob/22d2cf217597468ace8ba540d6990b1f6d8a816a/compiler/semtempl.nim#L274) when `--experimentalOpenSym` is disabled so that they can be semchecked to give a warning since #24007. The first nodes of object constructors (in this case) and in type conversions don't replace their first node (the symbol) with a typechecked one, they only call `semTypeNode` on it and leave it as is. Effect tracking checks if the type of a sym node has a destructor to check if the node type should be replaced with the sym type. But this causes a segfault when the type of the node is nil. To fix this, we always set the node type to the sym type if the node type is nil. Alternatively `semObjConstr` and `semConv` could be changed to set the type of their first node to the found type but I'm not sure if this would break anything. They could call `semExprWithType` on the first node but `semTypeNode` would still have to be called (maybe call it before?). This isn't a problem if the sym node has a type but is just nested in `nkOpenSym` or `nkOpenSymChoice` which have nil type instead (i.e. with openSym enabled), so maybe this still is the "most general" solution, I don't know. --- compiler/sempass2.nim | 2 +- tests/template/t24112.nim | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/template/t24112.nim diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 467f300b5..0a160897f 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -1210,7 +1210,7 @@ proc track(tracked: PEffects, n: PNode) = if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags: tracked.owner.flags.incl sfInjectDestructors # bug #15038: ensure consistency - if not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ): n.typ = n.sym.typ + if n.typ == nil or (not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ)): n.typ = n.sym.typ of nkHiddenAddr, nkAddr: if n[0].kind == nkSym and isLocalSym(tracked, n[0].sym) and n.typ.kind notin {tyVar, tyLent}: diff --git a/tests/template/t24112.nim b/tests/template/t24112.nim new file mode 100644 index 000000000..175fc7d5e --- /dev/null +++ b/tests/template/t24112.nim @@ -0,0 +1,19 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj --hints:off" + action: reject +""" + +# issue #24112, needs --experimental:openSym disabled + +block: # simplified + type + SomeObj = ref object # Doesn't error if you make SomeObj be non-ref + template foo = yield SomeObj() + when compiles(foo): discard + +import std/asyncdispatch +block: + proc someProc(): Future[void] {.async.} = discard + proc foo() = + await someProc() #[tt.Error + ^ Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead]# -- cgit 1.4.1-2-gfad0