diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 10bb33bcdc..cd0761c6b6 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -129,7 +129,14 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, result.typ = nil onUse(n.info, s) of skParam: - result = n + if s.owner == c.p.owner or true: + # Parameters of the routine currently being semchecked stay as local + # identifiers + result = n + else: + # Preserve captured outer parameters so nested generic procs can still + # see them after the generic pre-pass. + result = newSymNode(s, n.info) onUse(n.info, s) of skType: if (s.typ != nil) and diff --git a/tests/generics/t20811.nim b/tests/generics/t20811.nim new file mode 100644 index 0000000000..f165782719 --- /dev/null +++ b/tests/generics/t20811.nim @@ -0,0 +1,16 @@ +discard """ + output: '''42 +42''' +""" + +proc outer(j: int) = + proc genericInner[T](): int = + j + + proc plainInner(): int = + j + + echo genericInner[int]() + echo plainInner() + +outer(42) \ No newline at end of file diff --git a/tests/template/topensym.nim b/tests/template/topensym.nim index 2f930407b9..25127021d9 100644 --- a/tests/template/topensym.nim +++ b/tests/template/topensym.nim @@ -135,6 +135,19 @@ block: # issue #22605 for templates, original complex example doAssert g2(int) == "error" +block: # issue #20811 + template injectError(body: untyped): untyped = + template error: untyped {.used, inject.} = "injected" + body + + proc outerOpen(error: string): string = + injectError: + proc genericInner[T](): string = + error + genericInner[int]() + + doAssert outerOpen("captured") == "injected" + block: # issue #23865 for templates type Xxx = enum error