Skip to content

Commit b7c66ce

Browse files
authored
fixes #19013 [backport:1.6] (#19111)
* fixes #19013 [backport:1.6] * added test case
1 parent 83a9c3b commit b7c66ce

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed

compiler/ast.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,3 +2101,11 @@ proc skipAddr*(n: PNode): PNode {.inline.} =
21012101
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
21022102
assert n.kind == nkTypeClassTy
21032103
result = n[0].kind == nkEmpty
2104+
2105+
const
2106+
nodesToIgnoreSet* = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
2107+
nkTypeSection, nkProcDef, nkConverterDef,
2108+
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
2109+
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
2110+
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
2111+
nkTypeOfExpr, nkMixinStmt, nkBindStmt}

compiler/isolation_check.nim

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ proc canAlias*(arg, ret: PType): bool =
7777
var marker = initIntSet()
7878
result = canAlias(arg, ret, marker)
7979

80+
proc containsVariable(n: PNode): bool =
81+
case n.kind
82+
of nodesToIgnoreSet:
83+
result = false
84+
of nkSym:
85+
result = n.sym.kind in {skForVar, skParam, skVar, skLet, skConst, skResult, skTemp}
86+
else:
87+
for ch in n:
88+
if containsVariable(ch): return true
89+
result = false
90+
8091
proc checkIsolate*(n: PNode): bool =
8192
if types.containsTyRef(n.typ):
8293
# XXX Maybe require that 'n.typ' is acyclic. This is not much
@@ -96,7 +107,11 @@ proc checkIsolate*(n: PNode): bool =
96107
else:
97108
let argType = n[i].typ
98109
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
99-
if argType.canAlias(n.typ):
110+
if argType.canAlias(n.typ) or containsVariable(n[i]):
111+
# bug #19013: Alias information is not enough, we need to check for potential
112+
# "overlaps". I claim the problem can only happen by reading again from a location
113+
# that materialized which is only possible if a variable that contains a `ref`
114+
# is involved.
100115
return false
101116
result = true
102117
of nkIfStmt, nkIfExpr:

compiler/varpartitions.nim

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -647,13 +647,6 @@ proc deps(c: var Partitions; dest, src: PNode) =
647647
when explainCursors: echo "D not a cursor ", d.sym, " reassignedTo ", c.s[srcid].reassignedTo
648648
c.s[vid].flags.incl preventCursor
649649

650-
const
651-
nodesToIgnoreSet = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
652-
nkTypeSection, nkProcDef, nkConverterDef,
653-
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
654-
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
655-
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
656-
nkTypeOfExpr, nkMixinStmt, nkBindStmt}
657650

658651
proc potentialMutationViaArg(c: var Partitions; n: PNode; callee: PType) =
659652
if constParameters in c.goals and tfNoSideEffect in callee.flags:

tests/isolate/tisolate2.nim

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
discard """
2+
errormsg: "expression cannot be isolated: a_to_b(a)"
3+
line: 22
4+
"""
5+
6+
# bug #19013
7+
import std/isolation
8+
9+
type Z = ref object
10+
i: int
11+
12+
type A = object
13+
z: Z
14+
15+
type B = object
16+
z: Z
17+
18+
func a_to_b(a: A): B =
19+
result = B(z: a.z)
20+
21+
let a = A(z: Z(i: 3))
22+
let b = isolate(a_to_b(a))

0 commit comments

Comments
 (0)