From ea9811a4d2acc81cdd0e501669184a2fab194324 Mon Sep 17 00:00:00 2001 From: metagn Date: Sun, 6 Oct 2024 20:36:46 +0300 Subject: [PATCH] reset `inTypeofContext` in generic instantiations (#24229) fixes #24228, refs #22022 As described in https://github.com/nim-lang/Nim/issues/24228#issuecomment-2392462221, instantiating generic routines inside `typeof` causes all code inside to be treated as being in a typeof context, and thus preventing compile time proc folding, causing issues when code is generated for the instantiated routine. Now, instantiated generic procs are treated as never being inside a `typeof` context. This is probably an arbitrary special case and more issues with the `typeof` behavior from #22022 are likely. Ideally this behavior would be removed but it's necessary to accomodate the current [proc `declval` in the package `stew`](https://github.com/status-im/nim-stew/pull/190), at least without changes to `compileTime` that would either break other code (making it not eagerly fold by default) or still require a change in stew (adding an option to disable the eager folding). Alternatively we could also make the eager folding opt-in only for generic compileTime procs so that #22022 breaks nothing whatsoever, but a universal solution would be better. Edit: Done in #24230 via experimental switch --- compiler/seminst.nim | 6 +++++- tests/vm/tgenericcompiletimeproc.nim | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index e132e048a16c..d5afb8389fb4 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -371,7 +371,11 @@ proc generateInstance(c: PContext, fn: PSym, pt: LayeredIdTable, if c.instCounter > 50: globalError(c.config, info, "generic instantiation too nested") inc c.instCounter - defer: dec c.instCounter + let currentTypeofContext = c.inTypeofContext + c.inTypeofContext = 0 + defer: + dec c.instCounter + c.inTypeofContext = currentTypeofContext # careful! we copy the whole AST including the possibly nil body! var n = copyTree(fn.ast) # NOTE: for access of private fields within generics from a different module diff --git a/tests/vm/tgenericcompiletimeproc.nim b/tests/vm/tgenericcompiletimeproc.nim index 08099ebbe354..44d78ef921c0 100644 --- a/tests/vm/tgenericcompiletimeproc.nim +++ b/tests/vm/tgenericcompiletimeproc.nim @@ -34,3 +34,24 @@ block: # issue #24150, related regression discard compiles(y(w int)) proc s(): int {.compileTime.} = discard discard s() + +block: # issue #24228, also related regression + proc d(_: static[string]) = discard $0 + proc m(_: static[string]) = d("") + iterator v(): int {.closure.} = + template a(n: untyped) = + when typeof(n) is void: + n + else: + n + a(m("")) + let _ = v + +block: # issue #24228 simplified + proc d[T]() = + let x = $0 + proc v() = + when typeof(d[string]()) is void: + d[string]() + v() +