summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2020-09-20 09:01:42 +0200
committerAndreas Rumpf <rumpf_a@web.de>2020-09-20 10:43:57 +0200
commit33be7c6f5ef1a9e54d037682984f563c8ee11fcb (patch)
treef147553dd982de0313be33bba8ce2d24429ccfa4
parentebb632ccba0d786b90684e4da2b393cfae04a24c (diff)
downloadNim-33be7c6f5ef1a9e54d037682984f563c8ee11fcb.tar.gz
arc: =deepcopy fixes
-rw-r--r--compiler/varpartitions.nim1
-rw-r--r--lib/system/deepcopy.nim19
-rw-r--r--tests/arc/tdeepcopy.nim67
3 files changed, 81 insertions, 6 deletions
diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim
index 743c4d55d..f983f9416 100644
--- a/compiler/varpartitions.nim
+++ b/compiler/varpartitions.nim
@@ -459,7 +459,6 @@ proc traverse(c: var Partitions; n: PNode) =
           if paramType.kind == tyVar:
             if c.inNoSideEffectSection == 0:
               for r in roots: potentialMutation(c, r, it.info)
-          else:
             for r in roots: noCursor(c, r)
 
   of nkAddr, nkHiddenAddr:
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index 5905b5785..b9dc594fa 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -140,7 +140,10 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
       unsureAsgnRef(cast[PPointer](dest), s2)
     elif mt.base.deepcopy != nil:
       let z = mt.base.deepcopy(s2)
-      unsureAsgnRef(cast[PPointer](dest), z)
+      when defined(nimSeqsV2):
+        cast[PPointer](dest)[] = z
+      else:
+        unsureAsgnRef(cast[PPointer](dest), z)
     else:
       let z = tab.get(s2)
       if z == nil:
@@ -157,10 +160,16 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
             let x = usrToCell(s2)
             let realType = x.typ
             sysAssert realType == mt, " types do differ"
-          # this version should work for any possible GC:
-          let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
-          let z = when defined(nimSeqsV2): nimNewObj(typ.size) else: newObj(mt, typ.size)
-          unsureAsgnRef(cast[PPointer](dest), z)
+          when defined(nimSeqsV2):
+            let typ = if mt.base.kind == tyObject: cast[PNimType](cast[ptr PNimTypeV2](s2)[].typeInfoV1)
+                      else: mt.base
+            let z = nimNewObj(typ.size)
+            cast[PPointer](dest)[] = z
+          else:
+            # this version should work for any other GC:
+            let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
+            let z = newObj(mt, typ.size)
+            unsureAsgnRef(cast[PPointer](dest), z)
           tab.put(s2, z)
           genericDeepCopyAux(z, s2, typ, tab)
       else:
diff --git a/tests/arc/tdeepcopy.nim b/tests/arc/tdeepcopy.nim
new file mode 100644
index 000000000..0eaf7ea40
--- /dev/null
+++ b/tests/arc/tdeepcopy.nim
@@ -0,0 +1,67 @@
+discard """
+  cmd: "nim c --gc:arc $file"
+  output: '''13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+13 abc
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+called deepCopy for int
+0'''
+"""
+
+type
+  PBinaryTree = ref object of RootObj
+    le, ri: PBinaryTree
+    value: int
+
+proc mainB =
+  var x: PBinaryTree
+  deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13))))
+
+  var y: string
+  deepCopy y, "abc"
+  echo x.ri.le.value, " ", y
+
+for i in 0..10:
+  mainB()
+
+
+type
+  Bar[T] = object
+    x: T
+
+proc `=deepCopy`[T](b: ref Bar[T]): ref Bar[T] =
+  result.new
+  result.x = b.x
+  when T is int:
+    echo "called deepCopy for int"
+  else:
+    echo "called deepCopy for something else"
+
+proc main =
+  var dummy, c: ref Bar[int]
+  new(dummy)
+  dummy.x = 44
+
+  deepCopy c, dummy
+
+for i in 0..10:
+  main()
+
+echo getOccupiedMem()