diff --git a/compiler/lookups.nim b/compiler/lookups.nim index afa2716d8ac5f..6301368986e27 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -566,7 +566,11 @@ proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extr if name == "_": err = "the special identifier '_' is ignored in declarations and cannot be used" else: - err = "undeclared identifier: '" & name & "'" & extra + err = "undeclared identifier: '" & name & "'" + if "`gensym" in name: + err.add "; if declared in a template, this identifier may be inconsistently marked inject or gensym" + if extra.len != 0: + err.add extra if c.recursiveDep.len > 0: err.add "\nThis might be caused by a recursive module dependency:\n" err.add c.recursiveDep diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 36b7838ec6f13..871a10db98790 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -260,7 +260,7 @@ proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode = if n.kind == nkIdent: let s = qualifiedLookUp(c.c, n, {}) if s != nil: - if s.owner == c.owner and (s.kind == skParam or sfGenSym in s.flags): + if s.owner == c.owner and s.kind == skParam: incl(s.flags, sfUsed) result = newSymNode(s, n.info) onUse(n.info, s) diff --git a/testament/important_packages.nim b/testament/important_packages.nim index 462bf8a30d28f..65f48d5537493 100644 --- a/testament/important_packages.nim +++ b/testament/important_packages.nim @@ -60,7 +60,7 @@ pkg "compactdict" pkg "comprehension", "nimble test", "https://github.com/alehander92/comprehension" pkg "cowstrings" pkg "criterion", allowFailure = true # needs testing binary -pkg "datamancer" +pkg "datamancer", "nimble install -y arraymancer@#HEAD; nimble test" pkg "dashing", "nim c tests/functional.nim" pkg "delaunay" pkg "docopt" @@ -72,7 +72,7 @@ pkg "fragments", "nim c -r fragments/dsl.nim", allowFailure = true # pending htt pkg "fusion" pkg "gara" pkg "glob" -pkg "ggplotnim", "nim c -d:noCairo -r tests/tests.nim" +pkg "ggplotnim", "nimble install -y arraymancer@#HEAD; nim c -d:noCairo -r tests/tests.nim" pkg "gittyup", "nimble test", "https://github.com/disruptek/gittyup", allowFailure = true pkg "gnuplot", "nim c gnuplot.nim" # pkg "gram", "nim c -r --mm:arc --define:danger tests/test.nim", "https://github.com/disruptek/gram" @@ -124,7 +124,7 @@ pkg "nimx", "nim c test/main.nim", allowFailure = true pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter" pkg "norm", "testament r tests/common/tmodel.nim" pkg "npeg", "nimble testarc" -pkg "numericalnim", "nimble nimCI" +pkg "numericalnim", "nimble install -y arraymancer@#HEAD; nimble nimCI" pkg "optionsutils" pkg "ormin", "nim c -o:orminn ormin.nim" pkg "parsetoml" diff --git a/tests/errmsgs/tinconsistentgensym.nim b/tests/errmsgs/tinconsistentgensym.nim new file mode 100644 index 0000000000000..026c17fcaa202 --- /dev/null +++ b/tests/errmsgs/tinconsistentgensym.nim @@ -0,0 +1,25 @@ +discard """ + cmd: "nim check --hints:off $file" +""" + +block: + template foo = + when false: + let x = 123 + else: + template x: untyped = 456 + echo x #[tt.Error + ^ undeclared identifier: 'x`gensym0'; if declared in a template, this identifier may be inconsistently marked inject or gensym]# + foo() + +block: + template foo(y: static bool) = + block: + when y: + let x {.gensym.} = 123 + else: + let x {.inject.} = 456 + echo x #[tt.Error + ^ undeclared identifier: 'x']# + foo(false) + foo(true) diff --git a/tests/template/tgensymhijack.nim b/tests/template/tgensymhijack.nim new file mode 100644 index 0000000000000..72ff3d49571b2 --- /dev/null +++ b/tests/template/tgensymhijack.nim @@ -0,0 +1,37 @@ +# issue #23326 + +type Result*[E] = object + e*: E + +proc error*[E](v: Result[E]): E = discard + +template valueOr*[E](self: Result[E], def: untyped): int = + when E isnot void: + when false: + # Comment line below to make it work + template error(): E {.used, gensym.} = s.e + discard + else: + template error(): E {.used, inject.} = + self.e + + def + else: + def + + +block: + let rErr = Result[string](e: "a") + let rErrV = rErr.valueOr: + ord(error[0]) + +block: + template foo(x: static bool): untyped = + when x: + let a = 123 + else: + template a: untyped {.gensym.} = 456 + a + + doAssert foo(false) == 456 + doAssert foo(true) == 123