about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-04-25 21:06:34 +0200
committerGitHub <noreply@github.com>2023-04-25 21:06:34 +0200
commitf5a3039addd7dcdf6b79d47d8f308ad068cf3cb8 (patch)
tree1b06b64ef934d17212850ee0cdd0de2957f17aec /compiler
parent95e9f68eb50cfdaa830b07b3d960a311e4a0e540 (diff)
parent040e1b6b5fccc4c9e084ce620f95ebf8fd13ed8d (diff)
downloadrust-f5a3039addd7dcdf6b79d47d8f308ad068cf3cb8.tar.gz
rust-f5a3039addd7dcdf6b79d47d8f308ad068cf3cb8.zip
Rollup merge of #110783 - dtolnay:safeprint, r=petrochenkov
Fix ICE on --print=... i/o errors

`rustc --print=cfg > /dev/full`

**Before:** ICE (see below)

**After:** exits quietly with code 1.

```console
thread 'rustc' panicked at 'failed printing to stdout: No space left on device (os error 28)', library/std/src/io/stdio.rs:1019:9
stack backtrace:
   0:     0x7ffa84d68f33 - std::backtrace_rs::backtrace::libunwind::trace::h527d8d64d53ade2d
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x7ffa84d68f33 - std::backtrace_rs::backtrace::trace_unsynchronized::hfb55b01517dd6379
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x7ffa84d68f33 - std::sys_common::backtrace::_print_fmt::hd134e914eea0bd97
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:65:5
   3:     0x7ffa84d68f33 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1480db11ec399d77
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:44:22
   4:     0x7ffa84dc9d4f - core::fmt::write::h67ec4c4171c92b26
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/core/src/fmt/mod.rs:1247:17
   5:     0x7ffa84d5bed1 - std::io::Write::write_fmt::h3b12aef0fff2463b
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/io/mod.rs:1712:15
   6:     0x7ffa84d68d45 - std::sys_common::backtrace::_print::h584400135abdbd51
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:47:5
   7:     0x7ffa84d68d45 - std::sys_common::backtrace::print::hce41d3c8bd91096b
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:34:9
   8:     0x7ffa84d6b84f - std::panicking::default_hook::{{closure}}::h2043b657a3791225
   9:     0x7ffa84d6b507 - std::panicking::default_hook::h99252b8d3dd5719c
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:293:9
  10:     0x7ffa87fdf915 - <rustc_driver_impl[d30cd2737d9d343a]::DEFAULT_HOOK::{closure#0}::{closure#0} as core[cc19a662f3570270]::ops::function::FnOnce<(&core[cc19a662f3570270]::panic::panic_info::PanicInfo,)>>::call_once::{shim:vtable#0}
  11:     0x7ffa84d6c005 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h222a2b674b9f4762
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/alloc/src/boxed.rs:1976:9
  12:     0x7ffa84d6c005 - std::panicking::rust_panic_with_hook::h7f49b36bf7f8ff77
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:704:13
  13:     0x7ffa84d6bd73 - std::panicking::begin_panic_handler::{{closure}}::haa23a7352589e31e
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:595:13
  14:     0x7ffa84d69376 - std::sys_common::backtrace::__rust_end_short_backtrace::h3d0cf6e3c96e3fe9
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:150:18
  15:     0x7ffa84d6ba72 - rust_begin_unwind
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:584:5
  16:     0x7ffa84dc5fe3 - core::panicking::panic_fmt::hf4b4ea11e3fdb110
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/core/src/panicking.rs:67:14
  17:     0x7ffa84d5aa07 - std::io::stdio::print_to::h55760b9ede306280
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/io/stdio.rs:1019:9
  18:     0x7ffa84d5aa07 - std::io::stdio::_print::h93deb6099db33eab
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/io/stdio.rs:1095:5
  19:     0x7ffa871e163b - rustc_driver_impl[d30cd2737d9d343a]::print_crate_info
  20:     0x7ffa87fb8e01 - rustc_span[9551eaa044f53f4f]::set_source_map::<(), rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}::{closure#0}>
  21:     0x7ffa87fb6d59 - std[71a32ca0600a6a04]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[c2b70c9b1dae0906]::util::run_in_thread_pool_with_globals<rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  22:     0x7ffa87fe25b4 - std[71a32ca0600a6a04]::panicking::try::<(), core[cc19a662f3570270]::panic::unwind_safe::AssertUnwindSafe<<std[71a32ca0600a6a04]::thread::Builder>::spawn_unchecked_<rustc_interface[c2b70c9b1dae0906]::util::run_in_thread_pool_with_globals<rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1}::{closure#0}>>
  23:     0x7ffa87fb0cf1 - <<std[71a32ca0600a6a04]::thread::Builder>::spawn_unchecked_<rustc_interface[c2b70c9b1dae0906]::util::run_in_thread_pool_with_globals<rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[cc19a662f3570270]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  24:     0x7ffa84d763e5 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hf15d802f31f86225
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/alloc/src/boxed.rs:1962:9
  25:     0x7ffa84d763e5 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hac564355b46c52d6
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/alloc/src/boxed.rs:1962:9
  26:     0x7ffa84d763e5 - std::sys::unix::thread::Thread::new::thread_start::h86fb3aedb7811f07
                               at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys/unix/thread.rs:108:17
  27:     0x7ffa84a94b43 - start_thread
                               at ./nptl/pthread_create.c:442:8
  28:     0x7ffa84b26a00 - clone3
                               at ./misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
  29:                0x0 - <unknown>

error: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: rustc 1.71.0-nightly (7f94b314c 2023-04-23) running on x86_64-unknown-linux-gnu

query stack during panic:
end of query stack
```
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs88
-rw-r--r--compiler/rustc_driver_impl/src/print.rs20
2 files changed, 68 insertions, 40 deletions
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 1a80b4fc314..5fac485de64 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -58,8 +58,16 @@ use std::str;
 use std::sync::LazyLock;
 use std::time::Instant;
 
+// This import blocks the use of panicking `print` and `println` in all the code
+// below. Please use `safe_print` and `safe_println` to avoid ICE when
+// encountering an I/O error during print.
+#[allow(unused_imports)]
+use std::{compile_error as print, compile_error as println};
+
 pub mod args;
 pub mod pretty;
+#[macro_use]
+mod print;
 mod session_diagnostics;
 
 use crate::session_diagnostics::{
@@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
             if io::stdout().is_terminal() {
                 show_content_with_pager(&text);
             } else {
-                print!("{text}");
+                safe_print!("{text}");
             }
         }
         Err(InvalidErrorCode) => {
@@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) {
     // If pager fails for whatever reason, we should still print the content
     // to standard output
     if fallback_to_println {
-        print!("{content}");
+        safe_print!("{content}");
     }
 }
 
@@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co
                 let path = &(*ifile);
                 let mut v = Vec::new();
                 locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
-                println!("{}", String::from_utf8(v).unwrap());
+                safe_println!("{}", String::from_utf8(v).unwrap());
             }
             Input::Str { .. } => {
                 early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
@@ -642,12 +650,12 @@ fn print_crate_info(
             TargetList => {
                 let mut targets = rustc_target::spec::TARGETS.to_vec();
                 targets.sort_unstable();
-                println!("{}", targets.join("\n"));
+                safe_println!("{}", targets.join("\n"));
             }
-            Sysroot => println!("{}", sess.sysroot.display()),
-            TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
+            Sysroot => safe_println!("{}", sess.sysroot.display()),
+            TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()),
             TargetSpec => {
-                println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
+                safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
             }
             AllTargetSpecs => {
                 let mut targets = BTreeMap::new();
@@ -656,7 +664,7 @@ fn print_crate_info(
                     let target = Target::expect_builtin(&triple);
                     targets.insert(name, target.to_json());
                 }
-                println!("{}", serde_json::to_string_pretty(&targets).unwrap());
+                safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap());
             }
             FileNames | CrateName => {
                 let Some(attrs) = attrs.as_ref() else {
@@ -666,14 +674,14 @@ fn print_crate_info(
                 let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
                 let id = rustc_session::output::find_crate_name(sess, attrs);
                 if *req == PrintRequest::CrateName {
-                    println!("{id}");
+                    safe_println!("{id}");
                     continue;
                 }
                 let crate_types = collect_crate_types(sess, attrs);
                 for &style in &crate_types {
                     let fname =
                         rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
-                    println!("{}", fname.file_name().unwrap().to_string_lossy());
+                    safe_println!("{}", fname.file_name().unwrap().to_string_lossy());
                 }
             }
             Cfg => {
@@ -707,13 +715,13 @@ fn print_crate_info(
 
                 cfgs.sort();
                 for cfg in cfgs {
-                    println!("{cfg}");
+                    safe_println!("{cfg}");
                 }
             }
             CallingConventions => {
                 let mut calling_conventions = rustc_target::spec::abi::all_names();
                 calling_conventions.sort_unstable();
-                println!("{}", calling_conventions.join("\n"));
+                safe_println!("{}", calling_conventions.join("\n"));
             }
             RelocationModels
             | CodeModels
@@ -733,7 +741,7 @@ fn print_crate_info(
                     let stable = sess.target.options.supported_split_debuginfo.contains(split);
                     let unstable_ok = sess.unstable_options();
                     if stable || unstable_ok {
-                        println!("{split}");
+                        safe_println!("{split}");
                     }
                 }
             }
@@ -770,14 +778,14 @@ pub fn version_at_macro_invocation(
 ) {
     let verbose = matches.opt_present("verbose");
 
-    println!("{binary} {version}");
+    safe_println!("{binary} {version}");
 
     if verbose {
-        println!("binary: {binary}");
-        println!("commit-hash: {commit_hash}");
-        println!("commit-date: {commit_date}");
-        println!("host: {}", config::host_triple());
-        println!("release: {release}");
+        safe_println!("binary: {binary}");
+        safe_println!("commit-hash: {commit_hash}");
+        safe_println!("commit-date: {commit_date}");
+        safe_println!("host: {}", config::host_triple());
+        safe_println!("release: {release}");
 
         let debug_flags = matches.opt_strs("Z");
         let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
@@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
     } else {
         ""
     };
-    println!(
+    safe_println!(
         "{options}{at_path}\nAdditional help:
     -C help             Print codegen options
     -W help             \
@@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
 }
 
 fn print_wall_help() {
-    println!(
+    safe_println!(
         "
 The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
 default. Use `rustc -W help` to see all available lints. It's more common to put
@@ -832,7 +840,7 @@ the command line flag directly.
 
 /// Write to stdout lint command options, together with a list of all available lints
 pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
-    println!(
+    safe_println!(
         "
 Available lint options:
     -W <foo>           Warn about <foo>
@@ -877,21 +885,21 @@ Available lint options:
         s
     };
 
-    println!("Lint checks provided by rustc:\n");
+    safe_println!("Lint checks provided by rustc:\n");
 
     let print_lints = |lints: Vec<&Lint>| {
-        println!("    {}  {:7.7}  {}", padded("name"), "default", "meaning");
-        println!("    {}  {:7.7}  {}", padded("----"), "-------", "-------");
+        safe_println!("    {}  {:7.7}  {}", padded("name"), "default", "meaning");
+        safe_println!("    {}  {:7.7}  {}", padded("----"), "-------", "-------");
         for lint in lints {
             let name = lint.name_lower().replace('_', "-");
-            println!(
+            safe_println!(
                 "    {}  {:7.7}  {}",
                 padded(&name),
                 lint.default_level(sess.edition()).as_str(),
                 lint.desc
             );
         }
-        println!("\n");
+        safe_println!("\n");
     };
 
     print_lints(builtin);
@@ -912,14 +920,14 @@ Available lint options:
         s
     };
 
-    println!("Lint groups provided by rustc:\n");
+    safe_println!("Lint groups provided by rustc:\n");
 
     let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
-        println!("    {}  sub-lints", padded("name"));
-        println!("    {}  ---------", padded("----"));
+        safe_println!("    {}  sub-lints", padded("name"));
+        safe_println!("    {}  ---------", padded("----"));
 
         if all_warnings {
-            println!("    {}  all lints that are set to issue warnings", padded("warnings"));
+            safe_println!("    {}  all lints that are set to issue warnings", padded("warnings"));
         }
 
         for (name, to) in lints {
@@ -929,26 +937,26 @@ Available lint options:
                 .map(|x| x.to_string().replace('_', "-"))
                 .collect::<Vec<String>>()
                 .join(", ");
-            println!("    {}  {}", padded(&name), desc);
+            safe_println!("    {}  {}", padded(&name), desc);
         }
-        println!("\n");
+        safe_println!("\n");
     };
 
     print_lint_groups(builtin_groups, true);
 
     match (loaded_plugins, plugin.len(), plugin_groups.len()) {
         (false, 0, _) | (false, _, 0) => {
-            println!("Lint tools like Clippy can provide additional lints and lint groups.");
+            safe_println!("Lint tools like Clippy can provide additional lints and lint groups.");
         }
         (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
-        (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
+        (true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."),
         (true, l, g) => {
             if l > 0 {
-                println!("Lint checks provided by plugins loaded by this crate:\n");
+                safe_println!("Lint checks provided by plugins loaded by this crate:\n");
                 print_lints(plugin);
             }
             if g > 0 {
-                println!("Lint groups provided by plugins loaded by this crate:\n");
+                safe_println!("Lint groups provided by plugins loaded by this crate:\n");
                 print_lint_groups(plugin_groups, false);
             }
         }
@@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool {
 }
 
 fn describe_debug_flags() {
-    println!("\nAvailable options:\n");
+    safe_println!("\nAvailable options:\n");
     print_flag_list("-Z", config::Z_OPTIONS);
 }
 
 fn describe_codegen_flags() {
-    println!("\nAvailable codegen options:\n");
+    safe_println!("\nAvailable codegen options:\n");
     print_flag_list("-C", config::CG_OPTIONS);
 }
 
@@ -1012,7 +1020,7 @@ fn print_flag_list<T>(
     let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
 
     for &(name, _, _, desc) in flag_list {
-        println!(
+        safe_println!(
             "    {} {:>width$}=val -- {}",
             cmdline_opt,
             name.replace('_', "-"),
diff --git a/compiler/rustc_driver_impl/src/print.rs b/compiler/rustc_driver_impl/src/print.rs
new file mode 100644
index 00000000000..70de55320f7
--- /dev/null
+++ b/compiler/rustc_driver_impl/src/print.rs
@@ -0,0 +1,20 @@
+use std::fmt;
+use std::io::{self, Write as _};
+
+macro_rules! safe_print {
+    ($($arg:tt)*) => {{
+        $crate::print::print(std::format_args!($($arg)*));
+    }};
+}
+
+macro_rules! safe_println {
+    ($($arg:tt)*) => {
+        safe_print!("{}\n", std::format_args!($($arg)*))
+    };
+}
+
+pub(crate) fn print(args: fmt::Arguments<'_>) {
+    if let Err(_) = io::stdout().write_fmt(args) {
+        rustc_errors::FatalError.raise();
+    }
+}