authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-08 14:20:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-09 15:37:16-07:00
logfd32f6890db8d338ec5cad92871035767f2e84ac
tree729ea96f00e6f4190473f7aac38eb581703e8bfe
parentaf909f6c93f06e409e98cb90a9896aa5216f1563

stage2: fold redundant error notes


3 files changed, 98 insertions(+), 7 deletions(-)

src/Compilation.zig+95-6
......@@ -338,6 +338,8 @@ pub const AllErrors = struct {
338338 line: u32,
339339 column: u32,
340340 byte_offset: u32,
341 /// Usually one, but incremented for redundant messages.
342 count: u32 = 1,
341343 /// Does not include the trailing newline.
342344 source_line: ?[]const u8,
343345 notes: []Message = &.{},
......@@ -345,8 +347,21 @@ pub const AllErrors = struct {
345347 plain: struct {
346348 msg: []const u8,
347349 notes: []Message = &.{},
350 /// Usually one, but incremented for redundant messages.
351 count: u32 = 1,
348352 },
349353
354 pub fn incrementCount(msg: *Message) void {
355 switch (msg.*) {
356 .src => |*src| {
357 src.count += 1;
358 },
359 .plain => |*plain| {
360 plain.count += 1;
361 },
362 }
363 }
364
350365 pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {
351366 std.debug.getStderrMutex().lock();
352367 defer std.debug.getStderrMutex().unlock();
......@@ -376,7 +391,13 @@ pub const AllErrors = struct {
376391 try stderr.writeAll(kind);
377392 ttyconf.setColor(stderr, .Reset);
378393 ttyconf.setColor(stderr, .Bold);
379 try stderr.print(" {s}\n", .{src.msg});
394 if (src.count == 1) {
395 try stderr.print(" {s}\n", .{src.msg});
396 } else {
397 try stderr.print(" {s}", .{src.msg});
398 ttyconf.setColor(stderr, .Dim);
399 try stderr.print(" ({d} times)\n", .{src.count});
400 }
380401 ttyconf.setColor(stderr, .Reset);
381402 if (ttyconf != .no_color) {
382403 if (src.source_line) |line| {
......@@ -400,7 +421,13 @@ pub const AllErrors = struct {
400421 try stderr.writeByteNTimes(' ', indent);
401422 try stderr.writeAll(kind);
402423 ttyconf.setColor(stderr, .Reset);
403 try stderr.print(" {s}\n", .{plain.msg});
424 if (plain.count == 1) {
425 try stderr.print(" {s}\n", .{plain.msg});
426 } else {
427 try stderr.print(" {s}", .{plain.msg});
428 ttyconf.setColor(stderr, .Dim);
429 try stderr.print(" ({d} times)\n", .{plain.count});
430 }
404431 ttyconf.setColor(stderr, .Reset);
405432 for (plain.notes) |note| {
406433 try note.renderToStdErrInner(ttyconf, stderr_file, "error:", .Red, indent + 4);
......@@ -408,6 +435,50 @@ pub const AllErrors = struct {
408435 },
409436 }
410437 }
438
439 pub const HashContext = struct {
440 pub fn hash(ctx: HashContext, key: *Message) u64 {
441 _ = ctx;
442 var hasher = std.hash.Wyhash.init(0);
443
444 switch (key.*) {
445 .src => |src| {
446 hasher.update(src.msg);
447 hasher.update(src.src_path);
448 std.hash.autoHash(&hasher, src.line);
449 std.hash.autoHash(&hasher, src.column);
450 std.hash.autoHash(&hasher, src.byte_offset);
451 },
452 .plain => |plain| {
453 hasher.update(plain.msg);
454 },
455 }
456
457 return hasher.final();
458 }
459
460 pub fn eql(ctx: HashContext, a: *Message, b: *Message) bool {
461 _ = ctx;
462 switch (a.*) {
463 .src => |a_src| switch (b.*) {
464 .src => |b_src| {
465 return mem.eql(u8, a_src.msg, b_src.msg) and
466 mem.eql(u8, a_src.src_path, b_src.src_path) and
467 a_src.line == b_src.line and
468 a_src.column == b_src.column and
469 a_src.byte_offset == b_src.byte_offset;
470 },
471 .plain => return false,
472 },
473 .plain => |a_plain| switch (b.*) {
474 .src => return false,
475 .plain => |b_plain| {
476 return mem.eql(u8, a_plain.msg, b_plain.msg);
477 },
478 },
479 }
480 }
481 };
411482 };
412483
413484 pub fn deinit(self: *AllErrors, gpa: Allocator) void {
......@@ -421,13 +492,25 @@ pub const AllErrors = struct {
421492 module_err_msg: Module.ErrorMsg,
422493 ) !void {
423494 const allocator = arena.allocator();
424 const notes = try allocator.alloc(Message, module_err_msg.notes.len);
425 for (notes) |*note, i| {
426 const module_note = module_err_msg.notes[i];
495
496 const notes_buf = try allocator.alloc(Message, module_err_msg.notes.len);
497 var note_i: usize = 0;
498
499 // De-duplicate error notes. The main use case in mind for this is
500 // too many "note: called from here" notes when eval branch quota is reached.
501 var seen_notes = std.HashMap(
502 *Message,
503 void,
504 Message.HashContext,
505 std.hash_map.default_max_load_percentage,
506 ).init(allocator);
507
508 for (module_err_msg.notes) |module_note| {
427509 const source = try module_note.src_loc.file_scope.getSource(module.gpa);
428510 const byte_offset = try module_note.src_loc.byteOffset(module.gpa);
429511 const loc = std.zig.findLineColumn(source.bytes, byte_offset);
430512 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
513 const note = &notes_buf[note_i];
431514 note.* = .{
432515 .src = .{
433516 .src_path = file_path,
......@@ -438,6 +521,12 @@ pub const AllErrors = struct {
438521 .source_line = try allocator.dupe(u8, loc.source_line),
439522 },
440523 };
524 const gop = try seen_notes.getOrPut(note);
525 if (gop.found_existing) {
526 gop.key_ptr.*.incrementCount();
527 } else {
528 note_i += 1;
529 }
441530 }
442531 if (module_err_msg.src_loc.lazy == .entire_file) {
443532 try errors.append(.{
......@@ -458,7 +547,7 @@ pub const AllErrors = struct {
458547 .byte_offset = byte_offset,
459548 .line = @intCast(u32, loc.line),
460549 .column = @intCast(u32, loc.column),
461 .notes = notes,
550 .notes = notes_buf[0..note_i],
462551 .source_line = try allocator.dupe(u8, loc.source_line),
463552 },
464553 });
src/Sema.zig-1
......@@ -18061,7 +18061,6 @@ fn safetyPanic(
1806118061fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
1806218062 sema.branch_count += 1;
1806318063 if (sema.branch_count > sema.branch_quota) {
18064 // TODO show the "called from here" stack
1806518064 return sema.fail(block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota});
1806618065 }
1806718066}
test/cases/recursive_inline_function.1.zig+3
......@@ -14,3 +14,6 @@ inline fn fibonacci(n: usize) usize {
1414// error
1515//
1616// :11:21: error: evaluation exceeded 1000 backwards branches
17// :11:40: note: called from here (6 times)
18// :11:21: note: called from here (495 times)
19// :5:24: note: called from here