diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-02-18 14:10:56 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-02-18 19:20:19 -0700 |
| commit | 4dd958d585256df3119d5617d22492f41ed02884 (patch) | |
| tree | 6be6266e06c0b1dd5ad13992292046a6bae1537d | |
| parent | 601db3981ce820cfbca6001cbdfa87e24aa35ab5 (diff) | |
| download | zig-4dd958d585256df3119d5617d22492f41ed02884.tar.gz zig-4dd958d585256df3119d5617d22492f41ed02884.zip | |
improve error message for byref capture of byval array
| -rw-r--r-- | lib/std/crypto/aes/soft.zig | 2 | ||||
| -rw-r--r-- | src/Module.zig | 49 | ||||
| -rw-r--r-- | src/Sema.zig | 22 | ||||
| -rw-r--r-- | test/cases/compile_errors/for.zig | 8 |
4 files changed, 74 insertions, 7 deletions
diff --git a/lib/std/crypto/aes/soft.zig b/lib/std/crypto/aes/soft.zig index b57f1746dc..d8bd3d4ac0 100644 --- a/lib/std/crypto/aes/soft.zig +++ b/lib/std/crypto/aes/soft.zig @@ -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); } diff --git a/src/Module.zig b/src/Module.zig index 377ccd2441..76777532ab 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -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, diff --git a/src/Sema.zig b/src/Sema.zig index 7e8520eaa1..07176ad1a0 100644 --- a/src/Sema.zig +++ b/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, } } diff --git a/test/cases/compile_errors/for.zig b/test/cases/compile_errors/for.zig index abb87084b4..dff46af085 100644 --- a/test/cases/compile_errors/for.zig +++ b/test/cases/compile_errors/for.zig @@ -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 |
