authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-07-31 13:39:16+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-01 11:27:38+01:00
logf134f4345cf8484b82c46278074eb45af0efaf2e
tree6d4e30800a3017b2b57d96b342f719add4d4379d
parentf6c5f8b79908d6c1550fe535ceb26d1d8944c197
signaturelock-open Commit is signed but in an unrecognized format.

compiler: improve tracking of transitive analysis errors

This is an internal refactor to mark transitive semantic analysis errors as soon as they occur rather than relying on the root "update" function to do so. This is simpler to understand and slightly more efficient. The error surfaced in this case is renamed from `error.AnalysisFail` to `error.AlreadyReported` for consistency with the rest of the compiler. `error.AnalysisFail` is returned from the "ensure up to date" functions in `Zcu.PerThread` to indicate that the unit which was requested has failed analysis---using a different error name here is useful because it prevents `Sema` from accidentally introducing a bug by `try`ing. Alongside the above, I have also begun to store some useful debugging information (the reason for the transitive analysis error) with transitive analysis errors in compilers built with debug extensions. This information is surfaced by the incremental debug server, and was invaluable in tracking down an incremental compilation bug---details of that in the next commit.

7 files changed, 275 insertions(+), 162 deletions(-)

src/Compilation.zig+8-1
...@@ -4076,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4076,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
4076 ref = refs.get(r.referencer).?;4076 ref = refs.get(r.referencer).?;
4077 }4077 }
4078 }4078 }
4079 @panic("referenced transitive analysis errors, but none actually emitted");4079 if (comp.debugIncremental()) {
4080 std.debug.print("skipping compiler panic to allow incremental debug server usage", .{});
4081 try bundle.addRootErrorMessage(.{
4082 .msg = try bundle.addString("compiler bug: referenced transitive analysis errors, but none actually emitted"),
4083 });
4084 } else {
4085 @panic("referenced transitive analysis errors, but none actually emitted");
4086 }
4080 }4087 }
4081 };4088 };
40824089
src/IncrementalDebugServer.zig+20-7
...@@ -286,21 +286,34 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const...@@ -286,21 +286,34 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
286 const referencer = (ref orelse break :ref "<analysis root>").referencer;286 const referencer = (ref orelse break :ref "<analysis root>").referencer;
287 break :ref printAnalUnit(referencer, &ref_str_buf);287 break :ref printAnalUnit(referencer, &ref_str_buf);
288 };288 };
289 const has_err: []const u8 = err: {
290 if (zcu.failed_analysis.contains(unit)) break :err "true";
291 if (zcu.transitive_failed_analysis.contains(unit)) break :err "true (transitive)";
292 break :err "false";
293 };
294 try w.print(289 try w.print(
295 \\last update generation: {d}290 \\last update generation: {d}
296 \\current referencer: {s}291 \\current referencer: {s}
297 \\has error: {s}
298 \\292 \\
299 , .{293 , .{
300 unit_info.last_update_gen,294 unit_info.last_update_gen,
301 ref_str,295 ref_str,
302 has_err,
303 });296 });
297 if (zcu.failed_analysis.get(unit)) |err_msg| {
298 try w.print("analysis result: failure ({q})\n", .{err_msg.msg});
299 } else if (zcu.transitive_failed_analysis.get(unit)) |reason| {
300 switch (reason) {
301 .astgen_error => try w.writeAll("analysis result: transitive failure (astgen error)\n"),
302 .dependency_loop => try w.writeAll("analysis result: transitive failure (dependency loop)\n"),
303 .lost_tracking => try w.writeAll("analysis result: transitive failure (lost tracking for zir inst)\n"),
304 .failed_unit => |other_unit| {
305 var buf: [32]u8 = undefined;
306 try w.print("analysis result: transitive failure (failed unit: {s})\n", .{printAnalUnit(other_unit, &buf)});
307 },
308 .func_nav_val_changed => |func_index| try w.print("analysis result: transitive failure (owner nav of func '{d}' changed value)\n", .{@backingInt(func_index)}),
309 }
310 } else {
311 try w.writeAll("analysis result: success\n");
312 }
313 if (unit.unwrap() == .func) {
314 const nav_id = zcu.intern_pool.indexToKey(unit.unwrap().func).func.owner_nav;
315 try w.print("owner nav: {d}\n", .{@backingInt(nav_id)});
316 }
304 } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) {317 } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) {
305 const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit");318 const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit");
306 const unit_info = zcu.incremental_debug_state.units.get(unit) orelse return w.writeAll("unknown anal unit");319 const unit_info = zcu.incremental_debug_state.units.get(unit) orelse return w.writeAll("unknown anal unit");
src/Sema.zig+133-52
...@@ -1472,7 +1472,7 @@ fn analyzeBodyInner(...@@ -1472,7 +1472,7 @@ fn analyzeBodyInner(
1472 i += 1;1472 i += 1;
1473 continue;1473 continue;
1474 },1474 },
1475 .astgen_error => return error.AnalysisFail,1475 .astgen_error => return sema.failTransitive(.astgen_error),
1476 .float_op_result_ty => try sema.zirFloatOpResultType(block, extended),1476 .float_op_result_ty => try sema.zirFloatOpResultType(block, extended),
1477 };1477 };
1478 },1478 },
...@@ -2697,13 +2697,15 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T...@@ -2697,13 +2697,15 @@ fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: T
2697 });2697 });
2698}2698}
26992699
2700pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } {2700pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) SemaError {
2701 @branchHint(.cold);2701 @branchHint(.cold);
2702 const zcu = sema.pt.zcu;2702 const zcu = sema.pt.zcu;
2703 const comp = zcu.comp;2703 const comp = zcu.comp;
2704 const gpa = comp.gpa;2704 const gpa = comp.gpa;
2705 const io = comp.io;2705 const io = comp.io;
27062706
2707 assert(sema.err == null);
2708
2707 if (build_options.enable_debug_extensions and comp.debug_compile_errors) {2709 if (build_options.enable_debug_extensions and comp.debug_compile_errors) {
2708 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2710 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
2709 wip_errors.init(gpa) catch @panic("out of memory");2711 wip_errors.init(gpa) catch @panic("out of memory");
...@@ -2729,17 +2731,11 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg...@@ -2729,17 +2731,11 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg
27292731
2730 err_msg.reference_trace_root = sema.owner.toOptional();2732 err_msg.reference_trace_root = sema.owner.toOptional();
27312733
2732 const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner);2734 try zcu.failed_analysis.putNoClobber(gpa, sema.owner, err_msg);
2733 if (gop.found_existing) {2735 assert(!zcu.transitive_failed_analysis.contains(sema.owner));
2734 // If there are multiple errors for the same Decl, prefer the first one added.
2735 sema.err = null;
2736 err_msg.destroy(gpa);
2737 } else {
2738 sema.err = err_msg;
2739 gop.value_ptr.* = err_msg;
2740 }
27412736
2742 return error.AnalysisFail;2737 sema.err = err_msg;
2738 return error.AlreadyReported;
2743}2739}
27442740
2745/// Given an ErrorMsg, modify its message and source location to the given values, turning the2741/// Given an ErrorMsg, modify its message and source location to the given values, turning the
...@@ -4745,11 +4741,14 @@ fn failWithBadMemberAccess(...@@ -4745,11 +4741,14 @@ fn failWithBadMemberAccess(
4745 .@"enum" => "enum",4741 .@"enum" => "enum",
4746 else => unreachable,4742 else => unreachable,
4747 };4743 };
4748 if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) {4744 if (agg_ty.typeDeclInst(zcu)) |inst| {
4749 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{4745 const inst_index = inst.resolve(ip) orelse return sema.failTransitive(.{ .lost_tracking = inst });
4750 agg_ty.fmt(pt), field_name.fmt(ip),4746 if (inst_index == .main_struct_inst) {
4751 });4747 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{
4752 };4748 agg_ty.fmt(pt), field_name.fmt(ip),
4749 });
4750 }
4751 }
47534752
4754 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{4753 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{
4755 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),4754 kw_name, agg_ty.fmt(pt), field_name.fmt(ip),
...@@ -5997,7 +5996,14 @@ fn lookupInNamespace(...@@ -5997,7 +5996,14 @@ fn lookupInNamespace(
5997 const pt = sema.pt;5996 const pt = sema.pt;
5998 const zcu = pt.zcu;5997 const zcu = pt.zcu;
59995998
6000 try pt.ensureNamespaceUpToDate(namespace_index);5999 pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) {
6000 error.LostZirContainerDecl => {
6001 const namespace = zcu.namespacePtr(namespace_index);
6002 const ns_ty: Type = .fromInterned(namespace.owner_type);
6003 return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? });
6004 },
6005 else => |e| return e,
6006 };
60016007
6002 const namespace = zcu.namespacePtr(namespace_index);6008 const namespace = zcu.namespacePtr(namespace_index);
60036009
...@@ -6062,7 +6068,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -6062,7 +6068,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
6062 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace);6068 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace);
6063 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);6069 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
6064 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {6070 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
6065 error.AnalysisFail => @panic("std.lang.StackTrace is corrupt"),6071 error.AlreadyReported => @panic("std.lang.StackTrace is corrupt"),
6066 error.ComptimeReturn, error.ComptimeBreak => unreachable,6072 error.ComptimeReturn, error.ComptimeBreak => unreachable,
6067 error.OutOfMemory, error.Canceled => |e| return e,6073 error.OutOfMemory, error.Canceled => |e| return e,
6068 };6074 };
...@@ -6724,7 +6730,9 @@ fn analyzeCall(...@@ -6724,7 +6730,9 @@ fn analyzeCall(
6724 const fn_nav: InternPool.Nav, const fn_zir: Zir, const fn_tracked_inst: InternPool.TrackedInst.Index, const fn_zir_inst: Zir.Inst.Index, const fn_zir_info: Zir.FnInfo = if (func_val) |f| b: {6730 const fn_nav: InternPool.Nav, const fn_zir: Zir, const fn_tracked_inst: InternPool.TrackedInst.Index, const fn_zir_inst: Zir.Inst.Index, const fn_zir_info: Zir.FnInfo = if (func_val) |f| b: {
6725 const info = ip.indexToKey(f.toIntern()).func;6731 const info = ip.indexToKey(f.toIntern()).func;
6726 const nav = ip.getNav(info.owner_nav);6732 const nav = ip.getNav(info.owner_nav);
6727 const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail;6733 const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse {
6734 return sema.failTransitive(.{ .lost_tracking = info.zir_body_inst });
6735 };
6728 const file = zcu.fileByIndex(resolved_func_inst.file);6736 const file = zcu.fileByIndex(resolved_func_inst.file);
6729 const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst);6737 const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst);
6730 break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info };6738 break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info };
...@@ -8355,7 +8363,10 @@ fn zirFunc(...@@ -8355,7 +8363,10 @@ fn zirFunc(
8355 const cc: std.lang.CallingConvention = if (has_body) cc: {8363 const cc: std.lang.CallingConvention = if (has_body) cc: {
8356 const func_decl_nav = sema.owner.unwrap().nav_val;8364 const func_decl_nav = sema.owner.unwrap().nav_val;
8357 const fn_is_exported = exported: {8365 const fn_is_exported = exported: {
8358 const decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(ip) orelse return error.AnalysisFail;8366 const decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index;
8367 const decl_inst = decl_ti.resolve(ip) orelse {
8368 return sema.failTransitive(.{ .lost_tracking = decl_ti });
8369 };
8359 const zir_decl = sema.code.getDeclaration(decl_inst);8370 const zir_decl = sema.code.getDeclaration(decl_inst);
8360 break :exported zir_decl.linkage == .@"export";8371 break :exported zir_decl.linkage == .@"export";
8361 };8372 };
...@@ -12289,10 +12300,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12289,10 +12300,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12289 dummy_captures,12300 dummy_captures,
12290 .{ .override = item_srcs },12301 .{ .override = item_srcs },
12291 ) catch |err| switch (err) {12302 ) catch |err| switch (err) {
12292 error.AnalysisFail => {12303 error.AlreadyReported => |e| {
12293 const msg = sema.err orelse return error.AnalysisFail;12304 if (sema.err) |msg| {
12294 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});12305 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12295 return error.AnalysisFail;12306 }
12307 return e;
12296 },12308 },
12297 else => |e| return e,12309 else => |e| return e,
12298 };12310 };
...@@ -12328,11 +12340,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(...@@ -12328,11 +12340,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion(
12328 dummy_captures,12340 dummy_captures,
12329 .{ .override = item_srcs },12341 .{ .override = item_srcs },
12330 ) catch |err| switch (err) {12342 ) catch |err| switch (err) {
12331 error.AnalysisFail => {12343 error.AlreadyReported => |e| {
12332 const msg = sema.err orelse return error.AnalysisFail;12344 if (sema.err) |msg| {
12333 try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});12345 try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{});
12334 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});12346 try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{});
12335 return error.AnalysisFail;12347 }
12348 return e;
12336 },12349 },
12337 else => |e| return e,12350 else => |e| return e,
12338 };12351 };
...@@ -17207,7 +17220,14 @@ fn typeInfoNamespaceDecls(...@@ -17207,7 +17220,14 @@ fn typeInfoNamespaceDecls(
17207 const ip = &zcu.intern_pool;17220 const ip = &zcu.intern_pool;
1720817221
17209 const namespace_index = opt_namespace_index.unwrap() orelse return;17222 const namespace_index = opt_namespace_index.unwrap() orelse return;
17210 try pt.ensureNamespaceUpToDate(namespace_index);17223 pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) {
17224 error.LostZirContainerDecl => {
17225 const namespace = zcu.namespacePtr(namespace_index);
17226 const ns_ty: Type = .fromInterned(namespace.owner_type);
17227 return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? });
17228 },
17229 else => |e| return e,
17230 };
17211 const namespace = zcu.namespacePtr(namespace_index);17231 const namespace = zcu.namespacePtr(namespace_index);
1721217232
17213 const gop = try seen_namespaces.getOrPut(namespace);17233 const gop = try seen_namespaces.getOrPut(namespace);
...@@ -17933,11 +17953,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -17933,11 +17953,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
17933 }17953 }
17934 // TODO Add compile error for @optimizeFor occurring too late in a scope.17954 // TODO Add compile error for @optimizeFor occurring too late in a scope.
17935 sema.analyzeUnreachable(block, src, true) catch |err| switch (err) {17955 sema.analyzeUnreachable(block, src, true) catch |err| switch (err) {
17936 error.AnalysisFail => {17956 error.AlreadyReported => |e| {
17937 const msg = sema.err orelse return err;17957 if (sema.err) |msg| {
17938 if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;17958 if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err;
17939 try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});17959 try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{});
17940 return err;17960 }
17961 return e;
17941 },17962 },
17942 else => |e| return e,17963 else => |e| return e,
17943 };17964 };
...@@ -18353,11 +18374,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -18353,11 +18374,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1835318374
18354 const elem_ty = blk: {18375 const elem_ty = blk: {
18355 const air_inst = sema.resolveInst(extra.data.elem_type);18376 const air_inst = sema.resolveInst(extra.data.elem_type);
18356 const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| {18377 const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| switch (err) {
18357 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) {18378 error.AlreadyReported => |e| {
18358 try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});18379 if (sema.err) |msg| {
18359 }18380 if (sema.typeOf(air_inst).isSinglePointer(zcu)) {
18360 return err;18381 try sema.errNote(elem_ty_src, msg, "use '.*' to dereference pointer", .{});
18382 }
18383 }
18384 return e;
18385 },
18386 else => |e| return e,
18361 };18387 };
18362 assert(!ty.isGenericPoison());18388 assert(!ty.isGenericPoison());
18363 break :blk ty;18389 break :blk ty;
...@@ -24909,7 +24935,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -24909,7 +24935,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
24909 } else cc: {24935 } else cc: {
24910 if (has_body) {24936 if (has_body) {
24911 const func_decl_nav = sema.owner.unwrap().nav_val;24937 const func_decl_nav = sema.owner.unwrap().nav_val;
24912 const func_decl_inst = ip.getNav(func_decl_nav).analysis.?.zir_index.resolve(&zcu.intern_pool) orelse return error.AnalysisFail;24938 const func_decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index;
24939 const func_decl_inst = func_decl_ti.resolve(&zcu.intern_pool) orelse {
24940 return sema.failTransitive(.{ .lost_tracking = func_decl_ti });
24941 };
24913 const zir_decl = sema.code.getDeclaration(func_decl_inst);24942 const zir_decl = sema.code.getDeclaration(func_decl_inst);
24914 if (zir_decl.linkage == .@"export") {24943 if (zir_decl.linkage == .@"export") {
24915 break :cc target.cCallingConvention() orelse {24944 break :cc target.cCallingConvention() orelse {
...@@ -30642,7 +30671,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M...@@ -30642,7 +30671,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M
30642 if (pt.zcu.analysis_in_progress.contains(unit)) {30671 if (pt.zcu.analysis_in_progress.contains(unit)) {
30643 return sema.failWithDependencyLoop(unit, &reason);30672 return sema.failWithDependencyLoop(unit, &reason);
30644 }30673 }
30645 try pt.ensureMemoizedStateUpToDate(stage, &reason);30674 pt.ensureMemoizedStateUpToDate(stage, &reason) catch |err| switch (err) {
30675 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = unit }),
30676 else => |e| return e,
30677 };
30646}30678}
3064730679
30648pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {30680pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void {
...@@ -30678,9 +30710,15 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:...@@ -30678,9 +30710,15 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:
30678 switch (kind) {30710 switch (kind) {
30679 .type => {30711 .type => {
30680 try zcu.ensureNavValAnalysisQueued(nav_index);30712 try zcu.ensureNavValAnalysisQueued(nav_index);
30681 return pt.ensureNavTypeUpToDate(nav_index, &reason);30713 return pt.ensureNavTypeUpToDate(nav_index, &reason) catch |err| switch (err) {
30714 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = anal_unit }),
30715 else => |e| return e,
30716 };
30717 },
30718 .fully => return pt.ensureNavValUpToDate(nav_index, &reason) catch |err| switch (err) {
30719 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = anal_unit }),
30720 else => |e| return e,
30682 },30721 },
30683 .fully => return pt.ensureNavValUpToDate(nav_index, &reason),
30684 }30722 }
30685}30723}
3068630724
...@@ -33743,7 +33781,10 @@ fn ensureFuncIesResolved(...@@ -33743,7 +33781,10 @@ fn ensureFuncIesResolved(
33743 return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason);33781 return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason);
33744 }33782 }
3374533783
33746 try pt.ensureFuncBodyUpToDate(func_index, &reason);33784 pt.ensureFuncBodyUpToDate(func_index, &reason) catch |err| switch (err) {
33785 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .func = func_index }) }),
33786 else => |e| return e,
33787 };
33747}33788}
3374833789
33749pub fn resolveInferredErrorSetPtr(33790pub fn resolveInferredErrorSetPtr(
...@@ -34962,7 +35003,9 @@ pub fn setTypeName(...@@ -34962,7 +35003,9 @@ pub fn setTypeName(
34962 },35003 },
34963 .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()),35004 .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()),
34964 .func => {35005 .func => {
34965 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);35006 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse {
35007 return sema.failTransitive(.{ .lost_tracking = ip.funcZirBodyInst(sema.func_index) });
35008 });
34966 const zir_tags = sema.code.instructions.items(.tag);35009 const zir_tags = sema.code.instructions.items(.tag);
3496735010
34968 var aw: std.Io.Writer.Allocating = .init(gpa);35011 var aw: std.Io.Writer.Allocating = .init(gpa);
...@@ -35078,7 +35121,10 @@ fn zirStructDecl(...@@ -35078,7 +35121,10 @@ fn zirStructDecl(
35078 };35121 };
3507935122
35080 try sema.addTypeReferenceEntry(src, ty);35123 try sema.addTypeReferenceEntry(src, ty);
35081 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));35124 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35125 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35126 else => |e| return e,
35127 };
3508235128
35083 return .fromType(ty);35129 return .fromType(ty);
35084}35130}
...@@ -35151,7 +35197,10 @@ fn zirUnionDecl(...@@ -35151,7 +35197,10 @@ fn zirUnionDecl(
35151 };35197 };
3515235198
35153 try sema.addTypeReferenceEntry(src, ty);35199 try sema.addTypeReferenceEntry(src, ty);
35154 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));35200 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35201 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35202 else => |e| return e,
35203 };
3515535204
35156 return .fromType(ty);35205 return .fromType(ty);
35157}35206}
...@@ -35203,7 +35252,10 @@ fn zirEnumDecl(...@@ -35203,7 +35252,10 @@ fn zirEnumDecl(
35203 };35252 };
3520435253
35205 try sema.addTypeReferenceEntry(src, ty);35254 try sema.addTypeReferenceEntry(src, ty);
35206 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));35255 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35256 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35257 else => |e| return e,
35258 };
3520735259
35208 return .fromType(ty);35260 return .fromType(ty);
35209}35261}
...@@ -35252,7 +35304,10 @@ fn zirOpaqueDecl(...@@ -35252,7 +35304,10 @@ fn zirOpaqueDecl(
35252 };35304 };
3525335305
35254 try sema.addTypeReferenceEntry(src, ty);35306 try sema.addTypeReferenceEntry(src, ty);
35255 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));35307 pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)) catch |err| switch (err) {
35308 error.LostZirContainerDecl => unreachable, // we literally just tracked it
35309 else => |e| return e,
35310 };
3525635311
35257 return .fromType(ty);35312 return .fromType(ty);
35258}35313}
...@@ -35293,5 +35348,31 @@ pub fn failWithDependencyLoop(...@@ -35293,5 +35348,31 @@ pub fn failWithDependencyLoop(
35293 }35348 }
3529435349
35295 // A dependency loop error will be reported. Mark us all as transitive failures.35350 // A dependency loop error will be reported. Mark us all as transitive failures.
35296 return error.AnalysisFail;35351 return sema.failTransitive(.dependency_loop);
35352}
35353
35354/// Marks the owner of `sema` as having failed semantic failed *without* an error message, and
35355/// returns failure. This function is suitable to call when any one of the following is true:
35356///
35357/// * `sema.owner` is guaranteed to be unreferenced on this update, for instance because it uses a
35358/// dead `InternPool.TrackedInst`.
35359///
35360/// * There is guaranteed to be a compile error if this unit is referenced. In practice, this means
35361/// that either there is an error elsewhere in the pipeline (e.g. AstGen), or we depend on another
35362/// `AnalUnit` which has itself failed.
35363pub fn failTransitive(sema: *Sema, reason: Zcu.TransitiveFailureReason) SemaError {
35364 assert(sema.err == null);
35365 const zcu = sema.pt.zcu;
35366 const unit = sema.owner;
35367
35368 log.debug("transitive failure analyzing '{f}' ({t})", .{ zcu.fmtAnalUnit(unit), reason });
35369
35370 assert(!zcu.failed_analysis.contains(unit));
35371 try zcu.transitive_failed_analysis.putNoClobber(
35372 zcu.comp.gpa,
35373 unit,
35374 if (build_options.enable_debug_extensions) reason,
35375 );
35376
35377 return error.AlreadyReported;
35297}35378}
src/Sema/LowerZon.zig+2-2
...@@ -320,7 +320,7 @@ fn failUnsupportedResultType(...@@ -320,7 +320,7 @@ fn failUnsupportedResultType(
320 self: *LowerZon,320 self: *LowerZon,
321 ty: Type,321 ty: Type,
322 opt_note: ?[]const u8,322 opt_note: ?[]const u8,
323) error{ AnalysisFail, OutOfMemory } {323) Zcu.SemaError {
324 @branchHint(.cold);324 @branchHint(.cold);
325 const sema = self.sema;325 const sema = self.sema;
326 const gpa = sema.gpa;326 const gpa = sema.gpa;
...@@ -338,7 +338,7 @@ fn fail(...@@ -338,7 +338,7 @@ fn fail(
338 node: Zoir.Node.Index,338 node: Zoir.Node.Index,
339 comptime format: []const u8,339 comptime format: []const u8,
340 args: anytype,340 args: anytype,
341) error{ AnalysisFail, OutOfMemory } {341) Zcu.SemaError {
342 @branchHint(.cold);342 @branchHint(.cold);
343 const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args);343 const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args);
344 try self.sema.pt.zcu.errNote(self.import_loc, err_msg, "imported here", .{});344 try self.sema.pt.zcu.errNote(self.import_loc, err_msg, "imported here", .{});
src/Sema/type_resolution.zig+21-7
...@@ -116,7 +116,10 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons...@@ -116,7 +116,10 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons
116 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {116 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {
117 return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason);117 return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason);
118 }118 }
119 try pt.ensureTypeLayoutUpToDate(ty, reason);119 pt.ensureTypeLayoutUpToDate(ty, reason) catch |err| switch (err) {
120 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .type_layout = ty.toIntern() }) }),
121 else => |e| return e,
122 };
120 },123 },
121124
122 // values, not types125 // values, not types
...@@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema...@@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema
166 return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason);169 return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason);
167 }170 }
168171
169 try pt.ensureStructDefaultsUpToDate(ty, &reason);172 pt.ensureStructDefaultsUpToDate(ty, &reason) catch |err| switch (err) {
173 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .struct_defaults = ty.toIntern() }) }),
174 else => |e| return e,
175 };
170}176}
171177
172/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.178/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.
...@@ -188,7 +194,9 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {...@@ -188,7 +194,9 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
188194
189 const struct_obj = ip.loadStructType(struct_ty.toIntern());195 const struct_obj = ip.loadStructType(struct_ty.toIntern());
190 assert(struct_obj.want_layout);196 assert(struct_obj.want_layout);
191 const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;197 const zir_index = struct_obj.zir_index.resolve(ip) orelse {
198 return sema.failTransitive(.{ .lost_tracking = struct_obj.zir_index });
199 };
192200
193 var block: Block = .{201 var block: Block = .{
194 .parent = null,202 .parent = null,
...@@ -606,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {...@@ -606,7 +614,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
606 struct_ty.assertHasLayout(zcu);614 struct_ty.assertHasLayout(zcu);
607 const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() });615 const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() });
608 if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) {616 if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) {
609 return error.AnalysisFail;617 return sema.failTransitive(.{ .failed_unit = layout_unit });
610 }618 }
611619
612 const struct_obj = ip.loadStructType(struct_ty.toIntern());620 const struct_obj = ip.loadStructType(struct_ty.toIntern());
...@@ -656,7 +664,9 @@ fn resolveStructDefaultsInner(...@@ -656,7 +664,9 @@ fn resolveStructDefaultsInner(
656 assert(struct_obj.field_defaults.len > 0);664 assert(struct_obj.field_defaults.len > 0);
657665
658 // We'll need to map the struct decl instruction to provide result types666 // We'll need to map the struct decl instruction to provide result types
659 const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;667 const zir_index = struct_obj.zir_index.resolve(ip) orelse {
668 return sema.failTransitive(.{ .lost_tracking = struct_obj.zir_index });
669 };
660 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});670 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
661671
662 const field_types = struct_obj.field_types.get(ip);672 const field_types = struct_obj.field_types.get(ip);
...@@ -713,7 +723,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {...@@ -713,7 +723,9 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
713723
714 const union_obj = ip.loadUnionType(union_ty.toIntern());724 const union_obj = ip.loadUnionType(union_ty.toIntern());
715 assert(union_obj.want_layout);725 assert(union_obj.want_layout);
716 const zir_index = union_obj.zir_index.resolve(ip) orelse return error.AnalysisFail;726 const zir_index = union_obj.zir_index.resolve(ip) orelse {
727 return sema.failTransitive(.{ .lost_tracking = union_obj.zir_index });
728 };
717729
718 var block: Block = .{730 var block: Block = .{
719 .parent = null,731 .parent = null,
...@@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {...@@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
1212 };1224 };
12131225
1214 const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index;1226 const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index;
1215 const zir_index = tracked_inst.resolve(ip) orelse return error.AnalysisFail;1227 const zir_index = tracked_inst.resolve(ip) orelse {
1228 return sema.failTransitive(.{ .lost_tracking = tracked_inst });
1229 };
12161230
1217 var block: Block = .{1231 var block: Block = .{
1218 .parent = null,1232 .parent = null,
src/Zcu.zig+18-3
...@@ -182,7 +182,10 @@ analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason...@@ -182,7 +182,10 @@ analysis_in_progress: std.array_hash_map.Auto(AnalUnit, ?*const DependencyReason
182/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.182/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
183failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,183failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty,
184/// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed.184/// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed.
185transitive_failed_analysis: std.array_hash_map.Auto(AnalUnit, void) = .empty,185transitive_failed_analysis: std.array_hash_map.Auto(
186 AnalUnit,
187 if (build_options.enable_debug_extensions) TransitiveFailureReason else void,
188) = .empty,
186/// This `Nav` succeeded analysis, but failed codegen.189/// This `Nav` succeeded analysis, but failed codegen.
187/// This may be a simple "value" `Nav`, or it may be a function.190/// This may be a simple "value" `Nav`, or it may be a function.
188/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.191/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
...@@ -351,6 +354,18 @@ pub const DependencyReason = struct {...@@ -351,6 +354,18 @@ pub const DependencyReason = struct {
351 type_layout_reason: Sema.type_resolution.LayoutResolveReason,354 type_layout_reason: Sema.type_resolution.LayoutResolveReason,
352};355};
353356
357/// These are not required for anything, but when the compiler is built with debug extensions, we
358/// store these in `Zcu.transitive_failed_analysis` and surface them in the incremental debug server
359/// (see `src/IncrementalDebugServer.zig`) because they are a useful debugging aid for bugs in
360/// incremental compilation.
361pub const TransitiveFailureReason = union(enum) {
362 astgen_error,
363 dependency_loop,
364 lost_tracking: InternPool.TrackedInst.Index,
365 failed_unit: AnalUnit,
366 func_nav_val_changed: InternPool.Index,
367};
368
354pub const IncrementalDebugState = struct {369pub const IncrementalDebugState = struct {
355 /// All container types in the ZCU, even dead ones.370 /// All container types in the ZCU, even dead ones.
356 /// Value is the generation the type was created on.371 /// Value is the generation the type was created on.
...@@ -2808,13 +2823,13 @@ pub const LazySrcLoc = struct {...@@ -2808,13 +2823,13 @@ pub const LazySrcLoc = struct {
2808 }2823 }
2809};2824};
28102825
2811pub const SemaError = error{ OutOfMemory, Canceled, AnalysisFail };2826pub const SemaError = error{ OutOfMemory, Canceled, AlreadyReported };
2812pub const CompileError = error{2827pub const CompileError = error{
2813 OutOfMemory,2828 OutOfMemory,
2814 /// The compilation update is no longer desired.2829 /// The compilation update is no longer desired.
2815 Canceled,2830 Canceled,
2816 /// When this is returned, the compile error for the failure has already been recorded.2831 /// When this is returned, the compile error for the failure has already been recorded.
2817 AnalysisFail,2832 AlreadyReported,
2818 /// In a comptime scope, a return instruction was encountered. This error is only seen when2833 /// In a comptime scope, a return instruction was encountered. This error is only seen when
2819 /// doing a comptime function call.2834 /// doing a comptime function call.
2820 ComptimeReturn,2835 ComptimeReturn,
src/Zcu/PerThread.zig+73-90
...@@ -320,7 +320,7 @@ pub fn update(...@@ -320,7 +320,7 @@ pub fn update(
320 // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed,320 // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed,
321 // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze.321 // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze.
322 while (try zcu.findOutdatedToAnalyze()) |unit| {322 while (try zcu.findOutdatedToAnalyze()) |unit| {
323 const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) {323 const maybe_err: UpdateUnitError!void = switch (unit.unwrap()) {
324 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),324 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
325 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null),325 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null),
326 .nav_val => |nav| pt.ensureNavValUpToDate(nav, null),326 .nav_val => |nav| pt.ensureNavValUpToDate(nav, null),
...@@ -332,7 +332,7 @@ pub fn update(...@@ -332,7 +332,7 @@ pub fn update(
332 error.Canceled,332 error.Canceled,
333 => |e| return e,333 => |e| return e,
334334
335 error.AnalysisFail => {}, // already reported335 error.AnalysisFail => {},
336 };336 };
337 break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null);337 break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null);
338 },338 },
...@@ -344,7 +344,7 @@ pub fn update(...@@ -344,7 +344,7 @@ pub fn update(
344 error.Canceled,344 error.Canceled,
345 => |e| return e,345 => |e| return e,
346346
347 error.AnalysisFail => {}, // already reported347 error.AnalysisFail => {},
348 };348 };
349 }349 }
350}350}
...@@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc...@@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc
455455
456/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs456/// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs
457/// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`457/// AstGen as needed. Also updates `file.status`. Does not assume that `file.mod`
458/// is populated. Does not return `error.AnalysisFail` on AstGen failures.458/// is populated. Returns success even if the file has AstGen errors.
459pub fn updateFile(459pub fn updateFile(
460 pt: Zcu.PerThread,460 pt: Zcu.PerThread,
461 file_index: Zcu.File.Index,461 file_index: Zcu.File.Index,
...@@ -1036,6 +1036,11 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc...@@ -1036,6 +1036,11 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc
1036 zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index));1036 zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index));
1037}1037}
10381038
1039const UpdateUnitError = Allocator.Error || Io.Cancelable || error{
1040 /// Semantic analysis of this `AnalUnit` failed.
1041 AnalysisFail,
1042};
1043
1039/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.1044/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.
1040/// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore1045/// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore
1041/// this, since the error is already registered, but it must not use the value of memoized fields.1046/// this, since the error is already registered, but it must not use the value of memoized fields.
...@@ -1044,7 +1049,7 @@ pub fn ensureMemoizedStateUpToDate(...@@ -1044,7 +1049,7 @@ pub fn ensureMemoizedStateUpToDate(
1044 stage: InternPool.MemoizedStateStage,1049 stage: InternPool.MemoizedStateStage,
1045 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1050 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1046 reason: ?*const Zcu.DependencyReason,1051 reason: ?*const Zcu.DependencyReason,
1047) Zcu.SemaError!void {1052) UpdateUnitError!void {
1048 const zcu = pt.zcu;1053 const zcu = pt.zcu;
1049 const gpa = zcu.gpa;1054 const gpa = zcu.gpa;
10501055
...@@ -1078,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate(...@@ -1078,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate(
1078 const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed|1083 const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed|
1079 .{ any_changed or prev_failed, false }1084 .{ any_changed or prev_failed, false }
1080 else |err| switch (err) {1085 else |err| switch (err) {
1081 error.AnalysisFail => res: {1086 error.AlreadyReported => .{ !prev_failed, true },
1082 if (!zcu.failed_analysis.contains(unit)) {
1083 // If this unit caused the error, it would have an entry in `failed_analysis`.
1084 // Since it does not, this must be a transitive failure.
1085 try zcu.transitive_failed_analysis.put(gpa, unit, {});
1086 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(unit)});
1087 }
1088 break :res .{ !prev_failed, true };
1089 },
1090 error.OutOfMemory => {1087 error.OutOfMemory => {
1091 // TODO: same as for `ensureComptimeUnitUpToDate` etc1088 // TODO: same as for `ensureComptimeUnitUpToDate` etc
1092 return error.OutOfMemory;1089 return error.OutOfMemory;
...@@ -1154,7 +1151,7 @@ fn analyzeMemoizedState(...@@ -1154,7 +1151,7 @@ fn analyzeMemoizedState(
1154/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis1151/// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis
1155/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is1152/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
1156/// free to ignore this, since the error is already registered.1153/// free to ignore this, since the error is already registered.
1157pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void {1154pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) UpdateUnitError!void {
1158 const zcu = pt.zcu;1155 const zcu = pt.zcu;
1159 const gpa = zcu.gpa;1156 const gpa = zcu.gpa;
11601157
...@@ -1195,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -1195,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
1195 defer unit_tracking.end(zcu);1192 defer unit_tracking.end(zcu);
11961193
1197 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {1194 return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) {
1198 error.AnalysisFail => {1195 error.AlreadyReported => return error.AnalysisFail,
1199 if (!zcu.failed_analysis.contains(anal_unit)) {
1200 // If this unit caused the error, it would have an entry in `failed_analysis`.
1201 // Since it does not, this must be a transitive failure.
1202 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1203 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1204 }
1205 return error.AnalysisFail;
1206 },
1207 error.OutOfMemory => {1196 error.OutOfMemory => {
1208 // TODO: it's unclear how to gracefully handle this.1197 // TODO: it's unclear how to gracefully handle this.
1209 // To report the error cleanly, we need to add a message to `failed_analysis` and a1198 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -1221,8 +1210,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU...@@ -1221,8 +1210,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU
12211210
1222/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old1211/// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old
1223/// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this1212/// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this
1224/// function will return `error.AnalysisFail`, and it is the caller's reponsibility to add an entry1213/// function will return `error.AlreadyReported`.
1225/// to `transitive_failed_analysis` if necessary.
1226fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {1214fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void {
1227 const zcu = pt.zcu;1215 const zcu = pt.zcu;
1228 const ip = &zcu.intern_pool;1216 const ip = &zcu.intern_pool;
...@@ -1239,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -1239,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
1239 defer tracy_trace.end();1227 defer tracy_trace.end();
1240 tracy_trace.addTextFmt("cu_id={d}", .{cu_id});1228 tracy_trace.addTextFmt("cu_id={d}", .{cu_id});
12411229
1242 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1230 const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse {
1231 try zcu.transitive_failed_analysis.putNoClobber(
1232 gpa,
1233 anal_unit,
1234 if (build_options.enable_debug_extensions) .{ .lost_tracking = comptime_unit.zir_index },
1235 );
1236 return error.AlreadyReported;
1237 };
1243 const file = zcu.fileByIndex(inst_resolved.file);1238 const file = zcu.fileByIndex(inst_resolved.file);
1244 const zir = file.zir.?;1239 const zir = file.zir.?;
12451240
...@@ -1314,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1314,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate(
1314 ty: Type,1309 ty: Type,
1315 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1310 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1316 reason: ?*const Zcu.DependencyReason,1311 reason: ?*const Zcu.DependencyReason,
1317) Zcu.SemaError!void {1312) UpdateUnitError!void {
1318 const zcu = pt.zcu;1313 const zcu = pt.zcu;
1319 const ip = &zcu.intern_pool;1314 const ip = &zcu.intern_pool;
1320 const comp = zcu.comp;1315 const comp = zcu.comp;
...@@ -1399,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate(...@@ -1399,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate(
1399 const new_failed: bool = if (result) failed: {1394 const new_failed: bool = if (result) failed: {
1400 break :failed false;1395 break :failed false;
1401 } else |err| switch (err) {1396 } else |err| switch (err) {
1402 error.AnalysisFail => failed: {1397 error.AlreadyReported => true,
1403 if (!zcu.failed_analysis.contains(anal_unit)) {
1404 // If this unit caused the error, it would have an entry in `failed_analysis`.
1405 // Since it does not, this must be a transitive failure.
1406 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1407 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1408 }
1409 break :failed true;
1410 },
1411 error.OutOfMemory,1398 error.OutOfMemory,
1412 error.Canceled,1399 error.Canceled,
1413 => |e| return e,1400 => |e| return e,
...@@ -1442,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate(...@@ -1442,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate(
1442 ty: Type,1429 ty: Type,
1443 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1430 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1444 reason: ?*const Zcu.DependencyReason,1431 reason: ?*const Zcu.DependencyReason,
1445) Zcu.SemaError!void {1432) UpdateUnitError!void {
1446 const zcu = pt.zcu;1433 const zcu = pt.zcu;
1447 const ip = &zcu.intern_pool;1434 const ip = &zcu.intern_pool;
1448 const comp = zcu.comp;1435 const comp = zcu.comp;
...@@ -1513,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate(...@@ -1513,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate(
1513 const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: {1500 const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: {
1514 break :failed false;1501 break :failed false;
1515 } else |err| switch (err) {1502 } else |err| switch (err) {
1516 error.AnalysisFail => failed: {1503 error.AlreadyReported => true,
1517 if (!zcu.failed_analysis.contains(anal_unit)) {
1518 // If this unit caused the error, it would have an entry in `failed_analysis`.
1519 // Since it does not, this must be a transitive failure.
1520 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1521 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1522 }
1523 break :failed true;
1524 },
1525 error.OutOfMemory,1504 error.OutOfMemory,
1526 error.Canceled,1505 error.Canceled,
1527 => |e| return e,1506 => |e| return e,
...@@ -1547,7 +1526,7 @@ pub fn ensureNavValUpToDate(...@@ -1547,7 +1526,7 @@ pub fn ensureNavValUpToDate(
1547 nav_id: InternPool.Nav.Index,1526 nav_id: InternPool.Nav.Index,
1548 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1527 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1549 reason: ?*const Zcu.DependencyReason,1528 reason: ?*const Zcu.DependencyReason,
1550) Zcu.SemaError!void {1529) UpdateUnitError!void {
1551 const zcu = pt.zcu;1530 const zcu = pt.zcu;
1552 const gpa = zcu.gpa;1531 const gpa = zcu.gpa;
1553 const ip = &zcu.intern_pool;1532 const ip = &zcu.intern_pool;
...@@ -1594,15 +1573,7 @@ pub fn ensureNavValUpToDate(...@@ -1594,15 +1573,7 @@ pub fn ensureNavValUpToDate(
1594 false,1573 false,
1595 };1574 };
1596 } else |err| switch (err) {1575 } else |err| switch (err) {
1597 error.AnalysisFail => res: {1576 error.AlreadyReported => .{ !prev_failed, true },
1598 if (!zcu.failed_analysis.contains(anal_unit)) {
1599 // If this unit caused the error, it would have an entry in `failed_analysis`.
1600 // Since it does not, this must be a transitive failure.
1601 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1602 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1603 }
1604 break :res .{ !prev_failed, true };
1605 },
1606 error.OutOfMemory => {1577 error.OutOfMemory => {
1607 // TODO: it's unclear how to gracefully handle this.1578 // TODO: it's unclear how to gracefully handle this.
1608 // To report the error cleanly, we need to add a message to `failed_analysis` and a1579 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -1655,7 +1626,14 @@ fn analyzeNavVal(...@@ -1655,7 +1626,14 @@ fn analyzeNavVal(
1655 tracy_trace.addText(old_nav.fqn.toSlice(ip));1626 tracy_trace.addText(old_nav.fqn.toSlice(ip));
1656 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});1627 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});
16571628
1658 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1629 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse {
1630 try zcu.transitive_failed_analysis.putNoClobber(
1631 gpa,
1632 anal_unit,
1633 if (build_options.enable_debug_extensions) .{ .lost_tracking = old_nav.analysis.?.zir_index },
1634 );
1635 return error.AlreadyReported;
1636 };
1659 const file = zcu.fileByIndex(inst_resolved.file);1637 const file = zcu.fileByIndex(inst_resolved.file);
1660 const zir = file.zir.?;1638 const zir = file.zir.?;
1661 const zir_decl = zir.getDeclaration(inst_resolved.inst);1639 const zir_decl = zir.getDeclaration(inst_resolved.inst);
...@@ -1916,7 +1894,7 @@ pub fn ensureNavTypeUpToDate(...@@ -1916,7 +1894,7 @@ pub fn ensureNavTypeUpToDate(
1916 nav_id: InternPool.Nav.Index,1894 nav_id: InternPool.Nav.Index,
1917 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.1895 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
1918 reason: ?*const Zcu.DependencyReason,1896 reason: ?*const Zcu.DependencyReason,
1919) Zcu.SemaError!void {1897) UpdateUnitError!void {
1920 const zcu = pt.zcu;1898 const zcu = pt.zcu;
1921 const gpa = zcu.gpa;1899 const gpa = zcu.gpa;
1922 const ip = &zcu.intern_pool;1900 const ip = &zcu.intern_pool;
...@@ -1963,15 +1941,7 @@ pub fn ensureNavTypeUpToDate(...@@ -1963,15 +1941,7 @@ pub fn ensureNavTypeUpToDate(
1963 false,1941 false,
1964 };1942 };
1965 } else |err| switch (err) {1943 } else |err| switch (err) {
1966 error.AnalysisFail => res: {1944 error.AlreadyReported => .{ !prev_failed, true },
1967 if (!zcu.failed_analysis.contains(anal_unit)) {
1968 // If this unit caused the error, it would have an entry in `failed_analysis`.
1969 // Since it does not, this must be a transitive failure.
1970 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1971 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1972 }
1973 break :res .{ !prev_failed, true };
1974 },
1975 error.OutOfMemory => {1945 error.OutOfMemory => {
1976 // TODO: it's unclear how to gracefully handle this.1946 // TODO: it's unclear how to gracefully handle this.
1977 // To report the error cleanly, we need to add a message to `failed_analysis` and a1947 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -2024,7 +1994,14 @@ fn analyzeNavType(...@@ -2024,7 +1994,14 @@ fn analyzeNavType(
2024 tracy_trace.addText(old_nav.fqn.toSlice(ip));1994 tracy_trace.addText(old_nav.fqn.toSlice(ip));
2025 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});1995 tracy_trace.addTextFmt("nav_id={d}", .{nav_id});
20261996
2027 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail;1997 const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse {
1998 try zcu.transitive_failed_analysis.putNoClobber(
1999 gpa,
2000 anal_unit,
2001 if (build_options.enable_debug_extensions) .{ .lost_tracking = old_nav.analysis.?.zir_index },
2002 );
2003 return error.AlreadyReported;
2004 };
2028 const file = zcu.fileByIndex(inst_resolved.file);2005 const file = zcu.fileByIndex(inst_resolved.file);
2029 const zir = file.zir.?;2006 const zir = file.zir.?;
20302007
...@@ -2160,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate(...@@ -2160,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate(
2160 func_index: InternPool.Index,2137 func_index: InternPool.Index,
2161 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.2138 /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`.
2162 reason: ?*const Zcu.DependencyReason,2139 reason: ?*const Zcu.DependencyReason,
2163) Zcu.SemaError!void {2140) UpdateUnitError!void {
2164 dev.check(.sema);2141 dev.check(.sema);
21652142
2166 const zcu = pt.zcu;2143 const zcu = pt.zcu;
...@@ -2204,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate(...@@ -2204,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate(
2204 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result|2181 const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result|
2205 .{ prev_failed or result.ies_outdated, false }2182 .{ prev_failed or result.ies_outdated, false }
2206 else |err| switch (err) {2183 else |err| switch (err) {
2207 error.AnalysisFail => res: {2184 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
2208 if (!zcu.failed_analysis.contains(anal_unit)) {2185 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
2209 // If this function caused the error, it would have an entry in `failed_analysis`.2186 // a different error later (which may now be invalid).
2210 // Since it does not, this must be a transitive failure.2187 error.AlreadyReported => .{ !prev_failed, true },
2211 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
2212 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
2213 }
2214 // We consider the IES to be outdated if the function previously succeeded analysis; in this case,
2215 // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting
2216 // a different error later (which may now be invalid).
2217 break :res .{ !prev_failed, true };
2218 },
2219 error.OutOfMemory => {2188 error.OutOfMemory => {
2220 // TODO: it's unclear how to gracefully handle this.2189 // TODO: it's unclear how to gracefully handle this.
2221 // To report the error cleanly, we need to add a message to `failed_analysis` and a2190 // To report the error cleanly, we need to add a message to `failed_analysis` and a
...@@ -3306,15 +3275,21 @@ fn analyzeFuncBodyInner(...@@ -3306,15 +3275,21 @@ fn analyzeFuncBodyInner(
3306 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.3275 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
33073276
3308 if (func.generic_owner == .none) {3277 if (func.generic_owner == .none) {
3309 try pt.ensureNavValUpToDate(func.owner_nav, reason);3278 pt.ensureNavValUpToDate(func.owner_nav, reason) catch |err| switch (err) {
3279 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = func.owner_nav }) }),
3280 else => |e| return e,
3281 };
3310 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {3282 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {
3311 return error.AnalysisFail;3283 return sema.failTransitive(.{ .func_nav_val_changed = func_index });
3312 }3284 }
3313 } else {3285 } else {
3314 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;3286 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
3315 try pt.ensureNavValUpToDate(go_nav, reason);3287 pt.ensureNavValUpToDate(go_nav, reason) catch |err| switch (err) {
3288 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = go_nav }) }),
3289 else => |e| return e,
3290 };
3316 if (ip.getNav(go_nav).resolved.?.value != func.generic_owner) {3291 if (ip.getNav(go_nav).resolved.?.value != func.generic_owner) {
3317 return error.AnalysisFail;3292 return sema.failTransitive(.{ .func_nav_val_changed = func.generic_owner });
3318 }3293 }
3319 }3294 }
33203295
...@@ -3344,7 +3319,9 @@ fn analyzeFuncBodyInner(...@@ -3344,7 +3319,9 @@ fn analyzeFuncBodyInner(
3344 };3319 };
3345 defer inner_block.instructions.deinit(gpa);3320 defer inner_block.instructions.deinit(gpa);
33463321
3347 const fn_info = sema.code.getFnInfo(func.zirBodyInstUnordered(ip).resolve(ip) orelse return error.AnalysisFail);3322 const fn_info = sema.code.getFnInfo(func.zirBodyInstUnordered(ip).resolve(ip) orelse {
3323 return sema.failTransitive(.{ .lost_tracking = func.zirBodyInstUnordered(ip) });
3324 });
33483325
3349 // Here we are performing "runtime semantic analysis" for a function body, which means3326 // Here we are performing "runtime semantic analysis" for a function body, which means
3350 // we must map the parameter ZIR instructions to `arg` AIR instructions.3327 // we must map the parameter ZIR instructions to `arg` AIR instructions.
...@@ -4378,12 +4355,18 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable |...@@ -4378,12 +4355,18 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable |
4378 return result.index;4355 return result.index;
4379}4356}
43804357
4358const UpdateNamespaceError = Allocator.Error || Io.Cancelable || error{
4359 /// This namespace refers to a ZIR container declaration which no longer exists, so any code
4360 /// referencing it is guaranteed to be unreferenced on this update.
4361 LostZirContainerDecl,
4362};
4363
4381/// Given a namespace, re-scan its declarations from the type definition if they have not4364/// Given a namespace, re-scan its declarations from the type definition if they have not
4382/// yet been re-scanned on this update.4365/// yet been re-scanned on this update.
4383/// If the type declaration instruction has been lost, returns `error.AnalysisFail`.4366/// If the type declaration instruction has been lost, returns `error.LostZirContainerDecl`.
4384/// This will effectively short-circuit the caller, which will be semantic analysis of a4367/// This will effectively short-circuit the caller, which will be semantic analysis of a
4385/// guaranteed-unreferenced `AnalUnit`, to trigger a transitive analysis error.4368/// guaranteed-unreferenced `AnalUnit`, to trigger a transitive analysis error.
4386pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) Zcu.SemaError!void {4369pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) UpdateNamespaceError!void {
4387 const zcu = pt.zcu;4370 const zcu = pt.zcu;
4388 const ip = &zcu.intern_pool;4371 const ip = &zcu.intern_pool;
4389 const namespace = zcu.namespacePtr(namespace_index);4372 const namespace = zcu.namespacePtr(namespace_index);
...@@ -4410,7 +4393,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace...@@ -4410,7 +4393,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
44104393
4411 // Namespace outdated -- re-scan the type if necessary.4394 // Namespace outdated -- re-scan the type if necessary.
44124395
4413 const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;4396 const inst_info = key.zir_index.resolveFull(ip) orelse return error.LostZirContainerDecl;
4414 const file = zcu.fileByIndex(inst_info.file);4397 const file = zcu.fileByIndex(inst_info.file);
4415 const zir = &file.zir.?;4398 const zir = &file.zir.?;
44164399