From 9ac56662717d8f1a0ad1a90f1e0b2a59204cfd36 Mon Sep 17 00:00:00 2001 From: metagn Date: Thu, 7 Sep 2023 06:30:37 +0300 Subject: [PATCH] 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. (cherry picked from commit ed9e3cba07c9d03714b4ea22e50dcc7e706e0bed) --- compiler/vmdeps.nim | 4 ++++ tests/generics/timpl_ast.nim | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 75692fcc0e..b141505a30 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -133,6 +133,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; if inst: if allowRecursion: result = mapTypeToAstR(t.lastSon, info) + # keep original type info for getType calls on the output node: + result.typ = t else: result = newNodeX(nkBracketExpr) #result.add mapTypeToAst(t.lastSon, info) @@ -141,6 +143,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; result.add mapTypeToAst(t[i], info) else: result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion) + # keep original type info for getType calls on the output node: + result.typ = t of tyGenericBody: if inst: result = mapTypeToAstR(t.lastSon, info) diff --git a/tests/generics/timpl_ast.nim b/tests/generics/timpl_ast.nim index 69a59e24d4..682ef9677e 100644 --- a/tests/generics/timpl_ast.nim +++ b/tests/generics/timpl_ast.nim @@ -47,3 +47,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]