stage2: fold redundant error notes
This commit is contained in:
@@ -338,6 +338,8 @@ pub const AllErrors = struct {
|
||||
line: u32,
|
||||
column: u32,
|
||||
byte_offset: u32,
|
||||
/// Usually one, but incremented for redundant messages.
|
||||
count: u32 = 1,
|
||||
/// Does not include the trailing newline.
|
||||
source_line: ?[]const u8,
|
||||
notes: []Message = &.{},
|
||||
@@ -345,8 +347,21 @@ pub const AllErrors = struct {
|
||||
plain: struct {
|
||||
msg: []const u8,
|
||||
notes: []Message = &.{},
|
||||
/// Usually one, but incremented for redundant messages.
|
||||
count: u32 = 1,
|
||||
},
|
||||
|
||||
pub fn incrementCount(msg: *Message) void {
|
||||
switch (msg.*) {
|
||||
.src => |*src| {
|
||||
src.count += 1;
|
||||
},
|
||||
.plain => |*plain| {
|
||||
plain.count += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {
|
||||
std.debug.getStderrMutex().lock();
|
||||
defer std.debug.getStderrMutex().unlock();
|
||||
@@ -376,7 +391,13 @@ pub const AllErrors = struct {
|
||||
try stderr.writeAll(kind);
|
||||
ttyconf.setColor(stderr, .Reset);
|
||||
ttyconf.setColor(stderr, .Bold);
|
||||
try stderr.print(" {s}\n", .{src.msg});
|
||||
if (src.count == 1) {
|
||||
try stderr.print(" {s}\n", .{src.msg});
|
||||
} else {
|
||||
try stderr.print(" {s}", .{src.msg});
|
||||
ttyconf.setColor(stderr, .Dim);
|
||||
try stderr.print(" ({d} times)\n", .{src.count});
|
||||
}
|
||||
ttyconf.setColor(stderr, .Reset);
|
||||
if (ttyconf != .no_color) {
|
||||
if (src.source_line) |line| {
|
||||
@@ -400,7 +421,13 @@ pub const AllErrors = struct {
|
||||
try stderr.writeByteNTimes(' ', indent);
|
||||
try stderr.writeAll(kind);
|
||||
ttyconf.setColor(stderr, .Reset);
|
||||
try stderr.print(" {s}\n", .{plain.msg});
|
||||
if (plain.count == 1) {
|
||||
try stderr.print(" {s}\n", .{plain.msg});
|
||||
} else {
|
||||
try stderr.print(" {s}", .{plain.msg});
|
||||
ttyconf.setColor(stderr, .Dim);
|
||||
try stderr.print(" ({d} times)\n", .{plain.count});
|
||||
}
|
||||
ttyconf.setColor(stderr, .Reset);
|
||||
for (plain.notes) |note| {
|
||||
try note.renderToStdErrInner(ttyconf, stderr_file, "error:", .Red, indent + 4);
|
||||
@@ -408,6 +435,50 @@ pub const AllErrors = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const HashContext = struct {
|
||||
pub fn hash(ctx: HashContext, key: *Message) u64 {
|
||||
_ = ctx;
|
||||
var hasher = std.hash.Wyhash.init(0);
|
||||
|
||||
switch (key.*) {
|
||||
.src => |src| {
|
||||
hasher.update(src.msg);
|
||||
hasher.update(src.src_path);
|
||||
std.hash.autoHash(&hasher, src.line);
|
||||
std.hash.autoHash(&hasher, src.column);
|
||||
std.hash.autoHash(&hasher, src.byte_offset);
|
||||
},
|
||||
.plain => |plain| {
|
||||
hasher.update(plain.msg);
|
||||
},
|
||||
}
|
||||
|
||||
return hasher.final();
|
||||
}
|
||||
|
||||
pub fn eql(ctx: HashContext, a: *Message, b: *Message) bool {
|
||||
_ = ctx;
|
||||
switch (a.*) {
|
||||
.src => |a_src| switch (b.*) {
|
||||
.src => |b_src| {
|
||||
return mem.eql(u8, a_src.msg, b_src.msg) and
|
||||
mem.eql(u8, a_src.src_path, b_src.src_path) and
|
||||
a_src.line == b_src.line and
|
||||
a_src.column == b_src.column and
|
||||
a_src.byte_offset == b_src.byte_offset;
|
||||
},
|
||||
.plain => return false,
|
||||
},
|
||||
.plain => |a_plain| switch (b.*) {
|
||||
.src => return false,
|
||||
.plain => |b_plain| {
|
||||
return mem.eql(u8, a_plain.msg, b_plain.msg);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
pub fn deinit(self: *AllErrors, gpa: Allocator) void {
|
||||
@@ -421,13 +492,25 @@ pub const AllErrors = struct {
|
||||
module_err_msg: Module.ErrorMsg,
|
||||
) !void {
|
||||
const allocator = arena.allocator();
|
||||
const notes = try allocator.alloc(Message, module_err_msg.notes.len);
|
||||
for (notes) |*note, i| {
|
||||
const module_note = module_err_msg.notes[i];
|
||||
|
||||
const notes_buf = try allocator.alloc(Message, module_err_msg.notes.len);
|
||||
var note_i: usize = 0;
|
||||
|
||||
// De-duplicate error notes. The main use case in mind for this is
|
||||
// too many "note: called from here" notes when eval branch quota is reached.
|
||||
var seen_notes = std.HashMap(
|
||||
*Message,
|
||||
void,
|
||||
Message.HashContext,
|
||||
std.hash_map.default_max_load_percentage,
|
||||
).init(allocator);
|
||||
|
||||
for (module_err_msg.notes) |module_note| {
|
||||
const source = try module_note.src_loc.file_scope.getSource(module.gpa);
|
||||
const byte_offset = try module_note.src_loc.byteOffset(module.gpa);
|
||||
const loc = std.zig.findLineColumn(source.bytes, byte_offset);
|
||||
const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
|
||||
const note = ¬es_buf[note_i];
|
||||
note.* = .{
|
||||
.src = .{
|
||||
.src_path = file_path,
|
||||
@@ -438,6 +521,12 @@ pub const AllErrors = struct {
|
||||
.source_line = try allocator.dupe(u8, loc.source_line),
|
||||
},
|
||||
};
|
||||
const gop = try seen_notes.getOrPut(note);
|
||||
if (gop.found_existing) {
|
||||
gop.key_ptr.*.incrementCount();
|
||||
} else {
|
||||
note_i += 1;
|
||||
}
|
||||
}
|
||||
if (module_err_msg.src_loc.lazy == .entire_file) {
|
||||
try errors.append(.{
|
||||
@@ -458,7 +547,7 @@ pub const AllErrors = struct {
|
||||
.byte_offset = byte_offset,
|
||||
.line = @intCast(u32, loc.line),
|
||||
.column = @intCast(u32, loc.column),
|
||||
.notes = notes,
|
||||
.notes = notes_buf[0..note_i],
|
||||
.source_line = try allocator.dupe(u8, loc.source_line),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18061,7 +18061,6 @@ fn safetyPanic(
|
||||
fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
|
||||
sema.branch_count += 1;
|
||||
if (sema.branch_count > sema.branch_quota) {
|
||||
// TODO show the "called from here" stack
|
||||
return sema.fail(block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,3 +14,6 @@ inline fn fibonacci(n: usize) usize {
|
||||
// error
|
||||
//
|
||||
// :11:21: error: evaluation exceeded 1000 backwards branches
|
||||
// :11:40: note: called from here (6 times)
|
||||
// :11:21: note: called from here (495 times)
|
||||
// :5:24: note: called from here
|
||||
|
||||
Reference in New Issue
Block a user