| author | |
| committer | |
| log | 6201031e0581c54688fdf6071a250b80f892525b |
| tree | b8fac5782647b26920756d6a805cd5d799f533ff |
| parent | bdd3bc056ee998770ea48a93b4ec99521f069aed |
| parent | 3ba4f86198267fee0f6a8d50496908794e743cbd |
| signature |
incremental compilation progress10 files changed, 181 insertions(+), 62 deletions(-)
src/Compilation.zig+29-35| ... | @@ -2901,6 +2901,7 @@ pub fn makeBinFileWritable(comp: *Compilation) !void { | ... | @@ -2901,6 +2901,7 @@ pub fn makeBinFileWritable(comp: *Compilation) !void { |
| 2901 | const Header = extern struct { | 2901 | const Header = extern struct { |
| 2902 | intern_pool: extern struct { | 2902 | intern_pool: extern struct { |
| 2903 | thread_count: u32, | 2903 | thread_count: u32, |
| 2904 | file_deps_len: u32, | ||
| 2904 | src_hash_deps_len: u32, | 2905 | src_hash_deps_len: u32, |
| 2905 | nav_val_deps_len: u32, | 2906 | nav_val_deps_len: u32, |
| 2906 | namespace_deps_len: u32, | 2907 | namespace_deps_len: u32, |
| ... | @@ -2943,6 +2944,7 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -2943,6 +2944,7 @@ pub fn saveState(comp: *Compilation) !void { |
| 2943 | const header: Header = .{ | 2944 | const header: Header = .{ |
| 2944 | .intern_pool = .{ | 2945 | .intern_pool = .{ |
| 2945 | .thread_count = @intCast(ip.locals.len), | 2946 | .thread_count = @intCast(ip.locals.len), |
| 2947 | .file_deps_len = @intCast(ip.file_deps.count()), | ||
| 2946 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), | 2948 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), |
| 2947 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), | 2949 | .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), |
| 2948 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), | 2950 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), |
| ... | @@ -2969,6 +2971,8 @@ pub fn saveState(comp: *Compilation) !void { | ... | @@ -2969,6 +2971,8 @@ pub fn saveState(comp: *Compilation) !void { |
| 2969 | addBuf(&bufs, mem.asBytes(&header)); | 2971 | addBuf(&bufs, mem.asBytes(&header)); |
| 2970 | addBuf(&bufs, mem.sliceAsBytes(pt_headers.items)); | 2972 | addBuf(&bufs, mem.sliceAsBytes(pt_headers.items)); |
| 2971 | 2973 | ||
| 2974 | addBuf(&bufs, mem.sliceAsBytes(ip.file_deps.keys())); | ||
| 2975 | addBuf(&bufs, mem.sliceAsBytes(ip.file_deps.values())); | ||
| 2972 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); | 2976 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.keys())); |
| 2973 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); | 2977 | addBuf(&bufs, mem.sliceAsBytes(ip.src_hash_deps.values())); |
| 2974 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); | 2978 | addBuf(&bufs, mem.sliceAsBytes(ip.nav_val_deps.keys())); |
| ... | @@ -3076,15 +3080,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3076,15 +3080,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3076 | }); | 3080 | }); |
| 3077 | } | 3081 | } |
| 3078 | 3082 | ||
| 3079 | var all_references: ?std.AutoHashMapUnmanaged(InternPool.AnalUnit, ?Zcu.ResolvedReference) = null; | ||
| 3080 | defer if (all_references) |*a| a.deinit(gpa); | ||
| 3081 | |||
| 3082 | if (comp.zcu) |zcu| { | 3083 | if (comp.zcu) |zcu| { |
| 3083 | const ip = &zcu.intern_pool; | 3084 | const ip = &zcu.intern_pool; |
| 3084 | 3085 | ||
| 3085 | for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| { | 3086 | for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| { |
| 3086 | if (error_msg) |msg| { | 3087 | if (error_msg) |msg| { |
| 3087 | try addModuleErrorMsg(zcu, &bundle, msg.*, &all_references); | 3088 | try addModuleErrorMsg(zcu, &bundle, msg.*); |
| 3088 | } else { | 3089 | } else { |
| 3089 | // Must be ZIR errors. Note that this may include AST errors. | 3090 | // Must be ZIR errors. Note that this may include AST errors. |
| 3090 | // addZirErrorMessages asserts that the tree is loaded. | 3091 | // addZirErrorMessages asserts that the tree is loaded. |
| ... | @@ -3093,7 +3094,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3093,7 +3094,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3093 | } | 3094 | } |
| 3094 | } | 3095 | } |
| 3095 | for (zcu.failed_embed_files.values()) |error_msg| { | 3096 | for (zcu.failed_embed_files.values()) |error_msg| { |
| 3096 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references); | 3097 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3097 | } | 3098 | } |
| 3098 | { | 3099 | { |
| 3099 | const SortOrder = struct { | 3100 | const SortOrder = struct { |
| ... | @@ -3136,10 +3137,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3136,10 +3137,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3136 | } | 3137 | } |
| 3137 | for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| { | 3138 | for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| { |
| 3138 | if (comp.incremental) { | 3139 | if (comp.incremental) { |
| 3139 | if (all_references == null) { | 3140 | const refs = try zcu.resolveReferences(); |
| 3140 | all_references = try zcu.resolveReferences(); | 3141 | if (!refs.contains(anal_unit)) continue; |
| 3141 | } | ||
| 3142 | if (!all_references.?.contains(anal_unit)) continue; | ||
| 3143 | } | 3142 | } |
| 3144 | 3143 | ||
| 3145 | const file_index = switch (anal_unit.unwrap()) { | 3144 | const file_index = switch (anal_unit.unwrap()) { |
| ... | @@ -3151,7 +3150,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3151,7 +3150,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3151 | // We'll try again once parsing succeeds. | 3150 | // We'll try again once parsing succeeds. |
| 3152 | if (!zcu.fileByIndex(file_index).okToReportErrors()) continue; | 3151 | if (!zcu.fileByIndex(file_index).okToReportErrors()) continue; |
| 3153 | 3152 | ||
| 3154 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references); | 3153 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3155 | if (zcu.cimport_errors.get(anal_unit)) |errors| { | 3154 | if (zcu.cimport_errors.get(anal_unit)) |errors| { |
| 3156 | for (errors.getMessages()) |err_msg_index| { | 3155 | for (errors.getMessages()) |err_msg_index| { |
| 3157 | const err_msg = errors.getErrorMessage(err_msg_index); | 3156 | const err_msg = errors.getErrorMessage(err_msg_index); |
| ... | @@ -3175,10 +3174,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3175,10 +3174,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3175 | } | 3174 | } |
| 3176 | for (zcu.failed_codegen.keys(), zcu.failed_codegen.values()) |nav, error_msg| { | 3175 | for (zcu.failed_codegen.keys(), zcu.failed_codegen.values()) |nav, error_msg| { |
| 3177 | if (!zcu.navFileScope(nav).okToReportErrors()) continue; | 3176 | if (!zcu.navFileScope(nav).okToReportErrors()) continue; |
| 3178 | try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references); | 3177 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3179 | } | 3178 | } |
| 3180 | for (zcu.failed_exports.values()) |value| { | 3179 | for (zcu.failed_exports.values()) |value| { |
| 3181 | try addModuleErrorMsg(zcu, &bundle, value.*, &all_references); | 3180 | try addModuleErrorMsg(zcu, &bundle, value.*); |
| 3182 | } | 3181 | } |
| 3183 | 3182 | ||
| 3184 | const actual_error_count = zcu.intern_pool.global_error_set.getNamesFromMainThread().len; | 3183 | const actual_error_count = zcu.intern_pool.global_error_set.getNamesFromMainThread().len; |
| ... | @@ -3252,17 +3251,15 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { | ... | @@ -3252,17 +3251,15 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3252 | }; | 3251 | }; |
| 3253 | } | 3252 | } |
| 3254 | 3253 | ||
| 3255 | try addModuleErrorMsg(zcu, &bundle, err_msg, &all_references); | 3254 | try addModuleErrorMsg(zcu, &bundle, err_msg); |
| 3256 | } | 3255 | } |
| 3257 | } | 3256 | } |
| 3258 | 3257 | ||
| 3259 | if (comp.zcu) |zcu| { | 3258 | if (comp.zcu) |zcu| { |
| 3260 | if (comp.incremental and bundle.root_list.items.len == 0) { | 3259 | if (comp.incremental and bundle.root_list.items.len == 0) { |
| 3261 | const should_have_error = for (zcu.transitive_failed_analysis.keys()) |failed_unit| { | 3260 | const should_have_error = for (zcu.transitive_failed_analysis.keys()) |failed_unit| { |
| 3262 | if (all_references == null) { | 3261 | const refs = try zcu.resolveReferences(); |
| 3263 | all_references = try zcu.resolveReferences(); | 3262 | if (refs.contains(failed_unit)) break true; |
| 3264 | } | ||
| 3265 | if (all_references.?.contains(failed_unit)) break true; | ||
| 3266 | } else false; | 3263 | } else false; |
| 3267 | if (should_have_error) { | 3264 | if (should_have_error) { |
| 3268 | @panic("referenced transitive analysis errors, but none actually emitted"); | 3265 | @panic("referenced transitive analysis errors, but none actually emitted"); |
| ... | @@ -3331,14 +3328,13 @@ pub const ErrorNoteHashContext = struct { | ... | @@ -3331,14 +3328,13 @@ pub const ErrorNoteHashContext = struct { |
| 3331 | }; | 3328 | }; |
| 3332 | 3329 | ||
| 3333 | pub fn addModuleErrorMsg( | 3330 | pub fn addModuleErrorMsg( |
| 3334 | mod: *Zcu, | 3331 | zcu: *Zcu, |
| 3335 | eb: *ErrorBundle.Wip, | 3332 | eb: *ErrorBundle.Wip, |
| 3336 | module_err_msg: Zcu.ErrorMsg, | 3333 | module_err_msg: Zcu.ErrorMsg, |
| 3337 | all_references: *?std.AutoHashMapUnmanaged(InternPool.AnalUnit, ?Zcu.ResolvedReference), | ||
| 3338 | ) !void { | 3334 | ) !void { |
| 3339 | const gpa = eb.gpa; | 3335 | const gpa = eb.gpa; |
| 3340 | const ip = &mod.intern_pool; | 3336 | const ip = &zcu.intern_pool; |
| 3341 | const err_src_loc = module_err_msg.src_loc.upgrade(mod); | 3337 | const err_src_loc = module_err_msg.src_loc.upgrade(zcu); |
| 3342 | const err_source = err_src_loc.file_scope.getSource(gpa) catch |err| { | 3338 | const err_source = err_src_loc.file_scope.getSource(gpa) catch |err| { |
| 3343 | const file_path = try err_src_loc.file_scope.fullPath(gpa); | 3339 | const file_path = try err_src_loc.file_scope.fullPath(gpa); |
| 3344 | defer gpa.free(file_path); | 3340 | defer gpa.free(file_path); |
| ... | @@ -3358,22 +3354,20 @@ pub fn addModuleErrorMsg( | ... | @@ -3358,22 +3354,20 @@ pub fn addModuleErrorMsg( |
| 3358 | defer ref_traces.deinit(gpa); | 3354 | defer ref_traces.deinit(gpa); |
| 3359 | 3355 | ||
| 3360 | if (module_err_msg.reference_trace_root.unwrap()) |rt_root| { | 3356 | if (module_err_msg.reference_trace_root.unwrap()) |rt_root| { |
| 3361 | if (all_references.* == null) { | 3357 | const all_references = try zcu.resolveReferences(); |
| 3362 | all_references.* = try mod.resolveReferences(); | ||
| 3363 | } | ||
| 3364 | 3358 | ||
| 3365 | var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty; | 3359 | var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty; |
| 3366 | defer seen.deinit(gpa); | 3360 | defer seen.deinit(gpa); |
| 3367 | 3361 | ||
| 3368 | const max_references = mod.comp.reference_trace orelse Sema.default_reference_trace_len; | 3362 | const max_references = zcu.comp.reference_trace orelse Sema.default_reference_trace_len; |
| 3369 | 3363 | ||
| 3370 | var referenced_by = rt_root; | 3364 | var referenced_by = rt_root; |
| 3371 | while (all_references.*.?.get(referenced_by)) |maybe_ref| { | 3365 | while (all_references.get(referenced_by)) |maybe_ref| { |
| 3372 | const ref = maybe_ref orelse break; | 3366 | const ref = maybe_ref orelse break; |
| 3373 | const gop = try seen.getOrPut(gpa, ref.referencer); | 3367 | const gop = try seen.getOrPut(gpa, ref.referencer); |
| 3374 | if (gop.found_existing) break; | 3368 | if (gop.found_existing) break; |
| 3375 | if (ref_traces.items.len < max_references) { | 3369 | if (ref_traces.items.len < max_references) { |
| 3376 | const src = ref.src.upgrade(mod); | 3370 | const src = ref.src.upgrade(zcu); |
| 3377 | const source = try src.file_scope.getSource(gpa); | 3371 | const source = try src.file_scope.getSource(gpa); |
| 3378 | const span = try src.span(gpa); | 3372 | const span = try src.span(gpa); |
| 3379 | const loc = std.zig.findLineColumn(source.bytes, span.main); | 3373 | const loc = std.zig.findLineColumn(source.bytes, span.main); |
| ... | @@ -3385,7 +3379,7 @@ pub fn addModuleErrorMsg( | ... | @@ -3385,7 +3379,7 @@ pub fn addModuleErrorMsg( |
| 3385 | .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), | 3379 | .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), |
| 3386 | .none => "comptime", | 3380 | .none => "comptime", |
| 3387 | }, | 3381 | }, |
| 3388 | .func => |f| ip.getNav(mod.funcInfo(f).owner_nav).name.toSlice(ip), | 3382 | .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), |
| 3389 | }; | 3383 | }; |
| 3390 | try ref_traces.append(gpa, .{ | 3384 | try ref_traces.append(gpa, .{ |
| 3391 | .decl_name = try eb.addString(name), | 3385 | .decl_name = try eb.addString(name), |
| ... | @@ -3435,7 +3429,7 @@ pub fn addModuleErrorMsg( | ... | @@ -3435,7 +3429,7 @@ pub fn addModuleErrorMsg( |
| 3435 | defer notes.deinit(gpa); | 3429 | defer notes.deinit(gpa); |
| 3436 | 3430 | ||
| 3437 | for (module_err_msg.notes) |module_note| { | 3431 | for (module_err_msg.notes) |module_note| { |
| 3438 | const note_src_loc = module_note.src_loc.upgrade(mod); | 3432 | const note_src_loc = module_note.src_loc.upgrade(zcu); |
| 3439 | const source = try note_src_loc.file_scope.getSource(gpa); | 3433 | const source = try note_src_loc.file_scope.getSource(gpa); |
| 3440 | const span = try note_src_loc.span(gpa); | 3434 | const span = try note_src_loc.span(gpa); |
| 3441 | const loc = std.zig.findLineColumn(source.bytes, span.main); | 3435 | const loc = std.zig.findLineColumn(source.bytes, span.main); |
| ... | @@ -3488,13 +3482,13 @@ pub fn performAllTheWork( | ... | @@ -3488,13 +3482,13 @@ pub fn performAllTheWork( |
| 3488 | comp: *Compilation, | 3482 | comp: *Compilation, |
| 3489 | main_progress_node: std.Progress.Node, | 3483 | main_progress_node: std.Progress.Node, |
| 3490 | ) JobError!void { | 3484 | ) JobError!void { |
| 3491 | defer if (comp.zcu) |mod| { | 3485 | defer if (comp.zcu) |zcu| { |
| 3492 | mod.sema_prog_node.end(); | 3486 | zcu.sema_prog_node.end(); |
| 3493 | mod.sema_prog_node = std.Progress.Node.none; | 3487 | zcu.sema_prog_node = std.Progress.Node.none; |
| 3494 | mod.codegen_prog_node.end(); | 3488 | zcu.codegen_prog_node.end(); |
| 3495 | mod.codegen_prog_node = std.Progress.Node.none; | 3489 | zcu.codegen_prog_node = std.Progress.Node.none; |
| 3496 | 3490 | ||
| 3497 | mod.generation += 1; | 3491 | zcu.generation += 1; |
| 3498 | }; | 3492 | }; |
| 3499 | try comp.performAllTheWorkInner(main_progress_node); | 3493 | try comp.performAllTheWorkInner(main_progress_node); |
| 3500 | if (!InternPool.single_threaded) if (comp.codegen_work.job_error) |job_error| return job_error; | 3494 | if (!InternPool.single_threaded) if (comp.codegen_work.job_error) |job_error| return job_error; |
src/InternPool.zig+12| ... | @@ -17,6 +17,13 @@ tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32), | ... | @@ -17,6 +17,13 @@ tid_shift_31: if (single_threaded) u0 else std.math.Log2Int(u32), |
| 17 | /// Cached shift amount to put a `tid` in the top bits of a 32-bit value. | 17 | /// Cached shift amount to put a `tid` in the top bits of a 32-bit value. |
| 18 | tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32), | 18 | tid_shift_32: if (single_threaded) u0 else std.math.Log2Int(u32), |
| 19 | 19 | ||
| 20 | /// Dependencies on whether an entire file gets past AstGen. | ||
| 21 | /// These are triggered by `@import`, so that: | ||
| 22 | /// * if a file initially fails AstGen, triggering a transitive failure, when a future update | ||
| 23 | /// causes it to succeed AstGen, the `@import` is re-analyzed, allowing analysis to proceed | ||
| 24 | /// * if a file initially succeds AstGen, but a future update causes the file to fail it, | ||
| 25 | /// the `@import` is re-analyzed, registering a transitive failure | ||
| 26 | file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), | ||
| 20 | /// Dependencies on the source code hash associated with a ZIR instruction. | 27 | /// Dependencies on the source code hash associated with a ZIR instruction. |
| 21 | /// * For a `declaration`, this is the entire declaration body. | 28 | /// * For a `declaration`, this is the entire declaration body. |
| 22 | /// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations). | 29 | /// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations). |
| ... | @@ -70,6 +77,7 @@ pub const empty: InternPool = .{ | ... | @@ -70,6 +77,7 @@ pub const empty: InternPool = .{ |
| 70 | .tid_shift_30 = if (single_threaded) 0 else 31, | 77 | .tid_shift_30 = if (single_threaded) 0 else 31, |
| 71 | .tid_shift_31 = if (single_threaded) 0 else 31, | 78 | .tid_shift_31 = if (single_threaded) 0 else 31, |
| 72 | .tid_shift_32 = if (single_threaded) 0 else 31, | 79 | .tid_shift_32 = if (single_threaded) 0 else 31, |
| 80 | .file_deps = .empty, | ||
| 73 | .src_hash_deps = .empty, | 81 | .src_hash_deps = .empty, |
| 74 | .nav_val_deps = .empty, | 82 | .nav_val_deps = .empty, |
| 75 | .interned_deps = .empty, | 83 | .interned_deps = .empty, |
| ... | @@ -656,6 +664,7 @@ pub const Nav = struct { | ... | @@ -656,6 +664,7 @@ pub const Nav = struct { |
| 656 | }; | 664 | }; |
| 657 | 665 | ||
| 658 | pub const Dependee = union(enum) { | 666 | pub const Dependee = union(enum) { |
| 667 | file: FileIndex, | ||
| 659 | src_hash: TrackedInst.Index, | 668 | src_hash: TrackedInst.Index, |
| 660 | nav_val: Nav.Index, | 669 | nav_val: Nav.Index, |
| 661 | interned: Index, | 670 | interned: Index, |
| ... | @@ -704,6 +713,7 @@ pub const DependencyIterator = struct { | ... | @@ -704,6 +713,7 @@ pub const DependencyIterator = struct { |
| 704 | 713 | ||
| 705 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { | 714 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { |
| 706 | const first_entry = switch (dependee) { | 715 | const first_entry = switch (dependee) { |
| 716 | .file => |x| ip.file_deps.get(x), | ||
| 707 | .src_hash => |x| ip.src_hash_deps.get(x), | 717 | .src_hash => |x| ip.src_hash_deps.get(x), |
| 708 | .nav_val => |x| ip.nav_val_deps.get(x), | 718 | .nav_val => |x| ip.nav_val_deps.get(x), |
| 709 | .interned => |x| ip.interned_deps.get(x), | 719 | .interned => |x| ip.interned_deps.get(x), |
| ... | @@ -740,6 +750,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend | ... | @@ -740,6 +750,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend |
| 740 | const new_index: DepEntry.Index = switch (dependee) { | 750 | const new_index: DepEntry.Index = switch (dependee) { |
| 741 | inline else => |dependee_payload, tag| new_index: { | 751 | inline else => |dependee_payload, tag| new_index: { |
| 742 | const gop = try switch (tag) { | 752 | const gop = try switch (tag) { |
| 753 | .file => ip.file_deps, | ||
| 743 | .src_hash => ip.src_hash_deps, | 754 | .src_hash => ip.src_hash_deps, |
| 744 | .nav_val => ip.nav_val_deps, | 755 | .nav_val => ip.nav_val_deps, |
| 745 | .interned => ip.interned_deps, | 756 | .interned => ip.interned_deps, |
| ... | @@ -6268,6 +6279,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { | ... | @@ -6268,6 +6279,7 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void { |
| 6268 | } | 6279 | } |
| 6269 | 6280 | ||
| 6270 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { | 6281 | pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 6282 | ip.file_deps.deinit(gpa); | ||
| 6271 | ip.src_hash_deps.deinit(gpa); | 6283 | ip.src_hash_deps.deinit(gpa); |
| 6272 | ip.nav_val_deps.deinit(gpa); | 6284 | ip.nav_val_deps.deinit(gpa); |
| 6273 | ip.interned_deps.deinit(gpa); | 6285 | ip.interned_deps.deinit(gpa); |
src/Package/Module.zig+1| ... | @@ -454,6 +454,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { | ... | @@ -454,6 +454,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 454 | .tree = undefined, | 454 | .tree = undefined, |
| 455 | .zir = undefined, | 455 | .zir = undefined, |
| 456 | .status = .never_loaded, | 456 | .status = .never_loaded, |
| 457 | .prev_status = .never_loaded, | ||
| 457 | .mod = new, | 458 | .mod = new, |
| 458 | }; | 459 | }; |
| 459 | break :b new; | 460 | break :b new; |
src/Sema.zig+3-8| ... | @@ -2559,10 +2559,9 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg | ... | @@ -2559,10 +2559,9 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg |
| 2559 | const zcu = sema.pt.zcu; | 2559 | const zcu = sema.pt.zcu; |
| 2560 | 2560 | ||
| 2561 | if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) { | 2561 | if (build_options.enable_debug_extensions and zcu.comp.debug_compile_errors) { |
| 2562 | var all_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?Zcu.ResolvedReference) = null; | ||
| 2563 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | 2562 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 2564 | wip_errors.init(gpa) catch @panic("out of memory"); | 2563 | wip_errors.init(gpa) catch @panic("out of memory"); |
| 2565 | Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, &all_references) catch @panic("out of memory"); | 2564 | Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*) catch @panic("out of memory"); |
| 2566 | std.debug.print("compile error during Sema:\n", .{}); | 2565 | std.debug.print("compile error during Sema:\n", .{}); |
| 2567 | var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); | 2566 | var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); |
| 2568 | error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); | 2567 | error_bundle.renderToStdErr(.{ .ttyconf = .no_color }); |
| ... | @@ -6025,9 +6024,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -6025,9 +6024,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr |
| 6025 | pt.astGenFile(result.file, path_digest) catch |err| | 6024 | pt.astGenFile(result.file, path_digest) catch |err| |
| 6026 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); | 6025 | return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); |
| 6027 | 6026 | ||
| 6028 | // TODO: register some kind of dependency on the file. | 6027 | try sema.declareDependency(.{ .file = result.file_index }); |
| 6029 | // That way, if this returns `error.AnalysisFail`, we have the dependency banked ready to | ||
| 6030 | // trigger re-analysis later. | ||
| 6031 | try pt.ensureFileAnalyzed(result.file_index); | 6028 | try pt.ensureFileAnalyzed(result.file_index); |
| 6032 | const ty = zcu.fileRootType(result.file_index); | 6029 | const ty = zcu.fileRootType(result.file_index); |
| 6033 | try sema.declareDependency(.{ .interned = ty }); | 6030 | try sema.declareDependency(.{ .interned = ty }); |
| ... | @@ -14348,9 +14345,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -14348,9 +14345,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14348 | return sema.fail(block, operand_src, "unable to open '{s}': {s}", .{ operand, @errorName(err) }); | 14345 | return sema.fail(block, operand_src, "unable to open '{s}': {s}", .{ operand, @errorName(err) }); |
| 14349 | }, | 14346 | }, |
| 14350 | }; | 14347 | }; |
| 14351 | // TODO: register some kind of dependency on the file. | 14348 | try sema.declareDependency(.{ .file = result.file_index }); |
| 14352 | // That way, if this returns `error.AnalysisFail`, we have the dependency banked ready to | ||
| 14353 | // trigger re-analysis later. | ||
| 14354 | try pt.ensureFileAnalyzed(result.file_index); | 14349 | try pt.ensureFileAnalyzed(result.file_index); |
| 14355 | const ty = zcu.fileRootType(result.file_index); | 14350 | const ty = zcu.fileRootType(result.file_index); |
| 14356 | try sema.declareDependency(.{ .interned = ty }); | 14351 | try sema.declareDependency(.{ .interned = ty }); |
src/Zcu.zig+40-8| ... | @@ -173,6 +173,10 @@ retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .empty, | ... | @@ -173,6 +173,10 @@ retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .empty, |
| 173 | /// These are the modules which we initially queue for analysis in `Compilation.update`. | 173 | /// These are the modules which we initially queue for analysis in `Compilation.update`. |
| 174 | /// `resolveReferences` will use these as the root of its reachability traversal. | 174 | /// `resolveReferences` will use these as the root of its reachability traversal. |
| 175 | analysis_roots: std.BoundedArray(*Package.Module, 3) = .{}, | 175 | analysis_roots: std.BoundedArray(*Package.Module, 3) = .{}, |
| 176 | /// This is the cached result of `Zcu.resolveReferences`. It is computed on-demand, and | ||
| 177 | /// reset to `null` when any semantic analysis occurs (since this invalidates the data). | ||
| 178 | /// Allocated into `gpa`. | ||
| 179 | resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = null, | ||
| 176 | 180 | ||
| 177 | stage1_flags: packed struct { | 181 | stage1_flags: packed struct { |
| 178 | have_winmain: bool = false, | 182 | have_winmain: bool = false, |
| ... | @@ -420,13 +424,8 @@ pub const Namespace = struct { | ... | @@ -420,13 +424,8 @@ pub const Namespace = struct { |
| 420 | }; | 424 | }; |
| 421 | 425 | ||
| 422 | pub const File = struct { | 426 | pub const File = struct { |
| 423 | status: enum { | 427 | status: Status, |
| 424 | never_loaded, | 428 | prev_status: Status, |
| 425 | retryable_failure, | ||
| 426 | parse_failure, | ||
| 427 | astgen_failure, | ||
| 428 | success_zir, | ||
| 429 | }, | ||
| 430 | source_loaded: bool, | 429 | source_loaded: bool, |
| 431 | tree_loaded: bool, | 430 | tree_loaded: bool, |
| 432 | zir_loaded: bool, | 431 | zir_loaded: bool, |
| ... | @@ -454,6 +453,14 @@ pub const File = struct { | ... | @@ -454,6 +453,14 @@ pub const File = struct { |
| 454 | /// successful, this field is unloaded. | 453 | /// successful, this field is unloaded. |
| 455 | prev_zir: ?*Zir = null, | 454 | prev_zir: ?*Zir = null, |
| 456 | 455 | ||
| 456 | pub const Status = enum { | ||
| 457 | never_loaded, | ||
| 458 | retryable_failure, | ||
| 459 | parse_failure, | ||
| 460 | astgen_failure, | ||
| 461 | success_zir, | ||
| 462 | }; | ||
| 463 | |||
| 457 | /// A single reference to a file. | 464 | /// A single reference to a file. |
| 458 | pub const Reference = union(enum) { | 465 | pub const Reference = union(enum) { |
| 459 | /// The file is imported directly (i.e. not as a package) with @import. | 466 | /// The file is imported directly (i.e. not as a package) with @import. |
| ... | @@ -2192,6 +2199,8 @@ pub fn deinit(zcu: *Zcu) void { | ... | @@ -2192,6 +2199,8 @@ pub fn deinit(zcu: *Zcu) void { |
| 2192 | zcu.all_type_references.deinit(gpa); | 2199 | zcu.all_type_references.deinit(gpa); |
| 2193 | zcu.free_type_references.deinit(gpa); | 2200 | zcu.free_type_references.deinit(gpa); |
| 2194 | 2201 | ||
| 2202 | if (zcu.resolved_references) |*r| r.deinit(gpa); | ||
| 2203 | |||
| 2195 | zcu.intern_pool.deinit(gpa); | 2204 | zcu.intern_pool.deinit(gpa); |
| 2196 | } | 2205 | } |
| 2197 | 2206 | ||
| ... | @@ -2760,6 +2769,8 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void { | ... | @@ -2760,6 +2769,8 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void { |
| 2760 | pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { | 2769 | pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { |
| 2761 | const gpa = zcu.gpa; | 2770 | const gpa = zcu.gpa; |
| 2762 | 2771 | ||
| 2772 | zcu.clearCachedResolvedReferences(); | ||
| 2773 | |||
| 2763 | unit_refs: { | 2774 | unit_refs: { |
| 2764 | const kv = zcu.reference_table.fetchSwapRemove(anal_unit) orelse break :unit_refs; | 2775 | const kv = zcu.reference_table.fetchSwapRemove(anal_unit) orelse break :unit_refs; |
| 2765 | var idx = kv.value; | 2776 | var idx = kv.value; |
| ... | @@ -2792,6 +2803,8 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { | ... | @@ -2792,6 +2803,8 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { |
| 2792 | pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void { | 2803 | pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void { |
| 2793 | const gpa = zcu.gpa; | 2804 | const gpa = zcu.gpa; |
| 2794 | 2805 | ||
| 2806 | zcu.clearCachedResolvedReferences(); | ||
| 2807 | |||
| 2795 | try zcu.reference_table.ensureUnusedCapacity(gpa, 1); | 2808 | try zcu.reference_table.ensureUnusedCapacity(gpa, 1); |
| 2796 | 2809 | ||
| 2797 | const ref_idx = zcu.free_references.popOrNull() orelse idx: { | 2810 | const ref_idx = zcu.free_references.popOrNull() orelse idx: { |
| ... | @@ -2815,6 +2828,8 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit | ... | @@ -2815,6 +2828,8 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit |
| 2815 | pub fn addTypeReference(zcu: *Zcu, src_unit: AnalUnit, referenced_type: InternPool.Index, ref_src: LazySrcLoc) Allocator.Error!void { | 2828 | pub fn addTypeReference(zcu: *Zcu, src_unit: AnalUnit, referenced_type: InternPool.Index, ref_src: LazySrcLoc) Allocator.Error!void { |
| 2816 | const gpa = zcu.gpa; | 2829 | const gpa = zcu.gpa; |
| 2817 | 2830 | ||
| 2831 | zcu.clearCachedResolvedReferences(); | ||
| 2832 | |||
| 2818 | try zcu.type_reference_table.ensureUnusedCapacity(gpa, 1); | 2833 | try zcu.type_reference_table.ensureUnusedCapacity(gpa, 1); |
| 2819 | 2834 | ||
| 2820 | const ref_idx = zcu.free_type_references.popOrNull() orelse idx: { | 2835 | const ref_idx = zcu.free_type_references.popOrNull() orelse idx: { |
| ... | @@ -2835,6 +2850,11 @@ pub fn addTypeReference(zcu: *Zcu, src_unit: AnalUnit, referenced_type: InternPo | ... | @@ -2835,6 +2850,11 @@ pub fn addTypeReference(zcu: *Zcu, src_unit: AnalUnit, referenced_type: InternPo |
| 2835 | gop.value_ptr.* = @intCast(ref_idx); | 2850 | gop.value_ptr.* = @intCast(ref_idx); |
| 2836 | } | 2851 | } |
| 2837 | 2852 | ||
| 2853 | fn clearCachedResolvedReferences(zcu: *Zcu) void { | ||
| 2854 | if (zcu.resolved_references) |*r| r.deinit(zcu.gpa); | ||
| 2855 | zcu.resolved_references = null; | ||
| 2856 | } | ||
| 2857 | |||
| 2838 | pub fn errorSetBits(zcu: *const Zcu) u16 { | 2858 | pub fn errorSetBits(zcu: *const Zcu) u16 { |
| 2839 | if (zcu.error_limit == 0) return 0; | 2859 | if (zcu.error_limit == 0) return 0; |
| 2840 | return @as(u16, std.math.log2_int(ErrorInt, zcu.error_limit)) + 1; | 2860 | return @as(u16, std.math.log2_int(ErrorInt, zcu.error_limit)) + 1; |
| ... | @@ -3138,7 +3158,15 @@ pub const ResolvedReference = struct { | ... | @@ -3138,7 +3158,15 @@ pub const ResolvedReference = struct { |
| 3138 | /// Returns a mapping from an `AnalUnit` to where it is referenced. | 3158 | /// Returns a mapping from an `AnalUnit` to where it is referenced. |
| 3139 | /// If the value is `null`, the `AnalUnit` is a root of analysis. | 3159 | /// If the value is `null`, the `AnalUnit` is a root of analysis. |
| 3140 | /// If an `AnalUnit` is not in the returned map, it is unreferenced. | 3160 | /// If an `AnalUnit` is not in the returned map, it is unreferenced. |
| 3141 | pub fn resolveReferences(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | 3161 | /// The returned hashmap is owned by the `Zcu`, so should not be freed by the caller. |
| 3162 | /// This hashmap is cached, so repeated calls to this function are cheap. | ||
| 3163 | pub fn resolveReferences(zcu: *Zcu) !*const std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | ||
| 3164 | if (zcu.resolved_references == null) { | ||
| 3165 | zcu.resolved_references = try zcu.resolveReferencesInner(); | ||
| 3166 | } | ||
| 3167 | return &zcu.resolved_references.?; | ||
| 3168 | } | ||
| 3169 | fn resolveReferencesInner(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) { | ||
| 3142 | const gpa = zcu.gpa; | 3170 | const gpa = zcu.gpa; |
| 3143 | const comp = zcu.comp; | 3171 | const comp = zcu.comp; |
| 3144 | const ip = &zcu.intern_pool; | 3172 | const ip = &zcu.intern_pool; |
| ... | @@ -3449,6 +3477,10 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com | ... | @@ -3449,6 +3477,10 @@ fn formatDependee(data: struct { dependee: InternPool.Dependee, zcu: *Zcu }, com |
| 3449 | const zcu = data.zcu; | 3477 | const zcu = data.zcu; |
| 3450 | const ip = &zcu.intern_pool; | 3478 | const ip = &zcu.intern_pool; |
| 3451 | switch (data.dependee) { | 3479 | switch (data.dependee) { |
| 3480 | .file => |file| { | ||
| 3481 | const file_path = zcu.fileByIndex(file).sub_file_path; | ||
| 3482 | return writer.print("file('{s}')", .{file_path}); | ||
| 3483 | }, | ||
| 3452 | .src_hash => |ti| { | 3484 | .src_hash => |ti| { |
| 3453 | const info = ti.resolveFull(ip) orelse { | 3485 | const info = ti.resolveFull(ip) orelse { |
| 3454 | return writer.writeAll("inst(<lost>)"); | 3486 | return writer.writeAll("inst(<lost>)"); |
src/Zcu/PerThread.zig+26-10| ... | @@ -179,10 +179,10 @@ pub fn astGenFile( | ... | @@ -179,10 +179,10 @@ pub fn astGenFile( |
| 179 | .inode = header.stat_inode, | 179 | .inode = header.stat_inode, |
| 180 | .mtime = header.stat_mtime, | 180 | .mtime = header.stat_mtime, |
| 181 | }; | 181 | }; |
| 182 | file.prev_status = file.status; | ||
| 182 | file.status = .success_zir; | 183 | file.status = .success_zir; |
| 183 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); | 184 | log.debug("AstGen cached success: {s}", .{file.sub_file_path}); |
| 184 | 185 | ||
| 185 | // TODO don't report compile errors until Sema @importFile | ||
| 186 | if (file.zir.hasCompileErrors()) { | 186 | if (file.zir.hasCompileErrors()) { |
| 187 | { | 187 | { |
| 188 | comp.mutex.lock(); | 188 | comp.mutex.lock(); |
| ... | @@ -258,6 +258,7 @@ pub fn astGenFile( | ... | @@ -258,6 +258,7 @@ pub fn astGenFile( |
| 258 | // Any potential AST errors are converted to ZIR errors here. | 258 | // Any potential AST errors are converted to ZIR errors here. |
| 259 | file.zir = try AstGen.generate(gpa, file.tree); | 259 | file.zir = try AstGen.generate(gpa, file.tree); |
| 260 | file.zir_loaded = true; | 260 | file.zir_loaded = true; |
| 261 | file.prev_status = file.status; | ||
| 261 | file.status = .success_zir; | 262 | file.status = .success_zir; |
| 262 | log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); | 263 | log.debug("AstGen fresh success: {s}", .{file.sub_file_path}); |
| 263 | 264 | ||
| ... | @@ -350,6 +351,9 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { | ... | @@ -350,6 +351,9 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { |
| 350 | defer cleanupUpdatedFiles(gpa, &updated_files); | 351 | defer cleanupUpdatedFiles(gpa, &updated_files); |
| 351 | for (zcu.import_table.values()) |file_index| { | 352 | for (zcu.import_table.values()) |file_index| { |
| 352 | const file = zcu.fileByIndex(file_index); | 353 | const file = zcu.fileByIndex(file_index); |
| 354 | if (file.prev_status != file.status and file.prev_status != .never_loaded) { | ||
| 355 | try zcu.markDependeeOutdated(.not_marked_po, .{ .file = file_index }); | ||
| 356 | } | ||
| 353 | const old_zir = file.prev_zir orelse continue; | 357 | const old_zir = file.prev_zir orelse continue; |
| 354 | const new_zir = file.zir; | 358 | const new_zir = file.zir; |
| 355 | const gop = try updated_files.getOrPut(gpa, file_index); | 359 | const gop = try updated_files.getOrPut(gpa, file_index); |
| ... | @@ -551,11 +555,13 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu | ... | @@ -551,11 +555,13 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu |
| 551 | const cau_outdated = zcu.outdated.swapRemove(anal_unit) or | 555 | const cau_outdated = zcu.outdated.swapRemove(anal_unit) or |
| 552 | zcu.potentially_outdated.swapRemove(anal_unit); | 556 | zcu.potentially_outdated.swapRemove(anal_unit); |
| 553 | 557 | ||
| 558 | const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); | ||
| 559 | |||
| 554 | if (cau_outdated) { | 560 | if (cau_outdated) { |
| 555 | _ = zcu.outdated_ready.swapRemove(anal_unit); | 561 | _ = zcu.outdated_ready.swapRemove(anal_unit); |
| 556 | } else { | 562 | } else { |
| 557 | // We can trust the current information about this `Cau`. | 563 | // We can trust the current information about this `Cau`. |
| 558 | if (zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit)) { | 564 | if (prev_failed) { |
| 559 | return error.AnalysisFail; | 565 | return error.AnalysisFail; |
| 560 | } | 566 | } |
| 561 | // If it wasn't failed and wasn't marked outdated, then either... | 567 | // If it wasn't failed and wasn't marked outdated, then either... |
| ... | @@ -578,9 +584,13 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu | ... | @@ -578,9 +584,13 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu |
| 578 | // Since it does not, this must be a transitive failure. | 584 | // Since it does not, this must be a transitive failure. |
| 579 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | 585 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); |
| 580 | } | 586 | } |
| 581 | // We treat errors as up-to-date, since those uses would just trigger a transitive error. | 587 | // We consider this `Cau` to be outdated if: |
| 582 | // The exception is types, since type declarations may require re-analysis if the type, e.g. its captures, changed. | 588 | // * Previous analysis succeeded; in this case, we need to re-analyze dependants to ensure |
| 583 | const outdated = cau.owner.unwrap() == .type; | 589 | // they hit a transitive error here, rather than reporting a different error later (which |
| 590 | // may now be invalid). | ||
| 591 | // * The `Cau` is a type; in this case, the declaration site may require re-analysis to | ||
| 592 | // construct a valid type. | ||
| 593 | const outdated = !prev_failed or cau.owner.unwrap() == .type; | ||
| 584 | break :res .{ .{ | 594 | break :res .{ .{ |
| 585 | .invalidate_decl_val = outdated, | 595 | .invalidate_decl_val = outdated, |
| 586 | .invalidate_decl_ref = outdated, | 596 | .invalidate_decl_ref = outdated, |
| ... | @@ -597,10 +607,9 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu | ... | @@ -597,10 +607,9 @@ pub fn ensureCauAnalyzed(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) Zcu |
| 597 | ); | 607 | ); |
| 598 | zcu.retryable_failures.appendAssumeCapacity(anal_unit); | 608 | zcu.retryable_failures.appendAssumeCapacity(anal_unit); |
| 599 | zcu.failed_analysis.putAssumeCapacityNoClobber(anal_unit, msg); | 609 | zcu.failed_analysis.putAssumeCapacityNoClobber(anal_unit, msg); |
| 600 | // We treat errors as up-to-date, since those uses would just trigger a transitive error | ||
| 601 | break :res .{ .{ | 610 | break :res .{ .{ |
| 602 | .invalidate_decl_val = false, | 611 | .invalidate_decl_val = true, |
| 603 | .invalidate_decl_ref = false, | 612 | .invalidate_decl_ref = true, |
| 604 | }, true }; | 613 | }, true }; |
| 605 | }, | 614 | }, |
| 606 | }; | 615 | }; |
| ... | @@ -707,11 +716,13 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter | ... | @@ -707,11 +716,13 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 707 | const func_outdated = zcu.outdated.swapRemove(anal_unit) or | 716 | const func_outdated = zcu.outdated.swapRemove(anal_unit) or |
| 708 | zcu.potentially_outdated.swapRemove(anal_unit); | 717 | zcu.potentially_outdated.swapRemove(anal_unit); |
| 709 | 718 | ||
| 719 | const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); | ||
| 720 | |||
| 710 | if (func_outdated) { | 721 | if (func_outdated) { |
| 711 | _ = zcu.outdated_ready.swapRemove(anal_unit); | 722 | _ = zcu.outdated_ready.swapRemove(anal_unit); |
| 712 | } else { | 723 | } else { |
| 713 | // We can trust the current information about this function. | 724 | // We can trust the current information about this function. |
| 714 | if (zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit)) { | 725 | if (prev_failed) { |
| 715 | return error.AnalysisFail; | 726 | return error.AnalysisFail; |
| 716 | } | 727 | } |
| 717 | switch (func.analysisUnordered(ip).state) { | 728 | switch (func.analysisUnordered(ip).state) { |
| ... | @@ -730,7 +741,10 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter | ... | @@ -730,7 +741,10 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter |
| 730 | // Since it does not, this must be a transitive failure. | 741 | // Since it does not, this must be a transitive failure. |
| 731 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | 742 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); |
| 732 | } | 743 | } |
| 733 | break :res .{ false, true }; // we treat errors as up-to-date IES, since those uses would just trigger a transitive error | 744 | // We consider the IES to be outdated if the function previously succeeded analysis; in this case, |
| 745 | // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting | ||
| 746 | // a different error later (which may now be invalid). | ||
| 747 | break :res .{ !prev_failed, true }; | ||
| 734 | }, | 748 | }, |
| 735 | error.OutOfMemory => return error.OutOfMemory, // TODO: graceful handling like `ensureCauAnalyzed` | 749 | error.OutOfMemory => return error.OutOfMemory, // TODO: graceful handling like `ensureCauAnalyzed` |
| 736 | }; | 750 | }; |
| ... | @@ -1445,6 +1459,7 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { | ... | @@ -1445,6 +1459,7 @@ pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult { |
| 1445 | .tree = undefined, | 1459 | .tree = undefined, |
| 1446 | .zir = undefined, | 1460 | .zir = undefined, |
| 1447 | .status = .never_loaded, | 1461 | .status = .never_loaded, |
| 1462 | .prev_status = .never_loaded, | ||
| 1448 | .mod = mod, | 1463 | .mod = mod, |
| 1449 | }; | 1464 | }; |
| 1450 | 1465 | ||
| ... | @@ -1555,6 +1570,7 @@ pub fn importFile( | ... | @@ -1555,6 +1570,7 @@ pub fn importFile( |
| 1555 | .tree = undefined, | 1570 | .tree = undefined, |
| 1556 | .zir = undefined, | 1571 | .zir = undefined, |
| 1557 | .status = .never_loaded, | 1572 | .status = .never_loaded, |
| 1573 | .prev_status = .never_loaded, | ||
| 1558 | .mod = mod, | 1574 | .mod = mod, |
| 1559 | }; | 1575 | }; |
| 1560 | 1576 |
src/main.zig+3| ... | @@ -6118,6 +6118,7 @@ fn cmdAstCheck( | ... | @@ -6118,6 +6118,7 @@ fn cmdAstCheck( |
| 6118 | 6118 | ||
| 6119 | var file: Zcu.File = .{ | 6119 | var file: Zcu.File = .{ |
| 6120 | .status = .never_loaded, | 6120 | .status = .never_loaded, |
| 6121 | .prev_status = .never_loaded, | ||
| 6121 | .source_loaded = false, | 6122 | .source_loaded = false, |
| 6122 | .tree_loaded = false, | 6123 | .tree_loaded = false, |
| 6123 | .zir_loaded = false, | 6124 | .zir_loaded = false, |
| ... | @@ -6441,6 +6442,7 @@ fn cmdDumpZir( | ... | @@ -6441,6 +6442,7 @@ fn cmdDumpZir( |
| 6441 | 6442 | ||
| 6442 | var file: Zcu.File = .{ | 6443 | var file: Zcu.File = .{ |
| 6443 | .status = .never_loaded, | 6444 | .status = .never_loaded, |
| 6445 | .prev_status = .never_loaded, | ||
| 6444 | .source_loaded = false, | 6446 | .source_loaded = false, |
| 6445 | .tree_loaded = false, | 6447 | .tree_loaded = false, |
| 6446 | .zir_loaded = true, | 6448 | .zir_loaded = true, |
| ... | @@ -6508,6 +6510,7 @@ fn cmdChangelist( | ... | @@ -6508,6 +6510,7 @@ fn cmdChangelist( |
| 6508 | 6510 | ||
| 6509 | var file: Zcu.File = .{ | 6511 | var file: Zcu.File = .{ |
| 6510 | .status = .never_loaded, | 6512 | .status = .never_loaded, |
| 6513 | .prev_status = .never_loaded, | ||
| 6511 | .source_loaded = false, | 6514 | .source_loaded = false, |
| 6512 | .tree_loaded = false, | 6515 | .tree_loaded = false, |
| 6513 | .zir_loaded = false, | 6516 | .zir_loaded = false, |
test/incremental/add_decl+2-1| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | #target=x86_64-linux-selfhosted | 1 | // Disabled on self-hosted due to linker crash |
| 2 | // #target=x86_64-linux-selfhosted | ||
| 2 | #target=x86_64-linux-cbe | 3 | #target=x86_64-linux-cbe |
| 3 | #target=x86_64-windows-cbe | 4 | #target=x86_64-windows-cbe |
| 4 | #update=initial version | 5 | #update=initial version |
test/incremental/fix_astgen_failure created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | #target=x86_64-linux-selfhosted | ||
| 2 | #target=x86_64-linux-cbe | ||
| 3 | #target=x86_64-windows-cbe | ||
| 4 | #update=initial version with error | ||
| 5 | #file=main.zig | ||
| 6 | pub fn main() !void { | ||
| 7 | try @import("foo.zig").hello(); | ||
| 8 | } | ||
| 9 | #file=foo.zig | ||
| 10 | pub fn hello() !void { | ||
| 11 | try std.io.getStdOut().writeAll("Hello, World!\n"); | ||
| 12 | } | ||
| 13 | #expect_error=ignored | ||
| 14 | #update=fix the error | ||
| 15 | #file=foo.zig | ||
| 16 | const std = @import("std"); | ||
| 17 | pub fn hello() !void { | ||
| 18 | try std.io.getStdOut().writeAll("Hello, World!\n"); | ||
| 19 | } | ||
| 20 | #expect_stdout="Hello, World!\n" | ||
| 21 | #update=add new error | ||
| 22 | #file=foo.zig | ||
| 23 | const std = @import("std"); | ||
| 24 | pub fn hello() !void { | ||
| 25 | try std.io.getStdOut().writeAll(hello_str); | ||
| 26 | } | ||
| 27 | #expect_error=ignored | ||
| 28 | #update=fix the new error | ||
| 29 | #file=foo.zig | ||
| 30 | const std = @import("std"); | ||
| 31 | const hello_str = "Hello, World! Again!\n"; | ||
| 32 | pub fn hello() !void { | ||
| 33 | try std.io.getStdOut().writeAll(hello_str); | ||
| 34 | } | ||
| 35 | #expect_stdout="Hello, World! Again!\n" | ||
test/incremental/remove_invalid_union_backing_enum created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | #target=x86_64-linux-selfhosted | ||
| 2 | #target=x86_64-linux-cbe | ||
| 3 | #target=x86_64-windows-cbe | ||
| 4 | #update=initial version | ||
| 5 | #file=main.zig | ||
| 6 | const E = enum { a, b, c }; | ||
| 7 | const U = union(E) { | ||
| 8 | a: i32, | ||
| 9 | b: f64, | ||
| 10 | c: f64, | ||
| 11 | d: f64, | ||
| 12 | }; | ||
| 13 | pub fn main() void { | ||
| 14 | const u: U = .{ .a = 123 }; | ||
| 15 | _ = u; | ||
| 16 | } | ||
| 17 | #expect_error=ignored | ||
| 18 | #update=remove invalid backing enum | ||
| 19 | #file=main.zig | ||
| 20 | const U = union { | ||
| 21 | a: i32, | ||
| 22 | b: f64, | ||
| 23 | c: f64, | ||
| 24 | d: f64, | ||
| 25 | }; | ||
| 26 | pub fn main() void { | ||
| 27 | const u: U = .{ .a = 123 }; | ||
| 28 | _ = u; | ||
| 29 | } | ||
| 30 | #expect_stdout="" | ||