Skip to content

Commit

Permalink
fixes #19013 [backport:1.6] (#19111)
Browse files Browse the repository at this point in the history
* fixes #19013 [backport:1.6]

* added test case
  • Loading branch information
Araq authored Nov 9, 2021
1 parent 83a9c3b commit b7c66ce
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 8 deletions.
8 changes: 8 additions & 0 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2101,3 +2101,11 @@ proc skipAddr*(n: PNode): PNode {.inline.} =
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
assert n.kind == nkTypeClassTy
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}
17 changes: 16 additions & 1 deletion compiler/isolation_check.nim
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ proc canAlias*(arg, ret: PType): bool =
var marker = initIntSet()
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 =
if types.containsTyRef(n.typ):
# XXX Maybe require that 'n.typ' is acyclic. This is not much
Expand All @@ -96,7 +107,11 @@ proc checkIsolate*(n: PNode): bool =
else:
let argType = n[i].typ
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
result = true
of nkIfStmt, nkIfExpr:
Expand Down
7 changes: 0 additions & 7 deletions compiler/varpartitions.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
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) =
if constParameters in c.goals and tfNoSideEffect in callee.flags:
Expand Down
22 changes: 22 additions & 0 deletions tests/isolate/tisolate2.nim
Original file line number Diff line number Diff line change
@@ -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))

0 comments on commit b7c66ce

Please sign in to comment.