From f8e470eb579c96515693d76ad393dbd41b393f26 Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Tue, 16 Jun 2026 13:15:16 -0400 Subject: [PATCH] fix: {.cast(uncheckedAssign).} ineffective across yield in closure iterators (#25916) closureiters.nim splits a stmt list at yield points, moving post-yield code into a new state body. When that stmt list was inside a pragma block like `{.cast(uncheckedAssign).}`, the new state's body was created as a bare nkStmtList without the wrapper. Fix: track the enclosing pragma block in the transform context, and wrap newly-created state bodies in a copy of it when the split occurs inside one. Added an explicit `nkPragmaBlock` case to `transformClosureIteratorBody` that saves/restores `ctx.enclosingPragma` around its body. --- compiler/closureiters.nim | 19 ++++++++++-- tests/iter/tlowerpragmablock.nim | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tests/iter/tlowerpragmablock.nim diff --git a/compiler/closureiters.nim b/compiler/closureiters.nim index f96685cbbd..e85ad4975d 100644 --- a/compiler/closureiters.nim +++ b/compiler/closureiters.nim @@ -167,6 +167,8 @@ type curExcSym: PSym # Current exception externExcSym: PSym # Extern exception: what would getCurrentException() return outside of closure iter + enclosingPragmas: seq[PNode] # stack of pragma blocks wrapping stmtlist + states: seq[State] # The resulting states. Label is int literal. finallyPathStack: seq[FinallyTarget] # Stack of split blocks, whiles and finallies stateLoopLabel: PSym # Label to break on, when jumping between states. @@ -983,9 +985,14 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode for j in i + 1..