diff options
Diffstat (limited to 'tests/template')
-rw-r--r-- | tests/template/m19277_1.nim | 2 | ||||
-rw-r--r-- | tests/template/m19277_2.nim | 2 | ||||
-rw-r--r-- | tests/template/mdotcall.nim | 32 | ||||
-rw-r--r-- | tests/template/mqualifiedtype1.nim | 2 | ||||
-rw-r--r-- | tests/template/mqualifiedtype2.nim | 2 | ||||
-rw-r--r-- | tests/template/t13426.nim | 87 | ||||
-rw-r--r-- | tests/template/t19277.nim | 19 | ||||
-rw-r--r-- | tests/template/t21532.nim | 8 | ||||
-rw-r--r-- | tests/template/t24112.nim | 19 | ||||
-rw-r--r-- | tests/template/tdefaultparam.nim | 56 | ||||
-rw-r--r-- | tests/template/tdotcall.nim | 12 | ||||
-rw-r--r-- | tests/template/template_various.nim | 36 | ||||
-rw-r--r-- | tests/template/tgenericparam.nim | 93 | ||||
-rw-r--r-- | tests/template/tgensymhijack.nim | 37 | ||||
-rw-r--r-- | tests/template/tinnerouterproc.nim | 12 | ||||
-rw-r--r-- | tests/template/tnested.nim | 38 | ||||
-rw-r--r-- | tests/template/tobjectdeclfield.nim | 25 | ||||
-rw-r--r-- | tests/template/topensym.nim | 209 | ||||
-rw-r--r-- | tests/template/topensymoverride.nim | 39 | ||||
-rw-r--r-- | tests/template/topensymwarning.nim | 60 | ||||
-rw-r--r-- | tests/template/tparams_gensymed.nim | 9 | ||||
-rw-r--r-- | tests/template/tqualifiedident.nim | 8 | ||||
-rw-r--r-- | tests/template/tqualifiedtype.nim | 25 |
23 files changed, 824 insertions, 8 deletions
diff --git a/tests/template/m19277_1.nim b/tests/template/m19277_1.nim new file mode 100644 index 000000000..840bd4767 --- /dev/null +++ b/tests/template/m19277_1.nim @@ -0,0 +1,2 @@ +template foo*(x: untyped) = + echo "got: ", x diff --git a/tests/template/m19277_2.nim b/tests/template/m19277_2.nim new file mode 100644 index 000000000..de72dad45 --- /dev/null +++ b/tests/template/m19277_2.nim @@ -0,0 +1,2 @@ +proc foo*(a: string) = + echo "got string: ", a diff --git a/tests/template/mdotcall.nim b/tests/template/mdotcall.nim index 13dcbd824..fecd8ee26 100644 --- a/tests/template/mdotcall.nim +++ b/tests/template/mdotcall.nim @@ -48,3 +48,35 @@ template publicTemplateObjSyntax*(o: var ObjA, arg: Natural, doStuff: untyped) = o.foo2() doStuff o.bar2(arg) + +# issue #15246 +import os + +template sourceBaseName*(): string = + bind splitFile + instantiationInfo().filename.splitFile().name + +# issue #12683 + +import unicode +template toRune(s: string): Rune = s.runeAt(0) +proc heh*[T](x: Slice[T], chars: string) = discard chars.toRune + +# issue #7889 + +from streams import newStringStream, readData, writeData + +template bindmeTemplate*(): untyped = + var tst = "sometext" + var ss = newStringStream("anothertext") + ss.writeData(tst[0].addr, 2) + discard ss.readData(tst[0].addr, 2) # <= comment this out to make compilation successful + +from macros import quote, newIdentNode + +macro bindmeQuote*(): untyped = + quote do: + var tst = "sometext" + var ss = newStringStream("anothertext") + ss.writeData(tst[0].addr, 2) + discard ss.readData(tst[0].addr, 2) # <= comment this out to make compilation successful diff --git a/tests/template/mqualifiedtype1.nim b/tests/template/mqualifiedtype1.nim new file mode 100644 index 000000000..46569107f --- /dev/null +++ b/tests/template/mqualifiedtype1.nim @@ -0,0 +1,2 @@ +type A* = object + x*: int diff --git a/tests/template/mqualifiedtype2.nim b/tests/template/mqualifiedtype2.nim new file mode 100644 index 000000000..6a61c14bd --- /dev/null +++ b/tests/template/mqualifiedtype2.nim @@ -0,0 +1,2 @@ +type A* = object + x*: array[1000, byte] diff --git a/tests/template/t13426.nim b/tests/template/t13426.nim new file mode 100644 index 000000000..f7f44749c --- /dev/null +++ b/tests/template/t13426.nim @@ -0,0 +1,87 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: ''' +t13426.nim(81, 6) template/generic instantiation of `fun` from here +t13426.nim(80, 24) Error: type mismatch: got <int> but expected 'string' +t13426.nim(81, 6) template/generic instantiation of `fun` from here +t13426.nim(80, 17) Error: type mismatch: got <uint, string> +but expected one of: +proc `and`(x, y: uint): uint + first type mismatch at position: 2 + required type for y: uint + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint64): uint64 + first type mismatch at position: 2 + required type for y: uint64 + but expression 'high(@[1])' is of type: string +10 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them + +expression: 1'u and high(@[1]) +t13426.nim(81, 6) template/generic instantiation of `fun` from here +t13426.nim(80, 17) Error: expression '' has no type (or is ambiguous) +t13426.nim(87, 6) template/generic instantiation of `fun` from here +t13426.nim(86, 22) Error: type mismatch: got <int> but expected 'string' +t13426.nim(87, 6) template/generic instantiation of `fun` from here +t13426.nim(86, 15) Error: type mismatch: got <int literal(1), string> +but expected one of: +proc `and`(x, y: int): int + first type mismatch at position: 2 + required type for y: int + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int16): int16 + first type mismatch at position: 2 + required type for y: int16 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int32): int32 + first type mismatch at position: 2 + required type for y: int32 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int64): int64 + first type mismatch at position: 2 + required type for y: int64 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int8): int8 + first type mismatch at position: 2 + required type for y: int8 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint): uint + first type mismatch at position: 2 + required type for y: uint + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint16): uint16 + first type mismatch at position: 2 + required type for y: uint16 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint32): uint32 + first type mismatch at position: 2 + required type for y: uint32 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint64): uint64 + first type mismatch at position: 2 + required type for y: uint64 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint8): uint8 + first type mismatch at position: 2 + required type for y: uint8 + but expression 'high(@[1])' is of type: string +2 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them + +expression: 1 and high(@[1]) +t13426.nim(87, 6) template/generic instantiation of `fun` from here +t13426.nim(86, 15) Error: expression '' has no type (or is ambiguous) +''' +""" + +# bug # #13426 +block: + template bar(t): string = high(t) + proc fun[A](key: A) = + var h = 1'u and bar(@[1]) + fun(0) + +block: + template bar(t): string = high(t) + proc fun[A](key: A) = + var h = 1 and bar(@[1]) + fun(0) diff --git a/tests/template/t19277.nim b/tests/template/t19277.nim new file mode 100644 index 000000000..16435a09c --- /dev/null +++ b/tests/template/t19277.nim @@ -0,0 +1,19 @@ +discard """ + output: ''' +got: 0 +''' +""" + +# issue #19277 + +import m19277_1, m19277_2 + +template injector(val: untyped): untyped = + template subtemplate: untyped = val + subtemplate() + +template methodCall(val: untyped): untyped = val + +{.push raises: [Defect].} + +foo(injector(0).methodCall()) diff --git a/tests/template/t21532.nim b/tests/template/t21532.nim new file mode 100644 index 000000000..3193b0dc3 --- /dev/null +++ b/tests/template/t21532.nim @@ -0,0 +1,8 @@ + +template elementType(a: untyped): typedesc = + typeof(block: (for ai in a: ai)) + +func fn[T](a: T) = + doAssert elementType(a) is int + +@[1,2,3].fn \ No newline at end of file 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]# diff --git a/tests/template/tdefaultparam.nim b/tests/template/tdefaultparam.nim new file mode 100644 index 000000000..7ea0b2b25 --- /dev/null +++ b/tests/template/tdefaultparam.nim @@ -0,0 +1,56 @@ +block: + template foo(a: untyped, b: untyped = a(0)): untyped = + let x = a(0) + let y = b + (x, y) + proc bar(x: int): int = x + 1 + doAssert foo(bar, b = bar(0)) == (1, 1) + doAssert foo(bar) == (1, 1) + +block: # issue #23506 + var a: string + template foo(x: int; y = x) = + a = $($x, $y) + foo(1) + doAssert a == "(\"1\", \"1\")" + +block: # untyped params with default value + macro foo(x: typed): untyped = + result = x + template test(body: untyped, alt: untyped = (;), maxTries = 3): untyped {.foo.} = + body + alt + var s = "a" + test: + s.add "b" + do: + s.add "c" + doAssert s == "abc" + template test2(body: untyped, alt: untyped = s.add("e"), maxTries = 3): untyped = + body + alt + test2: + s.add "d" + doAssert s == "abcde" + template test3(body: untyped = willNotCompile) = + discard + test3() + +block: # typed params with `void` default value + macro foo(x: typed): untyped = + result = x + template test(body: untyped, alt: typed = (;), maxTries = 3): untyped {.foo.} = + body + alt + var s = "a" + test: + s.add "b" + do: + s.add "c" + doAssert s == "abc" + template test2(body: untyped, alt: typed = s.add("e"), maxTries = 3): untyped = + body + alt + test2: + s.add "d" + doAssert s == "abcde" diff --git a/tests/template/tdotcall.nim b/tests/template/tdotcall.nim index 5fc991dd2..dc97fd52e 100644 --- a/tests/template/tdotcall.nim +++ b/tests/template/tdotcall.nim @@ -18,3 +18,15 @@ block: # issue #11733 var evaluated = false a.publicTemplateObjSyntax(42): evaluated = true doAssert evaluated + +block: # issue #15246 + doAssert sourceBaseName() == "tdotcall" + +block: # issue #12683 + heh(0..40, "|") + +block: # issue #7889 + if false: + bindmeQuote() + if false: + bindmeTemplate() diff --git a/tests/template/template_various.nim b/tests/template/template_various.nim index a3b549e18..2088b1739 100644 --- a/tests/template/template_various.nim +++ b/tests/template/template_various.nim @@ -354,6 +354,23 @@ block gensym3: echo a ! b ! c ! d ! e echo x,y,z +block: # issue #2465 + template t() = + template declX(str: string) {.gensym.} = + var x {.inject.} : string = str + + t() + doAssert not declared(declX) + doAssert not compiles(declX("a string")) + + template t2() = + template fooGensym() {.gensym.} = + echo 42 + + t2() + doAssert not declared(fooGensym) + doAssert not compiles(fooGensym()) + block identifier_construction_with_overridden_symbol: # could use add, but wanna make sure it's an override no matter what @@ -368,3 +385,22 @@ block identifier_construction_with_overridden_symbol: `examplefn n`() exampletempl(1) + +import typetraits + +block: # issue #4596 + type + T0 = object + T1 = object + + template printFuncsT() = + proc getV[A](a: typedesc[A]): string = + var s {. global .} = name(A) + return s + + printFuncsT() + + doAssert getV(T1) == "T1" + doAssert getV(T0) == "T0" + doAssert getV(T0) == "T0" + doAssert getV(T1) == "T1" diff --git a/tests/template/tgenericparam.nim b/tests/template/tgenericparam.nim new file mode 100644 index 000000000..becf75d36 --- /dev/null +++ b/tests/template/tgenericparam.nim @@ -0,0 +1,93 @@ +block: # basic template generic parameter substitution + block: # issue #13527 + template typeNameTempl[T](a: T): string = $T + proc typeNameProc[T](a: T): string = $T + doAssert typeNameTempl(1) == typeNameProc(1) + doAssert typeNameTempl(true) == typeNameProc(true) + doAssert typeNameTempl(1.0) == typeNameProc(1.0) + doAssert typeNameTempl(1u8) == typeNameProc(1u8) + + template isDefault[T](a: T): bool = a == default(T) + doAssert isDefault(0.0) + + block: # issue #17240 + func to(c: int, t: typedesc[float]): t = discard + template converted[I, T](i: seq[I], t: typedesc[T]): seq[T] = + var result = newSeq[T](2) + result[0] = i[0].to(T) + result + doAssert newSeq[int](3).converted(float) == @[0.0, 0.0] + + block: # issue #6340 + type A[T] = object + v: T + proc foo(x: int): string = "int" + proc foo(x: typedesc[int]): string = "typedesc[int]" + template fooT(x: int): string = "int" + template fooT(x: typedesc[int]): string = "typedesc[int]" + proc foo[T](x: A[T]): (string, string) = + (foo(T), fooT(T)) + template fooT[T](x: A[T]): (string, string) = + (foo(T), fooT(T)) + var x: A[int] + doAssert foo(x) == fooT(x) + + block: # issue #20033 + template run[T](): T = default(T) + doAssert run[int]() == 0 + +import options, tables, typetraits + +block: # complex cases of above with imports + block: # issue #19576, complex case + type RegistryKey = object + key, val: string + var regKey = @[RegistryKey(key: "abc", val: "def")] + template findFirst[T](s: seq[T], pred: proc(x: T): bool): Option[T] = + var res = none(T) # important line + for x in s: + if pred(x): + res = some(x) + break + res + proc getval(searchKey: string): Option[string] = + let found = regKey.findFirst(proc (rk: RegistryKey): bool = rk.key == searchKey) + if found.isNone: none(string) + else: some(found.get().val) + doAssert getval("strange") == none(string) + doAssert getval("abc") == some("def") + block: # issue #19076 + block: # case 1 + var tested: Table[string,int] + template `[]`[V](t:Table[string,V],key:string):untyped = + $V + doAssert tested["abc"] == "int" + template `{}`[V](t:Table[string,V],key:string):untyped = + ($V, tables.`[]`(t, key)) + doAssert (try: tested{"abc"} except KeyError: ("not there", 123)) == ("not there", 123) + tables.`[]=`(tested, "abc", 456) + doAssert tested["abc"] == "int" + doAssert tested{"abc"} == ("int", 456) + block: # case 2 + type Foo[A,T] = object + t:T + proc init[A,T](f:type Foo,a:typedesc[A],t:T):Foo[A,T] = Foo[A,T](t:t) + template fromOption[A](o:Option[A]):auto = + when o.isSome: + Foo.init(A,35) + else: + Foo.init(A,"hi") + let op = fromOption(some(5)) + block: # issue #7461 + template p[T](): untyped = none(T) + doAssert p[int]() == none(int) + block: # issue #7995 + var res: string + template copyRange[T](dest: seq[T], destOffset: int) = + when supportsCopyMem(T): + res = "A" + else: + res = "B" + var a = @[1, 2, 3] + copyRange(a, 0) + doAssert res == "A" diff --git a/tests/template/tgensymhijack.nim b/tests/template/tgensymhijack.nim new file mode 100644 index 000000000..72ff3d495 --- /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 diff --git a/tests/template/tinnerouterproc.nim b/tests/template/tinnerouterproc.nim index 1f15fb13e..56e0d02df 100644 --- a/tests/template/tinnerouterproc.nim +++ b/tests/template/tinnerouterproc.nim @@ -6,3 +6,15 @@ block: # #20002 discard 3.bar # evaluates to 10 but only check if it compiles for now block: foo() + +block: # issue #23813 + template r(body: untyped) = + proc x() {.gensym.} = + body + template g() = + r: + let y = 0 + r: + proc y() = discard + y() + g() diff --git a/tests/template/tnested.nim b/tests/template/tnested.nim new file mode 100644 index 000000000..81e416a76 --- /dev/null +++ b/tests/template/tnested.nim @@ -0,0 +1,38 @@ +block: # issue #22775 + proc h(c: int) = discard + template k(v: int) = + template p() = v.h() + p() + let a = @[0] + k(0 and not a[0]) + +block: # issue #22775 case 2 + proc h(c: int, q: int) = discard + template k(v: int) = + template p() = h(v, v) + p() + let a = [0] + k(0 and not a[0]) + +block: # issue #22775 minimal cases + proc h(c: int) = discard + template k(v: int) = + template p() = h(v) + p() + let a = [0] + k(not a[0]) + block: + k(-a[0]) + block: + proc f(x: int): int = x + k(f a[0]) + +block: # bracket assignment case of above tests + proc h(c: int) = discard + template k(v: int) = + template p() = h(v) + p() + var a = [0] + k(not (block: + a[0] = 1 + 1)) diff --git a/tests/template/tobjectdeclfield.nim b/tests/template/tobjectdeclfield.nim index 201f076ca..afce2cae8 100644 --- a/tests/template/tobjectdeclfield.nim +++ b/tests/template/tobjectdeclfield.nim @@ -1,12 +1,21 @@ -var x = 0 +block: # issue #16005 + var x = 0 -block: - type Foo = object - x: float # ok - -template main() = block: type Foo = object - x: float # Error: cannot use symbol of kind 'var' as a 'field' + x: float # ok + + template main() = + block: + type Foo = object + x: float # Error: cannot use symbol of kind 'var' as a 'field' + + main() + +block: # issue #19552 + template test = + type + test2 = ref object + reset: int -main() + test() diff --git a/tests/template/topensym.nim b/tests/template/topensym.nim new file mode 100644 index 000000000..2f930407b --- /dev/null +++ b/tests/template/topensym.nim @@ -0,0 +1,209 @@ +{.experimental: "openSym".} + +block: # issue #24002 + type Result[T, E] = object + func value[T, E](self: Result[T, E]): T {.inline.} = + discard + func value[T: not void, E](self: var Result[T, E]): var T {.inline.} = + discard + template unrecognizedFieldWarning = + doAssert value == 123 + let x = value + doAssert value == x + proc readValue(value: var int) = + unrecognizedFieldWarning() + var foo: int = 123 + readValue(foo) + +block: # issue #22605 for templates, normal call syntax + const error = "bad" + + template valueOr(self: int, def: untyped): untyped = + case false + of true: "" + of false: + template error: untyped {.used, inject.} = "good" + def + + template g(T: type): string = + var res = "ok" + let x = valueOr 123: + res = $error + "dummy" + res + + doAssert g(int) == "good" + + template g2(T: type): string = + bind error # use the bad version on purpose + var res = "ok" + let x = valueOr 123: + res = $error + "dummy" + res + + doAssert g2(int) == "bad" + +block: # issue #22605 for templates, method call syntax + const error = "bad" + + template valueOr(self: int, def: untyped): untyped = + case false + of true: "" + of false: + template error: untyped {.used, inject.} = "good" + def + + template g(T: type): string = + var res = "ok" + let x = 123.valueOr: + res = $error + "dummy" + res + + doAssert g(int) == "good" + + template g2(T: type): string = + bind error # use the bad version on purpose + var res = "ok" + let x = 123.valueOr: + res = $error + "dummy" + res + + doAssert g2(int) == "bad" + +block: # issue #22605 for templates, original complex example + type Xxx = enum + error + value + + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + + template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + + proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + + template g(T: type): string = + var res = "ok" + let x = f().valueOr: + res = $error + 123 + res + + doAssert g(int) == "f" + + template g2(T: type): string = + bind error # use the bad version on purpose + var res = "ok" + let x = f().valueOr: + res = $error + 123 + res + + doAssert g2(int) == "error" + +block: # issue #23865 for templates + type Xxx = enum + error + value + + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate: bool + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + discard + else: + when E is void: + case oResultPrivate: bool + of false: + discard + of true: + vResultPrivate: T + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + vResultPrivate: T + + func error[T, E](self: Result[T, E]): E = + ## Fetch error of result if set, or raise Defect + case self.oResultPrivate + of true: + when T isnot void: + raiseResultDefect("Trying to access error when value is set", self.vResultPrivate) + else: + raiseResultDefect("Trying to access error when value is set") + of false: + when E isnot void: + self.eResultPrivate + + template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + template g(T: type): string = + var res = "ok" + let x = f().valueOr: + res = $error + 123 + res + doAssert g(int) == "f" + +import std/sequtils + +block: # issue #15314 + var it: string + var nums = @[1,2,3] + + template doubleNums() = + nums.applyIt(it * 2) + + doubleNums() + doAssert nums == @[2, 4, 6] diff --git a/tests/template/topensymoverride.nim b/tests/template/topensymoverride.nim new file mode 100644 index 000000000..3d4bb59f1 --- /dev/null +++ b/tests/template/topensymoverride.nim @@ -0,0 +1,39 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj" +""" + +const value = "captured" +template fooOld(x: int, body: untyped): untyped = + let value {.inject.} = "injected" + body +template foo(x: int, body: untyped): untyped = + let value {.inject.} = "injected" + {.push experimental: "genericsOpenSym".} + body + {.pop.} + +proc old[T](): string = + fooOld(123): + return value +doAssert old[int]() == "captured" + +template oldTempl(): string = + block: + var res: string + fooOld(123): + res = value + res +doAssert oldTempl() == "captured" + +proc bar[T](): string = + foo(123): + return value +doAssert bar[int]() == "injected" + +template barTempl(): string = + block: + var res: string + foo(123): + res = value + res +doAssert barTempl() == "injected" diff --git a/tests/template/topensymwarning.nim b/tests/template/topensymwarning.nim new file mode 100644 index 000000000..0bbe0a9fb --- /dev/null +++ b/tests/template/topensymwarning.nim @@ -0,0 +1,60 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj" +""" + +type Xxx = enum + error + value + +type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + +template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + +proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + +template g(T: type): string = + var res = "ok" + let x = f().valueOr: + {.push warningAsError[IgnoredSymbolInjection]: on.} + # test spurious error + discard true + let _ = f + {.pop.} + res = $error #[tt.Warning + ^ a new symbol 'error' has been injected during template or generic instantiation, however 'error' [enumField declared in topensymwarning.nim(6, 3)] captured at the proc declaration will be used instead; either enable --experimental:openSym to use the injected symbol, or `bind` this captured symbol explicitly [IgnoredSymbolInjection]]# + 123 + res + +discard g(int) diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index b68d7e253..b559c2d9e 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -16,6 +16,7 @@ wth (total: 6) S1 5 +abc ''' """ # bug #1915 @@ -394,3 +395,11 @@ proc chunkedReadLoop2 = test2 test1(); test2() + +block: # bug #22846 + template foo2(x: proc (y: string)) = + let f = x + f("abc") + + foo2(proc (y: string) = echo y) + diff --git a/tests/template/tqualifiedident.nim b/tests/template/tqualifiedident.nim new file mode 100644 index 000000000..463b14ee7 --- /dev/null +++ b/tests/template/tqualifiedident.nim @@ -0,0 +1,8 @@ +block: # issue #19865 + template f() = discard default(system.int) + f() + +# issue #21221, same as above +type M = object +template r() = discard default(tqualifiedident.M) +r() diff --git a/tests/template/tqualifiedtype.nim b/tests/template/tqualifiedtype.nim new file mode 100644 index 000000000..6497af6ee --- /dev/null +++ b/tests/template/tqualifiedtype.nim @@ -0,0 +1,25 @@ +# issue #19866 + +# Switch module import order to switch which of last two +# doAsserts fails +import mqualifiedtype1 +import mqualifiedtype2 + +# this isn't officially supported but needed to point out the issue: +template f(moduleName: untyped): int = sizeof(`moduleName`.A) +template g(someType: untyped): int = sizeof(someType) + +# These are legitimately true. +doAssert sizeof(mqualifiedtype1.A) != sizeof(mqualifiedtype2.A) +doAssert g(mqualifiedtype1.A) != g(mqualifiedtype2.A) + +# Which means that this should not be true, but is in Nim 1.6 +doAssert f(`mqualifiedtype1`) != f(`mqualifiedtype2`) +doAssert f(mqualifiedtype1) != f(mqualifiedtype2) + +# These should be true, but depending on import order, exactly one +# fails in Nim 1.2, 1.6 and devel. +doAssert f(`mqualifiedtype1`) == g(mqualifiedtype1.A) +doAssert f(`mqualifiedtype2`) == g(mqualifiedtype2.A) +doAssert f(mqualifiedtype1) == g(mqualifiedtype1.A) +doAssert f(mqualifiedtype2) == g(mqualifiedtype2.A) |