mirror of
https://github.com/ziglang/zig.git
synced 2026-01-16 12:25:21 +00:00
improve error message for byref capture of byval array
This commit is contained in:
parent
601db3981c
commit
4dd958d585
@ -420,7 +420,7 @@ const powx = init: {
|
||||
var array: [16]u8 = undefined;
|
||||
|
||||
var value = 1;
|
||||
for (array) |*power| {
|
||||
for (&array) |*power| {
|
||||
power.* = value;
|
||||
value = mul(value, 2);
|
||||
}
|
||||
|
||||
@ -2469,6 +2469,48 @@ pub const SrcLoc = struct {
|
||||
const src_node = for_full.ast.inputs[for_input.input_index];
|
||||
return nodeToSpan(tree, src_node);
|
||||
},
|
||||
.for_capture_from_input => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const input_node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
// We have to actually linear scan the whole AST to find the for loop
|
||||
// that contains this input.
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
for (node_tags, 0..) |node_tag, node_usize| {
|
||||
const node = @intCast(Ast.Node.Index, node_usize);
|
||||
switch (node_tag) {
|
||||
.for_simple, .@"for" => {
|
||||
const for_full = tree.fullFor(node).?;
|
||||
for (for_full.ast.inputs, 0..) |input, input_index| {
|
||||
if (input_node == input) {
|
||||
var count = input_index;
|
||||
var tok = for_full.payload_token;
|
||||
while (true) {
|
||||
switch (token_tags[tok]) {
|
||||
.comma => {
|
||||
count -= 1;
|
||||
tok += 1;
|
||||
},
|
||||
.identifier => {
|
||||
if (count == 0)
|
||||
return tokensToSpan(tree, tok, tok + 1, tok);
|
||||
tok += 1;
|
||||
},
|
||||
.asterisk => {
|
||||
if (count == 0)
|
||||
return tokensToSpan(tree, tok, tok + 2, tok);
|
||||
tok += 1;
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
} else unreachable;
|
||||
},
|
||||
.node_offset_bin_lhs => |node_off| {
|
||||
const tree = try src_loc.file_scope.getTree(gpa);
|
||||
const node = src_loc.declRelativeToNodeIndex(node_off);
|
||||
@ -3129,6 +3171,12 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// Picks one of the inputs from the condition.
|
||||
input_index: u32,
|
||||
},
|
||||
/// The source location points to one of the captures of a for loop, found
|
||||
/// by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to one of the input nodes of a for loop.
|
||||
/// Next, navigate to the corresponding capture.
|
||||
/// The Decl is determined contextually.
|
||||
for_capture_from_input: i32,
|
||||
|
||||
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
|
||||
|
||||
@ -3216,6 +3264,7 @@ pub const LazySrcLoc = union(enum) {
|
||||
.node_offset_store_ptr,
|
||||
.node_offset_store_operand,
|
||||
.for_input,
|
||||
.for_capture_from_input,
|
||||
=> .{
|
||||
.file_scope = decl.getFileScope(),
|
||||
.parent_decl_node = decl.src_node,
|
||||
|
||||
22
src/Sema.zig
22
src/Sema.zig
@ -9716,6 +9716,21 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const array_ptr = try sema.resolveInst(extra.lhs);
|
||||
const elem_index = try sema.resolveInst(extra.rhs);
|
||||
const indexable_ty = sema.typeOf(array_ptr);
|
||||
if (indexable_ty.zigTypeTag() != .Pointer) {
|
||||
const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node };
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{
|
||||
indexable_ty.fmt(sema.mod),
|
||||
});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
if (indexable_ty.zigTypeTag() == .Array) {
|
||||
try sema.errNote(block, src, msg, "consider using '&' here", .{});
|
||||
}
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false);
|
||||
}
|
||||
|
||||
@ -24195,12 +24210,7 @@ fn elemPtrOneLayerOnly(
|
||||
},
|
||||
}
|
||||
},
|
||||
else => {
|
||||
// TODO add note pointing at corresponding for loop input and suggest using '&'
|
||||
return sema.fail(block, indexable_src, "pointer capture of non pointer type '{}'", .{
|
||||
indexable_ty.fmt(sema.mod),
|
||||
});
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,12 @@ export fn b() void {
|
||||
_ = i; _ = j;
|
||||
}
|
||||
}
|
||||
export fn c() void {
|
||||
var buf: [10]u8 = undefined;
|
||||
for (buf) |*byte| {
|
||||
_ = byte;
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
@ -20,3 +26,5 @@ export fn b() void {
|
||||
// :2:19: note: length 11 here
|
||||
// :9:14: error: type 'bool' does not support indexing
|
||||
// :9:14: note: for loop operand must be an array, slice, tuple, or vector
|
||||
// :15:16: error: pointer capture of non pointer type '[10]u8'
|
||||
// :15:10: note: consider using '&' here
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user