From 07069b3a38463a00e74f82b266ad977fe49fef95 Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Mon, 6 Jul 2026 15:18:28 +0800 Subject: [PATCH] Fix ICE in `write_interface` when the interface file can't be written --- compiler/rustc_interface/src/diagnostics.rs | 2 +- compiler/rustc_interface/src/passes.rs | 8 +++++--- compiler/rustc_middle/src/error.rs | 2 +- .../write-interface-nonexistent-dir/libr.rs | 13 +++++++++++++ .../write-interface-nonexistent-dir/rmake.rs | 18 ++++++++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 tests/run-make/export/write-interface-nonexistent-dir/libr.rs create mode 100644 tests/run-make/export/write-interface-nonexistent-dir/rmake.rs diff --git a/compiler/rustc_interface/src/diagnostics.rs b/compiler/rustc_interface/src/diagnostics.rs index 7cae1aa54d2e7..44d6073b93037 100644 --- a/compiler/rustc_interface/src/diagnostics.rs +++ b/compiler/rustc_interface/src/diagnostics.rs @@ -84,7 +84,7 @@ pub(crate) struct TempsDirError; pub(crate) struct OutDirError; #[derive(Diagnostic)] -#[diag("failed to write file {$path}: {$error}\"")] +#[diag("failed to write file {$path}: {$error}")] pub(crate) struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ca6e48cb67fe5..50fa712a909c4 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -881,9 +881,11 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { &tcx.sess.psess.attr_id_generator, ); let export_output = tcx.output_filenames(()).interface_path(); - let mut file = fs::File::create_buffered(export_output).unwrap(); - if let Err(err) = write!(file, "{}", krate) { - tcx.dcx().fatal(format!("error writing interface file: {}", err)); + let mut file = fs::File::create_buffered(&export_output).unwrap_or_else(|error| { + tcx.dcx().emit_fatal(diagnostics::FailedWritingFile { path: &export_output, error }) + }); + if let Err(error) = write!(file, "{}", krate) { + tcx.dcx().emit_fatal(diagnostics::FailedWritingFile { path: &export_output, error }); } } diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 2823b7ba4e22e..e0ce5b8ccc843 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -18,7 +18,7 @@ pub(crate) struct DropCheckOverflow<'tcx> { } #[derive(Diagnostic)] -#[diag("failed to write file {$path}: {$error}\"")] +#[diag("failed to write file {$path}: {$error}")] pub(crate) struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, diff --git a/tests/run-make/export/write-interface-nonexistent-dir/libr.rs b/tests/run-make/export/write-interface-nonexistent-dir/libr.rs new file mode 100644 index 0000000000000..c6aeabf3228f0 --- /dev/null +++ b/tests/run-make/export/write-interface-nonexistent-dir/libr.rs @@ -0,0 +1,13 @@ +#![feature(export_stable)] +#![crate_type = "sdylib"] + +pub mod m { + #[repr(C)] + pub struct S { + pub x: i32, + } + + pub extern "C" fn foo1(x: S) -> i32 { + x.x + } +} diff --git a/tests/run-make/export/write-interface-nonexistent-dir/rmake.rs b/tests/run-make/export/write-interface-nonexistent-dir/rmake.rs new file mode 100644 index 0000000000000..636a8ab7ed9b4 --- /dev/null +++ b/tests/run-make/export/write-interface-nonexistent-dir/rmake.rs @@ -0,0 +1,18 @@ +// Regression test for . + +//@ ignore-cross-compile + +// NOTE: `sdylib`'s platform support is basically that of `dylib`. +//@ needs-crate-type: dylib + +use run_make_support::rustc; + +fn main() { + rustc() + .input("libr.rs") + .output("does-not-exist/output") + .run_fail() + .assert_exit_code(1) + .assert_stderr_contains("failed to write file") + .assert_not_ice(); +}