Skip to content

Commit

Permalink
generic issues test cases (#24028)
Browse files Browse the repository at this point in the history
closes #1969, closes #7547, closes #7737, closes #11838, closes #12283,
closes #12714, closes #12720, closes #14053, closes #16118, closes
#19670, closes #22645

I was going to wait on these but regression tests even for recent PRs
are turning out to be important in wide reaching PRs like #24010.

The other issues with the working label felt either finnicky (#7385,
#9156, #12732, #15247), excessive to test (#12405, #12424, #17527), or I
just don't know what fixed them/what the issue was (#16128: the PR link
gives a server error by Github, #12457, #12487).
  • Loading branch information
metagn authored Aug 30, 2024
1 parent 11ead19 commit fc853cb
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 0 deletions.
86 changes: 86 additions & 0 deletions tests/generics/tbracketinstantiation.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
discard """
nimout: '''
type
Bob = object
type
Another = object
'''
"""

block: # issue #22645
type
Opt[T] = object
FutureBase = ref object of RootObj
Future[T] = ref object of FutureBase ## Typed future.
internalValue: T ## Stored value
template err[T](E: type Opt[T]): E = E()
proc works(): Future[Opt[int]] {.stackTrace: off, gcsafe, raises: [].} =
var chronosInternalRetFuture: FutureBase
template result(): untyped {.used.} =
Future[Opt[int]](chronosInternalRetFuture).internalValue
result = err(type(result))
proc breaks(): Future[Opt[int]] {.stackTrace: off, gcsafe, raises: [].} =
var chronosInternalRetFuture: FutureBase
template result(): untyped {.used.} =
cast[Future[Opt[int]]](chronosInternalRetFuture).internalValue
result = err(type(result))

import macros

block: # issue #16118
macro thing(name: static[string]) =
result = newStmtList(
nnkTypeSection.newTree(
nnkTypeDef.newTree(
ident(name),
newEmptyNode(),
nnkObjectTy.newTree(
newEmptyNode(),
newEmptyNode(),
nnkRecList.newTree()))))
template foo(name: string): untyped =
thing(name)
expandMacros:
foo("Bob")
block:
expandMacros:
foo("Another")

block: # issue #19670
type
Past[Z] = object
OpenObject = object

macro rewriter(prc: untyped): untyped =
prc.body.add(nnkCall.newTree(
prc.params[0]
))
prc

macro macroAsync(name, restype: untyped): untyped =
quote do:
proc `name`(): Past[seq[`restype`]] {.rewriter.} = discard

macroAsync(testMacro, OpenObject)

import asyncdispatch

block: # issue #11838 long
type
R[P] = object
updates: seq[P]
D[T, P] = ref object
ps: seq[P]
t: T
proc newD[T, P](ps: seq[P], t: T): D[T, P] =
D[T, P](ps: ps, t: t)
proc loop[T, P](d: D[T, P]) =
var results = newSeq[Future[R[P]]](10)
let d = newD[string, int](@[1], "")
d.loop()

block: # issue #11838 minimal
type R[T] = object
proc loop[T]() =
discard newSeq[R[R[T]]]()
loop[int]()
12 changes: 12 additions & 0 deletions tests/generics/tmacroinjectedsym.nim
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,15 @@ block: # issue #23865
return $error
"ok"
doAssert g(int) == "f"

import sequtils

block: # issue #12283
var b = 5
type Foo[T] = object
h, w: int
proc bar[T](foos: seq[Foo[T]]): T =
let w = foldl(foos, a + b.w, 0)
w
let foos = @[Foo[int](h: 3, w: 5), Foo[int](h: 4, w: 6)]
doAssert bar(foos) == 11
31 changes: 31 additions & 0 deletions tests/generics/tuninstantiatedgenericcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,37 @@ block: # issue #22647
var x: b[4]
x.p()

block: # issue #1969
type ZeroGenerator = object
proc next(g: ZeroGenerator): int = 0
# This compiles.
type TripleOfInts = tuple
a, b, c: typeof(new(ZeroGenerator)[].next)
# This raises a compiler error before it's even instantiated.
# The `new` proc can't be resolved because `Generator` is not defined.
type TripleLike[Generator] = tuple
a, b, c: typeof(new(Generator)[].next)

import std/atomics

block: # issue #12720
const CacheLineSize = 128
type
Enqueueable = concept x, type T
x is ptr
x.next is Atomic[pointer]
MyChannel[T: Enqueueable] = object
pad: array[CacheLineSize - sizeof(default(T)[]), byte]
dummy: typeof(default(T)[])

block: # issue #12714
type
Enqueueable = concept x, type T
x is ptr
x.next is Atomic[pointer]
MyChannel[T: Enqueueable] = object
dummy: type(default(T)[])

when false: # issue #22342, type section version of #22607
type GenAlias[isInt: static bool] = (
when isInt:
Expand Down
61 changes: 61 additions & 0 deletions tests/macros/tgettypeinst7737.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
discard """
nimout: '''
seq[int]
CustomSeq[int]
'''
"""

import macros, typetraits, sequtils

block: # issue #7737 original
type
CustomSeq[T] = object
data: seq[T]

proc getSubType(T: NimNode): NimNode =
echo getTypeInst(T).repr
result = getTypeInst(T)[1]

macro typed_helper(x: varargs[typed]): untyped =
let foo = getSubType(x[0])
result = quote do: discard

macro untyped_heavylifting(x: varargs[untyped]): untyped =
var containers = nnkArgList.newTree()
for arg in x:
case arg.kind:
of nnkInfix:
if eqIdent(arg[0], "in"):
containers.add arg[2]
else:
discard
result = quote do:
typed_helper(`containers`)
var a, b, c: seq[int]
untyped_heavylifting z in c, x in a, y in b:
discard
## The following gives me CustomSeq instead
## of CustomSeq[int] in getTypeInst
var u, v, w: CustomSeq[int]
untyped_heavylifting z in u, x in v, y in w:
discard

block: # issue #7737 comment
type
CustomSeq[T] = object
data: seq[T]
# when using just one argument, `foo` and `bar` should be exactly
# identical.
macro foo(arg: typed): string =
result = newLit(arg.getTypeInst.repr)
macro bar(args: varargs[typed]): untyped =
result = newTree(nnkBracket)
for arg in args:
result.add newLit(arg.getTypeInst.repr)
var
a: seq[int]
b: CustomSeq[int]
doAssert foo(a) == "seq[int]"
doAssert bar(a) == ["seq[int]"]
doAssert foo(b) == "CustomSeq[int]"
doAssert bar(b) == ["CustomSeq[int]"]
31 changes: 31 additions & 0 deletions tests/proc/tstaticsignature.nim
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,37 @@ block: # issue #4990 comment
let bar = Bar(curIndex: 0)
doAssert bar.next() == meB

block: # issue #14053
template returnType(value: static[int]): typedesc =
when value == 1:
int
else:
float
proc fun(value: static[int]): returnType(value) = discard
doAssert fun(1) is int
template returnType2(value: static[int]): typedesc =
int
proc fun2(value: static[int]): returnType2(value) = discard
doAssert fun2(1) is int

block: # issue #7547
macro foo(N: static[int]): untyped =
result = getType(int)
type
Foo[N: static[int]] = foo(N)
ContainsFoo[N: static[int]] = object
Ffoo: Foo[N]
proc initFoo(N: static[int]): Foo[N] = discard
proc initContainsFoo(size: static[int]): ContainsFoo[size] = discard
var a: Foo[10] # Works
doAssert a is int
let b = initFoo(10) # Works
doAssert b is int
let c = ContainsFoo[5]() # Works
doAssert c.Ffoo is int
let z = initContainsFoo(5) # Error: undeclared identifier: 'N'
doAssert z.Ffoo is int

when false: # issue #22607, needs nkWhenStmt to be handled like nkRecWhen
proc test[x: static bool](
t: (
Expand Down

0 comments on commit fc853cb

Please sign in to comment.