Skip to content

Commit feb90f6

Browse files
committed
AstGen: emit debug stmt for try
This improves the following test case: ```zig pub fn main() !void { try foo(); } fn foo() !void { return error.Bad; } ``` The error return trace now points to the `try` token instead of pointing to the foo() function call, matching stage1. Closes #12308.
1 parent 0648177 commit feb90f6

File tree

2 files changed

+20
-8
lines changed

2 files changed

+20
-8
lines changed

src/AstGen.zig

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5051,6 +5051,16 @@ fn tryExpr(
50515051

50525052
if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{});
50535053

5054+
// Ensure debug line/column information is emitted for this try expression.
5055+
// Then we will save the line/column so that we can emit another one that goes
5056+
// "backwards" because we want to evaluate the operand, but then put the debug
5057+
// info back at the try keyword for error return tracing.
5058+
if (!parent_gz.force_comptime) {
5059+
try emitDbgNode(parent_gz, node);
5060+
}
5061+
const try_line = astgen.source_line - parent_gz.decl_line;
5062+
const try_column = astgen.source_column;
5063+
50545064
const operand_rl: ResultLoc = switch (rl) {
50555065
.ref => .ref,
50565066
else => .none,
@@ -5080,6 +5090,7 @@ fn tryExpr(
50805090
};
50815091
const err_code = try else_scope.addUnNode(err_tag, operand, node);
50825092
try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
5093+
try emitDbgStmt(&else_scope, try_line, try_column);
50835094
_ = try else_scope.addUnNode(.ret_node, err_code, node);
50845095

50855096
try else_scope.setTryBody(try_inst, operand);
@@ -6614,13 +6625,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66146625
const defer_counts = countDefers(astgen, defer_outer, scope);
66156626
if (!defer_counts.need_err_code) {
66166627
try genDefers(gz, defer_outer, scope, .both_sans_err);
6617-
try emitRetDbgStmt(gz, ret_line, ret_column);
6628+
try emitDbgStmt(gz, ret_line, ret_column);
66186629
_ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
66196630
return Zir.Inst.Ref.unreachable_value;
66206631
}
66216632
const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
66226633
try genDefers(gz, defer_outer, scope, .{ .both = err_code });
6623-
try emitRetDbgStmt(gz, ret_line, ret_column);
6634+
try emitDbgStmt(gz, ret_line, ret_column);
66246635
_ = try gz.addUnNode(.ret_node, err_code, node);
66256636
return Zir.Inst.Ref.unreachable_value;
66266637
}
@@ -6639,15 +6650,15 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66396650
.never => {
66406651
// Returning a value that cannot be an error; skip error defers.
66416652
try genDefers(gz, defer_outer, scope, .normal_only);
6642-
try emitRetDbgStmt(gz, ret_line, ret_column);
6653+
try emitDbgStmt(gz, ret_line, ret_column);
66436654
try gz.addRet(rl, operand, node);
66446655
return Zir.Inst.Ref.unreachable_value;
66456656
},
66466657
.always => {
66476658
// Value is always an error. Emit both error defers and regular defers.
66486659
const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;
66496660
try genDefers(gz, defer_outer, scope, .{ .both = err_code });
6650-
try emitRetDbgStmt(gz, ret_line, ret_column);
6661+
try emitDbgStmt(gz, ret_line, ret_column);
66516662
try gz.addRet(rl, operand, node);
66526663
return Zir.Inst.Ref.unreachable_value;
66536664
},
@@ -6656,7 +6667,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66566667
if (!defer_counts.have_err) {
66576668
// Only regular defers; no branch needed.
66586669
try genDefers(gz, defer_outer, scope, .normal_only);
6659-
try emitRetDbgStmt(gz, ret_line, ret_column);
6670+
try emitDbgStmt(gz, ret_line, ret_column);
66606671
try gz.addRet(rl, operand, node);
66616672
return Zir.Inst.Ref.unreachable_value;
66626673
}
@@ -6670,7 +6681,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66706681
defer then_scope.unstack();
66716682

66726683
try genDefers(&then_scope, defer_outer, scope, .normal_only);
6673-
try emitRetDbgStmt(gz, ret_line, ret_column);
6684+
try emitDbgStmt(&then_scope, ret_line, ret_column);
66746685
try then_scope.addRet(rl, operand, node);
66756686

66766687
var else_scope = gz.makeSubBlock(scope);
@@ -6680,7 +6691,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66806691
.both = try else_scope.addUnNode(.err_union_code, result, node),
66816692
};
66826693
try genDefers(&else_scope, defer_outer, scope, which_ones);
6683-
try emitRetDbgStmt(gz, ret_line, ret_column);
6694+
try emitDbgStmt(&else_scope, ret_line, ret_column);
66846695
try else_scope.addRet(rl, operand, node);
66856696

66866697
try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
@@ -11698,7 +11709,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
1169811709
return @intCast(u32, count);
1169911710
}
1170011711

11701-
fn emitRetDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
11712+
fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
1170211713
if (gz.force_comptime) return;
1170311714

1170411715
_ = try gz.add(.{ .tag = .dbg_stmt, .data = .{

test/stack_traces.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
2222
.ReleaseSafe = .{
2323
.exclude_os = .{
2424
.windows, // segfault
25+
.linux, // defeated by aggressive inlining
2526
},
2627
.expect =
2728
\\error: TheSkyIsFalling

0 commit comments

Comments
 (0)