Skip to content

Commit bb82124

Browse files
committed
Auto merge of #2455 - RalfJung:scalar-always-init, r=RalfJung
adjust for earlier init checking in the core engine Miri side of rust-lang/rust#100043
2 parents 101c4f2 + df19b85 commit bb82124

39 files changed

+178
-247
lines changed

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e1b28cd2f16bd5b832183d7968cae3bb9213e78d
1+
4065b89b1e7287047d7d6c65e7abd7b8ee70bcf0

src/concurrency/data_race.rs

+14-27
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
447447
offset: u64,
448448
layout: TyAndLayout<'tcx>,
449449
atomic: AtomicReadOrd,
450-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
450+
) -> InterpResult<'tcx, Scalar<Provenance>> {
451451
let this = self.eval_context_ref();
452452
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
453453
this.read_scalar_atomic(&value_place, atomic)
@@ -458,7 +458,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
458458
&mut self,
459459
op: &OpTy<'tcx, Provenance>,
460460
offset: u64,
461-
value: impl Into<ScalarMaybeUninit<Provenance>>,
461+
value: impl Into<Scalar<Provenance>>,
462462
layout: TyAndLayout<'tcx>,
463463
atomic: AtomicWriteOrd,
464464
) -> InterpResult<'tcx> {
@@ -472,7 +472,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
472472
&self,
473473
place: &MPlaceTy<'tcx, Provenance>,
474474
atomic: AtomicReadOrd,
475-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
475+
) -> InterpResult<'tcx, Scalar<Provenance>> {
476476
let this = self.eval_context_ref();
477477
this.atomic_access_check(place)?;
478478
// This will read from the last store in the modification order of this location. In case
@@ -490,7 +490,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
490490
/// Perform an atomic write operation at the memory location.
491491
fn write_scalar_atomic(
492492
&mut self,
493-
val: ScalarMaybeUninit<Provenance>,
493+
val: Scalar<Provenance>,
494494
dest: &MPlaceTy<'tcx, Provenance>,
495495
atomic: AtomicWriteOrd,
496496
) -> InterpResult<'tcx> {
@@ -530,12 +530,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
530530

531531
this.validate_atomic_rmw(place, atomic)?;
532532

533-
this.buffered_atomic_rmw(
534-
val.to_scalar_or_uninit(),
535-
place,
536-
atomic,
537-
old.to_scalar_or_uninit(),
538-
)?;
533+
this.buffered_atomic_rmw(val.to_scalar(), place, atomic, old.to_scalar())?;
539534
Ok(old)
540535
}
541536

@@ -544,9 +539,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
544539
fn atomic_exchange_scalar(
545540
&mut self,
546541
place: &MPlaceTy<'tcx, Provenance>,
547-
new: ScalarMaybeUninit<Provenance>,
542+
new: Scalar<Provenance>,
548543
atomic: AtomicRwOrd,
549-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
544+
) -> InterpResult<'tcx, Scalar<Provenance>> {
550545
let this = self.eval_context_mut();
551546
this.atomic_access_check(place)?;
552547

@@ -574,7 +569,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
574569

575570
this.validate_overlapping_atomic(place)?;
576571
let old = this.allow_data_races_mut(|this| this.read_immediate(&place.into()))?;
577-
let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar()?.to_bool()?;
572+
let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?;
578573

579574
let new_val = if min {
580575
if lt { &old } else { &rhs }
@@ -586,12 +581,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
586581

587582
this.validate_atomic_rmw(place, atomic)?;
588583

589-
this.buffered_atomic_rmw(
590-
new_val.to_scalar_or_uninit(),
591-
place,
592-
atomic,
593-
old.to_scalar_or_uninit(),
594-
)?;
584+
this.buffered_atomic_rmw(new_val.to_scalar(), place, atomic, old.to_scalar())?;
595585

596586
// Return the old value.
597587
Ok(old)
@@ -607,7 +597,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
607597
&mut self,
608598
place: &MPlaceTy<'tcx, Provenance>,
609599
expect_old: &ImmTy<'tcx, Provenance>,
610-
new: ScalarMaybeUninit<Provenance>,
600+
new: Scalar<Provenance>,
611601
success: AtomicRwOrd,
612602
fail: AtomicReadOrd,
613603
can_fail_spuriously: bool,
@@ -627,31 +617,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
627617
// If the operation would succeed, but is "weak", fail some portion
628618
// of the time, based on `success_rate`.
629619
let success_rate = 1.0 - this.machine.cmpxchg_weak_failure_rate;
630-
let cmpxchg_success = eq.to_scalar()?.to_bool()?
620+
let cmpxchg_success = eq.to_scalar().to_bool()?
631621
&& if can_fail_spuriously {
632622
this.machine.rng.get_mut().gen_bool(success_rate)
633623
} else {
634624
true
635625
};
636-
let res = Immediate::ScalarPair(
637-
old.to_scalar_or_uninit(),
638-
Scalar::from_bool(cmpxchg_success).into(),
639-
);
626+
let res = Immediate::ScalarPair(old.to_scalar(), Scalar::from_bool(cmpxchg_success));
640627

641628
// Update ptr depending on comparison.
642629
// if successful, perform a full rw-atomic validation
643630
// otherwise treat this as an atomic load with the fail ordering.
644631
if cmpxchg_success {
645632
this.allow_data_races_mut(|this| this.write_scalar(new, &place.into()))?;
646633
this.validate_atomic_rmw(place, success)?;
647-
this.buffered_atomic_rmw(new, place, success, old.to_scalar_or_uninit())?;
634+
this.buffered_atomic_rmw(new, place, success, old.to_scalar())?;
648635
} else {
649636
this.validate_atomic_load(place, fail)?;
650637
// A failed compare exchange is equivalent to a load, reading from the latest store
651638
// in the modification order.
652639
// Since `old` is only a value and not the store element, we need to separately
653640
// find it in our store buffer and perform load_impl on it.
654-
this.perform_read_on_buffered_latest(place, fail, old.to_scalar_or_uninit())?;
641+
this.perform_read_on_buffered_latest(place, fail, old.to_scalar())?;
655642
}
656643

657644
// Return the old value.

src/concurrency/weak_memory.rs

+18-24
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ use std::{
7777
collections::VecDeque,
7878
};
7979

80-
use rustc_const_eval::interpret::{
81-
alloc_range, AllocRange, InterpResult, MPlaceTy, ScalarMaybeUninit,
82-
};
80+
use rustc_const_eval::interpret::{alloc_range, AllocRange, InterpResult, MPlaceTy, Scalar};
8381
use rustc_data_structures::fx::FxHashMap;
8482

8583
use crate::*;
@@ -130,10 +128,10 @@ struct StoreElement {
130128
/// The timestamp of the storing thread when it performed the store
131129
timestamp: VTimestamp,
132130
/// The value of this store
133-
// FIXME: this means the store is either fully initialized or fully uninitialized;
131+
// FIXME: this means the store must be fully initialized;
134132
// we will have to change this if we want to support atomics on
135-
// partially initialized data.
136-
val: ScalarMaybeUninit<Provenance>,
133+
// (partially) uninitialized data.
134+
val: Scalar<Provenance>,
137135

138136
/// Timestamp of first loads from this store element by each thread
139137
/// Behind a RefCell to keep load op take &self
@@ -180,7 +178,7 @@ impl StoreBufferAlloc {
180178
fn get_or_create_store_buffer<'tcx>(
181179
&self,
182180
range: AllocRange,
183-
init: ScalarMaybeUninit<Provenance>,
181+
init: Scalar<Provenance>,
184182
) -> InterpResult<'tcx, Ref<'_, StoreBuffer>> {
185183
let access_type = self.store_buffers.borrow().access_type(range);
186184
let pos = match access_type {
@@ -205,7 +203,7 @@ impl StoreBufferAlloc {
205203
fn get_or_create_store_buffer_mut<'tcx>(
206204
&mut self,
207205
range: AllocRange,
208-
init: ScalarMaybeUninit<Provenance>,
206+
init: Scalar<Provenance>,
209207
) -> InterpResult<'tcx, &mut StoreBuffer> {
210208
let buffers = self.store_buffers.get_mut();
211209
let access_type = buffers.access_type(range);
@@ -226,7 +224,7 @@ impl StoreBufferAlloc {
226224
}
227225

228226
impl<'mir, 'tcx: 'mir> StoreBuffer {
229-
fn new(init: ScalarMaybeUninit<Provenance>) -> Self {
227+
fn new(init: Scalar<Provenance>) -> Self {
230228
let mut buffer = VecDeque::new();
231229
buffer.reserve(STORE_BUFFER_LIMIT);
232230
let mut ret = Self { buffer };
@@ -259,7 +257,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
259257
is_seqcst: bool,
260258
rng: &mut (impl rand::Rng + ?Sized),
261259
validate: impl FnOnce() -> InterpResult<'tcx>,
262-
) -> InterpResult<'tcx, (ScalarMaybeUninit<Provenance>, LoadRecency)> {
260+
) -> InterpResult<'tcx, (Scalar<Provenance>, LoadRecency)> {
263261
// Having a live borrow to store_buffer while calling validate_atomic_load is fine
264262
// because the race detector doesn't touch store_buffer
265263

@@ -284,7 +282,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
284282

285283
fn buffered_write(
286284
&mut self,
287-
val: ScalarMaybeUninit<Provenance>,
285+
val: Scalar<Provenance>,
288286
global: &DataRaceState,
289287
thread_mgr: &ThreadManager<'_, '_>,
290288
is_seqcst: bool,
@@ -375,7 +373,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
375373
/// ATOMIC STORE IMPL in the paper (except we don't need the location's vector clock)
376374
fn store_impl(
377375
&mut self,
378-
val: ScalarMaybeUninit<Provenance>,
376+
val: Scalar<Provenance>,
379377
index: VectorIdx,
380378
thread_clock: &VClock,
381379
is_seqcst: bool,
@@ -417,11 +415,7 @@ impl StoreElement {
417415
/// buffer regardless of subsequent loads by the same thread; if the earliest load of another
418416
/// thread doesn't happen before the current one, then no subsequent load by the other thread
419417
/// can happen before the current one.
420-
fn load_impl(
421-
&self,
422-
index: VectorIdx,
423-
clocks: &ThreadClockSet,
424-
) -> ScalarMaybeUninit<Provenance> {
418+
fn load_impl(&self, index: VectorIdx, clocks: &ThreadClockSet) -> Scalar<Provenance> {
425419
let _ = self.loads.borrow_mut().try_insert(index, clocks.clock[index]);
426420
self.val
427421
}
@@ -464,10 +458,10 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
464458

465459
fn buffered_atomic_rmw(
466460
&mut self,
467-
new_val: ScalarMaybeUninit<Provenance>,
461+
new_val: Scalar<Provenance>,
468462
place: &MPlaceTy<'tcx, Provenance>,
469463
atomic: AtomicRwOrd,
470-
init: ScalarMaybeUninit<Provenance>,
464+
init: Scalar<Provenance>,
471465
) -> InterpResult<'tcx> {
472466
let this = self.eval_context_mut();
473467
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
@@ -492,9 +486,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
492486
&self,
493487
place: &MPlaceTy<'tcx, Provenance>,
494488
atomic: AtomicReadOrd,
495-
latest_in_mo: ScalarMaybeUninit<Provenance>,
489+
latest_in_mo: Scalar<Provenance>,
496490
validate: impl FnOnce() -> InterpResult<'tcx>,
497-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
491+
) -> InterpResult<'tcx, Scalar<Provenance>> {
498492
let this = self.eval_context_ref();
499493
if let Some(global) = &this.machine.data_race {
500494
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
@@ -529,10 +523,10 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
529523

530524
fn buffered_atomic_write(
531525
&mut self,
532-
val: ScalarMaybeUninit<Provenance>,
526+
val: Scalar<Provenance>,
533527
dest: &MPlaceTy<'tcx, Provenance>,
534528
atomic: AtomicWriteOrd,
535-
init: ScalarMaybeUninit<Provenance>,
529+
init: Scalar<Provenance>,
536530
) -> InterpResult<'tcx> {
537531
let this = self.eval_context_mut();
538532
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr)?;
@@ -576,7 +570,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
576570
&self,
577571
place: &MPlaceTy<'tcx, Provenance>,
578572
atomic: AtomicReadOrd,
579-
init: ScalarMaybeUninit<Provenance>,
573+
init: Scalar<Provenance>,
580574
) -> InterpResult<'tcx> {
581575
let this = self.eval_context_ref();
582576

src/helpers.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
116116
let instance = this.resolve_path(path);
117117
let cid = GlobalId { instance, promoted: None };
118118
let const_val = this.eval_to_allocation(cid)?;
119-
let const_val = this.read_scalar(&const_val.into())?;
120-
const_val.check_init()
119+
this.read_scalar(&const_val.into())
121120
}
122121

123122
/// Helper function to get a `libc` constant as a `Scalar`.
@@ -567,7 +566,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
567566
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
568567
let this = self.eval_context_mut();
569568
let errno_place = this.last_error_place()?;
570-
this.read_scalar(&errno_place.into())?.check_init()
569+
this.read_scalar(&errno_place.into())
571570
}
572571

573572
/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
@@ -680,22 +679,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
680679
op: &OpTy<'tcx, Provenance>,
681680
offset: u64,
682681
layout: TyAndLayout<'tcx>,
683-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
682+
) -> InterpResult<'tcx, Scalar<Provenance>> {
684683
let this = self.eval_context_ref();
685684
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
686685
this.read_scalar(&value_place.into())
687686
}
688687

688+
fn write_immediate_at_offset(
689+
&mut self,
690+
op: &OpTy<'tcx, Provenance>,
691+
offset: u64,
692+
value: &ImmTy<'tcx, Provenance>,
693+
) -> InterpResult<'tcx, ()> {
694+
let this = self.eval_context_mut();
695+
let value_place = this.deref_operand_and_offset(op, offset, value.layout)?;
696+
this.write_immediate(**value, &value_place.into())
697+
}
698+
689699
fn write_scalar_at_offset(
690700
&mut self,
691701
op: &OpTy<'tcx, Provenance>,
692702
offset: u64,
693-
value: impl Into<ScalarMaybeUninit<Provenance>>,
703+
value: impl Into<Scalar<Provenance>>,
694704
layout: TyAndLayout<'tcx>,
695705
) -> InterpResult<'tcx, ()> {
696-
let this = self.eval_context_mut();
697-
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
698-
this.write_scalar(value, &value_place.into())
706+
self.write_immediate_at_offset(op, offset, &ImmTy::from_scalar(value.into(), layout))
699707
}
700708

701709
/// Parse a `timespec` struct and return it as a `std::time::Duration`. It returns `None`

src/machine.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ static_assert_size!(Pointer<Provenance>, 24);
149149
// #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
150150
//static_assert_size!(Pointer<Option<Provenance>>, 24);
151151
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
152-
static_assert_size!(ScalarMaybeUninit<Provenance>, 32);
152+
static_assert_size!(Scalar<Provenance>, 32);
153153

154154
impl interpret::Provenance for Provenance {
155155
/// We use absolute addresses in the `offset` of a `Pointer<Provenance>`.
@@ -581,7 +581,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
581581
}
582582

583583
#[inline(always)]
584-
fn force_int_for_alignment_check(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
584+
fn use_addr_for_alignment_check(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
585585
ecx.machine.check_alignment == AlignmentCheck::Int
586586
}
587587

@@ -590,11 +590,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
590590
ecx.machine.validate
591591
}
592592

593-
#[inline(always)]
594-
fn enforce_number_init(_ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
595-
true
596-
}
597-
598593
#[inline(always)]
599594
fn enforce_abi(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
600595
ecx.machine.enforce_abi

0 commit comments

Comments
 (0)