diff --git a/src/analyze.cpp b/src/analyze.cpp index 32cb3c0624..2dfb540801 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5701,23 +5701,30 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { // (await y) + x static void mark_suspension_point(Scope *scope) { ScopeExpr *child_expr_scope = (scope->id == ScopeIdExpr) ? reinterpret_cast(scope) : nullptr; + bool looking_for_exprs = true; for (;;) { scope = scope->parent; switch (scope->id) { - case ScopeIdDefer: case ScopeIdDeferExpr: case ScopeIdDecls: case ScopeIdFnDef: case ScopeIdCompTime: - case ScopeIdVarDecl: case ScopeIdCImport: case ScopeIdSuspend: case ScopeIdTypeOf: return; + case ScopeIdVarDecl: + case ScopeIdDefer: + looking_for_exprs = false; + continue; case ScopeIdLoop: case ScopeIdRuntime: continue; case ScopeIdExpr: { + if (!looking_for_exprs) { + // Now we're only looking for a block, to see if it's in a loop (see the case ScopeIdBlock) + continue; + } ScopeExpr *parent_expr_scope = reinterpret_cast(scope); if (child_expr_scope != nullptr) { for (size_t i = 0; parent_expr_scope->children_ptr[i] != child_expr_scope; i += 1) { diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 86a0b659a8..8445bcb5b2 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1233,3 +1233,38 @@ test "spill target expr in a for loop" { resume S.global_frame; } +test "spill target expr in a for loop, with a var decl in the loop body" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + var foo = Foo{ + .slice = [_]i32{1, 2}, + }; + expect(atest(&foo) == 3); + } + + const Foo = struct { + slice: []i32, + }; + + fn atest(foo: *Foo) i32 { + var sum: i32 = 0; + for (foo.slice) |x| { + // Previously this var decl would prevent spills. This test makes sure + // the for loop spills still happen even though there is a VarDecl in scope + // before the suspend. + var anything = true; + _ = anything; + suspend { + global_frame = @frame(); + } + sum += x; + } + return sum; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; + resume S.global_frame; +}