authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-18 14:10:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-18 19:20:19-07:00
log4dd958d585256df3119d5617d22492f41ed02884
tree6be6266e06c0b1dd5ad13992292046a6bae1537d
parent601db3981ce820cfbca6001cbdfa87e24aa35ab5

improve error message for byref capture of byval array


4 files changed, 74 insertions(+), 7 deletions(-)

lib/std/crypto/aes/soft.zig+1-1
......@@ -420,7 +420,7 @@ const powx = init: {
420420 var array: [16]u8 = undefined;
421421
422422 var value = 1;
423 for (array) |*power| {
423 for (&array) |*power| {
424424 power.* = value;
425425 value = mul(value, 2);
426426 }
src/Module.zig+49
......@@ -2469,6 +2469,48 @@ pub const SrcLoc = struct {
24692469 const src_node = for_full.ast.inputs[for_input.input_index];
24702470 return nodeToSpan(tree, src_node);
24712471 },
2472 .for_capture_from_input => |node_off| {
2473 const tree = try src_loc.file_scope.getTree(gpa);
2474 const token_tags = tree.tokens.items(.tag);
2475 const input_node = src_loc.declRelativeToNodeIndex(node_off);
2476 // We have to actually linear scan the whole AST to find the for loop
2477 // that contains this input.
2478 const node_tags = tree.nodes.items(.tag);
2479 for (node_tags, 0..) |node_tag, node_usize| {
2480 const node = @intCast(Ast.Node.Index, node_usize);
2481 switch (node_tag) {
2482 .for_simple, .@"for" => {
2483 const for_full = tree.fullFor(node).?;
2484 for (for_full.ast.inputs, 0..) |input, input_index| {
2485 if (input_node == input) {
2486 var count = input_index;
2487 var tok = for_full.payload_token;
2488 while (true) {
2489 switch (token_tags[tok]) {
2490 .comma => {
2491 count -= 1;
2492 tok += 1;
2493 },
2494 .identifier => {
2495 if (count == 0)
2496 return tokensToSpan(tree, tok, tok + 1, tok);
2497 tok += 1;
2498 },
2499 .asterisk => {
2500 if (count == 0)
2501 return tokensToSpan(tree, tok, tok + 2, tok);
2502 tok += 1;
2503 },
2504 else => unreachable,
2505 }
2506 }
2507 }
2508 }
2509 },
2510 else => continue,
2511 }
2512 } else unreachable;
2513 },
24722514 .node_offset_bin_lhs => |node_off| {
24732515 const tree = try src_loc.file_scope.getTree(gpa);
24742516 const node = src_loc.declRelativeToNodeIndex(node_off);
......@@ -3129,6 +3171,12 @@ pub const LazySrcLoc = union(enum) {
31293171 /// Picks one of the inputs from the condition.
31303172 input_index: u32,
31313173 },
3174 /// The source location points to one of the captures of a for loop, found
3175 /// by taking this AST node index offset from the containing
3176 /// Decl AST node, which points to one of the input nodes of a for loop.
3177 /// Next, navigate to the corresponding capture.
3178 /// The Decl is determined contextually.
3179 for_capture_from_input: i32,
31323180
31333181 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
31343182
......@@ -3216,6 +3264,7 @@ pub const LazySrcLoc = union(enum) {
32163264 .node_offset_store_ptr,
32173265 .node_offset_store_operand,
32183266 .for_input,
3267 .for_capture_from_input,
32193268 => .{
32203269 .file_scope = decl.getFileScope(),
32213270 .parent_decl_node = decl.src_node,
src/Sema.zig+16-6
......@@ -9716,6 +9716,21 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97169716 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
97179717 const array_ptr = try sema.resolveInst(extra.lhs);
97189718 const elem_index = try sema.resolveInst(extra.rhs);
9719 const indexable_ty = sema.typeOf(array_ptr);
9720 if (indexable_ty.zigTypeTag() != .Pointer) {
9721 const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node };
9722 const msg = msg: {
9723 const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{
9724 indexable_ty.fmt(sema.mod),
9725 });
9726 errdefer msg.destroy(sema.gpa);
9727 if (indexable_ty.zigTypeTag() == .Array) {
9728 try sema.errNote(block, src, msg, "consider using '&' here", .{});
9729 }
9730 break :msg msg;
9731 };
9732 return sema.failWithOwnedErrorMsg(msg);
9733 }
97199734 return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false);
97209735}
97219736
......@@ -24195,12 +24210,7 @@ fn elemPtrOneLayerOnly(
2419524210 },
2419624211 }
2419724212 },
24198 else => {
24199 // TODO add note pointing at corresponding for loop input and suggest using '&'
24200 return sema.fail(block, indexable_src, "pointer capture of non pointer type '{}'", .{
24201 indexable_ty.fmt(sema.mod),
24202 });
24203 },
24213 else => unreachable,
2420424214 }
2420524215}
2420624216
test/cases/compile_errors/for.zig+8
......@@ -10,6 +10,12 @@ export fn b() void {
1010 _ = i; _ = j;
1111 }
1212}
13export fn c() void {
14 var buf: [10]u8 = undefined;
15 for (buf) |*byte| {
16 _ = byte;
17 }
18}
1319
1420// error
1521// backend=stage2
......@@ -20,3 +26,5 @@ export fn b() void {
2026// :2:19: note: length 11 here
2127// :9:14: error: type 'bool' does not support indexing
2228// :9:14: note: for loop operand must be an array, slice, tuple, or vector
29// :15:16: error: pointer capture of non pointer type '[10]u8'
30// :15:10: note: consider using '&' here