diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index dee19818a8..1d2eca9703 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -3,24 +3,22 @@ //! is used to collect all the errors from the various places into one //! convenient place for API users to consume. -string_bytes: std.ArrayListUnmanaged(u8), -/// The first thing in this array is a ErrorMessageListIndex. -extra: std.ArrayListUnmanaged(u32), +string_bytes: []const u8, +/// The first thing in this array is an `ErrorMessageList`. +extra: []const u32, // An index into `extra` pointing at an `ErrorMessage`. pub const MessageIndex = enum(u32) { _, }; -/// After the header is: -/// * string_bytes -/// * extra (little endian) -pub const Header = struct { - string_bytes_len: u32, - extra_len: u32, +// An index into `extra` pointing at an `SourceLocation`. +pub const SourceLocationIndex = enum(u32) { + none = 0, + _, }; -/// Trailing: ErrorMessage for each len +/// There will be a MessageIndex for each len at start. pub const ErrorMessageList = struct { len: u32, start: u32, @@ -46,14 +44,13 @@ pub const SourceLocation = struct { }; /// Trailing: -/// * ErrorMessage for each notes_len. +/// * MessageIndex for each notes_len. pub const ErrorMessage = struct { /// null terminated string index msg: u32, /// Usually one, but incremented for redundant messages. count: u32 = 1, - /// 0 or the index into extra of a SourceLocation - src_loc: u32 = 0, + src_loc: SourceLocationIndex = .none, notes_len: u32 = 0, }; @@ -65,170 +62,41 @@ pub const ReferenceTrace = struct { decl_name: u32, /// Index into extra of a SourceLocation /// If this is 0, this is the sentinel ReferenceTrace element. - src_loc: u32, + src_loc: SourceLocationIndex, }; -pub fn init(eb: *ErrorBundle, gpa: Allocator) !void { - eb.* = .{ - .string_bytes = .{}, - .extra = .{}, - }; - - // So that 0 can be used to indicate a null string. - try eb.string_bytes.append(gpa, 0); - - _ = try addExtra(eb, gpa, ErrorMessageList{ - .len = 0, - .start = 0, - }); -} - pub fn deinit(eb: *ErrorBundle, gpa: Allocator) void { - eb.string_bytes.deinit(gpa); - eb.extra.deinit(gpa); + gpa.free(eb.string_bytes); + gpa.free(eb.extra); eb.* = undefined; } -pub fn addString(eb: *ErrorBundle, gpa: Allocator, s: []const u8) !u32 { - const index = @intCast(u32, eb.string_bytes.items.len); - try eb.string_bytes.ensureUnusedCapacity(gpa, s.len + 1); - eb.string_bytes.appendSliceAssumeCapacity(s); - eb.string_bytes.appendAssumeCapacity(0); - return index; -} - -pub fn printString(eb: *ErrorBundle, gpa: Allocator, comptime fmt: []const u8, args: anytype) !u32 { - const index = @intCast(u32, eb.string_bytes.items.len); - try eb.string_bytes.writer(gpa).print(fmt, args); - try eb.string_bytes.append(gpa, 0); - return index; -} - -pub fn addErrorMessage(eb: *ErrorBundle, gpa: Allocator, em: ErrorMessage) !void { - if (eb.errorMessageCount() == 0) { - eb.setStartIndex(@intCast(u32, eb.extra.items.len)); - } - _ = try addExtra(eb, gpa, em); -} - -pub fn addSourceLocation(eb: *ErrorBundle, gpa: Allocator, sl: SourceLocation) !u32 { - return addExtra(eb, gpa, sl); -} - -pub fn addReferenceTrace(eb: *ErrorBundle, gpa: Allocator, rt: ReferenceTrace) !void { - _ = try addExtra(eb, gpa, rt); -} - -pub fn addBundle(eb: *ErrorBundle, gpa: Allocator, other: ErrorBundle) !void { - // Skip over the initial ErrorMessageList len field. - const root_fields_len = @typeInfo(ErrorMessageList).Struct.fields.len; - const other_list = other.extraData(ErrorMessageList, 0).data; - const other_extra = other.extra.items[root_fields_len..]; - - try eb.string_bytes.ensureUnusedCapacity(gpa, other.string_bytes.items.len); - try eb.extra.ensureUnusedCapacity(gpa, other_extra.len); - - const new_string_base = @intCast(u32, eb.string_bytes.items.len); - const new_data_base = @intCast(u32, eb.extra.items.len - root_fields_len); - - eb.string_bytes.appendSliceAssumeCapacity(other.string_bytes.items); - eb.extra.appendSliceAssumeCapacity(other_extra); - - // Now we must offset the string indexes and extra indexes of the newly - // added extra. - var index = new_data_base + other_list.start; - for (0..other_list.len) |_| { - index = try patchMessage(eb, index, new_string_base, new_data_base); - } -} - -fn patchMessage(eb: *ErrorBundle, msg_idx: usize, new_string_base: u32, new_data_base: u32) !u32 { - var msg = eb.extraData(ErrorMessage, msg_idx); - if (msg.data.msg != 0) msg.data.msg += new_string_base; - if (msg.data.src_loc != 0) msg.data.src_loc += new_data_base; - eb.setExtra(msg_idx, msg.data); - - try patchSrcLoc(eb, msg.data.src_loc, new_string_base, new_data_base); - - var index = @intCast(u32, msg.end); - for (0..msg.data.notes_len) |_| { - index = try patchMessage(eb, index, new_string_base, new_data_base); - } - return index; -} - -fn patchSrcLoc(eb: *ErrorBundle, idx: usize, new_string_base: u32, new_data_base: u32) !void { - if (idx == 0) return; - - var src_loc = eb.extraData(SourceLocation, idx); - if (src_loc.data.src_path != 0) src_loc.data.src_path += new_string_base; - if (src_loc.data.source_line != 0) src_loc.data.source_line += new_string_base; - eb.setExtra(idx, src_loc.data); - - var index = src_loc.end; - for (0..src_loc.data.reference_trace_len) |_| { - var ref_trace = eb.extraData(ReferenceTrace, index); - if (ref_trace.data.decl_name != 0) ref_trace.data.decl_name += new_string_base; - if (ref_trace.data.src_loc != 0) ref_trace.data.src_loc += new_data_base; - eb.setExtra(index, ref_trace.data); - try patchSrcLoc(eb, ref_trace.data.src_loc, new_string_base, new_data_base); - index = ref_trace.end; - } -} - -fn addExtra(eb: *ErrorBundle, gpa: Allocator, extra: anytype) Allocator.Error!u32 { - const fields = @typeInfo(@TypeOf(extra)).Struct.fields; - try eb.extra.ensureUnusedCapacity(gpa, fields.len); - return addExtraAssumeCapacity(eb, extra); -} - -fn addExtraAssumeCapacity(eb: *ErrorBundle, extra: anytype) u32 { - const fields = @typeInfo(@TypeOf(extra)).Struct.fields; - const result = @intCast(u32, eb.extra.items.len); - eb.extra.items.len += fields.len; - setExtra(eb, result, extra); - return result; -} - -fn setExtra(eb: *ErrorBundle, index: usize, extra: anytype) void { - const fields = @typeInfo(@TypeOf(extra)).Struct.fields; - var i = index; - inline for (fields) |field| { - eb.extra.items[i] = switch (field.type) { - u32 => @field(extra, field.name), - else => @compileError("bad field type"), - }; - i += 1; - } -} - pub fn errorMessageCount(eb: ErrorBundle) u32 { - return eb.extra.items[0]; + return eb.getErrorMessageList().len; } -pub fn setErrorMessageCount(eb: *ErrorBundle, count: u32) void { - eb.extra.items[0] = count; +pub fn getErrorMessageList(eb: ErrorBundle) ErrorMessageList { + return eb.extraData(ErrorMessageList, 0).data; } -pub fn incrementCount(eb: *ErrorBundle, delta: u32) void { - eb.extra.items[0] += delta; -} - -pub fn getStartIndex(eb: ErrorBundle) u32 { - return eb.extra.items[1]; -} - -pub fn setStartIndex(eb: *ErrorBundle, index: u32) void { - eb.extra.items[1] = index; +pub fn getMessages(eb: ErrorBundle) []const MessageIndex { + const list = eb.getErrorMessageList(); + return @ptrCast([]const MessageIndex, eb.extra[list.start..][0..list.len]); } pub fn getErrorMessage(eb: ErrorBundle, index: MessageIndex) ErrorMessage { return eb.extraData(ErrorMessage, @enumToInt(index)).data; } -pub fn getSourceLocation(eb: ErrorBundle, index: u32) SourceLocation { - assert(index != 0); - return eb.extraData(SourceLocation, index).data; +pub fn getSourceLocation(eb: ErrorBundle, index: SourceLocationIndex) SourceLocation { + assert(index != .none); + return eb.extraData(SourceLocation, @enumToInt(index)).data; +} + +pub fn getNotes(eb: ErrorBundle, index: MessageIndex) []const MessageIndex { + const notes_len = eb.getErrorMessage(index).notes_len; + const start = @enumToInt(index) + @typeInfo(ErrorMessage).Struct.fields.len; + return @ptrCast([]const MessageIndex, eb.extra[start..][0..notes_len]); } /// Returns the requested data, as well as the new index which is at the start of the @@ -239,7 +107,9 @@ fn extraData(eb: ErrorBundle, comptime T: type, index: usize) struct { data: T, var result: T = undefined; inline for (fields) |field| { @field(result, field.name) = switch (field.type) { - u32 => eb.extra.items[i], + u32 => eb.extra[i], + MessageIndex => @intToEnum(MessageIndex, eb.extra[i]), + SourceLocationIndex => @intToEnum(SourceLocationIndex, eb.extra[i]), else => @compileError("bad field type"), }; i += 1; @@ -252,7 +122,7 @@ fn extraData(eb: ErrorBundle, comptime T: type, index: usize) struct { data: T, /// Given an index into `string_bytes` returns the null-terminated string found there. pub fn nullTerminatedString(eb: ErrorBundle, index: usize) [:0]const u8 { - const string_bytes = eb.string_bytes.items; + const string_bytes = eb.string_bytes; var end: usize = index; while (string_bytes[end] != 0) { end += 1; @@ -272,28 +142,25 @@ pub fn renderToWriter( ttyconf: std.debug.TTY.Config, writer: anytype, ) anyerror!void { - const list = eb.extraData(ErrorMessageList, 0).data; - var index: usize = list.start; - for (0..list.len) |_| { - const err_msg = eb.extraData(ErrorMessage, index); - index = try renderErrorMessageToWriter(eb, err_msg.data, err_msg.end, ttyconf, writer, "error", .Red, 0); + for (eb.getMessages()) |err_msg| { + try renderErrorMessageToWriter(eb, err_msg, ttyconf, writer, "error", .Red, 0); } } fn renderErrorMessageToWriter( eb: ErrorBundle, - err_msg: ErrorMessage, - end_index: usize, + err_msg_index: MessageIndex, ttyconf: std.debug.TTY.Config, stderr: anytype, kind: []const u8, color: std.debug.TTY.Color, indent: usize, -) anyerror!usize { +) anyerror!void { var counting_writer = std.io.countingWriter(stderr); const counting_stderr = counting_writer.writer(); - if (err_msg.src_loc != 0) { - const src = eb.extraData(SourceLocation, err_msg.src_loc); + const err_msg = eb.getErrorMessage(err_msg_index); + if (err_msg.src_loc != .none) { + const src = eb.extraData(SourceLocation, @enumToInt(err_msg.src_loc)); try counting_stderr.writeByteNTimes(' ', indent); try ttyconf.setColor(stderr, .Bold); try counting_stderr.print("{s}:{d}:{d}: ", .{ @@ -337,10 +204,8 @@ fn renderErrorMessageToWriter( try stderr.writeByte('\n'); try ttyconf.setColor(stderr, .Reset); } - var index = end_index; - for (0..err_msg.notes_len) |_| { - const note = eb.extraData(ErrorMessage, index); - index = try renderErrorMessageToWriter(eb, note.data, note.end, ttyconf, stderr, "note", .Cyan, indent); + for (eb.getNotes(err_msg_index)) |note| { + try renderErrorMessageToWriter(eb, note, ttyconf, stderr, "note", .Cyan, indent); } if (src.data.reference_trace_len > 0) { try ttyconf.setColor(stderr, .Reset); @@ -350,7 +215,7 @@ fn renderErrorMessageToWriter( for (0..src.data.reference_trace_len) |_| { const ref_trace = eb.extraData(ReferenceTrace, ref_index); ref_index = ref_trace.end; - if (ref_trace.data.src_loc != 0) { + if (ref_trace.data.src_loc != .none) { const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); try stderr.print(" {s}: {s}:{d}:{d}\n", .{ eb.nullTerminatedString(ref_trace.data.decl_name), @@ -374,7 +239,6 @@ fn renderErrorMessageToWriter( try stderr.writeByte('\n'); try ttyconf.setColor(stderr, .Reset); } - return index; } else { try ttyconf.setColor(stderr, color); try stderr.writeByteNTimes(' ', indent); @@ -390,12 +254,9 @@ fn renderErrorMessageToWriter( try stderr.print(" ({d} times)\n", .{err_msg.count}); } try ttyconf.setColor(stderr, .Reset); - var index = end_index; - for (0..err_msg.notes_len) |_| { - const note = eb.extraData(ErrorMessage, index); - index = try renderErrorMessageToWriter(eb, note.data, note.end, ttyconf, stderr, "note", .Cyan, indent + 4); + for (eb.getNotes(err_msg_index)) |note| { + try renderErrorMessageToWriter(eb, note, ttyconf, stderr, "note", .Cyan, indent + 4); } - return index; } } @@ -417,3 +278,186 @@ const std = @import("std"); const ErrorBundle = @This(); const Allocator = std.mem.Allocator; const assert = std.debug.assert; + +pub const Wip = struct { + gpa: Allocator, + string_bytes: std.ArrayListUnmanaged(u8), + /// The first thing in this array is a ErrorMessageList. + extra: std.ArrayListUnmanaged(u32), + root_list: std.ArrayListUnmanaged(MessageIndex), + + pub fn init(wip: *Wip, gpa: Allocator) !void { + wip.* = .{ + .gpa = gpa, + .string_bytes = .{}, + .extra = .{}, + .root_list = .{}, + }; + + // So that 0 can be used to indicate a null string. + try wip.string_bytes.append(gpa, 0); + + assert(0 == try addExtra(wip, ErrorMessageList{ + .len = 0, + .start = 0, + })); + } + + pub fn deinit(wip: *Wip) void { + const gpa = wip.gpa; + wip.root_list.deinit(gpa); + wip.string_bytes.deinit(gpa); + wip.extra.deinit(gpa); + wip.* = undefined; + } + + pub fn toOwnedBundle(wip: *Wip) !ErrorBundle { + const gpa = wip.gpa; + wip.setExtra(0, ErrorMessageList{ + .len = @intCast(u32, wip.root_list.items.len), + .start = @intCast(u32, wip.extra.items.len), + }); + try wip.extra.appendSlice(gpa, @ptrCast([]const u32, wip.root_list.items)); + wip.root_list.clearAndFree(gpa); + return .{ + .string_bytes = try wip.string_bytes.toOwnedSlice(gpa), + .extra = try wip.extra.toOwnedSlice(gpa), + }; + } + + pub fn tmpBundle(wip: Wip) ErrorBundle { + return .{ + .string_bytes = wip.string_bytes.items, + .extra = wip.extra.items, + }; + } + + pub fn addString(wip: *Wip, s: []const u8) !u32 { + const gpa = wip.gpa; + const index = @intCast(u32, wip.string_bytes.items.len); + try wip.string_bytes.ensureUnusedCapacity(gpa, s.len + 1); + wip.string_bytes.appendSliceAssumeCapacity(s); + wip.string_bytes.appendAssumeCapacity(0); + return index; + } + + pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) !u32 { + const gpa = wip.gpa; + const index = @intCast(u32, wip.string_bytes.items.len); + try wip.string_bytes.writer(gpa).print(fmt, args); + try wip.string_bytes.append(gpa, 0); + return index; + } + + pub fn addRootErrorMessage(wip: *Wip, em: ErrorMessage) !void { + try wip.root_list.ensureUnusedCapacity(wip.gpa, 1); + wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em)); + } + + pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) !MessageIndex { + return @intToEnum(MessageIndex, try addExtra(wip, em)); + } + + pub fn addErrorMessageAssumeCapacity(wip: *Wip, em: ErrorMessage) MessageIndex { + return @intToEnum(MessageIndex, addExtraAssumeCapacity(wip, em)); + } + + pub fn addSourceLocation(wip: *Wip, sl: SourceLocation) !SourceLocationIndex { + return @intToEnum(SourceLocationIndex, try addExtra(wip, sl)); + } + + pub fn addReferenceTrace(wip: *Wip, rt: ReferenceTrace) !void { + _ = try addExtra(wip, rt); + } + + pub fn addBundle(wip: *Wip, other: ErrorBundle) !void { + const gpa = wip.gpa; + + try wip.string_bytes.ensureUnusedCapacity(gpa, other.string_bytes.len); + try wip.extra.ensureUnusedCapacity(gpa, other.extra.len); + + const other_list = other.getMessages(); + + // The ensureUnusedCapacity call above guarantees this. + const notes_start = wip.reserveNotes(@intCast(u32, other_list.len)) catch unreachable; + for (notes_start.., other_list) |note, message| { + wip.extra.items[note] = @enumToInt(wip.addOtherMessage(other, message) catch unreachable); + } + } + + pub fn reserveNotes(wip: *Wip, notes_len: u32) !u32 { + try wip.extra.ensureUnusedCapacity(wip.gpa, notes_len + + notes_len * @typeInfo(ErrorBundle.ErrorMessage).Struct.fields.len); + wip.extra.items.len += notes_len; + return @intCast(u32, wip.extra.items.len - notes_len); + } + + fn addOtherMessage(wip: *Wip, other: ErrorBundle, msg_index: MessageIndex) !MessageIndex { + const other_msg = other.getErrorMessage(msg_index); + const src_loc = try wip.addOtherSourceLocation(other, other_msg.src_loc); + const msg = try wip.addErrorMessage(.{ + .msg = try wip.addString(other.nullTerminatedString(other_msg.msg)), + .count = other_msg.count, + .src_loc = src_loc, + .notes_len = other_msg.notes_len, + }); + const notes_start = try wip.reserveNotes(other_msg.notes_len); + for (notes_start.., other.getNotes(msg_index)) |note, other_note| { + wip.extra.items[note] = @enumToInt(try wip.addOtherMessage(other, other_note)); + } + return msg; + } + + fn addOtherSourceLocation( + wip: *Wip, + other: ErrorBundle, + index: SourceLocationIndex, + ) !SourceLocationIndex { + if (index == .none) return .none; + const other_sl = other.getSourceLocation(index); + + const src_loc = try wip.addSourceLocation(.{ + .src_path = try wip.addString(other.nullTerminatedString(other_sl.src_path)), + .line = other_sl.line, + .column = other_sl.column, + .span_start = other_sl.span_start, + .span_main = other_sl.span_main, + .span_end = other_sl.span_end, + .source_line = try wip.addString(other.nullTerminatedString(other_sl.source_line)), + .reference_trace_len = other_sl.reference_trace_len, + }); + + // TODO: also add the reference trace + + return src_loc; + } + + fn addExtra(wip: *Wip, extra: anytype) Allocator.Error!u32 { + const gpa = wip.gpa; + const fields = @typeInfo(@TypeOf(extra)).Struct.fields; + try wip.extra.ensureUnusedCapacity(gpa, fields.len); + return addExtraAssumeCapacity(wip, extra); + } + + fn addExtraAssumeCapacity(wip: *Wip, extra: anytype) u32 { + const fields = @typeInfo(@TypeOf(extra)).Struct.fields; + const result = @intCast(u32, wip.extra.items.len); + wip.extra.items.len += fields.len; + setExtra(wip, result, extra); + return result; + } + + fn setExtra(wip: *Wip, index: usize, extra: anytype) void { + const fields = @typeInfo(@TypeOf(extra)).Struct.fields; + var i = index; + inline for (fields) |field| { + wip.extra.items[i] = switch (field.type) { + u32 => @field(extra, field.name), + MessageIndex => @enumToInt(@field(extra, field.name)), + SourceLocationIndex => @enumToInt(@field(extra, field.name)), + else => @compileError("bad field type"), + }; + i += 1; + } + } +}; diff --git a/src/Compilation.zig b/src/Compilation.zig index f5a92c66ea..e19dc59445 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2546,9 +2546,9 @@ pub fn totalErrorCount(self: *Compilation) u32 { pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { const gpa = self.gpa; - var bundle: ErrorBundle = undefined; + var bundle: ErrorBundle.Wip = undefined; try bundle.init(gpa); - errdefer bundle.deinit(gpa); + defer bundle.deinit(); { var it = self.failed_c_objects.iterator(); @@ -2557,12 +2557,10 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { const err_msg = entry.value_ptr.*; // TODO these fields will need to be adjusted when we have proper // C error reporting bubbling up. - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.printString(gpa, "unable to build C object: {s}", .{ - err_msg.msg, - }), - .src_loc = try bundle.addSourceLocation(gpa, .{ - .src_path = try bundle.addString(gpa, c_object.src.src_path), + try bundle.addRootErrorMessage(.{ + .msg = try bundle.printString("unable to build C object: {s}", .{err_msg.msg}), + .src_loc = try bundle.addSourceLocation(.{ + .src_path = try bundle.addString(c_object.src.src_path), .span_start = 0, .span_main = 0, .span_end = 1, @@ -2571,49 +2569,46 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { .source_line = 0, // TODO }), }); - bundle.incrementCount(1); } } for (self.lld_errors.items) |lld_error| { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, lld_error.msg), - .notes_len = @intCast(u32, lld_error.context_lines.len), - }); - bundle.incrementCount(1); + const notes_len = @intCast(u32, lld_error.context_lines.len); - for (lld_error.context_lines) |context_line| { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, context_line), - }); + try bundle.addRootErrorMessage(.{ + .msg = try bundle.addString(lld_error.msg), + .notes_len = notes_len, + }); + const notes_start = try bundle.reserveNotes(notes_len); + for (notes_start.., lld_error.context_lines) |note, context_line| { + bundle.extra.items[note] = @enumToInt(bundle.addErrorMessageAssumeCapacity(.{ + .msg = try bundle.addString(context_line), + })); } } for (self.misc_failures.values()) |*value| { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, value.msg), + try bundle.addRootErrorMessage(.{ + .msg = try bundle.addString(value.msg), .notes_len = if (value.children) |b| b.errorMessageCount() else 0, }); - if (value.children) |b| try bundle.addBundle(gpa, b); - bundle.incrementCount(1); + if (value.children) |b| try bundle.addBundle(b); } if (self.alloc_failure_occurred) { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, "memory allocation failure"), + try bundle.addRootErrorMessage(.{ + .msg = try bundle.addString("memory allocation failure"), }); - bundle.incrementCount(1); } if (self.bin_file.options.module) |module| { { var it = module.failed_files.iterator(); while (it.next()) |entry| { if (entry.value_ptr.*) |msg| { - try addModuleErrorMsg(gpa, &bundle, msg.*); + try addModuleErrorMsg(&bundle, msg.*); } else { - // Must be ZIR errors. In order for ZIR errors to exist, the parsing - // must have completed successfully. - const tree = try entry.key_ptr.*.getTree(module.gpa); - assert(tree.errors.len == 0); - try addZirErrorMessages(gpa, &bundle, entry.key_ptr.*); + // Must be ZIR errors. Note that this may include AST errors. + // addZirErrorMessages asserts that the tree is loaded. + _ = try entry.key_ptr.*.getTree(gpa); + try addZirErrorMessages(&bundle, entry.key_ptr.*); } } } @@ -2621,7 +2616,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { var it = module.failed_embed_files.iterator(); while (it.next()) |entry| { const msg = entry.value_ptr.*; - try addModuleErrorMsg(gpa, &bundle, msg.*); + try addModuleErrorMsg(&bundle, msg.*); } } { @@ -2631,21 +2626,20 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { // Skip errors for Decls within files that had a parse failure. // We'll try again once parsing succeeds. if (decl.getFileScope().okToReportErrors()) { - try addModuleErrorMsg(gpa, &bundle, entry.value_ptr.*.*); + try addModuleErrorMsg(&bundle, entry.value_ptr.*.*); if (module.cimport_errors.get(entry.key_ptr.*)) |cimport_errors| for (cimport_errors) |c_error| { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, std.mem.span(c_error.msg)), - .src_loc = if (c_error.path) |some| try bundle.addSourceLocation(gpa, .{ - .src_path = try bundle.addString(gpa, std.mem.span(some)), + try bundle.addRootErrorMessage(.{ + .msg = try bundle.addString(std.mem.span(c_error.msg)), + .src_loc = if (c_error.path) |some| try bundle.addSourceLocation(.{ + .src_path = try bundle.addString(std.mem.span(some)), .span_start = c_error.offset, .span_main = c_error.offset, .span_end = c_error.offset + 1, .line = c_error.line, .column = c_error.column, - .source_line = if (c_error.source_line) |line| try bundle.addString(gpa, std.mem.span(line)) else 0, - }) else 0, + .source_line = if (c_error.source_line) |line| try bundle.addString(std.mem.span(line)) else 0, + }) else .none, }); - bundle.incrementCount(1); }; } } @@ -2657,40 +2651,39 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { // Skip errors for Decls within files that had a parse failure. // We'll try again once parsing succeeds. if (decl.getFileScope().okToReportErrors()) { - try addModuleErrorMsg(gpa, &bundle, entry.value_ptr.*.*); + try addModuleErrorMsg(&bundle, entry.value_ptr.*.*); } } } for (module.failed_exports.values()) |value| { - try addModuleErrorMsg(gpa, &bundle, value.*); + try addModuleErrorMsg(&bundle, value.*); } } - if (bundle.errorMessageCount() == 0) { + if (bundle.root_list.items.len == 0) { if (self.link_error_flags.no_entry_point_found) { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, "no entry point found"), + try bundle.addRootErrorMessage(.{ + .msg = try bundle.addString("no entry point found"), }); - bundle.incrementCount(1); } } if (self.link_error_flags.missing_libc) { - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, "libc not available"), + try bundle.addRootErrorMessage(.{ + .msg = try bundle.addString("libc not available"), .notes_len = 2, }); - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, "run 'zig libc -h' to learn about libc installations"), - }); - try bundle.addErrorMessage(gpa, .{ - .msg = try bundle.addString(gpa, "run 'zig targets' to see the targets for which zig can always provide libc"), - }); - bundle.incrementCount(1); + const notes_start = try bundle.reserveNotes(2); + bundle.extra.items[notes_start + 0] = @enumToInt(try bundle.addErrorMessage(.{ + .msg = try bundle.addString("run 'zig libc -h' to learn about libc installations"), + })); + bundle.extra.items[notes_start + 1] = @enumToInt(try bundle.addErrorMessage(.{ + .msg = try bundle.addString("run 'zig targets' to see the targets for which zig can always provide libc"), + })); } if (self.bin_file.options.module) |module| { - if (bundle.errorMessageCount() == 0 and module.compile_log_decls.count() != 0) { + if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { const keys = module.compile_log_decls.keys(); const values = module.compile_log_decls.values(); // First one will be the error; subsequent ones will be notes. @@ -2699,9 +2692,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { const err_msg = Module.ErrorMsg{ .src_loc = src_loc, .msg = "found compile log statement", - .notes = try self.gpa.alloc(Module.ErrorMsg, module.compile_log_decls.count() - 1), + .notes = try gpa.alloc(Module.ErrorMsg, module.compile_log_decls.count() - 1), }; - defer self.gpa.free(err_msg.notes); + defer gpa.free(err_msg.notes); for (keys[1..], 0..) |key, i| { const note_decl = module.declPtr(key); @@ -2711,25 +2704,26 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { }; } - try addModuleErrorMsg(gpa, &bundle, err_msg); + try addModuleErrorMsg(&bundle, err_msg); } } - assert(self.totalErrorCount() == bundle.errorMessageCount()); + assert(self.totalErrorCount() == bundle.root_list.items.len); - return bundle; + return bundle.toOwnedBundle(); } pub const ErrorNoteHashContext = struct { - eb: *const ErrorBundle, + eb: *const ErrorBundle.Wip, pub fn hash(ctx: ErrorNoteHashContext, key: ErrorBundle.ErrorMessage) u32 { var hasher = std.hash.Wyhash.init(0); + const eb = ctx.eb.tmpBundle(); - hasher.update(ctx.eb.nullTerminatedString(key.msg)); - if (key.src_loc != 0) { - const src = ctx.eb.getSourceLocation(key.src_loc); - hasher.update(ctx.eb.nullTerminatedString(src.src_path)); + hasher.update(eb.nullTerminatedString(key.msg)); + if (key.src_loc != .none) { + const src = eb.getSourceLocation(key.src_loc); + hasher.update(eb.nullTerminatedString(src.src_path)); std.hash.autoHash(&hasher, src.line); std.hash.autoHash(&hasher, src.column); std.hash.autoHash(&hasher, src.span_main); @@ -2745,17 +2739,18 @@ pub const ErrorNoteHashContext = struct { b_index: usize, ) bool { _ = b_index; - const msg_a = ctx.eb.nullTerminatedString(a.msg); - const msg_b = ctx.eb.nullTerminatedString(b.msg); + const eb = ctx.eb.tmpBundle(); + const msg_a = eb.nullTerminatedString(a.msg); + const msg_b = eb.nullTerminatedString(b.msg); if (!std.mem.eql(u8, msg_a, msg_b)) return false; - if (a.src_loc == 0 and b.src_loc == 0) return true; - if (a.src_loc == 0 or b.src_loc == 0) return false; - const src_a = ctx.eb.getSourceLocation(a.src_loc); - const src_b = ctx.eb.getSourceLocation(b.src_loc); + if (a.src_loc == .none and b.src_loc == .none) return true; + if (a.src_loc == .none or b.src_loc == .none) return false; + const src_a = eb.getSourceLocation(a.src_loc); + const src_b = eb.getSourceLocation(b.src_loc); - const src_path_a = ctx.eb.nullTerminatedString(src_a.src_path); - const src_path_b = ctx.eb.nullTerminatedString(src_b.src_path); + const src_path_a = eb.nullTerminatedString(src_a.src_path); + const src_path_b = eb.nullTerminatedString(src_b.src_path); return std.mem.eql(u8, src_path_a, src_path_b) and src_a.line == src_b.line and @@ -2764,16 +2759,16 @@ pub const ErrorNoteHashContext = struct { } }; -pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Module.ErrorMsg) !void { +pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg) !void { + const gpa = eb.gpa; const err_source = module_err_msg.src_loc.file_scope.getSource(gpa) catch |err| { const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa); defer gpa.free(file_path); - try eb.addErrorMessage(gpa, .{ - .msg = try eb.printString(gpa, "unable to load '{s}': {s}", .{ + try eb.addRootErrorMessage(.{ + .msg = try eb.printString("unable to load '{s}': {s}", .{ file_path, @errorName(err), }), }); - eb.incrementCount(1); return; }; const err_span = try module_err_msg.src_loc.span(gpa); @@ -2788,13 +2783,13 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul if (module_reference.hidden != 0) { try ref_traces.append(gpa, .{ .decl_name = module_reference.hidden, - .src_loc = 0, + .src_loc = .none, }); break; } else if (module_reference.decl == null) { try ref_traces.append(gpa, .{ .decl_name = 0, - .src_loc = 0, + .src_loc = .none, }); break; } @@ -2804,9 +2799,9 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa); defer gpa.free(rt_file_path); try ref_traces.append(gpa, .{ - .decl_name = try eb.addString(gpa, std.mem.sliceTo(module_reference.decl.?, 0)), - .src_loc = try eb.addSourceLocation(gpa, .{ - .src_path = try eb.addString(gpa, rt_file_path), + .decl_name = try eb.addString(std.mem.sliceTo(module_reference.decl.?, 0)), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(rt_file_path), .span_start = span.start, .span_main = span.main, .span_end = span.end, @@ -2817,8 +2812,8 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul }); } - const src_loc = try eb.addSourceLocation(gpa, .{ - .src_path = try eb.addString(gpa, file_path), + const src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(file_path), .span_start = err_span.start, .span_main = err_span.main, .span_end = err_span.end, @@ -2827,12 +2822,12 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul .source_line = if (module_err_msg.src_loc.lazy == .entire_file) 0 else - try eb.addString(gpa, err_loc.source_line), + try eb.addString(err_loc.source_line), .reference_trace_len = @intCast(u32, ref_traces.items.len), }); for (ref_traces.items) |rt| { - try eb.addReferenceTrace(gpa, rt); + try eb.addReferenceTrace(rt); } // De-duplicate error notes. The main use case in mind for this is @@ -2848,15 +2843,15 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul defer gpa.free(note_file_path); const gop = try notes.getOrPutContext(gpa, .{ - .msg = try eb.addString(gpa, module_note.msg), - .src_loc = try eb.addSourceLocation(gpa, .{ - .src_path = try eb.addString(gpa, note_file_path), + .msg = try eb.addString(module_note.msg), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(note_file_path), .span_start = span.start, .span_main = span.main, .span_end = span.end, .line = @intCast(u32, loc.line), .column = @intCast(u32, loc.column), - .source_line = if (err_loc.eql(loc)) 0 else try eb.addString(gpa, loc.source_line), + .source_line = if (err_loc.eql(loc)) 0 else try eb.addString(loc.source_line), }), }, .{ .eb = eb }); if (gop.found_existing) { @@ -2864,24 +2859,28 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul } } - try eb.addErrorMessage(gpa, .{ - .msg = try eb.addString(gpa, module_err_msg.msg), - .src_loc = src_loc, - .notes_len = @intCast(u32, notes.entries.len), - }); - eb.incrementCount(1); + const notes_len = @intCast(u32, notes.entries.len); - for (notes.keys()) |note| { - try eb.addErrorMessage(gpa, note); + try eb.addRootErrorMessage(.{ + .msg = try eb.addString(module_err_msg.msg), + .src_loc = src_loc, + .notes_len = notes_len, + }); + + const notes_start = try eb.reserveNotes(notes_len); + + for (notes_start.., notes.keys()) |i, note| { + eb.extra.items[i] = @enumToInt(try eb.addErrorMessage(note)); } } -pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) !void { +pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void { assert(file.zir_loaded); assert(file.tree_loaded); assert(file.source_loaded); const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)]; assert(payload_index != 0); + const gpa = eb.gpa; const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index); const items_len = header.data.items_len; @@ -2900,14 +2899,30 @@ pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) }; const err_loc = std.zig.findLineColumn(file.source, err_span.main); - var notes: []ErrorBundle.ErrorMessage = &.{}; - defer gpa.free(notes); + { + const msg = file.zir.nullTerminatedString(item.data.msg); + const src_path = try file.fullPath(gpa); + defer gpa.free(src_path); + try eb.addRootErrorMessage(.{ + .msg = try eb.addString(msg), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(src_path), + .span_start = err_span.start, + .span_main = err_span.main, + .span_end = err_span.end, + .line = @intCast(u32, err_loc.line), + .column = @intCast(u32, err_loc.column), + .source_line = try eb.addString(err_loc.source_line), + }), + .notes_len = item.data.notes, + }); + } if (item.data.notes != 0) { + const notes_start = try eb.reserveNotes(item.data.notes); const block = file.zir.extraData(Zir.Inst.Block, item.data.notes); const body = file.zir.extra[block.end..][0..block.data.body_len]; - notes = try gpa.alloc(ErrorBundle.ErrorMessage, body.len); - for (notes, body) |*note, body_elem| { + for (notes_start.., body) |note_i, body_elem| { const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); const msg = file.zir.nullTerminatedString(note_item.data.msg); const span = blk: { @@ -2923,10 +2938,10 @@ pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) const src_path = try file.fullPath(gpa); defer gpa.free(src_path); - note.* = .{ - .msg = try eb.addString(gpa, msg), - .src_loc = try eb.addSourceLocation(gpa, .{ - .src_path = try eb.addString(gpa, src_path), + eb.extra.items[note_i] = @enumToInt(try eb.addErrorMessage(.{ + .msg = try eb.addString(msg), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(src_path), .span_start = span.start, .span_main = span.main, .span_end = span.end, @@ -2935,35 +2950,13 @@ pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) .source_line = if (loc.eql(err_loc)) 0 else - try eb.addString(gpa, loc.source_line), + try eb.addString(loc.source_line), }), .notes_len = 0, // TODO rework this function to be recursive - }; + })); } } - - const msg = file.zir.nullTerminatedString(item.data.msg); - const src_path = try file.fullPath(gpa); - defer gpa.free(src_path); - try eb.addErrorMessage(gpa, .{ - .msg = try eb.addString(gpa, msg), - .src_loc = try eb.addSourceLocation(gpa, .{ - .src_path = try eb.addString(gpa, src_path), - .span_start = err_span.start, - .span_main = err_span.main, - .span_end = err_span.end, - .line = @intCast(u32, err_loc.line), - .column = @intCast(u32, err_loc.column), - .source_line = try eb.addString(gpa, err_loc.source_line), - }), - .notes_len = @intCast(u32, notes.len), - }); - - for (notes) |note| { - try eb.addErrorMessage(gpa, note); - } } - eb.incrementCount(items_len); } pub fn getCompileLogOutput(self: *Compilation) []const u8 { diff --git a/src/Package.zig b/src/Package.zig index febcc51788..d26daf5a0c 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -225,7 +225,7 @@ pub fn fetchAndAddDependencies( dependencies_source: *std.ArrayList(u8), build_roots_source: *std.ArrayList(u8), name_prefix: []const u8, - error_bundle: *std.zig.ErrorBundle, + error_bundle: *std.zig.ErrorBundle.Wip, all_modules: *AllModules, ) !void { const max_bytes = 10 * 1024 * 1024; @@ -260,13 +260,12 @@ pub fn fetchAndAddDependencies( if (manifest.errors.len > 0) { const file_path = try directory.join(arena, &.{Manifest.basename}); for (manifest.errors) |msg| { - try Report.addErrorMessage(gpa, ast, file_path, error_bundle, 0, msg); + try Report.addErrorMessage(ast, file_path, error_bundle, 0, msg); } return error.PackageFetchFailed; } const report: Report = .{ - .gpa = gpa, .ast = &ast, .directory = directory, .error_bundle = error_bundle, @@ -343,10 +342,9 @@ pub fn createFilePkg( } const Report = struct { - gpa: Allocator, ast: *const std.zig.Ast, directory: Compilation.Directory, - error_bundle: *std.zig.ErrorBundle, + error_bundle: *std.zig.ErrorBundle.Wip, fn fail( report: Report, @@ -354,7 +352,7 @@ const Report = struct { comptime fmt_string: []const u8, fmt_args: anytype, ) error{ PackageFetchFailed, OutOfMemory } { - const gpa = report.gpa; + const gpa = report.error_bundle.gpa; const file_path = try report.directory.join(gpa, &.{Manifest.basename}); defer gpa.free(file_path); @@ -362,7 +360,7 @@ const Report = struct { const msg = try std.fmt.allocPrint(gpa, fmt_string, fmt_args); defer gpa.free(msg); - try addErrorMessage(report.gpa, report.ast.*, file_path, report.error_bundle, 0, .{ + try addErrorMessage(report.ast.*, file_path, report.error_bundle, 0, .{ .tok = tok, .off = 0, .msg = msg, @@ -372,30 +370,28 @@ const Report = struct { } fn addErrorMessage( - gpa: Allocator, ast: std.zig.Ast, file_path: []const u8, - eb: *std.zig.ErrorBundle, + eb: *std.zig.ErrorBundle.Wip, notes_len: u32, msg: Manifest.ErrorMessage, ) error{OutOfMemory}!void { const token_starts = ast.tokens.items(.start); const start_loc = ast.tokenLocation(0, msg.tok); - try eb.addErrorMessage(gpa, .{ - .msg = try eb.addString(gpa, msg.msg), - .src_loc = try eb.addSourceLocation(gpa, .{ - .src_path = try eb.addString(gpa, file_path), + try eb.addRootErrorMessage(.{ + .msg = try eb.addString(msg.msg), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(file_path), .span_start = token_starts[msg.tok], .span_end = @intCast(u32, token_starts[msg.tok] + ast.tokenSlice(msg.tok).len), .span_main = token_starts[msg.tok] + msg.off, .line = @intCast(u32, start_loc.line), .column = @intCast(u32, start_loc.column), - .source_line = try eb.addString(gpa, ast.source[start_loc.line_start..start_loc.line_end]), + .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]), }), .notes_len = notes_len, }); - eb.incrementCount(1); } }; @@ -526,14 +522,16 @@ fn fetchAndUnpack( defer gpa.free(file_path); const eb = report.error_bundle; - try Report.addErrorMessage(gpa, report.ast.*, file_path, eb, 1, .{ + const notes_len = 1; + try Report.addErrorMessage(report.ast.*, file_path, eb, notes_len, .{ .tok = dep.url_tok, .off = 0, .msg = "url field is missing corresponding hash field", }); - try eb.addErrorMessage(gpa, .{ - .msg = try eb.printString(gpa, "expected .hash = \"{s}\",", .{&actual_hex}), - }); + const notes_start = try eb.reserveNotes(notes_len); + eb.extra.items[notes_start] = @enumToInt(try eb.addErrorMessage(.{ + .msg = try eb.printString("expected .hash = \"{s}\",", .{&actual_hex}), + })); return error.PackageFetchFailed; } diff --git a/src/Sema.zig b/src/Sema.zig index 237936547e..03ebbbdbac 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2215,11 +2215,12 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { if (crash_report.is_enabled and sema.mod.comp.debug_compile_errors) { if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation; - var errors: std.zig.ErrorBundle = undefined; - errors.init(gpa) catch unreachable; - Compilation.addModuleErrorMsg(gpa, &errors, err_msg.*) catch unreachable; + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + wip_errors.init(gpa) catch unreachable; + Compilation.addModuleErrorMsg(&wip_errors, err_msg.*) catch unreachable; std.debug.print("compile error during Sema:\n", .{}); - errors.renderToStdErr(.no_color); + var error_bundle = wip_errors.toOwnedBundle() catch unreachable; + error_bundle.renderToStdErr(.no_color); crash_report.compilerPanic("unexpected compile error occurred", null, null); } diff --git a/src/main.zig b/src/main.zig index 14b63017e5..0a16aa5a46 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4436,9 +4436,9 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi var all_modules: Package.AllModules = .{}; defer all_modules.deinit(gpa); - var errors: std.zig.ErrorBundle = undefined; - try errors.init(gpa); - defer errors.deinit(gpa); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); // Here we borrow main package's table and will replace it with a fresh // one after this process completes. @@ -4453,15 +4453,17 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi &dependencies_source, &build_roots_source, "", - &errors, + &wip_errors, &all_modules, ); - if (errors.errorMessageCount() > 0) { + if (wip_errors.root_list.items.len > 0) { const ttyconf: std.debug.TTY.Config = switch (color) { .auto => std.debug.detectTTYConfig(std.io.getStdErr()), .on => .escape_codes, .off => .no_color, }; + var errors = try wip_errors.toOwnedBundle(); + defer errors.deinit(gpa); errors.renderToStdErr(ttyconf); process.exit(1); } @@ -4721,16 +4723,18 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void defer file.zir.deinit(gpa); if (file.zir.hasCompileErrors()) { - var errors: std.zig.ErrorBundle = undefined; - try errors.init(gpa); - defer errors.deinit(gpa); - try Compilation.addZirErrorMessages(gpa, &errors, &file); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try Compilation.addZirErrorMessages(&wip_errors, &file); const ttyconf: std.debug.TTY.Config = switch (color) { .auto => std.debug.detectTTYConfig(std.io.getStdErr()), .on => .escape_codes, .off => .no_color, }; - errors.renderToStdErr(ttyconf); + var error_bundle = try wip_errors.toOwnedBundle(); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(ttyconf); has_ast_error = true; } } @@ -4930,16 +4934,18 @@ fn fmtPathFile( defer file.zir.deinit(gpa); if (file.zir.hasCompileErrors()) { - var errors: std.zig.ErrorBundle = undefined; - try errors.init(gpa); - defer errors.deinit(gpa); - try Compilation.addZirErrorMessages(gpa, &errors, &file); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try Compilation.addZirErrorMessages(&wip_errors, &file); const ttyconf: std.debug.TTY.Config = switch (fmt.color) { .auto => std.debug.detectTTYConfig(std.io.getStdErr()), .on => .escape_codes, .off => .no_color, }; - errors.renderToStdErr(ttyconf); + var error_bundle = try wip_errors.toOwnedBundle(); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(ttyconf); fmt.any_error = true; } } @@ -4968,17 +4974,19 @@ fn fmtPathFile( } fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { - var error_bundle: std.zig.ErrorBundle = undefined; - try error_bundle.init(gpa); - defer error_bundle.deinit(gpa); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); - try putAstErrorsIntoBundle(gpa, tree, path, &error_bundle); + try putAstErrorsIntoBundle(gpa, tree, path, &wip_errors); const ttyconf: std.debug.TTY.Config = switch (color) { .auto => std.debug.detectTTYConfig(std.io.getStdErr()), .on => .escape_codes, .off => .no_color, }; + var error_bundle = try wip_errors.toOwnedBundle(); + defer error_bundle.deinit(gpa); error_bundle.renderToStdErr(ttyconf); } @@ -4986,7 +4994,7 @@ pub fn putAstErrorsIntoBundle( gpa: Allocator, tree: Ast, path: []const u8, - error_bundle: *std.zig.ErrorBundle, + wip_errors: *std.zig.ErrorBundle.Wip, ) !void { var file: Module.File = .{ .status = .never_loaded, @@ -5013,7 +5021,7 @@ pub fn putAstErrorsIntoBundle( file.zir_loaded = true; defer file.zir.deinit(gpa); - try Compilation.addZirErrorMessages(gpa, error_bundle, &file); + try Compilation.addZirErrorMessages(wip_errors, &file); } pub const info_zen = @@ -5595,16 +5603,18 @@ pub fn cmdAstCheck( defer file.zir.deinit(gpa); if (file.zir.hasCompileErrors()) { - var errors: std.zig.ErrorBundle = undefined; - try errors.init(gpa); - defer errors.deinit(gpa); - try Compilation.addZirErrorMessages(gpa, &errors, &file); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try Compilation.addZirErrorMessages(&wip_errors, &file); const ttyconf: std.debug.TTY.Config = switch (color) { .auto => std.debug.detectTTYConfig(std.io.getStdErr()), .on => .escape_codes, .off => .no_color, }; - errors.renderToStdErr(ttyconf); + var error_bundle = try wip_errors.toOwnedBundle(); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(ttyconf); process.exit(1); } @@ -5719,12 +5729,14 @@ pub fn cmdChangelist( defer file.zir.deinit(gpa); if (file.zir.hasCompileErrors()) { - var errors: std.zig.ErrorBundle = undefined; - try errors.init(gpa); - defer errors.deinit(gpa); - try Compilation.addZirErrorMessages(gpa, &errors, &file); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try Compilation.addZirErrorMessages(&wip_errors, &file); const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); - errors.renderToStdErr(ttyconf); + var error_bundle = try wip_errors.toOwnedBundle(); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(ttyconf); process.exit(1); } @@ -5758,12 +5770,14 @@ pub fn cmdChangelist( file.zir_loaded = true; if (file.zir.hasCompileErrors()) { - var errors: std.zig.ErrorBundle = undefined; - try errors.init(gpa); - defer errors.deinit(gpa); - try Compilation.addZirErrorMessages(gpa, &errors, &file); + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try Compilation.addZirErrorMessages(&wip_errors, &file); const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); - errors.renderToStdErr(ttyconf); + var error_bundle = try wip_errors.toOwnedBundle(); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(ttyconf); process.exit(1); } diff --git a/src/test.zig b/src/test.zig index ce87742606..663c4f1aff 100644 --- a/src/test.zig +++ b/src/test.zig @@ -1242,7 +1242,7 @@ pub const TestContext = struct { defer self.gpa.free(zig_lib_directory.path.?); var aux_thread_pool: ThreadPool = undefined; - try aux_thread_pool.init(self.gpa); + try aux_thread_pool.init(.{ .allocator = self.gpa }); defer aux_thread_pool.deinit(); // Use the same global cache dir for all the tests, such that we for example don't have to @@ -1614,23 +1614,8 @@ pub const TestContext = struct { if (update.case != .Error) { var all_errors = try comp.getAllErrorsAlloc(); defer all_errors.deinit(allocator); - if (all_errors.list.len != 0) { - print( - "\nCase '{s}': unexpected errors at update_index={d}:\n{s}\n", - .{ case.name, update_index, hr }, - ); - for (all_errors.list) |err_msg| { - switch (err_msg) { - .src => |src| { - print("{s}:{d}:{d}: error: {s}\n{s}\n", .{ - src.src_path, src.line + 1, src.column + 1, src.msg, hr, - }); - }, - .plain => |plain| { - print("error: {s}\n{s}\n", .{ plain.msg, hr }); - }, - } - } + if (all_errors.errorMessageCount() > 0) { + all_errors.renderToStdErr(std.debug.detectTTYConfig(std.io.getStdErr())); // TODO print generated C code return error.UnexpectedCompileErrors; }