summary refs log tree commit diff stats
path: root/tests/generics
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-09-07 06:30:37 +0300
committerGitHub <noreply@github.com>2023-09-07 05:30:37 +0200
commited9e3cba07c9d03714b4ea22e50dcc7e706e0bed (patch)
tree349bed3019983c150279928804fed01149a73f12 /tests/generics
parentb9f039e0c39c8f4e10ebdbe77e9a91f2595e1cbe (diff)
downloadNim-ed9e3cba07c9d03714b4ea22e50dcc7e706e0bed.tar.gz
make getType nodes of generic insts have full inst type (#22655)
fixes #22639 for the third time

Nodes generated by `getType` for `tyGenericInst` types, instead of
having the original `tyGenericInst` type, will have the type of the last
child (due to the `mapTypeToAst` calls which set the type to the given
argument). This will cause subsequent `getType` calls to lose
information and think it's OK to use the sym of the instantiated type
rather than fully expand the generic instantiation.

To prevent this, update the type of the node from the `mapTypeToAst`
calls to the full generic instantiation type.
Diffstat (limited to 'tests/generics')
-rw-r--r--tests/generics/timpl_ast.nim35
1 files changed, 35 insertions, 0 deletions
diff --git a/tests/generics/timpl_ast.nim b/tests/generics/timpl_ast.nim
index 016128e30..97fe128cd 100644
--- a/tests/generics/timpl_ast.nim
+++ b/tests/generics/timpl_ast.nim
@@ -43,3 +43,38 @@ block: # issues #9899, ##14708
     macro parse(s: static string) =
       result = parseStmt(s)
     parse("type " & implRepr(Option))
+
+block: # issue #22639
+  type
+    Spectrum[N: static int] = object
+      data: array[N, float]
+    AngleInterpolator = object
+      data: seq[Spectrum[60]]
+  proc initInterpolator(num: int): AngleInterpolator =
+    result = AngleInterpolator()
+    for i in 0 ..< num:
+      result.data.add Spectrum[60]()
+  macro genCompatibleTuple(t: typed): untyped =
+    let typ = t.getType[1].getTypeImpl[2]
+    result = nnkTupleTy.newTree()
+    for i, ch in typ: # is `nnkObjectTy`
+      result.add nnkIdentDefs.newTree(ident(ch[0].strVal), # ch is `nnkIdentDefs`
+                                      ch[1],
+                                      newEmptyNode())
+  proc fullSize[T: object | tuple](x: T): int =
+    var tmp: genCompatibleTuple(T)
+    result = 0
+    for field, val in fieldPairs(x):
+      result += sizeof(val)
+    doAssert result == sizeof(tmp)
+
+  let reflectivity = initInterpolator(1)
+  for el in reflectivity.data:
+    doAssert fullSize(el) == sizeof(el)
+  doAssert fullSize(reflectivity.data[0]) == sizeof(reflectivity.data[0])
+  doAssert genCompatibleTuple(Spectrum[60]) is tuple[data: array[60, float]]
+  doAssert genCompatibleTuple(Spectrum[120]) is tuple[data: array[120, float]]
+  type Foo[T] = object
+    data: T
+  doAssert genCompatibleTuple(Foo[int]) is tuple[data: int]
+  doAssert genCompatibleTuple(Foo[float]) is tuple[data: float]