diff options
-rw-r--r-- | compiler/types.nim | 21 | ||||
-rw-r--r-- | tests/types/tcyclic.nim | 20 |
2 files changed, 28 insertions, 13 deletions
diff --git a/compiler/types.nim b/compiler/types.nim index 97cc439c0..96dbd26b2 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -374,15 +374,18 @@ proc canFormAcycleAux(g: ModuleGraph; marker: var IntSet, typ: PType, orig: PTyp proc canFormAcycleNode(g: ModuleGraph; marker: var IntSet, n: PNode, orig: PType, withRef: bool, hasTrace: bool): bool = result = false if n != nil: - result = canFormAcycleAux(g, marker, n.typ, orig, withRef, hasTrace) - if not result: - case n.kind - of nkNone..nkNilLit: - discard - else: - for i in 0..<n.len: - result = canFormAcycleNode(g, marker, n[i], orig, withRef, hasTrace) - if result: return + var hasCursor = n.kind == nkSym and sfCursor in n.sym.flags + # cursor fields don't own the refs, which cannot form reference cycles + if hasTrace or not hasCursor: + result = canFormAcycleAux(g, marker, n.typ, orig, withRef, hasTrace) + if not result: + case n.kind + of nkNone..nkNilLit: + discard + else: + for i in 0..<n.len: + result = canFormAcycleNode(g, marker, n[i], orig, withRef, hasTrace) + if result: return proc sameBackendType*(x, y: PType): bool diff --git a/tests/types/tcyclic.nim b/tests/types/tcyclic.nim index fc2852c49..651394c8b 100644 --- a/tests/types/tcyclic.nim +++ b/tests/types/tcyclic.nim @@ -51,10 +51,7 @@ cyclicNo((Cyclone, )) cyclicNo(Acyclic) cyclicYes(LinkedNode) - -when false: - # todo fix me - cyclicNo(LinkedNodeWithCursor) +cyclicNo(LinkedNodeWithCursor) # cursor doesn't increase rc, cannot form a cycle type ObjectWithoutCycles = object @@ -121,3 +118,18 @@ block: proc `=trace`(x: var myseq[Node]; env: pointer) = discard cyclicYes(Node) + +block: + type + Foo = object + id: ptr ref Foo + + cyclicNo(Foo) + +block: + type + InheritableObj = object of RootObj + InheritableRef = ref object of RootObj + + cyclicYes(InheritableObj) + cyclicYes(InheritableRef) |