| ... | ... | @@ -3493,19 +3493,43 @@ fn validateArrayInitTy( |
| 3493 | 3493 | block: *Block, |
| 3494 | 3494 | inst: Zir.Inst.Index, |
| 3495 | 3495 | ) CompileError!void { |
| 3496 | | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3496 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 3497 | 3497 | const src = inst_data.src(); |
| 3498 | | const ty = try sema.resolveType(block, src, inst_data.operand); |
| 3498 | const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; |
| 3499 | const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; |
| 3500 | const ty = try sema.resolveType(block, ty_src, extra.ty); |
| 3499 | 3501 | |
| 3500 | 3502 | switch (ty.zigTypeTag()) { |
| 3501 | | .Array, .Vector => return, |
| 3503 | .Array => { |
| 3504 | const array_len = ty.arrayLen(); |
| 3505 | if (extra.init_count != array_len) { |
| 3506 | return sema.fail(block, src, "expected {d} array elements; found {d}", .{ |
| 3507 | array_len, extra.init_count, |
| 3508 | }); |
| 3509 | } |
| 3510 | return; |
| 3511 | }, |
| 3512 | .Vector => { |
| 3513 | const array_len = ty.arrayLen(); |
| 3514 | if (extra.init_count != array_len) { |
| 3515 | return sema.fail(block, src, "expected {d} vector elements; found {d}", .{ |
| 3516 | array_len, extra.init_count, |
| 3517 | }); |
| 3518 | } |
| 3519 | return; |
| 3520 | }, |
| 3502 | 3521 | .Struct => if (ty.isTuple()) { |
| 3503 | | // TODO validate element count |
| 3522 | const array_len = ty.arrayLen(); |
| 3523 | if (extra.init_count > array_len) { |
| 3524 | return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{ |
| 3525 | array_len, extra.init_count, |
| 3526 | }); |
| 3527 | } |
| 3504 | 3528 | return; |
| 3505 | 3529 | }, |
| 3506 | 3530 | else => {}, |
| 3507 | 3531 | } |
| 3508 | | return sema.failWithArrayInitNotSupported(block, src, ty); |
| 3532 | return sema.failWithArrayInitNotSupported(block, ty_src, ty); |
| 3509 | 3533 | } |
| 3510 | 3534 | |
| 3511 | 3535 | fn validateStructInitTy( |
| ... | ... | @@ -3741,6 +3765,15 @@ fn validateStructInit( |
| 3741 | 3765 | |
| 3742 | 3766 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 3743 | 3767 | if (default_val.tag() == .unreachable_value) { |
| 3768 | if (struct_ty.isTuple()) { |
| 3769 | const template = "missing tuple field with index {d}"; |
| 3770 | if (root_msg) |msg| { |
| 3771 | try sema.errNote(block, init_src, msg, template, .{i}); |
| 3772 | } else { |
| 3773 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 3774 | } |
| 3775 | continue; |
| 3776 | } |
| 3744 | 3777 | const field_name = struct_ty.structFieldName(i); |
| 3745 | 3778 | const template = "missing struct field: {s}"; |
| 3746 | 3779 | const args = .{field_name}; |
| ... | ... | @@ -3753,7 +3786,10 @@ fn validateStructInit( |
| 3753 | 3786 | } |
| 3754 | 3787 | |
| 3755 | 3788 | const field_src = init_src; // TODO better source location |
| 3756 | | const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| 3789 | const default_field_ptr = if (struct_ty.isTuple()) |
| 3790 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) |
| 3791 | else |
| 3792 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| 3757 | 3793 | const field_ty = sema.typeOf(default_field_ptr).childType(); |
| 3758 | 3794 | const init = try sema.addConstant(field_ty, default_val); |
| 3759 | 3795 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); |
| ... | ... | @@ -3868,6 +3904,15 @@ fn validateStructInit( |
| 3868 | 3904 | |
| 3869 | 3905 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 3870 | 3906 | if (default_val.tag() == .unreachable_value) { |
| 3907 | if (struct_ty.isTuple()) { |
| 3908 | const template = "missing tuple field with index {d}"; |
| 3909 | if (root_msg) |msg| { |
| 3910 | try sema.errNote(block, init_src, msg, template, .{i}); |
| 3911 | } else { |
| 3912 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 3913 | } |
| 3914 | continue; |
| 3915 | } |
| 3871 | 3916 | const field_name = struct_ty.structFieldName(i); |
| 3872 | 3917 | const template = "missing struct field: {s}"; |
| 3873 | 3918 | const args = .{field_name}; |
| ... | ... | @@ -3911,7 +3956,10 @@ fn validateStructInit( |
| 3911 | 3956 | if (field_ptr != 0) continue; |
| 3912 | 3957 | |
| 3913 | 3958 | const field_src = init_src; // TODO better source location |
| 3914 | | const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| 3959 | const default_field_ptr = if (struct_ty.isTuple()) |
| 3960 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) |
| 3961 | else |
| 3962 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); |
| 3915 | 3963 | const field_ty = sema.typeOf(default_field_ptr).childType(); |
| 3916 | 3964 | const init = try sema.addConstant(field_ty, field_values[i]); |
| 3917 | 3965 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); |
| ... | ... | @@ -3934,15 +3982,24 @@ fn zirValidateArrayInit( |
| 3934 | 3982 | const array_ty = sema.typeOf(array_ptr).childType(); |
| 3935 | 3983 | const array_len = array_ty.arrayLen(); |
| 3936 | 3984 | |
| 3937 | | if (instrs.len != array_len) { |
| 3938 | | if (array_ty.zigTypeTag() == .Array) { |
| 3939 | | return sema.fail(block, init_src, "expected {d} array elements; found {d}", .{ |
| 3940 | | array_len, instrs.len, |
| 3941 | | }); |
| 3942 | | } else { |
| 3943 | | return sema.fail(block, init_src, "expected {d} vector elements; found {d}", .{ |
| 3944 | | array_len, instrs.len, |
| 3945 | | }); |
| 3985 | if (instrs.len != array_len and array_ty.isTuple()) { |
| 3986 | const struct_obj = array_ty.castTag(.tuple).?.data; |
| 3987 | var root_msg: ?*Module.ErrorMsg = null; |
| 3988 | for (struct_obj.values) |default_val, i| { |
| 3989 | if (i < instrs.len) continue; |
| 3990 | |
| 3991 | if (default_val.tag() == .unreachable_value) { |
| 3992 | const template = "missing tuple field with index {d}"; |
| 3993 | if (root_msg) |msg| { |
| 3994 | try sema.errNote(block, init_src, msg, template, .{i}); |
| 3995 | } else { |
| 3996 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 3997 | } |
| 3998 | } |
| 3999 | } |
| 4000 | |
| 4001 | if (root_msg) |msg| { |
| 4002 | return sema.failWithOwnedErrorMsg(block, msg); |
| 3946 | 4003 | } |
| 3947 | 4004 | } |
| 3948 | 4005 | |
| ... | ... | @@ -3995,10 +4052,17 @@ fn zirValidateArrayInit( |
| 3995 | 4052 | } |
| 3996 | 4053 | first_block_index = @minimum(first_block_index, block_index); |
| 3997 | 4054 | |
| 3998 | | // Array has one possible value, so value is always comptime-known |
| 3999 | | if (opt_opv) |opv| { |
| 4000 | | element_vals[i] = opv; |
| 4001 | | continue; |
| 4055 | if (array_ty.isTuple()) { |
| 4056 | if (array_ty.structFieldValueComptime(i)) |opv| { |
| 4057 | element_vals[i] = opv; |
| 4058 | continue; |
| 4059 | } |
| 4060 | } else { |
| 4061 | // Array has one possible value, so value is always comptime-known |
| 4062 | if (opt_opv) |opv| { |
| 4063 | element_vals[i] = opv; |
| 4064 | continue; |
| 4065 | } |
| 4002 | 4066 | } |
| 4003 | 4067 | |
| 4004 | 4068 | // If the next instructon is a store with a comptime operand, this element |
| ... | ... | @@ -14710,6 +14774,22 @@ fn finishStructInit( |
| 14710 | 14774 | field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); |
| 14711 | 14775 | } |
| 14712 | 14776 | } |
| 14777 | } else if (struct_ty.isTuple()) { |
| 14778 | const struct_obj = struct_ty.castTag(.tuple).?.data; |
| 14779 | for (struct_obj.values) |default_val, i| { |
| 14780 | if (field_inits[i] != .none) continue; |
| 14781 | |
| 14782 | if (default_val.tag() == .unreachable_value) { |
| 14783 | const template = "missing tuple field with index {d}"; |
| 14784 | if (root_msg) |msg| { |
| 14785 | try sema.errNote(block, init_src, msg, template, .{i}); |
| 14786 | } else { |
| 14787 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 14788 | } |
| 14789 | } else { |
| 14790 | field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); |
| 14791 | } |
| 14792 | } |
| 14713 | 14793 | } else { |
| 14714 | 14794 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 14715 | 14795 | for (struct_obj.fields.values()) |field, i| { |
| ... | ... | @@ -20255,7 +20335,7 @@ fn tupleFieldVal( |
| 20255 | 20335 | return tupleFieldValByIndex(sema, block, src, tuple_byval, field_index, tuple_ty); |
| 20256 | 20336 | } |
| 20257 | 20337 | |
| 20258 | | /// Don't forget to check for "len" before calling this. |
| 20338 | /// Asserts that `field_name` is not "len". |
| 20259 | 20339 | fn tupleFieldIndex( |
| 20260 | 20340 | sema: *Sema, |
| 20261 | 20341 | block: *Block, |
| ... | ... | @@ -20263,8 +20343,12 @@ fn tupleFieldIndex( |
| 20263 | 20343 | field_name: []const u8, |
| 20264 | 20344 | field_name_src: LazySrcLoc, |
| 20265 | 20345 | ) CompileError!u32 { |
| 20346 | assert(!std.mem.eql(u8, field_name, "len")); |
| 20266 | 20347 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { |
| 20267 | 20348 | if (field_index < tuple_ty.structFieldCount()) return field_index; |
| 20349 | return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{ |
| 20350 | field_name, tuple_ty.fmt(sema.mod), |
| 20351 | }); |
| 20268 | 20352 | } else |_| {} |
| 20269 | 20353 | |
| 20270 | 20354 | return sema.fail(block, field_name_src, "no field named '{s}' in tuple '{}'", .{ |