authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-18 12:26:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-18 19:17:21-07:00
log22965e6fcbafbcba207a6da8eb493af2cf7ef924
tree99f420ce5880d23f3053fbf52e977f1cf6715a83
parentb13745ac03195c87d9efec2b12f564d4d3cbd477

Sema: improve error message for mismatched for loop lengths


3 files changed, 52 insertions(+), 4 deletions(-)

src/Module.zig+16
...@@ -2462,6 +2462,13 @@ pub const SrcLoc = struct {...@@ -2462,6 +2462,13 @@ pub const SrcLoc = struct {
2462 };2462 };
2463 return nodeToSpan(tree, src_node);2463 return nodeToSpan(tree, src_node);
2464 },2464 },
2465 .for_input => |for_input| {
2466 const tree = try src_loc.file_scope.getTree(gpa);
2467 const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset);
2468 const for_full = tree.fullFor(node).?;
2469 const src_node = for_full.ast.inputs[for_input.input_index];
2470 return nodeToSpan(tree, src_node);
2471 },
2465 .node_offset_bin_lhs => |node_off| {2472 .node_offset_bin_lhs => |node_off| {
2466 const tree = try src_loc.file_scope.getTree(gpa);2473 const tree = try src_loc.file_scope.getTree(gpa);
2467 const node = src_loc.declRelativeToNodeIndex(node_off);2474 const node = src_loc.declRelativeToNodeIndex(node_off);
...@@ -3114,6 +3121,14 @@ pub const LazySrcLoc = union(enum) {...@@ -3114,6 +3121,14 @@ pub const LazySrcLoc = union(enum) {
3114 /// The source location points to the RHS of an assignment.3121 /// The source location points to the RHS of an assignment.
3115 /// The Decl is determined contextually.3122 /// The Decl is determined contextually.
3116 node_offset_store_operand: i32,3123 node_offset_store_operand: i32,
3124 /// The source location points to a for loop input.
3125 /// The Decl is determined contextually.
3126 for_input: struct {
3127 /// Points to the for loop AST node.
3128 for_node_offset: i32,
3129 /// Picks one of the inputs from the condition.
3130 input_index: u32,
3131 },
31173132
3118 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;3133 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
31193134
...@@ -3200,6 +3215,7 @@ pub const LazySrcLoc = union(enum) {...@@ -3200,6 +3215,7 @@ pub const LazySrcLoc = union(enum) {
3200 .node_offset_init_ty,3215 .node_offset_init_ty,
3201 .node_offset_store_ptr,3216 .node_offset_store_ptr,
3202 .node_offset_store_operand,3217 .node_offset_store_operand,
3218 .for_input,
3203 => .{3219 => .{
3204 .file_scope = decl.getFileScope(),3220 .file_scope = decl.getFileScope(),
3205 .parent_decl_node = decl.src_node,3221 .parent_decl_node = decl.src_node,
src/Sema.zig+23-4
...@@ -3910,14 +3910,15 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -3910,14 +3910,15 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
39103910
3911 var len: Air.Inst.Ref = .none;3911 var len: Air.Inst.Ref = .none;
3912 var len_val: ?Value = null;3912 var len_val: ?Value = null;
3913 var len_idx: usize = undefined;3913 var len_idx: u32 = undefined;
3914 var any_runtime = false;3914 var any_runtime = false;
39153915
3916 const runtime_arg_lens = try gpa.alloc(Air.Inst.Ref, args.len);3916 const runtime_arg_lens = try gpa.alloc(Air.Inst.Ref, args.len);
3917 defer gpa.free(runtime_arg_lens);3917 defer gpa.free(runtime_arg_lens);
39183918
3919 // First pass to look for comptime values.3919 // First pass to look for comptime values.
3920 for (args, 0..) |zir_arg, i| {3920 for (args, 0..) |zir_arg, i_usize| {
3921 const i = @intCast(u32, i_usize);
3921 runtime_arg_lens[i] = .none;3922 runtime_arg_lens[i] = .none;
3922 if (zir_arg == .none) continue;3923 if (zir_arg == .none) continue;
3923 const object = try sema.resolveInst(zir_arg);3924 const object = try sema.resolveInst(zir_arg);
...@@ -3941,8 +3942,26 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -3941,8 +3942,26 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
3941 if (try sema.resolveDefinedValue(block, src, arg_len)) |arg_val| {3942 if (try sema.resolveDefinedValue(block, src, arg_len)) |arg_val| {
3942 if (len_val) |v| {3943 if (len_val) |v| {
3943 if (!(try sema.valuesEqual(arg_val, v, Type.usize))) {3944 if (!(try sema.valuesEqual(arg_val, v, Type.usize))) {
3944 // TODO error notes for each arg stating the differing values3945 const msg = msg: {
3945 return sema.fail(block, src, "non-matching for loop lengths", .{});3946 const msg = try sema.errMsg(block, src, "non-matching for loop lengths", .{});
3947 errdefer msg.destroy(gpa);
3948 const a_src: LazySrcLoc = .{ .for_input = .{
3949 .for_node_offset = inst_data.src_node,
3950 .input_index = len_idx,
3951 } };
3952 const b_src: LazySrcLoc = .{ .for_input = .{
3953 .for_node_offset = inst_data.src_node,
3954 .input_index = i,
3955 } };
3956 try sema.errNote(block, a_src, msg, "length {} here", .{
3957 v.fmtValue(Type.usize, sema.mod),
3958 });
3959 try sema.errNote(block, b_src, msg, "length {} here", .{
3960 arg_val.fmtValue(Type.usize, sema.mod),
3961 });
3962 break :msg msg;
3963 };
3964 return sema.failWithOwnedErrorMsg(msg);
3946 }3965 }
3947 } else {3966 } else {
3948 len = arg_len;3967 len = arg_len;
test/cases/compile_errors/for.zig created+13
...@@ -0,0 +1,13 @@
1export fn a() void {
2 for (0..10, 10..21) |i, j| {
3 _ = i; _ = j;
4 }
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :2:5: error: non-matching for loop lengths
12// :2:11: note: length 10 here
13// :2:19: note: length 11 here