diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 35102d9e6b..2d1a42cd86 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -1345,6 +1345,7 @@ type PragmaBlockContext = object oldLocked: int enforcedGcSafety, enforceNoSideEffects: bool + oldInEnforcedGcSafe, oldInEnforcedNoSideEffects: bool oldExc, oldTags, oldForbids: int exc, tags, forbids: PNode excSource, tagsSource, forbidsSource: PNode @@ -1354,6 +1355,8 @@ proc createBlockContext(tracked: PEffects): PragmaBlockContext = if tracked.forbids != nil: oldForbidsLen = tracked.forbids.len result = PragmaBlockContext(oldLocked: tracked.locked.len, enforcedGcSafety: false, enforceNoSideEffects: false, + oldInEnforcedGcSafe: tracked.inEnforcedGcSafe, + oldInEnforcedNoSideEffects: tracked.inEnforcedNoSideEffects, oldExc: tracked.exc.len, oldTags: tracked.tags.len, oldForbids: oldForbidsLen) @@ -1362,8 +1365,9 @@ proc applyBlockContext(tracked: PEffects, bc: PragmaBlockContext) = if bc.enforceNoSideEffects: tracked.inEnforcedNoSideEffects = true proc unapplyBlockContext(tracked: PEffects; bc: PragmaBlockContext) = - if bc.enforcedGcSafety: tracked.inEnforcedGcSafe = false - if bc.enforceNoSideEffects: tracked.inEnforcedNoSideEffects = false + if bc.enforcedGcSafety: tracked.inEnforcedGcSafe = bc.oldInEnforcedGcSafe + if bc.enforceNoSideEffects: + tracked.inEnforcedNoSideEffects = bc.oldInEnforcedNoSideEffects setLen(tracked.locked, bc.oldLocked) if bc.exc != nil: # beware that 'raises: []' is very different from not saying diff --git a/tests/effects/tnestedcastblocks.nim b/tests/effects/tnestedcastblocks.nim new file mode 100644 index 0000000000..67fd87b481 --- /dev/null +++ b/tests/effects/tnestedcastblocks.nim @@ -0,0 +1,33 @@ +discard """ + output: '''4 +3''' +""" +# bug #26092: exiting a nested cast block used to cancel the enclosing +# block's cast for the statements after it. + +type Obj = ref object + x: int +let g: Obj = Obj(x: 1) +var fp: proc(): int {.nimcall.} = proc(): int {.nimcall.} = 2 + +proc consumer(): int {.gcsafe.} = + {.cast(gcsafe).}: + let a = g.x + var b: int + {.cast(gcsafe).}: + b = g.x + let c = fp() + a + b + c +echo consumer() + +var counter = 0 +proc bump() = inc counter + +proc pure(): int {.noSideEffect.} = + {.cast(noSideEffect).}: + bump() + {.cast(noSideEffect).}: + bump() + bump() + counter +echo pure()