| ... | ... | @@ -2699,6 +2699,7 @@ pub fn getStructType( |
| 2699 | 2699 | .requires_comptime = if (small.known_comptime_only) .yes else .unknown, |
| 2700 | 2700 | .any_default_inits = small.any_default_inits, |
| 2701 | 2701 | .any_comptime_fields = small.any_comptime_fields, |
| 2702 | .inits_resolved = false, |
| 2702 | 2703 | .any_aligned_fields = small.any_aligned_fields, |
| 2703 | 2704 | }); |
| 2704 | 2705 | |
| ... | ... | @@ -4718,6 +4719,7 @@ fn validateStructInit( |
| 4718 | 4719 | const i: u32 = @intCast(i_usize); |
| 4719 | 4720 | if (field_ptr != .none) continue; |
| 4720 | 4721 | |
| 4722 | try sema.resolveStructFieldInits(struct_ty); |
| 4721 | 4723 | const default_val = struct_ty.structFieldDefaultValue(i, mod); |
| 4722 | 4724 | if (default_val.toIntern() == .unreachable_value) { |
| 4723 | 4725 | const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse { |
| ... | ... | @@ -4773,6 +4775,8 @@ fn validateStructInit( |
| 4773 | 4775 | const air_tags = sema.air_instructions.items(.tag); |
| 4774 | 4776 | const air_datas = sema.air_instructions.items(.data); |
| 4775 | 4777 | |
| 4778 | try sema.resolveStructFieldInits(struct_ty); |
| 4779 | |
| 4776 | 4780 | // We collect the comptime field values in case the struct initialization |
| 4777 | 4781 | // ends up being comptime-known. |
| 4778 | 4782 | const field_values = try sema.arena.alloc(InternPool.Index, struct_ty.structFieldCount(mod)); |
| ... | ... | @@ -17630,6 +17634,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17630 | 17634 | }; |
| 17631 | 17635 | struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); |
| 17632 | 17636 | |
| 17637 | try sema.resolveStructFieldInits(ty); |
| 17638 | |
| 17633 | 17639 | for (struct_field_vals, 0..) |*field_val, i| { |
| 17634 | 17640 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 17635 | 17641 | const name = if (struct_type.fieldName(ip, i).unwrap()) |name_nts| |
| ... | ... | @@ -19205,17 +19211,20 @@ fn zirStructInit( |
| 19205 | 19211 | const uncoerced_init = try sema.resolveInst(item.data.init); |
| 19206 | 19212 | const field_ty = resolved_ty.structFieldType(field_index, mod); |
| 19207 | 19213 | field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src); |
| 19208 | | if (!is_packed) if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 19209 | | const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { |
| 19210 | | return sema.failWithNeededComptime(block, field_src, .{ |
| 19211 | | .needed_comptime_reason = "value stored in comptime field must be comptime-known", |
| 19212 | | }); |
| 19213 | | }; |
| 19214 | if (!is_packed) { |
| 19215 | try sema.resolveStructFieldInits(resolved_ty); |
| 19216 | if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| { |
| 19217 | const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { |
| 19218 | return sema.failWithNeededComptime(block, field_src, .{ |
| 19219 | .needed_comptime_reason = "value stored in comptime field must be comptime-known", |
| 19220 | }); |
| 19221 | }; |
| 19214 | 19222 | |
| 19215 | | if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index, mod), mod)) { |
| 19216 | | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); |
| 19223 | if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index, mod), mod)) { |
| 19224 | return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); |
| 19225 | } |
| 19217 | 19226 | } |
| 19218 | | }; |
| 19227 | } |
| 19219 | 19228 | } |
| 19220 | 19229 | |
| 19221 | 19230 | return sema.finishStructInit(block, src, src, field_inits, resolved_ty, result_ty, is_ref); |
| ... | ... | @@ -19368,6 +19377,8 @@ fn finishStructInit( |
| 19368 | 19377 | continue; |
| 19369 | 19378 | } |
| 19370 | 19379 | |
| 19380 | try sema.resolveStructFieldInits(struct_ty); |
| 19381 | |
| 19371 | 19382 | const field_init = struct_type.fieldInit(ip, i); |
| 19372 | 19383 | if (field_init == .none) { |
| 19373 | 19384 | const field_name = struct_type.field_names.get(ip)[i]; |
| ... | ... | @@ -21132,6 +21143,7 @@ fn reifyStruct( |
| 21132 | 21143 | // struct types. |
| 21133 | 21144 | .any_comptime_fields = true, |
| 21134 | 21145 | .any_default_inits = true, |
| 21146 | .inits_resolved = true, |
| 21135 | 21147 | .any_aligned_fields = true, |
| 21136 | 21148 | }); |
| 21137 | 21149 | // TODO: figure out InternPool removals for incremental compilation |
| ... | ... | @@ -26632,6 +26644,7 @@ fn finishFieldCallBind( |
| 26632 | 26644 | |
| 26633 | 26645 | const container_ty = ptr_ty.childType(mod); |
| 26634 | 26646 | if (container_ty.zigTypeTag(mod) == .Struct) { |
| 26647 | try sema.resolveStructFieldInits(container_ty); |
| 26635 | 26648 | if (try container_ty.structFieldValueComptime(mod, field_index)) |default_val| { |
| 26636 | 26649 | return .{ .direct = Air.internedToRef(default_val.toIntern()) }; |
| 26637 | 26650 | } |
| ... | ... | @@ -26847,6 +26860,7 @@ fn structFieldPtrByIndex( |
| 26847 | 26860 | const ptr_field_ty = try sema.ptrType(ptr_ty_data); |
| 26848 | 26861 | |
| 26849 | 26862 | if (struct_type.fieldIsComptime(ip, field_index)) { |
| 26863 | try sema.resolveStructFieldInits(struct_ty); |
| 26850 | 26864 | const val = try mod.intern(.{ .ptr = .{ |
| 26851 | 26865 | .ty = ptr_field_ty.toIntern(), |
| 26852 | 26866 | .addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] }, |
| ... | ... | @@ -26883,6 +26897,7 @@ fn structFieldVal( |
| 26883 | 26897 | assert(struct_ty.zigTypeTag(mod) == .Struct); |
| 26884 | 26898 | |
| 26885 | 26899 | try sema.resolveTypeFields(struct_ty); |
| 26900 | |
| 26886 | 26901 | switch (ip.indexToKey(struct_ty.toIntern())) { |
| 26887 | 26902 | .struct_type => |struct_type| { |
| 26888 | 26903 | if (struct_type.isTuple(ip)) |
| ... | ... | @@ -26891,6 +26906,7 @@ fn structFieldVal( |
| 26891 | 26906 | const field_index = struct_type.nameIndex(ip, field_name) orelse |
| 26892 | 26907 | return sema.failWithBadStructFieldAccess(block, struct_type, field_name_src, field_name); |
| 26893 | 26908 | if (struct_type.fieldIsComptime(ip, field_index)) { |
| 26909 | try sema.resolveStructFieldInits(struct_ty); |
| 26894 | 26910 | return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); |
| 26895 | 26911 | } |
| 26896 | 26912 | |
| ... | ... | @@ -31282,6 +31298,7 @@ fn coerceTupleToStruct( |
| 31282 | 31298 | const mod = sema.mod; |
| 31283 | 31299 | const ip = &mod.intern_pool; |
| 31284 | 31300 | try sema.resolveTypeFields(struct_ty); |
| 31301 | try sema.resolveStructFieldInits(struct_ty); |
| 31285 | 31302 | |
| 31286 | 31303 | if (struct_ty.isTupleOrAnonStruct(mod)) { |
| 31287 | 31304 | return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src); |
| ... | ... | @@ -34264,6 +34281,8 @@ fn resolvePeerTypesInner( |
| 34264 | 34281 | var comptime_val: ?Value = null; |
| 34265 | 34282 | for (peer_tys) |opt_ty| { |
| 34266 | 34283 | const struct_ty = opt_ty orelse continue; |
| 34284 | try sema.resolveStructFieldInits(struct_ty); |
| 34285 | |
| 34267 | 34286 | const uncoerced_field_val = try struct_ty.structFieldValueComptime(mod, field_idx) orelse { |
| 34268 | 34287 | comptime_val = null; |
| 34269 | 34288 | break; |
| ... | ... | @@ -34605,8 +34624,7 @@ pub fn resolveStructAlignment( |
| 34605 | 34624 | // We'll guess "pointer-aligned", if the struct has an |
| 34606 | 34625 | // underaligned pointer field then some allocations |
| 34607 | 34626 | // might require explicit alignment. |
| 34608 | | //TODO write this bit and emit an error later if incorrect |
| 34609 | | //struct_type.flagsPtr(ip).assumed_pointer_aligned = true; |
| 34627 | struct_type.flagsPtr(ip).assumed_pointer_aligned = true; |
| 34610 | 34628 | const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 34611 | 34629 | struct_type.flagsPtr(ip).alignment = result; |
| 34612 | 34630 | return result; |
| ... | ... | @@ -34618,8 +34636,7 @@ pub fn resolveStructAlignment( |
| 34618 | 34636 | // We'll guess "pointer-aligned", if the struct has an |
| 34619 | 34637 | // underaligned pointer field then some allocations |
| 34620 | 34638 | // might require explicit alignment. |
| 34621 | | //TODO write this bit and emit an error later if incorrect |
| 34622 | | //struct_type.flagsPtr(ip).assumed_pointer_aligned = true; |
| 34639 | struct_type.flagsPtr(ip).assumed_pointer_aligned = true; |
| 34623 | 34640 | const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 34624 | 34641 | struct_type.flagsPtr(ip).alignment = result; |
| 34625 | 34642 | return result; |
| ... | ... | @@ -34710,6 +34727,18 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34710 | 34727 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34711 | 34728 | } |
| 34712 | 34729 | |
| 34730 | if (struct_type.flagsPtr(ip).assumed_pointer_aligned and |
| 34731 | big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(mod.getTarget().ptrBitWidth(), 8)))) |
| 34732 | { |
| 34733 | const msg = try Module.ErrorMsg.create( |
| 34734 | sema.gpa, |
| 34735 | mod.declPtr(struct_type.decl.unwrap().?).srcLoc(mod), |
| 34736 | "struct layout depends on being pointer aligned", |
| 34737 | .{}, |
| 34738 | ); |
| 34739 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34740 | } |
| 34741 | |
| 34713 | 34742 | if (struct_type.hasReorderedFields()) { |
| 34714 | 34743 | const runtime_order = struct_type.runtime_order.get(ip); |
| 34715 | 34744 | |
| ... | ... | @@ -35329,6 +35358,32 @@ pub fn resolveTypeFieldsStruct( |
| 35329 | 35358 | try semaStructFields(mod, sema.arena, struct_type); |
| 35330 | 35359 | } |
| 35331 | 35360 | |
| 35361 | pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { |
| 35362 | const mod = sema.mod; |
| 35363 | const ip = &mod.intern_pool; |
| 35364 | const struct_type = mod.typeToStruct(ty) orelse return; |
| 35365 | const owner_decl = struct_type.decl.unwrap() orelse return; |
| 35366 | |
| 35367 | // Inits can start as resolved |
| 35368 | if (struct_type.haveFieldInits(ip)) return; |
| 35369 | |
| 35370 | try sema.resolveStructLayout(ty); |
| 35371 | |
| 35372 | if (struct_type.setInitsWip(ip)) { |
| 35373 | const msg = try Module.ErrorMsg.create( |
| 35374 | sema.gpa, |
| 35375 | mod.declPtr(owner_decl).srcLoc(mod), |
| 35376 | "struct '{}' depends on itself", |
| 35377 | .{ty.fmt(mod)}, |
| 35378 | ); |
| 35379 | return sema.failWithOwnedErrorMsg(null, msg); |
| 35380 | } |
| 35381 | defer struct_type.clearInitsWip(ip); |
| 35382 | |
| 35383 | try semaStructFieldInits(mod, sema.arena, struct_type); |
| 35384 | struct_type.setHaveFieldInits(ip); |
| 35385 | } |
| 35386 | |
| 35332 | 35387 | pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Key.UnionType) CompileError!void { |
| 35333 | 35388 | const mod = sema.mod; |
| 35334 | 35389 | const ip = &mod.intern_pool; |
| ... | ... | @@ -35510,24 +35565,18 @@ fn resolveInferredErrorSetTy( |
| 35510 | 35565 | } |
| 35511 | 35566 | } |
| 35512 | 35567 | |
| 35513 | | fn semaStructFields( |
| 35514 | | mod: *Module, |
| 35515 | | arena: Allocator, |
| 35516 | | struct_type: InternPool.Key.StructType, |
| 35517 | | ) CompileError!void { |
| 35518 | | const gpa = mod.gpa; |
| 35519 | | const ip = &mod.intern_pool; |
| 35520 | | const decl_index = struct_type.decl.unwrap() orelse return; |
| 35521 | | const decl = mod.declPtr(decl_index); |
| 35522 | | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 35523 | | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 35524 | | const zir_index = struct_type.zir_index; |
| 35568 | fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { |
| 35569 | /// fields_len |
| 35570 | usize, |
| 35571 | Zir.Inst.StructDecl.Small, |
| 35572 | /// extra_index |
| 35573 | usize, |
| 35574 | } { |
| 35525 | 35575 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 35526 | 35576 | assert(extended.opcode == .struct_decl); |
| 35527 | 35577 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| 35528 | 35578 | var extra_index: usize = extended.operand; |
| 35529 | 35579 | |
| 35530 | | const src = LazySrcLoc.nodeOffset(0); |
| 35531 | 35580 | extra_index += @intFromBool(small.has_src_node); |
| 35532 | 35581 | |
| 35533 | 35582 | const fields_len = if (small.has_fields_len) blk: { |
| ... | ... | @@ -35558,6 +35607,25 @@ fn semaStructFields( |
| 35558 | 35607 | while (decls_it.next()) |_| {} |
| 35559 | 35608 | extra_index = decls_it.extra_index; |
| 35560 | 35609 | |
| 35610 | return .{ fields_len, small, extra_index }; |
| 35611 | } |
| 35612 | |
| 35613 | fn semaStructFields( |
| 35614 | mod: *Module, |
| 35615 | arena: Allocator, |
| 35616 | struct_type: InternPool.Key.StructType, |
| 35617 | ) CompileError!void { |
| 35618 | const gpa = mod.gpa; |
| 35619 | const ip = &mod.intern_pool; |
| 35620 | const decl_index = struct_type.decl.unwrap() orelse return; |
| 35621 | const decl = mod.declPtr(decl_index); |
| 35622 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 35623 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 35624 | const zir_index = struct_type.zir_index; |
| 35625 | |
| 35626 | const src = LazySrcLoc.nodeOffset(0); |
| 35627 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 35628 | |
| 35561 | 35629 | if (fields_len == 0) switch (struct_type.layout) { |
| 35562 | 35630 | .Packed => { |
| 35563 | 35631 | try semaBackingIntType(mod, struct_type); |
| ... | ... | @@ -35685,7 +35753,6 @@ fn semaStructFields( |
| 35685 | 35753 | |
| 35686 | 35754 | // Next we do only types and alignments, saving the inits for a second pass, |
| 35687 | 35755 | // so that init values may depend on type layout. |
| 35688 | | const bodies_index = extra_index; |
| 35689 | 35756 | |
| 35690 | 35757 | for (fields, 0..) |zir_field, field_i| { |
| 35691 | 35758 | const field_ty: Type = ty: { |
| ... | ... | @@ -35809,44 +35876,161 @@ fn semaStructFields( |
| 35809 | 35876 | extra_index += zir_field.init_body_len; |
| 35810 | 35877 | } |
| 35811 | 35878 | |
| 35812 | | // TODO: there seems to be no mechanism to catch when an init depends on |
| 35813 | | // another init that hasn't been resolved. |
| 35879 | struct_type.clearTypesWip(ip); |
| 35880 | if (!any_inits) struct_type.setHaveFieldInits(ip); |
| 35881 | |
| 35882 | for (comptime_mutable_decls.items) |ct_decl_index| { |
| 35883 | const ct_decl = mod.declPtr(ct_decl_index); |
| 35884 | _ = try ct_decl.internValue(mod); |
| 35885 | } |
| 35886 | } |
| 35887 | |
| 35888 | // This logic must be kept in sync with `semaStructFields` |
| 35889 | fn semaStructFieldInits( |
| 35890 | mod: *Module, |
| 35891 | arena: Allocator, |
| 35892 | struct_type: InternPool.Key.StructType, |
| 35893 | ) CompileError!void { |
| 35894 | const gpa = mod.gpa; |
| 35895 | const ip = &mod.intern_pool; |
| 35896 | |
| 35897 | assert(!struct_type.haveFieldInits(ip)); |
| 35898 | |
| 35899 | const decl_index = struct_type.decl.unwrap() orelse return; |
| 35900 | const decl = mod.declPtr(decl_index); |
| 35901 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 35902 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 35903 | const zir_index = struct_type.zir_index; |
| 35904 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 35905 | |
| 35906 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); |
| 35907 | defer comptime_mutable_decls.deinit(); |
| 35908 | |
| 35909 | var sema: Sema = .{ |
| 35910 | .mod = mod, |
| 35911 | .gpa = gpa, |
| 35912 | .arena = arena, |
| 35913 | .code = zir, |
| 35914 | .owner_decl = decl, |
| 35915 | .owner_decl_index = decl_index, |
| 35916 | .func_index = .none, |
| 35917 | .func_is_naked = false, |
| 35918 | .fn_ret_ty = Type.void, |
| 35919 | .fn_ret_ty_ies = null, |
| 35920 | .owner_func_index = .none, |
| 35921 | .comptime_mutable_decls = &comptime_mutable_decls, |
| 35922 | }; |
| 35923 | defer sema.deinit(); |
| 35924 | |
| 35925 | var block_scope: Block = .{ |
| 35926 | .parent = null, |
| 35927 | .sema = &sema, |
| 35928 | .src_decl = decl_index, |
| 35929 | .namespace = namespace_index, |
| 35930 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), |
| 35931 | .instructions = .{}, |
| 35932 | .inlining = null, |
| 35933 | .is_comptime = true, |
| 35934 | }; |
| 35935 | defer assert(block_scope.instructions.items.len == 0); |
| 35936 | |
| 35937 | const Field = struct { |
| 35938 | type_body_len: u32 = 0, |
| 35939 | align_body_len: u32 = 0, |
| 35940 | init_body_len: u32 = 0, |
| 35941 | }; |
| 35942 | const fields = try sema.arena.alloc(Field, fields_len); |
| 35943 | |
| 35944 | var any_inits = false; |
| 35945 | |
| 35946 | { |
| 35947 | const bits_per_field = 4; |
| 35948 | const fields_per_u32 = 32 / bits_per_field; |
| 35949 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; |
| 35950 | const flags_index = extra_index; |
| 35951 | var bit_bag_index: usize = flags_index; |
| 35952 | extra_index += bit_bags_count; |
| 35953 | var cur_bit_bag: u32 = undefined; |
| 35954 | var field_i: u32 = 0; |
| 35955 | while (field_i < fields_len) : (field_i += 1) { |
| 35956 | if (field_i % fields_per_u32 == 0) { |
| 35957 | cur_bit_bag = zir.extra[bit_bag_index]; |
| 35958 | bit_bag_index += 1; |
| 35959 | } |
| 35960 | const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; |
| 35961 | cur_bit_bag >>= 1; |
| 35962 | const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; |
| 35963 | cur_bit_bag >>= 2; |
| 35964 | const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; |
| 35965 | cur_bit_bag >>= 1; |
| 35966 | |
| 35967 | if (!small.is_tuple) { |
| 35968 | extra_index += 1; |
| 35969 | } |
| 35970 | extra_index += 1; // doc_comment |
| 35971 | |
| 35972 | fields[field_i] = .{}; |
| 35973 | |
| 35974 | if (has_type_body) fields[field_i].type_body_len = zir.extra[extra_index]; |
| 35975 | extra_index += 1; |
| 35976 | |
| 35977 | if (has_align) { |
| 35978 | fields[field_i].align_body_len = zir.extra[extra_index]; |
| 35979 | extra_index += 1; |
| 35980 | } |
| 35981 | if (has_init) { |
| 35982 | fields[field_i].init_body_len = zir.extra[extra_index]; |
| 35983 | extra_index += 1; |
| 35984 | any_inits = true; |
| 35985 | } |
| 35986 | } |
| 35987 | } |
| 35814 | 35988 | |
| 35815 | 35989 | if (any_inits) { |
| 35816 | | extra_index = bodies_index; |
| 35817 | 35990 | for (fields, 0..) |zir_field, field_i| { |
| 35818 | | const field_ty = struct_type.field_types.get(ip)[field_i].toType(); |
| 35819 | 35991 | extra_index += zir_field.type_body_len; |
| 35820 | 35992 | extra_index += zir_field.align_body_len; |
| 35821 | | if (zir_field.init_body_len > 0) { |
| 35822 | | const body = zir.bodySlice(extra_index, zir_field.init_body_len); |
| 35823 | | extra_index += body.len; |
| 35824 | | const init = try sema.resolveBody(&block_scope, body, zir_index); |
| 35825 | | const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) { |
| 35826 | | error.NeededSourceLocation => { |
| 35827 | | const init_src = mod.fieldSrcLoc(decl_index, .{ |
| 35828 | | .index = field_i, |
| 35829 | | .range = .value, |
| 35830 | | }).lazy; |
| 35831 | | _ = try sema.coerce(&block_scope, field_ty, init, init_src); |
| 35832 | | unreachable; |
| 35833 | | }, |
| 35834 | | else => |e| return e, |
| 35835 | | }; |
| 35836 | | const default_val = (try sema.resolveValue(coerced)) orelse { |
| 35993 | const body = zir.bodySlice(extra_index, zir_field.init_body_len); |
| 35994 | extra_index += zir_field.init_body_len; |
| 35995 | |
| 35996 | if (body.len == 0) continue; |
| 35997 | |
| 35998 | // Pre-populate the type mapping the body expects to be there. |
| 35999 | // In init bodies, the zir index of the struct itself is used |
| 36000 | // to refer to the current field type. |
| 36001 | |
| 36002 | const field_ty = struct_type.field_types.get(ip)[field_i].toType(); |
| 36003 | const type_ref = Air.internedToRef(field_ty.toIntern()); |
| 36004 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index}); |
| 36005 | sema.inst_map.putAssumeCapacity(zir_index, type_ref); |
| 36006 | |
| 36007 | const init = try sema.resolveBody(&block_scope, body, zir_index); |
| 36008 | const coerced = sema.coerce(&block_scope, field_ty, init, .unneeded) catch |err| switch (err) { |
| 36009 | error.NeededSourceLocation => { |
| 35837 | 36010 | const init_src = mod.fieldSrcLoc(decl_index, .{ |
| 35838 | 36011 | .index = field_i, |
| 35839 | 36012 | .range = .value, |
| 35840 | 36013 | }).lazy; |
| 35841 | | return sema.failWithNeededComptime(&block_scope, init_src, .{ |
| 35842 | | .needed_comptime_reason = "struct field default value must be comptime-known", |
| 35843 | | }); |
| 35844 | | }; |
| 35845 | | const field_init = try default_val.intern(field_ty, mod); |
| 35846 | | struct_type.field_inits.get(ip)[field_i] = field_init; |
| 35847 | | } |
| 36014 | _ = try sema.coerce(&block_scope, field_ty, init, init_src); |
| 36015 | unreachable; |
| 36016 | }, |
| 36017 | else => |e| return e, |
| 36018 | }; |
| 36019 | const default_val = (try sema.resolveValue(coerced)) orelse { |
| 36020 | const init_src = mod.fieldSrcLoc(decl_index, .{ |
| 36021 | .index = field_i, |
| 36022 | .range = .value, |
| 36023 | }).lazy; |
| 36024 | return sema.failWithNeededComptime(&block_scope, init_src, .{ |
| 36025 | .needed_comptime_reason = "struct field default value must be comptime-known", |
| 36026 | }); |
| 36027 | }; |
| 36028 | |
| 36029 | const field_init = try default_val.intern(field_ty, mod); |
| 36030 | struct_type.field_inits.get(ip)[field_i] = field_init; |
| 35848 | 36031 | } |
| 35849 | 36032 | } |
| 36033 | |
| 35850 | 36034 | for (comptime_mutable_decls.items) |ct_decl_index| { |
| 35851 | 36035 | const ct_decl = mod.declPtr(ct_decl_index); |
| 35852 | 36036 | _ = try ct_decl.internValue(mod); |
| ... | ... | @@ -36674,6 +36858,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36674 | 36858 | ); |
| 36675 | 36859 | for (field_vals, 0..) |*field_val, i| { |
| 36676 | 36860 | if (struct_type.fieldIsComptime(ip, i)) { |
| 36861 | try sema.resolveStructFieldInits(ty); |
| 36677 | 36862 | field_val.* = struct_type.field_inits.get(ip)[i]; |
| 36678 | 36863 | continue; |
| 36679 | 36864 | } |