From 0c41ac792b64b710b4702cd4ae88d4392744a1ea Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 11 Sep 2020 01:50:42 +0200 Subject: [PATCH] fixes #15122 (#15301) --- compiler/liftdestructors.nim | 17 ++++++++++++-- tests/arc/theavy_recursion.nim | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/arc/theavy_recursion.nim diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index c1fd7981ef..b3300850e7 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -462,6 +462,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = case c.kind of attachedAsgn, attachedDeepCopy: + # XXX: replace these with assertions. if t.assignment == nil: return # protect from recursion body.add newHookCall(c, t.assignment, x, y) @@ -827,7 +828,10 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; if typ.kind == tyDistinct: return produceSymDistinctType(g, c, typ, kind, info) - result = symPrototype(g, typ, typ.owner, kind, info) + result = typ.attachedOps[kind] + if result == nil: + result = symPrototype(g, typ, typ.owner, kind, info) + var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType:typ) a.fn = result @@ -947,9 +951,18 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf let lastAttached = if g.config.selectedGC == gcOrc: attachedDispose else: attachedSink + # bug #15122: We need to produce all prototypes before entering the + # mind boggling recursion. Hacks like these imply we shoule rewrite + # this module. + var generics: array[attachedDestructor..attachedDispose, bool] + for k in attachedDestructor..lastAttached: + generics[k] = canon.attachedOps[k] != nil + if not generics[k]: + canon.attachedOps[k] = symPrototype(g, canon, canon.owner, k, info) + # we generate the destructor first so that other operators can depend on it: for k in attachedDestructor..lastAttached: - if canon.attachedOps[k] == nil: + if not generics[k]: discard produceSym(g, c, canon, k, info) else: inst(canon.attachedOps[k], canon) diff --git a/tests/arc/theavy_recursion.nim b/tests/arc/theavy_recursion.nim new file mode 100644 index 0000000000..9813331f4f --- /dev/null +++ b/tests/arc/theavy_recursion.nim @@ -0,0 +1,43 @@ +discard """ + output: "yay" + cmd: "nim c --gc:arc $file" +""" + +# bug #15122 + +import tables + +type + BENodeKind* = enum + tkEof, + tkBytes, + tkList, + tkDict + + BENode* = object + case kind: BENodeKind + of tkBytes: strVal: string + of tkList: listVal: seq[BENode] + of tkDict: dictVal*: Table[string, BENode] + else: + discard + +proc unused(s: string): BENode = + # bad: + result = BENode(kind: tkBytes, strVal: "abc") + +proc main = + var data = { + "examples": { + "values": BENode( + kind: tkList, + listVal: @[BENode(kind: tkBytes, strVal: "test")] + ) + }.toTable() + }.toTable() + + # For ARC listVal is empty for some reason + doAssert data["examples"]["values"].listVal[0].strVal == "test" + +main() +echo "yay"