Skip to content

Commit 8427412

Browse files
committed
stage2: Propagate error return trace into fn call
This change extends the "lifetime" of the error return trace associated with an error to include the duration of a function call it is passed to. This means that if a function returns an error, its return trace will include the error return trace for any error inputs. This is needed to support `testing.expectError` and similar functions. If a function returns a non-error, we have to clean up any error return traces created by error-able call arguments.
1 parent 0c04a45 commit 8427412

File tree

3 files changed

+250
-73
lines changed

3 files changed

+250
-73
lines changed

src/AstGen.zig

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ pub const ResultInfo = struct {
224224
/// such as if and switch expressions.
225225
fn br(ri: ResultInfo) ResultInfo {
226226
return switch (ri.rl) {
227-
.coerced_ty => |ty| .{
227+
.coerced_ty => |ty| .{
228228
.rl = .{ .ty = ty },
229229
.ctx = ri.ctx,
230230
},
@@ -247,9 +247,11 @@ pub const ResultContext = enum {
247247
/// The expression is the operand to a return expression.
248248
@"return",
249249
/// The expression is the input to an error-handling operator (if-else, try, or catch).
250-
error_handling_expr,
250+
error_handling_expr,
251251
/// The expression is the right-hand side of a shift operation.
252252
shift_op,
253+
/// The expression is an argument in a function call.
254+
fn_arg,
253255
/// No specific operator in particular.
254256
none,
255257
};
@@ -1693,8 +1695,7 @@ fn structInitExprRlNone(
16931695
.container_type = ty_inst,
16941696
.name_start = str_index,
16951697
}) } }
1696-
else
1697-
.{ .rl = .none };
1698+
else .{ .rl = .none };
16981699
setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{
16991700
.field_name = str_index,
17001701
.init = try expr(gz, scope, sub_ri, field_init),
@@ -5195,9 +5196,9 @@ fn popErrorReturnTrace(
51955196

51965197
const result_is_err = nodeMayEvalToError(tree, node);
51975198

5198-
// If we are breaking to a try/catch/error-union-if/return, the error trace propagates.
5199+
// If we are breaking to a try/catch/error-union-if/return or a function call, the error trace propagates.
51995200
const propagate_error_trace = switch (ri.ctx) {
5200-
.error_handling_expr, .@"return" => true,
5201+
.error_handling_expr, .@"return", .fn_arg => true,
52015202
else => false,
52025203
};
52035204

@@ -8462,7 +8463,7 @@ fn callExpr(
84628463
defer arg_block.unstack();
84638464

84648465
// `call_inst` is reused to provide the param type.
8465-
const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst } }, param_node);
8466+
const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node);
84668467
_ = try arg_block.addBreak(.break_inline, call_index, arg_ref);
84678468

84688469
const body = arg_block.instructionsSlice();
@@ -8476,7 +8477,7 @@ fn callExpr(
84768477
// If our result location is a try/catch/error-union-if/return, the error trace propagates.
84778478
// Otherwise, it should always be popped (handled in Sema).
84788479
const propagate_error_trace = switch (ri.ctx) {
8479-
.error_handling_expr, .@"return" => true, // Propagate to try/catch/error-union-if and return
8480+
.error_handling_expr, .@"return", .fn_arg => true, // Propagate to try/catch/error-union-if, return, and other function calls
84808481
else => false,
84818482
};
84828483

0 commit comments

Comments
 (0)