fixes #19986; mutable view from immutable location (#20134)

* fixes #19986; mutable view from immutable location

* fixes the tests
This commit is contained in:
ringabout
2022-09-28 20:02:07 +08:00
committed by GitHub
parent 18cea8e9bd
commit fdc6b0fb6e
2 changed files with 66 additions and 15 deletions

View File

@@ -580,24 +580,33 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
if dest.kind == nkSym:
if directViewType(dest.typ) != noView:
borrowFrom(c, dest.sym, src)
elif dest.kind in {nkHiddenDeref, nkDerefExpr, nkBracketExpr}:
case directViewType(dest[0].typ)
of mutableView, immutableView:
# we do not borrow, but we use the view to mutate the borrowed
# location:
let viewOrigin = pathExpr(dest, c.owner)
if viewOrigin.kind == nkSym:
let vid = variableId(c, viewOrigin.sym)
else:
let viewOrigin = pathExpr(dest, c.owner)
if viewOrigin != nil and viewOrigin.kind == nkSym:
let viewSym = viewOrigin.sym
let directView = directViewType(dest[0].typ) # check something like result[first] = toOpenArray(s, first, last-1)
# so we don't need to iterate the original type
let originSymbolView = directViewType(viewSym.typ) # find the original symbol which preserves the view type
# 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:
c.s[vid].flags.incl viewDoesMutate
#[of immutableView:
if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and
mutableParameter(dest[0][0]):
discard "remains a mutable location anyhow"
#[of immutableView:
if dest.kind == nkBracketExpr and dest[0].kind == nkHiddenDeref and
mutableParameter(dest[0][0]):
discard "remains a mutable location anyhow"
else:
localError(c.g.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
]#
else:
localError(c.g.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
]#
of noView: discard "nothing to do"
discard "nothing to do"
proc containsPointer(t: PType): bool =
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}

42
tests/views/t19986.nim Normal file
View 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()