Skip to content

Commit c1894b1

Browse files
authored
Rollup merge of rust-lang#122233 - RalfJung:custom-alloc-box, r=oli-obk
miri: do not apply aliasing restrictions to Box with custom allocator This is the Miri side of rust-lang#122018. The "intrinsics with body" made this much more pleasant. :) Fixes rust-lang/miri#3341. r? `@oli-obk`
2 parents 90c892c + 42e57d7 commit c1894b1

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

alloc/src/boxed.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ use core::error::Error;
155155
use core::fmt;
156156
use core::future::Future;
157157
use core::hash::{Hash, Hasher};
158+
use core::intrinsics::retag_box_to_raw;
158159
use core::iter::FusedIterator;
159160
use core::marker::Tuple;
160161
use core::marker::Unsize;
@@ -1110,8 +1111,16 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
11101111
#[unstable(feature = "allocator_api", issue = "32838")]
11111112
#[inline]
11121113
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
1113-
let (leaked, alloc) = Box::into_unique(b);
1114-
(leaked.as_ptr(), alloc)
1114+
// This is the transition point from `Box` to raw pointers. For Stacked Borrows, these casts
1115+
// are relevant -- if this is a global allocator Box and we just get the pointer from `b.0`,
1116+
// it will have `Unique` permission, which is not what we want from a raw pointer. We could
1117+
// fix that by going through `&mut`, but then if this is *not* a global allocator Box, we'd
1118+
// be adding uniqueness assertions that we do not want. So for Miri's sake we pass this
1119+
// pointer through an intrinsic for box-to-raw casts, which can do the right thing wrt the
1120+
// aliasing model.
1121+
let b = mem::ManuallyDrop::new(b);
1122+
let alloc = unsafe { ptr::read(&b.1) };
1123+
(unsafe { retag_box_to_raw::<T, A>(b.0.as_ptr()) }, alloc)
11151124
}
11161125

11171126
#[unstable(
@@ -1122,13 +1131,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
11221131
#[inline]
11231132
#[doc(hidden)]
11241133
pub fn into_unique(b: Self) -> (Unique<T>, A) {
1125-
// Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a
1126-
// raw pointer for the type system. Turning it directly into a raw pointer would not be
1127-
// recognized as "releasing" the unique pointer to permit aliased raw accesses,
1128-
// so all raw pointer methods have to go through `Box::leak`. Turning *that* to a raw pointer
1129-
// behaves correctly.
1130-
let alloc = unsafe { ptr::read(&b.1) };
1131-
(Unique::from(Box::leak(b)), alloc)
1134+
let (ptr, alloc) = Box::into_raw_with_allocator(b);
1135+
unsafe { (Unique::from(&mut *ptr), alloc) }
11321136
}
11331137

11341138
/// Returns a reference to the underlying allocator.
@@ -1184,7 +1188,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
11841188
where
11851189
A: 'a,
11861190
{
1187-
unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() }
1191+
unsafe { &mut *Box::into_raw(b) }
11881192
}
11891193

11901194
/// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then

core/src/intrinsics.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,6 +2695,19 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
26952695
unreachable!()
26962696
}
26972697

2698+
/// Retag a box pointer as part of casting it to a raw pointer. This is the `Box` equivalent of
2699+
/// `(x: &mut T) as *mut T`. The input pointer must be the pointer of a `Box` (passed as raw pointer
2700+
/// to avoid all questions around move semantics and custom allocators), and `A` must be the `Box`'s
2701+
/// allocator.
2702+
#[unstable(feature = "core_intrinsics", issue = "none")]
2703+
#[rustc_nounwind]
2704+
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
2705+
#[cfg_attr(bootstrap, inline)]
2706+
pub unsafe fn retag_box_to_raw<T: ?Sized, A>(ptr: *mut T) -> *mut T {
2707+
// Miri needs to adjust the provenance, but for regular codegen this is not needed
2708+
ptr
2709+
}
2710+
26982711
// Some functions are defined here because they accidentally got made
26992712
// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
27002713
// (`transmute` also falls into this category, but it cannot be wrapped due to the

0 commit comments

Comments
 (0)