AstGen: add missing addRestoreErrRetIndex calls when handling for/while expr

Fixes #30912
This commit is contained in:
Pavel Verigo
2026-03-10 08:38:12 +01:00
committed by Andrew Kelley
parent d4cac43d30
commit 36faf76fe1
2 changed files with 142 additions and 0 deletions
+16
View File
@@ -6656,9 +6656,16 @@ fn whileExpr(
.operand = undefined,
} },
});
if (!continue_scope.is_comptime) {
_ = try continue_scope.addRestoreErrRetIndex(.{ .block = continue_block }, .always, then_node);
}
_ = try continue_scope.addBreak(break_tag, continue_block, .void_value);
}
try continue_scope.setBlockBody(continue_block);
if (!then_scope.is_comptime) {
const cont_node = while_full.ast.cont_expr.unwrap() orelse then_node;
_ = try then_scope.addRestoreErrRetIndex(.{ .block = cond_block }, .always, cont_node);
}
_ = try then_scope.addBreak(break_tag, cond_block, .void_value);
var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
@@ -6703,6 +6710,9 @@ fn whileExpr(
try checkUsed(parent_gz, &else_scope.base, sub_scope);
if (!else_scope.endsWithNoReturn()) {
if (!else_scope.is_comptime) {
_ = try else_scope.addRestoreErrRetIndex(.{ .block = loop_block }, .always, else_node);
}
_ = try else_scope.addBreakWithSrcNode(break_tag, loop_block, else_result, else_node);
}
} else {
@@ -6973,6 +6983,9 @@ fn forExpr(
});
const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
if (!then_scope.is_comptime) {
_ = try then_scope.addRestoreErrRetIndex(.{ .block = cond_block }, .always, then_node);
}
_ = try then_scope.addBreak(break_tag, cond_block, .void_value);
var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
@@ -6990,6 +7003,9 @@ fn forExpr(
_ = try addEnsureResult(&else_scope, else_result, else_node);
}
if (!else_scope.endsWithNoReturn()) {
if (!else_scope.is_comptime) {
_ = try else_scope.addRestoreErrRetIndex(.{ .block = loop_block }, .always, else_node);
}
_ = try else_scope.addBreakWithSrcNode(break_tag, loop_block, else_result, else_node);
}
} else {
+126
View File
@@ -92,6 +92,132 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.
,
});
cases.addCase(.{
.name = "for loop pops error return trace",
.source =
\\fn foo() !void { return error.FooError; }
\\
\\pub fn main() !void {
\\ for (0..2) |_| {
\\ const f = foo();
\\ f catch {};
\\ } else {
\\ const f = foo();
\\ f catch {};
\\ }
\\ return error.Stop;
\\}
,
.expect_error = "Stop",
.expect_trace =
\\source.zig:11:5: [address] in main
\\ return error.Stop;
\\ ^
,
.disable_trace_optimized = &.{
.{ .x86_64, .windows },
.{ .x86, .windows },
.{ .x86_64, .macos },
.{ .aarch64, .macos },
},
});
cases.addCase(.{
.name = "implicit continue in for loop pops stale error return trace",
.source =
\\fn foo() !void { return error.FooError; }
\\
\\pub fn main() !void {
\\ for (0..2) |i| {
\\ const f = foo();
\\ f catch {};
\\
\\ if (i == 1) return error.Stop;
\\ }
\\}
,
.expect_error = "Stop",
.expect_trace =
\\source.zig:1:18: [address] in foo
\\fn foo() !void { return error.FooError; }
\\ ^
\\source.zig:8:21: [address] in main
\\ if (i == 1) return error.Stop;
\\ ^
,
.disable_trace_optimized = &.{
.{ .x86_64, .windows },
.{ .x86, .windows },
.{ .x86_64, .macos },
.{ .aarch64, .macos },
},
});
cases.addCase(.{
.name = "while loop pops error return trace",
.source =
\\fn foo() !void { return error.FooError; }
\\
\\pub fn main() !void {
\\ var i: usize = 0;
\\ while (i < 2) {
\\ const f = foo();
\\ f catch {};
\\ i += 1;
\\ } else {
\\ const f = foo();
\\ f catch {};
\\ }
\\ return error.Stop;
\\}
,
.expect_error = "Stop",
.expect_trace =
\\source.zig:13:5: [address] in main
\\ return error.Stop;
\\ ^
,
.disable_trace_optimized = &.{
.{ .x86_64, .windows },
.{ .x86, .windows },
.{ .x86_64, .macos },
.{ .aarch64, .macos },
},
});
cases.addCase(.{
.name = "implicit continue in while loop pops stale error return trace",
.source =
\\fn foo() !void { return error.FooError; }
\\
\\pub fn main() !void {
\\ var i: usize = 0;
\\ while (i < 2) {
\\ const f = foo();
\\ f catch {};
\\
\\ if (i == 1) return error.Stop;
\\ i += 1;
\\ }
\\}
,
.expect_error = "Stop",
.expect_trace =
\\source.zig:1:18: [address] in foo
\\fn foo() !void { return error.FooError; }
\\ ^
\\source.zig:9:21: [address] in main
\\ if (i == 1) return error.Stop;
\\ ^
,
.disable_trace_optimized = &.{
.{ .x86_64, .windows },
.{ .x86, .windows },
.{ .x86_64, .macos },
.{ .aarch64, .macos },
},
});
cases.addCase(.{
.name = "try return + handled catch/if-else",
.source =