authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-02 17:35:02+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:14+00:00
logc2b42383eb058f4c2bd17738cd73382e6a6672eb
tree064a6184bbb51ac4c6985deab38b0c0e5bc37132
parent9c9a5e722b84d12de34d16f53355adbe1f5e11d3
signaturelock-open Commit is signed but in an unrecognized format.

compiler,std: various little fixes


11 files changed, 246 insertions(+), 98 deletions(-)

lib/std/hash_map.zig+3-3
...@@ -1526,9 +1526,9 @@ pub fn HashMapUnmanaged(...@@ -1526,9 +1526,9 @@ pub fn HashMapUnmanaged(
1526 }1526 }
15271527
1528 comptime {1528 comptime {
1529 if (!builtin.strip_debug_info) _ = switch (builtin.zig_backend) {1529 if (!builtin.strip_debug_info) switch (builtin.zig_backend) {
1530 .stage2_llvm => &dbHelper,1530 .stage2_llvm => _ = &dbHelper,
1531 .stage2_x86_64 => KV,1531 .stage2_x86_64 => _ = @as(KV, undefined),
1532 else => {},1532 else => {},
1533 };1533 };
1534 }1534 }
src/InternPool.zig+14-2
...@@ -3334,11 +3334,17 @@ pub const LoadedStructType = struct {...@@ -3334,11 +3334,17 @@ pub const LoadedStructType = struct {
3334 field_defaults: Index.Slice,3334 field_defaults: Index.Slice,
3335 field_aligns: Alignment.Slice,3335 field_aligns: Alignment.Slice,
3336 field_is_comptime_bits: ComptimeBits,3336 field_is_comptime_bits: ComptimeBits,
3337 /// If `layout` is `.@"packed"`, this is `.empty`.
3337 field_runtime_order: RuntimeOrder.Slice,3338 field_runtime_order: RuntimeOrder.Slice,
3339 /// If `layout` is `.@"packed"`, this is `.empty`.
3338 field_offsets: Offsets,3340 field_offsets: Offsets,
3341 /// Only valid if `layout` is `.@"packed"`.
3339 packed_backing_int_type: Index,3342 packed_backing_int_type: Index,
3343 /// Only valid if `layout` is *not* `.@"packed"`.
3340 class: TypeClass,3344 class: TypeClass,
3345 /// Only valid if `layout` is *not* `.@"packed"`.
3341 size: u32,3346 size: u32,
3347 /// Only valid if `layout` is *not* `.@"packed"`.
3342 alignment: Alignment,3348 alignment: Alignment,
33433349
3344 pub const ComptimeBits = struct {3350 pub const ComptimeBits = struct {
...@@ -3516,15 +3522,21 @@ pub const LoadedUnionType = struct {...@@ -3516,15 +3522,21 @@ pub const LoadedUnionType = struct {
3516 tag_usage: TagUsage,3522 tag_usage: TagUsage,
3517 /// While `tag_usage` indicates whether the union should logically contain a tag, it may be3523 /// While `tag_usage` indicates whether the union should logically contain a tag, it may be
3518 /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an3524 /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an
3519 /// actual runtime tag in the union layout.3525 /// actual runtime tag, with one or more runtime bits, in the union layout. It is always `false`
3526 /// if `layout` is not `.auto`.
3520 has_runtime_tag: bool,3527 has_runtime_tag: bool,
3521 /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with3528 /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with
3522 /// the union's "hypothetical" tag type.3529 /// the union's "hypothetical" tag type.
3523 enum_tag_type: Index,3530 enum_tag_type: Index,
3531 /// Only valid if `layout` is `.@"packed"`.
3524 packed_backing_int_type: Index,3532 packed_backing_int_type: Index,
3533 /// Not valid if `layout` is `.@"packed"`.
3525 class: TypeClass,3534 class: TypeClass,
3535 /// Not valid if `layout` is `.@"packed"`.
3526 size: u32,3536 size: u32,
3537 /// Not valid if `layout` is `.@"packed"`.
3527 padding: u32,3538 padding: u32,
3539 /// Not valid if `layout` is `.@"packed"`.
3528 alignment: Alignment,3540 alignment: Alignment,
35293541
3530 pub const TagUsage = enum(u2) {3542 pub const TagUsage = enum(u2) {
...@@ -3898,7 +3910,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {...@@ -3898,7 +3910,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
3898 .want_layout = extra.data.bits.want_layout,3910 .want_layout = extra.data.bits.want_layout,
3899 .field_types = field_types,3911 .field_types = field_types,
3900 .field_aligns = .empty,3912 .field_aligns = .empty,
3901 .has_runtime_tag = undefined,3913 .has_runtime_tag = false,
3902 .class = undefined,3914 .class = undefined,
3903 .size = undefined,3915 .size = undefined,
3904 .padding = undefined,3916 .padding = undefined,
src/Sema.zig+50-42
...@@ -13777,45 +13777,44 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13777,45 +13777,44 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13777 const many_alloc = try block.addBitCast(many_ty, mutable_alloc);13777 const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
1377813778
13779 // lhs_dest_slice = dest[0..lhs.len]13779 // lhs_dest_slice = dest[0..lhs.len]
13780 const slice_ty_ref = Air.internedToRef(slice_ty.toIntern());13780 if (lhs_len > 0) {
13781 const lhs_len_ref = try pt.intRef(.usize, lhs_len);13781 const lhs_dest_slice = try block.addInst(.{
13782 const lhs_dest_slice = try block.addInst(.{13782 .tag = .slice,
13783 .tag = .slice,13783 .data = .{ .ty_pl = .{
13784 .data = .{ .ty_pl = .{13784 .ty = .fromType(slice_ty),
13785 .ty = slice_ty_ref,13785 .payload = try sema.addExtra(Air.Bin{
13786 .payload = try sema.addExtra(Air.Bin{13786 .lhs = many_alloc,
13787 .lhs = many_alloc,13787 .rhs = try pt.intRef(.usize, lhs_len),
13788 .rhs = lhs_len_ref,13788 }),
13789 }),13789 } },
13790 } },13790 });
13791 });13791 _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs);
1379213792 }
13793 _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs);
1379413793
13795 // rhs_dest_slice = dest[lhs.len..][0..rhs.len]13794 // rhs_dest_slice = dest[lhs.len..][0..rhs.len]
13796 const rhs_len_ref = try pt.intRef(.usize, rhs_len);13795 if (rhs_len > 0) {
13797 const rhs_dest_offset = try block.addInst(.{13796 const rhs_dest_offset = try block.addInst(.{
13798 .tag = .ptr_add,13797 .tag = .ptr_add,
13799 .data = .{ .ty_pl = .{13798 .data = .{ .ty_pl = .{
13800 .ty = Air.internedToRef(many_ty.toIntern()),13799 .ty = Air.internedToRef(many_ty.toIntern()),
13801 .payload = try sema.addExtra(Air.Bin{13800 .payload = try sema.addExtra(Air.Bin{
13802 .lhs = many_alloc,13801 .lhs = many_alloc,
13803 .rhs = lhs_len_ref,13802 .rhs = try pt.intRef(.usize, lhs_len),
13804 }),13803 }),
13805 } },13804 } },
13806 });13805 });
13807 const rhs_dest_slice = try block.addInst(.{13806 const rhs_dest_slice = try block.addInst(.{
13808 .tag = .slice,13807 .tag = .slice,
13809 .data = .{ .ty_pl = .{13808 .data = .{ .ty_pl = .{
13810 .ty = slice_ty_ref,13809 .ty = .fromType(slice_ty),
13811 .payload = try sema.addExtra(Air.Bin{13810 .payload = try sema.addExtra(Air.Bin{
13812 .lhs = rhs_dest_offset,13811 .lhs = rhs_dest_offset,
13813 .rhs = rhs_len_ref,13812 .rhs = try pt.intRef(.usize, rhs_len),
13814 }),13813 }),
13815 } },13814 } },
13816 });13815 });
1381713816 _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs);
13818 _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs);13817 }
1381913818
13820 if (res_sent_val) |sent_val| {13819 if (res_sent_val) |sent_val| {
13821 const elem_index = try pt.intRef(.usize, result_len);13820 const elem_index = try pt.intRef(.usize, result_len);
...@@ -18829,7 +18828,7 @@ fn finishStructInit(...@@ -18829,7 +18828,7 @@ fn finishStructInit(
18829 return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref);18828 return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref);
18830 },18829 },
18831 .@"packed" => {18830 .@"packed" => {
18832 const buf = try sema.arena.alloc(u8, (struct_ty.bitSize(zcu) + 7) / 8);18831 const buf = try sema.arena.alloc(u8, @intCast((struct_ty.bitSize(zcu) + 7) / 8));
18833 var bit_offset: u16 = 0;18832 var bit_offset: u16 = 0;
18834 for (field_inits) |field_init| {18833 for (field_inits) |field_init| {
18835 const field_val = sema.resolveValue(field_init).?;18834 const field_val = sema.resolveValue(field_init).?;
...@@ -21113,7 +21112,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -21113,7 +21112,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
21113 else => unreachable,21112 else => unreachable,
21114 };21113 };
2111521114
21116 if (!dest_err_ty.isAnyError(zcu) and !dest_err_ty.errorSetHasField(err_name, zcu)) {21115 if (result != .superset and !dest_err_ty.errorSetHasField(err_name, zcu)) {
21117 return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{21116 return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{
21118 err_name.fmt(ip), dest_err_ty.fmt(pt),21117 err_name.fmt(ip), dest_err_ty.fmt(pt),
21119 });21118 });
...@@ -25186,9 +25185,18 @@ pub fn explainWhyTypeIsNotExtern(...@@ -25186,9 +25185,18 @@ pub fn explainWhyTypeIsNotExtern(
25186 else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}),25185 else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}),
25187 },25186 },
25188 .@"enum" => {25187 .@"enum" => {
25189 const tag_ty = ty.intTagType(zcu);25188 const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern());
25190 try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});25189 switch (enum_obj.int_tag_mode) {
25191 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);25190 .auto => {
25191 try sema.errNote(ty.srcLoc(zcu), msg, "integer tag type of enum is inferred", .{});
25192 try sema.errNote(ty.srcLoc(zcu), msg, "consider explicitly specifying the integer tag type", .{});
25193 },
25194 .explicit => {
25195 const tag_ty: Type = .fromInterned(enum_obj.int_tag_type);
25196 try sema.errNote(ty.srcLoc(zcu), msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});
25197 try sema.explainWhyTypeIsNotExtern(msg, ty.srcLoc(zcu), tag_ty, position);
25198 },
25199 }
25192 },25200 },
25193 .@"struct" => {25201 .@"struct" => {
25194 const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern());25202 const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern());
src/Value.zig+2-2
...@@ -895,7 +895,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value {...@@ -895,7 +895,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value {
895 // Avoid hitting gpa for accesses to small packed structs895 // Avoid hitting gpa for accesses to small packed structs
896 var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa);896 var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa);
897 const sfba = sfba_state.get();897 const sfba = sfba_state.get();
898 const buf = try sfba.alloc(u8, (ty.bitSize(zcu) + 7) / 8);898 const buf = try sfba.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8));
899 defer sfba.free(buf);899 defer sfba.free(buf);
900 int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) {900 int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) {
901 error.ReinterpretDeclRef => unreachable, // it's an integer901 error.ReinterpretDeclRef => unreachable, // it's an integer
...@@ -2419,7 +2419,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory...@@ -2419,7 +2419,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory
2419 }2419 }
2420 for (field_vals, 0..) |*field_val, field_idx| {2420 for (field_vals, 0..) |*field_val, field_idx| {
2421 if (field_val.* == .none) {2421 if (field_val.* == .none) {
2422 const default_init = struct_obj.field_inits.get(ip)[field_idx];2422 const default_init = struct_obj.field_defaults.get(ip)[field_idx];
2423 if (default_init == .none) return error.TypeMismatch;2423 if (default_init == .none) return error.TypeMismatch;
2424 field_val.* = default_init;2424 field_val.* = default_init;
2425 }2425 }
src/Zcu.zig+6-1
...@@ -3686,6 +3686,11 @@ pub const ImportResult = struct {...@@ -3686,6 +3686,11 @@ pub const ImportResult = struct {
3686pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void {3686pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void {
3687 const gpa = zcu.comp.gpa;3687 const gpa = zcu.comp.gpa;
36883688
3689 if (!dev.env.supports(.incremental)) {
3690 // This is the first time `unit` is being analyzed, so there is no stale data to clear.
3691 return;
3692 }
3693
3689 // Compile errors3694 // Compile errors
3690 if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| {3695 if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| {
3691 kv.value.destroy(gpa);3696 kv.value.destroy(gpa);
...@@ -4309,7 +4314,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag...@@ -4309,7 +4314,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag
4309 });4314 });
4310 const gop = try units.getOrPut(gpa, other);4315 const gop = try units.getOrPut(gpa, other);
4311 if (gop.found_existing) break :queue_paired;4316 if (gop.found_existing) break :queue_paired;
4312 gop.value_ptr.* = units.values()[unit_idx]; // same reference location4317 gop.value_ptr.* = units.values()[unit_idx - 1]; // same reference location
4313 }4318 }
43144319
4315 refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});4320 refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});
src/Zcu/PerThread.zig+54-26
...@@ -1075,7 +1075,6 @@ pub fn ensureMemoizedStateUpToDate(...@@ -1075,7 +1075,6 @@ pub fn ensureMemoizedStateUpToDate(
1075 const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit);1075 const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit);
10761076
1077 if (was_outdated) {1077 if (was_outdated) {
1078 dev.check(.incremental);
1079 zcu.resetUnit(unit);1078 zcu.resetUnit(unit);
1080 } else {1079 } else {
1081 if (prev_failed) return error.AnalysisFail;1080 if (prev_failed) return error.AnalysisFail;
...@@ -1193,10 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -1193,10 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
1193 const was_outdated = zcu.clearOutdatedState(anal_unit);1192 const was_outdated = zcu.clearOutdatedState(anal_unit);
11941193
1195 if (was_outdated) {1194 if (was_outdated) {
1196 // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`.1195 zcu.resetUnit(anal_unit);
1197 if (dev.env.supports(.incremental)) {
1198 zcu.resetUnit(anal_unit);
1199 }
1200 } else {1196 } else {
1201 // We can trust the current information about this unit.1197 // We can trust the current information about this unit.
1202 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;1198 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
...@@ -1366,10 +1362,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1366,10 +1362,7 @@ pub fn ensureTypeLayoutUpToDate(
1366 };1362 };
13671363
1368 if (was_outdated) {1364 if (was_outdated) {
1369 // `was_outdated` is true in the initial update, so this isn't a `dev.check`.1365 zcu.resetUnit(anal_unit);
1370 if (dev.env.supports(.incremental)) {
1371 zcu.resetUnit(anal_unit);
1372 }
1373 // For types, we already know that we have to invalidate all dependees.1366 // For types, we already know that we have to invalidate all dependees.
1374 // TODO: we actually *could* detect whether everything was the same. should we bother?1367 // TODO: we actually *could* detect whether everything was the same. should we bother?
1375 try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() });1368 try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() });
...@@ -1492,10 +1485,7 @@ pub fn ensureStructDefaultsUpToDate(...@@ -1492,10 +1485,7 @@ pub fn ensureStructDefaultsUpToDate(
1492 };1485 };
14931486
1494 if (was_outdated) {1487 if (was_outdated) {
1495 // `was_outdated` is true in the initial update, so this isn't a `dev.check`.1488 zcu.resetUnit(anal_unit);
1496 if (dev.env.supports(.incremental)) {
1497 zcu.resetUnit(anal_unit);
1498 }
1499 // For types, we already know that we have to invalidate all dependees.1489 // For types, we already know that we have to invalidate all dependees.
1500 // TODO: we actually *could* detect whether everything was the same. should we bother?1490 // TODO: we actually *could* detect whether everything was the same. should we bother?
1501 try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() });1491 try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() });
...@@ -1609,7 +1599,6 @@ pub fn ensureNavValUpToDate(...@@ -1609,7 +1599,6 @@ pub fn ensureNavValUpToDate(
1609 zcu.transitive_failed_analysis.contains(anal_unit);1599 zcu.transitive_failed_analysis.contains(anal_unit);
16101600
1611 if (was_outdated) {1601 if (was_outdated) {
1612 dev.check(.incremental);
1613 zcu.resetUnit(anal_unit);1602 zcu.resetUnit(anal_unit);
1614 } else {1603 } else {
1615 // We can trust the current information about this unit.1604 // We can trust the current information about this unit.
...@@ -1893,6 +1882,30 @@ fn analyzeNavVal(...@@ -1893,6 +1882,30 @@ fn analyzeNavVal(
1893 }1882 }
1894 }1883 }
18951884
1885 // We're about to resolve the value of the Nav. This causes the information about what the value
1886 // was last update to be lost; therefore, if the `nav_ty` is currently out of date, it would
1887 // incorrectly think it was unchanged when eventually analyzed. To avoid this, we need to detect
1888 // that case and invalidate the dependee right now.
1889 if (zcu.clearOutdatedState(.wrap(.{ .nav_ty = nav_id }))) {
1890 assert(zir_decl.type_body == null); // otherwise we already resolved it with `Sema.ensureNavResolved`
1891 zcu.resetUnit(.wrap(.{ .nav_ty = nav_id }));
1892 try pt.addDependency(.wrap(.{ .nav_ty = nav_id }), .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!)
1893 if (comp.debugIncremental()) {
1894 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, .wrap(.{ .nav_ty = nav_id }));
1895 info.last_update_gen = zcu.generation;
1896 info.deps.clearRetainingCapacity();
1897 }
1898 const type_changed: bool = switch (old_nav.status) {
1899 .unresolved => true,
1900 .type_resolved => |old| old.type != nav_ty.toIntern(),
1901 .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(),
1902 };
1903 if (type_changed) {
1904 try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id });
1905 } else {
1906 try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id });
1907 }
1908 }
1896 ip.resolveNavValue(io, nav_id, .{1909 ip.resolveNavValue(io, nav_id, .{
1897 .val = nav_val.toIntern(),1910 .val = nav_val.toIntern(),
1898 .is_const = is_const,1911 .is_const = is_const,
...@@ -1930,10 +1943,10 @@ fn analyzeNavVal(...@@ -1930,10 +1943,10 @@ fn analyzeNavVal(
1930 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());1943 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
1931 }1944 }
19321945
1933 switch (old_nav.status) {1946 return switch (old_nav.status) {
1934 .unresolved, .type_resolved => return .{ .val_changed = true },1947 .unresolved, .type_resolved => .{ .val_changed = true },
1935 .fully_resolved => |old| return .{ .val_changed = old.val != nav_val.toIntern() },1948 .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() },
1936 }1949 };
1937}1950}
19381951
1939pub fn ensureNavTypeUpToDate(1952pub fn ensureNavTypeUpToDate(
...@@ -1973,7 +1986,6 @@ pub fn ensureNavTypeUpToDate(...@@ -1973,7 +1986,6 @@ pub fn ensureNavTypeUpToDate(
1973 zcu.transitive_failed_analysis.contains(anal_unit);1986 zcu.transitive_failed_analysis.contains(anal_unit);
19741987
1975 if (was_outdated) {1988 if (was_outdated) {
1976 dev.check(.incremental);
1977 zcu.resetUnit(anal_unit);1989 zcu.resetUnit(anal_unit);
1978 } else {1990 } else {
1979 // We can trust the current information about this unit.1991 // We can trust the current information about this unit.
...@@ -2107,12 +2119,29 @@ fn analyzeNavType(...@@ -2107,12 +2119,29 @@ fn analyzeNavType(
21072119
2108 const type_body = zir_decl.type_body orelse {2120 const type_body = zir_decl.type_body orelse {
2109 // There is no type annotation, so we just need to use the declaration's value.2121 // There is no type annotation, so we just need to use the declaration's value.
2122 // If the value had already been re-analyzed, it would have resolved the `nav_ty` unit as
2123 // either outdated or up-to-date. So we know that `old_nav` does contain information from
2124 // the previous update. As such, after this call, we will be able to determine whether the
2125 // type changed.
2110 try sema.ensureNavResolved(&block, init_src, nav_id, .fully);2126 try sema.ensureNavResolved(&block, init_src, nav_id, .fully);
2111 // We don't actually know what the type of this Nav was before it was resolved, so we just2127 const new = ip.getNav(nav_id).status.fully_resolved;
2112 // have to assume we were outdated. This isn't too bad, because assuming there was also no2128 const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern";
2113 // type annotation last update, we should only be re-analyzed if the value changes (it's our2129 const changed = switch (old_nav.status) {
2114 // only dependency), or if there was a dependency loop.2130 .unresolved => true,
2115 return .{ .type_changed = true };2131 .type_resolved => |r| r.type != ip.typeOf(new.val) or
2132 r.alignment != new.alignment or
2133 r.@"linksection" != new.@"linksection" or
2134 r.@"addrspace" != new.@"addrspace" or
2135 r.is_const != new.is_const or
2136 r.is_extern_decl != new_is_extern_decl,
2137 .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or
2138 r.alignment != new.alignment or
2139 r.@"linksection" != new.@"linksection" or
2140 r.@"addrspace" != new.@"addrspace" or
2141 r.is_const != new.is_const or
2142 (old_nav.getExtern(ip) != null) != new_is_extern_decl,
2143 };
2144 return .{ .type_changed = changed };
2116 };2145 };
21172146
2118 block.comptime_reason = .{ .reason = .{2147 block.comptime_reason = .{ .reason = .{
...@@ -2210,7 +2239,6 @@ pub fn ensureFuncBodyUpToDate(...@@ -2210,7 +2239,6 @@ pub fn ensureFuncBodyUpToDate(
2210 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);2239 const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit);
22112240
2212 if (was_outdated) {2241 if (was_outdated) {
2213 dev.check(.incremental);
2214 zcu.resetUnit(anal_unit);2242 zcu.resetUnit(anal_unit);
2215 } else {2243 } else {
2216 // We can trust the current information about this function.2244 // We can trust the current information about this function.
...@@ -2292,7 +2320,7 @@ fn analyzeFuncBody(...@@ -2292,7 +2320,7 @@ fn analyzeFuncBody(
22922320
2293 var air = try pt.analyzeFuncBodyInner(func_index, reason);2321 var air = try pt.analyzeFuncBodyInner(func_index, reason);
2294 var air_owned = true;2322 var air_owned = true;
2295 errdefer if (air_owned) air.deinit(gpa);2323 defer if (air_owned) air.deinit(gpa);
22962324
2297 const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or2325 const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or
2298 func.resolvedErrorSetUnordered(ip) != old_resolved_ies;2326 func.resolvedErrorSetUnordered(ip) != old_resolved_ies;
src/codegen/c.zig+3-3
...@@ -7132,9 +7132,9 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void...@@ -7132,9 +7132,9 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void
7132 var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined;7132 var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined;
7133 for (0..big.limbs_len) |limb_index| {7133 for (0..big.limbs_len) |limb_index| {
7134 if (limb_index != 0) try w.writeAll(", ");7134 if (limb_index != 0) try w.writeAll(", ");
7135 const limb_bit_offset: u64 = switch (target.cpu.arch.endian()) {7135 const limb_bit_offset: u16 = switch (target.cpu.arch.endian()) {
7136 .little => limb_index * big.limb_size.bits(),7136 .little => @intCast(limb_index * big.limb_size.bits()),
7137 .big => (big.limbs_len - limb_index - 1) * big.limb_size.bits(),7137 .big => @intCast((big.limbs_len - limb_index - 1) * big.limb_size.bits()),
7138 };7138 };
7139 var limb_bigint: std.math.big.int.Mutable = .{7139 var limb_bigint: std.math.big.int.Mutable = .{
7140 .limbs = &limb_buf,7140 .limbs = &limb_buf,
src/codegen/llvm.zig+1-1
...@@ -2432,7 +2432,7 @@ pub const Object = struct {...@@ -2432,7 +2432,7 @@ pub const Object = struct {
2432 const debug_payload_type = try o.builder.debugUnionType(2432 const debug_payload_type = try o.builder.debugUnionType(
2433 payload_name: {2433 payload_name: {
2434 if (layout.tag_size == 0) break :payload_name name;2434 if (layout.tag_size == 0) break :payload_name name;
2435 break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)});2435 break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(pt)});
2436 },2436 },
2437 file,2437 file,
2438 scope,2438 scope,
src/link.zig+4-1
...@@ -1557,7 +1557,10 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void...@@ -1557,7 +1557,10 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1557 .link_func => |codegen_task| nav: {1557 .link_func => |codegen_task| nav: {
1558 timer.pause(io);1558 timer.pause(io);
1559 const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) {1559 const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) {
1560 error.Canceled, error.AlreadyReported => return,1560 error.Canceled, error.AlreadyReported => {
1561 comp.link_prog_node.completeOne();
1562 return;
1563 },
1561 };1564 };
1562 defer mir.deinit(zcu);1565 defer mir.deinit(zcu);
1563 timer.@"resume"(io);1566 timer.@"resume"(io);
src/link/Dwarf.zig+101-9
...@@ -3344,6 +3344,7 @@ pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index...@@ -3344,6 +3344,7 @@ pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index
3344}3344}
3345fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void {3345fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void {
3346 const zcu = pt.zcu;3346 const zcu = pt.zcu;
3347 const ip = &zcu.intern_pool;
33473348
3348 const val: Value = .fromInterned(value_index);3349 const val: Value = .fromInterned(value_index);
33493350
...@@ -3383,20 +3384,109 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde...@@ -3383,20 +3384,109 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde
3383 .debug_loclists = .init(dwarf.gpa),3384 .debug_loclists = .init(dwarf.gpa),
3384 };3385 };
3385 defer wip_nav.deinit();3386 defer wip_nav.deinit();
3386 switch (val.typeOf(zcu).toIntern()) {3387
3387 .type_type => {3388 switch (ip.indexToKey(value_index)) {
3388 try wip_nav.abbrevCode(.generated_empty_struct_type);3389 // Container types still need to be valid namespaces.
3389 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});3390 .struct_type => {
3390 try wip_nav.debug_info.writer.writeByte(@intFromBool(true));3391 const loaded_struct = ip.loadStructType(value_index);
3392 const root_of_file: ?Zcu.File.Index = if (loaded_struct.zir_index.resolveFull(ip)) |r| f: {
3393 if (r.inst != .main_struct_inst) break :f null;
3394 break :f r.file;
3395 } else null;
3396 if (root_of_file) |file_index| {
3397 assert(loaded_struct.name_nav == .none);
3398 const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index);
3399 try wip_nav.abbrevCode(.empty_file);
3400 try wip_nav.debug_info.writer.writeUleb128(file_gop.index);
3401 try wip_nav.strp(loaded_struct.name.toSlice(ip));
3402 } else {
3403 try dwarf.emitIncompleteContainerType(
3404 &wip_nav,
3405 loaded_struct.zir_index,
3406 loaded_struct.name,
3407 loaded_struct.name_nav,
3408 );
3409 }
3391 },3410 },
3392 else => |ty| {3411 .union_type => {
3393 try wip_nav.abbrevCode(.undefined_comptime_value);3412 const loaded_union = ip.loadUnionType(value_index);
3394 try wip_nav.refType(.fromInterned(ty));3413 try dwarf.emitIncompleteContainerType(
3414 &wip_nav,
3415 loaded_union.zir_index,
3416 loaded_union.name,
3417 loaded_union.name_nav,
3418 );
3419 },
3420 .enum_type => {
3421 const loaded_enum = ip.loadEnumType(value_index);
3422 if (loaded_enum.zir_index.unwrap()) |zir_index| {
3423 try dwarf.emitIncompleteContainerType(
3424 &wip_nav,
3425 zir_index,
3426 loaded_enum.name,
3427 loaded_enum.name_nav,
3428 );
3429 } else {
3430 try wip_nav.abbrevCode(.generated_empty_struct_type);
3431 try wip_nav.strp(loaded_enum.name.toSlice(ip));
3432 try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
3433 }
3434 },
3435 .opaque_type => {
3436 const loaded_opaque = ip.loadOpaqueType(value_index);
3437 try dwarf.emitIncompleteContainerType(
3438 &wip_nav,
3439 loaded_opaque.zir_index,
3440 loaded_opaque.name,
3441 loaded_opaque.name_nav,
3442 );
3443 },
3444 // Not a container type, so just emit a dummy entry. If `val` happens to be a type, we'll
3445 // emit it as if it were an opaque type so that we can name it.
3446 else => |val_key| switch (val_key.typeOf()) {
3447 .type_type => {
3448 try wip_nav.abbrevCode(.generated_empty_struct_type);
3449 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3450 try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
3451 },
3452 else => |ty| {
3453 try wip_nav.abbrevCode(.undefined_comptime_value);
3454 try wip_nav.refType(.fromInterned(ty));
3455 },
3395 },3456 },
3396 }3457 }
3397 try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written());3458 try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written());
3398 try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written());3459 try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written());
3399}3460}
3461fn emitIncompleteContainerType(
3462 dwarf: *Dwarf,
3463 wip_nav: *WipNav,
3464 zir_index: InternPool.TrackedInst.Index,
3465 name: InternPool.NullTerminatedString,
3466 name_nav: InternPool.Nav.Index.Optional,
3467) !void {
3468 const zcu = wip_nav.pt.zcu;
3469 const ip = &zcu.intern_pool;
3470 const file = zir_index.resolveFile(ip);
3471 if (name_nav.unwrap()) |nav_index| {
3472 const nav = ip.getNav(nav_index);
3473 const decl_inst = nav.srcInst(ip).resolve(ip).?;
3474 const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst);
3475 try wip_nav.declCommon(.{
3476 .decl = .decl_namespace_struct,
3477 .generic_decl = .generic_decl_const,
3478 .decl_instance = .decl_instance_namespace_struct,
3479 }, &nav, file, &decl);
3480 try wip_nav.debug_info.writer.writeByte(@intFromBool(true));
3481 } else {
3482 const diw = &wip_nav.debug_info.writer;
3483 const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file);
3484 try wip_nav.abbrevCode(.empty_struct_type);
3485 try diw.writeUleb128(file_gop.index);
3486 try wip_nav.strp(name.toSlice(ip));
3487 try diw.writeByte(@intFromBool(true));
3488 }
3489}
3400/// Should only be called by the `link.ConstPool` implementation.3490/// Should only be called by the `link.ConstPool` implementation.
3401///3491///
3402/// Emits a DIE for the given comptime-only value (which may be a type).3492/// 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...@@ -3418,6 +3508,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3418 val.typeOf(zcu).assertHasLayout(zcu);3508 val.typeOf(zcu).assertHasLayout(zcu);
3419 }3509 }
34203510
3511 if (value_index == .anyerror_type) return; // handled in `flush` instead
3512
3421 const value_ip_key = ip.indexToKey(value_index);3513 const value_ip_key = ip.indexToKey(value_index);
3422 switch (value_ip_key) {3514 switch (value_ip_key) {
3423 .func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`)3515 .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...@@ -3746,7 +3838,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
3746 try wip_nav.abbrevCode(.void_type);3838 try wip_nav.abbrevCode(.void_type);
3747 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});3839 try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)});
3748 },3840 },
3749 .anyerror => return, // delay until flush3841 .anyerror => unreachable, // already did early return above
3750 .adhoc_inferred_error_set => unreachable,3842 .adhoc_inferred_error_set => unreachable,
3751 },3843 },
3752 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {3844 .tuple_type => |tuple_type| if (tuple_type.types.len == 0) {
tools/incr-check.zig+8-8
...@@ -311,12 +311,12 @@ const Eval = struct {...@@ -311,12 +311,12 @@ const Eval = struct {
311 .error_bundle => {311 .error_bundle => {
312 const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);312 const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
313 if (stderr.bufferedLen() > 0) {313 if (stderr.bufferedLen() > 0) {
314 const stderr_data = try mr.toOwnedSlice(1);
315 if (eval.allow_stderr) {314 if (eval.allow_stderr) {
316 std.log.info("error_bundle stderr:\n{s}", .{stderr_data});315 std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()});
317 } else {316 } else {
318 eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data});317 eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()});
319 }318 }
319 stderr.tossBuffered();
320 }320 }
321 if (result_error_bundle.errorMessageCount() != 0) {321 if (result_error_bundle.errorMessageCount() != 0) {
322 try eval.checkErrorOutcome(update, result_error_bundle);322 try eval.checkErrorOutcome(update, result_error_bundle);
...@@ -327,15 +327,15 @@ const Eval = struct {...@@ -327,15 +327,15 @@ const Eval = struct {
327 .emit_digest => {327 .emit_digest => {
328 var r: std.Io.Reader = .fixed(body);328 var r: std.Io.Reader = .fixed(body);
329 _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;329 _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable;
330
330 if (stderr.bufferedLen() > 0) {331 if (stderr.bufferedLen() > 0) {
331 const stderr_data = try mr.toOwnedSlice(1);
332 if (eval.allow_stderr) {332 if (eval.allow_stderr) {
333 std.log.info("emit_digest stderr:\n{s}", .{stderr_data});333 std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()});
334 } else {334 } else {
335 eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data});335 eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()});
336 }336 }
337 stderr.tossBuffered();
337 }338 }
338
339 if (eval.target.backend == .sema) {339 if (eval.target.backend == .sema) {
340 try eval.checkSuccessOutcome(update, null, prog_node);340 try eval.checkSuccessOutcome(update, null, prog_node);
341 continue;341 continue;
...@@ -369,7 +369,7 @@ const Eval = struct {...@@ -369,7 +369,7 @@ const Eval = struct {
369 }369 }
370370
371 waitChild(eval.child, eval);371 waitChild(eval.child, eval);
372 eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{});372 eval.fatal("compiler failed to send terminating error_bundle", .{});
373 }373 }
374374
375 fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void {375 fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void {