summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md4
-rw-r--r--lib/system/assign.nim10
-rw-r--r--tests/objects/tinherentedvalues.nim16
-rw-r--r--tests/objects/tobj_asgn_dont_slice.nim24
-rw-r--r--tests/objects/tobjconstr.nim7
5 files changed, 46 insertions, 15 deletions
diff --git a/changelog.md b/changelog.md
index e6d1f6b47..a3332789a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -11,6 +11,10 @@
   to deal with!
 - Indexing into a ``cstring`` for the JS target is now mapped
   to ``charCodeAt``.
+- Assignments that would "slice" an object into its supertype are not prevented
+  at runtime. Use ``ref object`` with inheritance rather than ``object`` with
+  inheritance to prevent this issue.
+
 
 #### Breaking changes in the standard library
 
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index f061c89cf..ff1ef31d2 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -79,8 +79,12 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
                       GenericSeqSize),
           mt.base, shallow)
   of tyObject:
-    if mt.base != nil:
-      genericAssignAux(dest, src, mt.base, shallow)
+    var it = mt.base
+    # don't use recursion here on the PNimType because the subtype
+    # check should only be done at the very end:
+    while it != nil:
+      genericAssignAux(dest, src, it.node, shallow)
+      it = it.base
     genericAssignAux(dest, src, mt.node, shallow)
     # we need to copy m_type field for tyObject, as it could be empty for
     # sequence reallocations:
@@ -89,6 +93,8 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
     #   if p of TB:
     #     var tbObj = TB(p)
     #     tbObj of TC # needs to be false!
+    #c_fprintf(stdout, "%s %s\n", pint[].name, mt.name)
+    chckObjAsgn(cast[ptr PNimType](src)[], mt)
     pint[] = mt # cast[ptr PNimType](src)[]
   of tyTuple:
     genericAssignAux(dest, src, mt.node, shallow)
diff --git a/tests/objects/tinherentedvalues.nim b/tests/objects/tinherentedvalues.nim
index c96a0fd6d..ad7b5f326 100644
--- a/tests/objects/tinherentedvalues.nim
+++ b/tests/objects/tinherentedvalues.nim
@@ -1,9 +1,7 @@
 discard """
-  output: '''tbObj of TC false
-false
+  output: '''tbObj of TC true
 true
-5
-false'''
+5'''
 """
 
 # bug #1053
@@ -20,10 +18,10 @@ type
 proc test(p: TA) =
   #echo "p of TB ", p of TB
   if p of TB:
-    var tbObj = TB(p)
+    #var tbObj = TB(p)
 
     # tbObj is actually no longer compatible with TC:
-    echo "tbObj of TC ", tbObj of TC
+    echo "tbObj of TC ", p of TC
 
 var v = TC()
 v.a = 1
@@ -48,8 +46,8 @@ proc isMyObject(obj: TObject) =
 
 asd.x = 5
 
-var asdCopy = TObject(asd)
-echo asdCopy of MyObject
+#var asdCopy = TObject(asd)
+#echo asdCopy of MyObject
 
 isMyObject(asd)
-isMyObject(asdCopy)
+#isMyObject(asdCopy)
diff --git a/tests/objects/tobj_asgn_dont_slice.nim b/tests/objects/tobj_asgn_dont_slice.nim
new file mode 100644
index 000000000..866b5aecc
--- /dev/null
+++ b/tests/objects/tobj_asgn_dont_slice.nim
@@ -0,0 +1,24 @@
+discard """
+  outputsub: '''ObjectAssignmentError'''
+  exitcode: "1"
+"""
+
+# bug #7637
+type
+  Fruit = object of RootObj
+    name*: string
+  Apple = object of Fruit
+  Pear = object of Fruit
+
+method eat(f: Fruit) {.base.} =
+  raise newException(Exception, "PURE VIRTUAL CALL")
+
+method eat(f: Apple) =
+  echo "fruity"
+
+method eat(f: Pear) =
+  echo "juicy"
+
+let basket = [Apple(name:"a"), Pear(name:"b")]
+
+eat(basket[0])
diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim
index d1f3c8bdb..7238d10c7 100644
--- a/tests/objects/tobjconstr.nim
+++ b/tests/objects/tobjconstr.nim
@@ -9,8 +9,8 @@ discard """
 (k: kindA, a: (x: "abc", z: [1, 8, 3]), method: ())
 (k: kindA, a: (x: "abc", z: [1, 9, 3]), method: ())
 (k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ())
-(x: 123)
-(x: 123)
+(y: 0, x: 123)
+(y: 678, x: 123)
 (z: 89, y: 0, x: 128)
 (y: 678, x: 123)
 (y: 678, x: 123)
@@ -33,7 +33,6 @@ type
       `method`: TEmpty # bug #1791
 
 proc `$`[T](s: seq[T]): string =
-  # XXX why is that not in the stdlib?
   result = "["
   for i, x in s:
     if i > 0: result.add(", ")
@@ -59,7 +58,7 @@ type
 # inherited fields are ignored, so no fields are set
 when true:
   var
-    o: A
+    o: B
   o = B(x: 123)
   echo o
   o = B(y: 678, x: 123)