Auto merge of #117579 - RalfJung:miri, r=RalfJung
Miri subtree update r? `@ghost`
This commit is contained in:
commit
9c8a2694fa
@ -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.
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
2e4e2a8f288f642cafcc41fff211955ceddc453d
|
3aaa0f57b7b877ef58532a8de075d1e5a79142bf
|
||||||
|
@ -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,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -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, ¤t_clocks.clock)
|
let Some(idx) = Self::find_gt_index(&atomic.write_vector, ¤t_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, ¤t_clocks.clock)
|
let Some(idx) = Self::find_gt_index(&atomic.read_vector, ¤t_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, ¤t_clocks.clock) {
|
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, ¤t_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, ¤t_clocks.clock)
|
if let Some(idx) = Self::find_gt_index(&atomic.write_vector, ¤t_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, ¤t_clocks.clock)
|
Self::find_gt_index(&atomic.read_vector, ¤t_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,
|
||||||
|
@ -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)
|
||||||
|
@ -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, {
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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>`/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
}
|
@ -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
|
||||||
|
|
@ -14,4 +14,3 @@ fn main() {
|
|||||||
}
|
}
|
||||||
panic!("this should never print");
|
panic!("this should never print");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
|
@ -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
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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>`
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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>(),
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
});
|
});
|
||||||
|
@ -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 || {
|
||||||
|
@ -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
|
||||||
|
@ -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>(),
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
});
|
});
|
||||||
|
@ -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 || {
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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`
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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>`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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):
|
||||||
|
@ -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>`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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):
|
||||||
|
@ -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>`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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):
|
||||||
|
@ -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>`
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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):
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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 || {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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`
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
12
src/tools/miri/tests/pass/atomic-readonly-load.rs
Normal file
12
src/tools/miri/tests/pass/atomic-readonly-load.rs
Normal 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);
|
||||||
|
}
|
71
src/tools/miri/tests/pass/underscore_pattern.rs
Normal file
71
src/tools/miri/tests/pass/underscore_pattern.rs
Normal 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
|
@ -1 +0,0 @@
|
|||||||
hi from the void!
|
|
Loading…
x
Reference in New Issue
Block a user