* fixes #19986; mutable view from immutable location * fixes the tests
This commit is contained in:
parent
18cea8e9bd
commit
fdc6b0fb6e
2 changed files with 66 additions and 15 deletions
|
|
@ -580,24 +580,33 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
|
||||||
if dest.kind == nkSym:
|
if dest.kind == nkSym:
|
||||||
if directViewType(dest.typ) != noView:
|
if directViewType(dest.typ) != noView:
|
||||||
borrowFrom(c, dest.sym, src)
|
borrowFrom(c, dest.sym, src)
|
||||||
elif dest.kind in {nkHiddenDeref, nkDerefExpr, nkBracketExpr}:
|
else:
|
||||||
case directViewType(dest[0].typ)
|
let viewOrigin = pathExpr(dest, c.owner)
|
||||||
of mutableView, immutableView:
|
if viewOrigin != nil and viewOrigin.kind == nkSym:
|
||||||
# we do not borrow, but we use the view to mutate the borrowed
|
let viewSym = viewOrigin.sym
|
||||||
# location:
|
let directView = directViewType(dest[0].typ) # check something like result[first] = toOpenArray(s, first, last-1)
|
||||||
let viewOrigin = pathExpr(dest, c.owner)
|
# so we don't need to iterate the original type
|
||||||
if viewOrigin.kind == nkSym:
|
let originSymbolView = directViewType(viewSym.typ) # find the original symbol which preserves the view type
|
||||||
let vid = variableId(c, viewOrigin.sym)
|
# var foo: var Object = a
|
||||||
|
# foo.id = 777 # the type of foo is no view, so we need
|
||||||
|
# to check the original symbol
|
||||||
|
let viewSets = {directView, originSymbolView}
|
||||||
|
|
||||||
|
if viewSets * {mutableView, immutableView} != {}:
|
||||||
|
# we do not borrow, but we use the view to mutate the borrowed
|
||||||
|
# location:
|
||||||
|
let vid = variableId(c, viewSym)
|
||||||
if vid >= 0:
|
if vid >= 0:
|
||||||
c.s[vid].flags.incl viewDoesMutate
|
c.s[vid].flags.incl viewDoesMutate
|
||||||
#[of immutableView:
|
#[of immutableView:
|
||||||
if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and
|
if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and
|
||||||
mutableParameter(dest[0][0]):
|
mutableParameter(dest[0][0]):
|
||||||
discard "remains a mutable location anyhow"
|
discard "remains a mutable location anyhow"
|
||||||
|
else:
|
||||||
|
localError(c.g.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
|
||||||
|
]#
|
||||||
else:
|
else:
|
||||||
localError(c.g.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
|
discard "nothing to do"
|
||||||
]#
|
|
||||||
of noView: discard "nothing to do"
|
|
||||||
|
|
||||||
proc containsPointer(t: PType): bool =
|
proc containsPointer(t: PType): bool =
|
||||||
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
|
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
|
||||||
|
|
|
||||||
42
tests/views/t19986.nim
Normal file
42
tests/views/t19986.nim
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim check --hints:off $file'''
|
||||||
|
action: reject
|
||||||
|
nimout: '''
|
||||||
|
t19986.nim(19, 7) Error: 'foo' borrows from the immutable location 'a' and attempts to mutate it
|
||||||
|
t19986.nim(28, 7) Error: 'foo' borrows from the immutable location 'a' and attempts to mutate it
|
||||||
|
t19986.nim(37, 7) Error: 'foo' borrows from the immutable location 'a' and attempts to mutate it
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
{.experimental: "views".}
|
||||||
|
|
||||||
|
type
|
||||||
|
Object = object
|
||||||
|
id: int
|
||||||
|
|
||||||
|
proc foo() =
|
||||||
|
let a = Object(id: 3)
|
||||||
|
var foo: var Object = a
|
||||||
|
|
||||||
|
foo.id = 777
|
||||||
|
echo a
|
||||||
|
|
||||||
|
foo()
|
||||||
|
|
||||||
|
proc bar() =
|
||||||
|
let a = "123"
|
||||||
|
var foo: var string = a
|
||||||
|
|
||||||
|
foo[0] = '7'
|
||||||
|
echo a
|
||||||
|
|
||||||
|
bar()
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
let a = 3
|
||||||
|
var foo: var int = a
|
||||||
|
|
||||||
|
foo = 777
|
||||||
|
echo a
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue