Skip to content

Commit 6e302b8

Browse files
committed
link to some websites for UB explanations
1 parent dd4fef0 commit 6e302b8

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

src/diagnostics.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub enum TerminationInfo {
99
Exit(i64),
1010
Abort(Option<String>),
1111
UnsupportedInIsolation(String),
12+
ExperimentalUb { msg: String, url: String }
1213
}
1314

1415
/// Miri specific diagnostics
@@ -25,7 +26,7 @@ pub fn report_error<'tcx, 'mir>(
2526
use InterpError::*;
2627

2728
e.print_backtrace();
28-
let (title, msg, help) = match e.kind {
29+
let (title, msg, helps) = match e.kind {
2930
MachineStop(info) => {
3031
let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
3132
use TerminationInfo::*;
@@ -37,13 +38,20 @@ pub fn report_error<'tcx, 'mir>(
3738
("abnormal termination", format!("the evaluated program aborted execution: {}", msg)),
3839
UnsupportedInIsolation(msg) =>
3940
("unsupported operation", format!("{}", msg)),
41+
ExperimentalUb { msg, .. } =>
42+
("Undefined Behavior", format!("{}", msg)),
4043
};
41-
let help = match info {
44+
let helps = match info {
4245
UnsupportedInIsolation(_) =>
43-
Some("pass the flag `-Zmiri-disable-isolation` to disable isolation"),
44-
_ => None,
46+
vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
47+
ExperimentalUb { url, .. } =>
48+
vec![
49+
format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
50+
format!("see {} for further information", url),
51+
],
52+
_ => vec![],
4553
};
46-
(title, msg, help)
54+
(title, msg, helps)
4755
}
4856
_ => {
4957
let (title, msg) = match e.kind {
@@ -56,21 +64,22 @@ pub fn report_error<'tcx, 'mir>(
5664
_ =>
5765
bug!("This error should be impossible in Miri: {}", e),
5866
};
59-
let help = match e.kind {
67+
let helps = match e.kind {
6068
Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
61-
Some("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`"),
69+
vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
6270
Unsupported(_) =>
63-
Some("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"),
64-
UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) =>
65-
Some("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
71+
vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
6672
UndefinedBehavior(_) =>
67-
Some("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
68-
_ => None,
73+
vec![
74+
format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
75+
format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
76+
],
77+
_ => vec![],
6978
};
70-
(title, msg, help)
79+
(title, msg, helps)
7180
}
7281
};
73-
report_msg(ecx, &format!("{}: {}", title, msg), msg, help, true)
82+
report_msg(ecx, &format!("{}: {}", title, msg), msg, &helps, true)
7483
}
7584

7685
/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
@@ -79,7 +88,7 @@ fn report_msg<'tcx, 'mir>(
7988
ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
8089
title: &str,
8190
span_msg: String,
82-
help: Option<&str>,
91+
helps: &[String],
8392
error: bool,
8493
) -> Option<i64> {
8594
let span = if let Some(frame) = ecx.stack().last() {
@@ -93,7 +102,7 @@ fn report_msg<'tcx, 'mir>(
93102
ecx.tcx.sess.diagnostic().span_note_diag(span, title)
94103
};
95104
err.span_label(span, span_msg);
96-
if let Some(help) = help {
105+
for help in helps {
97106
err.help(help);
98107
}
99108
// Add backtrace
@@ -149,7 +158,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
149158
CreatedAlloc(AllocId(id)) =>
150159
format!("created allocation with id {}", id),
151160
};
152-
report_msg(this, "tracking was triggered", msg, None, false);
161+
report_msg(this, "tracking was triggered", msg, &[], false);
153162
}
154163
});
155164
}

src/stacked_borrows.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ impl GlobalState {
192192
}
193193
}
194194

195+
/// Error reporting
196+
fn err_sb_ub(msg: String) -> InterpError<'static> {
197+
// FIXME: use `err_machine_stop!` macro, once that exists.
198+
InterpError::MachineStop(Box::new(TerminationInfo::ExperimentalUb {
199+
msg,
200+
url: format!("https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md"),
201+
}))
202+
}
203+
195204
// # Stacked Borrows Core Begin
196205

197206
/// We need to make at least the following things true:
@@ -272,15 +281,15 @@ impl<'tcx> Stack {
272281
if let Some(call) = item.protector {
273282
if global.is_active(call) {
274283
if let Some(tag) = tag {
275-
throw_ub!(UbExperimental(format!(
284+
Err(err_sb_ub(format!(
276285
"not granting access to tag {:?} because incompatible item is protected: {:?}",
277286
tag, item
278-
)));
287+
)))?
279288
} else {
280-
throw_ub!(UbExperimental(format!(
289+
Err(err_sb_ub(format!(
281290
"deallocating while item is protected: {:?}",
282291
item
283-
)));
292+
)))?
284293
}
285294
}
286295
}
@@ -294,10 +303,10 @@ impl<'tcx> Stack {
294303

295304
// Step 1: Find granting item.
296305
let granting_idx = self.find_granting(access, tag).ok_or_else(|| {
297-
err_ub!(UbExperimental(format!(
306+
err_sb_ub(format!(
298307
"no item granting {} to tag {:?} found in borrow stack.",
299308
access, tag
300-
),))
309+
))
301310
})?;
302311

303312
// Step 2: Remove incompatible items above them. Make sure we do not remove protected
@@ -338,10 +347,10 @@ impl<'tcx> Stack {
338347
fn dealloc(&mut self, tag: Tag, global: &GlobalState) -> InterpResult<'tcx> {
339348
// Step 1: Find granting item.
340349
self.find_granting(AccessKind::Write, tag).ok_or_else(|| {
341-
err_ub!(UbExperimental(format!(
350+
err_sb_ub(format!(
342351
"no item granting write access for deallocation to tag {:?} found in borrow stack",
343352
tag,
344-
)))
353+
))
345354
})?;
346355

347356
// Step 2: Remove all items. Also checks for protectors.
@@ -363,10 +372,10 @@ impl<'tcx> Stack {
363372
// Now we figure out which item grants our parent (`derived_from`) this kind of access.
364373
// We use that to determine where to put the new item.
365374
let granting_idx = self.find_granting(access, derived_from)
366-
.ok_or_else(|| err_ub!(UbExperimental(format!(
375+
.ok_or_else(|| err_sb_ub(format!(
367376
"trying to reborrow for {:?}, but parent tag {:?} does not have an appropriate item in the borrow stack",
368377
new.perm, derived_from,
369-
))))?;
378+
)))?;
370379

371380
// Compute where to put the new item.
372381
// Either way, we ensure that we insert the new item in a way such that between

0 commit comments

Comments
 (0)