| ... | ... | @@ -3326,7 +3326,7 @@ fn zirValidateStructInit( |
| 3326 | 3326 | switch (agg_ty.zigTypeTag()) { |
| 3327 | 3327 | .Struct => return sema.validateStructInit( |
| 3328 | 3328 | block, |
| 3329 | | agg_ty.castTag(.@"struct").?.data, |
| 3329 | agg_ty, |
| 3330 | 3330 | init_src, |
| 3331 | 3331 | instrs, |
| 3332 | 3332 | is_comptime, |
| ... | ... | @@ -3470,7 +3470,7 @@ fn validateUnionInit( |
| 3470 | 3470 | fn validateStructInit( |
| 3471 | 3471 | sema: *Sema, |
| 3472 | 3472 | block: *Block, |
| 3473 | | struct_obj: *Module.Struct, |
| 3473 | struct_ty: Type, |
| 3474 | 3474 | init_src: LazySrcLoc, |
| 3475 | 3475 | instrs: []const Zir.Inst.Index, |
| 3476 | 3476 | is_comptime: bool, |
| ... | ... | @@ -3478,7 +3478,7 @@ fn validateStructInit( |
| 3478 | 3478 | const gpa = sema.gpa; |
| 3479 | 3479 | |
| 3480 | 3480 | // Maps field index to field_ptr index of where it was already initialized. |
| 3481 | | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.count()); |
| 3481 | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount()); |
| 3482 | 3482 | defer gpa.free(found_fields); |
| 3483 | 3483 | mem.set(Zir.Inst.Index, found_fields, 0); |
| 3484 | 3484 | |
| ... | ... | @@ -3490,8 +3490,7 @@ fn validateStructInit( |
| 3490 | 3490 | const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; |
| 3491 | 3491 | struct_ptr_zir_ref = field_ptr_extra.lhs; |
| 3492 | 3492 | const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start); |
| 3493 | | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| 3494 | | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 3493 | const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| 3495 | 3494 | if (found_fields[field_index] != 0) { |
| 3496 | 3495 | const other_field_ptr = found_fields[field_index]; |
| 3497 | 3496 | const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node; |
| ... | ... | @@ -3509,10 +3508,7 @@ fn validateStructInit( |
| 3509 | 3508 | |
| 3510 | 3509 | var root_msg: ?*Module.ErrorMsg = null; |
| 3511 | 3510 | |
| 3512 | | const fields = struct_obj.fields.values(); |
| 3513 | 3511 | const struct_ptr = try sema.resolveInst(struct_ptr_zir_ref); |
| 3514 | | const struct_ty = sema.typeOf(struct_ptr).childType(); |
| 3515 | | |
| 3516 | 3512 | if ((is_comptime or block.is_comptime) and |
| 3517 | 3513 | (try sema.resolveDefinedValue(block, init_src, struct_ptr)) != null) |
| 3518 | 3514 | { |
| ... | ... | @@ -3522,10 +3518,9 @@ fn validateStructInit( |
| 3522 | 3518 | for (found_fields) |field_ptr, i| { |
| 3523 | 3519 | if (field_ptr != 0) continue; |
| 3524 | 3520 | |
| 3525 | | const field = fields[i]; |
| 3526 | | const field_name = struct_obj.fields.keys()[i]; |
| 3527 | | |
| 3528 | | if (field.default_val.tag() == .unreachable_value) { |
| 3521 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 3522 | if (default_val.tag() == .unreachable_value) { |
| 3523 | const field_name = struct_ty.structFieldName(i); |
| 3529 | 3524 | const template = "missing struct field: {s}"; |
| 3530 | 3525 | const args = .{field_name}; |
| 3531 | 3526 | if (root_msg) |msg| { |
| ... | ... | @@ -3536,22 +3531,25 @@ fn validateStructInit( |
| 3536 | 3531 | continue; |
| 3537 | 3532 | } |
| 3538 | 3533 | |
| 3539 | | const default_field_ptr = try sema.structFieldPtr(block, init_src, struct_ptr, field_name, init_src, struct_ty); |
| 3540 | | const init = try sema.addConstant(field.ty, field.default_val); |
| 3541 | 3534 | const field_src = init_src; // TODO better source location |
| 3535 | const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty); |
| 3536 | const field_ty = sema.typeOf(default_field_ptr).childType(); |
| 3537 | const init = try sema.addConstant(field_ty, default_val); |
| 3542 | 3538 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); |
| 3543 | 3539 | } |
| 3544 | 3540 | |
| 3545 | 3541 | if (root_msg) |msg| { |
| 3546 | | const mod = sema.mod; |
| 3547 | | const fqn = try struct_obj.getFullyQualifiedName(mod); |
| 3548 | | defer gpa.free(fqn); |
| 3549 | | try mod.errNoteNonLazy( |
| 3550 | | struct_obj.srcLoc(mod), |
| 3551 | | msg, |
| 3552 | | "struct '{s}' declared here", |
| 3553 | | .{fqn}, |
| 3554 | | ); |
| 3542 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| 3543 | const mod = sema.mod; |
| 3544 | const fqn = try struct_obj.data.getFullyQualifiedName(mod); |
| 3545 | defer gpa.free(fqn); |
| 3546 | try mod.errNoteNonLazy( |
| 3547 | struct_obj.data.srcLoc(mod), |
| 3548 | msg, |
| 3549 | "struct '{s}' declared here", |
| 3550 | .{fqn}, |
| 3551 | ); |
| 3552 | } |
| 3555 | 3553 | return sema.failWithOwnedErrorMsg(block, msg); |
| 3556 | 3554 | } |
| 3557 | 3555 | |
| ... | ... | @@ -3566,17 +3564,16 @@ fn validateStructInit( |
| 3566 | 3564 | |
| 3567 | 3565 | // We collect the comptime field values in case the struct initialization |
| 3568 | 3566 | // ends up being comptime-known. |
| 3569 | | const field_values = try sema.arena.alloc(Value, fields.len); |
| 3567 | const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount()); |
| 3570 | 3568 | |
| 3571 | 3569 | field: for (found_fields) |field_ptr, i| { |
| 3572 | | const field = fields[i]; |
| 3573 | | |
| 3574 | 3570 | if (field_ptr != 0) { |
| 3575 | 3571 | const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node; |
| 3576 | 3572 | const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_ptr_data.src_node }; |
| 3577 | 3573 | |
| 3578 | 3574 | // Determine whether the value stored to this pointer is comptime-known. |
| 3579 | | if (try sema.typeHasOnePossibleValue(block, field_src, field.ty)) |opv| { |
| 3575 | const field_ty = struct_ty.structFieldType(i); |
| 3576 | if (try sema.typeHasOnePossibleValue(block, field_src, field_ty)) |opv| { |
| 3580 | 3577 | field_values[i] = opv; |
| 3581 | 3578 | continue; |
| 3582 | 3579 | } |
| ... | ... | @@ -3648,9 +3645,9 @@ fn validateStructInit( |
| 3648 | 3645 | continue :field; |
| 3649 | 3646 | } |
| 3650 | 3647 | |
| 3651 | | const field_name = struct_obj.fields.keys()[i]; |
| 3652 | | |
| 3653 | | if (field.default_val.tag() == .unreachable_value) { |
| 3648 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 3649 | if (default_val.tag() == .unreachable_value) { |
| 3650 | const field_name = struct_ty.structFieldName(i); |
| 3654 | 3651 | const template = "missing struct field: {s}"; |
| 3655 | 3652 | const args = .{field_name}; |
| 3656 | 3653 | if (root_msg) |msg| { |
| ... | ... | @@ -3660,17 +3657,20 @@ fn validateStructInit( |
| 3660 | 3657 | } |
| 3661 | 3658 | continue; |
| 3662 | 3659 | } |
| 3660 | field_values[i] = default_val; |
| 3663 | 3661 | } |
| 3664 | 3662 | |
| 3665 | 3663 | if (root_msg) |msg| { |
| 3666 | | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); |
| 3667 | | defer gpa.free(fqn); |
| 3668 | | try sema.mod.errNoteNonLazy( |
| 3669 | | struct_obj.srcLoc(sema.mod), |
| 3670 | | msg, |
| 3671 | | "struct '{s}' declared here", |
| 3672 | | .{fqn}, |
| 3673 | | ); |
| 3664 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| 3665 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); |
| 3666 | defer gpa.free(fqn); |
| 3667 | try sema.mod.errNoteNonLazy( |
| 3668 | struct_obj.data.srcLoc(sema.mod), |
| 3669 | msg, |
| 3670 | "struct '{s}' declared here", |
| 3671 | .{fqn}, |
| 3672 | ); |
| 3673 | } |
| 3674 | 3674 | return sema.failWithOwnedErrorMsg(block, msg); |
| 3675 | 3675 | } |
| 3676 | 3676 | |
| ... | ... | @@ -3679,15 +3679,6 @@ fn validateStructInit( |
| 3679 | 3679 | // instead a single `store` to the struct_ptr with a comptime struct value. |
| 3680 | 3680 | |
| 3681 | 3681 | block.instructions.shrinkRetainingCapacity(first_block_index); |
| 3682 | | |
| 3683 | | // The `field_values` array has been populated for all the non-default struct |
| 3684 | | // fields. Here we fill in the default field values. |
| 3685 | | for (found_fields) |field_ptr, i| { |
| 3686 | | if (field_ptr != 0) continue; |
| 3687 | | |
| 3688 | | field_values[i] = fields[i].default_val; |
| 3689 | | } |
| 3690 | | |
| 3691 | 3682 | const struct_val = try Value.Tag.aggregate.create(sema.arena, field_values); |
| 3692 | 3683 | const struct_init = try sema.addConstant(struct_ty, struct_val); |
| 3693 | 3684 | try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store); |
| ... | ... | @@ -3695,16 +3686,13 @@ fn validateStructInit( |
| 3695 | 3686 | } |
| 3696 | 3687 | |
| 3697 | 3688 | // Our task is to insert `store` instructions for all the default field values. |
| 3698 | | |
| 3699 | 3689 | for (found_fields) |field_ptr, i| { |
| 3700 | 3690 | if (field_ptr != 0) continue; |
| 3701 | 3691 | |
| 3702 | | const field = fields[i]; |
| 3703 | | const field_name = struct_obj.fields.keys()[i]; |
| 3704 | | const default_field_ptr = try sema.structFieldPtr(block, init_src, struct_ptr, field_name, init_src, struct_ty); |
| 3705 | | |
| 3706 | | const init = try sema.addConstant(field.ty, field.default_val); |
| 3707 | 3692 | const field_src = init_src; // TODO better source location |
| 3693 | const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty); |
| 3694 | const field_ty = sema.typeOf(default_field_ptr).childType(); |
| 3695 | const init = try sema.addConstant(field_ty, field_values[i]); |
| 3708 | 3696 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); |
| 3709 | 3697 | } |
| 3710 | 3698 | } |
| ... | ... | @@ -13827,7 +13815,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 13827 | 13815 | const obj_ty = try sema.resolveType(block, src, inst_data.operand); |
| 13828 | 13816 | |
| 13829 | 13817 | switch (obj_ty.zigTypeTag()) { |
| 13830 | | .Struct => return structInitEmpty(sema, block, obj_ty, src, src), |
| 13818 | .Struct => return sema.structInitEmpty(block, obj_ty, src, src), |
| 13831 | 13819 | .Array => return arrayInitEmpty(sema, obj_ty), |
| 13832 | 13820 | .Void => return sema.addConstant(obj_ty, Value.void), |
| 13833 | 13821 | else => return sema.failWithArrayInitNotSupported(block, src, obj_ty), |
| ... | ... | @@ -13844,29 +13832,13 @@ fn structInitEmpty( |
| 13844 | 13832 | const gpa = sema.gpa; |
| 13845 | 13833 | // This logic must be synchronized with that in `zirStructInit`. |
| 13846 | 13834 | const struct_ty = try sema.resolveTypeFields(block, dest_src, obj_ty); |
| 13847 | | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 13848 | 13835 | |
| 13849 | 13836 | // The init values to use for the struct instance. |
| 13850 | | const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count()); |
| 13837 | const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount()); |
| 13851 | 13838 | defer gpa.free(field_inits); |
| 13839 | mem.set(Air.Inst.Ref, field_inits, .none); |
| 13852 | 13840 | |
| 13853 | | var root_msg: ?*Module.ErrorMsg = null; |
| 13854 | | |
| 13855 | | for (struct_obj.fields.values()) |field, i| { |
| 13856 | | if (field.default_val.tag() == .unreachable_value) { |
| 13857 | | const field_name = struct_obj.fields.keys()[i]; |
| 13858 | | const template = "missing struct field: {s}"; |
| 13859 | | const args = .{field_name}; |
| 13860 | | if (root_msg) |msg| { |
| 13861 | | try sema.errNote(block, init_src, msg, template, args); |
| 13862 | | } else { |
| 13863 | | root_msg = try sema.errMsg(block, init_src, template, args); |
| 13864 | | } |
| 13865 | | } else { |
| 13866 | | field_inits[i] = try sema.addConstant(field.ty, field.default_val); |
| 13867 | | } |
| 13868 | | } |
| 13869 | | return sema.finishStructInit(block, dest_src, field_inits, root_msg, struct_obj, struct_ty, false); |
| 13841 | return sema.finishStructInit(block, init_src, dest_src, field_inits, struct_ty, false); |
| 13870 | 13842 | } |
| 13871 | 13843 | |
| 13872 | 13844 | fn arrayInitEmpty(sema: *Sema, obj_ty: Type) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -13936,19 +13908,18 @@ fn zirStructInit( |
| 13936 | 13908 | const unresolved_struct_type = try sema.resolveType(block, src, first_field_type_extra.container_type); |
| 13937 | 13909 | const resolved_ty = try sema.resolveTypeFields(block, src, unresolved_struct_type); |
| 13938 | 13910 | |
| 13939 | | if (resolved_ty.castTag(.@"struct")) |struct_payload| { |
| 13911 | if (resolved_ty.zigTypeTag() == .Struct) { |
| 13940 | 13912 | // This logic must be synchronized with that in `zirStructInitEmpty`. |
| 13941 | | const struct_obj = struct_payload.data; |
| 13942 | 13913 | |
| 13943 | 13914 | // Maps field index to field_type index of where it was already initialized. |
| 13944 | 13915 | // For making sure all fields are accounted for and no fields are duplicated. |
| 13945 | | const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.count()); |
| 13916 | const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount()); |
| 13946 | 13917 | defer gpa.free(found_fields); |
| 13947 | | mem.set(Zir.Inst.Index, found_fields, 0); |
| 13948 | 13918 | |
| 13949 | 13919 | // The init values to use for the struct instance. |
| 13950 | | const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count()); |
| 13920 | const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount()); |
| 13951 | 13921 | defer gpa.free(field_inits); |
| 13922 | mem.set(Air.Inst.Ref, field_inits, .none); |
| 13952 | 13923 | |
| 13953 | 13924 | var field_i: u32 = 0; |
| 13954 | 13925 | var extra_index = extra.end; |
| ... | ... | @@ -13961,9 +13932,8 @@ fn zirStructInit( |
| 13961 | 13932 | const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_type_data.src_node }; |
| 13962 | 13933 | const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data; |
| 13963 | 13934 | const field_name = sema.code.nullTerminatedString(field_type_extra.name_start); |
| 13964 | | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| 13965 | | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 13966 | | if (found_fields[field_index] != 0) { |
| 13935 | const field_index = try sema.structFieldIndex(block, resolved_ty, field_name, field_src); |
| 13936 | if (field_inits[field_index] != .none) { |
| 13967 | 13937 | const other_field_type = found_fields[field_index]; |
| 13968 | 13938 | const other_field_type_data = zir_datas[other_field_type].pl_node; |
| 13969 | 13939 | const other_field_src: LazySrcLoc = .{ .node_offset_back2tok = other_field_type_data.src_node }; |
| ... | ... | @@ -13979,27 +13949,7 @@ fn zirStructInit( |
| 13979 | 13949 | field_inits[field_index] = try sema.resolveInst(item.data.init); |
| 13980 | 13950 | } |
| 13981 | 13951 | |
| 13982 | | var root_msg: ?*Module.ErrorMsg = null; |
| 13983 | | |
| 13984 | | for (found_fields) |field_type_inst, i| { |
| 13985 | | if (field_type_inst != 0) continue; |
| 13986 | | |
| 13987 | | // Check if the field has a default init. |
| 13988 | | const field = struct_obj.fields.values()[i]; |
| 13989 | | if (field.default_val.tag() == .unreachable_value) { |
| 13990 | | const field_name = struct_obj.fields.keys()[i]; |
| 13991 | | const template = "missing struct field: {s}"; |
| 13992 | | const args = .{field_name}; |
| 13993 | | if (root_msg) |msg| { |
| 13994 | | try sema.errNote(block, src, msg, template, args); |
| 13995 | | } else { |
| 13996 | | root_msg = try sema.errMsg(block, src, template, args); |
| 13997 | | } |
| 13998 | | } else { |
| 13999 | | field_inits[i] = try sema.addConstant(field.ty, field.default_val); |
| 14000 | | } |
| 14001 | | } |
| 14002 | | return sema.finishStructInit(block, src, field_inits, root_msg, struct_obj, resolved_ty, is_ref); |
| 13952 | return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref); |
| 14003 | 13953 | } else if (resolved_ty.zigTypeTag() == .Union) { |
| 14004 | 13954 | if (extra.data.fields_len != 1) { |
| 14005 | 13955 | return sema.fail(block, src, "union initialization expects exactly one field", .{}); |
| ... | ... | @@ -14051,29 +14001,69 @@ fn zirStructInit( |
| 14051 | 14001 | fn finishStructInit( |
| 14052 | 14002 | sema: *Sema, |
| 14053 | 14003 | block: *Block, |
| 14054 | | src: LazySrcLoc, |
| 14055 | | field_inits: []const Air.Inst.Ref, |
| 14056 | | root_msg: ?*Module.ErrorMsg, |
| 14057 | | struct_obj: *Module.Struct, |
| 14004 | init_src: LazySrcLoc, |
| 14005 | dest_src: LazySrcLoc, |
| 14006 | field_inits: []Air.Inst.Ref, |
| 14058 | 14007 | struct_ty: Type, |
| 14059 | 14008 | is_ref: bool, |
| 14060 | | ) !Air.Inst.Ref { |
| 14009 | ) CompileError!Air.Inst.Ref { |
| 14061 | 14010 | const gpa = sema.gpa; |
| 14062 | 14011 | |
| 14012 | var root_msg: ?*Module.ErrorMsg = null; |
| 14013 | if (struct_ty.isAnonStruct()) { |
| 14014 | const struct_obj = struct_ty.castTag(.anon_struct).?.data; |
| 14015 | for (struct_obj.values) |default_val, i| { |
| 14016 | if (field_inits[i] != .none) continue; |
| 14017 | |
| 14018 | if (default_val.tag() == .unreachable_value) { |
| 14019 | const field_name = struct_obj.names[i]; |
| 14020 | const template = "missing struct field: {s}"; |
| 14021 | const args = .{field_name}; |
| 14022 | if (root_msg) |msg| { |
| 14023 | try sema.errNote(block, init_src, msg, template, args); |
| 14024 | } else { |
| 14025 | root_msg = try sema.errMsg(block, init_src, template, args); |
| 14026 | } |
| 14027 | } else { |
| 14028 | field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); |
| 14029 | } |
| 14030 | } |
| 14031 | } else { |
| 14032 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 14033 | for (struct_obj.fields.values()) |field, i| { |
| 14034 | if (field_inits[i] != .none) continue; |
| 14035 | |
| 14036 | if (field.default_val.tag() == .unreachable_value) { |
| 14037 | const field_name = struct_obj.fields.keys()[i]; |
| 14038 | const template = "missing struct field: {s}"; |
| 14039 | const args = .{field_name}; |
| 14040 | if (root_msg) |msg| { |
| 14041 | try sema.errNote(block, init_src, msg, template, args); |
| 14042 | } else { |
| 14043 | root_msg = try sema.errMsg(block, init_src, template, args); |
| 14044 | } |
| 14045 | } else { |
| 14046 | field_inits[i] = try sema.addConstant(field.ty, field.default_val); |
| 14047 | } |
| 14048 | } |
| 14049 | } |
| 14050 | |
| 14063 | 14051 | if (root_msg) |msg| { |
| 14064 | | const fqn = try struct_obj.getFullyQualifiedName(sema.mod); |
| 14065 | | defer gpa.free(fqn); |
| 14066 | | try sema.mod.errNoteNonLazy( |
| 14067 | | struct_obj.srcLoc(sema.mod), |
| 14068 | | msg, |
| 14069 | | "struct '{s}' declared here", |
| 14070 | | .{fqn}, |
| 14071 | | ); |
| 14052 | if (struct_ty.castTag(.@"struct")) |struct_obj| { |
| 14053 | const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod); |
| 14054 | defer gpa.free(fqn); |
| 14055 | try sema.mod.errNoteNonLazy( |
| 14056 | struct_obj.data.srcLoc(sema.mod), |
| 14057 | msg, |
| 14058 | "struct '{s}' declared here", |
| 14059 | .{fqn}, |
| 14060 | ); |
| 14061 | } |
| 14072 | 14062 | return sema.failWithOwnedErrorMsg(block, msg); |
| 14073 | 14063 | } |
| 14074 | 14064 | |
| 14075 | 14065 | const is_comptime = for (field_inits) |field_init| { |
| 14076 | | if (!(try sema.isComptimeKnown(block, src, field_init))) { |
| 14066 | if (!(try sema.isComptimeKnown(block, dest_src, field_init))) { |
| 14077 | 14067 | break false; |
| 14078 | 14068 | } |
| 14079 | 14069 | } else true; |
| ... | ... | @@ -14081,10 +14071,10 @@ fn finishStructInit( |
| 14081 | 14071 | if (is_comptime) { |
| 14082 | 14072 | const values = try sema.arena.alloc(Value, field_inits.len); |
| 14083 | 14073 | for (field_inits) |field_init, i| { |
| 14084 | | values[i] = (sema.resolveMaybeUndefVal(block, src, field_init) catch unreachable).?; |
| 14074 | values[i] = (sema.resolveMaybeUndefVal(block, dest_src, field_init) catch unreachable).?; |
| 14085 | 14075 | } |
| 14086 | 14076 | const struct_val = try Value.Tag.aggregate.create(sema.arena, values); |
| 14087 | | return sema.addConstantMaybeRef(block, src, struct_ty, struct_val, is_ref); |
| 14077 | return sema.addConstantMaybeRef(block, dest_src, struct_ty, struct_val, is_ref); |
| 14088 | 14078 | } |
| 14089 | 14079 | |
| 14090 | 14080 | if (is_ref) { |
| ... | ... | @@ -14096,15 +14086,15 @@ fn finishStructInit( |
| 14096 | 14086 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 14097 | 14087 | for (field_inits) |field_init, i_usize| { |
| 14098 | 14088 | const i = @intCast(u32, i_usize); |
| 14099 | | const field_src = src; |
| 14100 | | const field_ptr = try sema.structFieldPtrByIndex(block, src, alloc, i, struct_obj, field_src); |
| 14101 | | try sema.storePtr(block, src, field_ptr, field_init); |
| 14089 | const field_src = dest_src; |
| 14090 | const field_ptr = try sema.structFieldPtrByIndex(block, dest_src, alloc, i, field_src, struct_ty); |
| 14091 | try sema.storePtr(block, dest_src, field_ptr, field_init); |
| 14102 | 14092 | } |
| 14103 | 14093 | |
| 14104 | 14094 | return alloc; |
| 14105 | 14095 | } |
| 14106 | 14096 | |
| 14107 | | try sema.requireRuntimeBlock(block, src); |
| 14097 | try sema.requireRuntimeBlock(block, dest_src); |
| 14108 | 14098 | try sema.queueFullTypeResolution(struct_ty); |
| 14109 | 14099 | return block.addAggregateInit(struct_ty, field_inits); |
| 14110 | 14100 | } |
| ... | ... | @@ -15872,7 +15862,8 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15872 | 15862 | |
| 15873 | 15863 | fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 { |
| 15874 | 15864 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 15875 | | sema.src = .{ .node_offset_bin_op = inst_data.src_node }; |
| 15865 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; |
| 15866 | sema.src = src; |
| 15876 | 15867 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 15877 | 15868 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 15878 | 15869 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| ... | ... | @@ -15882,50 +15873,38 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 15882 | 15873 | const target = sema.mod.getTarget(); |
| 15883 | 15874 | |
| 15884 | 15875 | try sema.resolveTypeLayout(block, lhs_src, ty); |
| 15885 | | if (ty.tag() != .@"struct") { |
| 15886 | | const msg = msg: { |
| 15887 | | const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)}); |
| 15888 | | errdefer msg.destroy(sema.gpa); |
| 15889 | | try sema.addDeclaredHereNote(msg, ty); |
| 15890 | | break :msg msg; |
| 15891 | | }; |
| 15892 | | return sema.failWithOwnedErrorMsg(block, msg); |
| 15876 | switch (ty.tag()) { |
| 15877 | .@"struct", .tuple, .anon_struct => {}, |
| 15878 | else => { |
| 15879 | const msg = msg: { |
| 15880 | const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)}); |
| 15881 | errdefer msg.destroy(sema.gpa); |
| 15882 | try sema.addDeclaredHereNote(msg, ty); |
| 15883 | break :msg msg; |
| 15884 | }; |
| 15885 | return sema.failWithOwnedErrorMsg(block, msg); |
| 15886 | }, |
| 15893 | 15887 | } |
| 15894 | 15888 | |
| 15895 | | const fields = ty.structFields(); |
| 15896 | | const index = fields.getIndex(field_name) orelse { |
| 15897 | | const msg = msg: { |
| 15898 | | const msg = try sema.errMsg( |
| 15899 | | block, |
| 15900 | | rhs_src, |
| 15901 | | "struct '{}' has no field '{s}'", |
| 15902 | | .{ ty.fmt(sema.mod), field_name }, |
| 15903 | | ); |
| 15904 | | errdefer msg.destroy(sema.gpa); |
| 15905 | | try sema.addDeclaredHereNote(msg, ty); |
| 15906 | | break :msg msg; |
| 15907 | | }; |
| 15908 | | return sema.failWithOwnedErrorMsg(block, msg); |
| 15909 | | }; |
| 15889 | const field_index = if (ty.isTuple()) blk: { |
| 15890 | if (mem.eql(u8, field_name, "len")) { |
| 15891 | return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); |
| 15892 | } |
| 15893 | break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); |
| 15894 | } else try sema.structFieldIndex(block, ty, field_name, rhs_src); |
| 15910 | 15895 | |
| 15911 | 15896 | switch (ty.containerLayout()) { |
| 15912 | 15897 | .Packed => { |
| 15913 | 15898 | var bit_sum: u64 = 0; |
| 15899 | const fields = ty.structFields(); |
| 15914 | 15900 | for (fields.values()) |field, i| { |
| 15915 | | if (i == index) { |
| 15901 | if (i == field_index) { |
| 15916 | 15902 | return bit_sum; |
| 15917 | 15903 | } |
| 15918 | 15904 | bit_sum += field.ty.bitSize(target); |
| 15919 | 15905 | } else unreachable; |
| 15920 | 15906 | }, |
| 15921 | | else => { |
| 15922 | | var it = ty.iterateStructOffsets(target); |
| 15923 | | while (it.next()) |field_offset| { |
| 15924 | | if (field_offset.field == index) { |
| 15925 | | return field_offset.offset * 8; |
| 15926 | | } |
| 15927 | | } else unreachable; |
| 15928 | | }, |
| 15907 | else => return ty.structFieldOffset(field_index, target) * 8, |
| 15929 | 15908 | } |
| 15930 | 15909 | } |
| 15931 | 15910 | |
| ... | ... | @@ -17193,24 +17172,28 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 17193 | 17172 | } |
| 17194 | 17173 | try sema.resolveTypeLayout(block, ty_src, struct_ty); |
| 17195 | 17174 | |
| 17196 | | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 17197 | | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| 17198 | | return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name); |
| 17175 | const field_index = if (struct_ty.isTuple()) blk: { |
| 17176 | if (mem.eql(u8, field_name, "len")) { |
| 17177 | return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{}); |
| 17178 | } |
| 17179 | break :blk try sema.tupleFieldIndex(block, struct_ty, field_name, name_src); |
| 17180 | } else try sema.structFieldIndex(block, struct_ty, field_name, name_src); |
| 17199 | 17181 | |
| 17200 | 17182 | try sema.checkPtrOperand(block, ptr_src, field_ptr_ty); |
| 17201 | | const field = struct_obj.fields.values()[field_index]; |
| 17202 | 17183 | const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; |
| 17203 | 17184 | |
| 17204 | 17185 | var ptr_ty_data: Type.Payload.Pointer.Data = .{ |
| 17205 | | .pointee_type = field.ty, |
| 17186 | .pointee_type = struct_ty.structFieldType(field_index), |
| 17206 | 17187 | .mutable = field_ptr_ty_info.mutable, |
| 17207 | 17188 | .@"addrspace" = field_ptr_ty_info.@"addrspace", |
| 17208 | 17189 | }; |
| 17209 | 17190 | |
| 17210 | | if (struct_obj.layout == .Packed) { |
| 17191 | if (struct_ty.containerLayout() == .Packed) { |
| 17211 | 17192 | return sema.fail(block, src, "TODO handle packed structs with @fieldParentPtr", .{}); |
| 17212 | 17193 | } else { |
| 17213 | | ptr_ty_data.@"align" = field.abi_align; |
| 17194 | ptr_ty_data.@"align" = if (struct_ty.castTag(.@"struct")) |struct_obj| b: { |
| 17195 | break :b struct_obj.data.fields.values()[field_index].abi_align; |
| 17196 | } else 0; |
| 17214 | 17197 | } |
| 17215 | 17198 | |
| 17216 | 17199 | const actual_field_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); |
| ... | ... | @@ -19059,7 +19042,7 @@ fn structFieldPtr( |
| 19059 | 19042 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name); |
| 19060 | 19043 | const field_index = @intCast(u32, field_index_big); |
| 19061 | 19044 | |
| 19062 | | return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_obj, field_name_src); |
| 19045 | return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, field_name_src, struct_ty); |
| 19063 | 19046 | } |
| 19064 | 19047 | |
| 19065 | 19048 | fn structFieldPtrByIndex( |
| ... | ... | @@ -19068,9 +19051,14 @@ fn structFieldPtrByIndex( |
| 19068 | 19051 | src: LazySrcLoc, |
| 19069 | 19052 | struct_ptr: Air.Inst.Ref, |
| 19070 | 19053 | field_index: u32, |
| 19071 | | struct_obj: *Module.Struct, |
| 19072 | 19054 | field_src: LazySrcLoc, |
| 19055 | struct_ty: Type, |
| 19073 | 19056 | ) CompileError!Air.Inst.Ref { |
| 19057 | if (struct_ty.isAnonStruct()) { |
| 19058 | return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index); |
| 19059 | } |
| 19060 | |
| 19061 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 19074 | 19062 | const field = struct_obj.fields.values()[field_index]; |
| 19075 | 19063 | const struct_ptr_ty = sema.typeOf(struct_ptr); |
| 19076 | 19064 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo().data; |
| ... | ... | @@ -19231,17 +19219,13 @@ fn tupleFieldIndex( |
| 19231 | 19219 | field_name: []const u8, |
| 19232 | 19220 | field_name_src: LazySrcLoc, |
| 19233 | 19221 | ) CompileError!u32 { |
| 19234 | | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| 19235 | | return sema.fail(block, field_name_src, "tuple '{}' has no such field '{s}': {s}", .{ |
| 19236 | | tuple_ty.fmt(sema.mod), field_name, @errorName(err), |
| 19237 | | }); |
| 19238 | | }; |
| 19239 | | if (field_index >= tuple_ty.structFieldCount()) { |
| 19240 | | return sema.fail(block, field_name_src, "tuple '{}' has no such field '{s}'", .{ |
| 19241 | | tuple_ty.fmt(sema.mod), field_name, |
| 19242 | | }); |
| 19243 | | } |
| 19244 | | return field_index; |
| 19222 | if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { |
| 19223 | if (field_index < tuple_ty.structFieldCount()) return field_index; |
| 19224 | } else |_| {} |
| 19225 | |
| 19226 | return sema.fail(block, field_name_src, "no field named '{s}' in tuple '{}'", .{ |
| 19227 | field_name, tuple_ty.fmt(sema.mod), |
| 19228 | }); |
| 19245 | 19229 | } |
| 19246 | 19230 | |
| 19247 | 19231 | fn tupleFieldValByIndex( |
| ... | ... | @@ -20356,7 +20340,7 @@ fn coerce( |
| 20356 | 20340 | }, |
| 20357 | 20341 | .Struct => { |
| 20358 | 20342 | if (inst == .empty_struct) { |
| 20359 | | return structInitEmpty(sema, block, dest_ty, dest_ty_src, inst_src); |
| 20343 | return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src); |
| 20360 | 20344 | } |
| 20361 | 20345 | if (inst_ty.isTupleOrAnonStruct()) { |
| 20362 | 20346 | return sema.coerceTupleToStruct(block, dest_ty, dest_ty_src, inst, inst_src); |
| ... | ... | @@ -25754,10 +25738,14 @@ fn structFieldIndex( |
| 25754 | 25738 | field_src: LazySrcLoc, |
| 25755 | 25739 | ) !u32 { |
| 25756 | 25740 | const struct_ty = try sema.resolveTypeFields(block, field_src, unresolved_struct_ty); |
| 25757 | | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 25758 | | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| 25759 | | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 25760 | | return @intCast(u32, field_index_usize); |
| 25741 | if (struct_ty.isAnonStruct()) { |
| 25742 | return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src); |
| 25743 | } else { |
| 25744 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 25745 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| 25746 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 25747 | return @intCast(u32, field_index_usize); |
| 25748 | } |
| 25761 | 25749 | } |
| 25762 | 25750 | |
| 25763 | 25751 | fn anonStructFieldIndex( |
| ... | ... | @@ -25773,8 +25761,8 @@ fn anonStructFieldIndex( |
| 25773 | 25761 | return @intCast(u32, i); |
| 25774 | 25762 | } |
| 25775 | 25763 | } |
| 25776 | | return sema.fail(block, field_src, "anonymous struct '{}' has no such field '{s}'", .{ |
| 25777 | | struct_ty.fmt(sema.mod), field_name, |
| 25764 | return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{ |
| 25765 | field_name, struct_ty.fmt(sema.mod), |
| 25778 | 25766 | }); |
| 25779 | 25767 | } |
| 25780 | 25768 | |