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 {...@@ -2195,6 +2195,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
21952195
2196 zcu.compile_log_text.shrinkAndFree(gpa, 0);2196 zcu.compile_log_text.shrinkAndFree(gpa, 0);
21972197
2198 zcu.skip_analysis_errors = false;
2199
2198 // Make sure std.zig is inside the import_table. We unconditionally need2200 // Make sure std.zig is inside the import_table. We unconditionally need
2199 // it for start.zig.2201 // it for start.zig.
2200 const std_mod = zcu.std_mod;2202 const std_mod = zcu.std_mod;
...@@ -3207,7 +3209,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3207,7 +3209,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3207 });3209 });
3208 }3210 }
32093211
3210 if (comp.zcu) |zcu| {3212 if (comp.zcu) |zcu| zcu_errors: {
3211 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {3213 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {
3212 if (error_msg) |msg| {3214 if (error_msg) |msg| {
3213 try addModuleErrorMsg(zcu, &bundle, msg.*);3215 try addModuleErrorMsg(zcu, &bundle, msg.*);
...@@ -3224,6 +3226,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3224,6 +3226,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3224 }3226 }
3225 }3227 }
3226 }3228 }
3229 if (zcu.skip_analysis_errors) break :zcu_errors;
3227 var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: {3230 var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: {
3228 const SortOrder = struct {3231 const SortOrder = struct {
3229 zcu: *Zcu,3232 zcu: *Zcu,
...@@ -3359,7 +3362,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3359,7 +3362,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3359 try comp.link_diags.addMessagesToBundle(&bundle, comp.bin_file);3362 try comp.link_diags.addMessagesToBundle(&bundle, comp.bin_file);
33603363
3361 if (comp.zcu) |zcu| {3364 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) {
3363 const values = zcu.compile_log_sources.values();3366 const values = zcu.compile_log_sources.values();
3364 // First one will be the error; subsequent ones will be notes.3367 // First one will be the error; subsequent ones will be notes.
3365 const src_loc = values[0].src();3368 const src_loc = values[0].src();
...@@ -3860,10 +3863,9 @@ fn performAllTheWorkInner(...@@ -3860,10 +3863,9 @@ fn performAllTheWorkInner(
3860 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents3863 // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents
3861 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.3864 // us from invalidating lots of incremental dependencies due to files with e.g. parse errors.
3862 // However, this means our analysis data is invalid, so we want to omit all analysis errors.3865 // 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
3865 assert(zcu.failed_files.count() > 0); // we will get an error3867 assert(zcu.failed_files.count() > 0); // we will get an error
3866 zcu.analysis_roots.clear(); // no analysis happened3868 zcu.skip_analysis_errors = true;
3867 return;3869 return;
3868 }3870 }
38693871
src/Zcu.zig+2
...@@ -181,6 +181,8 @@ analysis_roots: std.BoundedArray(*Package.Module, 3) = .{},...@@ -181,6 +181,8 @@ analysis_roots: std.BoundedArray(*Package.Module, 3) = .{},
181/// Allocated into `gpa`.181/// Allocated into `gpa`.
182resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null,182resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null,
183183
184skip_analysis_errors: bool = false,
185
184stage1_flags: packed struct {186stage1_flags: packed struct {
185 have_winmain: bool = false,187 have_winmain: bool = false,
186 have_wwinmain: bool = false,188 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=""