mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-09 13:18:11 +00:00
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:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
---------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
cmd: "nim c --experimental:strictFuncs $file"
|
||||
cmd: "nim c --experimental:strictFuncs --experimental:views $file"
|
||||
"""
|
||||
|
||||
import tables, streams, nre, parsecsv
|
||||
|
||||
Reference in New Issue
Block a user