fix aro and resinator compilation errors

This commit is contained in:
Andrew Kelley 2025-12-22 23:23:01 -08:00
parent c05e2720a1
commit 0870f17501
6 changed files with 104 additions and 102 deletions

View file

@ -134,8 +134,9 @@ strip: bool = false,
unwindlib: ?[]const u8 = null,
pub fn deinit(d: *Driver) void {
const io = d.comp.io;
for (d.link_objects.items[d.link_objects.items.len - d.temp_file_count ..]) |obj| {
std.fs.deleteFileAbsolute(obj) catch {};
Io.Dir.deleteFileAbsolute(io, obj) catch {};
d.comp.gpa.free(obj);
}
d.inputs.deinit(d.comp.gpa);

View file

@ -125,8 +125,8 @@ pub const Diagnostics = struct {
try self.errors.append(self.allocator, error_details);
}
pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) void {
const stderr = io.lockStderr(&.{}, null);
pub fn renderToStderr(self: *Diagnostics, io: Io, args: []const []const u8) Io.Cancelable!void {
const stderr = try io.lockStderr(&.{}, null);
defer io.unlockStderr();
self.renderToWriter(args, stderr.terminal()) catch return;
}
@ -419,7 +419,7 @@ pub const Arg = struct {
};
}
pub fn looksLikeFilepath(self: Arg) bool {
pub fn looksLikeFilepath(self: Arg, io: Io) bool {
const meets_min_requirements = self.prefix == .slash and isSupportedInputExtension(std.fs.path.extension(self.full));
if (!meets_min_requirements) return false;
@ -438,7 +438,7 @@ pub const Arg = struct {
// It's still possible for a file path to look like a /fo option but not actually
// be one, e.g. `/foo/bar.rc`. As a last ditch effort to reduce false negatives,
// check if the file path exists and, if so, then we ignore the 'could be /fo option'-ness
std.fs.accessAbsolute(self.full, .{}) catch return false;
Io.Dir.accessAbsolute(io, self.full, .{}) catch return false;
return true;
}
@ -490,7 +490,7 @@ pub const ParseError = error{ParseError} || Allocator.Error;
/// Note: Does not run `Options.maybeAppendRC` automatically. If that behavior is desired,
/// it must be called separately.
pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagnostics) ParseError!Options {
pub fn parse(allocator: Allocator, io: Io, args: []const []const u8, diagnostics: *Diagnostics) ParseError!Options {
var options = Options{ .allocator = allocator };
errdefer options.deinit();
@ -530,7 +530,7 @@ pub fn parse(allocator: Allocator, args: []const []const u8, diagnostics: *Diagn
}
const args_remaining = args.len - arg_i;
if (args_remaining <= 2 and arg.looksLikeFilepath()) {
if (args_remaining <= 2 and arg.looksLikeFilepath(io)) {
var err_details = Diagnostics.ErrorDetails{ .type = .note, .print_args = true, .arg_index = arg_i };
try err_details.msg.appendSlice(allocator, "this argument was inferred to be a filepath, so argument parsing was terminated");
try diagnostics.append(err_details);
@ -1344,41 +1344,42 @@ test parsePercent {
try std.testing.expectError(error.InvalidFormat, parsePercent("~1"));
}
pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void {
try config.setColor(writer, .dim);
pub fn renderErrorMessage(t: Io.Terminal, err_details: Diagnostics.ErrorDetails, args: []const []const u8) !void {
const writer = t.writer;
try t.setColor(.dim);
try writer.writeAll("<cli>");
try config.setColor(writer, .reset);
try config.setColor(writer, .bold);
try t.setColor(.reset);
try t.setColor(.bold);
try writer.writeAll(": ");
switch (err_details.type) {
.err => {
try config.setColor(writer, .red);
try t.setColor(.red);
try writer.writeAll("error: ");
},
.warning => {
try config.setColor(writer, .yellow);
try t.setColor(.yellow);
try writer.writeAll("warning: ");
},
.note => {
try config.setColor(writer, .cyan);
try t.setColor(.cyan);
try writer.writeAll("note: ");
},
}
try config.setColor(writer, .reset);
try config.setColor(writer, .bold);
try t.setColor(.reset);
try t.setColor(.bold);
try writer.writeAll(err_details.msg.items);
try writer.writeByte('\n');
try config.setColor(writer, .reset);
try t.setColor(.reset);
if (!err_details.print_args) {
try writer.writeByte('\n');
return;
}
try config.setColor(writer, .dim);
try t.setColor(.dim);
const prefix = " ... ";
try writer.writeAll(prefix);
try config.setColor(writer, .reset);
try t.setColor(.reset);
const arg_with_name = args[err_details.arg_index];
const prefix_slice = arg_with_name[0..err_details.arg_span.prefix_len];
@ -1389,15 +1390,15 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err
try writer.writeAll(prefix_slice);
if (before_name_slice.len > 0) {
try config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll(before_name_slice);
try config.setColor(writer, .reset);
try t.setColor(.reset);
}
try writer.writeAll(name_slice);
if (after_name_slice.len > 0) {
try config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll(after_name_slice);
try config.setColor(writer, .reset);
try t.setColor(.reset);
}
var next_arg_len: usize = 0;
@ -1415,13 +1416,13 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err
if (err_details.arg_span.value_offset >= arg_with_name.len) {
try writer.writeByte(' ');
}
try config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll(" ...");
try config.setColor(writer, .reset);
try t.setColor(.reset);
}
try writer.writeByte('\n');
try config.setColor(writer, .green);
try t.setColor(.green);
try writer.splatByteAll(' ', prefix.len);
// Special case for when the option is *only* a prefix (e.g. invalid option: -)
if (err_details.arg_span.prefix_len == arg_with_name.len) {
@ -1447,7 +1448,7 @@ pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, err
}
}
try writer.writeByte('\n');
try config.setColor(writer, .reset);
try t.setColor(.reset);
}
fn testParse(args: []const []const u8) !Options {

View file

@ -96,7 +96,7 @@ pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io
var search_dirs: std.ArrayList(SearchDir) = .empty;
defer {
for (search_dirs.items) |*search_dir| {
search_dir.deinit(allocator);
search_dir.deinit(allocator, io);
}
search_dirs.deinit(allocator);
}
@ -406,7 +406,7 @@ pub const Compiler = struct {
// `/test.bin` relative to include paths and instead only treats it as
// an absolute path.
if (std.fs.path.isAbsolute(path)) {
const file = try utils.openFileNotDir(Io.Dir.cwd(), path, .{});
const file = try utils.openFileNotDir(Io.Dir.cwd(), io, path, .{});
errdefer file.close(io);
if (self.dependencies) |dependencies| {
@ -418,7 +418,7 @@ pub const Compiler = struct {
var first_error: ?(std.Io.File.OpenError || std.Io.File.StatError) = null;
for (self.search_dirs) |search_dir| {
if (utils.openFileNotDir(search_dir.dir, path, .{})) |file| {
if (utils.openFileNotDir(search_dir.dir, io, path, .{})) |file| {
errdefer file.close(io);
if (self.dependencies) |dependencies| {

View file

@ -67,9 +67,9 @@ pub const Diagnostics = struct {
return @intCast(index);
}
pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) void {
pub fn renderToStderr(self: *Diagnostics, cwd: Io.Dir, source: []const u8, source_mappings: ?SourceMappings) Io.Cancelable!void {
const io = self.io;
const stderr = io.lockStderr(&.{}, null);
const stderr = try io.lockStderr(&.{}, null);
defer io.unlockStderr();
for (self.errors.items) |err_details| {
renderErrorMessage(io, stderr.terminal(), cwd, err_details, source, self.strings.items, source_mappings) catch return;
@ -901,8 +901,7 @@ const truncated_str = "<...truncated...>";
pub fn renderErrorMessage(
io: Io,
writer: *std.Io.Writer,
tty_config: std.Io.tty.Config,
t: Io.Terminal,
cwd: Io.Dir,
err_details: ErrorDetails,
source: []const u8,
@ -927,36 +926,37 @@ pub fn renderErrorMessage(
const err_line = if (corresponding_span) |span| span.start_line else err_details.token.line_number;
try tty_config.setColor(writer, .bold);
const writer = t.writer;
try t.setColor(.bold);
if (corresponding_file) |file| {
try writer.writeAll(file);
} else {
try tty_config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll("<after preprocessor>");
try tty_config.setColor(writer, .reset);
try tty_config.setColor(writer, .bold);
try t.setColor(.reset);
try t.setColor(.bold);
}
try writer.print(":{d}:{d}: ", .{ err_line, column });
switch (err_details.type) {
.err => {
try tty_config.setColor(writer, .red);
try t.setColor(.red);
try writer.writeAll("error: ");
},
.warning => {
try tty_config.setColor(writer, .yellow);
try t.setColor(.yellow);
try writer.writeAll("warning: ");
},
.note => {
try tty_config.setColor(writer, .cyan);
try t.setColor(.cyan);
try writer.writeAll("note: ");
},
.hint => unreachable,
}
try tty_config.setColor(writer, .reset);
try tty_config.setColor(writer, .bold);
try t.setColor(.reset);
try t.setColor(.bold);
try err_details.render(writer, source, strings);
try writer.writeByte('\n');
try tty_config.setColor(writer, .reset);
try t.setColor(.reset);
if (!err_details.print_source_line) {
try writer.writeByte('\n');
@ -983,20 +983,20 @@ pub fn renderErrorMessage(
try writer.writeAll(source_line_for_display.line);
if (source_line_for_display.truncated) {
try tty_config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll(truncated_str);
try tty_config.setColor(writer, .reset);
try t.setColor(.reset);
}
try writer.writeByte('\n');
try tty_config.setColor(writer, .green);
try t.setColor(.green);
const num_spaces = truncated_visual_info.point_offset - truncated_visual_info.before_len;
try writer.splatByteAll(' ', num_spaces);
try writer.splatByteAll('~', truncated_visual_info.before_len);
try writer.writeByte('^');
try writer.splatByteAll('~', truncated_visual_info.after_len);
try writer.writeByte('\n');
try tty_config.setColor(writer, .reset);
try t.setColor(.reset);
if (corresponding_span != null and corresponding_file != null) {
var worth_printing_lines: bool = true;
@ -1021,22 +1021,22 @@ pub fn renderErrorMessage(
break :blk null;
},
};
defer if (corresponding_lines) |*cl| cl.deinit();
defer if (corresponding_lines) |*cl| cl.deinit(io);
try tty_config.setColor(writer, .bold);
try t.setColor(.bold);
if (corresponding_file) |file| {
try writer.writeAll(file);
} else {
try tty_config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll("<after preprocessor>");
try tty_config.setColor(writer, .reset);
try tty_config.setColor(writer, .bold);
try t.setColor(.reset);
try t.setColor(.bold);
}
try writer.print(":{d}:{d}: ", .{ err_line, column });
try tty_config.setColor(writer, .cyan);
try t.setColor(.cyan);
try writer.writeAll("note: ");
try tty_config.setColor(writer, .reset);
try tty_config.setColor(writer, .bold);
try t.setColor(.reset);
try t.setColor(.bold);
try writer.writeAll("this line originated from line");
if (corresponding_span.?.start_line != corresponding_span.?.end_line) {
try writer.print("s {}-{}", .{ corresponding_span.?.start_line, corresponding_span.?.end_line });
@ -1044,7 +1044,7 @@ pub fn renderErrorMessage(
try writer.print(" {}", .{corresponding_span.?.start_line});
}
try writer.print(" of file '{s}'\n", .{corresponding_file.?});
try tty_config.setColor(writer, .reset);
try t.setColor(.reset);
if (!worth_printing_lines) return;
@ -1055,21 +1055,21 @@ pub fn renderErrorMessage(
}) |display_line| {
try writer.writeAll(display_line.line);
if (display_line.truncated) {
try tty_config.setColor(writer, .dim);
try t.setColor(.dim);
try writer.writeAll(truncated_str);
try tty_config.setColor(writer, .reset);
try t.setColor(.reset);
}
try writer.writeByte('\n');
}
break :write_lines null;
};
if (write_lines_err) |err| {
try tty_config.setColor(writer, .red);
try t.setColor(.red);
try writer.writeAll(" | ");
try tty_config.setColor(writer, .reset);
try tty_config.setColor(writer, .dim);
try t.setColor(.reset);
try t.setColor(.dim);
try writer.print("unable to print line(s) from file: {s}\n", .{@errorName(err)});
try tty_config.setColor(writer, .reset);
try t.setColor(.reset);
}
try writer.writeByte('\n');
}
@ -1120,12 +1120,12 @@ const CorrespondingLines = struct {
var corresponding_lines = CorrespondingLines{
.span = corresponding_span,
.file = try utils.openFileNotDir(cwd, corresponding_file, .{}),
.file = try utils.openFileNotDir(cwd, io, corresponding_file, .{}),
.code_page = err_details.code_page,
.file_reader = undefined,
};
corresponding_lines.file_reader = corresponding_lines.file.reader(io, file_reader_buf);
errdefer corresponding_lines.deinit();
errdefer corresponding_lines.deinit(io);
try corresponding_lines.writeLineFromStreamVerbatim(
&corresponding_lines.file_reader.interface,

View file

@ -64,18 +64,18 @@ pub fn main() !void {
var options = options: {
var cli_diagnostics = cli.Diagnostics.init(gpa);
defer cli_diagnostics.deinit();
var options = cli.parse(gpa, cli_args, &cli_diagnostics) catch |err| switch (err) {
var options = cli.parse(gpa, io, cli_args, &cli_diagnostics) catch |err| switch (err) {
error.ParseError => {
try error_handler.emitCliDiagnostics(gpa, cli_args, &cli_diagnostics);
try error_handler.emitCliDiagnostics(gpa, io, cli_args, &cli_diagnostics);
std.process.exit(1);
},
else => |e| return e,
};
try options.maybeAppendRC(Io.Dir.cwd());
try options.maybeAppendRC(io, Io.Dir.cwd());
if (!zig_integration) {
// print any warnings/notes
cli_diagnostics.renderToStderr(io, cli_args);
try cli_diagnostics.renderToStderr(io, cli_args);
// If there was something printed, then add an extra newline separator
// so that there is a clear separation between the cli diagnostics and whatever
// gets printed after
@ -193,7 +193,7 @@ pub fn main() !void {
};
},
.filename => |input_filename| {
break :full_input Io.Dir.cwd().readFileAlloc(input_filename, gpa, .unlimited) catch |err| {
break :full_input Io.Dir.cwd().readFileAlloc(io, input_filename, gpa, .unlimited) catch |err| {
try error_handler.emitMessage(gpa, io, .err, "unable to read input file path '{s}': {s}", .{ input_filename, @errorName(err) });
std.process.exit(1);
};
@ -206,7 +206,7 @@ pub fn main() !void {
if (options.preprocess == .only) {
switch (options.output_source) {
.stdio => |output_file| {
try output_file.writeAll(full_input);
try output_file.writeStreamingAll(io, full_input);
},
.filename => |output_filename| {
try Io.Dir.cwd().writeFile(io, .{ .sub_path = output_filename, .data = full_input });
@ -224,16 +224,16 @@ pub fn main() !void {
.source = .{ .memory = .empty },
}
else if (options.input_format == .res)
IoStream.fromIoSource(options.input_source, .input) catch |err| {
IoStream.fromIoSource(io, options.input_source, .input) catch |err| {
try error_handler.emitMessage(gpa, io, .err, "unable to read res file path '{s}': {s}", .{ options.input_source.filename, @errorName(err) });
std.process.exit(1);
}
else
IoStream.fromIoSource(options.output_source, .output) catch |err| {
IoStream.fromIoSource(io, options.output_source, .output) catch |err| {
try error_handler.emitMessage(gpa, io, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
std.process.exit(1);
};
defer res_stream.deinit(gpa);
defer res_stream.deinit(gpa, io);
const res_data = res_data: {
if (options.input_format != .res) {
@ -269,7 +269,7 @@ pub fn main() !void {
defer diagnostics.deinit();
var output_buffer: [4096]u8 = undefined;
var res_stream_writer = res_stream.source.writer(gpa, &output_buffer);
var res_stream_writer = res_stream.source.writer(gpa, io, &output_buffer);
defer res_stream_writer.deinit(&res_stream.source);
const output_buffered_stream = res_stream_writer.interface();
@ -303,7 +303,7 @@ pub fn main() !void {
// print any warnings/notes
if (!zig_integration) {
diagnostics.renderToStderr(io, Io.Dir.cwd(), final_input, mapping_results.mappings);
try diagnostics.renderToStderr(Io.Dir.cwd(), final_input, mapping_results.mappings);
}
// write the depfile
@ -356,14 +356,14 @@ pub fn main() !void {
};
defer resources.deinit();
var coff_stream = IoStream.fromIoSource(options.output_source, .output) catch |err| {
var coff_stream = IoStream.fromIoSource(io, options.output_source, .output) catch |err| {
try error_handler.emitMessage(gpa, io, .err, "unable to create output file '{s}': {s}", .{ options.output_source.filename, @errorName(err) });
std.process.exit(1);
};
defer coff_stream.deinit(gpa);
defer coff_stream.deinit(gpa, io);
var coff_output_buffer: [4096]u8 = undefined;
var coff_output_buffered_stream = coff_stream.source.writer(gpa, &coff_output_buffer);
var coff_output_buffered_stream = coff_stream.source.writer(gpa, io, &coff_output_buffer);
var cvtres_diagnostics: cvtres.Diagnostics = .{ .none = {} };
cvtres.writeCoff(gpa, coff_output_buffered_stream.interface(), resources.list.items, options.coff_options, &cvtres_diagnostics) catch |err| {
@ -413,22 +413,22 @@ const IoStream = struct {
pub const IoDirection = enum { input, output };
pub fn fromIoSource(source: cli.Options.IoSource, io: IoDirection) !IoStream {
pub fn fromIoSource(io: Io, source: cli.Options.IoSource, io_direction: IoDirection) !IoStream {
return .{
.name = switch (source) {
.filename => |filename| filename,
.stdio => switch (io) {
.stdio => switch (io_direction) {
.input => "<stdin>",
.output => "<stdout>",
},
},
.intermediate = false,
.source = try Source.fromIoSource(source, io),
.source = try Source.fromIoSource(io, source, io_direction),
};
}
pub fn deinit(self: *IoStream, allocator: Allocator) void {
self.source.deinit(allocator);
pub fn deinit(self: *IoStream, allocator: Allocator, io: Io) void {
self.source.deinit(allocator, io);
}
pub fn cleanupAfterError(self: *IoStream, io: Io) void {
@ -450,11 +450,11 @@ const IoStream = struct {
/// The source has been closed and any usage of the Source in this state is illegal (except deinit).
closed: void,
pub fn fromIoSource(source: cli.Options.IoSource, io: IoDirection) !Source {
pub fn fromIoSource(io: Io, source: cli.Options.IoSource, io_direction: IoDirection) !Source {
switch (source) {
.filename => |filename| return .{
.file = switch (io) {
.input => try openFileNotDir(Io.Dir.cwd(), filename, .{}),
.file = switch (io_direction) {
.input => try openFileNotDir(Io.Dir.cwd(), io, filename, .{}),
.output => try Io.Dir.cwd().createFile(io, filename, .{}),
},
},
@ -641,7 +641,7 @@ fn getIncludePaths(
};
const target = std.zig.resolveTargetQueryOrFatal(io, target_query);
const is_native_abi = target_query.isNativeAbi();
const detected_libc = std.zig.LibCDirs.detect(arena, zig_lib_dir, &target, is_native_abi, true, null) catch |err| switch (err) {
const detected_libc = std.zig.LibCDirs.detect(arena, io, zig_lib_dir, &target, is_native_abi, true, null) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => return error.MingwIncludesNotFound,
};
@ -672,7 +672,7 @@ const ErrorHandler = union(enum) {
try server.serveErrorBundle(error_bundle);
},
.stderr => diagnostics.renderToStderr(io, args),
.stderr => return diagnostics.renderToStderr(io, args),
}
}
@ -696,7 +696,7 @@ const ErrorHandler = union(enum) {
},
.stderr => {
// aro errors have already been emitted
const stderr = io.lockStderr(&.{}, null);
const stderr = try io.lockStderr(&.{}, null);
defer io.unlockStderr();
try renderErrorMessage(stderr.terminal(), .err, "{s}", .{fail_msg});
},
@ -706,7 +706,6 @@ const ErrorHandler = union(enum) {
pub fn emitDiagnostics(
self: *ErrorHandler,
allocator: Allocator,
io: Io,
cwd: Io.Dir,
source: []const u8,
diagnostics: *Diagnostics,
@ -719,7 +718,7 @@ const ErrorHandler = union(enum) {
try server.serveErrorBundle(error_bundle);
},
.stderr => diagnostics.renderToStderr(io, cwd, source, mappings),
.stderr => return diagnostics.renderToStderr(cwd, source, mappings),
}
}

View file

@ -92,31 +92,32 @@ pub const ErrorMessageType = enum { err, warning, note };
/// Used for generic colored errors/warnings/notes, more context-specific error messages
/// are handled elsewhere.
pub fn renderErrorMessage(writer: *std.Io.Writer, config: std.Io.tty.Config, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {
pub fn renderErrorMessage(t: Io.Terminal, msg_type: ErrorMessageType, comptime format: []const u8, args: anytype) !void {
const writer = t.writer;
switch (msg_type) {
.err => {
try config.setColor(writer, .bold);
try config.setColor(writer, .red);
try t.setColor(.bold);
try t.setColor(.red);
try writer.writeAll("error: ");
},
.warning => {
try config.setColor(writer, .bold);
try config.setColor(writer, .yellow);
try t.setColor(.bold);
try t.setColor(.yellow);
try writer.writeAll("warning: ");
},
.note => {
try config.setColor(writer, .reset);
try config.setColor(writer, .cyan);
try t.setColor(.reset);
try t.setColor(.cyan);
try writer.writeAll("note: ");
},
}
try config.setColor(writer, .reset);
try t.setColor(.reset);
if (msg_type == .err) {
try config.setColor(writer, .bold);
try t.setColor(.bold);
}
try writer.print(format, args);
try writer.writeByte('\n');
try config.setColor(writer, .reset);
try t.setColor(.reset);
}
pub fn isLineEndingPair(first: u8, second: u8) bool {