Auto merge of #117579 - RalfJung:miri, r=RalfJung

Miri subtree update

r? `@ghost`
This commit is contained in:
bors 2023-11-04 17:21:07 +00:00
commit 9c8a2694fa
99 changed files with 574 additions and 255 deletions

View File

@ -223,9 +223,10 @@ degree documented below):
- All Rust [Tier 1 targets](https://doc.rust-lang.org/rustc/platform-support.html) are supported by - All Rust [Tier 1 targets](https://doc.rust-lang.org/rustc/platform-support.html) are supported by
Miri. They are all checked on Miri's CI, and some (at least one per OS) are even checked on every Miri. They are all checked on Miri's CI, and some (at least one per OS) are even checked on every
Rust PR, so the shipped Miri should always work on these targets. Rust PR, so the shipped Miri should always work on these targets.
- We also support `s390x-unknown-linux-gnu` as our "big-endian target of choice". - `aarch64-apple-darwin` is supported.
- `s390x-unknown-linux-gnu` is supported as our "big-endian target of choice".
- For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we - For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we
make no promises. make no promises and we don't run tests for such targets.
- For targets on other operating systems, even basic operations such as printing to the standard - For targets on other operating systems, even basic operations such as printing to the standard
output might not work, and Miri might fail before even reaching the `main` function. output might not work, and Miri might fail before even reaching the `main` function.

View File

@ -1 +1 @@
2e4e2a8f288f642cafcc41fff211955ceddc453d 3aaa0f57b7b877ef58532a8de075d1e5a79142bf

View File

@ -241,7 +241,7 @@ fn run_compiler(
mut args: Vec<String>, mut args: Vec<String>,
target_crate: bool, target_crate: bool,
callbacks: &mut (dyn rustc_driver::Callbacks + Send), callbacks: &mut (dyn rustc_driver::Callbacks + Send),
using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool> using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool>,
) -> ! { ) -> ! {
if target_crate { if target_crate {
// Miri needs a custom sysroot for target crates. // Miri needs a custom sysroot for target crates.
@ -275,7 +275,8 @@ fn run_compiler(
// Invoke compiler, and handle return code. // Invoke compiler, and handle return code.
let exit_code = rustc_driver::catch_with_exit_code(move || { let exit_code = rustc_driver::catch_with_exit_code(move || {
rustc_driver::RunCompiler::new(&args, callbacks) rustc_driver::RunCompiler::new(&args, callbacks)
.set_using_internal_features(using_internal_features).run() .set_using_internal_features(using_internal_features)
.run()
}); });
std::process::exit(exit_code) std::process::exit(exit_code)
} }
@ -297,7 +298,8 @@ fn main() {
// If the environment asks us to actually be rustc, then do that. // If the environment asks us to actually be rustc, then do that.
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
// Earliest rustc setup. // Earliest rustc setup.
let using_internal_features = rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ()); let using_internal_features =
rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ());
rustc_driver::init_rustc_env_logger(&handler); rustc_driver::init_rustc_env_logger(&handler);
let target_crate = if crate_kind == "target" { let target_crate = if crate_kind == "target" {
@ -318,7 +320,8 @@ fn main() {
} }
// Add an ICE bug report hook. // Add an ICE bug report hook.
let using_internal_features = rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ()); let using_internal_features =
rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ());
// Init loggers the Miri way. // Init loggers the Miri way.
init_early_loggers(&handler); init_early_loggers(&handler);
@ -581,5 +584,10 @@ fn main() {
debug!("rustc arguments: {:?}", rustc_args); debug!("rustc arguments: {:?}", rustc_args);
debug!("crate arguments: {:?}", miri_config.args); debug!("crate arguments: {:?}", miri_config.args);
run_compiler(rustc_args, /* target_crate: */ true, &mut MiriCompilerCalls { miri_config }, using_internal_features) run_compiler(
rustc_args,
/* target_crate: */ true,
&mut MiriCompilerCalls { miri_config },
using_internal_features,
)
} }

View File

@ -41,7 +41,6 @@
//! on the data-race detection code. //! on the data-race detection code.
use std::{ use std::{
borrow::Cow,
cell::{Cell, Ref, RefCell, RefMut}, cell::{Cell, Ref, RefCell, RefMut},
fmt::Debug, fmt::Debug,
mem, mem,
@ -52,7 +51,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_index::{Idx, IndexVec}; use rustc_index::{Idx, IndexVec};
use rustc_middle::mir; use rustc_middle::mir;
use rustc_span::Span; use rustc_span::Span;
use rustc_target::abi::{Align, Size}; use rustc_target::abi::{Align, HasDataLayout, Size};
use crate::diagnostics::RacingOp; use crate::diagnostics::RacingOp;
use crate::*; use crate::*;
@ -194,12 +193,19 @@ struct AtomicMemoryCellClocks {
size: Size, size: Size,
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum AtomicAccessType {
Load(AtomicReadOrd),
Store,
Rmw,
}
/// Type of write operation: allocating memory /// Type of write operation: allocating memory
/// non-atomic writes and deallocating memory /// non-atomic writes and deallocating memory
/// are all treated as writes for the purpose /// are all treated as writes for the purpose
/// of the data-race detector. /// of the data-race detector.
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum WriteType { enum NaWriteType {
/// Allocate memory. /// Allocate memory.
Allocate, Allocate,
@ -212,12 +218,48 @@ enum WriteType {
/// (Same for `Allocate` above.) /// (Same for `Allocate` above.)
Deallocate, Deallocate,
} }
impl WriteType {
fn get_descriptor(self) -> &'static str { impl NaWriteType {
fn description(self) -> &'static str {
match self { match self {
WriteType::Allocate => "Allocate", NaWriteType::Allocate => "creating a new allocation",
WriteType::Write => "Write", NaWriteType::Write => "non-atomic write",
WriteType::Deallocate => "Deallocate", NaWriteType::Deallocate => "deallocation",
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum AccessType {
NaRead,
NaWrite(NaWriteType),
AtomicLoad,
AtomicStore,
AtomicRmw,
}
impl AccessType {
fn description(self) -> &'static str {
match self {
AccessType::NaRead => "non-atomic read",
AccessType::NaWrite(w) => w.description(),
AccessType::AtomicLoad => "atomic load",
AccessType::AtomicStore => "atomic store",
AccessType::AtomicRmw => "atomic read-modify-write",
}
}
fn is_atomic(self) -> bool {
match self {
AccessType::AtomicLoad | AccessType::AtomicStore | AccessType::AtomicRmw => true,
AccessType::NaRead | AccessType::NaWrite(_) => false,
}
}
fn is_read(self) -> bool {
match self {
AccessType::AtomicLoad | AccessType::NaRead => true,
AccessType::NaWrite(_) | AccessType::AtomicStore | AccessType::AtomicRmw => false,
} }
} }
} }
@ -234,7 +276,7 @@ struct MemoryCellClocks {
/// The type of operation that the write index represents, /// The type of operation that the write index represents,
/// either newly allocated memory, a non-atomic write or /// either newly allocated memory, a non-atomic write or
/// a deallocation of memory. /// a deallocation of memory.
write_type: WriteType, write_type: NaWriteType,
/// The vector-clock of all non-atomic reads that happened since the last non-atomic write /// The vector-clock of all non-atomic reads that happened since the last non-atomic write
/// (i.e., we join together the "singleton" clocks corresponding to each read). It is reset to /// (i.e., we join together the "singleton" clocks corresponding to each read). It is reset to
@ -265,7 +307,7 @@ impl MemoryCellClocks {
MemoryCellClocks { MemoryCellClocks {
read: VClock::default(), read: VClock::default(),
write: (alloc_index, alloc), write: (alloc_index, alloc),
write_type: WriteType::Allocate, write_type: NaWriteType::Allocate,
atomic_ops: None, atomic_ops: None,
} }
} }
@ -488,7 +530,7 @@ impl MemoryCellClocks {
&mut self, &mut self,
thread_clocks: &mut ThreadClockSet, thread_clocks: &mut ThreadClockSet,
index: VectorIdx, index: VectorIdx,
write_type: WriteType, write_type: NaWriteType,
current_span: Span, current_span: Span,
) -> Result<(), DataRace> { ) -> Result<(), DataRace> {
log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, thread_clocks); log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, thread_clocks);
@ -526,7 +568,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
atomic: AtomicReadOrd, atomic: AtomicReadOrd,
) -> InterpResult<'tcx, Scalar<Provenance>> { ) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_ref(); let this = self.eval_context_ref();
this.atomic_access_check(place)?; this.atomic_access_check(place, AtomicAccessType::Load(atomic))?;
// This will read from the last store in the modification order of this location. In case // This will read from the last store in the modification order of this location. In case
// weak memory emulation is enabled, this may not be the store we will pick to actually read from and return. // weak memory emulation is enabled, this may not be the store we will pick to actually read from and return.
// This is fine with StackedBorrow and race checks because they don't concern metadata on // This is fine with StackedBorrow and race checks because they don't concern metadata on
@ -546,7 +588,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
atomic: AtomicWriteOrd, atomic: AtomicWriteOrd,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
this.atomic_access_check(dest)?; this.atomic_access_check(dest, AtomicAccessType::Store)?;
this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?;
this.validate_atomic_store(dest, atomic)?; this.validate_atomic_store(dest, atomic)?;
@ -558,8 +600,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
this.buffered_atomic_write(val, dest, atomic, val) this.buffered_atomic_write(val, dest, atomic, val)
} }
/// Perform an atomic operation on a memory location. /// Perform an atomic RMW operation on a memory location.
fn atomic_op_immediate( fn atomic_rmw_op_immediate(
&mut self, &mut self,
place: &MPlaceTy<'tcx, Provenance>, place: &MPlaceTy<'tcx, Provenance>,
rhs: &ImmTy<'tcx, Provenance>, rhs: &ImmTy<'tcx, Provenance>,
@ -568,7 +610,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
atomic: AtomicRwOrd, atomic: AtomicRwOrd,
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
this.atomic_access_check(place)?; this.atomic_access_check(place, AtomicAccessType::Rmw)?;
let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
@ -592,7 +634,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
atomic: AtomicRwOrd, atomic: AtomicRwOrd,
) -> InterpResult<'tcx, Scalar<Provenance>> { ) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
this.atomic_access_check(place)?; this.atomic_access_check(place, AtomicAccessType::Rmw)?;
let old = this.allow_data_races_mut(|this| this.read_scalar(place))?; let old = this.allow_data_races_mut(|this| this.read_scalar(place))?;
this.allow_data_races_mut(|this| this.write_scalar(new, place))?; this.allow_data_races_mut(|this| this.write_scalar(new, place))?;
@ -613,7 +655,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
atomic: AtomicRwOrd, atomic: AtomicRwOrd,
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
this.atomic_access_check(place)?; this.atomic_access_check(place, AtomicAccessType::Rmw)?;
let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; let old = this.allow_data_races_mut(|this| this.read_immediate(place))?;
let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?; let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?;
@ -652,7 +694,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, Immediate<Provenance>> { ) -> InterpResult<'tcx, Immediate<Provenance>> {
use rand::Rng as _; use rand::Rng as _;
let this = self.eval_context_mut(); let this = self.eval_context_mut();
this.atomic_access_check(place)?; this.atomic_access_check(place, AtomicAccessType::Rmw)?;
// Failure ordering cannot be stronger than success ordering, therefore first attempt // Failure ordering cannot be stronger than success ordering, therefore first attempt
// to read with the failure ordering and if successful then try again with the success // to read with the failure ordering and if successful then try again with the success
@ -838,48 +880,45 @@ impl VClockAlloc {
global: &GlobalState, global: &GlobalState,
thread_mgr: &ThreadManager<'_, '_>, thread_mgr: &ThreadManager<'_, '_>,
mem_clocks: &MemoryCellClocks, mem_clocks: &MemoryCellClocks,
action: &str, access: AccessType,
is_atomic: bool,
access_size: Size, access_size: Size,
ptr_dbg: Pointer<AllocId>, ptr_dbg: Pointer<AllocId>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let (current_index, current_clocks) = global.current_thread_state(thread_mgr); let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
let mut action = Cow::Borrowed(action); let mut other_size = None; // if `Some`, this was a size-mismatch race
let mut involves_non_atomic = true;
let write_clock; let write_clock;
let (other_action, other_thread, other_clock) = let (other_access, other_thread, other_clock) =
// First check the atomic-nonatomic cases. If it looks like multiple // First check the atomic-nonatomic cases. If it looks like multiple
// cases apply, this one should take precedence, else it might look like // cases apply, this one should take precedence, else it might look like
// we are reporting races between two non-atomic reads. // we are reporting races between two non-atomic reads.
if !is_atomic && if !access.is_atomic() &&
let Some(atomic) = mem_clocks.atomic() && let Some(atomic) = mem_clocks.atomic() &&
let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock) let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
{ {
(format!("Atomic Store"), idx, &atomic.write_vector) (AccessType::AtomicStore, idx, &atomic.write_vector)
} else if !is_atomic && } else if !access.is_atomic() &&
let Some(atomic) = mem_clocks.atomic() && let Some(atomic) = mem_clocks.atomic() &&
let Some(idx) = Self::find_gt_index(&atomic.read_vector, &current_clocks.clock) let Some(idx) = Self::find_gt_index(&atomic.read_vector, &current_clocks.clock)
{ {
(format!("Atomic Load"), idx, &atomic.read_vector) (AccessType::AtomicLoad, idx, &atomic.read_vector)
// Then check races with non-atomic writes/reads. // Then check races with non-atomic writes/reads.
} else if mem_clocks.write.1 > current_clocks.clock[mem_clocks.write.0] { } else if mem_clocks.write.1 > current_clocks.clock[mem_clocks.write.0] {
write_clock = mem_clocks.write(); write_clock = mem_clocks.write();
(mem_clocks.write_type.get_descriptor().to_owned(), mem_clocks.write.0, &write_clock) (AccessType::NaWrite(mem_clocks.write_type), mem_clocks.write.0, &write_clock)
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) { } else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) {
(format!("Read"), idx, &mem_clocks.read) (AccessType::NaRead, idx, &mem_clocks.read)
// Finally, mixed-size races. // Finally, mixed-size races.
} else if is_atomic && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size { } else if access.is_atomic() && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size {
// This is only a race if we are not synchronized with all atomic accesses, so find // This is only a race if we are not synchronized with all atomic accesses, so find
// the one we are not synchronized with. // the one we are not synchronized with.
involves_non_atomic = false; other_size = Some(atomic.size);
action = format!("{}-byte (different-size) {action}", access_size.bytes()).into();
if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock) if let Some(idx) = Self::find_gt_index(&atomic.write_vector, &current_clocks.clock)
{ {
(format!("{}-byte Atomic Store", atomic.size.bytes()), idx, &atomic.write_vector) (AccessType::AtomicStore, idx, &atomic.write_vector)
} else if let Some(idx) = } else if let Some(idx) =
Self::find_gt_index(&atomic.read_vector, &current_clocks.clock) Self::find_gt_index(&atomic.read_vector, &current_clocks.clock)
{ {
(format!("{}-byte Atomic Load", atomic.size.bytes()), idx, &atomic.read_vector) (AccessType::AtomicLoad, idx, &atomic.read_vector)
} else { } else {
unreachable!( unreachable!(
"Failed to report data-race for mixed-size access: no race found" "Failed to report data-race for mixed-size access: no race found"
@ -892,18 +931,39 @@ impl VClockAlloc {
// Load elaborated thread information about the racing thread actions. // Load elaborated thread information about the racing thread actions.
let current_thread_info = global.print_thread_metadata(thread_mgr, current_index); let current_thread_info = global.print_thread_metadata(thread_mgr, current_index);
let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread); let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
let involves_non_atomic = !access.is_atomic() || !other_access.is_atomic();
// Throw the data-race detection. // Throw the data-race detection.
let extra = if other_size.is_some() {
assert!(!involves_non_atomic);
Some("overlapping unsynchronized atomic accesses must use the same access size")
} else if access.is_read() && other_access.is_read() {
assert!(involves_non_atomic);
Some(
"overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only",
)
} else {
None
};
Err(err_machine_stop!(TerminationInfo::DataRace { Err(err_machine_stop!(TerminationInfo::DataRace {
involves_non_atomic, involves_non_atomic,
extra,
ptr: ptr_dbg, ptr: ptr_dbg,
op1: RacingOp { op1: RacingOp {
action: other_action.to_string(), action: if let Some(other_size) = other_size {
format!("{}-byte {}", other_size.bytes(), other_access.description())
} else {
other_access.description().to_owned()
},
thread_info: other_thread_info, thread_info: other_thread_info,
span: other_clock.as_slice()[other_thread.index()].span_data(), span: other_clock.as_slice()[other_thread.index()].span_data(),
}, },
op2: RacingOp { op2: RacingOp {
action: action.to_string(), action: if other_size.is_some() {
format!("{}-byte {}", access_size.bytes(), access.description())
} else {
access.description().to_owned()
},
thread_info: current_thread_info, thread_info: current_thread_info,
span: current_clocks.clock.as_slice()[current_index.index()].span_data(), span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
}, },
@ -938,8 +998,7 @@ impl VClockAlloc {
global, global,
&machine.threads, &machine.threads,
mem_clocks, mem_clocks,
"Read", AccessType::NaRead,
/* is_atomic */ false,
access_range.size, access_range.size,
Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
); );
@ -956,7 +1015,7 @@ impl VClockAlloc {
&mut self, &mut self,
alloc_id: AllocId, alloc_id: AllocId,
access_range: AllocRange, access_range: AllocRange,
write_type: WriteType, write_type: NaWriteType,
machine: &mut MiriMachine<'_, '_>, machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let current_span = machine.current_span(); let current_span = machine.current_span();
@ -978,8 +1037,7 @@ impl VClockAlloc {
global, global,
&machine.threads, &machine.threads,
mem_clocks, mem_clocks,
write_type.get_descriptor(), AccessType::NaWrite(write_type),
/* is_atomic */ false,
access_range.size, access_range.size,
Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)), Pointer::new(alloc_id, Size::from_bytes(mem_clocks_range.start)),
); );
@ -1001,7 +1059,7 @@ impl VClockAlloc {
range: AllocRange, range: AllocRange,
machine: &mut MiriMachine<'_, '_>, machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
self.unique_access(alloc_id, range, WriteType::Write, machine) self.unique_access(alloc_id, range, NaWriteType::Write, machine)
} }
/// Detect data-races for an unsynchronized deallocate operation, will not perform /// Detect data-races for an unsynchronized deallocate operation, will not perform
@ -1014,7 +1072,7 @@ impl VClockAlloc {
range: AllocRange, range: AllocRange,
machine: &mut MiriMachine<'_, '_>, machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
self.unique_access(alloc_id, range, WriteType::Deallocate, machine) self.unique_access(alloc_id, range, NaWriteType::Deallocate, machine)
} }
} }
@ -1062,7 +1120,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
} }
/// Checks that an atomic access is legal at the given place. /// Checks that an atomic access is legal at the given place.
fn atomic_access_check(&self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { fn atomic_access_check(
&self,
place: &MPlaceTy<'tcx, Provenance>,
access_type: AtomicAccessType,
) -> InterpResult<'tcx> {
let this = self.eval_context_ref(); let this = self.eval_context_ref();
// Check alignment requirements. Atomics must always be aligned to their size, // Check alignment requirements. Atomics must always be aligned to their size,
// even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must
@ -1080,15 +1142,34 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
.ptr_try_get_alloc_id(place.ptr()) .ptr_try_get_alloc_id(place.ptr())
.expect("there are no zero-sized atomic accesses"); .expect("there are no zero-sized atomic accesses");
if this.get_alloc_mutability(alloc_id)? == Mutability::Not { if this.get_alloc_mutability(alloc_id)? == Mutability::Not {
// FIXME: make this prettier, once these messages have separate title/span/help messages. // See if this is fine.
throw_ub_format!( match access_type {
"atomic operations cannot be performed on read-only memory\n\ AtomicAccessType::Rmw | AtomicAccessType::Store => {
many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails \ throw_ub_format!(
(and is hence nominally read-only)\n\ "atomic store and read-modify-write operations cannot be performed on read-only memory\n\
some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; \ see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information"
it is possible that we could have an exception permitting this for specific kinds of loads\n\ );
please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you" }
); AtomicAccessType::Load(_)
if place.layout.size > this.tcx.data_layout().pointer_size() =>
{
throw_ub_format!(
"large atomic load operations cannot be performed on read-only memory\n\
these operations often have to be implemented using read-modify-write operations, which require writeable memory\n\
see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information"
);
}
AtomicAccessType::Load(o) if o != AtomicReadOrd::Relaxed => {
throw_ub_format!(
"non-relaxed atomic load operations cannot be performed on read-only memory\n\
these operations sometimes have to be implemented using read-modify-write operations, which require writeable memory\n\
see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information"
);
}
_ => {
// Large relaxed loads are fine!
}
}
} }
Ok(()) Ok(())
} }
@ -1104,7 +1185,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
this.validate_atomic_op( this.validate_atomic_op(
place, place,
atomic, atomic,
"Atomic Load", AccessType::AtomicLoad,
move |memory, clocks, index, atomic| { move |memory, clocks, index, atomic| {
if atomic == AtomicReadOrd::Relaxed { if atomic == AtomicReadOrd::Relaxed {
memory.load_relaxed(&mut *clocks, index, place.layout.size) memory.load_relaxed(&mut *clocks, index, place.layout.size)
@ -1126,7 +1207,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
this.validate_atomic_op( this.validate_atomic_op(
place, place,
atomic, atomic,
"Atomic Store", AccessType::AtomicStore,
move |memory, clocks, index, atomic| { move |memory, clocks, index, atomic| {
if atomic == AtomicWriteOrd::Relaxed { if atomic == AtomicWriteOrd::Relaxed {
memory.store_relaxed(clocks, index, place.layout.size) memory.store_relaxed(clocks, index, place.layout.size)
@ -1148,18 +1229,23 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
let acquire = matches!(atomic, Acquire | AcqRel | SeqCst); let acquire = matches!(atomic, Acquire | AcqRel | SeqCst);
let release = matches!(atomic, Release | AcqRel | SeqCst); let release = matches!(atomic, Release | AcqRel | SeqCst);
let this = self.eval_context_mut(); let this = self.eval_context_mut();
this.validate_atomic_op(place, atomic, "Atomic RMW", move |memory, clocks, index, _| { this.validate_atomic_op(
if acquire { place,
memory.load_acquire(clocks, index, place.layout.size)?; atomic,
} else { AccessType::AtomicRmw,
memory.load_relaxed(clocks, index, place.layout.size)?; move |memory, clocks, index, _| {
} if acquire {
if release { memory.load_acquire(clocks, index, place.layout.size)?;
memory.rmw_release(clocks, index, place.layout.size) } else {
} else { memory.load_relaxed(clocks, index, place.layout.size)?;
memory.rmw_relaxed(clocks, index, place.layout.size) }
} if release {
}) memory.rmw_release(clocks, index, place.layout.size)
} else {
memory.rmw_relaxed(clocks, index, place.layout.size)
}
},
)
} }
/// Generic atomic operation implementation /// Generic atomic operation implementation
@ -1167,7 +1253,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
&self, &self,
place: &MPlaceTy<'tcx, Provenance>, place: &MPlaceTy<'tcx, Provenance>,
atomic: A, atomic: A,
description: &str, access: AccessType,
mut op: impl FnMut( mut op: impl FnMut(
&mut MemoryCellClocks, &mut MemoryCellClocks,
&mut ThreadClockSet, &mut ThreadClockSet,
@ -1176,6 +1262,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
) -> Result<(), DataRace>, ) -> Result<(), DataRace>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let this = self.eval_context_ref(); let this = self.eval_context_ref();
assert!(access.is_atomic());
if let Some(data_race) = &this.machine.data_race { if let Some(data_race) = &this.machine.data_race {
if data_race.race_detecting() { if data_race.race_detecting() {
let size = place.layout.size; let size = place.layout.size;
@ -1185,7 +1272,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap(); let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap();
log::trace!( log::trace!(
"Atomic op({}) with ordering {:?} on {:?} (size={})", "Atomic op({}) with ordering {:?} on {:?} (size={})",
description, access.description(),
&atomic, &atomic,
place.ptr(), place.ptr(),
size.bytes() size.bytes()
@ -1207,8 +1294,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
data_race, data_race,
&this.machine.threads, &this.machine.threads,
mem_clocks, mem_clocks,
description, access,
/* is_atomic */ true,
place.layout.size, place.layout.size,
Pointer::new( Pointer::new(
alloc_id, alloc_id,

View File

@ -4,7 +4,7 @@ use std::num::NonZeroU64;
use log::trace; use log::trace;
use rustc_errors::DiagnosticMessage; use rustc_errors::DiagnosticMessage;
use rustc_span::{DUMMY_SP, SpanData, Symbol}; use rustc_span::{SpanData, Symbol, DUMMY_SP};
use rustc_target::abi::{Align, Size}; use rustc_target::abi::{Align, Size};
use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory; use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory;
@ -47,6 +47,7 @@ pub enum TerminationInfo {
ptr: Pointer, ptr: Pointer,
op1: RacingOp, op1: RacingOp,
op2: RacingOp, op2: RacingOp,
extra: Option<&'static str>,
}, },
} }
@ -75,7 +76,7 @@ impl fmt::Display for TerminationInfo {
write!(f, "multiple definitions of symbol `{link_name}`"), write!(f, "multiple definitions of symbol `{link_name}`"),
SymbolShimClashing { link_name, .. } => SymbolShimClashing { link_name, .. } =>
write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",), write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",),
DataRace { involves_non_atomic, ptr, op1, op2 } => DataRace { involves_non_atomic, ptr, op1, op2, .. } =>
write!( write!(
f, f,
"{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here", "{} detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here",
@ -266,12 +267,16 @@ pub fn report_error<'tcx, 'mir>(
vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))], vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
Int2PtrWithStrictProvenance => 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![(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, .. } => DataRace { op1, extra, .. } => {
vec![ let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))];
(Some(op1.span), format!("and (1) occurred earlier here")), if let Some(extra) = extra {
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")), helps.push((None, format!("{extra}")))
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")), }
], 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
}
,
_ => vec![], _ => vec![],
}; };
(title, helps) (title, helps)

View File

@ -265,12 +265,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
) -> InterpResult<'tcx, InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>> { ) -> InterpResult<'tcx, InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>> {
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
let layout_cx = LayoutCx { tcx, param_env }; let layout_cx = LayoutCx { tcx, param_env };
let mut ecx = InterpCx::new( let mut ecx =
tcx, InterpCx::new(tcx, rustc_span::DUMMY_SP, param_env, MiriMachine::new(config, layout_cx));
rustc_span::DUMMY_SP,
param_env,
MiriMachine::new(config, layout_cx),
);
// Some parts of initialization require a full `InterpCx`. // Some parts of initialization require a full `InterpCx`.
MiriMachine::late_init(&mut ecx, config, { MiriMachine::late_init(&mut ecx, config, {

View File

@ -77,40 +77,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.atomic_compare_exchange_weak(args, dest, rw_ord(ord1)?, read_ord(ord2)?)?, this.atomic_compare_exchange_weak(args, dest, rw_ord(ord1)?, read_ord(ord2)?)?,
["or", ord] => ["or", ord] =>
this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord)?)?, this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord)?)?,
["xor", ord] => ["xor", ord] =>
this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord)?)?, this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord)?)?,
["and", ord] => ["and", ord] =>
this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord)?)?, this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord)?)?,
["nand", ord] => ["nand", ord] =>
this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord)?)?, this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord)?)?,
["xadd", ord] => ["xadd", ord] =>
this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord)?)?, this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord)?)?,
["xsub", ord] => ["xsub", ord] =>
this.atomic_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord)?)?, this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord)?)?,
["min", ord] => { ["min", ord] => {
// Later we will use the type to indicate signed vs unsigned, // Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name. // so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Int(_))); assert!(matches!(args[1].layout.ty.kind(), ty::Int(_)));
this.atomic_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?; this.atomic_rmw_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?;
} }
["umin", ord] => { ["umin", ord] => {
// Later we will use the type to indicate signed vs unsigned, // Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name. // so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_))); assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_)));
this.atomic_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?; this.atomic_rmw_op(args, dest, AtomicOp::Min, rw_ord(ord)?)?;
} }
["max", ord] => { ["max", ord] => {
// Later we will use the type to indicate signed vs unsigned, // Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name. // so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Int(_))); assert!(matches!(args[1].layout.ty.kind(), ty::Int(_)));
this.atomic_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?; this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
} }
["umax", ord] => { ["umax", ord] => {
// Later we will use the type to indicate signed vs unsigned, // Later we will use the type to indicate signed vs unsigned,
// so make sure it matches the intrinsic name. // so make sure it matches the intrinsic name.
assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_))); assert!(matches!(args[1].layout.ty.kind(), ty::Uint(_)));
this.atomic_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?; this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?;
} }
_ => throw_unsup_format!("unimplemented intrinsic: `atomic_{intrinsic_name}`"), _ => throw_unsup_format!("unimplemented intrinsic: `atomic_{intrinsic_name}`"),
@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
Ok(()) Ok(())
} }
fn atomic_op( fn atomic_rmw_op(
&mut self, &mut self,
args: &[OpTy<'tcx, Provenance>], args: &[OpTy<'tcx, Provenance>],
dest: &PlaceTy<'tcx, Provenance>, dest: &PlaceTy<'tcx, Provenance>,
@ -213,7 +213,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
Ok(()) Ok(())
} }
AtomicOp::MirOp(op, neg) => { AtomicOp::MirOp(op, neg) => {
let old = this.atomic_op_immediate(&place, &rhs, op, neg, atomic)?; let old = this.atomic_rmw_op_immediate(&place, &rhs, op, neg, atomic)?;
this.write_immediate(*old, dest)?; // old value is returned this.write_immediate(*old, dest)?; // old value is returned
Ok(()) Ok(())
} }

View File

@ -17,7 +17,7 @@ fn thread_1(p: SendPtr) {
fn thread_2(p: SendPtr) { fn thread_2(p: SendPtr) {
let p = p.0; let p = p.0;
unsafe { unsafe {
*p = 5; //~ ERROR: /Data race detected between \(1\) (Read|Write) on thread `<unnamed>` and \(2\) Write on thread `<unnamed>`/ *p = 5; //~ ERROR: /Data race detected between \(1\) non-atomic (read|write) on thread `<unnamed>` and \(2\) non-atomic write on thread `<unnamed>`/
} }
} }

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/retag_data_race_write.rs:LL:CC --> $DIR/retag_data_race_write.rs:LL:CC
| |
LL | *p = 5; LL | *p = 5;
| ^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/retag_data_race_write.rs:LL:CC --> $DIR/retag_data_race_write.rs:LL:CC

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/retag_data_race_write.rs:LL:CC --> $DIR/retag_data_race_write.rs:LL:CC
| |
LL | *p = 5; LL | *p = 5;
| ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/retag_data_race_write.rs:LL:CC --> $DIR/retag_data_race_write.rs:LL:CC

View File

@ -7,5 +7,5 @@ fn main() {
static X: i32 = 0; static X: i32 = 0;
let x = &X as *const i32 as *const AtomicI32; let x = &X as *const i32 as *const AtomicI32;
let x = unsafe { &*x }; let x = unsafe { &*x };
x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err(); //~ERROR: atomic operations cannot be performed on read-only memory x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err(); //~ERROR: cannot be performed on read-only memory
} }

View File

@ -1,14 +1,10 @@
error: Undefined Behavior: atomic operations cannot be performed on read-only memory error: Undefined Behavior: atomic store and read-modify-write operations cannot be performed on read-only memory
many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only) see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
--> $DIR/read_only_atomic_cmpxchg.rs:LL:CC --> $DIR/read_only_atomic_cmpxchg.rs:LL:CC
| |
LL | x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err(); LL | x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ atomic operations cannot be performed on read-only memory | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ atomic store and read-modify-write operations cannot be performed on read-only memory
many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only) see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
| |
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -1,21 +0,0 @@
error: Undefined Behavior: atomic operations cannot be performed on read-only memory
many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only)
some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
--> $DIR/read_only_atomic_load.rs:LL:CC
|
LL | x.load(Ordering::Relaxed);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ atomic operations cannot be performed on read-only memory
many platforms require atomic read-modify-write instructions to be performed on writeable memory, even if the operation fails (and is hence nominally read-only)
some platforms implement (some) atomic loads via compare-exchange, which means they do not work on read-only memory; it is possible that we could have an exception permitting this for specific kinds of loads
please report an issue at <https://github.com/rust-lang/miri/issues> if this is a problem for you
|
= 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: inside `main` at $DIR/read_only_atomic_load.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

@ -9,5 +9,5 @@ fn main() {
let x = unsafe { &*x }; let x = unsafe { &*x };
// Some targets can implement atomic loads via compare_exchange, so we cannot allow them on // Some targets can implement atomic loads via compare_exchange, so we cannot allow them on
// read-only memory. // read-only memory.
x.load(Ordering::Relaxed); //~ERROR: atomic operations cannot be performed on read-only memory x.load(Ordering::Acquire); //~ERROR: cannot be performed on read-only memory
} }

View File

@ -0,0 +1,19 @@
error: Undefined Behavior: non-relaxed atomic load operations cannot be performed on read-only memory
these operations sometimes have to be implemented using read-modify-write operations, which require writeable memory
see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
--> $DIR/read_only_atomic_load_acquire.rs:LL:CC
|
LL | x.load(Ordering::Acquire);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ non-relaxed atomic load operations cannot be performed on read-only memory
these operations sometimes have to be implemented using read-modify-write operations, which require writeable memory
see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
|
= 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: inside `main` at $DIR/read_only_atomic_load_acquire.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

@ -0,0 +1,18 @@
// Should not rely on the aliasing model for its failure.
//@compile-flags: -Zmiri-disable-stacked-borrows
// Needs atomic accesses larger than the pointer size
//@ignore-64bit
use std::sync::atomic::{AtomicI64, Ordering};
#[repr(align(8))]
struct AlignedI64(i64);
fn main() {
static X: AlignedI64 = AlignedI64(0);
let x = &X as *const AlignedI64 as *const AtomicI64;
let x = unsafe { &*x };
// Some targets can implement atomic loads via compare_exchange, so we cannot allow them on
// read-only memory.
x.load(Ordering::Relaxed); //~ERROR: cannot be performed on read-only memory
}

View File

@ -0,0 +1,19 @@
error: Undefined Behavior: large atomic load operations cannot be performed on read-only memory
these operations often have to be implemented using read-modify-write operations, which require writeable memory
see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
--> $DIR/read_only_atomic_load_large.rs:LL:CC
|
LL | x.load(Ordering::Relaxed);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ large atomic load operations cannot be performed on read-only memory
these operations often have to be implemented using read-modify-write operations, which require writeable memory
see <https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#atomic-accesses-to-read-only-memory> for more information
|
= 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: inside `main` at $DIR/read_only_atomic_load_large.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

@ -14,4 +14,3 @@ fn main() {
} }
panic!("this should never print"); panic!("this should never print");
} }

View File

@ -1,5 +1,5 @@
error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
--> $DIR/dangling_pointer_project_underscore.rs:LL:CC --> $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
| |
LL | let _ = (*p).1; LL | let _ = (*p).1;
| ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling | ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
@ -7,17 +7,17 @@ LL | let _ = (*p).1;
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
help: ALLOC was allocated here: help: ALLOC was allocated here:
--> $DIR/dangling_pointer_project_underscore.rs:LL:CC --> $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
| |
LL | let b = Box::new(42); LL | let b = Box::new(42);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
help: ALLOC was deallocated here: help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_project_underscore.rs:LL:CC --> $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
| |
LL | }; LL | };
| ^ | ^
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_pointer_project_underscore.rs:LL:CC = note: inside `main` at $DIR/dangling_pointer_project_underscore_let.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

View File

@ -0,0 +1,12 @@
// Make sure we find these even with many checks disabled.
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
fn main() {
let p = {
let b = Box::new(42);
&*b as *const i32 as *const (u8, u8, u8, u8)
};
unsafe {
let _: u8 = (*p).1; //~ ERROR: out-of-bounds pointer arithmetic
}
}

View File

@ -0,0 +1,25 @@
error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
--> $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
|
LL | let _: u8 = (*p).1;
| ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
|
= 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
help: ALLOC was allocated here:
--> $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_pointer_project_underscore_let_type_annotation.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

@ -1,13 +1,14 @@
// A `_` binding in a match is a nop, so we do not detect that the pointer is dangling. // Make sure we find these even with many checks disabled.
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation //@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
fn main() { fn main() {
let p = { let p = {
let b = Box::new(42); let b = Box::new(42);
&*b as *const i32 &*b as *const i32 as *const (u8, u8, u8, u8)
}; };
unsafe { unsafe {
match *p { match (*p).1 {
//~^ ERROR: out-of-bounds pointer arithmetic
_ => {} _ => {}
} }
} }

View File

@ -0,0 +1,25 @@
error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
--> $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
|
LL | match (*p).1 {
| ^^^^^^ out-of-bounds pointer arithmetic: ALLOC has been freed, so this pointer is dangling
|
= 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
help: ALLOC was allocated here:
--> $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_pointer_project_underscore_match.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/alloc_read_race.rs:LL:CC --> $DIR/alloc_read_race.rs:LL:CC
| |
LL | *pointer.load(Ordering::Relaxed) LL | *pointer.load(Ordering::Relaxed)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/alloc_read_race.rs:LL:CC --> $DIR/alloc_read_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/alloc_write_race.rs:LL:CC --> $DIR/alloc_write_race.rs:LL:CC
| |
LL | *pointer.load(Ordering::Relaxed) = 2; LL | *pointer.load(Ordering::Relaxed) = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/alloc_write_race.rs:LL:CC --> $DIR/alloc_write_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
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 error: Undefined Behavior: Data race detected between (1) non-atomic 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 --> $DIR/atomic_read_na_write_race1.rs:LL:CC
| |
LL | (&*c.0).load(Ordering::SeqCst) LL | (&*c.0).load(Ordering::SeqCst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/atomic_read_na_write_race1.rs:LL:CC --> $DIR/atomic_read_na_write_race1.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
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 error: Undefined Behavior: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_read_na_write_race2.rs:LL:CC --> $DIR/atomic_read_na_write_race2.rs:LL:CC
| |
LL | *atomic_ref.get_mut() = 32; LL | *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/atomic_read_na_write_race2.rs:LL:CC --> $DIR/atomic_read_na_write_race2.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
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 error: Undefined Behavior: Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_write_na_read_race1.rs:LL:CC --> $DIR/atomic_write_na_read_race1.rs:LL:CC
| |
LL | *atomic_ref.get_mut() LL | *atomic_ref.get_mut()
| ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/atomic_write_na_read_race1.rs:LL:CC --> $DIR/atomic_write_na_read_race1.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
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 error: Undefined Behavior: Data race detected between (1) non-atomic 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 --> $DIR/atomic_write_na_read_race2.rs:LL:CC
| |
LL | (&*c.0).store(32, Ordering::SeqCst); LL | (&*c.0).store(32, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/atomic_write_na_read_race2.rs:LL:CC --> $DIR/atomic_write_na_read_race2.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
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 error: Undefined Behavior: Data race detected between (1) non-atomic 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 --> $DIR/atomic_write_na_write_race1.rs:LL:CC
| |
LL | (&*c.0).store(64, Ordering::SeqCst); LL | (&*c.0).store(64, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/atomic_write_na_write_race1.rs:LL:CC --> $DIR/atomic_write_na_write_race1.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
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 error: Undefined Behavior: Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/atomic_write_na_write_race2.rs:LL:CC --> $DIR/atomic_write_na_write_race2.rs:LL:CC
| |
LL | *atomic_ref.get_mut() = 32; LL | *atomic_ref.get_mut() = 32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic store on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/atomic_write_na_write_race2.rs:LL:CC --> $DIR/atomic_write_na_write_race2.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dangling_thread_async_race.rs:LL:CC --> $DIR/dangling_thread_async_race.rs:LL:CC
| |
LL | *c.0 = 64; LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/dangling_thread_async_race.rs:LL:CC --> $DIR/dangling_thread_async_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
--> $DIR/dangling_thread_race.rs:LL:CC --> $DIR/dangling_thread_race.rs:LL:CC
| |
LL | *c.0 = 64; LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here | ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/dangling_thread_race.rs:LL:CC --> $DIR/dangling_thread_race.rs:LL:CC

View File

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

View File

@ -1,4 +1,4 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_read_race1.rs:LL:CC --> $DIR/dealloc_read_race1.rs:LL:CC
| |
LL | / __rust_dealloc( LL | / __rust_dealloc(
@ -7,7 +7,7 @@ LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(), LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(), LL | | std::mem::align_of::<usize>(),
LL | | ); LL | | );
| |_____________^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here | |_____________^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/dealloc_read_race1.rs:LL:CC --> $DIR/dealloc_read_race1.rs:LL:CC

View File

@ -30,7 +30,7 @@ pub fn main() {
let j2 = spawn(move || { let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing let ptr = ptr; // avoid field capturing
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` // Also an error of the form: Data race detected between (1) deallocation on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
// but the invalid allocation is detected first. // but the invalid allocation is detected first.
*ptr.0 //~ ERROR: has been freed *ptr.0 //~ ERROR: has been freed
}); });

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_read_race_stack.rs:LL:CC --> $DIR/dealloc_read_race_stack.rs:LL:CC
| |
LL | } LL | }
| ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here | ^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/dealloc_read_race_stack.rs:LL:CC --> $DIR/dealloc_read_race_stack.rs:LL:CC

View File

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

View File

@ -1,4 +1,4 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_write_race1.rs:LL:CC --> $DIR/dealloc_write_race1.rs:LL:CC
| |
LL | / __rust_dealloc( LL | / __rust_dealloc(
@ -7,7 +7,7 @@ LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(), LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(), LL | | std::mem::align_of::<usize>(),
LL | | ); LL | | );
| |_____________^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here | |_____________^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/dealloc_write_race1.rs:LL:CC --> $DIR/dealloc_write_race1.rs:LL:CC

View File

@ -29,7 +29,7 @@ pub fn main() {
let j2 = spawn(move || { let j2 = spawn(move || {
let ptr = ptr; // avoid field capturing let ptr = ptr; // avoid field capturing
// Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` // Also an error of the form: Data race detected between (1) deallocation on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
// but the invalid allocation is detected first. // but the invalid allocation is detected first.
*ptr.0 = 2; //~ ERROR: has been freed *ptr.0 = 2; //~ ERROR: has been freed
}); });

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/dealloc_write_race_stack.rs:LL:CC --> $DIR/dealloc_write_race_stack.rs:LL:CC
| |
LL | } LL | }
| ^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here | ^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) deallocation on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/dealloc_write_race_stack.rs:LL:CC --> $DIR/dealloc_write_race_stack.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/enable_after_join_to_main.rs:LL:CC --> $DIR/enable_after_join_to_main.rs:LL:CC
| |
LL | *c.0 = 64; LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/enable_after_join_to_main.rs:LL:CC --> $DIR/enable_after_join_to_main.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
--> $DIR/fence_after_load.rs:LL:CC --> $DIR/fence_after_load.rs:LL:CC
| |
LL | unsafe { V = 2 } LL | unsafe { V = 2 }
| ^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here | ^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `main` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/fence_after_load.rs:LL:CC --> $DIR/fence_after_load.rs:LL:CC

View File

@ -19,7 +19,7 @@ fn main() {
}); });
s.spawn(|| { s.spawn(|| {
a8[0].load(Ordering::SeqCst); a8[0].load(Ordering::SeqCst);
//~^ ERROR: Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` //~^ ERROR: Race condition detected between (1) 2-byte atomic load on thread `<unnamed>` and (2) 1-byte atomic load on thread `<unnamed>`
}); });
}); });
} }

View File

@ -1,14 +1,15 @@
error: Undefined Behavior: Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Race condition detected between (1) 2-byte atomic load on thread `<unnamed>` and (2) 1-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/mixed_size_read.rs:LL:CC --> $DIR/mixed_size_read.rs:LL:CC
| |
LL | a8[0].load(Ordering::SeqCst); LL | a8[0].load(Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte atomic load on thread `<unnamed>` and (2) 1-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/mixed_size_read.rs:LL:CC --> $DIR/mixed_size_read.rs:LL:CC
| |
LL | a16.load(Ordering::SeqCst); LL | a16.load(Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: overlapping unsynchronized atomic accesses must use the same access size
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):

View File

@ -19,7 +19,7 @@ fn main() {
}); });
s.spawn(|| { s.spawn(|| {
a8[0].store(1, Ordering::SeqCst); a8[0].store(1, Ordering::SeqCst);
//~^ ERROR: Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` //~^ ERROR: Race condition detected between (1) 2-byte atomic store on thread `<unnamed>` and (2) 1-byte atomic store on thread `<unnamed>`
}); });
}); });
} }

View File

@ -1,14 +1,15 @@
error: Undefined Behavior: Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Race condition detected between (1) 2-byte atomic store on thread `<unnamed>` and (2) 1-byte atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/mixed_size_write.rs:LL:CC --> $DIR/mixed_size_write.rs:LL:CC
| |
LL | a8[0].store(1, Ordering::SeqCst); LL | a8[0].store(1, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte atomic store on thread `<unnamed>` and (2) 1-byte atomic store on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/mixed_size_write.rs:LL:CC --> $DIR/mixed_size_write.rs:LL:CC
| |
LL | a16.store(1, Ordering::SeqCst); LL | a16.store(1, Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: overlapping unsynchronized atomic accesses must use the same access size
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):

View File

@ -21,7 +21,7 @@ fn main() {
unsafe { ptr.read() }; unsafe { ptr.read() };
// Then do the atomic access. // Then do the atomic access.
a.load(Ordering::SeqCst); a.load(Ordering::SeqCst);
//~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` //~^ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic load on thread `<unnamed>`
}); });
}); });
} }

View File

@ -1,14 +1,15 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/read_read_race1.rs:LL:CC --> $DIR/read_read_race1.rs:LL:CC
| |
LL | a.load(Ordering::SeqCst); LL | a.load(Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/read_read_race1.rs:LL:CC --> $DIR/read_read_race1.rs:LL:CC
| |
LL | unsafe { ptr.read() }; LL | unsafe { ptr.read() };
| ^^^^^^^^^^ | ^^^^^^^^^^
= help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):

View File

@ -21,7 +21,7 @@ fn main() {
let ptr = &a as *const AtomicU16 as *mut u16; let ptr = &a as *const AtomicU16 as *mut u16;
unsafe { ptr.read() }; unsafe { ptr.read() };
//~^ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` //~^ ERROR: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
}); });
}); });
} }

View File

@ -1,14 +1,15 @@
error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/read_read_race2.rs:LL:CC --> $DIR/read_read_race2.rs:LL:CC
| |
LL | unsafe { ptr.read() }; LL | unsafe { ptr.read() };
| ^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^ Data race detected between (1) atomic load on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/read_read_race2.rs:LL:CC --> $DIR/read_read_race2.rs:LL:CC
| |
LL | a.load(Ordering::SeqCst); LL | a.load(Ordering::SeqCst);
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
= help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/read_write_race.rs:LL:CC --> $DIR/read_write_race.rs:LL:CC
| |
LL | *c.0 = 64; LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/read_write_race.rs:LL:CC --> $DIR/read_write_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/read_write_race_stack.rs:LL:CC --> $DIR/read_write_race_stack.rs:LL:CC
| |
LL | stack_var LL | stack_var
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/read_write_race_stack.rs:LL:CC --> $DIR/read_write_race_stack.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/relax_acquire_race.rs:LL:CC --> $DIR/relax_acquire_race.rs:LL:CC
| |
LL | *c.0 LL | *c.0
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/relax_acquire_race.rs:LL:CC --> $DIR/relax_acquire_race.rs:LL:CC

View File

@ -43,7 +43,7 @@ pub fn main() {
let c = c; // avoid field capturing let c = c; // avoid field capturing
sleep(Duration::from_millis(500)); sleep(Duration::from_millis(500));
if SYNC.load(Ordering::Acquire) == 3 { if SYNC.load(Ordering::Acquire) == 3 {
*c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` *c.0 //~ ERROR: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>`
} else { } else {
0 0
} }

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/release_seq_race.rs:LL:CC --> $DIR/release_seq_race.rs:LL:CC
| |
LL | *c.0 LL | *c.0
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/release_seq_race.rs:LL:CC --> $DIR/release_seq_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/release_seq_race_same_thread.rs:LL:CC --> $DIR/release_seq_race_same_thread.rs:LL:CC
| |
LL | *c.0 LL | *c.0
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/release_seq_race_same_thread.rs:LL:CC --> $DIR/release_seq_race_same_thread.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/rmw_race.rs:LL:CC --> $DIR/rmw_race.rs:LL:CC
| |
LL | *c.0 LL | *c.0
| ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/rmw_race.rs:LL:CC --> $DIR/rmw_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
--> $DIR/stack_pop_race.rs:LL:CC --> $DIR/stack_pop_race.rs:LL:CC
| |
LL | } LL | }
| ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here | ^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) deallocation on thread `main` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/stack_pop_race.rs:LL:CC --> $DIR/stack_pop_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/write_write_race.rs:LL:CC --> $DIR/write_write_race.rs:LL:CC
| |
LL | *c.0 = 64; LL | *c.0 = 64;
| ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/write_write_race.rs:LL:CC --> $DIR/write_write_race.rs:LL:CC

View File

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

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/write_write_race_stack.rs:LL:CC --> $DIR/write_write_race_stack.rs:LL:CC
| |
LL | stack_var = 1usize; LL | stack_var = 1usize;
| ^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/write_write_race_stack.rs:LL:CC --> $DIR/write_write_race_stack.rs:LL:CC

View File

@ -13,7 +13,7 @@ fn main() {
let ptr = ptr; let ptr = ptr;
// We do a protected mutable retag (but no write!) in this thread. // We do a protected mutable retag (but no write!) in this thread.
fn retag(_x: &mut i32) {} fn retag(_x: &mut i32) {}
retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) Read on thread `main` and (2) Write on thread `<unnamed>` retag(unsafe { &mut *ptr.0 }); //~ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `<unnamed>`
}); });
// We do a read in the main thread. // We do a read in the main thread.

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `main` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/retag_data_race_protected_read.rs:LL:CC --> $DIR/retag_data_race_protected_read.rs:LL:CC
| |
LL | retag(unsafe { &mut *ptr.0 }); LL | retag(unsafe { &mut *ptr.0 });
| ^^^^^^^^^^^ Data race detected between (1) Read on thread `main` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/retag_data_race_protected_read.rs:LL:CC --> $DIR/retag_data_race_protected_read.rs:LL:CC

View File

@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) {
fn thread_2(p: SendPtr) { fn thread_2(p: SendPtr) {
let p = p.0; let p = p.0;
unsafe { unsafe {
*p = 5; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` *p = 5; //~ ERROR: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>`
} }
} }

View File

@ -1,8 +1,8 @@
error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/retag_data_race_read.rs:LL:CC --> $DIR/retag_data_race_read.rs:LL:CC
| |
LL | *p = 5; LL | *p = 5;
| ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^ Data race detected between (1) non-atomic read on thread `<unnamed>` and (2) non-atomic write on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/retag_data_race_read.rs:LL:CC --> $DIR/retag_data_race_read.rs:LL:CC

View File

@ -8,10 +8,8 @@ fn main() {
unsafe { unsafe {
let x: Uninit<Void> = Uninit { uninit: () }; let x: Uninit<Void> = Uninit { uninit: () };
match x.value { match x.value {
// rustc warns about un unreachable pattern,
// but is wrong in unsafe code.
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
_ => println!("hi from the void!"), _x => println!("hi from the void!"), //~ERROR: invalid value
} }
} }
} }

View File

@ -0,0 +1,15 @@
error: Undefined Behavior: constructing invalid value: encountered a value of uninhabited type `main::Void`
--> $DIR/match_binder_checks_validity1.rs:LL:CC
|
LL | _x => println!("hi from the void!"),
| ^^ constructing invalid value: encountered a value of uninhabited type `main::Void`
|
= 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: inside `main` at $DIR/match_binder_checks_validity1.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

@ -0,0 +1,14 @@
fn main() {
#[derive(Copy, Clone)]
union Uninit<T: Copy> {
value: T,
uninit: u8,
}
unsafe {
let x: Uninit<bool> = Uninit { uninit: 3 };
match x.value {
#[allow(unreachable_patterns)]
_x => println!("hi from the void!"), //~ERROR: invalid value
}
}
}

View File

@ -0,0 +1,15 @@
error: Undefined Behavior: constructing invalid value: encountered 0x03, but expected a boolean
--> $DIR/match_binder_checks_validity2.rs:LL:CC
|
LL | _x => println!("hi from the void!"),
| ^^ constructing invalid value: encountered 0x03, but expected a boolean
|
= 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: inside `main` at $DIR/match_binder_checks_validity2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error

View File

@ -31,7 +31,7 @@ pub fn main() {
let x_split = split_u32_ptr(x_ptr); let x_split = split_u32_ptr(x_ptr);
unsafe { unsafe {
let hi = ptr::addr_of!((*x_split)[0]); let hi = ptr::addr_of!((*x_split)[0]);
std::intrinsics::atomic_load_relaxed(hi); //~ ERROR: different-size std::intrinsics::atomic_load_relaxed(hi); //~ ERROR: (1) 4-byte atomic store on thread `<unnamed>` and (2) 2-byte atomic load
} }
}); });

View File

@ -1,14 +1,15 @@
error: Undefined Behavior: Race condition detected between (1) 4-byte Atomic Store on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Race condition detected between (1) 4-byte atomic store on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/racing_mixed_size.rs:LL:CC --> $DIR/racing_mixed_size.rs:LL:CC
| |
LL | std::intrinsics::atomic_load_relaxed(hi); LL | std::intrinsics::atomic_load_relaxed(hi);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte Atomic Store on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte atomic store on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/racing_mixed_size.rs:LL:CC --> $DIR/racing_mixed_size.rs:LL:CC
| |
LL | x.store(1, Relaxed); LL | x.store(1, Relaxed);
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
= help: overlapping unsynchronized atomic accesses must use the same access size
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):

View File

@ -29,7 +29,7 @@ pub fn main() {
let x_split = split_u32_ptr(x_ptr); let x_split = split_u32_ptr(x_ptr);
unsafe { unsafe {
let hi = x_split as *const u16 as *const AtomicU16; let hi = x_split as *const u16 as *const AtomicU16;
(*hi).load(Relaxed); //~ ERROR: different-size (*hi).load(Relaxed); //~ ERROR: (1) 4-byte atomic load on thread `<unnamed>` and (2) 2-byte atomic load
} }
}); });

View File

@ -1,14 +1,15 @@
error: Undefined Behavior: Race condition detected between (1) 4-byte Atomic Load on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here error: Undefined Behavior: Race condition detected between (1) 4-byte atomic load on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
--> $DIR/racing_mixed_size_read.rs:LL:CC --> $DIR/racing_mixed_size_read.rs:LL:CC
| |
LL | (*hi).load(Relaxed); LL | (*hi).load(Relaxed);
| ^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte Atomic Load on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | ^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte atomic load on thread `<unnamed>` and (2) 2-byte atomic load on thread `<unnamed>` at ALLOC. (2) just happened here
| |
help: and (1) occurred earlier here help: and (1) occurred earlier here
--> $DIR/racing_mixed_size_read.rs:LL:CC --> $DIR/racing_mixed_size_read.rs:LL:CC
| |
LL | x.load(Relaxed); LL | x.load(Relaxed);
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
= help: overlapping unsynchronized atomic accesses must use the same access size
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE (of the first span): = note: BACKTRACE (of the first span):

View File

@ -0,0 +1,12 @@
// Stacked Borrows doesn't like this.
//@compile-flags: -Zmiri-tree-borrows
use std::sync::atomic::*;
fn main() {
// Atomic loads from read-only memory are fine if they are relaxed and small.
static X: i32 = 0;
let x = &X as *const i32 as *const AtomicI32;
let x = unsafe { &*x };
x.load(Ordering::Relaxed);
}

View File

@ -0,0 +1,71 @@
// Various tests ensuring that underscore patterns really just construct the place, but don't check its contents.
#![feature(strict_provenance)]
use std::ptr;
fn main() {
dangling_match();
invalid_match();
dangling_let();
invalid_let();
dangling_let_type_annotation();
invalid_let_type_annotation();
}
fn dangling_match() {
let p = {
let b = Box::new(42);
&*b as *const i32
};
unsafe {
match *p {
_ => {}
}
}
}
fn invalid_match() {
union Uninit<T: Copy> {
value: T,
uninit: (),
}
unsafe {
let x: Uninit<bool> = Uninit { uninit: () };
match x.value {
_ => {}
}
}
}
fn dangling_let() {
unsafe {
let ptr = ptr::invalid::<bool>(0x40);
let _ = *ptr;
}
}
fn invalid_let() {
unsafe {
let val = 3u8;
let ptr = ptr::addr_of!(val).cast::<bool>();
let _ = *ptr;
}
}
// Adding a type annotation used to change how MIR is generated, make sure we cover both cases.
fn dangling_let_type_annotation() {
unsafe {
let ptr = ptr::invalid::<bool>(0x40);
let _: bool = *ptr;
}
}
fn invalid_let_type_annotation() {
unsafe {
let val = 3u8;
let ptr = ptr::addr_of!(val).cast::<bool>();
let _: bool = *ptr;
}
}
// FIXME: we should also test `!`, not just `bool` -- but that s currently buggy:
// https://github.com/rust-lang/rust/issues/117288

View File

@ -1 +0,0 @@
hi from the void!