| author | |
| committer | |
| log | 22965e6fcbafbcba207a6da8eb493af2cf7ef924 |
| tree | 99f420ce5880d23f3053fbf52e977f1cf6715a83 |
| parent | b13745ac03195c87d9efec2b12f564d4d3cbd477 |
3 files changed, 52 insertions(+), 4 deletions(-)
src/Module.zig+16| ... | ... | @@ -2462,6 +2462,13 @@ pub const SrcLoc = struct { |
| 2462 | 2462 | }; |
| 2463 | 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 | 2472 | .node_offset_bin_lhs => |node_off| { |
| 2466 | 2473 | const tree = try src_loc.file_scope.getTree(gpa); |
| 2467 | 2474 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| ... | ... | @@ -3114,6 +3121,14 @@ pub const LazySrcLoc = union(enum) { |
| 3114 | 3121 | /// The source location points to the RHS of an assignment. |
| 3115 | 3122 | /// The Decl is determined contextually. |
| 3116 | 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 | }, | |
| 3117 | 3132 | |
| 3118 | 3133 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
| 3119 | 3134 | |
| ... | ... | @@ -3200,6 +3215,7 @@ pub const LazySrcLoc = union(enum) { |
| 3200 | 3215 | .node_offset_init_ty, |
| 3201 | 3216 | .node_offset_store_ptr, |
| 3202 | 3217 | .node_offset_store_operand, |
| 3218 | .for_input, | |
| 3203 | 3219 | => .{ |
| 3204 | 3220 | .file_scope = decl.getFileScope(), |
| 3205 | 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 | 3910 | |
| 3911 | 3911 | var len: Air.Inst.Ref = .none; |
| 3912 | 3912 | var len_val: ?Value = null; |
| 3913 | var len_idx: usize = undefined; | |
| 3913 | var len_idx: u32 = undefined; | |
| 3914 | 3914 | var any_runtime = false; |
| 3915 | 3915 | |
| 3916 | 3916 | const runtime_arg_lens = try gpa.alloc(Air.Inst.Ref, args.len); |
| 3917 | 3917 | defer gpa.free(runtime_arg_lens); |
| 3918 | 3918 | |
| 3919 | 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 | 3922 | runtime_arg_lens[i] = .none; |
| 3922 | 3923 | if (zir_arg == .none) continue; |
| 3923 | 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 | 3942 | if (try sema.resolveDefinedValue(block, src, arg_len)) |arg_val| { |
| 3942 | 3943 | if (len_val) |v| { |
| 3943 | 3944 | if (!(try sema.valuesEqual(arg_val, v, Type.usize))) { |
| 3944 | // TODO error notes for each arg stating the differing values | |
| 3945 | return sema.fail(block, src, "non-matching for loop lengths", .{}); | |
| 3945 | const msg = msg: { | |
| 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 | 3966 | } else { |
| 3948 | 3967 | len = arg_len; |
test/cases/compile_errors/for.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | export 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 |