about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/json/tests.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs31
2 files changed, 29 insertions, 4 deletions
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs
index 671dc449eaa..db0dd4ffe8e 100644
--- a/compiler/rustc_errors/src/json/tests.rs
+++ b/compiler/rustc_errors/src/json/tests.rs
@@ -64,7 +64,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
         );
 
         let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
-        let handler = Handler::with_emitter(true, None, Box::new(je));
+        let handler = Handler::with_emitter(true, None, Box::new(je), None);
         handler.span_err(span, "foo");
 
         let bytes = output.lock().unwrap();
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index b9db25103a3..31410c39d36 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -47,9 +47,10 @@ use std::borrow::Cow;
 use std::error::Report;
 use std::fmt;
 use std::hash::Hash;
+use std::io::Write;
 use std::num::NonZeroUsize;
 use std::panic;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use termcolor::{Color, ColorSpec};
 
@@ -461,6 +462,10 @@ struct HandlerInner {
     ///
     /// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html
     fulfilled_expectations: FxHashSet<LintExpectationId>,
+
+    /// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be
+    /// stored along side the main panic backtrace.
+    ice_file: Option<PathBuf>,
 }
 
 /// A key denoting where from a diagnostic was stashed.
@@ -550,6 +555,7 @@ impl Handler {
         sm: Option<Lrc<SourceMap>>,
         fluent_bundle: Option<Lrc<FluentBundle>>,
         fallback_bundle: LazyFallbackBundle,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         Self::with_tty_emitter_and_flags(
             color_config,
@@ -557,6 +563,7 @@ impl Handler {
             fluent_bundle,
             fallback_bundle,
             HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
+            ice_file,
         )
     }
 
@@ -566,6 +573,7 @@ impl Handler {
         fluent_bundle: Option<Lrc<FluentBundle>>,
         fallback_bundle: LazyFallbackBundle,
         flags: HandlerFlags,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         let emitter = Box::new(EmitterWriter::stderr(
             color_config,
@@ -579,23 +587,26 @@ impl Handler {
             flags.track_diagnostics,
             TerminalUrl::No,
         ));
-        Self::with_emitter_and_flags(emitter, flags)
+        Self::with_emitter_and_flags(emitter, flags, ice_file)
     }
 
     pub fn with_emitter(
         can_emit_warnings: bool,
         treat_err_as_bug: Option<NonZeroUsize>,
         emitter: Box<dyn Emitter + sync::Send>,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         Handler::with_emitter_and_flags(
             emitter,
             HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() },
+            ice_file,
         )
     }
 
     pub fn with_emitter_and_flags(
         emitter: Box<dyn Emitter + sync::Send>,
         flags: HandlerFlags,
+        ice_file: Option<PathBuf>,
     ) -> Self {
         Self {
             flags,
@@ -618,6 +629,7 @@ impl Handler {
                 check_unstable_expect_diagnostics: false,
                 unstable_expect_diagnostics: Vec::new(),
                 fulfilled_expectations: Default::default(),
+                ice_file,
             }),
         }
     }
@@ -1657,8 +1669,21 @@ impl HandlerInner {
         explanation: impl Into<DiagnosticMessage> + Copy,
     ) {
         let mut no_bugs = true;
+        // If backtraces are enabled, also print the query stack
+        let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
         for bug in bugs {
-            let mut bug = bug.decorate();
+            if let Some(file) = self.ice_file.as_ref()
+                && let Ok(mut out) = std::fs::File::options().append(true).open(file)
+            {
+                let _ = write!(
+                    &mut out,
+                    "\n\ndelayed span bug: {}\n{}",
+                    bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::<String>(),
+                    &bug.note
+                );
+            }
+            let mut bug =
+                if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
 
             if no_bugs {
                 // Put the overall explanation before the `DelayedBug`s, to