commit 978f7fb1ff1cdb36f48b774516aa09ab6a1dfbc0 (tree)
parent 0a246f5e67118328a11df51cd6dfa419793ebeb1
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date: Sat, 28 Feb 2026 11:40:25 +0000
Zcu: improve error message sorting
Diffstat:
| M | src/Compilation.zig | | | 55 | +++++++++---------------------------------------------- |
| M | src/Zcu.zig | | | 53 | ++++++++++++++++++++++++++++++----------------------- |
2 files changed, 39 insertions(+), 69 deletions(-)
diff --git 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
@@ -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);
}
};