parent
ccd77b42af
commit
217675cf84
3 changed files with 39 additions and 5 deletions
|
|
@ -57,7 +57,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||||
of tyVar, tyLent:
|
of tyVar, tyLent:
|
||||||
if kind in {skProc, skFunc, skConst} and (views notin c.features):
|
if kind in {skProc, skFunc, skConst} and (views notin c.features):
|
||||||
result = t
|
result = t
|
||||||
elif t.kind == tyLent and kind != skResult:
|
elif t.kind == tyLent and kind != skResult and (views notin c.features):
|
||||||
result = t
|
result = t
|
||||||
else:
|
else:
|
||||||
var t2 = skipTypes(t[0], abstractInst-{tyTypeDesc})
|
var t2 = skipTypes(t[0], abstractInst-{tyTypeDesc})
|
||||||
|
|
@ -68,10 +68,10 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||||
if (kind != skParam and views notin c.features) or taIsOpenArray in flags: result = t
|
if (kind != skParam and views notin c.features) or taIsOpenArray in flags: result = t
|
||||||
else: result = typeAllowedAux(marker, t2[0], kind, c, flags+{taIsOpenArray})
|
else: result = typeAllowedAux(marker, t2[0], kind, c, flags+{taIsOpenArray})
|
||||||
of tyUncheckedArray:
|
of tyUncheckedArray:
|
||||||
if kind != skParam: result = t
|
if kind != skParam and views notin c.features: result = t
|
||||||
else: result = typeAllowedAux(marker, t2[0], kind, c, flags)
|
else: result = typeAllowedAux(marker, t2[0], kind, c, flags)
|
||||||
else:
|
else:
|
||||||
if kind notin {skParam, skResult}: result = t
|
if kind notin {skParam, skResult} and views notin c.features: result = t
|
||||||
else: result = typeAllowedAux(marker, t2, kind, c, flags)
|
else: result = typeAllowedAux(marker, t2, kind, c, flags)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if kind in {skVar, skLet, skConst} and taIsTemplateOrMacro in flags:
|
if kind in {skVar, skLet, skConst} and taIsTemplateOrMacro in flags:
|
||||||
|
|
|
||||||
|
|
@ -375,7 +375,7 @@ proc deps(c: var Partitions; dest, src: PNode) =
|
||||||
allRoots(src, sources)
|
allRoots(src, sources)
|
||||||
|
|
||||||
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
|
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr}
|
||||||
let destIsComplex = types.searchTypeFor(dest.typ, wrap)
|
let destIsComplex = types.searchTypeFor(dest.typ, wrap) or isViewType(dest.typ)
|
||||||
|
|
||||||
for t in targets:
|
for t in targets:
|
||||||
if dest.kind != nkSym and c.inNoSideEffectSection == 0:
|
if dest.kind != nkSym and c.inNoSideEffectSection == 0:
|
||||||
|
|
@ -518,19 +518,35 @@ proc computeGraphPartitions*(s: PSym; n: PNode; cursorInference = false): Partit
|
||||||
traverse(result, n)
|
traverse(result, n)
|
||||||
|
|
||||||
proc dangerousMutation(g: MutationInfo; v: VarIndex): bool =
|
proc dangerousMutation(g: MutationInfo; v: VarIndex): bool =
|
||||||
|
#echo "range ", v.aliveStart, " .. ", v.aliveEnd
|
||||||
if isMutated in g.flags:
|
if isMutated in g.flags:
|
||||||
for m in g.mutations:
|
for m in g.mutations:
|
||||||
|
#echo "mutation ", m
|
||||||
if m in v.aliveStart..v.aliveEnd:
|
if m in v.aliveStart..v.aliveEnd:
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
proc cannotBorrow(config: ConfigRef; s: PSym; g: MutationInfo) =
|
||||||
|
var m = "cannot borrow " & s.name.s &
|
||||||
|
"; what it borrows from is potentially mutated"
|
||||||
|
|
||||||
|
if g.mutatedHere != unknownLineInfo:
|
||||||
|
m.add "\n"
|
||||||
|
m.add config $ g.mutatedHere
|
||||||
|
m.add " the mutation is here"
|
||||||
|
if g.connectedVia != unknownLineInfo:
|
||||||
|
m.add "\n"
|
||||||
|
m.add config $ g.connectedVia
|
||||||
|
m.add " is the statement that connected the mutation to the parameter"
|
||||||
|
localError(config, s.info, m)
|
||||||
|
|
||||||
proc checkBorrowedLocations*(par: var Partitions; config: ConfigRef) =
|
proc checkBorrowedLocations*(par: var Partitions; config: ConfigRef) =
|
||||||
for i in 0 ..< par.s.len:
|
for i in 0 ..< par.s.len:
|
||||||
let s = par.s[i].sym
|
let s = par.s[i].sym
|
||||||
if s.kind != skParam and isViewType(s.typ):
|
if s.kind != skParam and isViewType(s.typ):
|
||||||
let rid = root(par, i)
|
let rid = root(par, i)
|
||||||
if par.s[rid].kind == isRootOf and dangerousMutation(par.graphs[par.s[rid].graphIndex], par.s[i]):
|
if par.s[rid].kind == isRootOf and dangerousMutation(par.graphs[par.s[rid].graphIndex], par.s[i]):
|
||||||
localError(config, s.info, config $ par.graphs[par.s[rid].graphIndex])
|
cannotBorrow(config, s, par.graphs[par.s[rid].graphIndex])
|
||||||
|
|
||||||
proc computeCursors*(s: PSym; n: PNode; config: ConfigRef) =
|
proc computeCursors*(s: PSym; n: PNode; config: ConfigRef) =
|
||||||
var par = computeGraphPartitions(s, n, true)
|
var par = computeGraphPartitions(s, n, true)
|
||||||
|
|
|
||||||
18
tests/effects/tcannot_borrow.nim
Normal file
18
tests/effects/tcannot_borrow.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "cannot borrow"
|
||||||
|
nimout: '''tcannot_borrow.nim(16, 7) Error: cannot borrow meh; what it borrows from is potentially mutated
|
||||||
|
tcannot_borrow.nim(17, 3) the mutation is here
|
||||||
|
tcannot_borrow.nim(16, 7) is the statement that connected the mutation to the parameter'''
|
||||||
|
line: 16
|
||||||
|
"""
|
||||||
|
|
||||||
|
{.experimental: "views".}
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = object
|
||||||
|
field: string
|
||||||
|
|
||||||
|
proc dangerous(s: var seq[Foo]) =
|
||||||
|
let meh: lent Foo = s[0]
|
||||||
|
s.setLen 0
|
||||||
|
echo meh.field
|
||||||
Loading…
Add table
Add a link
Reference in a new issue