diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2024-02-16 11:25:32 +0000 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2024-02-16 11:26:35 +0000 |
| commit | e6cf3ce24c42d4a2dffd4f0204a22a31eef3c562 (patch) | |
| tree | eaa21f0a22f03d595151edc806d7120d8f5e0074 | |
| parent | 260c84535546c81028cf42f1eb6ec9f17275db0f (diff) | |
| download | zig-e6cf3ce24c42d4a2dffd4f0204a22a31eef3c562.tar.gz zig-e6cf3ce24c42d4a2dffd4f0204a22a31eef3c562.zip | |
Sema: correct source location for return value coercion errors
When coercing the operand of a `ret_node` etc instruction, the source
location for errors used to point to the entire `return` statement.
Instead, we now point to the operand, as would be expected if there was
an explicit `as_node` instruction (like there used to be).
| -rw-r--r-- | src/Module.zig | 15 | ||||
| -rw-r--r-- | src/Sema.zig | 15 |
2 files changed, 23 insertions, 7 deletions
diff --git a/src/Module.zig b/src/Module.zig index d332c4db53..66d6aa3fe5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1867,6 +1867,16 @@ pub const SrcLoc = struct { else => return nodeToSpan(tree, node), } }, + .node_offset_return_operand => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node = src_loc.declRelativeToNodeIndex(node_off); + const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); + if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { + return nodeToSpan(tree, node_datas[node].lhs); + } + return nodeToSpan(tree, node); + }, } } @@ -2221,6 +2231,10 @@ pub const LazySrcLoc = union(enum) { /// The source location points to the RHS of an assignment. /// The Decl is determined contextually. node_offset_store_operand: i32, + /// The source location points to the operand of a `return` statement, or + /// the `return` itself if there is no explicit operand. + /// The Decl is determined contextually. + node_offset_return_operand: i32, /// The source location points to a for loop input. /// The Decl is determined contextually. for_input: struct { @@ -2347,6 +2361,7 @@ pub const LazySrcLoc = union(enum) { .node_offset_init_ty, .node_offset_store_ptr, .node_offset_store_operand, + .node_offset_return_operand, .for_input, .for_capture_from_input, .array_cat_lhs, diff --git a/src/Sema.zig b/src/Sema.zig index 45f0edcb56..ce231af6fd 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -19182,7 +19182,7 @@ fn zirRetErrValue( .ty = error_set_type.toIntern(), .name = err_name, } }))); - return sema.analyzeRet(block, result_inst, src); + return sema.analyzeRet(block, result_inst, src, src); } fn zirRetImplicit( @@ -19232,7 +19232,7 @@ fn zirRetImplicit( return sema.failWithOwnedErrorMsg(block, msg); } - return sema.analyzeRet(block, operand, r_brace_src); + return sema.analyzeRet(block, operand, r_brace_src, r_brace_src); } fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { @@ -19243,7 +19243,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir const operand = try sema.resolveInst(inst_data.operand); const src = inst_data.src(); - return sema.analyzeRet(block, operand, src); + return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node }); } fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { @@ -19256,7 +19256,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir if (block.is_comptime or block.inlining != null or sema.func_is_naked) { const operand = try sema.analyzeLoad(block, src, ret_ptr, src); - return sema.analyzeRet(block, operand, src); + return sema.analyzeRet(block, operand, src, .{ .node_offset_return_operand = inst_data.src_node }); } if (sema.wantErrorReturnTracing(sema.fn_ret_ty)) { @@ -19450,6 +19450,7 @@ fn analyzeRet( block: *Block, uncasted_operand: Air.Inst.Ref, src: LazySrcLoc, + operand_src: LazySrcLoc, ) CompileError!Zir.Inst.Index { // Special case for returning an error to an inferred error set; we need to // add the error tag to the inferred error set of the in-scope function, so @@ -19458,14 +19459,14 @@ fn analyzeRet( if (sema.fn_ret_ty_ies != null and sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) { try sema.addToInferredErrorSet(uncasted_operand); } - const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) { + const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, operand_src, .{ .is_ret = true }) catch |err| switch (err) { error.NotCoercible => unreachable, else => |e| return e, }; if (block.inlining) |inlining| { if (block.is_comptime) { - const ret_val = try sema.resolveConstValue(block, src, operand, .{ + const ret_val = try sema.resolveConstValue(block, operand_src, operand, .{ .needed_comptime_reason = "value being returned at comptime must be comptime-known", }); inlining.comptime_result = operand; @@ -19500,7 +19501,7 @@ fn analyzeRet( if (sema.wantErrorReturnTracing(sema.fn_ret_ty)) { // Avoid adding a frame to the error return trace in case the value is comptime-known // to be not an error. - const is_non_err = try sema.analyzeIsNonErr(block, src, operand); + const is_non_err = try sema.analyzeIsNonErr(block, operand_src, operand); return sema.retWithErrTracing(block, src, is_non_err, air_tag, operand); } |
