* fixes #19013 [backport:1.6] * added test case
This commit is contained in:
parent
83a9c3ba31
commit
b7c66ce860
4 changed files with 46 additions and 8 deletions
|
|
@ -2101,3 +2101,11 @@ proc skipAddr*(n: PNode): PNode {.inline.} =
|
||||||
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
|
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
|
||||||
assert n.kind == nkTypeClassTy
|
assert n.kind == nkTypeClassTy
|
||||||
result = n[0].kind == nkEmpty
|
result = n[0].kind == nkEmpty
|
||||||
|
|
||||||
|
const
|
||||||
|
nodesToIgnoreSet* = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||||
|
nkTypeSection, nkProcDef, nkConverterDef,
|
||||||
|
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||||
|
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||||
|
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||||
|
nkTypeOfExpr, nkMixinStmt, nkBindStmt}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,17 @@ proc canAlias*(arg, ret: PType): bool =
|
||||||
var marker = initIntSet()
|
var marker = initIntSet()
|
||||||
result = canAlias(arg, ret, marker)
|
result = canAlias(arg, ret, marker)
|
||||||
|
|
||||||
|
proc containsVariable(n: PNode): bool =
|
||||||
|
case n.kind
|
||||||
|
of nodesToIgnoreSet:
|
||||||
|
result = false
|
||||||
|
of nkSym:
|
||||||
|
result = n.sym.kind in {skForVar, skParam, skVar, skLet, skConst, skResult, skTemp}
|
||||||
|
else:
|
||||||
|
for ch in n:
|
||||||
|
if containsVariable(ch): return true
|
||||||
|
result = false
|
||||||
|
|
||||||
proc checkIsolate*(n: PNode): bool =
|
proc checkIsolate*(n: PNode): bool =
|
||||||
if types.containsTyRef(n.typ):
|
if types.containsTyRef(n.typ):
|
||||||
# XXX Maybe require that 'n.typ' is acyclic. This is not much
|
# XXX Maybe require that 'n.typ' is acyclic. This is not much
|
||||||
|
|
@ -96,7 +107,11 @@ proc checkIsolate*(n: PNode): bool =
|
||||||
else:
|
else:
|
||||||
let argType = n[i].typ
|
let argType = n[i].typ
|
||||||
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
|
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
|
||||||
if argType.canAlias(n.typ):
|
if argType.canAlias(n.typ) or containsVariable(n[i]):
|
||||||
|
# bug #19013: Alias information is not enough, we need to check for potential
|
||||||
|
# "overlaps". I claim the problem can only happen by reading again from a location
|
||||||
|
# that materialized which is only possible if a variable that contains a `ref`
|
||||||
|
# is involved.
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
of nkIfStmt, nkIfExpr:
|
of nkIfStmt, nkIfExpr:
|
||||||
|
|
|
||||||
|
|
@ -647,13 +647,6 @@ proc deps(c: var Partitions; dest, src: PNode) =
|
||||||
when explainCursors: echo "D not a cursor ", d.sym, " reassignedTo ", c.s[srcid].reassignedTo
|
when explainCursors: echo "D not a cursor ", d.sym, " reassignedTo ", c.s[srcid].reassignedTo
|
||||||
c.s[vid].flags.incl preventCursor
|
c.s[vid].flags.incl preventCursor
|
||||||
|
|
||||||
const
|
|
||||||
nodesToIgnoreSet = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
|
|
||||||
nkTypeSection, nkProcDef, nkConverterDef,
|
|
||||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
|
||||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
|
||||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
|
||||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt}
|
|
||||||
|
|
||||||
proc potentialMutationViaArg(c: var Partitions; n: PNode; callee: PType) =
|
proc potentialMutationViaArg(c: var Partitions; n: PNode; callee: PType) =
|
||||||
if constParameters in c.goals and tfNoSideEffect in callee.flags:
|
if constParameters in c.goals and tfNoSideEffect in callee.flags:
|
||||||
|
|
|
||||||
22
tests/isolate/tisolate2.nim
Normal file
22
tests/isolate/tisolate2.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "expression cannot be isolated: a_to_b(a)"
|
||||||
|
line: 22
|
||||||
|
"""
|
||||||
|
|
||||||
|
# bug #19013
|
||||||
|
import std/isolation
|
||||||
|
|
||||||
|
type Z = ref object
|
||||||
|
i: int
|
||||||
|
|
||||||
|
type A = object
|
||||||
|
z: Z
|
||||||
|
|
||||||
|
type B = object
|
||||||
|
z: Z
|
||||||
|
|
||||||
|
func a_to_b(a: A): B =
|
||||||
|
result = B(z: a.z)
|
||||||
|
|
||||||
|
let a = A(z: Z(i: 3))
|
||||||
|
let b = isolate(a_to_b(a))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue