views: yet another bugfix (#15447)

* views: yet another bugfix

* views: extended the spec

* views: take into account potential hidden mutations via proc calls
This commit is contained in:
Andreas Rumpf
2020-10-01 15:04:36 +02:00
committed by GitHub
parent 79a92da8ef
commit ab405c936e
5 changed files with 44 additions and 10 deletions

View File

@@ -707,11 +707,6 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
localError(c.c.config, n.info, "invalid expression")
result = n
proc stupidStmtListExpr(n: PNode): bool =
for i in 0..<n.len-1:
if n[i].kind notin {nkEmpty, nkCommentStmt}: return false
result = true
result = n
case n.kind
of nkIdent:

View File

@@ -190,3 +190,8 @@ proc getRoot*(n: PNode): PSym =
of nkCallKinds:
if getMagic(n) == mSlice: result = getRoot(n[1])
else: discard
proc stupidStmtListExpr*(n: PNode): bool =
for i in 0..<n.len-1:
if n[i].kind notin {nkEmpty, nkCommentStmt}: return false
result = true

View File

@@ -29,7 +29,7 @@
## for a high-level description of how borrow checking works.
import ast, types, lineinfos, options, msgs, renderer, typeallowed
from trees import getMagic, whichPragma
from trees import getMagic, whichPragma, stupidStmtListExpr
from wordrecg import wNoSideEffect
from isolation_check import canAlias
@@ -309,6 +309,11 @@ proc pathExpr(node: PNode; owner: PSym): PNode =
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast,
nkObjUpConv, nkObjDownConv:
n = n.lastSon
of nkStmtList, nkStmtListExpr:
if n.len > 0 and stupidStmtListExpr(n):
n = n.lastSon
else:
break
of nkCallKinds:
if n.len > 1:
if (n.typ != nil and classifyViewType(n.typ) != noView) or getMagic(n) == mSlice:
@@ -551,6 +556,10 @@ proc borrowingAsgn(c: var Partitions; dest, src: PNode) =
localError(c.config, dest.info, "attempt to mutate a borrowed location from an immutable view")
of noView: discard "nothing to do"
proc containsPointer(t: PType): bool =
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
result = types.searchTypeFor(t, wrap)
proc deps(c: var Partitions; dest, src: PNode) =
if borrowChecking in c.goals:
borrowingAsgn(c, dest, src)
@@ -559,9 +568,7 @@ proc deps(c: var Partitions; dest, src: PNode) =
allRoots(dest, targets)
allRoots(src, sources)
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
let destIsComplex = types.searchTypeFor(dest.typ, wrap)
let destIsComplex = containsPointer(dest.typ)
for t in targets:
if dest.kind != nkSym and c.inNoSideEffectSection == 0:
@@ -607,6 +614,14 @@ const
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr}
proc potentialMutationViaArg(c: var Partitions; n: PNode; callee: PType) =
if constParameters in c.goals and tfNoSideEffect in callee.flags:
discard "we know there are no hidden mutations through an immutable parameter"
elif c.inNoSideEffectSection == 0 and containsPointer(n.typ):
var roots: seq[PSym]
allRoots(n, roots)
for r in roots: potentialMutation(c, r, n.info)
proc traverse(c: var Partitions; n: PNode) =
inc c.abstractTime
case n.kind
@@ -640,6 +655,7 @@ proc traverse(c: var Partitions; n: PNode) =
let parameters = n[0].typ
let L = if parameters != nil: parameters.len else: 0
let m = getMagic(n)
for i in 1..<n.len:
let it = n[i]
@@ -659,6 +675,8 @@ proc traverse(c: var Partitions; n: PNode) =
# 'paramType[0]' is still a view type, this is not a typo!
if directViewType(paramType[0]) == noView and classifyViewType(paramType[0]) != noView:
borrowingCall(c, paramType[0], n, i)
elif borrowChecking in c.goals and m == mNone:
potentialMutationViaArg(c, n[i], parameters)
of nkAddr, nkHiddenAddr:
traverse(c, n[0])

View File

@@ -1988,6 +1988,22 @@ borrow operation of ``v`` even though a human being can easily see that it
will never do that at runtime.
Start of a borrow
-----------------
A borrow starts with one of the following:
- The assignment of a non-view-type to a view-type.
- The assingment of a location that is derived from a local parameter
to a view-type.
End of a borrow
---------------
A borrow operation ends with the last usage of the view variable.
Reborrows
---------

View File

@@ -1,5 +1,5 @@
discard """
cmd: "nim c --experimental:strictFuncs $file"
cmd: "nim c --experimental:strictFuncs --experimental:views $file"
"""
import tables, streams, nre, parsecsv