diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-10-01 15:04:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-01 15:04:36 +0200 |
commit | ab405c936e77a875199aa1ee0f99eddd3d5a0c10 (patch) | |
tree | 5fb692102a125746bb4a05f767cfa7e16b6d54e3 /compiler | |
parent | 79a92da8efdb895ba5762ca9ed0471a3a5846068 (diff) | |
download | Nim-ab405c936e77a875199aa1ee0f99eddd3d5a0c10.tar.gz |
views: yet another bugfix (#15447)
* views: yet another bugfix * views: extended the spec * views: take into account potential hidden mutations via proc calls
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semtempl.nim | 5 | ||||
-rw-r--r-- | compiler/trees.nim | 5 | ||||
-rw-r--r-- | compiler/varpartitions.nim | 26 |
3 files changed, 27 insertions, 9 deletions
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 1ec8c07b0..df832c814 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -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: diff --git a/compiler/trees.nim b/compiler/trees.nim index c5c1a0d75..473264b52 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -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 diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index b416aa41d..e59c5cb75 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -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]) |