| author | |
| committer | |
| log | 6f717b18f05ba02439603e0987e9c9551fbadedb |
| tree | c95613ef714eed338372d1947c0132808beffab4 |
| parent | 572cb24d1a4f70c662ddf17df72d27dec44bc4fc |
* Separate into a "WIP" struct and a "finished" struct.
* Use a bit of indirection for error notes to simplify ergonomics of
this data structure.6 files changed, 425 insertions(+), 390 deletions(-)
lib/std/zig/ErrorBundle.zig+227-183| ... | ... | @@ -3,24 +3,22 @@ |
| 3 | 3 | //! is used to collect all the errors from the various places into one |
| 4 | 4 | //! convenient place for API users to consume. |
| 5 | 5 | |
| 6 | string_bytes: std.ArrayListUnmanaged(u8), | |
| 7 | /// The first thing in this array is a ErrorMessageListIndex. | |
| 8 | extra: std.ArrayListUnmanaged(u32), | |
| 6 | string_bytes: []const u8, | |
| 7 | /// The first thing in this array is an `ErrorMessageList`. | |
| 8 | extra: []const u32, | |
| 9 | 9 | |
| 10 | 10 | // An index into `extra` pointing at an `ErrorMessage`. |
| 11 | 11 | pub const MessageIndex = enum(u32) { |
| 12 | 12 | _, |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | /// After the header is: | |
| 16 | /// * string_bytes | |
| 17 | /// * extra (little endian) | |
| 18 | pub const Header = struct { | |
| 19 | string_bytes_len: u32, | |
| 20 | extra_len: u32, | |
| 15 | // An index into `extra` pointing at an `SourceLocation`. | |
| 16 | pub const SourceLocationIndex = enum(u32) { | |
| 17 | none = 0, | |
| 18 | _, | |
| 21 | 19 | }; |
| 22 | 20 | |
| 23 | /// Trailing: ErrorMessage for each len | |
| 21 | /// There will be a MessageIndex for each len at start. | |
| 24 | 22 | pub const ErrorMessageList = struct { |
| 25 | 23 | len: u32, |
| 26 | 24 | start: u32, |
| ... | ... | @@ -46,14 +44,13 @@ pub const SourceLocation = struct { |
| 46 | 44 | }; |
| 47 | 45 | |
| 48 | 46 | /// Trailing: |
| 49 | /// * ErrorMessage for each notes_len. | |
| 47 | /// * MessageIndex for each notes_len. | |
| 50 | 48 | pub const ErrorMessage = struct { |
| 51 | 49 | /// null terminated string index |
| 52 | 50 | msg: u32, |
| 53 | 51 | /// Usually one, but incremented for redundant messages. |
| 54 | 52 | count: u32 = 1, |
| 55 | /// 0 or the index into extra of a SourceLocation | |
| 56 | src_loc: u32 = 0, | |
| 53 | src_loc: SourceLocationIndex = .none, | |
| 57 | 54 | notes_len: u32 = 0, |
| 58 | 55 | }; |
| 59 | 56 | |
| ... | ... | @@ -65,170 +62,41 @@ pub const ReferenceTrace = struct { |
| 65 | 62 | decl_name: u32, |
| 66 | 63 | /// Index into extra of a SourceLocation |
| 67 | 64 | /// If this is 0, this is the sentinel ReferenceTrace element. |
| 68 | src_loc: u32, | |
| 65 | src_loc: SourceLocationIndex, | |
| 69 | 66 | }; |
| 70 | 67 | |
| 71 | pub fn init(eb: *ErrorBundle, gpa: Allocator) !void { | |
| 72 | eb.* = .{ | |
| 73 | .string_bytes = .{}, | |
| 74 | .extra = .{}, | |
| 75 | }; | |
| 76 | ||
| 77 | // So that 0 can be used to indicate a null string. | |
| 78 | try eb.string_bytes.append(gpa, 0); | |
| 79 | ||
| 80 | _ = try addExtra(eb, gpa, ErrorMessageList{ | |
| 81 | .len = 0, | |
| 82 | .start = 0, | |
| 83 | }); | |
| 84 | } | |
| 85 | ||
| 86 | 68 | pub fn deinit(eb: *ErrorBundle, gpa: Allocator) void { |
| 87 | eb.string_bytes.deinit(gpa); | |
| 88 | eb.extra.deinit(gpa); | |
| 69 | gpa.free(eb.string_bytes); | |
| 70 | gpa.free(eb.extra); | |
| 89 | 71 | eb.* = undefined; |
| 90 | 72 | } |
| 91 | 73 | |
| 92 | pub fn addString(eb: *ErrorBundle, gpa: Allocator, s: []const u8) !u32 { | |
| 93 | const index = @intCast(u32, eb.string_bytes.items.len); | |
| 94 | try eb.string_bytes.ensureUnusedCapacity(gpa, s.len + 1); | |
| 95 | eb.string_bytes.appendSliceAssumeCapacity(s); | |
| 96 | eb.string_bytes.appendAssumeCapacity(0); | |
| 97 | return index; | |
| 98 | } | |
| 99 | ||
| 100 | pub fn printString(eb: *ErrorBundle, gpa: Allocator, comptime fmt: []const u8, args: anytype) !u32 { | |
| 101 | const index = @intCast(u32, eb.string_bytes.items.len); | |
| 102 | try eb.string_bytes.writer(gpa).print(fmt, args); | |
| 103 | try eb.string_bytes.append(gpa, 0); | |
| 104 | return index; | |
| 105 | } | |
| 106 | ||
| 107 | pub fn addErrorMessage(eb: *ErrorBundle, gpa: Allocator, em: ErrorMessage) !void { | |
| 108 | if (eb.errorMessageCount() == 0) { | |
| 109 | eb.setStartIndex(@intCast(u32, eb.extra.items.len)); | |
| 110 | } | |
| 111 | _ = try addExtra(eb, gpa, em); | |
| 112 | } | |
| 113 | ||
| 114 | pub fn addSourceLocation(eb: *ErrorBundle, gpa: Allocator, sl: SourceLocation) !u32 { | |
| 115 | return addExtra(eb, gpa, sl); | |
| 116 | } | |
| 117 | ||
| 118 | pub fn addReferenceTrace(eb: *ErrorBundle, gpa: Allocator, rt: ReferenceTrace) !void { | |
| 119 | _ = try addExtra(eb, gpa, rt); | |
| 120 | } | |
| 121 | ||
| 122 | pub fn addBundle(eb: *ErrorBundle, gpa: Allocator, other: ErrorBundle) !void { | |
| 123 | // Skip over the initial ErrorMessageList len field. | |
| 124 | const root_fields_len = @typeInfo(ErrorMessageList).Struct.fields.len; | |
| 125 | const other_list = other.extraData(ErrorMessageList, 0).data; | |
| 126 | const other_extra = other.extra.items[root_fields_len..]; | |
| 127 | ||
| 128 | try eb.string_bytes.ensureUnusedCapacity(gpa, other.string_bytes.items.len); | |
| 129 | try eb.extra.ensureUnusedCapacity(gpa, other_extra.len); | |
| 130 | ||
| 131 | const new_string_base = @intCast(u32, eb.string_bytes.items.len); | |
| 132 | const new_data_base = @intCast(u32, eb.extra.items.len - root_fields_len); | |
| 133 | ||
| 134 | eb.string_bytes.appendSliceAssumeCapacity(other.string_bytes.items); | |
| 135 | eb.extra.appendSliceAssumeCapacity(other_extra); | |
| 136 | ||
| 137 | // Now we must offset the string indexes and extra indexes of the newly | |
| 138 | // added extra. | |
| 139 | var index = new_data_base + other_list.start; | |
| 140 | for (0..other_list.len) |_| { | |
| 141 | index = try patchMessage(eb, index, new_string_base, new_data_base); | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | fn patchMessage(eb: *ErrorBundle, msg_idx: usize, new_string_base: u32, new_data_base: u32) !u32 { | |
| 146 | var msg = eb.extraData(ErrorMessage, msg_idx); | |
| 147 | if (msg.data.msg != 0) msg.data.msg += new_string_base; | |
| 148 | if (msg.data.src_loc != 0) msg.data.src_loc += new_data_base; | |
| 149 | eb.setExtra(msg_idx, msg.data); | |
| 150 | ||
| 151 | try patchSrcLoc(eb, msg.data.src_loc, new_string_base, new_data_base); | |
| 152 | ||
| 153 | var index = @intCast(u32, msg.end); | |
| 154 | for (0..msg.data.notes_len) |_| { | |
| 155 | index = try patchMessage(eb, index, new_string_base, new_data_base); | |
| 156 | } | |
| 157 | return index; | |
| 158 | } | |
| 159 | ||
| 160 | fn patchSrcLoc(eb: *ErrorBundle, idx: usize, new_string_base: u32, new_data_base: u32) !void { | |
| 161 | if (idx == 0) return; | |
| 162 | ||
| 163 | var src_loc = eb.extraData(SourceLocation, idx); | |
| 164 | if (src_loc.data.src_path != 0) src_loc.data.src_path += new_string_base; | |
| 165 | if (src_loc.data.source_line != 0) src_loc.data.source_line += new_string_base; | |
| 166 | eb.setExtra(idx, src_loc.data); | |
| 167 | ||
| 168 | var index = src_loc.end; | |
| 169 | for (0..src_loc.data.reference_trace_len) |_| { | |
| 170 | var ref_trace = eb.extraData(ReferenceTrace, index); | |
| 171 | if (ref_trace.data.decl_name != 0) ref_trace.data.decl_name += new_string_base; | |
| 172 | if (ref_trace.data.src_loc != 0) ref_trace.data.src_loc += new_data_base; | |
| 173 | eb.setExtra(index, ref_trace.data); | |
| 174 | try patchSrcLoc(eb, ref_trace.data.src_loc, new_string_base, new_data_base); | |
| 175 | index = ref_trace.end; | |
| 176 | } | |
| 177 | } | |
| 178 | ||
| 179 | fn addExtra(eb: *ErrorBundle, gpa: Allocator, extra: anytype) Allocator.Error!u32 { | |
| 180 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; | |
| 181 | try eb.extra.ensureUnusedCapacity(gpa, fields.len); | |
| 182 | return addExtraAssumeCapacity(eb, extra); | |
| 183 | } | |
| 184 | ||
| 185 | fn addExtraAssumeCapacity(eb: *ErrorBundle, extra: anytype) u32 { | |
| 186 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; | |
| 187 | const result = @intCast(u32, eb.extra.items.len); | |
| 188 | eb.extra.items.len += fields.len; | |
| 189 | setExtra(eb, result, extra); | |
| 190 | return result; | |
| 191 | } | |
| 192 | ||
| 193 | fn setExtra(eb: *ErrorBundle, index: usize, extra: anytype) void { | |
| 194 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; | |
| 195 | var i = index; | |
| 196 | inline for (fields) |field| { | |
| 197 | eb.extra.items[i] = switch (field.type) { | |
| 198 | u32 => @field(extra, field.name), | |
| 199 | else => @compileError("bad field type"), | |
| 200 | }; | |
| 201 | i += 1; | |
| 202 | } | |
| 203 | } | |
| 204 | ||
| 205 | 74 | pub fn errorMessageCount(eb: ErrorBundle) u32 { |
| 206 | return eb.extra.items[0]; | |
| 207 | } | |
| 208 | ||
| 209 | pub fn setErrorMessageCount(eb: *ErrorBundle, count: u32) void { | |
| 210 | eb.extra.items[0] = count; | |
| 75 | return eb.getErrorMessageList().len; | |
| 211 | 76 | } |
| 212 | 77 | |
| 213 | pub fn incrementCount(eb: *ErrorBundle, delta: u32) void { | |
| 214 | eb.extra.items[0] += delta; | |
| 78 | pub fn getErrorMessageList(eb: ErrorBundle) ErrorMessageList { | |
| 79 | return eb.extraData(ErrorMessageList, 0).data; | |
| 215 | 80 | } |
| 216 | 81 | |
| 217 | pub fn getStartIndex(eb: ErrorBundle) u32 { | |
| 218 | return eb.extra.items[1]; | |
| 219 | } | |
| 220 | ||
| 221 | pub fn setStartIndex(eb: *ErrorBundle, index: u32) void { | |
| 222 | eb.extra.items[1] = index; | |
| 82 | pub fn getMessages(eb: ErrorBundle) []const MessageIndex { | |
| 83 | const list = eb.getErrorMessageList(); | |
| 84 | return @ptrCast([]const MessageIndex, eb.extra[list.start..][0..list.len]); | |
| 223 | 85 | } |
| 224 | 86 | |
| 225 | 87 | pub fn getErrorMessage(eb: ErrorBundle, index: MessageIndex) ErrorMessage { |
| 226 | 88 | return eb.extraData(ErrorMessage, @enumToInt(index)).data; |
| 227 | 89 | } |
| 228 | 90 | |
| 229 | pub fn getSourceLocation(eb: ErrorBundle, index: u32) SourceLocation { | |
| 230 | assert(index != 0); | |
| 231 | return eb.extraData(SourceLocation, index).data; | |
| 91 | pub fn getSourceLocation(eb: ErrorBundle, index: SourceLocationIndex) SourceLocation { | |
| 92 | assert(index != .none); | |
| 93 | return eb.extraData(SourceLocation, @enumToInt(index)).data; | |
| 94 | } | |
| 95 | ||
| 96 | pub fn getNotes(eb: ErrorBundle, index: MessageIndex) []const MessageIndex { | |
| 97 | const notes_len = eb.getErrorMessage(index).notes_len; | |
| 98 | const start = @enumToInt(index) + @typeInfo(ErrorMessage).Struct.fields.len; | |
| 99 | return @ptrCast([]const MessageIndex, eb.extra[start..][0..notes_len]); | |
| 232 | 100 | } |
| 233 | 101 | |
| 234 | 102 | /// 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, |
| 239 | 107 | var result: T = undefined; |
| 240 | 108 | inline for (fields) |field| { |
| 241 | 109 | @field(result, field.name) = switch (field.type) { |
| 242 | u32 => eb.extra.items[i], | |
| 110 | u32 => eb.extra[i], | |
| 111 | MessageIndex => @intToEnum(MessageIndex, eb.extra[i]), | |
| 112 | SourceLocationIndex => @intToEnum(SourceLocationIndex, eb.extra[i]), | |
| 243 | 113 | else => @compileError("bad field type"), |
| 244 | 114 | }; |
| 245 | 115 | i += 1; |
| ... | ... | @@ -252,7 +122,7 @@ fn extraData(eb: ErrorBundle, comptime T: type, index: usize) struct { data: T, |
| 252 | 122 | |
| 253 | 123 | /// Given an index into `string_bytes` returns the null-terminated string found there. |
| 254 | 124 | pub fn nullTerminatedString(eb: ErrorBundle, index: usize) [:0]const u8 { |
| 255 | const string_bytes = eb.string_bytes.items; | |
| 125 | const string_bytes = eb.string_bytes; | |
| 256 | 126 | var end: usize = index; |
| 257 | 127 | while (string_bytes[end] != 0) { |
| 258 | 128 | end += 1; |
| ... | ... | @@ -272,28 +142,25 @@ pub fn renderToWriter( |
| 272 | 142 | ttyconf: std.debug.TTY.Config, |
| 273 | 143 | writer: anytype, |
| 274 | 144 | ) anyerror!void { |
| 275 | const list = eb.extraData(ErrorMessageList, 0).data; | |
| 276 | var index: usize = list.start; | |
| 277 | for (0..list.len) |_| { | |
| 278 | const err_msg = eb.extraData(ErrorMessage, index); | |
| 279 | index = try renderErrorMessageToWriter(eb, err_msg.data, err_msg.end, ttyconf, writer, "error", .Red, 0); | |
| 145 | for (eb.getMessages()) |err_msg| { | |
| 146 | try renderErrorMessageToWriter(eb, err_msg, ttyconf, writer, "error", .Red, 0); | |
| 280 | 147 | } |
| 281 | 148 | } |
| 282 | 149 | |
| 283 | 150 | fn renderErrorMessageToWriter( |
| 284 | 151 | eb: ErrorBundle, |
| 285 | err_msg: ErrorMessage, | |
| 286 | end_index: usize, | |
| 152 | err_msg_index: MessageIndex, | |
| 287 | 153 | ttyconf: std.debug.TTY.Config, |
| 288 | 154 | stderr: anytype, |
| 289 | 155 | kind: []const u8, |
| 290 | 156 | color: std.debug.TTY.Color, |
| 291 | 157 | indent: usize, |
| 292 | ) anyerror!usize { | |
| 158 | ) anyerror!void { | |
| 293 | 159 | var counting_writer = std.io.countingWriter(stderr); |
| 294 | 160 | const counting_stderr = counting_writer.writer(); |
| 295 | if (err_msg.src_loc != 0) { | |
| 296 | const src = eb.extraData(SourceLocation, err_msg.src_loc); | |
| 161 | const err_msg = eb.getErrorMessage(err_msg_index); | |
| 162 | if (err_msg.src_loc != .none) { | |
| 163 | const src = eb.extraData(SourceLocation, @enumToInt(err_msg.src_loc)); | |
| 297 | 164 | try counting_stderr.writeByteNTimes(' ', indent); |
| 298 | 165 | try ttyconf.setColor(stderr, .Bold); |
| 299 | 166 | try counting_stderr.print("{s}:{d}:{d}: ", .{ |
| ... | ... | @@ -337,10 +204,8 @@ fn renderErrorMessageToWriter( |
| 337 | 204 | try stderr.writeByte('\n'); |
| 338 | 205 | try ttyconf.setColor(stderr, .Reset); |
| 339 | 206 | } |
| 340 | var index = end_index; | |
| 341 | for (0..err_msg.notes_len) |_| { | |
| 342 | const note = eb.extraData(ErrorMessage, index); | |
| 343 | index = try renderErrorMessageToWriter(eb, note.data, note.end, ttyconf, stderr, "note", .Cyan, indent); | |
| 207 | for (eb.getNotes(err_msg_index)) |note| { | |
| 208 | try renderErrorMessageToWriter(eb, note, ttyconf, stderr, "note", .Cyan, indent); | |
| 344 | 209 | } |
| 345 | 210 | if (src.data.reference_trace_len > 0) { |
| 346 | 211 | try ttyconf.setColor(stderr, .Reset); |
| ... | ... | @@ -350,7 +215,7 @@ fn renderErrorMessageToWriter( |
| 350 | 215 | for (0..src.data.reference_trace_len) |_| { |
| 351 | 216 | const ref_trace = eb.extraData(ReferenceTrace, ref_index); |
| 352 | 217 | ref_index = ref_trace.end; |
| 353 | if (ref_trace.data.src_loc != 0) { | |
| 218 | if (ref_trace.data.src_loc != .none) { | |
| 354 | 219 | const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); |
| 355 | 220 | try stderr.print(" {s}: {s}:{d}:{d}\n", .{ |
| 356 | 221 | eb.nullTerminatedString(ref_trace.data.decl_name), |
| ... | ... | @@ -374,7 +239,6 @@ fn renderErrorMessageToWriter( |
| 374 | 239 | try stderr.writeByte('\n'); |
| 375 | 240 | try ttyconf.setColor(stderr, .Reset); |
| 376 | 241 | } |
| 377 | return index; | |
| 378 | 242 | } else { |
| 379 | 243 | try ttyconf.setColor(stderr, color); |
| 380 | 244 | try stderr.writeByteNTimes(' ', indent); |
| ... | ... | @@ -390,12 +254,9 @@ fn renderErrorMessageToWriter( |
| 390 | 254 | try stderr.print(" ({d} times)\n", .{err_msg.count}); |
| 391 | 255 | } |
| 392 | 256 | try ttyconf.setColor(stderr, .Reset); |
| 393 | var index = end_index; | |
| 394 | for (0..err_msg.notes_len) |_| { | |
| 395 | const note = eb.extraData(ErrorMessage, index); | |
| 396 | index = try renderErrorMessageToWriter(eb, note.data, note.end, ttyconf, stderr, "note", .Cyan, indent + 4); | |
| 257 | for (eb.getNotes(err_msg_index)) |note| { | |
| 258 | try renderErrorMessageToWriter(eb, note, ttyconf, stderr, "note", .Cyan, indent + 4); | |
| 397 | 259 | } |
| 398 | return index; | |
| 399 | 260 | } |
| 400 | 261 | } |
| 401 | 262 | |
| ... | ... | @@ -417,3 +278,186 @@ const std = @import("std"); |
| 417 | 278 | const ErrorBundle = @This(); |
| 418 | 279 | const Allocator = std.mem.Allocator; |
| 419 | 280 | const assert = std.debug.assert; |
| 281 | ||
| 282 | pub const Wip = struct { | |
| 283 | gpa: Allocator, | |
| 284 | string_bytes: std.ArrayListUnmanaged(u8), | |
| 285 | /// The first thing in this array is a ErrorMessageList. | |
| 286 | extra: std.ArrayListUnmanaged(u32), | |
| 287 | root_list: std.ArrayListUnmanaged(MessageIndex), | |
| 288 | ||
| 289 | pub fn init(wip: *Wip, gpa: Allocator) !void { | |
| 290 | wip.* = .{ | |
| 291 | .gpa = gpa, | |
| 292 | .string_bytes = .{}, | |
| 293 | .extra = .{}, | |
| 294 | .root_list = .{}, | |
| 295 | }; | |
| 296 | ||
| 297 | // So that 0 can be used to indicate a null string. | |
| 298 | try wip.string_bytes.append(gpa, 0); | |
| 299 | ||
| 300 | assert(0 == try addExtra(wip, ErrorMessageList{ | |
| 301 | .len = 0, | |
| 302 | .start = 0, | |
| 303 | })); | |
| 304 | } | |
| 305 | ||
| 306 | pub fn deinit(wip: *Wip) void { | |
| 307 | const gpa = wip.gpa; | |
| 308 | wip.root_list.deinit(gpa); | |
| 309 | wip.string_bytes.deinit(gpa); | |
| 310 | wip.extra.deinit(gpa); | |
| 311 | wip.* = undefined; | |
| 312 | } | |
| 313 | ||
| 314 | pub fn toOwnedBundle(wip: *Wip) !ErrorBundle { | |
| 315 | const gpa = wip.gpa; | |
| 316 | wip.setExtra(0, ErrorMessageList{ | |
| 317 | .len = @intCast(u32, wip.root_list.items.len), | |
| 318 | .start = @intCast(u32, wip.extra.items.len), | |
| 319 | }); | |
| 320 | try wip.extra.appendSlice(gpa, @ptrCast([]const u32, wip.root_list.items)); | |
| 321 | wip.root_list.clearAndFree(gpa); | |
| 322 | return .{ | |
| 323 | .string_bytes = try wip.string_bytes.toOwnedSlice(gpa), | |
| 324 | .extra = try wip.extra.toOwnedSlice(gpa), | |
| 325 | }; | |
| 326 | } | |
| 327 | ||
| 328 | pub fn tmpBundle(wip: Wip) ErrorBundle { | |
| 329 | return .{ | |
| 330 | .string_bytes = wip.string_bytes.items, | |
| 331 | .extra = wip.extra.items, | |
| 332 | }; | |
| 333 | } | |
| 334 | ||
| 335 | pub fn addString(wip: *Wip, s: []const u8) !u32 { | |
| 336 | const gpa = wip.gpa; | |
| 337 | const index = @intCast(u32, wip.string_bytes.items.len); | |
| 338 | try wip.string_bytes.ensureUnusedCapacity(gpa, s.len + 1); | |
| 339 | wip.string_bytes.appendSliceAssumeCapacity(s); | |
| 340 | wip.string_bytes.appendAssumeCapacity(0); | |
| 341 | return index; | |
| 342 | } | |
| 343 | ||
| 344 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) !u32 { | |
| 345 | const gpa = wip.gpa; | |
| 346 | const index = @intCast(u32, wip.string_bytes.items.len); | |
| 347 | try wip.string_bytes.writer(gpa).print(fmt, args); | |
| 348 | try wip.string_bytes.append(gpa, 0); | |
| 349 | return index; | |
| 350 | } | |
| 351 | ||
| 352 | pub fn addRootErrorMessage(wip: *Wip, em: ErrorMessage) !void { | |
| 353 | try wip.root_list.ensureUnusedCapacity(wip.gpa, 1); | |
| 354 | wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em)); | |
| 355 | } | |
| 356 | ||
| 357 | pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) !MessageIndex { | |
| 358 | return @intToEnum(MessageIndex, try addExtra(wip, em)); | |
| 359 | } | |
| 360 | ||
| 361 | pub fn addErrorMessageAssumeCapacity(wip: *Wip, em: ErrorMessage) MessageIndex { | |
| 362 | return @intToEnum(MessageIndex, addExtraAssumeCapacity(wip, em)); | |
| 363 | } | |
| 364 | ||
| 365 | pub fn addSourceLocation(wip: *Wip, sl: SourceLocation) !SourceLocationIndex { | |
| 366 | return @intToEnum(SourceLocationIndex, try addExtra(wip, sl)); | |
| 367 | } | |
| 368 | ||
| 369 | pub fn addReferenceTrace(wip: *Wip, rt: ReferenceTrace) !void { | |
| 370 | _ = try addExtra(wip, rt); | |
| 371 | } | |
| 372 | ||
| 373 | pub fn addBundle(wip: *Wip, other: ErrorBundle) !void { | |
| 374 | const gpa = wip.gpa; | |
| 375 | ||
| 376 | try wip.string_bytes.ensureUnusedCapacity(gpa, other.string_bytes.len); | |
| 377 | try wip.extra.ensureUnusedCapacity(gpa, other.extra.len); | |
| 378 | ||
| 379 | const other_list = other.getMessages(); | |
| 380 | ||
| 381 | // The ensureUnusedCapacity call above guarantees this. | |
| 382 | const notes_start = wip.reserveNotes(@intCast(u32, other_list.len)) catch unreachable; | |
| 383 | for (notes_start.., other_list) |note, message| { | |
| 384 | wip.extra.items[note] = @enumToInt(wip.addOtherMessage(other, message) catch unreachable); | |
| 385 | } | |
| 386 | } | |
| 387 | ||
| 388 | pub fn reserveNotes(wip: *Wip, notes_len: u32) !u32 { | |
| 389 | try wip.extra.ensureUnusedCapacity(wip.gpa, notes_len + | |
| 390 | notes_len * @typeInfo(ErrorBundle.ErrorMessage).Struct.fields.len); | |
| 391 | wip.extra.items.len += notes_len; | |
| 392 | return @intCast(u32, wip.extra.items.len - notes_len); | |
| 393 | } | |
| 394 | ||
| 395 | fn addOtherMessage(wip: *Wip, other: ErrorBundle, msg_index: MessageIndex) !MessageIndex { | |
| 396 | const other_msg = other.getErrorMessage(msg_index); | |
| 397 | const src_loc = try wip.addOtherSourceLocation(other, other_msg.src_loc); | |
| 398 | const msg = try wip.addErrorMessage(.{ | |
| 399 | .msg = try wip.addString(other.nullTerminatedString(other_msg.msg)), | |
| 400 | .count = other_msg.count, | |
| 401 | .src_loc = src_loc, | |
| 402 | .notes_len = other_msg.notes_len, | |
| 403 | }); | |
| 404 | const notes_start = try wip.reserveNotes(other_msg.notes_len); | |
| 405 | for (notes_start.., other.getNotes(msg_index)) |note, other_note| { | |
| 406 | wip.extra.items[note] = @enumToInt(try wip.addOtherMessage(other, other_note)); | |
| 407 | } | |
| 408 | return msg; | |
| 409 | } | |
| 410 | ||
| 411 | fn addOtherSourceLocation( | |
| 412 | wip: *Wip, | |
| 413 | other: ErrorBundle, | |
| 414 | index: SourceLocationIndex, | |
| 415 | ) !SourceLocationIndex { | |
| 416 | if (index == .none) return .none; | |
| 417 | const other_sl = other.getSourceLocation(index); | |
| 418 | ||
| 419 | const src_loc = try wip.addSourceLocation(.{ | |
| 420 | .src_path = try wip.addString(other.nullTerminatedString(other_sl.src_path)), | |
| 421 | .line = other_sl.line, | |
| 422 | .column = other_sl.column, | |
| 423 | .span_start = other_sl.span_start, | |
| 424 | .span_main = other_sl.span_main, | |
| 425 | .span_end = other_sl.span_end, | |
| 426 | .source_line = try wip.addString(other.nullTerminatedString(other_sl.source_line)), | |
| 427 | .reference_trace_len = other_sl.reference_trace_len, | |
| 428 | }); | |
| 429 | ||
| 430 | // TODO: also add the reference trace | |
| 431 | ||
| 432 | return src_loc; | |
| 433 | } | |
| 434 | ||
| 435 | fn addExtra(wip: *Wip, extra: anytype) Allocator.Error!u32 { | |
| 436 | const gpa = wip.gpa; | |
| 437 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; | |
| 438 | try wip.extra.ensureUnusedCapacity(gpa, fields.len); | |
| 439 | return addExtraAssumeCapacity(wip, extra); | |
| 440 | } | |
| 441 | ||
| 442 | fn addExtraAssumeCapacity(wip: *Wip, extra: anytype) u32 { | |
| 443 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; | |
| 444 | const result = @intCast(u32, wip.extra.items.len); | |
| 445 | wip.extra.items.len += fields.len; | |
| 446 | setExtra(wip, result, extra); | |
| 447 | return result; | |
| 448 | } | |
| 449 | ||
| 450 | fn setExtra(wip: *Wip, index: usize, extra: anytype) void { | |
| 451 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; | |
| 452 | var i = index; | |
| 453 | inline for (fields) |field| { | |
| 454 | wip.extra.items[i] = switch (field.type) { | |
| 455 | u32 => @field(extra, field.name), | |
| 456 | MessageIndex => @enumToInt(@field(extra, field.name)), | |
| 457 | SourceLocationIndex => @enumToInt(@field(extra, field.name)), | |
| 458 | else => @compileError("bad field type"), | |
| 459 | }; | |
| 460 | i += 1; | |
| 461 | } | |
| 462 | } | |
| 463 | }; |
src/Compilation.zig+123-130| ... | ... | @@ -2546,9 +2546,9 @@ pub fn totalErrorCount(self: *Compilation) u32 { |
| 2546 | 2546 | pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2547 | 2547 | const gpa = self.gpa; |
| 2548 | 2548 | |
| 2549 | var bundle: ErrorBundle = undefined; | |
| 2549 | var bundle: ErrorBundle.Wip = undefined; | |
| 2550 | 2550 | try bundle.init(gpa); |
| 2551 | errdefer bundle.deinit(gpa); | |
| 2551 | defer bundle.deinit(); | |
| 2552 | 2552 | |
| 2553 | 2553 | { |
| 2554 | 2554 | var it = self.failed_c_objects.iterator(); |
| ... | ... | @@ -2557,12 +2557,10 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2557 | 2557 | const err_msg = entry.value_ptr.*; |
| 2558 | 2558 | // TODO these fields will need to be adjusted when we have proper |
| 2559 | 2559 | // C error reporting bubbling up. |
| 2560 | try bundle.addErrorMessage(gpa, .{ | |
| 2561 | .msg = try bundle.printString(gpa, "unable to build C object: {s}", .{ | |
| 2562 | err_msg.msg, | |
| 2563 | }), | |
| 2564 | .src_loc = try bundle.addSourceLocation(gpa, .{ | |
| 2565 | .src_path = try bundle.addString(gpa, c_object.src.src_path), | |
| 2560 | try bundle.addRootErrorMessage(.{ | |
| 2561 | .msg = try bundle.printString("unable to build C object: {s}", .{err_msg.msg}), | |
| 2562 | .src_loc = try bundle.addSourceLocation(.{ | |
| 2563 | .src_path = try bundle.addString(c_object.src.src_path), | |
| 2566 | 2564 | .span_start = 0, |
| 2567 | 2565 | .span_main = 0, |
| 2568 | 2566 | .span_end = 1, |
| ... | ... | @@ -2571,49 +2569,46 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2571 | 2569 | .source_line = 0, // TODO |
| 2572 | 2570 | }), |
| 2573 | 2571 | }); |
| 2574 | bundle.incrementCount(1); | |
| 2575 | 2572 | } |
| 2576 | 2573 | } |
| 2577 | 2574 | |
| 2578 | 2575 | for (self.lld_errors.items) |lld_error| { |
| 2579 | try bundle.addErrorMessage(gpa, .{ | |
| 2580 | .msg = try bundle.addString(gpa, lld_error.msg), | |
| 2581 | .notes_len = @intCast(u32, lld_error.context_lines.len), | |
| 2582 | }); | |
| 2583 | bundle.incrementCount(1); | |
| 2576 | const notes_len = @intCast(u32, lld_error.context_lines.len); | |
| 2584 | 2577 | |
| 2585 | for (lld_error.context_lines) |context_line| { | |
| 2586 | try bundle.addErrorMessage(gpa, .{ | |
| 2587 | .msg = try bundle.addString(gpa, context_line), | |
| 2588 | }); | |
| 2578 | try bundle.addRootErrorMessage(.{ | |
| 2579 | .msg = try bundle.addString(lld_error.msg), | |
| 2580 | .notes_len = notes_len, | |
| 2581 | }); | |
| 2582 | const notes_start = try bundle.reserveNotes(notes_len); | |
| 2583 | for (notes_start.., lld_error.context_lines) |note, context_line| { | |
| 2584 | bundle.extra.items[note] = @enumToInt(bundle.addErrorMessageAssumeCapacity(.{ | |
| 2585 | .msg = try bundle.addString(context_line), | |
| 2586 | })); | |
| 2589 | 2587 | } |
| 2590 | 2588 | } |
| 2591 | 2589 | for (self.misc_failures.values()) |*value| { |
| 2592 | try bundle.addErrorMessage(gpa, .{ | |
| 2593 | .msg = try bundle.addString(gpa, value.msg), | |
| 2590 | try bundle.addRootErrorMessage(.{ | |
| 2591 | .msg = try bundle.addString(value.msg), | |
| 2594 | 2592 | .notes_len = if (value.children) |b| b.errorMessageCount() else 0, |
| 2595 | 2593 | }); |
| 2596 | if (value.children) |b| try bundle.addBundle(gpa, b); | |
| 2597 | bundle.incrementCount(1); | |
| 2594 | if (value.children) |b| try bundle.addBundle(b); | |
| 2598 | 2595 | } |
| 2599 | 2596 | if (self.alloc_failure_occurred) { |
| 2600 | try bundle.addErrorMessage(gpa, .{ | |
| 2601 | .msg = try bundle.addString(gpa, "memory allocation failure"), | |
| 2597 | try bundle.addRootErrorMessage(.{ | |
| 2598 | .msg = try bundle.addString("memory allocation failure"), | |
| 2602 | 2599 | }); |
| 2603 | bundle.incrementCount(1); | |
| 2604 | 2600 | } |
| 2605 | 2601 | if (self.bin_file.options.module) |module| { |
| 2606 | 2602 | { |
| 2607 | 2603 | var it = module.failed_files.iterator(); |
| 2608 | 2604 | while (it.next()) |entry| { |
| 2609 | 2605 | if (entry.value_ptr.*) |msg| { |
| 2610 | try addModuleErrorMsg(gpa, &bundle, msg.*); | |
| 2606 | try addModuleErrorMsg(&bundle, msg.*); | |
| 2611 | 2607 | } else { |
| 2612 | // Must be ZIR errors. In order for ZIR errors to exist, the parsing | |
| 2613 | // must have completed successfully. | |
| 2614 | const tree = try entry.key_ptr.*.getTree(module.gpa); | |
| 2615 | assert(tree.errors.len == 0); | |
| 2616 | try addZirErrorMessages(gpa, &bundle, entry.key_ptr.*); | |
| 2608 | // Must be ZIR errors. Note that this may include AST errors. | |
| 2609 | // addZirErrorMessages asserts that the tree is loaded. | |
| 2610 | _ = try entry.key_ptr.*.getTree(gpa); | |
| 2611 | try addZirErrorMessages(&bundle, entry.key_ptr.*); | |
| 2617 | 2612 | } |
| 2618 | 2613 | } |
| 2619 | 2614 | } |
| ... | ... | @@ -2621,7 +2616,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2621 | 2616 | var it = module.failed_embed_files.iterator(); |
| 2622 | 2617 | while (it.next()) |entry| { |
| 2623 | 2618 | const msg = entry.value_ptr.*; |
| 2624 | try addModuleErrorMsg(gpa, &bundle, msg.*); | |
| 2619 | try addModuleErrorMsg(&bundle, msg.*); | |
| 2625 | 2620 | } |
| 2626 | 2621 | } |
| 2627 | 2622 | { |
| ... | ... | @@ -2631,21 +2626,20 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2631 | 2626 | // Skip errors for Decls within files that had a parse failure. |
| 2632 | 2627 | // We'll try again once parsing succeeds. |
| 2633 | 2628 | if (decl.getFileScope().okToReportErrors()) { |
| 2634 | try addModuleErrorMsg(gpa, &bundle, entry.value_ptr.*.*); | |
| 2629 | try addModuleErrorMsg(&bundle, entry.value_ptr.*.*); | |
| 2635 | 2630 | if (module.cimport_errors.get(entry.key_ptr.*)) |cimport_errors| for (cimport_errors) |c_error| { |
| 2636 | try bundle.addErrorMessage(gpa, .{ | |
| 2637 | .msg = try bundle.addString(gpa, std.mem.span(c_error.msg)), | |
| 2638 | .src_loc = if (c_error.path) |some| try bundle.addSourceLocation(gpa, .{ | |
| 2639 | .src_path = try bundle.addString(gpa, std.mem.span(some)), | |
| 2631 | try bundle.addRootErrorMessage(.{ | |
| 2632 | .msg = try bundle.addString(std.mem.span(c_error.msg)), | |
| 2633 | .src_loc = if (c_error.path) |some| try bundle.addSourceLocation(.{ | |
| 2634 | .src_path = try bundle.addString(std.mem.span(some)), | |
| 2640 | 2635 | .span_start = c_error.offset, |
| 2641 | 2636 | .span_main = c_error.offset, |
| 2642 | 2637 | .span_end = c_error.offset + 1, |
| 2643 | 2638 | .line = c_error.line, |
| 2644 | 2639 | .column = c_error.column, |
| 2645 | .source_line = if (c_error.source_line) |line| try bundle.addString(gpa, std.mem.span(line)) else 0, | |
| 2646 | }) else 0, | |
| 2640 | .source_line = if (c_error.source_line) |line| try bundle.addString(std.mem.span(line)) else 0, | |
| 2641 | }) else .none, | |
| 2647 | 2642 | }); |
| 2648 | bundle.incrementCount(1); | |
| 2649 | 2643 | }; |
| 2650 | 2644 | } |
| 2651 | 2645 | } |
| ... | ... | @@ -2657,40 +2651,39 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2657 | 2651 | // Skip errors for Decls within files that had a parse failure. |
| 2658 | 2652 | // We'll try again once parsing succeeds. |
| 2659 | 2653 | if (decl.getFileScope().okToReportErrors()) { |
| 2660 | try addModuleErrorMsg(gpa, &bundle, entry.value_ptr.*.*); | |
| 2654 | try addModuleErrorMsg(&bundle, entry.value_ptr.*.*); | |
| 2661 | 2655 | } |
| 2662 | 2656 | } |
| 2663 | 2657 | } |
| 2664 | 2658 | for (module.failed_exports.values()) |value| { |
| 2665 | try addModuleErrorMsg(gpa, &bundle, value.*); | |
| 2659 | try addModuleErrorMsg(&bundle, value.*); | |
| 2666 | 2660 | } |
| 2667 | 2661 | } |
| 2668 | 2662 | |
| 2669 | if (bundle.errorMessageCount() == 0) { | |
| 2663 | if (bundle.root_list.items.len == 0) { | |
| 2670 | 2664 | if (self.link_error_flags.no_entry_point_found) { |
| 2671 | try bundle.addErrorMessage(gpa, .{ | |
| 2672 | .msg = try bundle.addString(gpa, "no entry point found"), | |
| 2665 | try bundle.addRootErrorMessage(.{ | |
| 2666 | .msg = try bundle.addString("no entry point found"), | |
| 2673 | 2667 | }); |
| 2674 | bundle.incrementCount(1); | |
| 2675 | 2668 | } |
| 2676 | 2669 | } |
| 2677 | 2670 | |
| 2678 | 2671 | if (self.link_error_flags.missing_libc) { |
| 2679 | try bundle.addErrorMessage(gpa, .{ | |
| 2680 | .msg = try bundle.addString(gpa, "libc not available"), | |
| 2672 | try bundle.addRootErrorMessage(.{ | |
| 2673 | .msg = try bundle.addString("libc not available"), | |
| 2681 | 2674 | .notes_len = 2, |
| 2682 | 2675 | }); |
| 2683 | try bundle.addErrorMessage(gpa, .{ | |
| 2684 | .msg = try bundle.addString(gpa, "run 'zig libc -h' to learn about libc installations"), | |
| 2685 | }); | |
| 2686 | try bundle.addErrorMessage(gpa, .{ | |
| 2687 | .msg = try bundle.addString(gpa, "run 'zig targets' to see the targets for which zig can always provide libc"), | |
| 2688 | }); | |
| 2689 | bundle.incrementCount(1); | |
| 2676 | const notes_start = try bundle.reserveNotes(2); | |
| 2677 | bundle.extra.items[notes_start + 0] = @enumToInt(try bundle.addErrorMessage(.{ | |
| 2678 | .msg = try bundle.addString("run 'zig libc -h' to learn about libc installations"), | |
| 2679 | })); | |
| 2680 | bundle.extra.items[notes_start + 1] = @enumToInt(try bundle.addErrorMessage(.{ | |
| 2681 | .msg = try bundle.addString("run 'zig targets' to see the targets for which zig can always provide libc"), | |
| 2682 | })); | |
| 2690 | 2683 | } |
| 2691 | 2684 | |
| 2692 | 2685 | if (self.bin_file.options.module) |module| { |
| 2693 | if (bundle.errorMessageCount() == 0 and module.compile_log_decls.count() != 0) { | |
| 2686 | if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { | |
| 2694 | 2687 | const keys = module.compile_log_decls.keys(); |
| 2695 | 2688 | const values = module.compile_log_decls.values(); |
| 2696 | 2689 | // First one will be the error; subsequent ones will be notes. |
| ... | ... | @@ -2699,9 +2692,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2699 | 2692 | const err_msg = Module.ErrorMsg{ |
| 2700 | 2693 | .src_loc = src_loc, |
| 2701 | 2694 | .msg = "found compile log statement", |
| 2702 | .notes = try self.gpa.alloc(Module.ErrorMsg, module.compile_log_decls.count() - 1), | |
| 2695 | .notes = try gpa.alloc(Module.ErrorMsg, module.compile_log_decls.count() - 1), | |
| 2703 | 2696 | }; |
| 2704 | defer self.gpa.free(err_msg.notes); | |
| 2697 | defer gpa.free(err_msg.notes); | |
| 2705 | 2698 | |
| 2706 | 2699 | for (keys[1..], 0..) |key, i| { |
| 2707 | 2700 | const note_decl = module.declPtr(key); |
| ... | ... | @@ -2711,25 +2704,26 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2711 | 2704 | }; |
| 2712 | 2705 | } |
| 2713 | 2706 | |
| 2714 | try addModuleErrorMsg(gpa, &bundle, err_msg); | |
| 2707 | try addModuleErrorMsg(&bundle, err_msg); | |
| 2715 | 2708 | } |
| 2716 | 2709 | } |
| 2717 | 2710 | |
| 2718 | assert(self.totalErrorCount() == bundle.errorMessageCount()); | |
| 2711 | assert(self.totalErrorCount() == bundle.root_list.items.len); | |
| 2719 | 2712 | |
| 2720 | return bundle; | |
| 2713 | return bundle.toOwnedBundle(); | |
| 2721 | 2714 | } |
| 2722 | 2715 | |
| 2723 | 2716 | pub const ErrorNoteHashContext = struct { |
| 2724 | eb: *const ErrorBundle, | |
| 2717 | eb: *const ErrorBundle.Wip, | |
| 2725 | 2718 | |
| 2726 | 2719 | pub fn hash(ctx: ErrorNoteHashContext, key: ErrorBundle.ErrorMessage) u32 { |
| 2727 | 2720 | var hasher = std.hash.Wyhash.init(0); |
| 2721 | const eb = ctx.eb.tmpBundle(); | |
| 2728 | 2722 | |
| 2729 | hasher.update(ctx.eb.nullTerminatedString(key.msg)); | |
| 2730 | if (key.src_loc != 0) { | |
| 2731 | const src = ctx.eb.getSourceLocation(key.src_loc); | |
| 2732 | hasher.update(ctx.eb.nullTerminatedString(src.src_path)); | |
| 2723 | hasher.update(eb.nullTerminatedString(key.msg)); | |
| 2724 | if (key.src_loc != .none) { | |
| 2725 | const src = eb.getSourceLocation(key.src_loc); | |
| 2726 | hasher.update(eb.nullTerminatedString(src.src_path)); | |
| 2733 | 2727 | std.hash.autoHash(&hasher, src.line); |
| 2734 | 2728 | std.hash.autoHash(&hasher, src.column); |
| 2735 | 2729 | std.hash.autoHash(&hasher, src.span_main); |
| ... | ... | @@ -2745,17 +2739,18 @@ pub const ErrorNoteHashContext = struct { |
| 2745 | 2739 | b_index: usize, |
| 2746 | 2740 | ) bool { |
| 2747 | 2741 | _ = b_index; |
| 2748 | const msg_a = ctx.eb.nullTerminatedString(a.msg); | |
| 2749 | const msg_b = ctx.eb.nullTerminatedString(b.msg); | |
| 2742 | const eb = ctx.eb.tmpBundle(); | |
| 2743 | const msg_a = eb.nullTerminatedString(a.msg); | |
| 2744 | const msg_b = eb.nullTerminatedString(b.msg); | |
| 2750 | 2745 | if (!std.mem.eql(u8, msg_a, msg_b)) return false; |
| 2751 | 2746 | |
| 2752 | if (a.src_loc == 0 and b.src_loc == 0) return true; | |
| 2753 | if (a.src_loc == 0 or b.src_loc == 0) return false; | |
| 2754 | const src_a = ctx.eb.getSourceLocation(a.src_loc); | |
| 2755 | const src_b = ctx.eb.getSourceLocation(b.src_loc); | |
| 2747 | if (a.src_loc == .none and b.src_loc == .none) return true; | |
| 2748 | if (a.src_loc == .none or b.src_loc == .none) return false; | |
| 2749 | const src_a = eb.getSourceLocation(a.src_loc); | |
| 2750 | const src_b = eb.getSourceLocation(b.src_loc); | |
| 2756 | 2751 | |
| 2757 | const src_path_a = ctx.eb.nullTerminatedString(src_a.src_path); | |
| 2758 | const src_path_b = ctx.eb.nullTerminatedString(src_b.src_path); | |
| 2752 | const src_path_a = eb.nullTerminatedString(src_a.src_path); | |
| 2753 | const src_path_b = eb.nullTerminatedString(src_b.src_path); | |
| 2759 | 2754 | |
| 2760 | 2755 | return std.mem.eql(u8, src_path_a, src_path_b) and |
| 2761 | 2756 | src_a.line == src_b.line and |
| ... | ... | @@ -2764,16 +2759,16 @@ pub const ErrorNoteHashContext = struct { |
| 2764 | 2759 | } |
| 2765 | 2760 | }; |
| 2766 | 2761 | |
| 2767 | pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Module.ErrorMsg) !void { | |
| 2762 | pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg) !void { | |
| 2763 | const gpa = eb.gpa; | |
| 2768 | 2764 | const err_source = module_err_msg.src_loc.file_scope.getSource(gpa) catch |err| { |
| 2769 | 2765 | const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa); |
| 2770 | 2766 | defer gpa.free(file_path); |
| 2771 | try eb.addErrorMessage(gpa, .{ | |
| 2772 | .msg = try eb.printString(gpa, "unable to load '{s}': {s}", .{ | |
| 2767 | try eb.addRootErrorMessage(.{ | |
| 2768 | .msg = try eb.printString("unable to load '{s}': {s}", .{ | |
| 2773 | 2769 | file_path, @errorName(err), |
| 2774 | 2770 | }), |
| 2775 | 2771 | }); |
| 2776 | eb.incrementCount(1); | |
| 2777 | 2772 | return; |
| 2778 | 2773 | }; |
| 2779 | 2774 | 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 |
| 2788 | 2783 | if (module_reference.hidden != 0) { |
| 2789 | 2784 | try ref_traces.append(gpa, .{ |
| 2790 | 2785 | .decl_name = module_reference.hidden, |
| 2791 | .src_loc = 0, | |
| 2786 | .src_loc = .none, | |
| 2792 | 2787 | }); |
| 2793 | 2788 | break; |
| 2794 | 2789 | } else if (module_reference.decl == null) { |
| 2795 | 2790 | try ref_traces.append(gpa, .{ |
| 2796 | 2791 | .decl_name = 0, |
| 2797 | .src_loc = 0, | |
| 2792 | .src_loc = .none, | |
| 2798 | 2793 | }); |
| 2799 | 2794 | break; |
| 2800 | 2795 | } |
| ... | ... | @@ -2804,9 +2799,9 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul |
| 2804 | 2799 | const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa); |
| 2805 | 2800 | defer gpa.free(rt_file_path); |
| 2806 | 2801 | try ref_traces.append(gpa, .{ |
| 2807 | .decl_name = try eb.addString(gpa, std.mem.sliceTo(module_reference.decl.?, 0)), | |
| 2808 | .src_loc = try eb.addSourceLocation(gpa, .{ | |
| 2809 | .src_path = try eb.addString(gpa, rt_file_path), | |
| 2802 | .decl_name = try eb.addString(std.mem.sliceTo(module_reference.decl.?, 0)), | |
| 2803 | .src_loc = try eb.addSourceLocation(.{ | |
| 2804 | .src_path = try eb.addString(rt_file_path), | |
| 2810 | 2805 | .span_start = span.start, |
| 2811 | 2806 | .span_main = span.main, |
| 2812 | 2807 | .span_end = span.end, |
| ... | ... | @@ -2817,8 +2812,8 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul |
| 2817 | 2812 | }); |
| 2818 | 2813 | } |
| 2819 | 2814 | |
| 2820 | const src_loc = try eb.addSourceLocation(gpa, .{ | |
| 2821 | .src_path = try eb.addString(gpa, file_path), | |
| 2815 | const src_loc = try eb.addSourceLocation(.{ | |
| 2816 | .src_path = try eb.addString(file_path), | |
| 2822 | 2817 | .span_start = err_span.start, |
| 2823 | 2818 | .span_main = err_span.main, |
| 2824 | 2819 | .span_end = err_span.end, |
| ... | ... | @@ -2827,12 +2822,12 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul |
| 2827 | 2822 | .source_line = if (module_err_msg.src_loc.lazy == .entire_file) |
| 2828 | 2823 | 0 |
| 2829 | 2824 | else |
| 2830 | try eb.addString(gpa, err_loc.source_line), | |
| 2825 | try eb.addString(err_loc.source_line), | |
| 2831 | 2826 | .reference_trace_len = @intCast(u32, ref_traces.items.len), |
| 2832 | 2827 | }); |
| 2833 | 2828 | |
| 2834 | 2829 | for (ref_traces.items) |rt| { |
| 2835 | try eb.addReferenceTrace(gpa, rt); | |
| 2830 | try eb.addReferenceTrace(rt); | |
| 2836 | 2831 | } |
| 2837 | 2832 | |
| 2838 | 2833 | // 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 |
| 2848 | 2843 | defer gpa.free(note_file_path); |
| 2849 | 2844 | |
| 2850 | 2845 | const gop = try notes.getOrPutContext(gpa, .{ |
| 2851 | .msg = try eb.addString(gpa, module_note.msg), | |
| 2852 | .src_loc = try eb.addSourceLocation(gpa, .{ | |
| 2853 | .src_path = try eb.addString(gpa, note_file_path), | |
| 2846 | .msg = try eb.addString(module_note.msg), | |
| 2847 | .src_loc = try eb.addSourceLocation(.{ | |
| 2848 | .src_path = try eb.addString(note_file_path), | |
| 2854 | 2849 | .span_start = span.start, |
| 2855 | 2850 | .span_main = span.main, |
| 2856 | 2851 | .span_end = span.end, |
| 2857 | 2852 | .line = @intCast(u32, loc.line), |
| 2858 | 2853 | .column = @intCast(u32, loc.column), |
| 2859 | .source_line = if (err_loc.eql(loc)) 0 else try eb.addString(gpa, loc.source_line), | |
| 2854 | .source_line = if (err_loc.eql(loc)) 0 else try eb.addString(loc.source_line), | |
| 2860 | 2855 | }), |
| 2861 | 2856 | }, .{ .eb = eb }); |
| 2862 | 2857 | if (gop.found_existing) { |
| ... | ... | @@ -2864,24 +2859,28 @@ pub fn addModuleErrorMsg(gpa: Allocator, eb: *ErrorBundle, module_err_msg: Modul |
| 2864 | 2859 | } |
| 2865 | 2860 | } |
| 2866 | 2861 | |
| 2867 | try eb.addErrorMessage(gpa, .{ | |
| 2868 | .msg = try eb.addString(gpa, module_err_msg.msg), | |
| 2862 | const notes_len = @intCast(u32, notes.entries.len); | |
| 2863 | ||
| 2864 | try eb.addRootErrorMessage(.{ | |
| 2865 | .msg = try eb.addString(module_err_msg.msg), | |
| 2869 | 2866 | .src_loc = src_loc, |
| 2870 | .notes_len = @intCast(u32, notes.entries.len), | |
| 2867 | .notes_len = notes_len, | |
| 2871 | 2868 | }); |
| 2872 | eb.incrementCount(1); | |
| 2873 | 2869 | |
| 2874 | for (notes.keys()) |note| { | |
| 2875 | try eb.addErrorMessage(gpa, note); | |
| 2870 | const notes_start = try eb.reserveNotes(notes_len); | |
| 2871 | ||
| 2872 | for (notes_start.., notes.keys()) |i, note| { | |
| 2873 | eb.extra.items[i] = @enumToInt(try eb.addErrorMessage(note)); | |
| 2876 | 2874 | } |
| 2877 | 2875 | } |
| 2878 | 2876 | |
| 2879 | pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) !void { | |
| 2877 | pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void { | |
| 2880 | 2878 | assert(file.zir_loaded); |
| 2881 | 2879 | assert(file.tree_loaded); |
| 2882 | 2880 | assert(file.source_loaded); |
| 2883 | 2881 | const payload_index = file.zir.extra[@enumToInt(Zir.ExtraIndex.compile_errors)]; |
| 2884 | 2882 | assert(payload_index != 0); |
| 2883 | const gpa = eb.gpa; | |
| 2885 | 2884 | |
| 2886 | 2885 | const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index); |
| 2887 | 2886 | const items_len = header.data.items_len; |
| ... | ... | @@ -2900,14 +2899,30 @@ pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) |
| 2900 | 2899 | }; |
| 2901 | 2900 | const err_loc = std.zig.findLineColumn(file.source, err_span.main); |
| 2902 | 2901 | |
| 2903 | var notes: []ErrorBundle.ErrorMessage = &.{}; | |
| 2904 | defer gpa.free(notes); | |
| 2902 | { | |
| 2903 | const msg = file.zir.nullTerminatedString(item.data.msg); | |
| 2904 | const src_path = try file.fullPath(gpa); | |
| 2905 | defer gpa.free(src_path); | |
| 2906 | try eb.addRootErrorMessage(.{ | |
| 2907 | .msg = try eb.addString(msg), | |
| 2908 | .src_loc = try eb.addSourceLocation(.{ | |
| 2909 | .src_path = try eb.addString(src_path), | |
| 2910 | .span_start = err_span.start, | |
| 2911 | .span_main = err_span.main, | |
| 2912 | .span_end = err_span.end, | |
| 2913 | .line = @intCast(u32, err_loc.line), | |
| 2914 | .column = @intCast(u32, err_loc.column), | |
| 2915 | .source_line = try eb.addString(err_loc.source_line), | |
| 2916 | }), | |
| 2917 | .notes_len = item.data.notes, | |
| 2918 | }); | |
| 2919 | } | |
| 2905 | 2920 | |
| 2906 | 2921 | if (item.data.notes != 0) { |
| 2922 | const notes_start = try eb.reserveNotes(item.data.notes); | |
| 2907 | 2923 | const block = file.zir.extraData(Zir.Inst.Block, item.data.notes); |
| 2908 | 2924 | const body = file.zir.extra[block.end..][0..block.data.body_len]; |
| 2909 | notes = try gpa.alloc(ErrorBundle.ErrorMessage, body.len); | |
| 2910 | for (notes, body) |*note, body_elem| { | |
| 2925 | for (notes_start.., body) |note_i, body_elem| { | |
| 2911 | 2926 | const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); |
| 2912 | 2927 | const msg = file.zir.nullTerminatedString(note_item.data.msg); |
| 2913 | 2928 | const span = blk: { |
| ... | ... | @@ -2923,10 +2938,10 @@ pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) |
| 2923 | 2938 | const src_path = try file.fullPath(gpa); |
| 2924 | 2939 | defer gpa.free(src_path); |
| 2925 | 2940 | |
| 2926 | note.* = .{ | |
| 2927 | .msg = try eb.addString(gpa, msg), | |
| 2928 | .src_loc = try eb.addSourceLocation(gpa, .{ | |
| 2929 | .src_path = try eb.addString(gpa, src_path), | |
| 2941 | eb.extra.items[note_i] = @enumToInt(try eb.addErrorMessage(.{ | |
| 2942 | .msg = try eb.addString(msg), | |
| 2943 | .src_loc = try eb.addSourceLocation(.{ | |
| 2944 | .src_path = try eb.addString(src_path), | |
| 2930 | 2945 | .span_start = span.start, |
| 2931 | 2946 | .span_main = span.main, |
| 2932 | 2947 | .span_end = span.end, |
| ... | ... | @@ -2935,35 +2950,13 @@ pub fn addZirErrorMessages(gpa: Allocator, eb: *ErrorBundle, file: *Module.File) |
| 2935 | 2950 | .source_line = if (loc.eql(err_loc)) |
| 2936 | 2951 | 0 |
| 2937 | 2952 | else |
| 2938 | try eb.addString(gpa, loc.source_line), | |
| 2953 | try eb.addString(loc.source_line), | |
| 2939 | 2954 | }), |
| 2940 | 2955 | .notes_len = 0, // TODO rework this function to be recursive |
| 2941 | }; | |
| 2956 | })); | |
| 2942 | 2957 | } |
| 2943 | 2958 | } |
| 2944 | ||
| 2945 | const msg = file.zir.nullTerminatedString(item.data.msg); | |
| 2946 | const src_path = try file.fullPath(gpa); | |
| 2947 | defer gpa.free(src_path); | |
| 2948 | try eb.addErrorMessage(gpa, .{ | |
| 2949 | .msg = try eb.addString(gpa, msg), | |
| 2950 | .src_loc = try eb.addSourceLocation(gpa, .{ | |
| 2951 | .src_path = try eb.addString(gpa, src_path), | |
| 2952 | .span_start = err_span.start, | |
| 2953 | .span_main = err_span.main, | |
| 2954 | .span_end = err_span.end, | |
| 2955 | .line = @intCast(u32, err_loc.line), | |
| 2956 | .column = @intCast(u32, err_loc.column), | |
| 2957 | .source_line = try eb.addString(gpa, err_loc.source_line), | |
| 2958 | }), | |
| 2959 | .notes_len = @intCast(u32, notes.len), | |
| 2960 | }); | |
| 2961 | ||
| 2962 | for (notes) |note| { | |
| 2963 | try eb.addErrorMessage(gpa, note); | |
| 2964 | } | |
| 2965 | 2959 | } |
| 2966 | eb.incrementCount(items_len); | |
| 2967 | 2960 | } |
| 2968 | 2961 | |
| 2969 | 2962 | pub fn getCompileLogOutput(self: *Compilation) []const u8 { |
src/Package.zig+17-19| ... | ... | @@ -225,7 +225,7 @@ pub fn fetchAndAddDependencies( |
| 225 | 225 | dependencies_source: *std.ArrayList(u8), |
| 226 | 226 | build_roots_source: *std.ArrayList(u8), |
| 227 | 227 | name_prefix: []const u8, |
| 228 | error_bundle: *std.zig.ErrorBundle, | |
| 228 | error_bundle: *std.zig.ErrorBundle.Wip, | |
| 229 | 229 | all_modules: *AllModules, |
| 230 | 230 | ) !void { |
| 231 | 231 | const max_bytes = 10 * 1024 * 1024; |
| ... | ... | @@ -260,13 +260,12 @@ pub fn fetchAndAddDependencies( |
| 260 | 260 | if (manifest.errors.len > 0) { |
| 261 | 261 | const file_path = try directory.join(arena, &.{Manifest.basename}); |
| 262 | 262 | for (manifest.errors) |msg| { |
| 263 | try Report.addErrorMessage(gpa, ast, file_path, error_bundle, 0, msg); | |
| 263 | try Report.addErrorMessage(ast, file_path, error_bundle, 0, msg); | |
| 264 | 264 | } |
| 265 | 265 | return error.PackageFetchFailed; |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | 268 | const report: Report = .{ |
| 269 | .gpa = gpa, | |
| 270 | 269 | .ast = &ast, |
| 271 | 270 | .directory = directory, |
| 272 | 271 | .error_bundle = error_bundle, |
| ... | ... | @@ -343,10 +342,9 @@ pub fn createFilePkg( |
| 343 | 342 | } |
| 344 | 343 | |
| 345 | 344 | const Report = struct { |
| 346 | gpa: Allocator, | |
| 347 | 345 | ast: *const std.zig.Ast, |
| 348 | 346 | directory: Compilation.Directory, |
| 349 | error_bundle: *std.zig.ErrorBundle, | |
| 347 | error_bundle: *std.zig.ErrorBundle.Wip, | |
| 350 | 348 | |
| 351 | 349 | fn fail( |
| 352 | 350 | report: Report, |
| ... | ... | @@ -354,7 +352,7 @@ const Report = struct { |
| 354 | 352 | comptime fmt_string: []const u8, |
| 355 | 353 | fmt_args: anytype, |
| 356 | 354 | ) error{ PackageFetchFailed, OutOfMemory } { |
| 357 | const gpa = report.gpa; | |
| 355 | const gpa = report.error_bundle.gpa; | |
| 358 | 356 | |
| 359 | 357 | const file_path = try report.directory.join(gpa, &.{Manifest.basename}); |
| 360 | 358 | defer gpa.free(file_path); |
| ... | ... | @@ -362,7 +360,7 @@ const Report = struct { |
| 362 | 360 | const msg = try std.fmt.allocPrint(gpa, fmt_string, fmt_args); |
| 363 | 361 | defer gpa.free(msg); |
| 364 | 362 | |
| 365 | try addErrorMessage(report.gpa, report.ast.*, file_path, report.error_bundle, 0, .{ | |
| 363 | try addErrorMessage(report.ast.*, file_path, report.error_bundle, 0, .{ | |
| 366 | 364 | .tok = tok, |
| 367 | 365 | .off = 0, |
| 368 | 366 | .msg = msg, |
| ... | ... | @@ -372,30 +370,28 @@ const Report = struct { |
| 372 | 370 | } |
| 373 | 371 | |
| 374 | 372 | fn addErrorMessage( |
| 375 | gpa: Allocator, | |
| 376 | 373 | ast: std.zig.Ast, |
| 377 | 374 | file_path: []const u8, |
| 378 | eb: *std.zig.ErrorBundle, | |
| 375 | eb: *std.zig.ErrorBundle.Wip, | |
| 379 | 376 | notes_len: u32, |
| 380 | 377 | msg: Manifest.ErrorMessage, |
| 381 | 378 | ) error{OutOfMemory}!void { |
| 382 | 379 | const token_starts = ast.tokens.items(.start); |
| 383 | 380 | const start_loc = ast.tokenLocation(0, msg.tok); |
| 384 | 381 | |
| 385 | try eb.addErrorMessage(gpa, .{ | |
| 386 | .msg = try eb.addString(gpa, msg.msg), | |
| 387 | .src_loc = try eb.addSourceLocation(gpa, .{ | |
| 388 | .src_path = try eb.addString(gpa, file_path), | |
| 382 | try eb.addRootErrorMessage(.{ | |
| 383 | .msg = try eb.addString(msg.msg), | |
| 384 | .src_loc = try eb.addSourceLocation(.{ | |
| 385 | .src_path = try eb.addString(file_path), | |
| 389 | 386 | .span_start = token_starts[msg.tok], |
| 390 | 387 | .span_end = @intCast(u32, token_starts[msg.tok] + ast.tokenSlice(msg.tok).len), |
| 391 | 388 | .span_main = token_starts[msg.tok] + msg.off, |
| 392 | 389 | .line = @intCast(u32, start_loc.line), |
| 393 | 390 | .column = @intCast(u32, start_loc.column), |
| 394 | .source_line = try eb.addString(gpa, ast.source[start_loc.line_start..start_loc.line_end]), | |
| 391 | .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]), | |
| 395 | 392 | }), |
| 396 | 393 | .notes_len = notes_len, |
| 397 | 394 | }); |
| 398 | eb.incrementCount(1); | |
| 399 | 395 | } |
| 400 | 396 | }; |
| 401 | 397 | |
| ... | ... | @@ -526,14 +522,16 @@ fn fetchAndUnpack( |
| 526 | 522 | defer gpa.free(file_path); |
| 527 | 523 | |
| 528 | 524 | const eb = report.error_bundle; |
| 529 | try Report.addErrorMessage(gpa, report.ast.*, file_path, eb, 1, .{ | |
| 525 | const notes_len = 1; | |
| 526 | try Report.addErrorMessage(report.ast.*, file_path, eb, notes_len, .{ | |
| 530 | 527 | .tok = dep.url_tok, |
| 531 | 528 | .off = 0, |
| 532 | 529 | .msg = "url field is missing corresponding hash field", |
| 533 | 530 | }); |
| 534 | try eb.addErrorMessage(gpa, .{ | |
| 535 | .msg = try eb.printString(gpa, "expected .hash = \"{s}\",", .{&actual_hex}), | |
| 536 | }); | |
| 531 | const notes_start = try eb.reserveNotes(notes_len); | |
| 532 | eb.extra.items[notes_start] = @enumToInt(try eb.addErrorMessage(.{ | |
| 533 | .msg = try eb.printString("expected .hash = \"{s}\",", .{&actual_hex}), | |
| 534 | })); | |
| 537 | 535 | return error.PackageFetchFailed; |
| 538 | 536 | } |
| 539 | 537 |
src/Sema.zig+5-4| ... | ... | @@ -2215,11 +2215,12 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { |
| 2215 | 2215 | |
| 2216 | 2216 | if (crash_report.is_enabled and sema.mod.comp.debug_compile_errors) { |
| 2217 | 2217 | if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation; |
| 2218 | var errors: std.zig.ErrorBundle = undefined; | |
| 2219 | errors.init(gpa) catch unreachable; | |
| 2220 | Compilation.addModuleErrorMsg(gpa, &errors, err_msg.*) catch unreachable; | |
| 2218 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 2219 | wip_errors.init(gpa) catch unreachable; | |
| 2220 | Compilation.addModuleErrorMsg(&wip_errors, err_msg.*) catch unreachable; | |
| 2221 | 2221 | std.debug.print("compile error during Sema:\n", .{}); |
| 2222 | errors.renderToStdErr(.no_color); | |
| 2222 | var error_bundle = wip_errors.toOwnedBundle() catch unreachable; | |
| 2223 | error_bundle.renderToStdErr(.no_color); | |
| 2223 | 2224 | crash_report.compilerPanic("unexpected compile error occurred", null, null); |
| 2224 | 2225 | } |
| 2225 | 2226 |
src/main.zig+50-36| ... | ... | @@ -4436,9 +4436,9 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi |
| 4436 | 4436 | var all_modules: Package.AllModules = .{}; |
| 4437 | 4437 | defer all_modules.deinit(gpa); |
| 4438 | 4438 | |
| 4439 | var errors: std.zig.ErrorBundle = undefined; | |
| 4440 | try errors.init(gpa); | |
| 4441 | defer errors.deinit(gpa); | |
| 4439 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 4440 | try wip_errors.init(gpa); | |
| 4441 | defer wip_errors.deinit(); | |
| 4442 | 4442 | |
| 4443 | 4443 | // Here we borrow main package's table and will replace it with a fresh |
| 4444 | 4444 | // one after this process completes. |
| ... | ... | @@ -4453,15 +4453,17 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi |
| 4453 | 4453 | &dependencies_source, |
| 4454 | 4454 | &build_roots_source, |
| 4455 | 4455 | "", |
| 4456 | &errors, | |
| 4456 | &wip_errors, | |
| 4457 | 4457 | &all_modules, |
| 4458 | 4458 | ); |
| 4459 | if (errors.errorMessageCount() > 0) { | |
| 4459 | if (wip_errors.root_list.items.len > 0) { | |
| 4460 | 4460 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 4461 | 4461 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4462 | 4462 | .on => .escape_codes, |
| 4463 | 4463 | .off => .no_color, |
| 4464 | 4464 | }; |
| 4465 | var errors = try wip_errors.toOwnedBundle(); | |
| 4466 | defer errors.deinit(gpa); | |
| 4465 | 4467 | errors.renderToStdErr(ttyconf); |
| 4466 | 4468 | process.exit(1); |
| 4467 | 4469 | } |
| ... | ... | @@ -4721,16 +4723,18 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void |
| 4721 | 4723 | defer file.zir.deinit(gpa); |
| 4722 | 4724 | |
| 4723 | 4725 | if (file.zir.hasCompileErrors()) { |
| 4724 | var errors: std.zig.ErrorBundle = undefined; | |
| 4725 | try errors.init(gpa); | |
| 4726 | defer errors.deinit(gpa); | |
| 4727 | try Compilation.addZirErrorMessages(gpa, &errors, &file); | |
| 4726 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 4727 | try wip_errors.init(gpa); | |
| 4728 | defer wip_errors.deinit(); | |
| 4729 | try Compilation.addZirErrorMessages(&wip_errors, &file); | |
| 4728 | 4730 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 4729 | 4731 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4730 | 4732 | .on => .escape_codes, |
| 4731 | 4733 | .off => .no_color, |
| 4732 | 4734 | }; |
| 4733 | errors.renderToStdErr(ttyconf); | |
| 4735 | var error_bundle = try wip_errors.toOwnedBundle(); | |
| 4736 | defer error_bundle.deinit(gpa); | |
| 4737 | error_bundle.renderToStdErr(ttyconf); | |
| 4734 | 4738 | has_ast_error = true; |
| 4735 | 4739 | } |
| 4736 | 4740 | } |
| ... | ... | @@ -4930,16 +4934,18 @@ fn fmtPathFile( |
| 4930 | 4934 | defer file.zir.deinit(gpa); |
| 4931 | 4935 | |
| 4932 | 4936 | if (file.zir.hasCompileErrors()) { |
| 4933 | var errors: std.zig.ErrorBundle = undefined; | |
| 4934 | try errors.init(gpa); | |
| 4935 | defer errors.deinit(gpa); | |
| 4936 | try Compilation.addZirErrorMessages(gpa, &errors, &file); | |
| 4937 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 4938 | try wip_errors.init(gpa); | |
| 4939 | defer wip_errors.deinit(); | |
| 4940 | try Compilation.addZirErrorMessages(&wip_errors, &file); | |
| 4937 | 4941 | const ttyconf: std.debug.TTY.Config = switch (fmt.color) { |
| 4938 | 4942 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4939 | 4943 | .on => .escape_codes, |
| 4940 | 4944 | .off => .no_color, |
| 4941 | 4945 | }; |
| 4942 | errors.renderToStdErr(ttyconf); | |
| 4946 | var error_bundle = try wip_errors.toOwnedBundle(); | |
| 4947 | defer error_bundle.deinit(gpa); | |
| 4948 | error_bundle.renderToStdErr(ttyconf); | |
| 4943 | 4949 | fmt.any_error = true; |
| 4944 | 4950 | } |
| 4945 | 4951 | } |
| ... | ... | @@ -4968,17 +4974,19 @@ fn fmtPathFile( |
| 4968 | 4974 | } |
| 4969 | 4975 | |
| 4970 | 4976 | fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { |
| 4971 | var error_bundle: std.zig.ErrorBundle = undefined; | |
| 4972 | try error_bundle.init(gpa); | |
| 4973 | defer error_bundle.deinit(gpa); | |
| 4977 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 4978 | try wip_errors.init(gpa); | |
| 4979 | defer wip_errors.deinit(); | |
| 4974 | 4980 | |
| 4975 | try putAstErrorsIntoBundle(gpa, tree, path, &error_bundle); | |
| 4981 | try putAstErrorsIntoBundle(gpa, tree, path, &wip_errors); | |
| 4976 | 4982 | |
| 4977 | 4983 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 4978 | 4984 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 4979 | 4985 | .on => .escape_codes, |
| 4980 | 4986 | .off => .no_color, |
| 4981 | 4987 | }; |
| 4988 | var error_bundle = try wip_errors.toOwnedBundle(); | |
| 4989 | defer error_bundle.deinit(gpa); | |
| 4982 | 4990 | error_bundle.renderToStdErr(ttyconf); |
| 4983 | 4991 | } |
| 4984 | 4992 | |
| ... | ... | @@ -4986,7 +4994,7 @@ pub fn putAstErrorsIntoBundle( |
| 4986 | 4994 | gpa: Allocator, |
| 4987 | 4995 | tree: Ast, |
| 4988 | 4996 | path: []const u8, |
| 4989 | error_bundle: *std.zig.ErrorBundle, | |
| 4997 | wip_errors: *std.zig.ErrorBundle.Wip, | |
| 4990 | 4998 | ) !void { |
| 4991 | 4999 | var file: Module.File = .{ |
| 4992 | 5000 | .status = .never_loaded, |
| ... | ... | @@ -5013,7 +5021,7 @@ pub fn putAstErrorsIntoBundle( |
| 5013 | 5021 | file.zir_loaded = true; |
| 5014 | 5022 | defer file.zir.deinit(gpa); |
| 5015 | 5023 | |
| 5016 | try Compilation.addZirErrorMessages(gpa, error_bundle, &file); | |
| 5024 | try Compilation.addZirErrorMessages(wip_errors, &file); | |
| 5017 | 5025 | } |
| 5018 | 5026 | |
| 5019 | 5027 | pub const info_zen = |
| ... | ... | @@ -5595,16 +5603,18 @@ pub fn cmdAstCheck( |
| 5595 | 5603 | defer file.zir.deinit(gpa); |
| 5596 | 5604 | |
| 5597 | 5605 | if (file.zir.hasCompileErrors()) { |
| 5598 | var errors: std.zig.ErrorBundle = undefined; | |
| 5599 | try errors.init(gpa); | |
| 5600 | defer errors.deinit(gpa); | |
| 5601 | try Compilation.addZirErrorMessages(gpa, &errors, &file); | |
| 5606 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 5607 | try wip_errors.init(gpa); | |
| 5608 | defer wip_errors.deinit(); | |
| 5609 | try Compilation.addZirErrorMessages(&wip_errors, &file); | |
| 5602 | 5610 | const ttyconf: std.debug.TTY.Config = switch (color) { |
| 5603 | 5611 | .auto => std.debug.detectTTYConfig(std.io.getStdErr()), |
| 5604 | 5612 | .on => .escape_codes, |
| 5605 | 5613 | .off => .no_color, |
| 5606 | 5614 | }; |
| 5607 | errors.renderToStdErr(ttyconf); | |
| 5615 | var error_bundle = try wip_errors.toOwnedBundle(); | |
| 5616 | defer error_bundle.deinit(gpa); | |
| 5617 | error_bundle.renderToStdErr(ttyconf); | |
| 5608 | 5618 | process.exit(1); |
| 5609 | 5619 | } |
| 5610 | 5620 | |
| ... | ... | @@ -5719,12 +5729,14 @@ pub fn cmdChangelist( |
| 5719 | 5729 | defer file.zir.deinit(gpa); |
| 5720 | 5730 | |
| 5721 | 5731 | if (file.zir.hasCompileErrors()) { |
| 5722 | var errors: std.zig.ErrorBundle = undefined; | |
| 5723 | try errors.init(gpa); | |
| 5724 | defer errors.deinit(gpa); | |
| 5725 | try Compilation.addZirErrorMessages(gpa, &errors, &file); | |
| 5732 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 5733 | try wip_errors.init(gpa); | |
| 5734 | defer wip_errors.deinit(); | |
| 5735 | try Compilation.addZirErrorMessages(&wip_errors, &file); | |
| 5726 | 5736 | const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); |
| 5727 | errors.renderToStdErr(ttyconf); | |
| 5737 | var error_bundle = try wip_errors.toOwnedBundle(); | |
| 5738 | defer error_bundle.deinit(gpa); | |
| 5739 | error_bundle.renderToStdErr(ttyconf); | |
| 5728 | 5740 | process.exit(1); |
| 5729 | 5741 | } |
| 5730 | 5742 | |
| ... | ... | @@ -5758,12 +5770,14 @@ pub fn cmdChangelist( |
| 5758 | 5770 | file.zir_loaded = true; |
| 5759 | 5771 | |
| 5760 | 5772 | if (file.zir.hasCompileErrors()) { |
| 5761 | var errors: std.zig.ErrorBundle = undefined; | |
| 5762 | try errors.init(gpa); | |
| 5763 | defer errors.deinit(gpa); | |
| 5764 | try Compilation.addZirErrorMessages(gpa, &errors, &file); | |
| 5773 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 5774 | try wip_errors.init(gpa); | |
| 5775 | defer wip_errors.deinit(); | |
| 5776 | try Compilation.addZirErrorMessages(&wip_errors, &file); | |
| 5765 | 5777 | const ttyconf = std.debug.detectTTYConfig(std.io.getStdErr()); |
| 5766 | errors.renderToStdErr(ttyconf); | |
| 5778 | var error_bundle = try wip_errors.toOwnedBundle(); | |
| 5779 | defer error_bundle.deinit(gpa); | |
| 5780 | error_bundle.renderToStdErr(ttyconf); | |
| 5767 | 5781 | process.exit(1); |
| 5768 | 5782 | } |
| 5769 | 5783 |
src/test.zig+3-18| ... | ... | @@ -1242,7 +1242,7 @@ pub const TestContext = struct { |
| 1242 | 1242 | defer self.gpa.free(zig_lib_directory.path.?); |
| 1243 | 1243 | |
| 1244 | 1244 | var aux_thread_pool: ThreadPool = undefined; |
| 1245 | try aux_thread_pool.init(self.gpa); | |
| 1245 | try aux_thread_pool.init(.{ .allocator = self.gpa }); | |
| 1246 | 1246 | defer aux_thread_pool.deinit(); |
| 1247 | 1247 | |
| 1248 | 1248 | // 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 { |
| 1614 | 1614 | if (update.case != .Error) { |
| 1615 | 1615 | var all_errors = try comp.getAllErrorsAlloc(); |
| 1616 | 1616 | defer all_errors.deinit(allocator); |
| 1617 | if (all_errors.list.len != 0) { | |
| 1618 | print( | |
| 1619 | "\nCase '{s}': unexpected errors at update_index={d}:\n{s}\n", | |
| 1620 | .{ case.name, update_index, hr }, | |
| 1621 | ); | |
| 1622 | for (all_errors.list) |err_msg| { | |
| 1623 | switch (err_msg) { | |
| 1624 | .src => |src| { | |
| 1625 | print("{s}:{d}:{d}: error: {s}\n{s}\n", .{ | |
| 1626 | src.src_path, src.line + 1, src.column + 1, src.msg, hr, | |
| 1627 | }); | |
| 1628 | }, | |
| 1629 | .plain => |plain| { | |
| 1630 | print("error: {s}\n{s}\n", .{ plain.msg, hr }); | |
| 1631 | }, | |
| 1632 | } | |
| 1633 | } | |
| 1617 | if (all_errors.errorMessageCount() > 0) { | |
| 1618 | all_errors.renderToStdErr(std.debug.detectTTYConfig(std.io.getStdErr())); | |
| 1634 | 1619 | // TODO print generated C code |
| 1635 | 1620 | return error.UnexpectedCompileErrors; |
| 1636 | 1621 | } |