commit c2b42383eb058f4c2bd17738cd73382e6a6672eb (tree)
parent 9c9a5e722b84d12de34d16f53355adbe1f5e11d3
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date: Mon, 2 Mar 2026 17:35:02 +0000
compiler,std: various little fixes
Diffstat:
11 files changed, 246 insertions(+), 98 deletions(-)
diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig
@@ -1526,9 +1526,9 @@ pub fn HashMapUnmanaged(
}
comptime {
- if (!builtin.strip_debug_info) _ = switch (builtin.zig_backend) {
- .stage2_llvm => &dbHelper,
- .stage2_x86_64 => KV,
+ if (!builtin.strip_debug_info) switch (builtin.zig_backend) {
+ .stage2_llvm => _ = &dbHelper,
+ .stage2_x86_64 => _ = @as(KV, undefined),
else => {},
};
}
diff --git a/src/InternPool.zig b/src/InternPool.zig
@@ -3334,11 +3334,17 @@ pub const LoadedStructType = struct {
field_defaults: Index.Slice,
field_aligns: Alignment.Slice,
field_is_comptime_bits: ComptimeBits,
+ /// If `layout` is `.@"packed"`, this is `.empty`.
field_runtime_order: RuntimeOrder.Slice,
+ /// If `layout` is `.@"packed"`, this is `.empty`.
field_offsets: Offsets,
+ /// Only valid if `layout` is `.@"packed"`.
packed_backing_int_type: Index,
+ /// Only valid if `layout` is *not* `.@"packed"`.
class: TypeClass,
+ /// Only valid if `layout` is *not* `.@"packed"`.
size: u32,
+ /// Only valid if `layout` is *not* `.@"packed"`.
alignment: Alignment,
pub const ComptimeBits = struct {
@@ -3516,15 +3522,21 @@ pub const LoadedUnionType = struct {
tag_usage: TagUsage,
/// While `tag_usage` indicates whether the union should logically contain a tag, it may be
/// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an
- /// actual runtime tag in the union layout.
+ /// actual runtime tag, with one or more runtime bits, in the union layout. It is always `false`
+ /// if `layout` is not `.auto`.
has_runtime_tag: bool,
/// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with
/// the union's "hypothetical" tag type.
enum_tag_type: Index,
+ /// Only valid if `layout` is `.@"packed"`.
packed_backing_int_type: Index,
+ /// Not valid if `layout` is `.@"packed"`.
class: TypeClass,
+ /// Not valid if `layout` is `.@"packed"`.
size: u32,
+ /// Not valid if `layout` is `.@"packed"`.
padding: u32,
+ /// Not valid if `layout` is `.@"packed"`.
alignment: Alignment,
pub const TagUsage = enum(u2) {
@@ -3898,7 +3910,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
.want_layout = extra.data.bits.want_layout,
.field_types = field_types,
.field_aligns = .empty,
- .has_runtime_tag = undefined,
+ .has_runtime_tag = false,
.class = undefined,
.size = undefined,
.padding = undefined,
diff --git a/src/Sema.zig b/src/Sema.zig
@@ -13777,45 +13777,44 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
// lhs_dest_slice = dest[0..lhs.len]
- const slice_ty_ref = Air.internedToRef(slice_ty.toIntern());
- const lhs_len_ref = try pt.intRef(.usize, lhs_len);
- const lhs_dest_slice = try block.addInst(.{
- .tag = .slice,
- .data = .{ .ty_pl = .{
- .ty = slice_ty_ref,
- .payload = try sema.addExtra(Air.Bin{
- .lhs = many_alloc,
- .rhs = lhs_len_ref,
- }),
- } },
- });
-
- _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs);
+ if (lhs_len > 0) {
+ const lhs_dest_slice = try block.addInst(.{
+ .tag = .slice,
+ .data = .{ .ty_pl = .{
+ .ty = .fromType(slice_ty),
+ .payload = try sema.addExtra(Air.Bin{
+ .lhs = many_alloc,
+ .rhs = try pt.intRef(.usize, lhs_len),
+ }),
+ } },
+ });
+ _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs);
+ }
// rhs_dest_slice = dest[lhs.len..][0..rhs.len]
- const rhs_len_ref = try pt.intRef(.usize, rhs_len);
- const rhs_dest_offset = try block.addInst(.{
- .tag = .ptr_add,
- .data = .{ .ty_pl = .{
- .ty = Air.internedToRef(many_ty.toIntern()),
- .payload = try sema.addExtra(Air.Bin{
- .lhs = many_alloc,
- .rhs = lhs_len_ref,
- }),
- } },
- });
- const rhs_dest_slice = try block.addInst(.{
- .tag = .slice,
- .data = .{ .ty_pl = .{
- .ty = slice_ty_ref,
- .payload = try sema.addExtra(Air.Bin{
- .lhs = rhs_dest_offset,
- .rhs = rhs_len_ref,
- }),
- } },
- });
-
- _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs);
+ if (rhs_len > 0) {
+ const rhs_dest_offset = try block.addInst(.{
+ .tag = .ptr_add,
+ .data = .{ .ty_pl = .{
+ .ty = Air.internedToRef(many_ty.toIntern()),
+ .payload = try sema.addExtra(Air.Bin{
+ .lhs = many_alloc,
+ .rhs = try pt.intRef(.usize, lhs_len),
+ }),
+ } },
+ });
+ const rhs_dest_slice = try block.addInst(.{
+ .tag = .slice,
+ .data = .{ .ty_pl = .{
+ .ty = .fromType(slice_ty),
+ .payload = try sema.addExtra(Air.Bin{
+ .lhs = rhs_dest_offset,
+ .rhs = try pt.intRef(.usize, rhs_len),
+ }),
+ } },
+ });
+ _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs);
+ }
if (res_sent_val) |sent_val| {
const elem_index = try pt.intRef(.usize, result_len);
@@ -18829,7 +18828,7 @@ fn finishStructInit(
return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref);
},
.@"packed" => {
- const buf = try sema.arena.alloc(u8, (struct_ty.bitSize(zcu) + 7) / 8);
+ const buf = try sema.arena.alloc(u8, @intCast((struct_ty.bitSize(zcu) + 7) / 8));
var bit_offset: u16 = 0;
for (field_inits) |field_init| {
const field_val = sema.resolveValue(field_init).?;
@@ -21113,7 +21112,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
else => unreachable,
};
- if (!dest_err_ty.isAnyError(zcu) and !dest_err_ty.errorSetHasField(err_name, zcu)) {
+ if (result != .superset and !dest_err_ty.errorSetHasField(err_name, zcu)) {
return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{
err_name.fmt(ip), dest_err_ty.fmt(pt),
});
@@ -25186,9 +25185,18 @@ pub fn explainWhyTypeIsNotExtern(
else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}),
},
.@"enum" => {
- const tag_ty = ty.intTagType(zcu);
- try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});
- try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
+ const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern());
+ switch (enum_obj.int_tag_mode) {
+ .auto => {
+ try sema.errNote(ty.srcLoc(zcu), msg, "integer tag type of enum is inferred", .{});
+ try sema.errNote(ty.srcLoc(zcu), msg, "consider explicitly specifying the integer tag type", .{});
+ },
+ .explicit => {
+ const tag_ty: Type = .fromInterned(enum_obj.int_tag_type);
+ try sema.errNote(ty.srcLoc(zcu), msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});
+ try sema.explainWhyTypeIsNotExtern(msg, ty.srcLoc(zcu), tag_ty, position);
+ },
+ }
},
.@"struct" => {
const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern());
diff --git a/src/Value.zig b/src/Value.zig
@@ -895,7 +895,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value {
// Avoid hitting gpa for accesses to small packed structs
var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa);
const sfba = sfba_state.get();
- const buf = try sfba.alloc(u8, (ty.bitSize(zcu) + 7) / 8);
+ const buf = try sfba.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8));
defer sfba.free(buf);
int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) {
error.ReinterpretDeclRef => unreachable, // it's an integer
@@ -2419,7 +2419,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory
}
for (field_vals, 0..) |*field_val, field_idx| {
if (field_val.* == .none) {
- const default_init = struct_obj.field_inits.get(ip)[field_idx];
+ const default_init = struct_obj.field_defaults.get(ip)[field_idx];
if (default_init == .none) return error.TypeMismatch;
field_val.* = default_init;
}
diff --git a/src/Zcu.zig b/src/Zcu.zig
@@ -3686,6 +3686,11 @@ pub const ImportResult = struct {
pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void {
const gpa = zcu.comp.gpa;
+ if (!dev.env.supports(.incremental)) {
+ // This is the first time `unit` is being analyzed, so there is no stale data to clear.
+ return;
+ }
+
// Compile errors
if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| {
kv.value.destroy(gpa);
@@ -4309,7 +4314,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag
});
const gop = try units.getOrPut(gpa, other);
if (gop.found_existing) break :queue_paired;
- gop.value_ptr.* = units.values()[unit_idx]; // same reference location
+ gop.value_ptr.* = units.values()[unit_idx - 1]; // same reference location
}
refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
@@ -1075,7 +1075,6 @@ pub fn ensureMemoizedStateUpToDate(
const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit);
if (was_outdated) {
- dev.check(.incremental);
zcu.resetUnit(unit);
} else {
if (prev_failed) return error.AnalysisFail;
@@ -1193,10 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
const was_outdated = zcu.clearOutdatedState(anal_unit);
if (was_outdated) {
- // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`.
- if (dev.env.supports(.incremental)) {
- zcu.resetUnit(anal_unit);
- }
+ zcu.resetUnit(anal_unit);
} else {
// We can trust the current information about this unit.
if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
@@ -1366,10 +1362,7 @@ pub fn ensureTypeLayoutUpToDate(
};
if (was_outdated) {
- // `was_outdated` is true in the initial update, so this isn't a `dev.check`.
- if (dev.env.supports(.incremental)) {
- zcu.resetUnit(anal_unit);
- }
+ zcu.resetUnit(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, .{ .type_layout = ty.toIntern() });
@@ -1492,10 +1485,7 @@ pub fn ensureStructDefaultsUpToDate(
};
if (was_outdated) {
- // `was_outdated` is true in the initial update, so this isn't a `dev.check`.
- if (dev.env.supports(.incremental)) {
- zcu.resetUnit(anal_unit);
- }
+ zcu.resetUnit(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() });
@@ -1609,7 +1599,6 @@ pub fn ensureNavValUpToDate(
zcu.transitive_failed_analysis.contains(anal_unit);
if (was_outdated) {
- dev.check(.incremental);
zcu.resetUnit(anal_unit);
} else {
// We can trust the current information about this unit.
@@ -1893,6 +1882,30 @@ fn analyzeNavVal(
}
}
+ // We're about to resolve the value of the Nav. This causes the information about what the value
+ // was last update to be lost; therefore, if the `nav_ty` is currently out of date, it would
+ // incorrectly think it was unchanged when eventually analyzed. To avoid this, we need to detect
+ // that case and invalidate the dependee right now.
+ if (zcu.clearOutdatedState(.wrap(.{ .nav_ty = nav_id }))) {
+ assert(zir_decl.type_body == null); // otherwise we already resolved it with `Sema.ensureNavResolved`
+ zcu.resetUnit(.wrap(.{ .nav_ty = nav_id }));
+ try pt.addDependency(.wrap(.{ .nav_ty = nav_id }), .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!)
+ if (comp.debugIncremental()) {
+ const info = try zcu.incremental_debug_state.getUnitInfo(gpa, .wrap(.{ .nav_ty = nav_id }));
+ info.last_update_gen = zcu.generation;
+ info.deps.clearRetainingCapacity();
+ }
+ const type_changed: bool = switch (old_nav.status) {
+ .unresolved => true,
+ .type_resolved => |old| old.type != nav_ty.toIntern(),
+ .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(),
+ };
+ if (type_changed) {
+ try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id });
+ } else {
+ try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id });
+ }
+ }
ip.resolveNavValue(io, nav_id, .{
.val = nav_val.toIntern(),
.is_const = is_const,
@@ -1930,10 +1943,10 @@ fn analyzeNavVal(
try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
}
- switch (old_nav.status) {
- .unresolved, .type_resolved => return .{ .val_changed = true },
- .fully_resolved => |old| return .{ .val_changed = old.val != nav_val.toIntern() },
- }
+ return switch (old_nav.status) {
+ .unresolved, .type_resolved => .{ .val_changed = true },
+ .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() },
+ };
}
pub fn ensureNavTypeUpToDate(
@@ -1973,7 +1986,6 @@ pub fn ensureNavTypeUpToDate(
zcu.transitive_failed_analysis.contains(anal_unit);
if (was_outdated) {
- dev.check(.incremental);
zcu.resetUnit(anal_unit);
} else {
// We can trust the current information about this unit.
@@ -2107,12 +2119,29 @@ fn analyzeNavType(
const type_body = zir_decl.type_body orelse {
// There is no type annotation, so we just need to use the declaration's value.
+ // If the value had already been re-analyzed, it would have resolved the `nav_ty` unit as
+ // either outdated or up-to-date. So we know that `old_nav` does contain information from
+ // the previous update. As such, after this call, we will be able to determine whether the
+ // type changed.
try sema.ensureNavResolved(&block, init_src, nav_id, .fully);
- // We don't actually know what the type of this Nav was before it was resolved, so we just
- // have to assume we were outdated. This isn't too bad, because assuming there was also no
- // type annotation last update, we should only be re-analyzed if the value changes (it's our
- // only dependency), or if there was a dependency loop.
- return .{ .type_changed = true };
+ const new = ip.getNav(nav_id).status.fully_resolved;
+ const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern";
+ const changed = switch (old_nav.status) {
+ .unresolved => true,
+ .type_resolved => |r| r.type != ip.typeOf(new.val) or
+ r.alignment != new.alignment or
+ r.@"linksection" != new.@"linksection" or
+ r.@"addrspace" != new.@"addrspace" or
+ r.is_const != new.is_const or
+ r.is_extern_decl != new_is_extern_decl,
+ .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or
+ r.alignment != new.alignment or
+ r.@"linksection" != new.@"linksection" or
+ r.@"addrspace" != new.@"addrspace" or
+ r.is_const != new.is_const or
+ (old_nav.getExtern(ip) != null) != new_is_extern_decl,
+ };
+ return .{ .type_changed = changed };
};
block.comptime_reason = .{ .reason = .{
@@ -2210,7 +2239,6 @@ pub fn ensureFuncBodyUpToDate(
const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);
if (was_outdated) {
- dev.check(.incremental);
zcu.resetUnit(anal_unit);
} else {
// We can trust the current information about this function.
@@ -2292,7 +2320,7 @@ fn analyzeFuncBody(
var air = try pt.analyzeFuncBodyInner(func_index, reason);
var air_owned = true;
- errdefer if (air_owned) air.deinit(gpa);
+ defer if (air_owned) air.deinit(gpa);
const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or
func.resolvedErrorSetUnordered(ip) != old_resolved_ies;
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
@@ -7132,9 +7132,9 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void
var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined;
for (0..big.limbs_len) |limb_index| {
if (limb_index != 0) try w.writeAll(", ");
- const limb_bit_offset: u64 = switch (target.cpu.arch.endian()) {
- .little => limb_index * big.limb_size.bits(),
- .big => (big.limbs_len - limb_index - 1) * big.limb_size.bits(),
+ const limb_bit_offset: u16 = switch (target.cpu.arch.endian()) {
+ .little => @intCast(limb_index * big.limb_size.bits()),
+ .big => @intCast((big.limbs_len - limb_index - 1) * big.limb_size.bits()),
};
var limb_bigint: std.math.big.int.Mutable = .{
.limbs = &limb_buf,
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
@@ -2432,7 +2432,7 @@ pub const Object = struct {
const debug_payload_type = try o.builder.debugUnionType(
payload_name: {
if (layout.tag_size == 0) break :payload_name name;
- break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)});
+ break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(pt)});
},
file,
scope,
diff --git a/src/link.zig b/src/link.zig
@@ -1557,7 +1557,10 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
.link_func => |codegen_task| nav: {
timer.pause(io);
const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) {
- error.Canceled, error.AlreadyReported => return,
+ error.Canceled, error.AlreadyReported => {
+ comp.link_prog_node.completeOne();
+ return;
+ },
};
defer mir.deinit(zcu);
timer.@"resume"(io);
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
@@ -3344,6 +3344,7 @@ pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index
}
fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void {
const zcu = pt.zcu;
+ const ip = &zcu.intern_pool;
const val: Value = .fromInterned(value_index);
@@ -3383,20 +3384,109 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde
.debug_loclists = .init(dwarf.gpa),
};
defer wip_nav.deinit();
- switch (val.typeOf(zcu).toIntern()) {
- .type_type => {
- try wip_nav.abbrevCode(.generated_empty_struct_type);
- try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
- try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
+
+ switch (ip.indexToKey(value_index)) {
+ // Container types still need to be valid namespaces.
+ .struct_type => {
+ const loaded_struct = ip.loadStructType(value_index);
+ const root_of_file: ?Zcu.File.Index = if (loaded_struct.zir_index.resolveFull(ip)) |r| f: {
+ if (r.inst != .main_struct_inst) break :f null;
+ break :f r.file;
+ } else null;
+ if (root_of_file) |file_index| {
+ assert(loaded_struct.name_nav == .none);
+ const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index);
+ try wip_nav.abbrevCode(.empty_file);
+ try wip_nav.debug_info.writer.writeUleb128(file_gop.index);
+ try wip_nav.strp(loaded_struct.name.toSlice(ip));
+ } else {
+ try dwarf.emitIncompleteContainerType(
+ &wip_nav,
+ loaded_struct.zir_index,
+ loaded_struct.name,
+ loaded_struct.name_nav,
+ );
+ }
},
- else => |ty| {
- try wip_nav.abbrevCode(.undefined_comptime_value);
- try wip_nav.refType(.fromInterned(ty));
+ .union_type => {
+ const loaded_union = ip.loadUnionType(value_index);
+ try dwarf.emitIncompleteContainerType(
+ &wip_nav,
+ loaded_union.zir_index,
+ loaded_union.name,
+ loaded_union.name_nav,
+ );
+ },
+ .enum_type => {
+ const loaded_enum = ip.loadEnumType(value_index);
+ if (loaded_enum.zir_index.unwrap()) |zir_index| {
+ try dwarf.emitIncompleteContainerType(
+ &wip_nav,
+ zir_index,
+ loaded_enum.name,
+ loaded_enum.name_nav,
+ );
+ } else {
+ try wip_nav.abbrevCode(.generated_empty_struct_type);
+ try wip_nav.strp(loaded_enum.name.toSlice(ip));
+ try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
+ }
+ },
+ .opaque_type => {
+ const loaded_opaque = ip.loadOpaqueType(value_index);
+ try dwarf.emitIncompleteContainerType(
+ &wip_nav,
+ loaded_opaque.zir_index,
+ loaded_opaque.name,
+ loaded_opaque.name_nav,
+ );
+ },
+ // Not a container type, so just emit a dummy entry. If `val` happens to be a type, we'll
+ // emit it as if it were an opaque type so that we can name it.
+ else => |val_key| switch (val_key.typeOf()) {
+ .type_type => {
+ try wip_nav.abbrevCode(.generated_empty_struct_type);
+ try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
+ try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
+ },
+ else => |ty| {
+ try wip_nav.abbrevCode(.undefined_comptime_value);
+ try wip_nav.refType(.fromInterned(ty));
+ },
},
}
try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written());
try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written());
}
+fn emitIncompleteContainerType(
+ dwarf: *Dwarf,
+ wip_nav: *WipNav,
+ zir_index: InternPool.TrackedInst.Index,
+ name: InternPool.NullTerminatedString,
+ name_nav: InternPool.Nav.Index.Optional,
+) !void {
+ const zcu = wip_nav.pt.zcu;
+ const ip = &zcu.intern_pool;
+ const file = zir_index.resolveFile(ip);
+ if (name_nav.unwrap()) |nav_index| {
+ const nav = ip.getNav(nav_index);
+ const decl_inst = nav.srcInst(ip).resolve(ip).?;
+ const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
+ try wip_nav.declCommon(.{
+ .decl = .decl_namespace_struct,
+ .generic_decl = .generic_decl_const,
+ .decl_instance = .decl_instance_namespace_struct,
+ }, &nav, file, &decl);
+ try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
+ } else {
+ const diw = &wip_nav.debug_info.writer;
+ const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file);
+ try wip_nav.abbrevCode(.empty_struct_type);
+ try diw.writeUleb128(file_gop.index);
+ try wip_nav.strp(name.toSlice(ip));
+ try diw.writeByte(@intFromBool(true));
+ }
+}
/// Should only be called by the `link.ConstPool` implementation.
///
/// Emits a DIE for the given comptime-only value (which may be a type).
@@ -3418,6 +3508,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
val.typeOf(zcu).assertHasLayout(zcu);
}
+ if (value_index == .anyerror_type) return; // handled in `flush` instead
+
const value_ip_key = ip.indexToKey(value_index);
switch (value_ip_key) {
.func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`)
@@ -3746,7 +3838,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
try wip_nav.abbrevCode(.void_type);
try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
},
- .anyerror => return, // delay until flush
+ .anyerror => unreachable, // already did early return above
.adhoc_inferred_error_set => unreachable,
},
.tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
diff --git a/tools/incr-check.zig b/tools/incr-check.zig
@@ -311,12 +311,12 @@ const Eval = struct {
.error_bundle => {
const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
if (stderr.bufferedLen() > 0) {
- const stderr_data = try mr.toOwnedSlice(1);
if (eval.allow_stderr) {
- std.log.info("error_bundle stderr:\n{s}", .{stderr_data});
+ std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()});
} else {
- eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data});
+ eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()});
}
+ stderr.tossBuffered();
}
if (result_error_bundle.errorMessageCount() != 0) {
try eval.checkErrorOutcome(update, result_error_bundle);
@@ -327,15 +327,15 @@ const Eval = struct {
.emit_digest => {
var r: std.Io.Reader = .fixed(body);
_ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
+
if (stderr.bufferedLen() > 0) {
- const stderr_data = try mr.toOwnedSlice(1);
if (eval.allow_stderr) {
- std.log.info("emit_digest stderr:\n{s}", .{stderr_data});
+ std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()});
} else {
- eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data});
+ eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()});
}
+ stderr.tossBuffered();
}
-
if (eval.target.backend == .sema) {
try eval.checkSuccessOutcome(update, null, prog_node);
continue;
@@ -369,7 +369,7 @@ const Eval = struct {
}
waitChild(eval.child, eval);
- eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{});
+ eval.fatal("compiler failed to send terminating error_bundle", .{});
}
fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void {