mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
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.
This commit is contained in:
@@ -153,8 +153,8 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li
|
||||
usize,
|
||||
(air.instructions.len * bpi + @bitSizeOf(usize) - 1) / @bitSizeOf(usize),
|
||||
),
|
||||
.extra = .{},
|
||||
.special = .{},
|
||||
.extra = .empty,
|
||||
.special = .empty,
|
||||
.intern_pool = intern_pool,
|
||||
};
|
||||
errdefer gpa.free(a.tomb_bits);
|
||||
@@ -175,7 +175,7 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li
|
||||
var data: LivenessPassData(.main_analysis) = .{};
|
||||
defer data.deinit(gpa);
|
||||
data.old_extra = a.extra;
|
||||
a.extra = .{};
|
||||
a.extra = .empty;
|
||||
try analyzeBody(&a, .main_analysis, &data, main_body);
|
||||
assert(data.live_set.count() == 0);
|
||||
}
|
||||
@@ -1360,7 +1360,7 @@ fn analyzeInstSwitchBr(
|
||||
const mirrored_deaths = try gpa.alloc(DeathList, ncases + 1);
|
||||
defer gpa.free(mirrored_deaths);
|
||||
|
||||
@memset(mirrored_deaths, .{});
|
||||
@memset(mirrored_deaths, .empty);
|
||||
defer for (mirrored_deaths) |*md| md.deinit(gpa);
|
||||
|
||||
{
|
||||
|
||||
+2
-7
@@ -3713,7 +3713,6 @@ const Header = extern struct {
|
||||
nav_val_deps_len: u32,
|
||||
nav_ty_deps_len: u32,
|
||||
type_layout_deps_len: u32,
|
||||
struct_defaults_deps_len: u32,
|
||||
func_ies_deps_len: u32,
|
||||
zon_file_deps_len: u32,
|
||||
embed_file_deps_len: u32,
|
||||
@@ -3763,7 +3762,6 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
.nav_val_deps_len = @intCast(ip.nav_val_deps.count()),
|
||||
.nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()),
|
||||
.type_layout_deps_len = @intCast(ip.type_layout_deps.count()),
|
||||
.struct_defaults_deps_len = @intCast(ip.struct_defaults_deps.count()),
|
||||
.func_ies_deps_len = @intCast(ip.func_ies_deps.count()),
|
||||
.zon_file_deps_len = @intCast(ip.zon_file_deps.count()),
|
||||
.embed_file_deps_len = @intCast(ip.embed_file_deps.count()),
|
||||
@@ -3788,7 +3786,7 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
},
|
||||
});
|
||||
|
||||
try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len);
|
||||
try bufs.ensureTotalCapacityPrecise(24 + 9 * pt_headers.items.len);
|
||||
addBuf(&bufs, mem.asBytes(&header));
|
||||
addBuf(&bufs, @ptrCast(pt_headers.items));
|
||||
|
||||
@@ -3800,8 +3798,6 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.type_layout_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys()));
|
||||
addBuf(&bufs, @ptrCast(ip.func_ies_deps.values()));
|
||||
addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys()));
|
||||
@@ -4481,7 +4477,7 @@ pub fn addModuleErrorMsg(
|
||||
const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) {
|
||||
.@"comptime" => "comptime",
|
||||
.nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
|
||||
.type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
|
||||
.type_layout => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
|
||||
.func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
|
||||
.memoized_state => null,
|
||||
};
|
||||
@@ -5251,7 +5247,6 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
|
||||
.nav_ty => |nav| pt.ensureNavTypeUpToDate(nav),
|
||||
.nav_val => |nav| pt.ensureNavValUpToDate(nav),
|
||||
.type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)),
|
||||
.struct_defaults => |ty| pt.ensureStructDefaultsUpToDate(.fromInterned(ty)),
|
||||
.memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage),
|
||||
.func => |func| pt.ensureFuncBodyUpToDate(func),
|
||||
};
|
||||
|
||||
@@ -307,7 +307,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
|
||||
switch (dependee) {
|
||||
.src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}),
|
||||
.nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }),
|
||||
.type_layout, .struct_defaults, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }),
|
||||
.type_layout, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }),
|
||||
.memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}),
|
||||
}
|
||||
try w.writeByte('\n');
|
||||
@@ -374,8 +374,6 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit {
|
||||
return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) });
|
||||
} else if (std.mem.eql(u8, kind, "type_layout")) {
|
||||
return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) });
|
||||
} else if (std.mem.eql(u8, kind, "struct_defaults")) {
|
||||
return .wrap(.{ .struct_defaults = @enumFromInt(parseIndex(idx_str) orelse return null) });
|
||||
} else if (std.mem.eql(u8, kind, "func")) {
|
||||
return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) });
|
||||
} else if (std.mem.eql(u8, kind, "memoized_state")) {
|
||||
|
||||
+5
-82
@@ -54,9 +54,6 @@ func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
|
||||
/// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type.
|
||||
/// Value is index into `dep_entries` of the first dependency on this type's layout.
|
||||
type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
|
||||
/// Dependencies on the resolved default field values of a `struct` type.
|
||||
/// Value is index into `dep_entries` of the first dependency on this type's inits.
|
||||
struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
|
||||
/// Dependencies on a ZON file. Triggered by `@import` of ZON.
|
||||
/// Value is index into `dep_entries` of the first dependency on this ZON file.
|
||||
zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index),
|
||||
@@ -111,7 +108,6 @@ pub const empty: InternPool = .{
|
||||
.nav_ty_deps = .empty,
|
||||
.func_ies_deps = .empty,
|
||||
.type_layout_deps = .empty,
|
||||
.struct_defaults_deps = .empty,
|
||||
.zon_file_deps = .empty,
|
||||
.embed_file_deps = .empty,
|
||||
.namespace_deps = .empty,
|
||||
@@ -423,7 +419,6 @@ pub const AnalUnit = packed struct(u64) {
|
||||
nav_val,
|
||||
nav_ty,
|
||||
type_layout,
|
||||
struct_defaults,
|
||||
func,
|
||||
memoized_state,
|
||||
};
|
||||
@@ -437,8 +432,6 @@ pub const AnalUnit = packed struct(u64) {
|
||||
nav_ty: Nav.Index,
|
||||
/// This `AnalUnit` resolves the layout of the given `struct`, `union`, or `enum` type.
|
||||
type_layout: InternPool.Index,
|
||||
/// This `AnalUnit` resolves the default field values of the given `struct` type.
|
||||
struct_defaults: InternPool.Index,
|
||||
/// This `AnalUnit` analyzes the body of the given runtime function.
|
||||
func: InternPool.Index,
|
||||
/// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`.
|
||||
@@ -858,7 +851,6 @@ pub const Dependee = union(enum) {
|
||||
/// Index is the function, not its IES.
|
||||
func_ies: Index,
|
||||
type_layout: Index,
|
||||
struct_defaults: Index,
|
||||
zon_file: FileIndex,
|
||||
embed_file: Zcu.EmbedFile.Index,
|
||||
namespace: TrackedInst.Index,
|
||||
@@ -912,7 +904,6 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
|
||||
.nav_ty => |x| ip.nav_ty_deps.get(x),
|
||||
.func_ies => |x| ip.func_ies_deps.get(x),
|
||||
.type_layout => |x| ip.type_layout_deps.get(x),
|
||||
.struct_defaults => |x| ip.struct_defaults_deps.get(x),
|
||||
.zon_file => |x| ip.zon_file_deps.get(x),
|
||||
.embed_file => |x| ip.embed_file_deps.get(x),
|
||||
.namespace => |x| ip.namespace_deps.get(x),
|
||||
@@ -987,7 +978,6 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
|
||||
.nav_ty => ip.nav_ty_deps,
|
||||
.func_ies => ip.func_ies_deps,
|
||||
.type_layout => ip.type_layout_deps,
|
||||
.struct_defaults => ip.struct_defaults_deps,
|
||||
.zon_file => ip.zon_file_deps,
|
||||
.embed_file => ip.embed_file_deps,
|
||||
.namespace => ip.namespace_deps,
|
||||
@@ -3326,15 +3316,6 @@ pub const LoadedStructType = struct {
|
||||
/// compiler frontend resolves this by traversing the reference graph at the end of each update
|
||||
/// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis.
|
||||
want_layout: bool,
|
||||
/// Initially `false`, and set to `true` once any dependency on or reference to the struct's
|
||||
/// default field values is encountered, after which it is never reset to `false`, even across
|
||||
/// incremental updates.
|
||||
///
|
||||
/// This field is purely an optimization to avoid resolving the layout of types whose layouts
|
||||
/// are never demanded. If this field is `true` but the layout is not actually needed, the
|
||||
/// compiler frontend resolves this by traversing the reference graph at the end of each update
|
||||
/// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis.
|
||||
want_defaults: bool,
|
||||
|
||||
// The remaining fields are only valid once the struct's layout is resolved.
|
||||
field_name_map: MapIndex,
|
||||
@@ -3711,7 +3692,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
|
||||
.packed_backing_mode = undefined,
|
||||
|
||||
.want_layout = extra.data.flags.want_layout,
|
||||
.want_defaults = extra.data.flags.want_defaults,
|
||||
|
||||
.field_name_map = extra.data.field_name_map,
|
||||
.field_names = field_names,
|
||||
@@ -3772,7 +3752,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
|
||||
.packed_backing_mode = backing_mode,
|
||||
|
||||
.want_layout = extra.data.bits.want_layout,
|
||||
.want_defaults = extra.data.bits.want_defaults,
|
||||
|
||||
.field_name_map = extra.data.field_name_map,
|
||||
.field_names = field_names,
|
||||
@@ -5666,9 +5645,8 @@ pub const Tag = enum(u8) {
|
||||
alignment: Alignment,
|
||||
|
||||
want_layout: bool,
|
||||
want_defaults: bool,
|
||||
|
||||
_: u15 = 0,
|
||||
_: u16 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5693,12 +5671,11 @@ pub const Tag = enum(u8) {
|
||||
field_name_map: MapIndex,
|
||||
|
||||
const Bits = packed struct(u32) {
|
||||
captures_len: enum(u30) {
|
||||
reified = std.math.maxInt(u30),
|
||||
captures_len: enum(u31) {
|
||||
reified = std.math.maxInt(u31),
|
||||
_,
|
||||
},
|
||||
want_layout: bool,
|
||||
want_defaults: bool,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6477,7 +6454,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void {
|
||||
ip.nav_ty_deps.deinit(gpa);
|
||||
ip.func_ies_deps.deinit(gpa);
|
||||
ip.type_layout_deps.deinit(gpa);
|
||||
ip.struct_defaults_deps.deinit(gpa);
|
||||
ip.zon_file_deps.deinit(gpa);
|
||||
ip.embed_file_deps.deinit(gpa);
|
||||
ip.namespace_deps.deinit(gpa);
|
||||
@@ -8191,7 +8167,6 @@ pub fn getDeclaredStructType(
|
||||
.bits = .{
|
||||
.captures_len = @enumFromInt(ini.captures.len),
|
||||
.want_layout = false,
|
||||
.want_defaults = false,
|
||||
},
|
||||
.name = undefined, // set by `finish`
|
||||
.name_nav = undefined, // set by `finish`
|
||||
@@ -8256,7 +8231,6 @@ pub fn getDeclaredStructType(
|
||||
.class = .no_possible_value,
|
||||
.alignment = .none,
|
||||
.want_layout = false,
|
||||
.want_defaults = false,
|
||||
},
|
||||
});
|
||||
if (ini.captures.len != 0) {
|
||||
@@ -8337,7 +8311,6 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe
|
||||
.bits = .{
|
||||
.captures_len = .reified,
|
||||
.want_layout = false,
|
||||
.want_defaults = false,
|
||||
},
|
||||
.name = undefined, // set by `finish`
|
||||
.name_nav = undefined, // set by `finish`
|
||||
@@ -8407,7 +8380,6 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe
|
||||
.class = .no_possible_value,
|
||||
.alignment = .none,
|
||||
.want_layout = false,
|
||||
.want_defaults = false,
|
||||
},
|
||||
});
|
||||
_ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash
|
||||
@@ -10647,7 +10619,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
const nav_ty_deps_len = ip.nav_ty_deps.count();
|
||||
const func_ies_deps_len = ip.func_ies_deps.count();
|
||||
const type_layout_deps_len = ip.type_layout_deps.count();
|
||||
const struct_defaults_deps_len = ip.struct_defaults_deps.count();
|
||||
const zon_file_deps_len = ip.zon_file_deps.count();
|
||||
const embed_file_deps_len = ip.embed_file_deps.count();
|
||||
const namespace_deps_len = ip.namespace_deps.count();
|
||||
@@ -10658,7 +10629,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
const nav_ty_deps_size = nav_ty_deps_len * 8;
|
||||
const func_ies_deps_size = func_ies_deps_len * 8;
|
||||
const type_layout_deps_size = type_layout_deps_len * 8;
|
||||
const struct_defaults_deps_size = struct_defaults_deps_len * 8;
|
||||
const zon_file_deps_size = zon_file_deps_len * 8;
|
||||
const embed_file_deps_size = embed_file_deps_len * 8;
|
||||
const namespace_deps_size = namespace_deps_len * 8;
|
||||
@@ -10672,7 +10642,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
\\ {d} nav_ty: {d} bytes
|
||||
\\ {d} func_ies: {d} bytes
|
||||
\\ {d} type_layout: {d} bytes
|
||||
\\ {d} struct_defaults: {d} bytes
|
||||
\\ {d} zon_file: {d} bytes
|
||||
\\ {d} embed_file: {d} bytes
|
||||
\\ {d} namespace: {d} bytes
|
||||
@@ -10680,7 +10649,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
\\
|
||||
, .{
|
||||
dep_entries_size + src_hash_deps_size + nav_val_deps_size + nav_ty_deps_size +
|
||||
func_ies_deps_size + type_layout_deps_size + struct_defaults_deps_size + zon_file_deps_size +
|
||||
func_ies_deps_size + type_layout_deps_size + zon_file_deps_size +
|
||||
embed_file_deps_size + namespace_deps_size + namespace_name_deps_size,
|
||||
dep_entries_len,
|
||||
dep_entries_size,
|
||||
@@ -10694,8 +10663,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void {
|
||||
func_ies_deps_size,
|
||||
type_layout_deps_len,
|
||||
type_layout_deps_size,
|
||||
struct_defaults_deps_len,
|
||||
struct_defaults_deps_size,
|
||||
zon_file_deps_len,
|
||||
zon_file_deps_size,
|
||||
embed_file_deps_len,
|
||||
@@ -11136,7 +11103,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator,
|
||||
const info = extraData(extra_list, Tag.FuncInstance, data);
|
||||
|
||||
const gop = try instances.getOrPut(arena, info.generic_owner);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
if (!gop.found_existing) gop.value_ptr.* = .empty;
|
||||
|
||||
try gop.value_ptr.append(
|
||||
arena,
|
||||
@@ -12969,50 +12936,6 @@ pub fn setWantTypeLayout(ip: *InternPool, io: Io, container_type: Index) bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `setWantTypeLayout`, but for the default field values of a struct (so this sets the
|
||||
/// `want_defaults` flag rather than the `want_layout` flag).
|
||||
pub fn setWantStructDefaults(ip: *InternPool, io: Io, struct_type: Index) bool {
|
||||
const unwrapped_index = struct_type.unwrap(ip);
|
||||
|
||||
const local = ip.getLocal(unwrapped_index.tid);
|
||||
local.mutate.extra.mutex.lockUncancelable(io);
|
||||
defer local.mutate.extra.mutex.unlock(io);
|
||||
|
||||
const extra_items = local.shared.extra.view().items(.@"0");
|
||||
const item = unwrapped_index.getItem(ip);
|
||||
switch (item.tag) {
|
||||
.type_struct_packed_auto,
|
||||
.type_struct_packed_explicit,
|
||||
.type_struct_packed_auto_defaults,
|
||||
.type_struct_packed_explicit_defaults,
|
||||
=> {
|
||||
const bits: *Tag.TypeStructPacked.Bits = @ptrCast(&extra_items[
|
||||
item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "bits").?
|
||||
]);
|
||||
if (bits.want_defaults) {
|
||||
return false;
|
||||
} else {
|
||||
bits.want_defaults = true;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
.type_struct => {
|
||||
const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[
|
||||
item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?
|
||||
]);
|
||||
if (flags.want_defaults) {
|
||||
return false;
|
||||
} else {
|
||||
flags.want_defaults = true;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `setWantTypeLayout`, but for runtime analysis of a function body, using the
|
||||
/// `FuncAnalysis.want_runtime_analysis` flag.
|
||||
pub fn setWantRuntimeFnAnalysis(ip: *InternPool, io: Io, func_index: Index) bool {
|
||||
|
||||
+29
-39
@@ -4519,10 +4519,6 @@ fn validateStructInit(
|
||||
if (explicit) continue;
|
||||
if (struct_ty.structFieldIsComptime(i, zcu)) continue;
|
||||
|
||||
if (!struct_ty.isTuple(zcu)) {
|
||||
try sema.ensureStructDefaultsResolved(struct_ty, init_src);
|
||||
}
|
||||
|
||||
const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse {
|
||||
const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse {
|
||||
const template = "missing tuple field with index {d}";
|
||||
@@ -5180,9 +5176,9 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
var label: Block.Label = .{
|
||||
.zir_block = inst,
|
||||
.merges = .{
|
||||
.src_locs = .{},
|
||||
.results = .{},
|
||||
.br_list = .{},
|
||||
.src_locs = .empty,
|
||||
.results = .empty,
|
||||
.br_list = .empty,
|
||||
.block_inst = block_inst,
|
||||
},
|
||||
};
|
||||
@@ -5254,7 +5250,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
.namespace = parent_block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = parent_block.inlining,
|
||||
.comptime_reason = .{ .reason = .{
|
||||
.src = src,
|
||||
@@ -5389,9 +5385,9 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
var label: Block.Label = .{
|
||||
.zir_block = inst,
|
||||
.merges = .{
|
||||
.src_locs = .{},
|
||||
.results = .{},
|
||||
.br_list = .{},
|
||||
.src_locs = .empty,
|
||||
.results = .empty,
|
||||
.br_list = .empty,
|
||||
.block_inst = block_inst,
|
||||
},
|
||||
};
|
||||
@@ -5400,7 +5396,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
.namespace = parent_block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.label = &label,
|
||||
.inlining = parent_block.inlining,
|
||||
.comptime_reason = parent_block.comptime_reason,
|
||||
@@ -5839,7 +5835,6 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
|
||||
.nav_val,
|
||||
.nav_ty,
|
||||
.type_layout,
|
||||
.struct_defaults,
|
||||
.memoized_state,
|
||||
=> return, // does nothing outside a function
|
||||
};
|
||||
@@ -5858,7 +5853,6 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
|
||||
.nav_val,
|
||||
.nav_ty,
|
||||
.type_layout,
|
||||
.struct_defaults,
|
||||
.memoized_state,
|
||||
=> return, // does nothing outside a function
|
||||
};
|
||||
@@ -6870,7 +6864,7 @@ fn analyzeCall(
|
||||
.parent = null,
|
||||
.sema = sema,
|
||||
.namespace = fn_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = &generic_inlining,
|
||||
.src_base_inst = fn_nav.analysis.?.zir_index,
|
||||
.type_name_ctx = fn_nav.fqn,
|
||||
@@ -7067,7 +7061,7 @@ fn analyzeCall(
|
||||
});
|
||||
if (func_ty_info.cc == .auto) {
|
||||
switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {},
|
||||
.@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {},
|
||||
.func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true),
|
||||
}
|
||||
}
|
||||
@@ -7382,7 +7376,7 @@ fn analyzeCall(
|
||||
.parent = null,
|
||||
.sema = sema,
|
||||
.namespace = fn_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = &inlining,
|
||||
.is_typeof = block.is_typeof,
|
||||
.comptime_reason = if (block.isComptime()) .inlining_parent else null,
|
||||
@@ -9945,9 +9939,9 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
|
||||
var label: Block.Label = .{
|
||||
.zir_block = inst,
|
||||
.merges = .{
|
||||
.src_locs = .{},
|
||||
.results = .{},
|
||||
.br_list = .{},
|
||||
.src_locs = .empty,
|
||||
.results = .empty,
|
||||
.br_list = .empty,
|
||||
.block_inst = block_inst,
|
||||
},
|
||||
};
|
||||
@@ -10100,9 +10094,9 @@ fn zirSwitchBlock(
|
||||
var label: Block.Label = .{
|
||||
.zir_block = inst,
|
||||
.merges = .{
|
||||
.src_locs = .{},
|
||||
.results = .{},
|
||||
.br_list = .{},
|
||||
.src_locs = .empty,
|
||||
.results = .empty,
|
||||
.br_list = .empty,
|
||||
.block_inst = block_inst,
|
||||
},
|
||||
};
|
||||
@@ -16864,7 +16858,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
.struct_type => ip.loadStructType(ty.toIntern()),
|
||||
else => unreachable,
|
||||
};
|
||||
try sema.ensureStructDefaultsResolved(ty, src); // can't do this sooner, since it's not allowed on tuples
|
||||
struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);
|
||||
|
||||
for (struct_field_vals, 0..) |*field_val, field_index| {
|
||||
@@ -17122,7 +17115,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
|
||||
.parent = block,
|
||||
.sema = sema,
|
||||
.namespace = block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = block.inlining,
|
||||
.comptime_reason = null,
|
||||
.is_typeof = true,
|
||||
@@ -17190,7 +17183,7 @@ fn zirTypeofPeer(
|
||||
.parent = block,
|
||||
.sema = sema,
|
||||
.namespace = block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = block.inlining,
|
||||
.comptime_reason = null,
|
||||
.is_typeof = true,
|
||||
@@ -17764,9 +17757,9 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
|
||||
.label = .{
|
||||
.zir_block = dest_block,
|
||||
.merges = .{
|
||||
.src_locs = .{},
|
||||
.results = .{},
|
||||
.br_list = .{},
|
||||
.src_locs = .empty,
|
||||
.results = .empty,
|
||||
.br_list = .empty,
|
||||
.block_inst = new_block_inst,
|
||||
},
|
||||
},
|
||||
@@ -17774,7 +17767,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
|
||||
.parent = block,
|
||||
.sema = sema,
|
||||
.namespace = block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.label = &labeled_block.label,
|
||||
.inlining = block.inlining,
|
||||
.comptime_reason = block.comptime_reason,
|
||||
@@ -18753,8 +18746,6 @@ fn finishStructInit(
|
||||
continue;
|
||||
}
|
||||
|
||||
try sema.ensureStructDefaultsResolved(struct_ty, init_src);
|
||||
|
||||
const field_default: InternPool.Index = d: {
|
||||
if (struct_type.field_defaults.len == 0) break :d .none;
|
||||
break :d struct_type.field_defaults.get(ip)[i];
|
||||
@@ -19420,7 +19411,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
|
||||
.func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) {
|
||||
return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
|
||||
},
|
||||
.@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {},
|
||||
.@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {},
|
||||
}
|
||||
return Air.internedToRef(try pt.intern(.{ .opt = .{
|
||||
.ty = opt_ptr_stack_trace_ty.toIntern(),
|
||||
@@ -24738,7 +24729,7 @@ fn zirBuiltinExtern(
|
||||
// So, for now, just use our containing `declaration`.
|
||||
.zir_index = switch (sema.owner.unwrap()) {
|
||||
.@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
|
||||
.type_layout, .struct_defaults => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?,
|
||||
.type_layout => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?,
|
||||
.memoized_state => unreachable,
|
||||
.nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
|
||||
.func => |func| zir_index: {
|
||||
@@ -25230,7 +25221,7 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In
|
||||
try sema.ensureMemoizedStateResolved(src, .panic);
|
||||
const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin());
|
||||
switch (sema.owner.unwrap()) {
|
||||
.@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {},
|
||||
.@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {},
|
||||
.func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true),
|
||||
}
|
||||
return panic_fn_index;
|
||||
@@ -25250,7 +25241,7 @@ fn addSafetyCheck(
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
.namespace = parent_block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = parent_block.inlining,
|
||||
.comptime_reason = null,
|
||||
.src_base_inst = parent_block.src_base_inst,
|
||||
@@ -25344,7 +25335,7 @@ fn addSafetyCheckUnwrapError(
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
.namespace = parent_block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = parent_block.inlining,
|
||||
.comptime_reason = null,
|
||||
.src_base_inst = parent_block.src_base_inst,
|
||||
@@ -25449,7 +25440,7 @@ fn addSafetyCheckCall(
|
||||
.parent = parent_block,
|
||||
.sema = sema,
|
||||
.namespace = parent_block.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = parent_block.inlining,
|
||||
.comptime_reason = null,
|
||||
.src_base_inst = parent_block.src_base_inst,
|
||||
@@ -33859,7 +33850,6 @@ const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStor
|
||||
|
||||
pub const type_resolution = @import("Sema/type_resolution.zig");
|
||||
pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved;
|
||||
pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved;
|
||||
|
||||
pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type {
|
||||
assert(decl.kind() == .type);
|
||||
|
||||
@@ -770,7 +770,6 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
|
||||
const ip = &pt.zcu.intern_pool;
|
||||
|
||||
try self.sema.ensureLayoutResolved(res_ty, self.import_loc);
|
||||
try self.sema.ensureStructDefaultsResolved(res_ty, self.import_loc);
|
||||
const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?;
|
||||
|
||||
const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {
|
||||
|
||||
+45
-144
@@ -85,30 +85,6 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!vo
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that `ty` is a non-tuple `struct` type, and ensures that its fields' default values
|
||||
/// are resolved. Adds incremental dependencies tracking the required type resolution.
|
||||
///
|
||||
/// It is not necessary to call this function to query the values of comptime fields: those values
|
||||
/// are available from type *layout* resolution, see `ensureLayoutResolved`.
|
||||
pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
assert(ip.indexToKey(ty.toIntern()) == .struct_type);
|
||||
|
||||
try sema.declareDependency(.{ .struct_defaults = ty.toIntern() });
|
||||
try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() }));
|
||||
if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) {
|
||||
// TODO: better error message
|
||||
return sema.failWithOwnedErrorMsg(null, try sema.errMsg(
|
||||
ty.srcLoc(zcu),
|
||||
"struct '{f}' depends on itself",
|
||||
.{ty.fmt(pt)},
|
||||
));
|
||||
}
|
||||
try pt.ensureStructDefaultsUpToDate(ty);
|
||||
}
|
||||
|
||||
/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.
|
||||
/// This function *does* register the `src_hash` dependency on the struct.
|
||||
pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
@@ -129,7 +105,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
.parent = null,
|
||||
.sema = sema,
|
||||
.namespace = struct_obj.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = undefined, // always set before using `block`
|
||||
.src_base_inst = struct_obj.zir_index,
|
||||
@@ -168,6 +144,13 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
@memset(struct_obj.field_is_comptime_bits.getAll(ip), 0);
|
||||
|
||||
const zir_struct = sema.code.getStructDecl(zir_index);
|
||||
|
||||
// If we have any default values to resolve, we'll need to map the struct decl instruction
|
||||
// to the result type.
|
||||
if (zir_struct.field_default_body_lens != null) {
|
||||
try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
|
||||
}
|
||||
|
||||
var field_it = zir_struct.iterateFields();
|
||||
while (field_it.next()) |zir_field| {
|
||||
{
|
||||
@@ -182,18 +165,16 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
struct_obj.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask;
|
||||
}
|
||||
|
||||
{
|
||||
const field_ty: Type = field_ty: {
|
||||
const field_ty_src = block.src(.{ .container_field_type = zir_field.idx });
|
||||
const field_ty: Type = field_ty: {
|
||||
block.comptime_reason = .{ .reason = .{
|
||||
.src = field_ty_src,
|
||||
.r = .{ .simple = .struct_field_types },
|
||||
} };
|
||||
const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index);
|
||||
break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref);
|
||||
};
|
||||
struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
|
||||
}
|
||||
block.comptime_reason = .{ .reason = .{
|
||||
.src = field_ty_src,
|
||||
.r = .{ .simple = .struct_field_types },
|
||||
} };
|
||||
const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index);
|
||||
break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref);
|
||||
};
|
||||
struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
|
||||
|
||||
if (struct_obj.field_aligns.len == 0) {
|
||||
assert(zir_field.align_body == null);
|
||||
@@ -210,6 +191,31 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
};
|
||||
struct_obj.field_aligns.get(ip)[zir_field.idx] = field_align;
|
||||
}
|
||||
|
||||
if (struct_obj.field_defaults.len == 0) {
|
||||
assert(zir_field.default_body == null);
|
||||
} else {
|
||||
const field_default_src = block.src(.{ .container_field_value = zir_field.idx });
|
||||
const field_default: InternPool.Index = d: {
|
||||
block.comptime_reason = .{ .reason = .{
|
||||
.src = field_default_src,
|
||||
.r = .{ .simple = .struct_field_default_value },
|
||||
} };
|
||||
const default_body = zir_field.default_body orelse break :d .none;
|
||||
// Provide the result type
|
||||
sema.inst_map.putAssumeCapacity(zir_index, .fromType(field_ty));
|
||||
defer assert(sema.inst_map.remove(zir_index));
|
||||
const uncoerced_default_val = try sema.resolveInlineBody(&block, default_body, zir_index);
|
||||
const coerced_default_val = try sema.coerce(&block, field_ty, uncoerced_default_val, field_default_src);
|
||||
const default_val = try sema.resolveConstValue(&block, field_default_src, coerced_default_val, null);
|
||||
if (default_val.canMutateComptimeVarState(zcu)) {
|
||||
const field_name = struct_obj.field_names.get(ip)[zir_field.idx];
|
||||
return sema.failWithContainsReferenceToComptimeVar(&block, field_default_src, field_name, "field default value", default_val);
|
||||
}
|
||||
break :d default_val.toIntern();
|
||||
};
|
||||
struct_obj.field_defaults.get(ip)[zir_field.idx] = field_default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,11 +363,6 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
struct_align,
|
||||
class,
|
||||
);
|
||||
|
||||
if (any_comptime_fields and !struct_obj.is_reified) {
|
||||
// We also resolve field inits in this case. MLUGG TODO: this sucks, see TODO in resolveStructDefaults
|
||||
return resolveStructDefaultsInner(sema, &block, &struct_obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type.
|
||||
@@ -465,105 +466,6 @@ fn resolvePackedStructLayout(
|
||||
);
|
||||
}
|
||||
|
||||
/// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type.
|
||||
/// This function *does* register the `src_hash` dependency on the struct.
|
||||
pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const comp = zcu.comp;
|
||||
const gpa = comp.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern());
|
||||
|
||||
try sema.ensureLayoutResolved(struct_ty, struct_ty.srcLoc(zcu));
|
||||
|
||||
const struct_obj = ip.loadStructType(struct_ty.toIntern());
|
||||
assert(struct_obj.want_defaults);
|
||||
|
||||
if (struct_obj.is_reified) {
|
||||
// `Sema.zirReifyStruct` has already populated the default field values *and* (by loading
|
||||
// the default values from pointers) validated their types, so we have nothing to do. We
|
||||
// don't even need to mark any dependencies.
|
||||
return;
|
||||
}
|
||||
|
||||
try sema.declareDependency(.{ .src_hash = struct_obj.zir_index });
|
||||
|
||||
if (struct_obj.field_defaults.len == 0) {
|
||||
// The struct has no default field values, so the slice has been omitted.
|
||||
return;
|
||||
}
|
||||
|
||||
for (struct_obj.field_is_comptime_bits.getAll(ip)) |bit_bag| {
|
||||
if (bit_bag != 0) {
|
||||
// There is a comptime field, so layout resolution already filled in the defaults for us!
|
||||
// MLUGG TODO: perhaps a better idea would be for layout resolution to populate only the defaults *for comptime fields*.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var block: Block = .{
|
||||
.parent = null,
|
||||
.sema = sema,
|
||||
.namespace = struct_obj.namespace,
|
||||
.instructions = .{},
|
||||
.inlining = null,
|
||||
.comptime_reason = undefined, // always set before using `block`
|
||||
.src_base_inst = struct_obj.zir_index,
|
||||
.type_name_ctx = struct_obj.name,
|
||||
};
|
||||
defer block.instructions.deinit(gpa);
|
||||
|
||||
return resolveStructDefaultsInner(sema, &block, &struct_obj);
|
||||
}
|
||||
/// MLUGG TODO: i dislike this, see the 'TODO' in the prev func
|
||||
fn resolveStructDefaultsInner(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
struct_obj: *const InternPool.LoadedStructType,
|
||||
) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
const zcu = pt.zcu;
|
||||
const comp = zcu.comp;
|
||||
const gpa = comp.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
// We'll need to map the struct decl instruction to provide result types
|
||||
const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;
|
||||
try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
|
||||
|
||||
const field_types = struct_obj.field_types.get(ip);
|
||||
|
||||
const zir_struct = sema.code.getStructDecl(zir_index);
|
||||
var field_it = zir_struct.iterateFields();
|
||||
while (field_it.next()) |zir_field| {
|
||||
const default_val_src = block.src(.{ .container_field_value = zir_field.idx });
|
||||
block.comptime_reason = .{ .reason = .{
|
||||
.src = default_val_src,
|
||||
.r = .{ .simple = .struct_field_default_value },
|
||||
} };
|
||||
const default_body = zir_field.default_body orelse {
|
||||
struct_obj.field_defaults.get(ip)[zir_field.idx] = .none;
|
||||
continue;
|
||||
};
|
||||
const field_ty: Type = .fromInterned(field_types[zir_field.idx]);
|
||||
const uncoerced = ref: {
|
||||
// Provide the result type
|
||||
sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern()));
|
||||
defer assert(sema.inst_map.remove(zir_index));
|
||||
break :ref try sema.resolveInlineBody(block, default_body, zir_index);
|
||||
};
|
||||
const coerced = try sema.coerce(block, field_ty, uncoerced, default_val_src);
|
||||
const default_val = try sema.resolveConstValue(block, default_val_src, coerced, null);
|
||||
if (default_val.canMutateComptimeVarState(zcu)) {
|
||||
const field_name = struct_obj.field_names.get(ip)[zir_field.idx];
|
||||
return sema.failWithContainsReferenceToComptimeVar(block, default_val_src, field_name, "field default value", default_val);
|
||||
}
|
||||
struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern();
|
||||
}
|
||||
}
|
||||
|
||||
/// This logic must be kept in sync with `Type.getUnionLayout`.
|
||||
pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
|
||||
const pt = sema.pt;
|
||||
@@ -583,7 +485,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
|
||||
.parent = null,
|
||||
.sema = sema,
|
||||
.namespace = union_obj.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = undefined, // always set before using `block`
|
||||
.src_base_inst = union_obj.zir_index,
|
||||
@@ -1048,7 +950,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
|
||||
.parent = null,
|
||||
.sema = sema,
|
||||
.namespace = enum_obj.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = undefined, // always set before using `block`
|
||||
.src_base_inst = tracked_inst,
|
||||
@@ -1287,8 +1189,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
|
||||
}
|
||||
}
|
||||
|
||||
// MLUGG TODO: fate of this line rests on whether comptime_int is a valid int tag type
|
||||
if (enum_obj.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
|
||||
if (enum_obj.nonexhaustive) {
|
||||
const fields_len = enum_obj.field_names.len;
|
||||
if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) {
|
||||
return sema.fail(&block, block.nodeOffset(.zero), "non-exhaustive enum specifies every value", .{});
|
||||
|
||||
+3
-5
@@ -3122,7 +3122,6 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
|
||||
.nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
|
||||
.nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }),
|
||||
.type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }),
|
||||
.struct_defaults => |ty| try zcu.markPoDependeeUpToDate(.{ .struct_defaults = ty }),
|
||||
.func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }),
|
||||
.memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }),
|
||||
}
|
||||
@@ -3138,7 +3137,6 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
|
||||
.nav_val => |nav| .{ .nav_val = nav },
|
||||
.nav_ty => |nav| .{ .nav_ty = nav },
|
||||
.type_layout => |ty| .{ .type_layout = ty },
|
||||
.struct_defaults => |ty| .{ .struct_defaults = ty },
|
||||
.func => |func_index| .{ .func_ies = func_index },
|
||||
.memoized_state => |stage| .{ .memoized_state = stage },
|
||||
};
|
||||
@@ -4116,7 +4114,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
|
||||
const other: AnalUnit = .wrap(switch (unit.unwrap()) {
|
||||
.nav_val => |n| .{ .nav_ty = n },
|
||||
.nav_ty => |n| .{ .nav_val = n },
|
||||
.@"comptime", .type_layout, .struct_defaults, .func, .memoized_state => break :queue_paired,
|
||||
.@"comptime", .type_layout, .func, .memoized_state => break :queue_paired,
|
||||
});
|
||||
const gop = try units.getOrPut(gpa, other);
|
||||
if (gop.found_existing) break :queue_paired;
|
||||
@@ -4273,7 +4271,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void
|
||||
}
|
||||
},
|
||||
.nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
|
||||
.type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
|
||||
.type_layout => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
|
||||
.func => |func| {
|
||||
const nav = zcu.funcInfo(func).owner_nav;
|
||||
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
|
||||
const fqn = ip.getNav(nav).fqn;
|
||||
return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) });
|
||||
},
|
||||
.type_layout, .struct_defaults => |ip_index, tag| {
|
||||
.type_layout => |ip_index, tag| {
|
||||
const name = Type.fromInterned(ip_index).containerTypeName(ip);
|
||||
return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) });
|
||||
},
|
||||
|
||||
+8
-114
@@ -865,7 +865,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage)
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.namespace = std_namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = .{ .reason = .{
|
||||
.src = src,
|
||||
@@ -1014,7 +1014,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.namespace = comptime_unit.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = .{ .reason = .{
|
||||
.src = .{
|
||||
@@ -1152,109 +1152,6 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void
|
||||
};
|
||||
}
|
||||
|
||||
/// Ensures that the default values of the given "declared" (not reified) `struct` type are fully
|
||||
/// up-to-date, performing re-analysis if necessary. Asserts that `ty` is a struct (not tuple) type.
|
||||
/// Returns `error.AnalysisFail` if an analysis error is encountered while resolving the default
|
||||
/// field values; the caller is free to ignore this, since the error is already registered.
|
||||
pub fn ensureStructDefaultsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
assert(ty.zigTypeTag(zcu) == .@"struct");
|
||||
assert(!ty.isTuple(zcu));
|
||||
|
||||
const anal_unit: AnalUnit = .wrap(.{ .struct_defaults = ty.toIntern() });
|
||||
|
||||
log.debug("ensureStructDefaultsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
|
||||
|
||||
assert(!zcu.analysis_in_progress.contains(anal_unit));
|
||||
|
||||
const was_outdated = zcu.outdated.swapRemove(anal_unit) or
|
||||
zcu.potentially_outdated.swapRemove(anal_unit) or
|
||||
zcu.intern_pool.setWantStructDefaults(zcu.comp.io, ty.toIntern());
|
||||
|
||||
if (was_outdated) {
|
||||
_ = zcu.outdated_ready.swapRemove(anal_unit);
|
||||
// `was_outdated` is true in the initial update, so this isn't a `dev.check`.
|
||||
if (dev.env.supports(.incremental)) {
|
||||
zcu.deleteUnitExports(anal_unit);
|
||||
zcu.deleteUnitReferences(anal_unit);
|
||||
zcu.deleteUnitCompileLogs(anal_unit);
|
||||
if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
|
||||
kv.value.destroy(gpa);
|
||||
}
|
||||
_ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
|
||||
zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
|
||||
}
|
||||
// For types, we already know that we have to invalidate all dependees.
|
||||
// TODO: we actually *could* detect whether everything was the same. should we bother?
|
||||
try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() });
|
||||
} else {
|
||||
// We can trust the current information about this unit.
|
||||
if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
|
||||
if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail;
|
||||
return;
|
||||
}
|
||||
|
||||
if (zcu.comp.debugIncremental()) {
|
||||
const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
|
||||
info.last_update_gen = zcu.generation;
|
||||
info.deps.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null);
|
||||
defer unit_tracking.end(zcu);
|
||||
|
||||
try zcu.analysis_in_progress.put(gpa, anal_unit, {});
|
||||
defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
|
||||
|
||||
var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
|
||||
defer analysis_arena.deinit();
|
||||
|
||||
var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa);
|
||||
defer comptime_err_ret_trace.deinit();
|
||||
|
||||
const zir = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu).zir.?;
|
||||
|
||||
var sema: Sema = .{
|
||||
.pt = pt,
|
||||
.gpa = gpa,
|
||||
.arena = analysis_arena.allocator(),
|
||||
.code = zir,
|
||||
.owner = anal_unit,
|
||||
.func_index = .none,
|
||||
.func_is_naked = false,
|
||||
.fn_ret_ty = .void,
|
||||
.fn_ret_ty_ies = null,
|
||||
.comptime_err_ret_trace = &comptime_err_ret_trace,
|
||||
};
|
||||
defer sema.deinit();
|
||||
|
||||
Sema.type_resolution.resolveStructDefaults(&sema, ty) catch |err| switch (err) {
|
||||
error.AnalysisFail => {
|
||||
if (!zcu.failed_analysis.contains(anal_unit)) {
|
||||
// If this unit caused the error, it would have an entry in `failed_analysis`.
|
||||
// Since it does not, this must be a transitive failure.
|
||||
try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
|
||||
log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
|
||||
}
|
||||
return error.AnalysisFail;
|
||||
},
|
||||
error.OutOfMemory,
|
||||
error.Canceled,
|
||||
=> |e| return e,
|
||||
error.ComptimeReturn => unreachable,
|
||||
error.ComptimeBreak => unreachable,
|
||||
};
|
||||
|
||||
sema.flushExports() catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
|
||||
/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
|
||||
/// 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
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.namespace = old_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = undefined, // set below
|
||||
.src_base_inst = old_nav.analysis.?.zir_index,
|
||||
@@ -1831,7 +1728,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.namespace = old_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = undefined, // set below
|
||||
.src_base_inst = old_nav.analysis.?.zir_index,
|
||||
@@ -3078,7 +2975,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem
|
||||
.parent = null,
|
||||
.sema = &sema,
|
||||
.namespace = decl_nav.analysis.?.namespace,
|
||||
.instructions = .{},
|
||||
.instructions = .empty,
|
||||
.inlining = null,
|
||||
.comptime_reason = null,
|
||||
.src_base_inst = decl_nav.analysis.?.zir_index,
|
||||
@@ -3327,7 +3224,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
|
||||
break :gop .{ gop.value_ptr, gop.found_existing };
|
||||
},
|
||||
};
|
||||
if (!found_existing) value_ptr.* = .{};
|
||||
if (!found_existing) value_ptr.* = .empty;
|
||||
try value_ptr.append(gpa, export_idx);
|
||||
}
|
||||
|
||||
@@ -3356,7 +3253,7 @@ pub fn processExports(pt: Zcu.PerThread) !void {
|
||||
break :gop .{ gop.value_ptr, gop.found_existing };
|
||||
},
|
||||
};
|
||||
if (!found_existing) value_ptr.* = .{};
|
||||
if (!found_existing) value_ptr.* = .empty;
|
||||
try value_ptr.append(gpa, @enumFromInt(export_idx));
|
||||
}
|
||||
}
|
||||
@@ -4353,10 +4250,7 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
|
||||
},
|
||||
|
||||
.@"struct" => switch (ip.indexToKey(ty.toIntern())) {
|
||||
.struct_type => {
|
||||
try pt.ensureTypeLayoutUpToDate(ty);
|
||||
try pt.ensureStructDefaultsUpToDate(ty);
|
||||
},
|
||||
.struct_type => try pt.ensureTypeLayoutUpToDate(ty),
|
||||
.tuple_type => |tuple| for (0..tuple.types.len) |i| {
|
||||
const field_is_comptime = tuple.values.get(ip)[i] != .none;
|
||||
if (field_is_comptime) continue;
|
||||
|
||||
@@ -1054,13 +1054,13 @@ pub const Pool = struct {
|
||||
};
|
||||
|
||||
pub const empty: Pool = .{
|
||||
.map = .{},
|
||||
.items = .{},
|
||||
.extra = .{},
|
||||
.map = .empty,
|
||||
.items = .empty,
|
||||
.extra = .empty,
|
||||
|
||||
.string_map = .{},
|
||||
.string_indices = .{},
|
||||
.string_bytes = .{},
|
||||
.string_map = .empty,
|
||||
.string_indices = .empty,
|
||||
.string_bytes = .empty,
|
||||
};
|
||||
|
||||
pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void {
|
||||
|
||||
@@ -775,7 +775,7 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO
|
||||
|
||||
const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
gop.value_ptr.* = .empty;
|
||||
}
|
||||
try gop.value_ptr.append(elf_file.base.comp.gpa, self.index);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
|
||||
const ptr_size = elf_file.ptrWidthBytes();
|
||||
|
||||
try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section
|
||||
try self.relocs.append(gpa, .{}); // null relocs section
|
||||
try self.relocs.append(gpa, .empty); // null relocs section
|
||||
try self.strtab.buffer.append(gpa, 0);
|
||||
|
||||
{
|
||||
@@ -546,7 +546,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
|
||||
atom_ptr.name_offset = name_off;
|
||||
|
||||
const relocs_index: u32 = @intCast(self.relocs.items.len);
|
||||
self.relocs.addOneAssumeCapacity().* = .{};
|
||||
self.relocs.addOneAssumeCapacity().* = .empty;
|
||||
atom_ptr.relocs_section_index = relocs_index;
|
||||
|
||||
return index;
|
||||
@@ -730,7 +730,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
|
||||
|
||||
const gop = try dupes.getOrPut(self.symbols_resolver.items[i]);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
gop.value_ptr.* = .empty;
|
||||
}
|
||||
try gop.value_ptr.append(elf_file.base.comp.gpa, self.index);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ data: std.ArrayList(u8) = .empty,
|
||||
basename: []const u8,
|
||||
index: File.Index,
|
||||
|
||||
symtab: std.MultiArrayList(Nlist) = .{},
|
||||
symtab: std.MultiArrayList(Nlist) = .empty,
|
||||
strtab: StringTable = .{},
|
||||
|
||||
symbols: std.ArrayList(Symbol) = .empty,
|
||||
@@ -29,7 +29,7 @@ uavs: UavTable = .{},
|
||||
tlv_initializers: TlvInitializerTable = .{},
|
||||
|
||||
/// A table of relocations.
|
||||
relocs: RelocationTable = .{},
|
||||
relocs: RelocationTable = .empty,
|
||||
|
||||
dwarf: ?Dwarf = null,
|
||||
|
||||
|
||||
+2
-2
@@ -78,7 +78,7 @@ export_table: bool,
|
||||
/// Output name of the file
|
||||
name: []const u8,
|
||||
/// List of relocatable files to be linked into the final binary.
|
||||
objects: std.ArrayList(Object) = .{},
|
||||
objects: std.ArrayList(Object) = .empty,
|
||||
|
||||
func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty,
|
||||
/// Provides a mapping of both imports and provided functions to symbol name.
|
||||
@@ -278,7 +278,7 @@ any_tls_relocs: bool = false,
|
||||
any_passive_inits: bool = false,
|
||||
|
||||
/// All MIR instructions for all Zcu functions.
|
||||
mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
|
||||
mir_instructions: std.MultiArrayList(Mir.Inst) = .empty,
|
||||
/// Corresponds to `mir_instructions`.
|
||||
mir_extra: std.ArrayList(u32) = .empty,
|
||||
/// All local types for all Zcu functions.
|
||||
|
||||
+9
-9
@@ -979,7 +979,7 @@ fn buildOutputType(
|
||||
.dirs = undefined,
|
||||
.object_format = null,
|
||||
.dynamic_linker = null,
|
||||
.modules = .{},
|
||||
.modules = .empty,
|
||||
.opts = .{
|
||||
.is_test = switch (arg_mode) {
|
||||
.zig_test, .zig_test_obj => true,
|
||||
@@ -1006,18 +1006,18 @@ fn buildOutputType(
|
||||
.windows_libs = .empty,
|
||||
.link_inputs = .empty,
|
||||
|
||||
.c_source_files = .{},
|
||||
.rc_source_files = .{},
|
||||
.c_source_files = .empty,
|
||||
.rc_source_files = .empty,
|
||||
|
||||
.llvm_m_args = .{},
|
||||
.llvm_m_args = .empty,
|
||||
.sysroot = null,
|
||||
.lib_directories = .{}, // populated by createModule()
|
||||
.lib_dir_args = .{}, // populated from CLI arg parsing
|
||||
.lib_directories = .empty, // populated by createModule()
|
||||
.lib_dir_args = .empty, // populated from CLI arg parsing
|
||||
.libc_installation = null,
|
||||
.want_native_include_dirs = false,
|
||||
.frameworks = .{},
|
||||
.framework_dirs = .{},
|
||||
.rpath_list = .{},
|
||||
.frameworks = .empty,
|
||||
.framework_dirs = .empty,
|
||||
.rpath_list = .empty,
|
||||
.each_lib_rpath = null,
|
||||
.libc_paths_file = EnvVar.ZIG_LIBC.get(environ_map),
|
||||
.native_system_include_paths = &.{},
|
||||
|
||||
Reference in New Issue
Block a user