Skip to content

Commit fccd785

Browse files
committed
Use translatable diagnostics in rustc_const_eval
1 parent 28bc0c1 commit fccd785

File tree

7 files changed

+65
-23
lines changed

7 files changed

+65
-23
lines changed

src/diagnostics.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::num::NonZeroU64;
33

44
use log::trace;
55

6+
use rustc_const_eval::ReportErrorExt;
7+
use rustc_errors::DiagnosticMessage;
68
use rustc_span::{source_map::DUMMY_SP, SpanData, Symbol};
79
use rustc_target::abi::{Align, Size};
810

@@ -83,7 +85,21 @@ impl fmt::Display for TerminationInfo {
8385
}
8486
}
8587

86-
impl MachineStopType for TerminationInfo {}
88+
impl fmt::Debug for TerminationInfo {
89+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90+
write!(f, "{self}")
91+
}
92+
}
93+
94+
impl MachineStopType for TerminationInfo {
95+
fn diagnostic_message(&self) -> DiagnosticMessage {
96+
self.to_string().into()
97+
}
98+
fn add_args(
99+
self: Box<Self>,
100+
_: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue<'static>),
101+
) {}
102+
}
87103

88104
/// Miri specific diagnostics
89105
pub enum NonHaltingDiagnostic {
@@ -302,8 +318,32 @@ pub fn report_error<'tcx, 'mir>(
302318

303319
let stacktrace = ecx.generate_stacktrace();
304320
let (stacktrace, was_pruned) = prune_stacktrace(stacktrace, &ecx.machine);
305-
e.print_backtrace();
306-
msg.insert(0, e.to_string());
321+
let (e, backtrace) = e.into_parts();
322+
backtrace.print_backtrace();
323+
324+
// We want to dump the allocation if this is `InvalidUninitBytes`. Since `add_args` consumes
325+
// the `InterpError`, we extract the variables it before that.
326+
let extra = match e {
327+
UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
328+
Some((alloc_id, access))
329+
}
330+
_ => None
331+
};
332+
333+
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
334+
// label and arguments from the InterpError.
335+
let e = {
336+
let handler = &ecx.tcx.sess.parse_sess.span_diagnostic;
337+
let mut diag = ecx.tcx.sess.struct_allow("");
338+
let msg = e.diagnostic_message();
339+
e.add_args(handler, &mut diag);
340+
let s = handler.eagerly_translate_to_string(msg, diag.args());
341+
diag.cancel();
342+
s
343+
};
344+
345+
msg.insert(0, e);
346+
307347
report_msg(
308348
DiagLevel::Error,
309349
if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() },
@@ -332,15 +372,12 @@ pub fn report_error<'tcx, 'mir>(
332372
}
333373

334374
// Extra output to help debug specific issues.
335-
match e.kind() {
336-
UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
337-
eprintln!(
338-
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
339-
range = access.uninit,
340-
);
341-
eprintln!("{:?}", ecx.dump_alloc(*alloc_id));
342-
}
343-
_ => {}
375+
if let Some((alloc_id, access)) = extra {
376+
eprintln!(
377+
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
378+
range = access.uninit,
379+
);
380+
eprintln!("{:?}", ecx.dump_alloc(alloc_id));
344381
}
345382

346383
None
@@ -438,20 +475,23 @@ pub fn report_msg<'tcx>(
438475
// Add visual separator before backtrace.
439476
err.note(if extra_span { "BACKTRACE (of the first span):" } else { "BACKTRACE:" });
440477
}
478+
479+
let (mut err, handler) = err.into_diagnostic().unwrap();
480+
441481
// Add backtrace
442482
for (idx, frame_info) in stacktrace.iter().enumerate() {
443483
let is_local = machine.is_local(frame_info);
444484
// No span for non-local frames and the first frame (which is the error site).
445485
if is_local && idx > 0 {
446-
err.span_note(frame_info.span, frame_info.to_string());
486+
err.eager_subdiagnostic(handler, frame_info.as_note(machine.tcx));
447487
} else {
448488
let sm = sess.source_map();
449489
let span = sm.span_to_embeddable_string(frame_info.span);
450490
err.note(format!("{frame_info} at {span}"));
451491
}
452492
}
453493

454-
err.emit();
494+
handler.emit_diagnostic(&mut err);
455495
}
456496

457497
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {

src/eval.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,9 @@ pub fn eval_entry<'tcx>(
422422
let mut ecx = match create_ecx(tcx, entry_id, entry_type, &config) {
423423
Ok(v) => v,
424424
Err(err) => {
425-
err.print_backtrace();
426-
panic!("Miri initialization error: {}", err.kind())
425+
let (kind, backtrace) = err.into_parts();
426+
backtrace.print_backtrace();
427+
panic!("Miri initialization error: {kind:?}")
427428
}
428429
};
429430

src/helpers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
164164
// We don't give a span -- this isn't actually used directly by the program anyway.
165165
let const_val = this
166166
.eval_global(cid, None)
167-
.unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err}"));
167+
.unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err:?}"));
168168
this.read_scalar(&const_val.into())
169-
.unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err}"))
169+
.unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err:?}"))
170170
}
171171

172172
/// Helper function to get a `libc` constant as a `Scalar`.

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
extern crate rustc_apfloat;
4545
extern crate rustc_ast;
46+
extern crate rustc_errors;
4647
#[macro_use]
4748
extern crate rustc_middle;
4849
extern crate rustc_const_eval;

tests/fail/intrinsics/copy_overlapping.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ fn main() {
1010
unsafe {
1111
let a = data.as_mut_ptr();
1212
let b = a.wrapping_offset(1) as *mut _;
13-
copy_nonoverlapping(a, b, 2); //~ ERROR: copy_nonoverlapping called on overlapping ranges
13+
copy_nonoverlapping(a, b, 2); //~ ERROR: `copy_nonoverlapping` called on overlapping ranges
1414
}
1515
}

tests/fail/intrinsics/copy_overlapping.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: copy_nonoverlapping called on overlapping ranges
1+
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
22
--> $DIR/copy_overlapping.rs:LL:CC
33
|
44
LL | copy_nonoverlapping(a, b, 2);
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ copy_nonoverlapping called on overlapping ranges
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

tests/fail/intrinsics/ptr_offset_from_oob.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: Undefined Behavior: out-of-bounds offset_from: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
1+
error: Undefined Behavior: out-of-bounds `offset_from`: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
22
--> $DIR/ptr_offset_from_oob.rs:LL:CC
33
|
44
LL | unsafe { end_ptr.offset_from(end_ptr) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

0 commit comments

Comments
 (0)