authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-01 23:34:55+02:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-01 23:34:55+02:00
log4af8a35ca91578615f1a6c7a3dc8c82cfd48fea3
tree0ac66d9f4ab22e2265e7b67b7c263944935c2ca5
parent6ee0ef96fea84f66ad3e7e987a07a5b89ab41308
parent804c284d2a4ece85aec64d25c241a48b4e8b11ad

Merge pull request 'incremental: fix incorrect dependency in generic instances' (#36363) from mlugg/incremental-generic-instance-owner-dep into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36363

8 files changed, 323 insertions(+), 164 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+75-92
...@@ -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
...@@ -3293,9 +3262,7 @@ fn analyzeFuncBodyInner(...@@ -3293,9 +3262,7 @@ fn analyzeFuncBodyInner(
3293 defer sema.deinit();3262 defer sema.deinit();
32943263
3295 // Every runtime function has a dependency on the source of the Decl it originates from.3264 // Every runtime function has a dependency on the source of the Decl it originates from.
3296 // It also depends on the value of its owner Decl.
3297 try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });3265 try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });
3298 try sema.declareDependency(.{ .nav_val = func.owner_nav });
32993266
3300 // Make sure that the declaration `Nav` still refers to this function (or its generic owner).3267 // Make sure that the declaration `Nav` still refers to this function (or its generic owner).
3301 // This will not be the case if the incremental update has changed a function type or turned a3268 // This will not be the case if the incremental update has changed a function type or turned a
...@@ -3306,15 +3273,23 @@ fn analyzeFuncBodyInner(...@@ -3306,15 +3273,23 @@ fn analyzeFuncBodyInner(
3306 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.3273 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
33073274
3308 if (func.generic_owner == .none) {3275 if (func.generic_owner == .none) {
3309 try pt.ensureNavValUpToDate(func.owner_nav, reason);3276 try sema.declareDependency(.{ .nav_val = func.owner_nav });
3277 pt.ensureNavValUpToDate(func.owner_nav, reason) catch |err| switch (err) {
3278 error.AnalysisFail => return sema.failTransitive(.{ .failed_unit = .wrap(.{ .nav_val = func.owner_nav }) }),
3279 else => |e| return e,
3280 };
3310 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {3281 if (ip.getNav(func.owner_nav).resolved.?.value != func_index) {
3311 return error.AnalysisFail;3282 return sema.failTransitive(.{ .func_nav_val_changed = func_index });
3312 }3283 }
3313 } else {3284 } else {
3314 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;3285 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
3315 try pt.ensureNavValUpToDate(go_nav, reason);3286 try sema.declareDependency(.{ .nav_val = go_nav });
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
test/incremental/temporary_analysis_error_in_generic_signature created+46
...@@ -0,0 +1,46 @@
1#update=initial version
2#file=main.zig
3//! The original repro here depends on re-analysis order, which depends on
4//! declaration order, so this exact declaration order must be used.
5const Foo = struct { x: u8 };
6pub fn main(init: std.process.Init) !void {
7 const c = bar('Z').x;
8 try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
9}
10fn bar(comptime x: u8) @This().Foo {
11 return .{ .x = x };
12}
13const std = @import("std");
14#expect_stdout="Z\n"
15
16#update=change generic signature to use non-existent member
17#file=main.zig
18//! The original repro here depends on re-analysis order, which depends on
19//! declaration order, so this exact declaration order must be used.
20const Foo = struct { x: u8 };
21pub fn main(init: std.process.Init) !void {
22 const c = bar('Z').x;
23 try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
24}
25fn bar(comptime x: u8) @This().FooAlias {
26 return .{ .x = x };
27}
28const std = @import("std");
29#expect_error=main.zig:8:31: error: root source file struct 'main' has no member named 'FooAlias'
30#expect_error=main.zig:1:1: note: struct declared here
31
32#update=add that member, fixing the error
33#file=main.zig
34//! The original repro here depends on re-analysis order, which depends on
35//! declaration order, so this exact declaration order must be used.
36const Foo = struct { x: u8 };
37const FooAlias = Foo;
38pub fn main(init: std.process.Init) !void {
39 const c = bar('Z').x;
40 try std.Io.File.stdout().writeStreamingAll(init.io, &.{ c, '\n' });
41}
42fn bar(comptime x: u8) @This().FooAlias {
43 return .{ .x = x };
44}
45const std = @import("std");
46#expect_stdout="Z\n"