authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-05 21:58:32+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-02-05 22:00:55+00:00
logb21becb2a6a82b4ac65e98fa0094a7786cbbfdc3
tree3f34547059ff6e207e17ccf64d0ce68cf0728220
parent3031d813874f6d6ad9ae4b793e3af6cdf632fa66
signaturelock-open Commit is signed but in an unrecognized format.

incremental: fix crash when introducing syntax error

Clearing the analysis roots was very clever and all, but not actually valid. We need to avoid *any* reference to the analysis errors if there were any fatal files, and that includes sorting the errors! Resolves: #22774

3 files changed, 50 insertions(+), 4 deletions(-)

src/Compilation.zig+6-4
......@@ -2195,6 +2195,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
21952195
21962196 zcu.compile_log_text.shrinkAndFree(gpa, 0);
21972197
2198 zcu.skip_analysis_errors = false;
2199
21982200 // Make sure std.zig is inside the import_table. We unconditionally need
21992201 // it for start.zig.
22002202 const std_mod = zcu.std_mod;
......@@ -3207,7 +3209,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
32073209 });
32083210 }
32093211
3210 if (comp.zcu) |zcu| {
3212 if (comp.zcu) |zcu| zcu_errors: {
32113213 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {
32123214 if (error_msg) |msg| {
32133215 try addModuleErrorMsg(zcu, &bundle, msg.*);
......@@ -3224,6 +3226,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
32243226 }
32253227 }
32263228 }
3229 if (zcu.skip_analysis_errors) break :zcu_errors;
32273230 var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: {
32283231 const SortOrder = struct {
32293232 zcu: *Zcu,
......@@ -3359,7 +3362,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
33593362 try comp.link_diags.addMessagesToBundle(&bundle, comp.bin_file);
33603363
33613364 if (comp.zcu) |zcu| {
3362 if (bundle.root_list.items.len == 0 and zcu.compile_log_sources.count() != 0) {
3365 if (!zcu.skip_analysis_errors and bundle.root_list.items.len == 0 and zcu.compile_log_sources.count() != 0) {
33633366 const values = zcu.compile_log_sources.values();
33643367 // First one will be the error; subsequent ones will be notes.
33653368 const src_loc = values[0].src();
......@@ -3860,10 +3863,9 @@ fn performAllTheWorkInner(
38603863 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents
38613864 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.
38623865 // However, this means our analysis data is invalid, so we want to omit all analysis errors.
3863 // To do that, let's just clear the analysis roots!
38643866
38653867 assert(zcu.failed_files.count() > 0); // we will get an error
3866 zcu.analysis_roots.clear(); // no analysis happened
3868 zcu.skip_analysis_errors = true;
38673869 return;
38683870 }
38693871
src/Zcu.zig+2
......@@ -181,6 +181,8 @@ analysis_roots: std.BoundedArray(*Package.Module, 3) = .{},
181181/// Allocated into `gpa`.
182182resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null,
183183
184skip_analysis_errors: bool = false,
185
184186stage1_flags: packed struct {
185187 have_winmain: bool = false,
186188 have_wwinmain: bool = false,
test/incremental/analysis_error_and_syntax_error created+42
......@@ -0,0 +1,42 @@
1#target=x86_64-linux-selfhosted
2#target=x86_64-linux-cbe
3#target=x86_64-windows-cbe
4#target=wasm32-wasi-selfhosted
5#update=initial version
6#file=main.zig
7pub fn main() !void {
8 @compileError("uh oh");
9}
10#expect_error=main.zig:2:5: error: uh oh
11
12#update=add parse error
13#file=main.zig
14pub fn main() !void {
15 @compileError("uh oh");
16#expect_error=main.zig:3:1: error: expected statement, found 'EOF'
17
18#update=fix parse error
19#file=main.zig
20pub fn main() !void {
21 @compileError("uh oh");
22}
23#expect_error=main.zig:2:5: error: uh oh
24
25#update=add parse error again
26#file=main.zig
27pub fn main() !void {
28 @compileError("uh oh");
29#expect_error=main.zig:3:1: error: expected statement, found 'EOF'
30
31#update=comment @compileError call
32#file=main.zig
33pub fn main() !void {
34 //@compileError("uh oh");
35#expect_error=main.zig:3:1: error: expected statement, found 'EOF'
36
37#update=fix parse error again
38#file=main.zig
39pub fn main() !void {
40 //@compileError("uh oh");
41}
42#expect_stdout=""