link_name: Symbol,
span: SpanData,
},
+ DataRace {
+ op1: RacingOp,
+ op2: RacingOp,
+ ptr: Pointer,
+ },
+}
+
+pub struct RacingOp {
+ pub action: String,
+ pub thread_info: String,
+ pub span: SpanData,
}
impl fmt::Display for TerminationInfo {
write!(f, "multiple definitions of symbol `{link_name}`"),
SymbolShimClashing { link_name, .. } =>
write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",),
+ DataRace { ptr, op1, op2 } =>
+ write!(
+ f,
+ "Data race detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here",
+ op1.action, op1.thread_info, op2.action, op2.thread_info
+ ),
}
}
}
/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
- /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag))
+ /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
///
- /// new_kind is `None` for base tags.
+ /// new_perm is `None` for base tags.
CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
/// This `Item` was popped from the borrow stack. The string explains the reason.
PoppedPointerTag(Item, String),
Abort(_) => Some("abnormal termination"),
UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
Some("unsupported operation"),
- StackedBorrowsUb { .. } => Some("Undefined Behavior"),
+ StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
Deadlock => Some("deadlock"),
MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
};
vec![(Some(*span), format!("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"))],
+ DataRace { op1, .. } =>
+ vec![
+ (Some(op1.span), format!("and (1) occurred earlier here")),
+ (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")),
+ ],
_ => vec![],
};
(title, helps)
}
// Show note and help messages.
+ let mut extra_span = false;
for (span_data, note) in ¬es {
if let Some(span_data) = span_data {
err.span_note(span_data.span(), note);
+ extra_span = true;
} else {
err.note(note);
}
for (span_data, help) in &helps {
if let Some(span_data) = span_data {
err.span_help(span_data.span(), help);
+ extra_span = true;
} else {
err.help(help);
}
}
if notes.len() + helps.len() > 0 {
// Add visual separator before backtrace.
- err.note("BACKTRACE:");
+ err.note(if extra_span { "BACKTRACE (of the first span):" } else { "BACKTRACE:" });
}
// Add backtrace
for (idx, frame_info) in stacktrace.iter().enumerate() {
if is_local && idx > 0 {
err.span_note(frame_info.span, &frame_info.to_string());
} else {
- err.note(&frame_info.to_string());
+ let sm = sess.source_map();
+ let span = sm.span_to_embeddable_string(frame_info.span);
+ err.note(format!("{frame_info} at {span}"));
}
}
let msg = match &e {
CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
- CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"),
- CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) =>
+ CreatedPointerTag(tag, Some(perm), None) =>
+ format!("created {tag:?} with {perm} derived from unknown tag"),
+ CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
format!(
- "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
+ "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
),
PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
CreatedCallId(id) => format!("function call with id {id}"),