authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-20 09:51:36+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-20 16:27:04+02:00
log4a65cc4aca6fd03e80272a211e9b6c8c50716594
treec2adba549fe8ae9cca555bf0c7cb1176802d5a58
parentfec502ec674e458a53e846abb875e6591c3eacfb

Zcu: report outdated nav_ty when previous generation had a compile error

This logic existed when actually analyzing a `nav_ty` unit directly; it was just missing in the code path which resolves a `nav_ty` unit due to a `nav_val` being resolved. Resolves: #35307

2 files changed, 35 insertions(+), 5 deletions(-)

src/Zcu/PerThread.zig+12-5
......@@ -1872,15 +1872,22 @@ fn analyzeNavVal(
18721872 // that case and invalidate the dependee right now.
18731873 if (zcu.clearOutdatedState(.wrap(.{ .nav_ty = nav_id }))) {
18741874 assert(zir_decl.type_body == null); // otherwise we already resolved it with `Sema.ensureNavResolved`
1875 zcu.resetUnit(.wrap(.{ .nav_ty = nav_id }));
1876 try pt.addDependency(.wrap(.{ .nav_ty = nav_id }), .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!)
1875 const type_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id });
1876 const prev_type_failed = zcu.failed_analysis.contains(type_unit) or
1877 zcu.transitive_failed_analysis.contains(type_unit);
1878 zcu.resetUnit(type_unit);
1879 try pt.addDependency(type_unit, .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!)
18771880 if (comp.debugIncremental()) {
1878 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, .wrap(.{ .nav_ty = nav_id }));
1881 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, type_unit);
18791882 info.last_update_gen = zcu.generation;
18801883 info.deps.clearRetainingCapacity();
18811884 }
1882 const type_changed: bool = if (old_nav.resolved) |r| r.type != nav_ty.toIntern() else true;
1883 if (type_changed) {
1885 const type_outdated: bool = type_outdated: {
1886 if (prev_type_failed) break :type_outdated true;
1887 const r = old_nav.resolved orelse break :type_outdated true;
1888 break :type_outdated r.type != nav_ty.toIntern();
1889 };
1890 if (type_outdated) {
18841891 try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id });
18851892 } else {
18861893 try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id });
test/incremental/pointer_to_decl_with_astgen_error created+23
......@@ -0,0 +1,23 @@
1#update=initial version
2#file=main.zig
3const foo = {};
4pub fn main() void {
5 _ = &foo;
6}
7#expect_stdout=""
8
9#update=introduce use of undeclared identifier
10#file=main.zig
11const foo = something;
12pub fn main() void {
13 _ = &foo;
14}
15#expect_error=main.zig:1:13: error: use of undeclared identifier 'something'
16
17#update=revert use of undeclared identifier
18#file=main.zig
19const foo = {};
20pub fn main() void {
21 _ = &foo;
22}
23#expect_stdout=""