Switch select_unpredictable guard to raw pointer
This commit is contained in:
parent
354787b5ba
commit
ee9803a244
1 changed files with 11 additions and 8 deletions
|
|
@ -788,19 +788,20 @@ pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
|
|||
let mut false_val = MaybeUninit::new(false_val);
|
||||
|
||||
struct DropOnPanic<T> {
|
||||
// Invariant: valid pointer and points to an initialized `MaybeUninit`.
|
||||
inner: *mut MaybeUninit<T>,
|
||||
// Invariant: valid pointer and points to an initialized value that is not further used,
|
||||
// i.e. it can be dropped by this guard.
|
||||
inner: *mut T,
|
||||
}
|
||||
|
||||
impl<T> Drop for DropOnPanic<T> {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: Must be guaranteed on construction of local type `DropOnPanic`.
|
||||
unsafe { (*self.inner).assume_init_drop() }
|
||||
unsafe { self.inner.drop_in_place() }
|
||||
}
|
||||
}
|
||||
|
||||
let true_ptr = (&mut true_val) as *mut _;
|
||||
let false_ptr = (&mut false_val) as *mut _;
|
||||
let true_ptr = true_val.as_mut_ptr();
|
||||
let false_ptr = false_val.as_mut_ptr();
|
||||
|
||||
// SAFETY: The value that is not selected is dropped, and the selected one
|
||||
// is returned. This is necessary because the intrinsic doesn't drop the
|
||||
|
|
@ -813,10 +814,12 @@ pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
|
|||
let guard = crate::intrinsics::select_unpredictable(condition, true_ptr, false_ptr);
|
||||
let drop = crate::intrinsics::select_unpredictable(condition, false_ptr, true_ptr);
|
||||
|
||||
// SAFETY: both pointers are to valid `MaybeUninit`, in both variants they do not alias but
|
||||
// the two arguments we have selected from did alias each other.
|
||||
// SAFETY: both pointers are well-aligned and point to initialized values inside a
|
||||
// `MaybeUninit` each. In both possible values for `condition` the pointer `guard` and
|
||||
// `drop` do not alias (even though the two argument pairs we have selected from did alias
|
||||
// each other).
|
||||
let guard = DropOnPanic { inner: guard };
|
||||
(*drop).assume_init_drop();
|
||||
drop.drop_in_place();
|
||||
crate::mem::forget(guard);
|
||||
|
||||
// Note that it is important to use the values here. Reading from the pointer we got makes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue