authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-14 00:42:31+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-14 00:42:31+02:00
log65270cdc3345e9840427179168a09ef6e4dd34b9
tree3d4cd45795caaae02817d6642b1a373b07150b55
parent9be5323e93123a3979037997fa40a95b4c985b85
parent7561f63b5d93fb32b39410590625bb16bf2ac0dd
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12298 from r00ster91/debugerror

std.debug: handle some possible errors and resolve low-hanging TODOs

4 files changed, 73 insertions(+), 94 deletions(-)

lib/std/Progress.zig+17-8
...@@ -210,8 +210,11 @@ fn refreshWithHeldLock(self: *Progress) void {...@@ -210,8 +210,11 @@ fn refreshWithHeldLock(self: *Progress) void {
210 std.debug.assert(self.is_windows_terminal);210 std.debug.assert(self.is_windows_terminal);
211211
212 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;212 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
213 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE)213 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE) {
214 unreachable;214 // stop trying to write to this file
215 self.terminal = null;
216 break :winapi;
217 }
215218
216 var cursor_pos = windows.COORD{219 var cursor_pos = windows.COORD{
217 .X = info.dwCursorPosition.X - @intCast(windows.SHORT, self.columns_written),220 .X = info.dwCursorPosition.X - @intCast(windows.SHORT, self.columns_written),
...@@ -231,7 +234,7 @@ fn refreshWithHeldLock(self: *Progress) void {...@@ -231,7 +234,7 @@ fn refreshWithHeldLock(self: *Progress) void {
231 cursor_pos,234 cursor_pos,
232 &written,235 &written,
233 ) != windows.TRUE) {236 ) != windows.TRUE) {
234 // Stop trying to write to this file.237 // stop trying to write to this file
235 self.terminal = null;238 self.terminal = null;
236 break :winapi;239 break :winapi;
237 }240 }
...@@ -241,10 +244,16 @@ fn refreshWithHeldLock(self: *Progress) void {...@@ -241,10 +244,16 @@ fn refreshWithHeldLock(self: *Progress) void {
241 fill_chars,244 fill_chars,
242 cursor_pos,245 cursor_pos,
243 &written,246 &written,
244 ) != windows.TRUE) unreachable;247 ) != windows.TRUE) {
245248 // stop trying to write to this file
246 if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE)249 self.terminal = null;
247 unreachable;250 break :winapi;
251 }
252 if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE) {
253 // stop trying to write to this file
254 self.terminal = null;
255 break :winapi;
256 }
248 } else {257 } else {
249 // we are in a "dumb" terminal like in acme or writing to a file258 // we are in a "dumb" terminal like in acme or writing to a file
250 self.output_buffer[end] = '\n';259 self.output_buffer[end] = '\n';
...@@ -288,7 +297,7 @@ fn refreshWithHeldLock(self: *Progress) void {...@@ -288,7 +297,7 @@ fn refreshWithHeldLock(self: *Progress) void {
288 }297 }
289298
290 _ = file.write(self.output_buffer[0..end]) catch {299 _ = file.write(self.output_buffer[0..end]) catch {
291 // Stop trying to write to this file once it errors.300 // stop trying to write to this file
292 self.terminal = null;301 self.terminal = null;
293 };302 };
294 if (self.timer) |*timer| {303 if (self.timer) |*timer| {
lib/std/debug.zig+37-67
...@@ -119,7 +119,7 @@ pub fn detectTTYConfig() TTY.Config {...@@ -119,7 +119,7 @@ pub fn detectTTYConfig() TTY.Config {
119 if (stderr_file.supportsAnsiEscapeCodes()) {119 if (stderr_file.supportsAnsiEscapeCodes()) {
120 return .escape_codes;120 return .escape_codes;
121 } else if (native_os == .windows and stderr_file.isTty()) {121 } else if (native_os == .windows and stderr_file.isTty()) {
122 return .windows_api;122 return .{ .windows_api = stderr_file };
123 } else {123 } else {
124 return .no_color;124 return .no_color;
125 }125 }
...@@ -384,14 +384,6 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize...@@ -384,14 +384,6 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize
384 os.abort();384 os.abort();
385}385}
386386
387const RED = "\x1b[31;1m";
388const GREEN = "\x1b[32;1m";
389const CYAN = "\x1b[36;1m";
390const WHITE = "\x1b[37;1m";
391const BOLD = "\x1b[1m";
392const DIM = "\x1b[2m";
393const RESET = "\x1b[0m";
394
395pub fn writeStackTrace(387pub fn writeStackTrace(
396 stack_trace: std.builtin.StackTrace,388 stack_trace: std.builtin.StackTrace,
397 out_stream: anytype,389 out_stream: anytype,
...@@ -415,9 +407,9 @@ pub fn writeStackTrace(...@@ -415,9 +407,9 @@ pub fn writeStackTrace(
415 if (stack_trace.index > stack_trace.instruction_addresses.len) {407 if (stack_trace.index > stack_trace.instruction_addresses.len) {
416 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;408 const dropped_frames = stack_trace.index - stack_trace.instruction_addresses.len;
417409
418 tty_config.setColor(out_stream, .Bold);410 tty_config.setColor(out_stream, .Bold) catch {};
419 try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});411 try out_stream.print("({d} additional stack frames skipped...)\n", .{dropped_frames});
420 tty_config.setColor(out_stream, .Reset);412 tty_config.setColor(out_stream, .Reset) catch {};
421 }413 }
422}414}
423415
...@@ -605,59 +597,39 @@ pub const TTY = struct {...@@ -605,59 +597,39 @@ pub const TTY = struct {
605 Reset,597 Reset,
606 };598 };
607599
608 pub const Config = enum {600 pub const Config = union(enum) {
609 no_color,601 no_color,
610 escape_codes,602 escape_codes,
611 // TODO give this a payload of file handle603 windows_api: File,
612 windows_api,
613604
614 pub fn setColor(conf: Config, out_stream: anytype, color: Color) void {605 pub fn setColor(conf: Config, out_stream: anytype, color: Color) !void {
615 nosuspend switch (conf) {606 nosuspend switch (conf) {
616 .no_color => return,607 .no_color => return,
617 .escape_codes => switch (color) {608 .escape_codes => {
618 .Red => out_stream.writeAll(RED) catch return,609 const color_string = switch (color) {
619 .Green => out_stream.writeAll(GREEN) catch return,610 .Red => "\x1b[31;1m",
620 .Cyan => out_stream.writeAll(CYAN) catch return,611 .Green => "\x1b[32;1m",
621 .White => out_stream.writeAll(WHITE) catch return,612 .Cyan => "\x1b[36;1m",
622 .Dim => out_stream.writeAll(DIM) catch return,613 .White => "\x1b[37;1m",
623 .Bold => out_stream.writeAll(BOLD) catch return,614 .Bold => "\x1b[1m",
624 .Reset => out_stream.writeAll(RESET) catch return,615 .Dim => "\x1b[2m",
616 .Reset => "\x1b[0m",
617 };
618 try out_stream.writeAll(color_string);
625 },619 },
626 .windows_api => if (native_os == .windows) {620 .windows_api => |file| if (native_os == .windows) {
627 const stderr_file = io.getStdErr();621 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
628 const S = struct {622 if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE)
629 var attrs: windows.WORD = undefined;623 return error.FailedRetrievingTerminalInfo;
630 var init_attrs = false;624 const attributes = switch (color) {
625 .Red => windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY,
626 .Green => windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY,
627 .Cyan => windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY,
628 .White, .Bold => windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY,
629 .Dim => windows.FOREGROUND_INTENSITY,
630 .Reset => info.wAttributes,
631 };631 };
632 if (!S.init_attrs) {632 try windows.SetConsoleTextAttribute(file.handle, attributes);
633 S.init_attrs = true;
634 var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
635 // TODO handle error
636 _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info);
637 S.attrs = info.wAttributes;
638 }
639
640 // TODO handle errors
641 switch (color) {
642 .Red => {
643 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {};
644 },
645 .Green => {
646 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {};
647 },
648 .Cyan => {
649 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
650 },
651 .White, .Bold => {
652 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
653 },
654 .Dim => {
655 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {};
656 },
657 .Reset => {
658 _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {};
659 },
660 }
661 } else {633 } else {
662 unreachable;634 unreachable;
663 },635 },
...@@ -751,7 +723,7 @@ fn printLineInfo(...@@ -751,7 +723,7 @@ fn printLineInfo(
751 comptime printLineFromFile: anytype,723 comptime printLineFromFile: anytype,
752) !void {724) !void {
753 nosuspend {725 nosuspend {
754 tty_config.setColor(out_stream, .Bold);726 try tty_config.setColor(out_stream, .Bold);
755727
756 if (line_info) |*li| {728 if (line_info) |*li| {
757 try out_stream.print("{s}:{d}:{d}", .{ li.file_name, li.line, li.column });729 try out_stream.print("{s}:{d}:{d}", .{ li.file_name, li.line, li.column });
...@@ -759,11 +731,11 @@ fn printLineInfo(...@@ -759,11 +731,11 @@ fn printLineInfo(
759 try out_stream.writeAll("???:?:?");731 try out_stream.writeAll("???:?:?");
760 }732 }
761733
762 tty_config.setColor(out_stream, .Reset);734 try tty_config.setColor(out_stream, .Reset);
763 try out_stream.writeAll(": ");735 try out_stream.writeAll(": ");
764 tty_config.setColor(out_stream, .Dim);736 try tty_config.setColor(out_stream, .Dim);
765 try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });737 try out_stream.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
766 tty_config.setColor(out_stream, .Reset);738 try tty_config.setColor(out_stream, .Reset);
767 try out_stream.writeAll("\n");739 try out_stream.writeAll("\n");
768740
769 // Show the matching source code line if possible741 // Show the matching source code line if possible
...@@ -774,9 +746,9 @@ fn printLineInfo(...@@ -774,9 +746,9 @@ fn printLineInfo(
774 const space_needed = @intCast(usize, li.column - 1);746 const space_needed = @intCast(usize, li.column - 1);
775747
776 try out_stream.writeByteNTimes(' ', space_needed);748 try out_stream.writeByteNTimes(' ', space_needed);
777 tty_config.setColor(out_stream, .Green);749 try tty_config.setColor(out_stream, .Green);
778 try out_stream.writeAll("^");750 try out_stream.writeAll("^");
779 tty_config.setColor(out_stream, .Reset);751 try tty_config.setColor(out_stream, .Reset);
780 }752 }
781 try out_stream.writeAll("\n");753 try out_stream.writeAll("\n");
782 } else |err| switch (err) {754 } else |err| switch (err) {
...@@ -789,14 +761,12 @@ fn printLineInfo(...@@ -789,14 +761,12 @@ fn printLineInfo(
789 }761 }
790}762}
791763
792// TODO use this
793pub const OpenSelfDebugInfoError = error{764pub const OpenSelfDebugInfoError = error{
794 MissingDebugInfo,765 MissingDebugInfo,
795 OutOfMemory,
796 UnsupportedOperatingSystem,766 UnsupportedOperatingSystem,
797};767};
798768
799pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo {769pub fn openSelfDebugInfo(allocator: mem.Allocator) OpenSelfDebugInfoError!DebugInfo {
800 nosuspend {770 nosuspend {
801 if (builtin.strip_debug_info)771 if (builtin.strip_debug_info)
802 return error.MissingDebugInfo;772 return error.MissingDebugInfo;
...@@ -813,7 +783,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo {...@@ -813,7 +783,7 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo {
813 .windows,783 .windows,
814 .solaris,784 .solaris,
815 => return DebugInfo.init(allocator),785 => return DebugInfo.init(allocator),
816 else => return error.UnsupportedDebugInfo,786 else => return error.UnsupportedOperatingSystem,
817 }787 }
818 }788 }
819}789}
lib/std/testing.zig+4-4
...@@ -387,9 +387,9 @@ fn SliceDiffer(comptime T: type) type {...@@ -387,9 +387,9 @@ fn SliceDiffer(comptime T: type) type {
387 for (self.expected) |value, i| {387 for (self.expected) |value, i| {
388 var full_index = self.start_index + i;388 var full_index = self.start_index + i;
389 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;389 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;
390 if (diff) self.ttyconf.setColor(writer, .Red);390 if (diff) try self.ttyconf.setColor(writer, .Red);
391 try writer.print("[{}]: {any}\n", .{ full_index, value });391 try writer.print("[{}]: {any}\n", .{ full_index, value });
392 if (diff) self.ttyconf.setColor(writer, .Reset);392 if (diff) try self.ttyconf.setColor(writer, .Reset);
393 }393 }
394 }394 }
395 };395 };
...@@ -427,9 +427,9 @@ const BytesDiffer = struct {...@@ -427,9 +427,9 @@ const BytesDiffer = struct {
427 }427 }
428428
429 fn writeByteDiff(self: BytesDiffer, writer: anytype, comptime fmt: []const u8, byte: u8, diff: bool) !void {429 fn writeByteDiff(self: BytesDiffer, writer: anytype, comptime fmt: []const u8, byte: u8, diff: bool) !void {
430 if (diff) self.ttyconf.setColor(writer, .Red);430 if (diff) try self.ttyconf.setColor(writer, .Red);
431 try writer.print(fmt, .{byte});431 try writer.print(fmt, .{byte});
432 if (diff) self.ttyconf.setColor(writer, .Reset);432 if (diff) try self.ttyconf.setColor(writer, .Reset);
433 }433 }
434434
435 const ChunkIterator = struct {435 const ChunkIterator = struct {
src/Compilation.zig+15-15
...@@ -428,29 +428,29 @@ pub const AllErrors = struct {...@@ -428,29 +428,29 @@ pub const AllErrors = struct {
428 switch (msg) {428 switch (msg) {
429 .src => |src| {429 .src => |src| {
430 try counting_stderr.writeByteNTimes(' ', indent);430 try counting_stderr.writeByteNTimes(' ', indent);
431 ttyconf.setColor(stderr, .Bold);431 try ttyconf.setColor(stderr, .Bold);
432 try counting_stderr.print("{s}:{d}:{d}: ", .{432 try counting_stderr.print("{s}:{d}:{d}: ", .{
433 src.src_path,433 src.src_path,
434 src.line + 1,434 src.line + 1,
435 src.column + 1,435 src.column + 1,
436 });436 });
437 ttyconf.setColor(stderr, color);437 try ttyconf.setColor(stderr, color);
438 try counting_stderr.writeAll(kind);438 try counting_stderr.writeAll(kind);
439 try counting_stderr.writeAll(": ");439 try counting_stderr.writeAll(": ");
440 // This is the length of the part before the error message:440 // This is the length of the part before the error message:
441 // e.g. "file.zig:4:5: error: "441 // e.g. "file.zig:4:5: error: "
442 const prefix_len = @intCast(usize, counting_stderr.context.bytes_written);442 const prefix_len = @intCast(usize, counting_stderr.context.bytes_written);
443 ttyconf.setColor(stderr, .Reset);443 try ttyconf.setColor(stderr, .Reset);
444 ttyconf.setColor(stderr, .Bold);444 try ttyconf.setColor(stderr, .Bold);
445 if (src.count == 1) {445 if (src.count == 1) {
446 try src.writeMsg(stderr, prefix_len);446 try src.writeMsg(stderr, prefix_len);
447 try stderr.writeByte('\n');447 try stderr.writeByte('\n');
448 } else {448 } else {
449 try src.writeMsg(stderr, prefix_len);449 try src.writeMsg(stderr, prefix_len);
450 ttyconf.setColor(stderr, .Dim);450 try ttyconf.setColor(stderr, .Dim);
451 try stderr.print(" ({d} times)\n", .{src.count});451 try stderr.print(" ({d} times)\n", .{src.count});
452 }452 }
453 ttyconf.setColor(stderr, .Reset);453 try ttyconf.setColor(stderr, .Reset);
454 if (src.source_line) |line| {454 if (src.source_line) |line| {
455 for (line) |b| switch (b) {455 for (line) |b| switch (b) {
456 '\t' => try stderr.writeByte(' '),456 '\t' => try stderr.writeByte(' '),
...@@ -462,19 +462,19 @@ pub const AllErrors = struct {...@@ -462,19 +462,19 @@ pub const AllErrors = struct {
462 // -1 since span.main includes the caret462 // -1 since span.main includes the caret
463 const after_caret = src.span.end - src.span.main -| 1;463 const after_caret = src.span.end - src.span.main -| 1;
464 try stderr.writeByteNTimes(' ', src.column - before_caret);464 try stderr.writeByteNTimes(' ', src.column - before_caret);
465 ttyconf.setColor(stderr, .Green);465 try ttyconf.setColor(stderr, .Green);
466 try stderr.writeByteNTimes('~', before_caret);466 try stderr.writeByteNTimes('~', before_caret);
467 try stderr.writeByte('^');467 try stderr.writeByte('^');
468 try stderr.writeByteNTimes('~', after_caret);468 try stderr.writeByteNTimes('~', after_caret);
469 try stderr.writeByte('\n');469 try stderr.writeByte('\n');
470 ttyconf.setColor(stderr, .Reset);470 try ttyconf.setColor(stderr, .Reset);
471 }471 }
472 for (src.notes) |note| {472 for (src.notes) |note| {
473 try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent);473 try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent);
474 }474 }
475 if (src.reference_trace.len != 0) {475 if (src.reference_trace.len != 0) {
476 ttyconf.setColor(stderr, .Reset);476 try ttyconf.setColor(stderr, .Reset);
477 ttyconf.setColor(stderr, .Dim);477 try ttyconf.setColor(stderr, .Dim);
478 try stderr.print("referenced by:\n", .{});478 try stderr.print("referenced by:\n", .{});
479 for (src.reference_trace) |reference| {479 for (src.reference_trace) |reference| {
480 switch (reference) {480 switch (reference) {
...@@ -498,23 +498,23 @@ pub const AllErrors = struct {...@@ -498,23 +498,23 @@ pub const AllErrors = struct {
498 }498 }
499 }499 }
500 try stderr.writeByte('\n');500 try stderr.writeByte('\n');
501 ttyconf.setColor(stderr, .Reset);501 try ttyconf.setColor(stderr, .Reset);
502 }502 }
503 },503 },
504 .plain => |plain| {504 .plain => |plain| {
505 ttyconf.setColor(stderr, color);505 try ttyconf.setColor(stderr, color);
506 try stderr.writeByteNTimes(' ', indent);506 try stderr.writeByteNTimes(' ', indent);
507 try stderr.writeAll(kind);507 try stderr.writeAll(kind);
508 try stderr.writeAll(": ");508 try stderr.writeAll(": ");
509 ttyconf.setColor(stderr, .Reset);509 try ttyconf.setColor(stderr, .Reset);
510 if (plain.count == 1) {510 if (plain.count == 1) {
511 try stderr.print("{s}\n", .{plain.msg});511 try stderr.print("{s}\n", .{plain.msg});
512 } else {512 } else {
513 try stderr.print("{s}", .{plain.msg});513 try stderr.print("{s}", .{plain.msg});
514 ttyconf.setColor(stderr, .Dim);514 try ttyconf.setColor(stderr, .Dim);
515 try stderr.print(" ({d} times)\n", .{plain.count});515 try stderr.print(" ({d} times)\n", .{plain.count});
516 }516 }
517 ttyconf.setColor(stderr, .Reset);517 try ttyconf.setColor(stderr, .Reset);
518 for (plain.notes) |note| {518 for (plain.notes) |note| {
519 try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent + 4);519 try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent + 4);
520 }520 }