Auto merge of #2646 - saethlin:data-race-spans, r=RalfJung

Data race spans

Fixes https://github.com/rust-lang/miri/issues/2205

This adds output to data race errors very similar to the spans we emit for Stacked Borrows errors. For example, from our test suite:
```
help: The Atomic Load on thread `<unnamed>` is here
  --> tests/fail/data_race/atomic_read_na_write_race1.rs:23:13
   |
23 | ...   (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between Atomic Load on thread `<unnamed>` and Write o...
   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: The Write on thread `<unnamed>` is here
  --> tests/fail/data_race/atomic_read_na_write_race1.rs:19:13
   |
19 |             *(c.0 as *mut usize) = 32;
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^```
```

Because of https://github.com/rust-lang/miri/pull/2647 this comes without a perf regression, according to our benchmarks.
This commit is contained in:
bors 2022-12-24 08:13:31 +00:00
commit 245357f619
126 changed files with 554 additions and 272 deletions

View file

@ -50,8 +50,10 @@ use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir;
use rustc_span::Span;
use rustc_target::abi::{Align, Size};
use crate::diagnostics::RacingOp;
use crate::*;
use super::{
@ -144,8 +146,8 @@ impl ThreadClockSet {
/// Increment the happens-before clock at a
/// known index.
#[inline]
fn increment_clock(&mut self, index: VectorIdx) {
self.clock.increment_index(index);
fn increment_clock(&mut self, index: VectorIdx, current_span: Span) {
self.clock.increment_index(index, current_span);
}
/// Join the happens-before clock with that of
@ -356,13 +358,9 @@ impl MemoryCellClocks {
index: VectorIdx,
) -> Result<(), DataRace> {
log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, clocks);
if self.write <= clocks.clock[self.write_index] {
let atomic = self.atomic_mut();
atomic.read_vector.set_at_index(&clocks.clock, index);
Ok(())
} else {
Err(DataRace)
}
if self.write <= clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
}
/// Detect data-races with an atomic write, either with a non-atomic read or with
@ -373,9 +371,9 @@ impl MemoryCellClocks {
index: VectorIdx,
) -> Result<(), DataRace> {
log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, clocks);
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
let atomic = self.atomic_mut();
atomic.write_vector.set_at_index(&clocks.clock, index);
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
Ok(())
} else {
Err(DataRace)
@ -386,22 +384,22 @@ impl MemoryCellClocks {
/// returns true if a data-race is detected.
fn read_race_detect(
&mut self,
clocks: &ThreadClockSet,
clocks: &mut ThreadClockSet,
index: VectorIdx,
current_span: Span,
) -> Result<(), DataRace> {
log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks);
if !current_span.is_dummy() {
clocks.clock[index].span = current_span;
}
if self.write <= clocks.clock[self.write_index] {
let race_free = if let Some(atomic) = self.atomic() {
atomic.write_vector <= clocks.clock
} else {
true
};
if race_free {
self.read.set_at_index(&clocks.clock, index);
Ok(())
} else {
Err(DataRace)
}
if race_free { Ok(()) } else { Err(DataRace) }
} else {
Err(DataRace)
}
@ -411,21 +409,25 @@ impl MemoryCellClocks {
/// returns true if a data-race is detected.
fn write_race_detect(
&mut self,
clocks: &ThreadClockSet,
clocks: &mut ThreadClockSet,
index: VectorIdx,
write_type: WriteType,
current_span: Span,
) -> Result<(), DataRace> {
log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks);
if !current_span.is_dummy() {
clocks.clock[index].span = current_span;
}
if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
let race_free = if let Some(atomic) = self.atomic() {
atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock
} else {
true
};
if race_free {
self.write = clocks.clock[index];
self.write_index = index;
self.write_type = write_type;
if race_free {
self.read.set_zero_vector();
Ok(())
} else {
@ -621,8 +623,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
/// Update the data-race detector for an atomic fence on the current thread.
fn atomic_fence(&mut self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let current_span = this.machine.current_span();
if let Some(data_race) = &mut this.machine.data_race {
data_race.maybe_perform_sync_operation(&this.machine.threads, |index, mut clocks| {
data_race.maybe_perform_sync_operation(
&this.machine.threads,
current_span,
|index, mut clocks| {
log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic);
// Apply data-race detection for the current fences
@ -644,7 +650,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
// Increment timestamp in case of release semantics.
Ok(atomic != AtomicFenceOrd::Acquire)
})
},
)
} else {
Ok(())
}
@ -682,6 +689,7 @@ impl VClockAlloc {
thread_mgr: &ThreadManager<'_, '_>,
len: Size,
kind: MemoryKind<MiriMemoryKind>,
current_span: Span,
) -> VClockAlloc {
let (alloc_timestamp, alloc_index) = match kind {
// User allocated and stack memory should track allocation.
@ -693,7 +701,8 @@ impl VClockAlloc {
)
| MemoryKind::Stack => {
let (alloc_index, clocks) = global.current_thread_state(thread_mgr);
let alloc_timestamp = clocks.clock[alloc_index];
let mut alloc_timestamp = clocks.clock[alloc_index];
alloc_timestamp.span = current_span;
(alloc_timestamp, alloc_index)
}
// Other global memory should trace races but be allocated at the 0 timestamp.
@ -704,7 +713,7 @@ impl VClockAlloc {
| MiriMemoryKind::ExternStatic
| MiriMemoryKind::Tls,
)
| MemoryKind::CallerLocation => (0, VectorIdx::MAX_INDEX),
| MemoryKind::CallerLocation => (VTimestamp::ZERO, VectorIdx::MAX_INDEX),
};
VClockAlloc {
alloc_ranges: RefCell::new(RangeMap::new(
@ -735,7 +744,7 @@ impl VClockAlloc {
let idx = l_remainder_slice
.iter()
.enumerate()
.find_map(|(idx, &r)| if r == 0 { None } else { Some(idx) })
.find_map(|(idx, &r)| if r == VTimestamp::ZERO { None } else { Some(idx) })
.expect("Invalid VClock Invariant");
Some(idx + r_slice.len())
} else {
@ -762,7 +771,7 @@ impl VClockAlloc {
) -> InterpResult<'tcx> {
let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
let write_clock;
let (other_action, other_thread, _other_clock) = if range.write
let (other_action, other_thread, other_clock) = if range.write
> current_clocks.clock[range.write_index]
{
// Convert the write action into the vector clock it
@ -799,14 +808,19 @@ impl VClockAlloc {
let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
// Throw the data-race detection.
throw_ub_format!(
"Data race detected between {} on {} and {} on {} at {:?}",
action,
current_thread_info,
other_action,
other_thread_info,
ptr_dbg,
)
Err(err_machine_stop!(TerminationInfo::DataRace {
ptr: ptr_dbg,
op1: RacingOp {
action: other_action.to_string(),
thread_info: other_thread_info,
span: other_clock.as_slice()[other_thread.index()].span_data(),
},
op2: RacingOp {
action: action.to_string(),
thread_info: current_thread_info,
span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
},
}))?
}
/// Detect racing atomic read and writes (not data races)
@ -840,12 +854,14 @@ impl VClockAlloc {
range: AllocRange,
machine: &MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let current_span = machine.current_span();
let global = machine.data_race.as_ref().unwrap();
if global.race_detecting() {
let (index, clocks) = global.current_thread_state(&machine.threads);
let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
if let Err(DataRace) = range.read_race_detect(&clocks, index) {
if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) {
drop(clocks);
// Report data-race.
return Self::report_data_race(
global,
@ -871,11 +887,15 @@ impl VClockAlloc {
write_type: WriteType,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let current_span = machine.current_span();
let global = machine.data_race.as_mut().unwrap();
if global.race_detecting() {
let (index, clocks) = global.current_thread_state(&machine.threads);
let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
if let Err(DataRace) =
range.write_race_detect(&mut clocks, index, write_type, current_span)
{
drop(clocks);
// Report data-race
return Self::report_data_race(
global,
@ -1100,9 +1120,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
size.bytes()
);
let current_span = this.machine.current_span();
// Perform the atomic operation.
data_race.maybe_perform_sync_operation(
&this.machine.threads,
current_span,
|index, mut clocks| {
for (offset, range) in
alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size)
@ -1303,7 +1325,12 @@ impl GlobalState {
// Hook for thread creation, enabled multi-threaded execution and marks
// the current thread timestamp as happening-before the current thread.
#[inline]
pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: ThreadId) {
pub fn thread_created(
&mut self,
thread_mgr: &ThreadManager<'_, '_>,
thread: ThreadId,
current_span: Span,
) {
let current_index = self.current_index(thread_mgr);
// Enable multi-threaded execution, there are now at least two threads
@ -1320,7 +1347,7 @@ impl GlobalState {
// Now re-configure the re-use candidate, increment the clock
// for the new sync use of the vector.
let vector_clocks = self.vector_clocks.get_mut();
vector_clocks[reuse_index].increment_clock(reuse_index);
vector_clocks[reuse_index].increment_clock(reuse_index, current_span);
// Locate the old thread the vector was associated with and update
// it to represent the new thread instead.
@ -1360,8 +1387,8 @@ impl GlobalState {
// Advance both threads after the synchronized operation.
// Both operations are considered to have release semantics.
current.increment_clock(current_index);
created.increment_clock(created_index);
current.increment_clock(current_index, current_span);
created.increment_clock(created_index, current_span);
}
/// Hook on a thread join to update the implicit happens-before relation between the joined
@ -1427,13 +1454,13 @@ impl GlobalState {
/// This should be called strictly before any calls to
/// `thread_joined`.
#[inline]
pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>) {
pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>, current_span: Span) {
let current_index = self.current_index(thread_mgr);
// Increment the clock to a unique termination timestamp.
let vector_clocks = self.vector_clocks.get_mut();
let current_clocks = &mut vector_clocks[current_index];
current_clocks.increment_clock(current_index);
current_clocks.increment_clock(current_index, current_span);
// Load the current thread id for the executing vector.
let vector_info = self.vector_info.get_mut();
@ -1462,13 +1489,14 @@ impl GlobalState {
fn maybe_perform_sync_operation<'tcx>(
&self,
thread_mgr: &ThreadManager<'_, '_>,
current_span: Span,
op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>,
) -> InterpResult<'tcx> {
if self.multi_threaded.get() {
let (index, clocks) = self.current_thread_state_mut(thread_mgr);
if op(index, clocks)? {
let (_, mut clocks) = self.current_thread_state_mut(thread_mgr);
clocks.increment_clock(index);
clocks.increment_clock(index, current_span);
}
}
Ok(())
@ -1501,10 +1529,10 @@ impl GlobalState {
/// since an acquire operation should have occurred before, however
/// for futex & condvar operations this is not the case and this
/// operation must be used.
pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId) {
pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId, current_span: Span) {
let (index, mut clocks) = self.load_thread_state_mut(thread);
lock.clone_from(&clocks.clock);
clocks.increment_clock(index);
clocks.increment_clock(index, current_span);
}
/// Release a lock handle, express that this happens-before
@ -1514,10 +1542,15 @@ impl GlobalState {
/// For normal locks this should be equivalent to `validate_lock_release`.
/// This function only exists for joining over the set of concurrent readers
/// in a read-write lock and should not be used for anything else.
pub fn validate_lock_release_shared(&self, lock: &mut VClock, thread: ThreadId) {
pub fn validate_lock_release_shared(
&self,
lock: &mut VClock,
thread: ThreadId,
current_span: Span,
) {
let (index, mut clocks) = self.load_thread_state_mut(thread);
lock.join(&clocks.clock);
clocks.increment_clock(index);
clocks.increment_clock(index, current_span);
}
/// Load the vector index used by the given thread as well as the set of vector clocks

View file

@ -160,6 +160,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let current_thread = this.get_active_thread();
let current_span = this.machine.current_span();
let init_once = &mut this.machine.threads.sync.init_onces[id];
assert_eq!(
@ -172,7 +173,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Each complete happens-before the end of the wait
if let Some(data_race) = &this.machine.data_race {
data_race.validate_lock_release(&mut init_once.data_race, current_thread);
data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
}
// Wake up everyone.
@ -188,6 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let current_thread = this.get_active_thread();
let current_span = this.machine.current_span();
let init_once = &mut this.machine.threads.sync.init_onces[id];
assert_eq!(
init_once.status,
@ -197,7 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Each complete happens-before the end of the wait
if let Some(data_race) = &this.machine.data_race {
data_race.validate_lock_release(&mut init_once.data_race, current_thread);
data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
}
// Wake up one waiting thread, so they can go ahead and try to init this.

View file

@ -359,6 +359,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// return `None`.
fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option<usize> {
let this = self.eval_context_mut();
let current_span = this.machine.current_span();
let mutex = &mut this.machine.threads.sync.mutexes[id];
if let Some(current_owner) = mutex.owner {
// Mutex is locked.
@ -375,7 +376,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// The mutex is completely unlocked. Try transfering ownership
// to another thread.
if let Some(data_race) = &this.machine.data_race {
data_race.validate_lock_release(&mut mutex.data_race, current_owner);
data_race.validate_lock_release(
&mut mutex.data_race,
current_owner,
current_span,
);
}
this.mutex_dequeue_and_lock(id);
}
@ -454,6 +459,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
/// Returns `true` if succeeded, `false` if this `reader` did not hold the lock.
fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool {
let this = self.eval_context_mut();
let current_span = this.machine.current_span();
let rwlock = &mut this.machine.threads.sync.rwlocks[id];
match rwlock.readers.entry(reader) {
Entry::Occupied(mut entry) => {
@ -470,7 +476,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
Entry::Vacant(_) => return false, // we did not even own this lock
}
if let Some(data_race) = &this.machine.data_race {
data_race.validate_lock_release_shared(&mut rwlock.data_race_reader, reader);
data_race.validate_lock_release_shared(
&mut rwlock.data_race_reader,
reader,
current_span,
);
}
// The thread was a reader. If the lock is not held any more, give it to a writer.
@ -511,6 +521,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
#[inline]
fn rwlock_writer_unlock(&mut self, id: RwLockId, expected_writer: ThreadId) -> bool {
let this = self.eval_context_mut();
let current_span = this.machine.current_span();
let rwlock = &mut this.machine.threads.sync.rwlocks[id];
if let Some(current_writer) = rwlock.writer {
if current_writer != expected_writer {
@ -523,8 +534,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// since this writer happens-before both the union of readers once they are finished
// and the next writer
if let Some(data_race) = &this.machine.data_race {
data_race.validate_lock_release(&mut rwlock.data_race, current_writer);
data_race.validate_lock_release(&mut rwlock.data_race_reader, current_writer);
data_race.validate_lock_release(
&mut rwlock.data_race,
current_writer,
current_span,
);
data_race.validate_lock_release(
&mut rwlock.data_race_reader,
current_writer,
current_span,
);
}
// The thread was a writer.
//
@ -595,12 +614,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> {
let this = self.eval_context_mut();
let current_thread = this.get_active_thread();
let current_span = this.machine.current_span();
let condvar = &mut this.machine.threads.sync.condvars[id];
let data_race = &this.machine.data_race;
// Each condvar signal happens-before the end of the condvar wake
if let Some(data_race) = data_race {
data_race.validate_lock_release(&mut condvar.data_race, current_thread);
data_race.validate_lock_release(&mut condvar.data_race, current_thread, current_span);
}
condvar.waiters.pop_front().map(|waiter| {
if let Some(data_race) = data_race {
@ -628,12 +648,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn futex_wake(&mut self, addr: u64, bitset: u32) -> Option<ThreadId> {
let this = self.eval_context_mut();
let current_thread = this.get_active_thread();
let current_span = this.machine.current_span();
let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr)?;
let data_race = &this.machine.data_race;
// Each futex-wake happens-before the end of the futex wait
if let Some(data_race) = data_race {
data_race.validate_lock_release(&mut futex.data_race, current_thread);
data_race.validate_lock_release(&mut futex.data_race, current_thread, current_span);
}
// Wake up the first thread in the queue that matches any of the bits in the bitset.

View file

@ -13,6 +13,7 @@ use rustc_hir::def_id::DefId;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::Mutability;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use crate::concurrency::data_race;
@ -617,6 +618,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
fn thread_terminated(
&mut self,
mut data_race: Option<&mut data_race::GlobalState>,
current_span: Span,
) -> Vec<Pointer<Provenance>> {
let mut free_tls_statics = Vec::new();
{
@ -634,7 +636,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
}
// Set the thread into a terminated state in the data-race detector.
if let Some(ref mut data_race) = data_race {
data_race.thread_terminated(self);
data_race.thread_terminated(self, current_span);
}
// Check if we need to unblock any threads.
let mut joined_threads = vec![]; // store which threads joined, we'll need it
@ -813,8 +815,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let mut state = tls::TlsDtorsState::default();
Box::new(move |m| state.on_stack_empty(m))
});
let current_span = this.machine.current_span();
if let Some(data_race) = &mut this.machine.data_race {
data_race.thread_created(&this.machine.threads, new_thread_id);
data_race.thread_created(&this.machine.threads, new_thread_id, current_span);
}
// Write the current thread-id, switch to the next thread later
@ -1041,7 +1044,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated");
thread.state = ThreadState::Terminated;
for ptr in this.machine.threads.thread_terminated(this.machine.data_race.as_mut()) {
let current_span = this.machine.current_span();
for ptr in
this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span)
{
this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
}
Ok(())

View file

@ -1,6 +1,11 @@
use rustc_index::vec::Idx;
use rustc_span::{Span, SpanData, DUMMY_SP};
use smallvec::SmallVec;
use std::{cmp::Ordering, fmt::Debug, ops::Index};
use std::{
cmp::Ordering,
fmt::Debug,
ops::{Index, IndexMut},
};
/// A vector clock index, this is associated with a thread id
/// but in some cases one vector index may be shared with
@ -40,9 +45,42 @@ impl From<u32> for VectorIdx {
/// clock vectors larger than this will be stored on the heap
const SMALL_VECTOR: usize = 4;
/// The type of the time-stamps recorded in the data-race detector
/// set to a type of unsigned integer
pub type VTimestamp = u32;
/// The time-stamps recorded in the data-race detector consist of both
/// a 32-bit unsigned integer which is the actual timestamp, and a `Span`
/// so that diagnostics can report what code was responsible for an operation.
#[derive(Clone, Copy, Debug)]
pub struct VTimestamp {
time: u32,
pub span: Span,
}
impl VTimestamp {
pub const ZERO: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP };
pub fn span_data(&self) -> SpanData {
self.span.data()
}
}
impl PartialEq for VTimestamp {
fn eq(&self, other: &Self) -> bool {
self.time == other.time
}
}
impl Eq for VTimestamp {}
impl PartialOrd for VTimestamp {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for VTimestamp {
fn cmp(&self, other: &Self) -> Ordering {
self.time.cmp(&other.time)
}
}
/// A vector clock for detecting data-races, this is conceptually
/// a map from a vector index (and thus a thread id) to a timestamp.
@ -62,7 +100,7 @@ impl VClock {
/// for a value at the given index
pub fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
let len = index.index() + 1;
let mut vec = smallvec::smallvec![0; len];
let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
vec[index.index()] = timestamp;
VClock(vec)
}
@ -79,7 +117,7 @@ impl VClock {
#[inline]
fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
if self.0.len() < min_len {
self.0.resize(min_len, 0);
self.0.resize(min_len, VTimestamp::ZERO);
}
assert!(self.0.len() >= min_len);
self.0.as_mut_slice()
@ -88,11 +126,14 @@ impl VClock {
/// Increment the vector clock at a known index
/// this will panic if the vector index overflows
#[inline]
pub fn increment_index(&mut self, idx: VectorIdx) {
pub fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
let idx = idx.index();
let mut_slice = self.get_mut_with_min_len(idx + 1);
let idx_ref = &mut mut_slice[idx];
*idx_ref = idx_ref.checked_add(1).expect("Vector clock overflow")
idx_ref.time = idx_ref.time.checked_add(1).expect("Vector clock overflow");
if !current_span.is_dummy() {
idx_ref.span = current_span;
}
}
// Join the two vector-clocks together, this
@ -102,14 +143,23 @@ impl VClock {
let rhs_slice = other.as_slice();
let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
let l_span = l.span;
let r_span = r.span;
*l = r.max(*l);
l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
}
}
/// Set the element at the current index of the vector
pub fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
let prev_span = mut_slice[idx.index()].span;
mut_slice[idx.index()] = other[idx];
let span = &mut mut_slice[idx.index()].span;
*span = span.substitute_dummy(prev_span);
}
/// Set the vector to the all-zero vector
@ -313,7 +363,14 @@ impl Index<VectorIdx> for VClock {
#[inline]
fn index(&self, index: VectorIdx) -> &VTimestamp {
self.as_slice().get(index.to_u32() as usize).unwrap_or(&0)
self.as_slice().get(index.to_u32() as usize).unwrap_or(&VTimestamp::ZERO)
}
}
impl IndexMut<VectorIdx> for VClock {
#[inline]
fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
self.0.as_mut_slice().get_mut(index.to_u32() as usize).unwrap()
}
}
@ -324,6 +381,7 @@ impl Index<VectorIdx> for VClock {
mod tests {
use super::{VClock, VTimestamp, VectorIdx};
use rustc_span::DUMMY_SP;
use std::cmp::Ordering;
#[test]
@ -331,13 +389,13 @@ mod tests {
let mut c1 = VClock::default();
let mut c2 = VClock::default();
assert_eq!(c1, c2);
c1.increment_index(VectorIdx(5));
c1.increment_index(VectorIdx(5), DUMMY_SP);
assert_ne!(c1, c2);
c2.increment_index(VectorIdx(53));
c2.increment_index(VectorIdx(53), DUMMY_SP);
assert_ne!(c1, c2);
c1.increment_index(VectorIdx(53));
c1.increment_index(VectorIdx(53), DUMMY_SP);
assert_ne!(c1, c2);
c2.increment_index(VectorIdx(5));
c2.increment_index(VectorIdx(5), DUMMY_SP);
assert_eq!(c1, c2);
}
@ -386,14 +444,14 @@ mod tests {
);
}
fn from_slice(mut slice: &[VTimestamp]) -> VClock {
fn from_slice(mut slice: &[u32]) -> VClock {
while let Some(0) = slice.last() {
slice = &slice[..slice.len() - 1]
}
VClock(smallvec::SmallVec::from_slice(slice))
VClock(slice.iter().copied().map(|time| VTimestamp { time, span: DUMMY_SP }).collect())
}
fn assert_order(l: &[VTimestamp], r: &[VTimestamp], o: Option<Ordering>) {
fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
let l = from_slice(l);
let r = from_slice(r);

View file

@ -258,7 +258,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
// The thread index and timestamp of the initialisation write
// are never meaningfully used, so it's fine to leave them as 0
store_index: VectorIdx::from(0),
timestamp: 0,
timestamp: VTimestamp::ZERO,
val: init,
is_seqcst: false,
load_info: RefCell::new(LoadInfo::default()),

View file

@ -35,6 +35,17 @@ pub enum TerminationInfo {
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 {
@ -55,6 +66,12 @@ 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
),
}
}
}
@ -167,7 +184,7 @@ pub fn report_error<'tcx, 'mir>(
Abort(_) => Some("abnormal termination"),
UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
Some("unsupported operation"),
StackedBorrowsUb { .. } => Some("Undefined Behavior"),
StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
Deadlock => Some("deadlock"),
MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
};
@ -205,6 +222,12 @@ pub fn report_error<'tcx, 'mir>(
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)
@ -339,9 +362,11 @@ fn report_msg<'tcx>(
}
// Show note and help messages.
let mut extra_span = false;
for (span_data, note) in &notes {
if let Some(span_data) = span_data {
err.span_note(span_data.span(), note);
extra_span = true;
} else {
err.note(note);
}
@ -349,13 +374,14 @@ fn report_msg<'tcx>(
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() {

View file

@ -956,6 +956,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
&ecx.machine.threads,
alloc.size(),
kind,
ecx.machine.current_span(),
)
});
let buffer_alloc = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation);

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a Unique retag
|
LL | let res = helper(val, ptr);
| ^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
note: inside `main`
--> $DIR/box-cell-alias.rs:LL:CC

View file

@ -37,7 +37,7 @@ pub fn main() {
let pointer = &*ptr.0;
// Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.
*pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>`
*pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/alloc_read_race.rs:LL:CC
|
LL | *pointer.load(Ordering::Relaxed)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/alloc_read_race.rs:LL:CC
|
LL | pointer.store(Box::into_raw(Box::new_uninit()), Ordering::Relaxed);
| ^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/alloc_read_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -35,7 +35,7 @@ pub fn main() {
let j2 = spawn(move || {
let pointer = &*ptr.0;
*pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>`
*pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/alloc_write_race.rs:LL:CC
|
LL | *pointer.load(Ordering::Relaxed) = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/alloc_write_race.rs:LL:CC
|
LL | .store(Box::into_raw(Box::<usize>::new_uninit()) as *mut usize, Ordering::Relaxed);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/alloc_write_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -20,7 +20,7 @@ pub fn main() {
});
let j2 = spawn(move || {
(&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>`
(&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_read_na_write_race1.rs:LL:CC
|
LL | (&*c.0).load(Ordering::SeqCst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/atomic_read_na_write_race1.rs:LL:CC
|
LL | *(c.0 as *mut usize) = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/atomic_read_na_write_race1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -23,7 +23,7 @@ pub fn main() {
let j2 = spawn(move || {
let atomic_ref = &mut *c.0;
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>`
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_read_na_write_race2.rs:LL:CC
|
LL | *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/atomic_read_na_write_race2.rs:LL:CC
|
LL | atomic_ref.load(Ordering::SeqCst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/atomic_read_na_write_race2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -23,7 +23,7 @@ pub fn main() {
let j2 = spawn(move || {
let atomic_ref = &mut *c.0;
*atomic_ref.get_mut() //~ ERROR: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
*atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_write_na_read_race1.rs:LL:CC
|
LL | *atomic_ref.get_mut()
| ^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/atomic_write_na_read_race1.rs:LL:CC
|
LL | atomic_ref.store(32, Ordering::SeqCst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/atomic_write_na_read_race1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -20,7 +20,7 @@ pub fn main() {
});
let j2 = spawn(move || {
(&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>`
(&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_write_na_read_race2.rs:LL:CC
|
LL | (&*c.0).store(32, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/atomic_write_na_read_race2.rs:LL:CC
|
LL | let _val = *(c.0 as *mut usize);
| ^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/atomic_write_na_read_race2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -20,7 +20,7 @@ pub fn main() {
});
let j2 = spawn(move || {
(&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>`
(&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_write_na_write_race1.rs:LL:CC
|
LL | (&*c.0).store(64, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/atomic_write_na_write_race1.rs:LL:CC
|
LL | *(c.0 as *mut usize) = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/atomic_write_na_write_race1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -23,7 +23,7 @@ pub fn main() {
let j2 = spawn(move || {
let atomic_ref = &mut *c.0;
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
*atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_write_na_write_race2.rs:LL:CC
|
LL | *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/atomic_write_na_write_race2.rs:LL:CC
|
LL | atomic_ref.store(64, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/atomic_write_na_write_race2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -34,7 +34,7 @@ fn main() {
let join2 = unsafe {
spawn(move || {
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
})
};

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dangling_thread_async_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/dangling_thread_async_race.rs:LL:CC
|
LL | *c.0 = 32;
| ^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dangling_thread_async_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -33,6 +33,6 @@ fn main() {
spawn(|| ()).join().unwrap();
unsafe {
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
}
}

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
--> $DIR/dangling_thread_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/dangling_thread_race.rs:LL:CC
|
LL | *c.0 = 32;
| ^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_thread_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -25,7 +25,7 @@ pub fn main() {
let j2 = spawn(move || {
__rust_dealloc(
//~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
//~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
ptr.0 as *mut _,
std::mem::size_of::<usize>(),
std::mem::align_of::<usize>(),

View file

@ -1,4 +1,4 @@
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_read_race1.rs:LL:CC
|
LL | / __rust_dealloc(
@ -7,11 +7,16 @@ LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
| |_____________^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/dealloc_read_race1.rs:LL:CC
|
LL | let _val = *ptr.0;
| ^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dealloc_read_race1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -28,7 +28,7 @@ pub fn main() {
});
let j2 = spawn(move || {
// Also an error of the form: Data race detected between Read on thread `<unnamed>` and Deallocate on thread `<unnamed>`
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
// but the invalid allocation is detected first.
*ptr.0 //~ ERROR: dereferenced after this allocation got freed
});

View file

@ -35,7 +35,7 @@ pub fn main() {
sleep(Duration::from_millis(200));
// Now `stack_var` gets deallocated.
} //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
} //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
});
let j2 = spawn(move || {

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_read_race_stack.rs:LL:CC
|
LL | }
| ^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
| ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/dealloc_read_race_stack.rs:LL:CC
|
LL | *pointer.load(Ordering::Acquire)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dealloc_read_race_stack.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -24,7 +24,7 @@ pub fn main() {
let j2 = spawn(move || {
__rust_dealloc(
//~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
//~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
ptr.0 as *mut _,
std::mem::size_of::<usize>(),
std::mem::align_of::<usize>(),

View file

@ -1,4 +1,4 @@
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_write_race1.rs:LL:CC
|
LL | / __rust_dealloc(
@ -7,11 +7,16 @@ LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| |_____________^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/dealloc_write_race1.rs:LL:CC
|
LL | *ptr.0 = 2;
| ^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dealloc_write_race1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -27,7 +27,7 @@ pub fn main() {
});
let j2 = spawn(move || {
// Also an error of the form: Data race detected between Write on thread `<unnamed>` and Deallocate on thread `<unnamed>`
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
// but the invalid allocation is detected first.
*ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed
});

View file

@ -35,7 +35,7 @@ pub fn main() {
sleep(Duration::from_millis(200));
// Now `stack_var` gets deallocated.
} //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
} //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
});
let j2 = spawn(move || {

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_write_race_stack.rs:LL:CC
|
LL | }
| ^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/dealloc_write_race_stack.rs:LL:CC
|
LL | *pointer.load(Ordering::Acquire) = 3;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dealloc_write_race_stack.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -30,7 +30,7 @@ pub fn main() {
});
let j2 = spawn(move || {
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/enable_after_join_to_main.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/enable_after_join_to_main.rs:LL:CC
|
LL | *c.0 = 32;
| ^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/enable_after_join_to_main.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -20,5 +20,5 @@ fn main() {
// The fence is useless, since it did not happen-after the `store` in the other thread.
// Hence this is a data race.
// Also see https://github.com/rust-lang/miri/issues/2192.
unsafe { V = 2 } //~ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
unsafe { V = 2 } //~ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
}

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
--> $DIR/fence_after_load.rs:LL:CC
|
LL | unsafe { V = 2 }
| ^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
| ^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/fence_after_load.rs:LL:CC
|
LL | unsafe { V = 1 }
| ^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/fence_after_load.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ pub fn main() {
});
let j2 = spawn(move || {
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>`
*c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/read_write_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
| ^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/read_write_race.rs:LL:CC
|
LL | let _val = *c.0;
| ^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/read_write_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -42,7 +42,7 @@ pub fn main() {
sleep(Duration::from_millis(200));
stack_var //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
stack_var //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
});
let j2 = spawn(move || {

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/read_write_race_stack.rs:LL:CC
|
LL | stack_var
| ^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/read_write_race_stack.rs:LL:CC
|
LL | *pointer.load(Ordering::Acquire) = 3;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/read_write_race_stack.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -37,7 +37,7 @@ pub fn main() {
let j3 = spawn(move || {
if SYNC.load(Ordering::Acquire) == 2 {
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {
0
}

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/relax_acquire_race.rs:LL:CC
|
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/relax_acquire_race.rs:LL:CC
|
LL | *c.0 = 1;
| ^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/relax_acquire_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -41,7 +41,7 @@ pub fn main() {
let j3 = spawn(move || {
sleep(Duration::from_millis(500));
if SYNC.load(Ordering::Acquire) == 3 {
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {
0
}

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/release_seq_race.rs:LL:CC
|
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/release_seq_race.rs:LL:CC
|
LL | *c.0 = 1;
| ^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/release_seq_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -37,7 +37,7 @@ pub fn main() {
let j2 = spawn(move || {
if SYNC.load(Ordering::Acquire) == 2 {
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {
0
}

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/release_seq_race_same_thread.rs:LL:CC
|
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/release_seq_race_same_thread.rs:LL:CC
|
LL | *c.0 = 1;
| ^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/release_seq_race_same_thread.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -38,7 +38,7 @@ pub fn main() {
let j3 = spawn(move || {
if SYNC.load(Ordering::Acquire) == 3 {
*c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
} else {
0
}

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/rmw_race.rs:LL:CC
|
LL | *c.0
| ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/rmw_race.rs:LL:CC
|
LL | *c.0 = 1;
| ^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/rmw_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -21,4 +21,4 @@ fn race(local: i32) {
// Deallocating the local (when `main` returns)
// races with the read in the other thread.
// Make sure the error points at this function's end, not just the call site.
} //~ERROR: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>`
} //~ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main`

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
--> $DIR/stack_pop_race.rs:LL:CC
|
LL | }
| ^ Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
| ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/stack_pop_race.rs:LL:CC
|
LL | let _val = unsafe { *ptr.0 };
| ^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
note: inside `main`
--> $DIR/stack_pop_race.rs:LL:CC

View file

@ -19,7 +19,7 @@ pub fn main() {
});
let j2 = spawn(move || {
*c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
*c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
});
j1.join().unwrap();

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/write_write_race.rs:LL:CC
|
LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/write_write_race.rs:LL:CC
|
LL | *c.0 = 32;
| ^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/write_write_race.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -39,7 +39,7 @@ pub fn main() {
sleep(Duration::from_millis(200));
stack_var = 1usize; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
stack_var = 1usize; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
// read to silence errors
stack_var

View file

@ -1,12 +1,17 @@
error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/write_write_race_stack.rs:LL:CC
|
LL | stack_var = 1usize;
| ^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
| ^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
|
help: and (1) occurred earlier here
--> $DIR/write_write_race_stack.rs:LL:CC
|
LL | *pointer.load(Ordering::Acquire) = 3;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/write_write_race_stack.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -14,7 +14,7 @@ help: then it's defined here again, in crate `exported_symbol_clashing`
|
LL | fn bar() {}
| ^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/exported_symbol_clashing.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -12,7 +12,7 @@ LL | |
LL | | unreachable!()
LL | | }
| |_^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/exported_symbol_shim_clashing.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *target = 13;
| ^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/alias_through_mutation.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
| ^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
note: inside `main`
--> $DIR/aliasing_mut1.rs:LL:CC

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | pub fn safe(_x: &i32, _y: &mut i32) {}
| ^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
note: inside `main`
--> $DIR/aliasing_mut2.rs:LL:CC

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
|
LL | safe_raw(xraw, xshr);
| ^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
note: inside `main`
--> $DIR/aliasing_mut3.rs:LL:CC

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
| ^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
note: inside `main`
--> $DIR/aliasing_mut4.rs:LL:CC

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *our = 5;
| ^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
note: inside `demo_box_advanced_unique`
--> $DIR/box_exclusive_violation1.rs:LL:CC

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 {
| ^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
note: inside `main`
--> $DIR/box_noalias_violation.rs:LL:CC

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique retag
|
LL | unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/buggy_as_mut_slice.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x10] by a Unique retag
|
LL | from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/buggy_split_at_mut.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *base = 1;
| ^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/disable_mut_does_not_merge_srw.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
|
LL | x.do_bad();
| ^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/fnentry_invalidation.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique FnEntry reta
|
LL | let _ = t.sli.as_mut_ptr();
| ^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/fnentry_invalidation2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -16,7 +16,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a write access
|
LL | ptr1.write(0);
| ^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
note: inside `main`
--> $DIR/illegal_deALLOC.rs:LL:CC

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
LL | let _val = unsafe { *xraw };
| ^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a SharedReadOnly reta
|
LL | let shr = unsafe { &*xraw };
| ^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
LL | let _val = unsafe { *xref1.r };
| ^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read3.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
LL | let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
| ^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read4.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [$HEX..$HEX] by a read access
|
LL | mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref
| ^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read5.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
|
LL | let x = &mut *x; // kill `raw`
| ^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read6.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
LL | let _val = ptr::read(raw);
| ^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read7.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *y2 += 1;
| ^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read8.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *exposed_ptr = 0;
| ^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read_despite_exposed1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
LL | let _val = *exposed_ptr;
| ^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_read_despite_exposed2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
|
LL | let x: *mut u32 = xref as *const _ as *mut _;
| ^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_write1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
|
LL | drop(&mut *target); // reborrow
| ^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_write2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
|
LL | let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag
| ^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_write3.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
|
LL | let _mut_ref: &mut i32 = unsafe { mem::transmute(raw) }; // &mut, with raw tag
| ^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_write4.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | unsafe { *xraw = 15 };
| ^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_write5.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | fn foo(a: &mut u32, y: *mut u32) -> u32 {
| ^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
note: inside `main`
--> $DIR/illegal_write6.rs:LL:CC

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *exposed_ptr = 0;
| ^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/illegal_write_despite_exposed1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *c.get() = UnsafeCell::new(1); // invalidates inner_shr
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/interior_mut1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/interior_mut2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | fn inner(x: *mut i32, _y: &mut i32) {
| ^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
note: inside `main`
--> $DIR/invalidate_against_protector1.rs:LL:CC

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | fn inner(x: *mut i32, _y: &i32) {
| ^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
note: inside `main`
--> $DIR/invalidate_against_protector2.rs:LL:CC

View file

@ -16,7 +16,7 @@ help: <TAG> is this argument
|
LL | fn inner(x: *mut i32, _y: &i32) {
| ^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
note: inside `main`
--> $DIR/invalidate_against_protector3.rs:LL:CC

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
|
LL | let _val = unsafe { *xraw }; // invalidate xref
| ^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/load_invalid_mut.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View file

@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
|
LL | unsafe { *xraw = 42 }; // unfreeze
| ^^^^^^^^^^
= note: BACKTRACE:
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/load_invalid_shr.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Some files were not shown because too many files have changed in this diff Show more