diff options
| author | Ralf Jung <post@ralfj.de> | 2024-03-09 13:05:13 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-03-09 13:08:55 +0100 |
| commit | e632e3f9a501daefde13a264e1d0aff54a417510 (patch) | |
| tree | 359398ad1caca9d7bba77599018ea1f0a284537b /library/alloc | |
| parent | 1b427b3bf79c2cd48c75915301be3b009b82dea3 (diff) | |
| download | rust-e632e3f9a501daefde13a264e1d0aff54a417510.tar.gz rust-e632e3f9a501daefde13a264e1d0aff54a417510.zip | |
miri: do not apply aliasing restrictions to Box with custom allocator
Diffstat (limited to 'library/alloc')
| -rw-r--r-- | library/alloc/src/boxed.rs | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 2736e5ee6c5..304f607000b 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -155,6 +155,7 @@ use core::error::Error; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; +use core::intrinsics::retag_box_to_raw; use core::iter::FusedIterator; use core::marker::Tuple; use core::marker::Unsize; @@ -1110,8 +1111,16 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { - let (leaked, alloc) = Box::into_unique(b); - (leaked.as_ptr(), alloc) + // This is the transition point from `Box` to raw pointers. For Stacked Borrows, these casts + // are relevant -- if this is a global allocator Box and we just get the pointer from `b.0`, + // it will have `Unique` permission, which is not what we want from a raw pointer. We could + // fix that by going through `&mut`, but then if this is *not* a global allocator Box, we'd + // be adding uniqueness assertions that we do not want. So for Miri's sake we pass this + // pointer through an intrinsic for box-to-raw casts, which can do the right thing wrt the + // aliasing model. + let b = mem::ManuallyDrop::new(b); + let alloc = unsafe { ptr::read(&b.1) }; + (unsafe { retag_box_to_raw::<T, A>(b.0.as_ptr()) }, alloc) } #[unstable( @@ -1122,13 +1131,8 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { #[inline] #[doc(hidden)] pub fn into_unique(b: Self) -> (Unique<T>, A) { - // Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a - // raw pointer for the type system. Turning it directly into a raw pointer would not be - // recognized as "releasing" the unique pointer to permit aliased raw accesses, - // so all raw pointer methods have to go through `Box::leak`. Turning *that* to a raw pointer - // behaves correctly. - let alloc = unsafe { ptr::read(&b.1) }; - (Unique::from(Box::leak(b)), alloc) + let (ptr, alloc) = Box::into_raw_with_allocator(b); + unsafe { (Unique::from(&mut *ptr), alloc) } } /// Returns a reference to the underlying allocator. @@ -1184,7 +1188,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> { where A: 'a, { - unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() } + unsafe { &mut *Box::into_raw(b) } } /// Converts a `Box<T>` into a `Pin<Box<T>>`. If `T` does not implement [`Unpin`], then |
