about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs23
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs7
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs3
-rw-r--r--src/tools/miri/src/diagnostics.rs65
5 files changed, 57 insertions, 44 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 90848dbfbc7..bd3d87470c9 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -25,8 +25,8 @@ use super::{
     Scalar, StackPopJump,
 };
 use crate::errors::{self, ErroneousConstUsed};
-use crate::fluent_generated as fluent;
 use crate::util;
+use crate::{fluent_generated as fluent, ReportErrorExt};
 
 pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     /// Stores the `Machine` instance.
@@ -432,6 +432,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .map_or(CRATE_HIR_ID, |def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
     }
 
+    /// Turn the given error into a human-readable string. Expects the string to be printed, so if
+    /// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that
+    /// triggered the error.
+    ///
+    /// This is NOT the preferred way to render an error; use `report` from `const_eval` instead.
+    /// However, this is useful when error messages appear in ICEs.
+    pub fn format_error(&self, e: InterpErrorInfo<'tcx>) -> String {
+        let (e, backtrace) = e.into_parts();
+        backtrace.print_backtrace();
+        // FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
+        // label and arguments from the InterpError.
+        let handler = &self.tcx.sess.parse_sess.span_diagnostic;
+        #[allow(rustc::untranslatable_diagnostic)]
+        let mut diag = self.tcx.sess.struct_allow("");
+        let msg = e.diagnostic_message();
+        e.add_args(handler, &mut diag);
+        let s = handler.eagerly_translate_to_string(msg, diag.args());
+        diag.cancel();
+        s
+    }
+
     #[inline(always)]
     pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
         M::stack(self)
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 910c3ca5d0a..42950d1ffb0 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -378,7 +378,8 @@ pub fn intern_const_alloc_recursive<
                 ecx.tcx.sess.delay_span_bug(
                     ecx.tcx.span,
                     format!(
-                        "error during interning should later cause validation failure: {error:?}"
+                        "error during interning should later cause validation failure: {}",
+                        ecx.format_error(error),
                     ),
                 );
             }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index d3f05af1c72..0d08d6be919 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -911,9 +911,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // Complain about any other kind of error -- those are bad because we'd like to
             // report them in a way that shows *where* in the value the issue lies.
             Err(err) => {
-                let (err, backtrace) = err.into_parts();
-                backtrace.print_backtrace();
-                bug!("Unexpected Undefined Behavior error during validation: {err:?}");
+                bug!(
+                    "Unexpected Undefined Behavior error during validation: {}",
+                    self.format_error(err)
+                );
             }
         }
     }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index da8913d604b..755b3985791 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -273,7 +273,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 // dedicated error variants should be introduced instead.
                 assert!(
                     !error.kind().formatted_string(),
-                    "const-prop encountered formatting error: {error:?}",
+                    "const-prop encountered formatting error: {}",
+                    self.ecx.format_error(error),
                 );
                 None
             }
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index f3285ccf917..799a9a8e4be 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -1,9 +1,8 @@
-use std::fmt;
+use std::fmt::{self, Write};
 use std::num::NonZeroU64;
 
 use log::trace;
 
-use rustc_const_eval::ReportErrorExt;
 use rustc_errors::DiagnosticMessage;
 use rustc_span::{source_map::DUMMY_SP, SpanData, Symbol};
 use rustc_target::abi::{Align, Size};
@@ -271,10 +270,13 @@ pub fn report_error<'tcx, 'mir>(
         };
         (title, helps)
     } else {
-        #[rustfmt::skip]
         let title = match e.kind() {
-            UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(e)) if matches!(e.kind, ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer) =>
-                bug!("This validation error should be impossible in Miri: {:?}", e.kind),
+            UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(validation_err))
+                if matches!(validation_err.kind, ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer) =>
+            {
+                ecx.handle_ice(); // print interpreter backtrace
+                bug!("This validation error should be impossible in Miri: {}", ecx.format_error(e));
+            }
             UndefinedBehavior(_) =>
                 "Undefined Behavior",
             ResourceExhaustion(_) =>
@@ -290,8 +292,10 @@ pub fn report_error<'tcx, 'mir>(
                 InvalidProgramInfo::Layout(..)
             ) =>
                 "post-monomorphization error",
-            kind =>
-                bug!("This error should be impossible in Miri: {kind:?}"),
+            _ => {
+                ecx.handle_ice(); // print interpreter backtrace
+                bug!("This error should be impossible in Miri: {}", ecx.format_error(e));
+            }
         };
         #[rustfmt::skip]
         let helps = match e.kind() {
@@ -333,30 +337,22 @@ pub fn report_error<'tcx, 'mir>(
 
     let stacktrace = ecx.generate_stacktrace();
     let (stacktrace, was_pruned) = prune_stacktrace(stacktrace, &ecx.machine);
-    let (e, backtrace) = e.into_parts();
-    backtrace.print_backtrace();
-
-    // We want to dump the allocation if this is `InvalidUninitBytes`. Since `add_args` consumes
-    // the `InterpError`, we extract the variables it before that.
-    let extra = match e {
-        UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) =>
-            Some((alloc_id, access)),
-        _ => None,
-    };
 
-    // FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
-    // label and arguments from the InterpError.
-    let e = {
-        let handler = &ecx.tcx.sess.parse_sess.span_diagnostic;
-        let mut diag = ecx.tcx.sess.struct_allow("");
-        let msg = e.diagnostic_message();
-        e.add_args(handler, &mut diag);
-        let s = handler.eagerly_translate_to_string(msg, diag.args());
-        diag.cancel();
-        s
-    };
+    // We want to dump the allocation if this is `InvalidUninitBytes`. Since `format_error` consumes `e`, we compute the outut early.
+    let mut extra = String::new();
+    match e.kind() {
+        UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
+            writeln!(
+                extra,
+                "Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
+                range = access.bad,
+            ).unwrap();
+            writeln!(extra, "{:?}", ecx.dump_alloc(*alloc_id)).unwrap();
+        }
+        _ => {}
+    }
 
-    msg.insert(0, e);
+    msg.insert(0, ecx.format_error(e));
 
     report_msg(
         DiagLevel::Error,
@@ -375,6 +371,8 @@ pub fn report_error<'tcx, 'mir>(
         );
     }
 
+    eprint!("{extra}"); // newlines are already in the string
+
     // Debug-dump all locals.
     for (i, frame) in ecx.active_thread_stack().iter().enumerate() {
         trace!("-------------------");
@@ -385,15 +383,6 @@ pub fn report_error<'tcx, 'mir>(
         }
     }
 
-    // Extra output to help debug specific issues.
-    if let Some((alloc_id, access)) = extra {
-        eprintln!(
-            "Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
-            range = access.bad,
-        );
-        eprintln!("{:?}", ecx.dump_alloc(alloc_id));
-    }
-
     None
 }