summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/types.nim21
-rw-r--r--tests/types/tcyclic.nim20
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)