Skip to content

Commit 23f8625

Browse files
authored
Rollup merge of #115272 - RalfJung:miri-error-print, r=saethlin
miri/diagnostics: don't forget to print_backtrace when ICEing on unexpected errors This should fix the missing output encountered [here](#115145 (comment)). r? `@saethlin`
2 parents 6391165 + beeb2b1 commit 23f8625

File tree

5 files changed

+57
-44
lines changed

5 files changed

+57
-44
lines changed

compiler/rustc_const_eval/src/interpret/eval_context.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use super::{
2525
Scalar, StackPopJump,
2626
};
2727
use crate::errors::{self, ErroneousConstUsed};
28-
use crate::fluent_generated as fluent;
2928
use crate::util;
29+
use crate::{fluent_generated as fluent, ReportErrorExt};
3030

3131
pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
3232
/// Stores the `Machine` instance.
@@ -432,6 +432,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
432432
.map_or(CRATE_HIR_ID, |def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
433433
}
434434

435+
/// Turn the given error into a human-readable string. Expects the string to be printed, so if
436+
/// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that
437+
/// triggered the error.
438+
///
439+
/// This is NOT the preferred way to render an error; use `report` from `const_eval` instead.
440+
/// However, this is useful when error messages appear in ICEs.
441+
pub fn format_error(&self, e: InterpErrorInfo<'tcx>) -> String {
442+
let (e, backtrace) = e.into_parts();
443+
backtrace.print_backtrace();
444+
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
445+
// label and arguments from the InterpError.
446+
let handler = &self.tcx.sess.parse_sess.span_diagnostic;
447+
#[allow(rustc::untranslatable_diagnostic)]
448+
let mut diag = self.tcx.sess.struct_allow("");
449+
let msg = e.diagnostic_message();
450+
e.add_args(handler, &mut diag);
451+
let s = handler.eagerly_translate_to_string(msg, diag.args());
452+
diag.cancel();
453+
s
454+
}
455+
435456
#[inline(always)]
436457
pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
437458
M::stack(self)

compiler/rustc_const_eval/src/interpret/intern.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ pub fn intern_const_alloc_recursive<
378378
ecx.tcx.sess.delay_span_bug(
379379
ecx.tcx.span,
380380
format!(
381-
"error during interning should later cause validation failure: {error:?}"
381+
"error during interning should later cause validation failure: {}",
382+
ecx.format_error(error),
382383
),
383384
);
384385
}

compiler/rustc_const_eval/src/interpret/validity.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -911,9 +911,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
911911
// Complain about any other kind of error -- those are bad because we'd like to
912912
// report them in a way that shows *where* in the value the issue lies.
913913
Err(err) => {
914-
let (err, backtrace) = err.into_parts();
915-
backtrace.print_backtrace();
916-
bug!("Unexpected Undefined Behavior error during validation: {err:?}");
914+
bug!(
915+
"Unexpected Undefined Behavior error during validation: {}",
916+
self.format_error(err)
917+
);
917918
}
918919
}
919920
}

compiler/rustc_mir_transform/src/const_prop_lint.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
273273
// dedicated error variants should be introduced instead.
274274
assert!(
275275
!error.kind().formatted_string(),
276-
"const-prop encountered formatting error: {error:?}",
276+
"const-prop encountered formatting error: {}",
277+
self.ecx.format_error(error),
277278
);
278279
None
279280
}

src/tools/miri/src/diagnostics.rs

+27-38
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::fmt;
1+
use std::fmt::{self, Write};
22
use std::num::NonZeroU64;
33

44
use log::trace;
55

6-
use rustc_const_eval::ReportErrorExt;
76
use rustc_errors::DiagnosticMessage;
87
use rustc_span::{source_map::DUMMY_SP, SpanData, Symbol};
98
use rustc_target::abi::{Align, Size};
@@ -271,10 +270,13 @@ pub fn report_error<'tcx, 'mir>(
271270
};
272271
(title, helps)
273272
} else {
274-
#[rustfmt::skip]
275273
let title = match e.kind() {
276-
UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(e)) if matches!(e.kind, ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer) =>
277-
bug!("This validation error should be impossible in Miri: {:?}", e.kind),
274+
UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(validation_err))
275+
if matches!(validation_err.kind, ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer) =>
276+
{
277+
ecx.handle_ice(); // print interpreter backtrace
278+
bug!("This validation error should be impossible in Miri: {}", ecx.format_error(e));
279+
}
278280
UndefinedBehavior(_) =>
279281
"Undefined Behavior",
280282
ResourceExhaustion(_) =>
@@ -290,8 +292,10 @@ pub fn report_error<'tcx, 'mir>(
290292
InvalidProgramInfo::Layout(..)
291293
) =>
292294
"post-monomorphization error",
293-
kind =>
294-
bug!("This error should be impossible in Miri: {kind:?}"),
295+
_ => {
296+
ecx.handle_ice(); // print interpreter backtrace
297+
bug!("This error should be impossible in Miri: {}", ecx.format_error(e));
298+
}
295299
};
296300
#[rustfmt::skip]
297301
let helps = match e.kind() {
@@ -333,30 +337,22 @@ pub fn report_error<'tcx, 'mir>(
333337

334338
let stacktrace = ecx.generate_stacktrace();
335339
let (stacktrace, was_pruned) = prune_stacktrace(stacktrace, &ecx.machine);
336-
let (e, backtrace) = e.into_parts();
337-
backtrace.print_backtrace();
338-
339-
// We want to dump the allocation if this is `InvalidUninitBytes`. Since `add_args` consumes
340-
// the `InterpError`, we extract the variables it before that.
341-
let extra = match e {
342-
UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) =>
343-
Some((alloc_id, access)),
344-
_ => None,
345-
};
346340

347-
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
348-
// label and arguments from the InterpError.
349-
let e = {
350-
let handler = &ecx.tcx.sess.parse_sess.span_diagnostic;
351-
let mut diag = ecx.tcx.sess.struct_allow("");
352-
let msg = e.diagnostic_message();
353-
e.add_args(handler, &mut diag);
354-
let s = handler.eagerly_translate_to_string(msg, diag.args());
355-
diag.cancel();
356-
s
357-
};
341+
// We want to dump the allocation if this is `InvalidUninitBytes`. Since `format_error` consumes `e`, we compute the outut early.
342+
let mut extra = String::new();
343+
match e.kind() {
344+
UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
345+
writeln!(
346+
extra,
347+
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
348+
range = access.bad,
349+
).unwrap();
350+
writeln!(extra, "{:?}", ecx.dump_alloc(*alloc_id)).unwrap();
351+
}
352+
_ => {}
353+
}
358354

359-
msg.insert(0, e);
355+
msg.insert(0, ecx.format_error(e));
360356

361357
report_msg(
362358
DiagLevel::Error,
@@ -375,6 +371,8 @@ pub fn report_error<'tcx, 'mir>(
375371
);
376372
}
377373

374+
eprint!("{extra}"); // newlines are already in the string
375+
378376
// Debug-dump all locals.
379377
for (i, frame) in ecx.active_thread_stack().iter().enumerate() {
380378
trace!("-------------------");
@@ -385,15 +383,6 @@ pub fn report_error<'tcx, 'mir>(
385383
}
386384
}
387385

388-
// Extra output to help debug specific issues.
389-
if let Some((alloc_id, access)) = extra {
390-
eprintln!(
391-
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
392-
range = access.bad,
393-
);
394-
eprintln!("{:?}", ecx.dump_alloc(alloc_id));
395-
}
396-
397386
None
398387
}
399388

0 commit comments

Comments
 (0)