Skip to content

Commit a1b8238

Browse files
committed
give some context in error messages
1 parent d7d2266 commit a1b8238

File tree

1 file changed

+54
-35
lines changed

1 file changed

+54
-35
lines changed

src/diagnostics.rs

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use rustc_mir::interpret::InterpErrorInfo;
21
use std::cell::RefCell;
32

3+
use rustc_span::DUMMY_SP;
4+
45
use crate::*;
56

67
/// Miri specific diagnostics
@@ -14,62 +15,80 @@ pub fn report_diagnostic<'tcx, 'mir>(
1415
ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
1516
mut e: InterpErrorInfo<'tcx>,
1617
) -> Option<i64> {
17-
// Special treatment for some error kinds
18+
use InterpError::*;
19+
let title = match e.kind {
20+
Unsupported(_) => "unsupported operation",
21+
UndefinedBehavior(_) => "Undefined Behavior",
22+
InvalidProgram(_) => bug!("This error should be impossible in Miri: {}", e),
23+
ResourceExhaustion(_) => "resource exhaustion",
24+
MachineStop(_) => "program stopped",
25+
};
1826
let msg = match e.kind {
19-
InterpError::MachineStop(ref info) => {
27+
MachineStop(ref info) => {
2028
let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
2129
match info {
2230
TerminationInfo::Exit(code) => return Some(*code),
2331
TerminationInfo::Abort(None) => format!("the evaluated program aborted execution"),
2432
TerminationInfo::Abort(Some(msg)) => format!("the evaluated program aborted execution: {}", msg),
2533
}
2634
}
27-
err_unsup!(NoMirFor(..)) => format!(
28-
"{}. Did you set `MIRI_SYSROOT` to a Miri-enabled sysroot? You can prepare one with `cargo miri setup`.",
29-
e
30-
),
31-
InterpError::InvalidProgram(_) => bug!("This error should be impossible in Miri: {}", e),
3235
_ => e.to_string(),
3336
};
37+
let help = match e.kind {
38+
Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
39+
Some("set `MIRI_SYSROOT` to a Miri sysroot, which you can prepare with `cargo miri setup`"),
40+
Unsupported(_) =>
41+
Some("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"),
42+
UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) =>
43+
Some("this indicates a potential bug in the program: it violated *experimental* rules, and caused Undefined Behavior"),
44+
UndefinedBehavior(_) =>
45+
Some("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
46+
_ => None,
47+
};
3448
e.print_backtrace();
35-
report_msg(ecx, msg, true)
49+
report_msg(ecx, &format!("{}: {}", title, msg), msg, help, true)
3650
}
3751

3852
/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
3953
/// Also emits a full stacktrace of the interpreter stack.
4054
pub fn report_msg<'tcx, 'mir>(
4155
ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
42-
msg: String,
56+
title: &str,
57+
span_msg: String,
58+
help: Option<&str>,
4359
error: bool,
4460
) -> Option<i64> {
45-
if let Some(frame) = ecx.stack().last() {
46-
let span = frame.current_source_info().unwrap().span;
47-
48-
let mut err = if error {
49-
let msg = format!("Miri evaluation error: {}", msg);
50-
ecx.tcx.sess.struct_span_err(span, msg.as_str())
61+
let span = if let Some(frame) = ecx.stack().last() {
62+
frame.current_source_info().unwrap().span
63+
} else {
64+
DUMMY_SP
65+
};
66+
let mut err = if error {
67+
ecx.tcx.sess.struct_span_err(span, title)
68+
} else {
69+
ecx.tcx.sess.diagnostic().span_note_diag(span, title)
70+
};
71+
err.span_label(span, span_msg);
72+
if let Some(help) = help {
73+
err.help(help);
74+
}
75+
// Add backtrace
76+
let frames = ecx.generate_stacktrace(None);
77+
// We iterate with indices because we need to look at the next frame (the caller).
78+
for idx in 0..frames.len() {
79+
let frame_info = &frames[idx];
80+
let call_site_is_local = frames
81+
.get(idx + 1)
82+
.map_or(false, |caller_info| caller_info.instance.def_id().is_local());
83+
if call_site_is_local {
84+
err.span_note(frame_info.call_site, &frame_info.to_string());
5185
} else {
52-
ecx.tcx.sess.diagnostic().span_note_diag(span, msg.as_str())
53-
};
54-
let frames = ecx.generate_stacktrace(None);
55-
err.span_label(span, msg);
56-
// We iterate with indices because we need to look at the next frame (the caller).
57-
for idx in 0..frames.len() {
58-
let frame_info = &frames[idx];
59-
let call_site_is_local = frames
60-
.get(idx + 1)
61-
.map_or(false, |caller_info| caller_info.instance.def_id().is_local());
62-
if call_site_is_local {
63-
err.span_note(frame_info.call_site, &frame_info.to_string());
64-
} else {
65-
err.note(&frame_info.to_string());
66-
}
86+
err.note(&frame_info.to_string());
6787
}
68-
err.emit();
69-
} else {
70-
ecx.tcx.sess.err(&msg);
7188
}
7289

90+
err.emit();
91+
7392
for (i, frame) in ecx.stack().iter().enumerate() {
7493
trace!("-------------------");
7594
trace!("Frame {}", i);
@@ -106,7 +125,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
106125
CreatedAlloc(AllocId(id)) =>
107126
format!("created allocation with id {}", id),
108127
};
109-
report_msg(this, msg, false);
128+
report_msg(this, "tracking was triggered", msg, None, false);
110129
}
111130
});
112131
}

0 commit comments

Comments
 (0)