mirror of
https://github.com/ziglang/zig.git
synced 2026-02-01 04:03:40 +00:00
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).
This commit is contained in:
parent
260c845355
commit
e6cf3ce24c
@ -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,
|
||||
|
||||
15
src/Sema.zig
15
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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user