authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-29 18:44:25+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:08+00:00
log650185692dc6fb6b9c2c4e591d37cb94410972e1
tree0d70c9462da40fe604cb674a17e5ea4b5ae1f564
parent8eefe86939e917e4e85049325bff8c5a43f50f95
signature Commit is signed but in an unrecognized format.

compiler: merge struct default value resolution into layout resolution

This actually doesn't cause any dependency loops in std, which is pretty much my benchmark for it being acceptable. This can be reverted if it turns out to be problematic, but for now, let's err on the side of language simplicity. To be clear, this *does* regress some cases which previously worked: I will have to remove some behavior tests as a result of this commit. To be honest, the tests which look to be failing as a result of this are things which I think are generally unadvisable; I actually reckon a bit more friction to use default field values in non-trivial ways might be a good thing to stop people from misusing them as much. Struct fields should very rarely have default values; about the only common situation where they make sense is "options" structs.

15 files changed, 120 insertions(+), 422 deletions(-)

src/Air/Liveness.zig+4-4
......@@ -153,8 +153,8 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li
153153 usize,
154154 (air.instructions.len * bpi + @bitSizeOf(usize) - 1) / @bitSizeOf(usize),
155155 ),
156 .extra = .{},
157 .special = .{},
156 .extra = .empty,
157 .special = .empty,
158158 .intern_pool = intern_pool,
159159 };
160160 errdefer gpa.free(a.tomb_bits);
......@@ -175,7 +175,7 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li
175175 var data: LivenessPassData(.main_analysis) = .{};
176176 defer data.deinit(gpa);
177177 data.old_extra = a.extra;
178 a.extra = .{};
178 a.extra = .empty;
179179 try analyzeBody(&a, .main_analysis, &data, main_body);
180180 assert(data.live_set.count() == 0);
181181 }
......@@ -1360,7 +1360,7 @@ fn analyzeInstSwitchBr(
13601360 const mirrored_deaths = try gpa.alloc(DeathList, ncases + 1);
13611361 defer gpa.free(mirrored_deaths);
13621362
1363 @memset(mirrored_deaths, .{});
1363 @memset(mirrored_deaths, .empty);
13641364 defer for (mirrored_deaths) |*md| md.deinit(gpa);
13651365
13661366 {
src/Compilation.zig+2-7
......@@ -3713,7 +3713,6 @@ const Header = extern struct {
37133713 nav_val_deps_len: u32,
37143714 nav_ty_deps_len: u32,
37153715 type_layout_deps_len: u32,
3716 struct_defaults_deps_len: u32,
37173716 func_ies_deps_len: u32,
37183717 zon_file_deps_len: u32,
37193718 embed_file_deps_len: u32,
......@@ -3763,7 +3762,6 @@ pub fn saveState(comp: *Compilation) !void {
37633762 .nav_val_deps_len = @intCast(ip.nav_val_deps.count()),
37643763 .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()),
37653764 .type_layout_deps_len = @intCast(ip.type_layout_deps.count()),
3766 .struct_defaults_deps_len = @intCast(ip.struct_defaults_deps.count()),
37673765 .func_ies_deps_len = @intCast(ip.func_ies_deps.count()),
37683766 .zon_file_deps_len = @intCast(ip.zon_file_deps.count()),
37693767 .embed_file_deps_len = @intCast(ip.embed_file_deps.count()),
......@@ -3788,7 +3786,7 @@ pub fn saveState(comp: *Compilation) !void {
37883786 },
37893787 });
37903788
3791 try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len);
3789 try bufs.ensureTotalCapacityPrecise(24 + 9 * pt_headers.items.len);
37923790 addBuf(&bufs, mem.asBytes(&header));
37933791 addBuf(&bufs, @ptrCast(pt_headers.items));
37943792
......@@ -3800,8 +3798,6 @@ pub fn saveState(comp: *Compilation) !void {
38003798 addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values()));
38013799 addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys()));
38023800 addBuf(&bufs, @ptrCast(ip.type_layout_deps.values()));
3803 addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.keys()));
3804 addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.values()));
38053801 addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys()));
38063802 addBuf(&bufs, @ptrCast(ip.func_ies_deps.values()));
38073803 addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys()));
......@@ -4481,7 +4477,7 @@ pub fn addModuleErrorMsg(
44814477 const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) {
44824478 .@"comptime" => "comptime",
44834479 .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
4484 .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
4480 .type_layout => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
44854481 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
44864482 .memoized_state => null,
44874483 };
......@@ -5251,7 +5247,6 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
52515247 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav),
52525248 .nav_val => |nav| pt.ensureNavValUpToDate(nav),
52535249 .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)),
5254 .struct_defaults => |ty| pt.ensureStructDefaultsUpToDate(.fromInterned(ty)),
52555250 .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage),
52565251 .func => |func| pt.ensureFuncBodyUpToDate(func),
52575252 };
src/IncrementalDebugServer.zig+1-3
......@@ -307,7 +307,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
307307 switch (dependee) {
308308 .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}),
309309 .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }),
310 .type_layout, .struct_defaults, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }),
310 .type_layout, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }),
311311 .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}),
312312 }
313313 try w.writeByte('\n');
......@@ -374,8 +374,6 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit {
374374 return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) });
375375 } else if (std.mem.eql(u8, kind, "type_layout")) {
376376 return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) });
377 } else if (std.mem.eql(u8, kind, "struct_defaults")) {
378 return .wrap(.{ .struct_defaults = @enumFromInt(parseIndex(idx_str) orelse return null) });
379377 } else if (std.mem.eql(u8, kind, "func")) {
380378 return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) });
381379 } else if (std.mem.eql(u8, kind, "memoized_state")) {
src/InternPool.zig+5-82
......@@ -54,9 +54,6 @@ func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
5454/// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type.
5555/// Value is index into `dep_entries` of the first dependency on this type's layout.
5656type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
57/// Dependencies on the resolved default field values of a `struct` type.
58/// Value is index into `dep_entries` of the first dependency on this type's inits.
59struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
6057/// Dependencies on a ZON file. Triggered by `@import` of ZON.
6158/// Value is index into `dep_entries` of the first dependency on this ZON file.
6259zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index),
......@@ -111,7 +108,6 @@ pub const empty: InternPool = .{
111108 .nav_ty_deps = .empty,
112109 .func_ies_deps = .empty,
113110 .type_layout_deps = .empty,
114 .struct_defaults_deps = .empty,
115111 .zon_file_deps = .empty,
116112 .embed_file_deps = .empty,
117113 .namespace_deps = .empty,
......@@ -423,7 +419,6 @@ pub const AnalUnit = packed struct(u64) {
423419 nav_val,
424420 nav_ty,
425421 type_layout,
426 struct_defaults,
427422 func,
428423 memoized_state,
429424 };
......@@ -437,8 +432,6 @@ pub const AnalUnit = packed struct(u64) {
437432 nav_ty: Nav.Index,
438433 /// This `AnalUnit` resolves the layout of the given `struct`, `union`, or `enum` type.
439434 type_layout: InternPool.Index,
440 /// This `AnalUnit` resolves the default field values of the given `struct` type.
441 struct_defaults: InternPool.Index,
442435 /// This `AnalUnit` analyzes the body of the given runtime function.
443436 func: InternPool.Index,
444437 /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`.
......@@ -858,7 +851,6 @@ pub const Dependee = union(enum) {
858851 /// Index is the function, not its IES.
859852 func_ies: Index,
860853 type_layout: Index,
861 struct_defaults: Index,
862854 zon_file: FileIndex,
863855 embed_file: Zcu.EmbedFile.Index,
864856 namespace: TrackedInst.Index,
......@@ -912,7 +904,6 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
912904 .nav_ty => |x| ip.nav_ty_deps.get(x),
913905 .func_ies => |x| ip.func_ies_deps.get(x),
914906 .type_layout => |x| ip.type_layout_deps.get(x),
915 .struct_defaults => |x| ip.struct_defaults_deps.get(x),
916907 .zon_file => |x| ip.zon_file_deps.get(x),
917908 .embed_file => |x| ip.embed_file_deps.get(x),
918909 .namespace => |x| ip.namespace_deps.get(x),
......@@ -987,7 +978,6 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
987978 .nav_ty => ip.nav_ty_deps,
988979 .func_ies => ip.func_ies_deps,
989980 .type_layout => ip.type_layout_deps,
990 .struct_defaults => ip.struct_defaults_deps,
991981 .zon_file => ip.zon_file_deps,
992982 .embed_file => ip.embed_file_deps,
993983 .namespace => ip.namespace_deps,
......@@ -3326,15 +3316,6 @@ pub const LoadedStructType = struct {
33263316 /// compiler frontend resolves this by traversing the reference graph at the end of each update
33273317 /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis.
33283318 want_layout: bool,
3329 /// Initially `false`, and set to `true` once any dependency on or reference to the struct's
3330 /// default field values is encountered, after which it is never reset to `false`, even across
3331 /// incremental updates.
3332 ///
3333 /// This field is purely an optimization to avoid resolving the layout of types whose layouts
3334 /// are never demanded. If this field is `true` but the layout is not actually needed, the
3335 /// compiler frontend resolves this by traversing the reference graph at the end of each update
3336 /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis.
3337 want_defaults: bool,
33383319
33393320 // The remaining fields are only valid once the struct's layout is resolved.
33403321 field_name_map: MapIndex,
......@@ -3711,7 +3692,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
37113692 .packed_backing_mode = undefined,
37123693
37133694 .want_layout = extra.data.flags.want_layout,
3714 .want_defaults = extra.data.flags.want_defaults,
37153695
37163696 .field_name_map = extra.data.field_name_map,
37173697 .field_names = field_names,
......@@ -3772,7 +3752,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
37723752 .packed_backing_mode = backing_mode,
37733753
37743754 .want_layout = extra.data.bits.want_layout,
3775 .want_defaults = extra.data.bits.want_defaults,
37763755
37773756 .field_name_map = extra.data.field_name_map,
37783757 .field_names = field_names,
......@@ -5666,9 +5645,8 @@ pub const Tag = enum(u8) {
56665645 alignment: Alignment,
56675646
56685647 want_layout: bool,
5669 want_defaults: bool,
56705648
5671 _: u15 = 0,
5649 _: u16 = 0,
56725650 };
56735651 };
56745652
......@@ -5693,12 +5671,11 @@ pub const Tag = enum(u8) {
56935671 field_name_map: MapIndex,
56945672
56955673 const Bits = packed struct(u32) {
5696 captures_len: enum(u30) {
5697 reified = std.math.maxInt(u30),
5674 captures_len: enum(u31) {
5675 reified = std.math.maxInt(u31),
56985676 _,
56995677 },
57005678 want_layout: bool,
5701 want_defaults: bool,
57025679 };
57035680 };
57045681
......@@ -6477,7 +6454,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void {
64776454 ip.nav_ty_deps.deinit(gpa);
64786455 ip.func_ies_deps.deinit(gpa);
64796456 ip.type_layout_deps.deinit(gpa);
6480 ip.struct_defaults_deps.deinit(gpa);
64816457 ip.zon_file_deps.deinit(gpa);
64826458 ip.embed_file_deps.deinit(gpa);
64836459 ip.namespace_deps.deinit(gpa);
......@@ -8191,7 +8167,6 @@ pub fn getDeclaredStructType(
81918167 .bits = .{
81928168 .captures_len = @enumFromInt(ini.captures.len),
81938169 .want_layout = false,
8194 .want_defaults = false,
81958170 },
81968171 .name = undefined, // set by `finish`
81978172 .name_nav = undefined, // set by `finish`
......@@ -8256,7 +8231,6 @@ pub fn getDeclaredStructType(
82568231 .class = .no_possible_value,
82578232 .alignment = .none,
82588233 .want_layout = false,
8259 .want_defaults = false,
82608234 },
82618235 });
82628236 if (ini.captures.len != 0) {
......@@ -8337,7 +8311,6 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe
83378311 .bits = .{
83388312 .captures_len = .reified,
83398313 .want_layout = false,
8340 .want_defaults = false,
83418314 },
83428315 .name = undefined, // set by `finish`
83438316 .name_nav = undefined, // set by `finish`
......@@ -8407,7 +8380,6 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe
84078380 .class = .no_possible_value,
84088381 .alignment = .none,
84098382 .want_layout = false,
8410 .want_defaults = false,
84118383 },
84128384 });
84138385 _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash
......@@ -10647,7 +10619,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
1064710619 const nav_ty_deps_len = ip.nav_ty_deps.count();
1064810620 const func_ies_deps_len = ip.func_ies_deps.count();
1064910621 const type_layout_deps_len = ip.type_layout_deps.count();
10650 const struct_defaults_deps_len = ip.struct_defaults_deps.count();
1065110622 const zon_file_deps_len = ip.zon_file_deps.count();
1065210623 const embed_file_deps_len = ip.embed_file_deps.count();
1065310624 const namespace_deps_len = ip.namespace_deps.count();
......@@ -10658,7 +10629,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
1065810629 const nav_ty_deps_size = nav_ty_deps_len * 8;
1065910630 const func_ies_deps_size = func_ies_deps_len * 8;
1066010631 const type_layout_deps_size = type_layout_deps_len * 8;
10661 const struct_defaults_deps_size = struct_defaults_deps_len * 8;
1066210632 const zon_file_deps_size = zon_file_deps_len * 8;
1066310633 const embed_file_deps_size = embed_file_deps_len * 8;
1066410634 const namespace_deps_size = namespace_deps_len * 8;
......@@ -10672,7 +10642,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
1067210642 \\ {d} nav_ty: {d} bytes
1067310643 \\ {d} func_ies: {d} bytes
1067410644 \\ {d} type_layout: {d} bytes
10675 \\ {d} struct_defaults: {d} bytes
1067610645 \\ {d} zon_file: {d} bytes
1067710646 \\ {d} embed_file: {d} bytes
1067810647 \\ {d} namespace: {d} bytes
......@@ -10680,7 +10649,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
1068010649 \\
1068110650 , .{
1068210651 dep_entries_size + src_hash_deps_size + nav_val_deps_size + nav_ty_deps_size +
10683 func_ies_deps_size + type_layout_deps_size + struct_defaults_deps_size + zon_file_deps_size +
10652 func_ies_deps_size + type_layout_deps_size + zon_file_deps_size +
1068410653 embed_file_deps_size + namespace_deps_size + namespace_name_deps_size,
1068510654 dep_entries_len,
1068610655 dep_entries_size,
......@@ -10694,8 +10663,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
1069410663 func_ies_deps_size,
1069510664 type_layout_deps_len,
1069610665 type_layout_deps_size,
10697 struct_defaults_deps_len,
10698 struct_defaults_deps_size,
1069910666 zon_file_deps_len,
1070010667 zon_file_deps_size,
1070110668 embed_file_deps_len,
......@@ -11136,7 +11103,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator,
1113611103 const info = extraData(extra_list, Tag.FuncInstance, data);
1113711104
1113811105 const gop = try instances.getOrPut(arena, info.generic_owner);
11139 if (!gop.found_existing) gop.value_ptr.* = .{};
11106 if (!gop.found_existing) gop.value_ptr.* = .empty;
1114011107
1114111108 try gop.value_ptr.append(
1114211109 arena,
......@@ -12969,50 +12936,6 @@ pub fn setWantTypeLayout(ip: *InternPool, io: Io, container_type: Index) bool {
1296912936 }
1297012937}
1297112938
12972/// Like `setWantTypeLayout`, but for the default field values of a struct (so this sets the
12973/// `want_defaults` flag rather than the `want_layout` flag).
12974pub fn setWantStructDefaults(ip: *InternPool, io: Io, struct_type: Index) bool {
12975 const unwrapped_index = struct_type.unwrap(ip);
12976
12977 const local = ip.getLocal(unwrapped_index.tid);
12978 local.mutate.extra.mutex.lockUncancelable(io);
12979 defer local.mutate.extra.mutex.unlock(io);
12980
12981 const extra_items = local.shared.extra.view().items(.@"0");
12982 const item = unwrapped_index.getItem(ip);
12983 switch (item.tag) {
12984 .type_struct_packed_auto,
12985 .type_struct_packed_explicit,
12986 .type_struct_packed_auto_defaults,
12987 .type_struct_packed_explicit_defaults,
12988 => {
12989 const bits: *Tag.TypeStructPacked.Bits = @ptrCast(&extra_items[
12990 item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "bits").?
12991 ]);
12992 if (bits.want_defaults) {
12993 return false;
12994 } else {
12995 bits.want_defaults = true;
12996 return true;
12997 }
12998 },
12999
13000 .type_struct => {
13001 const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[
13002 item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?
13003 ]);
13004 if (flags.want_defaults) {
13005 return false;
13006 } else {
13007 flags.want_defaults = true;
13008 return true;
13009 }
13010 },
13011
13012 else => unreachable,
13013 }
13014}
13015
1301612939/// Like `setWantTypeLayout`, but for runtime analysis of a function body, using the
1301712940/// `FuncAnalysis.want_runtime_analysis` flag.
1301812941pub fn setWantRuntimeFnAnalysis(ip: *InternPool, io: Io, func_index: Index) bool {
src/Sema.zig+29-39
......@@ -4519,10 +4519,6 @@ fn validateStructInit(
45194519 if (explicit) continue;
45204520 if (struct_ty.structFieldIsComptime(i, zcu)) continue;
45214521
4522 if (!struct_ty.isTuple(zcu)) {
4523 try sema.ensureStructDefaultsResolved(struct_ty, init_src);
4524 }
4525
45264522 const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse {
45274523 const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse {
45284524 const template = "missing tuple field with index {d}";
......@@ -5180,9 +5176,9 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
51805176 var label: Block.Label = .{
51815177 .zir_block = inst,
51825178 .merges = .{
5183 .src_locs = .{},
5184 .results = .{},
5185 .br_list = .{},
5179 .src_locs = .empty,
5180 .results = .empty,
5181 .br_list = .empty,
51865182 .block_inst = block_inst,
51875183 },
51885184 };
......@@ -5254,7 +5250,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
52545250 .parent = parent_block,
52555251 .sema = sema,
52565252 .namespace = parent_block.namespace,
5257 .instructions = .{},
5253 .instructions = .empty,
52585254 .inlining = parent_block.inlining,
52595255 .comptime_reason = .{ .reason = .{
52605256 .src = src,
......@@ -5389,9 +5385,9 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
53895385 var label: Block.Label = .{
53905386 .zir_block = inst,
53915387 .merges = .{
5392 .src_locs = .{},
5393 .results = .{},
5394 .br_list = .{},
5388 .src_locs = .empty,
5389 .results = .empty,
5390 .br_list = .empty,
53955391 .block_inst = block_inst,
53965392 },
53975393 };
......@@ -5400,7 +5396,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
54005396 .parent = parent_block,
54015397 .sema = sema,
54025398 .namespace = parent_block.namespace,
5403 .instructions = .{},
5399 .instructions = .empty,
54045400 .label = &label,
54055401 .inlining = parent_block.inlining,
54065402 .comptime_reason = parent_block.comptime_reason,
......@@ -5839,7 +5835,6 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
58395835 .nav_val,
58405836 .nav_ty,
58415837 .type_layout,
5842 .struct_defaults,
58435838 .memoized_state,
58445839 => return, // does nothing outside a function
58455840 };
......@@ -5858,7 +5853,6 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
58585853 .nav_val,
58595854 .nav_ty,
58605855 .type_layout,
5861 .struct_defaults,
58625856 .memoized_state,
58635857 => return, // does nothing outside a function
58645858 };
......@@ -6870,7 +6864,7 @@ fn analyzeCall(
68706864 .parent = null,
68716865 .sema = sema,
68726866 .namespace = fn_nav.analysis.?.namespace,
6873 .instructions = .{},
6867 .instructions = .empty,
68746868 .inlining = &generic_inlining,
68756869 .src_base_inst = fn_nav.analysis.?.zir_index,
68766870 .type_name_ctx = fn_nav.fqn,
......@@ -7067,7 +7061,7 @@ fn analyzeCall(
70677061 });
70687062 if (func_ty_info.cc == .auto) {
70697063 switch (sema.owner.unwrap()) {
7070 .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {},
7064 .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {},
70717065 .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true),
70727066 }
70737067 }
......@@ -7382,7 +7376,7 @@ fn analyzeCall(
73827376 .parent = null,
73837377 .sema = sema,
73847378 .namespace = fn_nav.analysis.?.namespace,
7385 .instructions = .{},
7379 .instructions = .empty,
73867380 .inlining = &inlining,
73877381 .is_typeof = block.is_typeof,
73887382 .comptime_reason = if (block.isComptime()) .inlining_parent else null,
......@@ -9945,9 +9939,9 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
99459939 var label: Block.Label = .{
99469940 .zir_block = inst,
99479941 .merges = .{
9948 .src_locs = .{},
9949 .results = .{},
9950 .br_list = .{},
9942 .src_locs = .empty,
9943 .results = .empty,
9944 .br_list = .empty,
99519945 .block_inst = block_inst,
99529946 },
99539947 };
......@@ -10100,9 +10094,9 @@ fn zirSwitchBlock(
1010010094 var label: Block.Label = .{
1010110095 .zir_block = inst,
1010210096 .merges = .{
10103 .src_locs = .{},
10104 .results = .{},
10105 .br_list = .{},
10097 .src_locs = .empty,
10098 .results = .empty,
10099 .br_list = .empty,
1010610100 .block_inst = block_inst,
1010710101 },
1010810102 };
......@@ -16864,7 +16858,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1686416858 .struct_type => ip.loadStructType(ty.toIntern()),
1686516859 else => unreachable,
1686616860 };
16867 try sema.ensureStructDefaultsResolved(ty, src); // can't do this sooner, since it's not allowed on tuples
1686816861 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);
1686916862
1687016863 for (struct_field_vals, 0..) |*field_val, field_index| {
......@@ -17122,7 +17115,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1712217115 .parent = block,
1712317116 .sema = sema,
1712417117 .namespace = block.namespace,
17125 .instructions = .{},
17118 .instructions = .empty,
1712617119 .inlining = block.inlining,
1712717120 .comptime_reason = null,
1712817121 .is_typeof = true,
......@@ -17190,7 +17183,7 @@ fn zirTypeofPeer(
1719017183 .parent = block,
1719117184 .sema = sema,
1719217185 .namespace = block.namespace,
17193 .instructions = .{},
17186 .instructions = .empty,
1719417187 .inlining = block.inlining,
1719517188 .comptime_reason = null,
1719617189 .is_typeof = true,
......@@ -17764,9 +17757,9 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
1776417757 .label = .{
1776517758 .zir_block = dest_block,
1776617759 .merges = .{
17767 .src_locs = .{},
17768 .results = .{},
17769 .br_list = .{},
17760 .src_locs = .empty,
17761 .results = .empty,
17762 .br_list = .empty,
1777017763 .block_inst = new_block_inst,
1777117764 },
1777217765 },
......@@ -17774,7 +17767,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
1777417767 .parent = block,
1777517768 .sema = sema,
1777617769 .namespace = block.namespace,
17777 .instructions = .{},
17770 .instructions = .empty,
1777817771 .label = &labeled_block.label,
1777917772 .inlining = block.inlining,
1778017773 .comptime_reason = block.comptime_reason,
......@@ -18753,8 +18746,6 @@ fn finishStructInit(
1875318746 continue;
1875418747 }
1875518748
18756 try sema.ensureStructDefaultsResolved(struct_ty, init_src);
18757
1875818749 const field_default: InternPool.Index = d: {
1875918750 if (struct_type.field_defaults.len == 0) break :d .none;
1876018751 break :d struct_type.field_defaults.get(ip)[i];
......@@ -19420,7 +19411,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1942019411 .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) {
1942119412 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
1942219413 },
19423 .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {},
19414 .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {},
1942419415 }
1942519416 return Air.internedToRef(try pt.intern(.{ .opt = .{
1942619417 .ty = opt_ptr_stack_trace_ty.toIntern(),
......@@ -24738,7 +24729,7 @@ fn zirBuiltinExtern(
2473824729 // So, for now, just use our containing `declaration`.
2473924730 .zir_index = switch (sema.owner.unwrap()) {
2474024731 .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
24741 .type_layout, .struct_defaults => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?,
24732 .type_layout => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?,
2474224733 .memoized_state => unreachable,
2474324734 .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
2474424735 .func => |func| zir_index: {
......@@ -25230,7 +25221,7 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In
2523025221 try sema.ensureMemoizedStateResolved(src, .panic);
2523125222 const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin());
2523225223 switch (sema.owner.unwrap()) {
25233 .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {},
25224 .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {},
2523425225 .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true),
2523525226 }
2523625227 return panic_fn_index;
......@@ -25250,7 +25241,7 @@ fn addSafetyCheck(
2525025241 .parent = parent_block,
2525125242 .sema = sema,
2525225243 .namespace = parent_block.namespace,
25253 .instructions = .{},
25244 .instructions = .empty,
2525425245 .inlining = parent_block.inlining,
2525525246 .comptime_reason = null,
2525625247 .src_base_inst = parent_block.src_base_inst,
......@@ -25344,7 +25335,7 @@ fn addSafetyCheckUnwrapError(
2534425335 .parent = parent_block,
2534525336 .sema = sema,
2534625337 .namespace = parent_block.namespace,
25347 .instructions = .{},
25338 .instructions = .empty,
2534825339 .inlining = parent_block.inlining,
2534925340 .comptime_reason = null,
2535025341 .src_base_inst = parent_block.src_base_inst,
......@@ -25449,7 +25440,7 @@ fn addSafetyCheckCall(
2544925440 .parent = parent_block,
2545025441 .sema = sema,
2545125442 .namespace = parent_block.namespace,
25452 .instructions = .{},
25443 .instructions = .empty,
2545325444 .inlining = parent_block.inlining,
2545425445 .comptime_reason = null,
2545525446 .src_base_inst = parent_block.src_base_inst,
......@@ -33859,7 +33850,6 @@ const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStor
3385933850
3386033851pub const type_resolution = @import("Sema/type_resolution.zig");
3386133852pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved;
33862pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved;
3386333853
3386433854pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type {
3386533855 assert(decl.kind() == .type);
src/Sema/LowerZon.zig-1
......@@ -770,7 +770,6 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
770770 const ip = &pt.zcu.intern_pool;
771771
772772 try self.sema.ensureLayoutResolved(res_ty, self.import_loc);
773 try self.sema.ensureStructDefaultsResolved(res_ty, self.import_loc);
774773 const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?;
775774
776775 const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {
src/Sema/type_resolution.zig+45-144
......@@ -85,30 +85,6 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!vo
8585 }
8686}
8787
88/// Asserts that `ty` is a non-tuple `struct` type, and ensures that its fields' default values
89/// are resolved. Adds incremental dependencies tracking the required type resolution.
90///
91/// It is not necessary to call this function to query the values of comptime fields: those values
92/// are available from type *layout* resolution, see `ensureLayoutResolved`.
93pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void {
94 const pt = sema.pt;
95 const zcu = pt.zcu;
96 const ip = &zcu.intern_pool;
97 assert(ip.indexToKey(ty.toIntern()) == .struct_type);
98
99 try sema.declareDependency(.{ .struct_defaults = ty.toIntern() });
100 try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() }));
101 if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) {
102 // TODO: better error message
103 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(
104 ty.srcLoc(zcu),
105 "struct '{f}' depends on itself",
106 .{ty.fmt(pt)},
107 ));
108 }
109 try pt.ensureStructDefaultsUpToDate(ty);
110}
111
11288/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.
11389/// This function *does* register the `src_hash` dependency on the struct.
11490pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
......@@ -129,7 +105,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
129105 .parent = null,
130106 .sema = sema,
131107 .namespace = struct_obj.namespace,
132 .instructions = .{},
108 .instructions = .empty,
133109 .inlining = null,
134110 .comptime_reason = undefined, // always set before using `block`
135111 .src_base_inst = struct_obj.zir_index,
......@@ -168,6 +144,13 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
168144 @memset(struct_obj.field_is_comptime_bits.getAll(ip), 0);
169145
170146 const zir_struct = sema.code.getStructDecl(zir_index);
147
148 // If we have any default values to resolve, we'll need to map the struct decl instruction
149 // to the result type.
150 if (zir_struct.field_default_body_lens != null) {
151 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
152 }
153
171154 var field_it = zir_struct.iterateFields();
172155 while (field_it.next()) |zir_field| {
173156 {
......@@ -182,18 +165,16 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
182165 struct_obj.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask;
183166 }
184167
185 {
168 const field_ty: Type = field_ty: {
186169 const field_ty_src = block.src(.{ .container_field_type = zir_field.idx });
187 const field_ty: Type = field_ty: {
188 block.comptime_reason = .{ .reason = .{
189 .src = field_ty_src,
190 .r = .{ .simple = .struct_field_types },
191 } };
192 const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index);
193 break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref);
194 };
195 struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
196 }
170 block.comptime_reason = .{ .reason = .{
171 .src = field_ty_src,
172 .r = .{ .simple = .struct_field_types },
173 } };
174 const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index);
175 break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref);
176 };
177 struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
197178
198179 if (struct_obj.field_aligns.len == 0) {
199180 assert(zir_field.align_body == null);
......@@ -210,6 +191,31 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
210191 };
211192 struct_obj.field_aligns.get(ip)[zir_field.idx] = field_align;
212193 }
194
195 if (struct_obj.field_defaults.len == 0) {
196 assert(zir_field.default_body == null);
197 } else {
198 const field_default_src = block.src(.{ .container_field_value = zir_field.idx });
199 const field_default: InternPool.Index = d: {
200 block.comptime_reason = .{ .reason = .{
201 .src = field_default_src,
202 .r = .{ .simple = .struct_field_default_value },
203 } };
204 const default_body = zir_field.default_body orelse break :d .none;
205 // Provide the result type
206 sema.inst_map.putAssumeCapacity(zir_index, .fromType(field_ty));
207 defer assert(sema.inst_map.remove(zir_index));
208 const uncoerced_default_val = try sema.resolveInlineBody(&block, default_body, zir_index);
209 const coerced_default_val = try sema.coerce(&block, field_ty, uncoerced_default_val, field_default_src);
210 const default_val = try sema.resolveConstValue(&block, field_default_src, coerced_default_val, null);
211 if (default_val.canMutateComptimeVarState(zcu)) {
212 const field_name = struct_obj.field_names.get(ip)[zir_field.idx];
213 return sema.failWithContainsReferenceToComptimeVar(&block, field_default_src, field_name, "field default value", default_val);
214 }
215 break :d default_val.toIntern();
216 };
217 struct_obj.field_defaults.get(ip)[zir_field.idx] = field_default;
218 }
213219 }
214220 }
215221
......@@ -357,11 +363,6 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
357363 struct_align,
358364 class,
359365 );
360
361 if (any_comptime_fields and !struct_obj.is_reified) {
362 // We also resolve field inits in this case. MLUGG TODO: this sucks, see TODO in resolveStructDefaults
363 return resolveStructDefaultsInner(sema, &block, &struct_obj);
364 }
365366}
366367
367368/// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type.
......@@ -465,105 +466,6 @@ fn resolvePackedStructLayout(
465466 );
466467}
467468
468/// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type.
469/// This function *does* register the `src_hash` dependency on the struct.
470pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
471 const pt = sema.pt;
472 const zcu = pt.zcu;
473 const comp = zcu.comp;
474 const gpa = comp.gpa;
475 const ip = &zcu.intern_pool;
476
477 assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern());
478
479 try sema.ensureLayoutResolved(struct_ty, struct_ty.srcLoc(zcu));
480
481 const struct_obj = ip.loadStructType(struct_ty.toIntern());
482 assert(struct_obj.want_defaults);
483
484 if (struct_obj.is_reified) {
485 // `Sema.zirReifyStruct` has already populated the default field values *and* (by loading
486 // the default values from pointers) validated their types, so we have nothing to do. We
487 // don't even need to mark any dependencies.
488 return;
489 }
490
491 try sema.declareDependency(.{ .src_hash = struct_obj.zir_index });
492
493 if (struct_obj.field_defaults.len == 0) {
494 // The struct has no default field values, so the slice has been omitted.
495 return;
496 }
497
498 for (struct_obj.field_is_comptime_bits.getAll(ip)) |bit_bag| {
499 if (bit_bag != 0) {
500 // There is a comptime field, so layout resolution already filled in the defaults for us!
501 // MLUGG TODO: perhaps a better idea would be for layout resolution to populate only the defaults *for comptime fields*.
502 return;
503 }
504 }
505
506 var block: Block = .{
507 .parent = null,
508 .sema = sema,
509 .namespace = struct_obj.namespace,
510 .instructions = .{},
511 .inlining = null,
512 .comptime_reason = undefined, // always set before using `block`
513 .src_base_inst = struct_obj.zir_index,
514 .type_name_ctx = struct_obj.name,
515 };
516 defer block.instructions.deinit(gpa);
517
518 return resolveStructDefaultsInner(sema, &block, &struct_obj);
519}
520/// MLUGG TODO: i dislike this, see the 'TODO' in the prev func
521fn resolveStructDefaultsInner(
522 sema: *Sema,
523 block: *Block,
524 struct_obj: *const InternPool.LoadedStructType,
525) CompileError!void {
526 const pt = sema.pt;
527 const zcu = pt.zcu;
528 const comp = zcu.comp;
529 const gpa = comp.gpa;
530 const ip = &zcu.intern_pool;
531
532 // We'll need to map the struct decl instruction to provide result types
533 const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
534 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
535
536 const field_types = struct_obj.field_types.get(ip);
537
538 const zir_struct = sema.code.getStructDecl(zir_index);
539 var field_it = zir_struct.iterateFields();
540 while (field_it.next()) |zir_field| {
541 const default_val_src = block.src(.{ .container_field_value = zir_field.idx });
542 block.comptime_reason = .{ .reason = .{
543 .src = default_val_src,
544 .r = .{ .simple = .struct_field_default_value },
545 } };
546 const default_body = zir_field.default_body orelse {
547 struct_obj.field_defaults.get(ip)[zir_field.idx] = .none;
548 continue;
549 };
550 const field_ty: Type = .fromInterned(field_types[zir_field.idx]);
551 const uncoerced = ref: {
552 // Provide the result type
553 sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern()));
554 defer assert(sema.inst_map.remove(zir_index));
555 break :ref try sema.resolveInlineBody(block, default_body, zir_index);
556 };
557 const coerced = try sema.coerce(block, field_ty, uncoerced, default_val_src);
558 const default_val = try sema.resolveConstValue(block, default_val_src, coerced, null);
559 if (default_val.canMutateComptimeVarState(zcu)) {
560 const field_name = struct_obj.field_names.get(ip)[zir_field.idx];
561 return sema.failWithContainsReferenceToComptimeVar(block, default_val_src, field_name, "field default value", default_val);
562 }
563 struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern();
564 }
565}
566
567469/// This logic must be kept in sync with `Type.getUnionLayout`.
568470pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
569471 const pt = sema.pt;
......@@ -583,7 +485,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
583485 .parent = null,
584486 .sema = sema,
585487 .namespace = union_obj.namespace,
586 .instructions = .{},
488 .instructions = .empty,
587489 .inlining = null,
588490 .comptime_reason = undefined, // always set before using `block`
589491 .src_base_inst = union_obj.zir_index,
......@@ -1048,7 +950,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
1048950 .parent = null,
1049951 .sema = sema,
1050952 .namespace = enum_obj.namespace,
1051 .instructions = .{},
953 .instructions = .empty,
1052954 .inlining = null,
1053955 .comptime_reason = undefined, // always set before using `block`
1054956 .src_base_inst = tracked_inst,
......@@ -1287,8 +1189,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
12871189 }
12881190 }
12891191
1290 // MLUGG TODO: fate of this line rests on whether comptime_int is a valid int tag type
1291 if (enum_obj.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
1192 if (enum_obj.nonexhaustive) {
12921193 const fields_len = enum_obj.field_names.len;
12931194 if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) {
12941195 return sema.fail(&block, block.nodeOffset(.zero), "non-exhaustive enum specifies every value", .{});
src/Zcu.zig+3-5
......@@ -3122,7 +3122,6 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
31223122 .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
31233123 .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }),
31243124 .type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }),
3125 .struct_defaults => |ty| try zcu.markPoDependeeUpToDate(.{ .struct_defaults = ty }),
31263125 .func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }),
31273126 .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }),
31283127 }
......@@ -3138,7 +3137,6 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
31383137 .nav_val => |nav| .{ .nav_val = nav },
31393138 .nav_ty => |nav| .{ .nav_ty = nav },
31403139 .type_layout => |ty| .{ .type_layout = ty },
3141 .struct_defaults => |ty| .{ .struct_defaults = ty },
31423140 .func => |func_index| .{ .func_ies = func_index },
31433141 .memoized_state => |stage| .{ .memoized_state = stage },
31443142 };
......@@ -4116,7 +4114,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
41164114 const other: AnalUnit = .wrap(switch (unit.unwrap()) {
41174115 .nav_val => |n| .{ .nav_ty = n },
41184116 .nav_ty => |n| .{ .nav_val = n },
4119 .@"comptime", .type_layout, .struct_defaults, .func, .memoized_state => break :queue_paired,
4117 .@"comptime", .type_layout, .func, .memoized_state => break :queue_paired,
41204118 });
41214119 const gop = try units.getOrPut(gpa, other);
41224120 if (gop.found_existing) break :queue_paired;
......@@ -4273,7 +4271,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void
42734271 }
42744272 },
42754273 .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4276 .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
4274 .type_layout => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
42774275 .func => |func| {
42784276 const nav = zcu.funcInfo(func).owner_nav;
42794277 return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });
......@@ -4299,7 +4297,7 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void
42994297 const fqn = ip.getNav(nav).fqn;
43004298 return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) });
43014299 },
4302 .type_layout, .struct_defaults => |ip_index, tag| {
4300 .type_layout => |ip_index, tag| {
43034301 const name = Type.fromInterned(ip_index).containerTypeName(ip);
43044302 return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) });
43054303 },
src/Zcu/PerThread.zig+8-114
......@@ -865,7 +865,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)
865865 .parent = null,
866866 .sema = &sema,
867867 .namespace = std_namespace,
868 .instructions = .{},
868 .instructions = .empty,
869869 .inlining = null,
870870 .comptime_reason = .{ .reason = .{
871871 .src = src,
......@@ -1014,7 +1014,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
10141014 .parent = null,
10151015 .sema = &sema,
10161016 .namespace = comptime_unit.namespace,
1017 .instructions = .{},
1017 .instructions = .empty,
10181018 .inlining = null,
10191019 .comptime_reason = .{ .reason = .{
10201020 .src = .{
......@@ -1152,109 +1152,6 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void
11521152 };
11531153}
11541154
1155/// Ensures that the default values of the given "declared" (not reified) `struct` type are fully
1156/// up-to-date, performing re-analysis if necessary. Asserts that `ty` is a struct (not tuple) type.
1157/// Returns `error.AnalysisFail` if an analysis error is encountered while resolving the default
1158/// field values; the caller is free to ignore this, since the error is already registered.
1159pub fn ensureStructDefaultsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
1160 const tracy = trace(@src());
1161 defer tracy.end();
1162
1163 const zcu = pt.zcu;
1164 const gpa = zcu.gpa;
1165
1166 assert(ty.zigTypeTag(zcu) == .@"struct");
1167 assert(!ty.isTuple(zcu));
1168
1169 const anal_unit: AnalUnit = .wrap(.{ .struct_defaults = ty.toIntern() });
1170
1171 log.debug("ensureStructDefaultsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
1172
1173 assert(!zcu.analysis_in_progress.contains(anal_unit));
1174
1175 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
1176 zcu.potentially_outdated.swapRemove(anal_unit) or
1177 zcu.intern_pool.setWantStructDefaults(zcu.comp.io, ty.toIntern());
1178
1179 if (was_outdated) {
1180 _ = zcu.outdated_ready.swapRemove(anal_unit);
1181 // `was_outdated` is true in the initial update, so this isn't a `dev.check`.
1182 if (dev.env.supports(.incremental)) {
1183 zcu.deleteUnitExports(anal_unit);
1184 zcu.deleteUnitReferences(anal_unit);
1185 zcu.deleteUnitCompileLogs(anal_unit);
1186 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
1187 kv.value.destroy(gpa);
1188 }
1189 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
1190 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
1191 }
1192 // For types, we already know that we have to invalidate all dependees.
1193 // TODO: we actually *could* detect whether everything was the same. should we bother?
1194 try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() });
1195 } else {
1196 // We can trust the current information about this unit.
1197 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
1198 if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail;
1199 return;
1200 }
1201
1202 if (zcu.comp.debugIncremental()) {
1203 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
1204 info.last_update_gen = zcu.generation;
1205 info.deps.clearRetainingCapacity();
1206 }
1207
1208 const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null);
1209 defer unit_tracking.end(zcu);
1210
1211 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
1212 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1213
1214 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
1215 defer analysis_arena.deinit();
1216
1217 var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa);
1218 defer comptime_err_ret_trace.deinit();
1219
1220 const zir = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu).zir.?;
1221
1222 var sema: Sema = .{
1223 .pt = pt,
1224 .gpa = gpa,
1225 .arena = analysis_arena.allocator(),
1226 .code = zir,
1227 .owner = anal_unit,
1228 .func_index = .none,
1229 .func_is_naked = false,
1230 .fn_ret_ty = .void,
1231 .fn_ret_ty_ies = null,
1232 .comptime_err_ret_trace = &comptime_err_ret_trace,
1233 };
1234 defer sema.deinit();
1235
1236 Sema.type_resolution.resolveStructDefaults(&sema, ty) catch |err| switch (err) {
1237 error.AnalysisFail => {
1238 if (!zcu.failed_analysis.contains(anal_unit)) {
1239 // If this unit caused the error, it would have an entry in `failed_analysis`.
1240 // Since it does not, this must be a transitive failure.
1241 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1242 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1243 }
1244 return error.AnalysisFail;
1245 },
1246 error.OutOfMemory,
1247 error.Canceled,
1248 => |e| return e,
1249 error.ComptimeReturn => unreachable,
1250 error.ComptimeBreak => unreachable,
1251 };
1252
1253 sema.flushExports() catch |err| switch (err) {
1254 error.OutOfMemory => |e| return e,
1255 };
1256}
1257
12581155/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
12591156/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
12601157/// free to ignore this, since the error is already registered.
......@@ -1452,7 +1349,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
14521349 .parent = null,
14531350 .sema = &sema,
14541351 .namespace = old_nav.analysis.?.namespace,
1455 .instructions = .{},
1352 .instructions = .empty,
14561353 .inlining = null,
14571354 .comptime_reason = undefined, // set below
14581355 .src_base_inst = old_nav.analysis.?.zir_index,
......@@ -1831,7 +1728,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
18311728 .parent = null,
18321729 .sema = &sema,
18331730 .namespace = old_nav.analysis.?.namespace,
1834 .instructions = .{},
1731 .instructions = .empty,
18351732 .inlining = null,
18361733 .comptime_reason = undefined, // set below
18371734 .src_base_inst = old_nav.analysis.?.zir_index,
......@@ -3078,7 +2975,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem
30782975 .parent = null,
30792976 .sema = &sema,
30802977 .namespace = decl_nav.analysis.?.namespace,
3081 .instructions = .{},
2978 .instructions = .empty,
30822979 .inlining = null,
30832980 .comptime_reason = null,
30842981 .src_base_inst = decl_nav.analysis.?.zir_index,
......@@ -3327,7 +3224,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
33273224 break :gop .{ gop.value_ptr, gop.found_existing };
33283225 },
33293226 };
3330 if (!found_existing) value_ptr.* = .{};
3227 if (!found_existing) value_ptr.* = .empty;
33313228 try value_ptr.append(gpa, export_idx);
33323229 }
33333230
......@@ -3356,7 +3253,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
33563253 break :gop .{ gop.value_ptr, gop.found_existing };
33573254 },
33583255 };
3359 if (!found_existing) value_ptr.* = .{};
3256 if (!found_existing) value_ptr.* = .empty;
33603257 try value_ptr.append(gpa, @enumFromInt(export_idx));
33613258 }
33623259 }
......@@ -4353,10 +4250,7 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
43534250 },
43544251
43554252 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
4356 .struct_type => {
4357 try pt.ensureTypeLayoutUpToDate(ty);
4358 try pt.ensureStructDefaultsUpToDate(ty);
4359 },
4253 .struct_type => try pt.ensureTypeLayoutUpToDate(ty),
43604254 .tuple_type => |tuple| for (0..tuple.types.len) |i| {
43614255 const field_is_comptime = tuple.values.get(ip)[i] != .none;
43624256 if (field_is_comptime) continue;
src/codegen/c/Type.zig+6-6
......@@ -1054,13 +1054,13 @@ pub const Pool = struct {
10541054 };
10551055
10561056 pub const empty: Pool = .{
1057 .map = .{},
1058 .items = .{},
1059 .extra = .{},
1057 .map = .empty,
1058 .items = .empty,
1059 .extra = .empty,
10601060
1061 .string_map = .{},
1062 .string_indices = .{},
1063 .string_bytes = .{},
1061 .string_map = .empty,
1062 .string_indices = .empty,
1063 .string_bytes = .empty,
10641064 };
10651065
10661066 pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void {
src/link/Elf/Object.zig+1-1
......@@ -775,7 +775,7 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO
775775
776776 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
777777 if (!gop.found_existing) {
778 gop.value_ptr.* = .{};
778 gop.value_ptr.* = .empty;
779779 }
780780 try gop.value_ptr.append(elf_file.base.comp.gpa, self.index);
781781 }
src/link/Elf/ZigObject.zig+3-3
......@@ -84,7 +84,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
8484 const ptr_size = elf_file.ptrWidthBytes();
8585
8686 try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section
87 try self.relocs.append(gpa, .{}); // null relocs section
87 try self.relocs.append(gpa, .empty); // null relocs section
8888 try self.strtab.buffer.append(gpa, 0);
8989
9090 {
......@@ -546,7 +546,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
546546 atom_ptr.name_offset = name_off;
547547
548548 const relocs_index: u32 = @intCast(self.relocs.items.len);
549 self.relocs.addOneAssumeCapacity().* = .{};
549 self.relocs.addOneAssumeCapacity().* = .empty;
550550 atom_ptr.relocs_section_index = relocs_index;
551551
552552 return index;
......@@ -730,7 +730,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
730730
731731 const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
732732 if (!gop.found_existing) {
733 gop.value_ptr.* = .{};
733 gop.value_ptr.* = .empty;
734734 }
735735 try gop.value_ptr.append(elf_file.base.comp.gpa, self.index);
736736 }
src/link/MachO/ZigObject.zig+2-2
......@@ -3,7 +3,7 @@ data: std.ArrayList(u8) = .empty,
33basename: []const u8,
44index: File.Index,
55
6symtab: std.MultiArrayList(Nlist) = .{},
6symtab: std.MultiArrayList(Nlist) = .empty,
77strtab: StringTable = .{},
88
99symbols: std.ArrayList(Symbol) = .empty,
......@@ -29,7 +29,7 @@ uavs: UavTable = .{},
2929tlv_initializers: TlvInitializerTable = .{},
3030
3131/// A table of relocations.
32relocs: RelocationTable = .{},
32relocs: RelocationTable = .empty,
3333
3434dwarf: ?Dwarf = null,
3535
src/link/Wasm.zig+2-2
......@@ -78,7 +78,7 @@ export_table: bool,
7878/// Output name of the file
7979name: []const u8,
8080/// List of relocatable files to be linked into the final binary.
81objects: std.ArrayList(Object) = .{},
81objects: std.ArrayList(Object) = .empty,
8282
8383func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty,
8484/// Provides a mapping of both imports and provided functions to symbol name.
......@@ -278,7 +278,7 @@ any_tls_relocs: bool = false,
278278any_passive_inits: bool = false,
279279
280280/// All MIR instructions for all Zcu functions.
281mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
281mir_instructions: std.MultiArrayList(Mir.Inst) = .empty,
282282/// Corresponds to `mir_instructions`.
283283mir_extra: std.ArrayList(u32) = .empty,
284284/// All local types for all Zcu functions.
src/main.zig+9-9
......@@ -979,7 +979,7 @@ fn buildOutputType(
979979 .dirs = undefined,
980980 .object_format = null,
981981 .dynamic_linker = null,
982 .modules = .{},
982 .modules = .empty,
983983 .opts = .{
984984 .is_test = switch (arg_mode) {
985985 .zig_test, .zig_test_obj => true,
......@@ -1006,18 +1006,18 @@ fn buildOutputType(
10061006 .windows_libs = .empty,
10071007 .link_inputs = .empty,
10081008
1009 .c_source_files = .{},
1010 .rc_source_files = .{},
1009 .c_source_files = .empty,
1010 .rc_source_files = .empty,
10111011
1012 .llvm_m_args = .{},
1012 .llvm_m_args = .empty,
10131013 .sysroot = null,
1014 .lib_directories = .{}, // populated by createModule()
1015 .lib_dir_args = .{}, // populated from CLI arg parsing
1014 .lib_directories = .empty, // populated by createModule()
1015 .lib_dir_args = .empty, // populated from CLI arg parsing
10161016 .libc_installation = null,
10171017 .want_native_include_dirs = false,
1018 .frameworks = .{},
1019 .framework_dirs = .{},
1020 .rpath_list = .{},
1018 .frameworks = .empty,
1019 .framework_dirs = .empty,
1020 .rpath_list = .empty,
10211021 .each_lib_rpath = null,
10221022 .libc_paths_file = EnvVar.ZIG_LIBC.get(environ_map),
10231023 .native_system_include_paths = &.{},