diff --git a/src/Compilation.zig b/src/Compilation.zig index c60f6cef7f..efb1183cdb 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -4054,21 +4054,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { const SortOrder = struct { zcu: *Zcu, errors: []const *Zcu.ErrorMsg, - read_err: *?ReadError, - const ReadError = struct { - file: *Zcu.File, - err: Zcu.File.GetSourceError, - }; pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { - if (ctx.read_err.* != null) return lhs_index < rhs_index; - var bad_file: *Zcu.File = undefined; - return ctx.errors[lhs_index].src_loc.lessThan(ctx.errors[rhs_index].src_loc, ctx.zcu, &bad_file) catch |err| { - ctx.read_err.* = .{ - .file = bad_file, - .err = err, - }; - return lhs_index < rhs_index; - }; + return Zcu.ErrorMsg.order( + ctx.errors[lhs_index], + ctx.errors[rhs_index], + ctx.zcu, + ).compare(.lt); } }; @@ -4078,16 +4069,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { var entries = try zcu.failed_analysis.entries.clone(gpa); errdefer entries.deinit(gpa); - var read_err: ?SortOrder.ReadError = null; entries.sort(SortOrder{ .zcu = zcu, .errors = entries.items(.value), - .read_err = &read_err, }); - if (read_err) |e| { - try unableToLoadZcuFile(zcu, &bundle, e.file, e.err); - break :zcu_errors; - } break :s entries.slice(); }; defer sorted_failed_analysis.deinit(gpa); @@ -4208,33 +4193,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { // Okay, there *are* referenced compile logs. Sort them into a consistent order. - { - const SortContext = struct { - zcu: *Zcu, - read_err: *?ReadError, - const ReadError = struct { - file: *Zcu.File, - err: Zcu.File.GetSourceError, - }; - fn lessThan(ctx: @This(), lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool { - if (ctx.read_err.* != null) return false; - var bad_file: *Zcu.File = undefined; - return lhs.src_loc.lessThan(rhs.src_loc, ctx.zcu, &bad_file) catch |err| { - ctx.read_err.* = .{ - .file = bad_file, - .err = err, - }; - return false; - }; - } - }; - var read_err: ?SortContext.ReadError = null; - std.mem.sort(Zcu.ErrorMsg, messages.items, @as(SortContext, .{ .read_err = &read_err, .zcu = zcu }), SortContext.lessThan); - if (read_err) |e| { - try unableToLoadZcuFile(zcu, &bundle, e.file, e.err); - break :compile_log_text ""; + std.mem.sort(Zcu.ErrorMsg, messages.items, zcu, struct { + fn lessThan(zcu_inner: *Zcu, lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool { + return Zcu.ErrorMsg.order(&lhs, &rhs, zcu_inner).compare(.lt); } - } + }.lessThan); var log_text: std.ArrayList(u8) = .empty; defer log_text.deinit(gpa); diff --git a/src/Zcu.zig b/src/Zcu.zig index c623c1ec49..eb4b8bdb05 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -1250,6 +1250,15 @@ pub const ErrorMsg = struct { notes: []ErrorMsg = &.{}, reference_trace_root: AnalUnit.Optional = .none, + pub fn order(lhs: *const ErrorMsg, rhs: *const ErrorMsg, zcu: *Zcu) std.math.Order { + return lhs.src_loc.order(rhs.src_loc, zcu).differ() orelse + std.mem.order(u8, lhs.msg, rhs.msg).differ() orelse + std.math.order(lhs.notes.len, rhs.notes.len).differ() orelse + for (lhs.notes, rhs.notes) |*lhs_note, *rhs_note| { + if (order(lhs_note, rhs_note, zcu).differ()) |o| break o; + } else .eq; + } + pub fn create( gpa: Allocator, src_loc: LazySrcLoc, @@ -2724,36 +2733,34 @@ pub const LazySrcLoc = struct { }; } - /// Used to sort error messages, so that they're printed in a consistent order. - /// If an error is returned, a file could not be read in order to resolve a source location. - /// In that case, `bad_file_out` is populated, and sorting is impossible. - pub fn lessThan(lhs_lazy: LazySrcLoc, rhs_lazy: LazySrcLoc, zcu: *Zcu, bad_file_out: **Zcu.File) File.GetSourceError!bool { - const lhs_src = lhs_lazy.upgradeOrLost(zcu) orelse { + pub fn order(lhs: LazySrcLoc, rhs: LazySrcLoc, zcu: *Zcu) std.math.Order { + const lhs_resolved = lhs.upgradeOrLost(zcu) orelse { // LHS source location lost, so should never be referenced. Just sort it to the end. - return false; + return .gt; }; - const rhs_src = rhs_lazy.upgradeOrLost(zcu) orelse { + const rhs_resolved = rhs.upgradeOrLost(zcu) orelse { // RHS source location lost, so should never be referenced. Just sort it to the end. - return true; + return .lt; }; - if (lhs_src.file_scope != rhs_src.file_scope) { - const lhs_path = lhs_src.file_scope.path; - const rhs_path = rhs_src.file_scope.path; - if (lhs_path.root != rhs_path.root) { - return @intFromEnum(lhs_path.root) < @intFromEnum(rhs_path.root); - } - return std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).compare(.lt); + if (lhs_resolved.file_scope != rhs_resolved.file_scope) { + const lhs_path = lhs_resolved.file_scope.path; + const rhs_path = rhs_resolved.file_scope.path; + return std.math.order(@intFromEnum(lhs_path.root), @intFromEnum(rhs_path.root)).differ() orelse + std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).differ().?; } - - const lhs_span = lhs_src.span(zcu) catch |err| { - bad_file_out.* = lhs_src.file_scope; - return err; + const prev_prot = zcu.comp.io.swapCancelProtection(.blocked); + defer _ = zcu.comp.io.swapCancelProtection(prev_prot); + const lhs_span = lhs_resolved.span(zcu) catch |err| { + assert(err != error.Canceled); // we're protected + // Failed to read LHS, so we'll get a transient error. Just sort it to the end. + return .gt; }; - const rhs_span = rhs_src.span(zcu) catch |err| { - bad_file_out.* = rhs_src.file_scope; - return err; + const rhs_span = rhs_resolved.span(zcu) catch |err| { + assert(err != error.Canceled); // we're protected + // Failed to read RHS, so we'll get a transient error. Just sort it to the end. + return .lt; }; - return lhs_span.main < rhs_span.main; + return std.math.order(lhs_span.main, rhs_span.main); } };