| author | |
| committer | |
| log | f0d5e0df4d95c06287e0fe3fe48b69daf5306c8f |
| tree | b4f177522ebba9e27ce9745255f321d194de6e82 |
| parent | ba78d79228e6b62a3b5fe9d1fafac18da252e4d6 |
| signature |
Previously, logic in `Compilation.getAllErrorsAlloc` was corrupting the
`failed_analysis` hashmap. This meant that on updates after the initial
update, attempts to remove entries from this map (because the `AnalUnit`
in question is being re-analyzed) silently failed. This resulted in
compile errors from earlier updates wrongly getting "stuck", i.e. never
being removed.
This commit also adds a few log calls which helped me to find this bug.3 files changed, 83 insertions(+), 15 deletions(-)
src/Compilation.zig+25-9| ... | ... | @@ -3102,9 +3102,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3102 | 3102 | for (zcu.failed_embed_files.values()) |error_msg| { |
| 3103 | 3103 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3104 | 3104 | } |
| 3105 | { | |
| 3105 | var sorted_failed_analysis: std.AutoArrayHashMapUnmanaged(InternPool.AnalUnit, *Zcu.ErrorMsg).DataList.Slice = s: { | |
| 3106 | 3106 | const SortOrder = struct { |
| 3107 | 3107 | zcu: *Zcu, |
| 3108 | errors: []const *Zcu.ErrorMsg, | |
| 3108 | 3109 | err: *?Error, |
| 3109 | 3110 | |
| 3110 | 3111 | const Error = @typeInfo( |
| ... | ... | @@ -3113,12 +3114,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3113 | 3114 | |
| 3114 | 3115 | pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { |
| 3115 | 3116 | if (ctx.err.*) |_| return lhs_index < rhs_index; |
| 3116 | const errors = ctx.zcu.failed_analysis.values(); | |
| 3117 | const lhs_src_loc = errors[lhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { | |
| 3117 | const lhs_src_loc = ctx.errors[lhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { | |
| 3118 | 3118 | // LHS source location lost, so should never be referenced. Just sort it to the end. |
| 3119 | 3119 | return false; |
| 3120 | 3120 | }; |
| 3121 | const rhs_src_loc = errors[rhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { | |
| 3121 | const rhs_src_loc = ctx.errors[rhs_index].src_loc.upgradeOrLost(ctx.zcu) orelse { | |
| 3122 | 3122 | // RHS source location lost, so should never be referenced. Just sort it to the end. |
| 3123 | 3123 | return true; |
| 3124 | 3124 | }; |
| ... | ... | @@ -3135,13 +3135,24 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3135 | 3135 | }).main; |
| 3136 | 3136 | } |
| 3137 | 3137 | }; |
| 3138 | ||
| 3139 | // We can't directly sort `zcu.failed_analysis.entries`, because that would leave the map | |
| 3140 | // in an invalid state, and we need it intact for future incremental updates. The amount | |
| 3141 | // of data here is only as large as the number of analysis errors, so just dupe it all. | |
| 3142 | var entries = try zcu.failed_analysis.entries.clone(gpa); | |
| 3143 | errdefer entries.deinit(gpa); | |
| 3144 | ||
| 3138 | 3145 | var err: ?SortOrder.Error = null; |
| 3139 | // This leaves `zcu.failed_analysis` an invalid state, but we do not | |
| 3140 | // need lookups anymore anyway. | |
| 3141 | zcu.failed_analysis.entries.sort(SortOrder{ .zcu = zcu, .err = &err }); | |
| 3146 | entries.sort(SortOrder{ | |
| 3147 | .zcu = zcu, | |
| 3148 | .errors = entries.items(.value), | |
| 3149 | .err = &err, | |
| 3150 | }); | |
| 3142 | 3151 | if (err) |e| return e; |
| 3143 | } | |
| 3144 | for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| { | |
| 3152 | break :s entries.slice(); | |
| 3153 | }; | |
| 3154 | defer sorted_failed_analysis.deinit(gpa); | |
| 3155 | for (sorted_failed_analysis.items(.key), sorted_failed_analysis.items(.value)) |anal_unit, error_msg| { | |
| 3145 | 3156 | if (comp.incremental) { |
| 3146 | 3157 | const refs = try zcu.resolveReferences(); |
| 3147 | 3158 | if (!refs.contains(anal_unit)) continue; |
| ... | ... | @@ -3158,6 +3169,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle { |
| 3158 | 3169 | // We'll try again once parsing succeeds. |
| 3159 | 3170 | if (!zcu.fileByIndex(file_index).okToReportErrors()) continue; |
| 3160 | 3171 | |
| 3172 | std.log.scoped(.zcu).debug("analysis error '{s}' reported from unit '{}'", .{ | |
| 3173 | error_msg.msg, | |
| 3174 | zcu.fmtAnalUnit(anal_unit), | |
| 3175 | }); | |
| 3176 | ||
| 3161 | 3177 | try addModuleErrorMsg(zcu, &bundle, error_msg.*); |
| 3162 | 3178 | if (zcu.cimport_errors.get(anal_unit)) |errors| { |
| 3163 | 3179 | for (errors.getMessages()) |err_msg_index| { |
src/Zcu.zig+6-6| ... | ... | @@ -3590,17 +3590,17 @@ fn formatAnalUnit(data: struct { unit: AnalUnit, zcu: *Zcu }, comptime fmt: []co |
| 3590 | 3590 | const cu = ip.getComptimeUnit(cu_id); |
| 3591 | 3591 | if (cu.zir_index.resolveFull(ip)) |resolved| { |
| 3592 | 3592 | const file_path = zcu.fileByIndex(resolved.file).sub_file_path; |
| 3593 | return writer.print("comptime(inst=('{s}', %{}))", .{ file_path, @intFromEnum(resolved.inst) }); | |
| 3593 | return writer.print("comptime(inst=('{s}', %{}) [{}])", .{ file_path, @intFromEnum(resolved.inst), @intFromEnum(cu_id) }); | |
| 3594 | 3594 | } else { |
| 3595 | return writer.writeAll("comptime(inst=<list>)"); | |
| 3595 | return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)}); | |
| 3596 | 3596 | } |
| 3597 | 3597 | }, |
| 3598 | .nav_val => |nav| return writer.print("nav_val('{}')", .{ip.getNav(nav).fqn.fmt(ip)}), | |
| 3599 | .nav_ty => |nav| return writer.print("nav_ty('{}')", .{ip.getNav(nav).fqn.fmt(ip)}), | |
| 3600 | .type => |ty| return writer.print("ty('{}')", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}), | |
| 3598 | .nav_val => |nav| return writer.print("nav_val('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), | |
| 3599 | .nav_ty => |nav| return writer.print("nav_ty('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), | |
| 3600 | .type => |ty| return writer.print("ty('{}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), | |
| 3601 | 3601 | .func => |func| { |
| 3602 | 3602 | const nav = zcu.funcInfo(func).owner_nav; |
| 3603 | return writer.print("func('{}')", .{ip.getNav(nav).fqn.fmt(ip)}); | |
| 3603 | return writer.print("func('{}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); | |
| 3604 | 3604 | }, |
| 3605 | 3605 | } |
| 3606 | 3606 | } |
test/incremental/fix_many_errors created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 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 | pub fn main() !void {} | |
| 7 | comptime { @compileError("c0"); } | |
| 8 | comptime { @compileError("c1"); } | |
| 9 | comptime { @compileError("c2"); } | |
| 10 | comptime { @compileError("c3"); } | |
| 11 | comptime { @compileError("c4"); } | |
| 12 | comptime { @compileError("c5"); } | |
| 13 | comptime { @compileError("c6"); } | |
| 14 | comptime { @compileError("c7"); } | |
| 15 | comptime { @compileError("c8"); } | |
| 16 | comptime { @compileError("c9"); } | |
| 17 | export fn f0() void { @compileError("f0"); } | |
| 18 | export fn f1() void { @compileError("f1"); } | |
| 19 | export fn f2() void { @compileError("f2"); } | |
| 20 | export fn f3() void { @compileError("f3"); } | |
| 21 | export fn f4() void { @compileError("f4"); } | |
| 22 | export fn f5() void { @compileError("f5"); } | |
| 23 | export fn f6() void { @compileError("f6"); } | |
| 24 | export fn f7() void { @compileError("f7"); } | |
| 25 | export fn f8() void { @compileError("f8"); } | |
| 26 | export fn f9() void { @compileError("f9"); } | |
| 27 | #expect_error=ignored | |
| 28 | #update=fix all the errors | |
| 29 | #file=main.zig | |
| 30 | pub fn main() !void {} | |
| 31 | comptime {} | |
| 32 | comptime {} | |
| 33 | comptime {} | |
| 34 | comptime {} | |
| 35 | comptime {} | |
| 36 | comptime {} | |
| 37 | comptime {} | |
| 38 | comptime {} | |
| 39 | comptime {} | |
| 40 | comptime {} | |
| 41 | export fn f0() void {} | |
| 42 | export fn f1() void {} | |
| 43 | export fn f2() void {} | |
| 44 | export fn f3() void {} | |
| 45 | export fn f4() void {} | |
| 46 | export fn f5() void {} | |
| 47 | export fn f6() void {} | |
| 48 | export fn f7() void {} | |
| 49 | export fn f8() void {} | |
| 50 | export fn f9() void {} | |
| 51 | const std = @import("std"); | |
| 52 | #expect_stdout="" |