diagnostics: add a macro to make things a bit easier to read
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 6d10a21..1bed557 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -140,6 +140,15 @@ pub enum DiagLevel {
Note,
}
+/// Generate a note/help text without a span.
+macro_rules! note {
+ ($($tt:tt)*) => { (None, format!($($tt)*)) };
+}
+/// Generate a note/help text with a span.
+macro_rules! note_span {
+ ($span:expr, $($tt:tt)*) => { (Some($span), format!($($tt)*)) };
+}
+
/// Attempts to prune a stacktrace to omit the Rust runtime, and returns a bool indicating if any
/// frames were pruned. If the stacktrace does not have any local frames, we conclude that it must
/// be pointing to a problem in the Rust runtime itself, and do not prune it at all.
@@ -228,38 +237,38 @@ pub fn report_error<'tcx>(
let helps = match info {
UnsupportedInIsolation(_) =>
vec![
- (None, format!("set `MIRIFLAGS=-Zmiri-disable-isolation` to disable isolation;")),
- (None, format!("or set `MIRIFLAGS=-Zmiri-isolation-error=warn` to make Miri return an error code from isolated operations (if supported for that operation) and continue with a warning")),
+ note!("set `MIRIFLAGS=-Zmiri-disable-isolation` to disable isolation;"),
+ note!("or set `MIRIFLAGS=-Zmiri-isolation-error=warn` to make Miri return an error code from isolated operations (if supported for that operation) and continue with a warning"),
],
UnsupportedForeignItem(_) => {
vec![
- (None, format!("if this is a basic API commonly used on this target, please report an issue with Miri")),
- (None, format!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases")),
+ note!("if this is a basic API commonly used on this target, please report an issue with Miri"),
+ note!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases"),
]
}
StackedBorrowsUb { help, history, .. } => {
msg.extend(help.clone());
let mut helps = vec![
- (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental")),
- (None, format!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information")),
+ note!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental"),
+ note!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information"),
];
if let Some(TagHistory {created, invalidated, protected}) = history.clone() {
helps.push((Some(created.1), created.0));
if let Some((msg, span)) = invalidated {
- helps.push((Some(span), msg));
+ helps.push(note_span!(span, "{msg}"));
}
if let Some((protector_msg, protector_span)) = protected {
- helps.push((Some(protector_span), protector_msg));
+ helps.push(note_span!(protector_span, "{protector_msg}"));
}
}
helps
},
TreeBorrowsUb { title: _, details, history } => {
let mut helps = vec![
- (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental"))
+ note!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental")
];
for m in details {
- helps.push((None, m.clone()));
+ helps.push(note!("{m}"));
}
for event in history.events.clone() {
helps.push(event);
@@ -268,26 +277,26 @@ pub fn report_error<'tcx>(
}
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
vec![
- (Some(*first), format!("it's first defined here, in crate `{first_crate}`")),
- (Some(*second), format!("then it's defined here again, in crate `{second_crate}`")),
+ note_span!(*first, "it's first defined here, in crate `{first_crate}`"),
+ note_span!(*second, "then it's defined here again, in crate `{second_crate}`"),
],
SymbolShimClashing { link_name, span } =>
- vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
+ vec![note_span!(*span, "the `{link_name}` symbol is defined here")],
Int2PtrWithStrictProvenance =>
- vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
+ vec![note!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead")],
DataRace { op1, extra, retag_explain, .. } => {
- let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))];
+ let mut helps = vec![note_span!(op1.span, "and (1) occurred earlier here")];
if let Some(extra) = extra {
- helps.push((None, format!("{extra}")));
- helps.push((None, format!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model")));
+ helps.push(note!("{extra}"));
+ helps.push(note!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model"));
}
if *retag_explain {
- helps.push((None, "retags occur on all (re)borrows and as well as when references are copied or moved".to_owned()));
- helps.push((None, "retags permit optimizations that insert speculative reads or writes".to_owned()));
- helps.push((None, "therefore from the perspective of data races, a retag has the same implications as a read or write".to_owned()));
+ helps.push(note!("retags occur on all (re)borrows and as well as when references are copied or moved"));
+ helps.push(note!("retags permit optimizations that insert speculative reads or writes"));
+ helps.push(note!("therefore from the perspective of data races, a retag has the same implications as a read or write"));
}
- helps.push((None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")));
- helps.push((None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")));
+ helps.push(note!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"));
+ helps.push(note!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"));
helps
}
,
@@ -332,32 +341,32 @@ pub fn report_error<'tcx>(
let helps = match e.kind() {
Unsupported(_) =>
vec![
- (None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support")),
+ note!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support"),
],
UndefinedBehavior(AlignmentCheckFailed { .. })
if ecx.machine.check_alignment == AlignmentCheck::Symbolic
=>
vec![
- (None, format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior")),
- (None, format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives")),
+ note!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
+ note!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives"),
],
UndefinedBehavior(info) => {
let mut helps = vec![
- (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
- (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
+ note!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
+ note!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
];
match info {
PointerUseAfterFree(alloc_id, _) | PointerOutOfBounds { alloc_id, .. } => {
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
- helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
+ helps.push(note_span!(span, "{:?} was allocated here:", alloc_id));
}
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
- helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
+ helps.push(note_span!(span, "{:?} was deallocated here:", alloc_id));
}
}
AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => {
- helps.push((None, format!("this means these two types are not *guaranteed* to be ABI-compatible across all targets")));
- helps.push((None, format!("if you think this code should be accepted anyway, please report an issue with Miri")));
+ helps.push(note!("this means these two types are not *guaranteed* to be ABI-compatible across all targets"));
+ helps.push(note!("if you think this code should be accepted anyway, please report an issue with Miri"));
}
_ => {},
}
@@ -639,9 +648,7 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
let notes = match &e {
ProgressReport { block_count } => {
- // It is important that each progress report is slightly different, since
- // identical diagnostics are being deduplicated.
- vec![(None, format!("so far, {block_count} basic blocks have been executed"))]
+ vec![note!("so far, {block_count} basic blocks have been executed")]
}
_ => vec![],
};
@@ -649,63 +656,39 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
let helps = match &e {
Int2Ptr { details: true } => {
let mut v = vec![
- (
- None,
- format!(
- "this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program"
- ),
+ note!(
+ "this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program"
),
- (
- None,
- format!(
- "see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation"
- ),
+ note!(
+ "see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation"
),
- (
- None,
- format!(
- "to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"
- ),
+ note!(
+ "to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"
),
- (
- None,
- format!(
- "you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics"
- ),
+ note!(
+ "you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics"
),
];
if self.borrow_tracker.as_ref().is_some_and(|b| {
matches!(b.borrow().borrow_tracker_method(), BorrowTrackerMethod::TreeBorrows)
}) {
- v.push((
- None,
- format!(
- "Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used"
- ),
- ));
+ v.push(
+ note!("Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used")
+ );
} else {
- v.push((
- None,
- format!(
- "alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning"
- ),
- ));
+ v.push(
+ note!("alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning")
+ );
}
v
}
ExternTypeReborrow => {
vec![
- (
- None,
- format!(
- "`extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code"
- ),
+ note!(
+ "`extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code"
),
- (
- None,
- format!(
- "try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead"
- ),
+ note!(
+ "try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead"
),
]
}