fixes #7637; assignments are not allowed to slice object; minor breaking change
This commit is contained in:
parent
14046d975d
commit
85ea9593b3
5 changed files with 46 additions and 15 deletions
|
|
@ -11,6 +11,10 @@
|
||||||
to deal with!
|
to deal with!
|
||||||
- Indexing into a ``cstring`` for the JS target is now mapped
|
- Indexing into a ``cstring`` for the JS target is now mapped
|
||||||
to ``charCodeAt``.
|
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
|
#### Breaking changes in the standard library
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,12 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
GenericSeqSize),
|
GenericSeqSize),
|
||||||
mt.base, shallow)
|
mt.base, shallow)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
if mt.base != nil:
|
var it = mt.base
|
||||||
genericAssignAux(dest, src, mt.base, shallow)
|
# 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)
|
genericAssignAux(dest, src, mt.node, shallow)
|
||||||
# we need to copy m_type field for tyObject, as it could be empty for
|
# we need to copy m_type field for tyObject, as it could be empty for
|
||||||
# sequence reallocations:
|
# sequence reallocations:
|
||||||
|
|
@ -89,6 +93,8 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||||
# if p of TB:
|
# if p of TB:
|
||||||
# var tbObj = TB(p)
|
# var tbObj = TB(p)
|
||||||
# tbObj of TC # needs to be false!
|
# 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)[]
|
pint[] = mt # cast[ptr PNimType](src)[]
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
genericAssignAux(dest, src, mt.node, shallow)
|
genericAssignAux(dest, src, mt.node, shallow)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''tbObj of TC false
|
output: '''tbObj of TC true
|
||||||
false
|
|
||||||
true
|
true
|
||||||
5
|
5'''
|
||||||
false'''
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# bug #1053
|
# bug #1053
|
||||||
|
|
@ -20,10 +18,10 @@ type
|
||||||
proc test(p: TA) =
|
proc test(p: TA) =
|
||||||
#echo "p of TB ", p of TB
|
#echo "p of TB ", p of TB
|
||||||
if p of TB:
|
if p of TB:
|
||||||
var tbObj = TB(p)
|
#var tbObj = TB(p)
|
||||||
|
|
||||||
# tbObj is actually no longer compatible with TC:
|
# 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()
|
var v = TC()
|
||||||
v.a = 1
|
v.a = 1
|
||||||
|
|
@ -48,8 +46,8 @@ proc isMyObject(obj: TObject) =
|
||||||
|
|
||||||
asd.x = 5
|
asd.x = 5
|
||||||
|
|
||||||
var asdCopy = TObject(asd)
|
#var asdCopy = TObject(asd)
|
||||||
echo asdCopy of MyObject
|
#echo asdCopy of MyObject
|
||||||
|
|
||||||
isMyObject(asd)
|
isMyObject(asd)
|
||||||
isMyObject(asdCopy)
|
#isMyObject(asdCopy)
|
||||||
|
|
|
||||||
24
tests/objects/tobj_asgn_dont_slice.nim
Normal file
24
tests/objects/tobj_asgn_dont_slice.nim
Normal file
|
|
@ -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])
|
||||||
|
|
@ -9,8 +9,8 @@ discard """
|
||||||
(k: kindA, a: (x: "abc", z: [1, 8, 3]), method: ())
|
(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, 9, 3]), method: ())
|
||||||
(k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ())
|
(k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ())
|
||||||
(x: 123)
|
(y: 0, x: 123)
|
||||||
(x: 123)
|
(y: 678, x: 123)
|
||||||
(z: 89, y: 0, x: 128)
|
(z: 89, y: 0, x: 128)
|
||||||
(y: 678, x: 123)
|
(y: 678, x: 123)
|
||||||
(y: 678, x: 123)
|
(y: 678, x: 123)
|
||||||
|
|
@ -33,7 +33,6 @@ type
|
||||||
`method`: TEmpty # bug #1791
|
`method`: TEmpty # bug #1791
|
||||||
|
|
||||||
proc `$`[T](s: seq[T]): string =
|
proc `$`[T](s: seq[T]): string =
|
||||||
# XXX why is that not in the stdlib?
|
|
||||||
result = "["
|
result = "["
|
||||||
for i, x in s:
|
for i, x in s:
|
||||||
if i > 0: result.add(", ")
|
if i > 0: result.add(", ")
|
||||||
|
|
@ -59,7 +58,7 @@ type
|
||||||
# inherited fields are ignored, so no fields are set
|
# inherited fields are ignored, so no fields are set
|
||||||
when true:
|
when true:
|
||||||
var
|
var
|
||||||
o: A
|
o: B
|
||||||
o = B(x: 123)
|
o = B(x: 123)
|
||||||
echo o
|
echo o
|
||||||
o = B(y: 678, x: 123)
|
o = B(y: 678, x: 123)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue