diff options
| author | Tim Diekmann <tim.diekmann@3dvision.de> | 2020-10-06 16:37:23 +0200 |
|---|---|---|
| committer | Tim Diekmann <tim.diekmann@3dvision.de> | 2020-10-07 03:07:02 +0200 |
| commit | f288cd2e179f600fa00c2a407206a12f6c5a91e0 (patch) | |
| tree | 17d8a9240d44b2e34d96e63c4368778748cee14b | |
| parent | 59dafb876e125c49fca93820c5ef22da3fcb8644 (diff) | |
| download | rust-f288cd2e179f600fa00c2a407206a12f6c5a91e0.tar.gz rust-f288cd2e179f600fa00c2a407206a12f6c5a91e0.zip | |
Support custom allocators in `Box`
Remove `Box::leak_with_alloc` Add leak-test for box with allocator Rename `AllocErr` to `AllocError` in leak-test Add `Box::alloc` and adjust examples to use the new API
29 files changed, 574 insertions, 212 deletions
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index ce70de6ebdd..4b8300f1862 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -2,8 +2,13 @@ #![stable(feature = "alloc_module", since = "1.28.0")] -use core::intrinsics::{self, min_align_of_val, size_of_val}; -use core::ptr::{self, NonNull, Unique}; +#[cfg(not(test))] +use core::intrinsics; +use core::intrinsics::{min_align_of_val, size_of_val}; + +use core::ptr::Unique; +#[cfg(not(test))] +use core::ptr::{self, NonNull}; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] @@ -40,8 +45,12 @@ extern "Rust" { /// accessed through the [free functions in `alloc`](index.html#functions). #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] +#[cfg(not(test))] pub struct Global; +#[cfg(test)] +pub use std::alloc::Global; + /// Allocate memory with the global allocator. /// /// This function forwards calls to the [`GlobalAlloc::alloc`] method @@ -145,6 +154,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } } +#[cfg(not(test))] impl Global { #[inline] fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> { @@ -208,6 +218,7 @@ impl Global { } #[unstable(feature = "allocator_api", issue = "32838")] +#[cfg(not(test))] unsafe impl AllocRef for Global { #[inline] fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { @@ -314,12 +325,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { // well. // For example if `Box` is changed to `struct Box<T: ?Sized, A: AllocRef>(Unique<T>, A)`, // this function has to be changed to `fn box_free<T: ?Sized, A: AllocRef>(Unique<T>, A)` as well. -pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) { +pub(crate) unsafe fn box_free<T: ?Sized, A: AllocRef>(ptr: Unique<T>, alloc: A) { unsafe { let size = size_of_val(ptr.as_ref()); let align = min_align_of_val(ptr.as_ref()); let layout = Layout::from_size_align_unchecked(size, align); - Global.dealloc(ptr.cast().into(), layout) + alloc.dealloc(ptr.cast().into(), layout) } } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 5c8c2c5a5a8..d6d09b68a61 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -145,7 +145,7 @@ use core::pin::Pin; use core::ptr::{self, Unique}; use core::task::{Context, Poll}; -use crate::alloc::{self, AllocRef, Global}; +use crate::alloc::{handle_alloc_error, AllocRef, Global, Layout}; use crate::borrow::Cow; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -157,7 +157,10 @@ use crate::vec::Vec; #[lang = "owned_box"] #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Box<T: ?Sized>(Unique<T>); +pub struct Box< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global, +>(Unique<T>, A); impl<T> Box<T> { /// Allocates memory on the heap and then places `x` into it. @@ -171,7 +174,7 @@ impl<T> Box<T> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - pub fn new(x: T) -> Box<T> { + pub fn new(x: T) -> Self { box x } @@ -194,10 +197,9 @@ impl<T> Box<T> { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] pub fn new_uninit() -> Box<mem::MaybeUninit<T>> { - let layout = alloc::Layout::new::<mem::MaybeUninit<T>>(); - let ptr = Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast(); - unsafe { Box::from_raw(ptr.as_ptr()) } + Self::new_uninit_in(Global) } /// Constructs a new `Box` with uninitialized contents, with the memory @@ -219,13 +221,9 @@ impl<T> Box<T> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> { - let layout = alloc::Layout::new::<mem::MaybeUninit<T>>(); - let ptr = Global - .alloc_zeroed(layout) - .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) - .cast(); - unsafe { Box::from_raw(ptr.as_ptr()) } + Self::new_zeroed_in(Global) } /// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then @@ -235,14 +233,103 @@ impl<T> Box<T> { pub fn pin(x: T) -> Pin<Box<T>> { (box x).into() } +} + +impl<T, A: AllocRef> Box<T, A> { + /// Allocates memory in the given allocator then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let five = Box::new_in(5, System); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn new_in(x: T, alloc: A) -> Self { + let mut boxed = Self::new_uninit_in(alloc); + unsafe { + boxed.as_mut_ptr().write(x); + boxed.assume_init() + } + } + + /// Constructs a new box with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::<u32, _>::new_uninit_in(System); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> { + let layout = Layout::new::<mem::MaybeUninit<T>>(); + let ptr = alloc.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)).cast(); + unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes in the provided allocator. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let zero = Box::<u32, _>::new_zeroed_in(System); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> { + let layout = Layout::new::<mem::MaybeUninit<T>>(); + let ptr = alloc.alloc_zeroed(layout).unwrap_or_else(|_| handle_alloc_error(layout)).cast(); + unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } + } + + /// Constructs a new `Pin<Box<T, A>>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline(always)] + pub fn pin_in(x: T, alloc: A) -> Pin<Self> { + Self::new_in(x, alloc).into() + } /// Converts a `Box<T>` into a `Box<[T]>` /// /// This conversion does not allocate on the heap and happens in place. #[unstable(feature = "box_into_boxed_slice", issue = "71582")] - pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> { - // *mut T and *mut [T; 1] have the same size and alignment - unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1]) } + pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_alloc(boxed); + unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } } } @@ -296,8 +383,64 @@ impl<T> Box<[T]> { } } -impl<T> Box<mem::MaybeUninit<T>> { - /// Converts to `Box<T>`. +impl<T, A: AllocRef> Box<[T], A> { + /// Constructs a new boxed slice with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut values = Box::<[u32], _>::new_uninit_slice_in(3, System); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> { + unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } + } + + /// Constructs a new boxed slice with uninitialized contents in the provided allocator, + /// with the memory being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, new_uninit)] + /// + /// use std::alloc::System; + /// + /// let values = Box::<[u32], _>::new_zeroed_slice_in(3, System); + /// let values = unsafe { values.assume_init() }; + /// + /// assert_eq!(*values, [0, 0, 0]) + /// ``` + /// + /// [zeroed]: mem::MaybeUninit::zeroed + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit<T>], A> { + unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } + } +} + +impl<T, A: AllocRef> Box<mem::MaybeUninit<T>, A> { + /// Converts to `Box<T, A>`. /// /// # Safety /// @@ -327,13 +470,14 @@ impl<T> Box<mem::MaybeUninit<T>> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Box<T> { - unsafe { Box::from_raw(Box::into_raw(self) as *mut T) } + pub unsafe fn assume_init(self) -> Box<T, A> { + let (raw, alloc) = Box::into_raw_with_alloc(self); + unsafe { Box::from_raw_in(raw as *mut T, alloc) } } } -impl<T> Box<[mem::MaybeUninit<T>]> { - /// Converts to `Box<[T]>`. +impl<T, A: AllocRef> Box<[mem::MaybeUninit<T>], A> { + /// Converts to `Box<[T], A>`. /// /// # Safety /// @@ -365,8 +509,9 @@ impl<T> Box<[mem::MaybeUninit<T>]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Box<[T]> { - unsafe { Box::from_raw(Box::into_raw(self) as *mut [T]) } + pub unsafe fn assume_init(self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_alloc(self); + unsafe { Box::from_raw_in(raw as *mut [T], alloc) } } } @@ -412,7 +557,62 @@ impl<T: ?Sized> Box<T> { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - Box(unsafe { Unique::new_unchecked(raw) }) + unsafe { Self::from_raw_in(raw, Global) } + } +} + +impl<T: ?Sized, A: AllocRef> Box<T, A> { + /// Constructs a box from a raw pointer in the given allocator. + /// + /// After calling this function, the raw pointer is owned by the + /// resulting `Box`. Specifically, the `Box` destructor will call + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, a double-free may occur if the + /// function is called twice on the same raw pointer. + /// + /// + /// # Examples + /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw_with_alloc`]: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(5, System); + /// let (ptr, alloc) = Box::into_raw_with_alloc(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manually create a `Box` from scratch by using the system allocator: + /// ``` + /// #![feature(allocator_api, slice_ptr_get)] + /// + /// use std::alloc::{AllocRef, Layout, System}; + /// + /// unsafe { + /// let ptr = System.alloc(Layout::new::<i32>())?.as_mut_ptr(); + /// // In general .write is required to avoid attempting to destruct + /// // the (uninitialized) previous contents of `ptr`, though for this + /// // simple example `*ptr = 5` would have worked as well. + /// ptr.write(5); + /// let x = Box::from_raw_in(ptr, System); + /// } + /// # Ok::<(), std::alloc::AllocError>(()) + /// ``` + /// + /// [memory layout]: self#memory-layout + /// [`Layout`]: crate::Layout + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + Box(unsafe { Unique::new_unchecked(raw) }, alloc) } /// Consumes the `Box`, returning a wrapped raw pointer. @@ -456,13 +656,61 @@ impl<T: ?Sized> Box<T> { /// [memory layout]: self#memory-layout #[stable(feature = "box_raw", since = "1.4.0")] #[inline] - pub fn into_raw(b: Box<T>) -> *mut T { - // 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 go through `leak` which creates a (unique) - // mutable reference. Turning *that* to a raw pointer behaves correctly. - Box::leak(b) as *mut T + pub fn into_raw(b: Self) -> *mut T { + Self::into_raw_with_alloc(b).0 + } + + /// Consumes the `Box`, returning a wrapped raw pointer and the allocator. + /// + /// The pointer will be properly aligned and non-null. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Box`. In particular, the + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform + /// the cleanup. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw_with_alloc(b)` instead of `b.into_raw_with_alloc()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// # Examples + /// Converting the raw pointer back into a `Box` with [`Box::from_raw_in`] + /// for automatic cleanup: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (ptr, alloc) = Box::into_raw_with_alloc(x); + /// let x = unsafe { Box::from_raw_in(ptr, alloc) }; + /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::{AllocRef, Layout, System}; + /// use std::ptr::{self, NonNull}; + /// + /// let x = Box::new_in(String::from("Hello"), System); + /// let (ptr, alloc) = Box::into_raw_with_alloc(x); + /// unsafe { + /// ptr::drop_in_place(ptr); + /// let non_null = NonNull::new_unchecked(ptr); + /// alloc.dealloc(non_null.cast(), Layout::new::<String>()); + /// } + /// ``` + /// + /// [memory layout]: self#memory-layout + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn into_raw_with_alloc(b: Self) -> (*mut T, A) { + let (leaked, alloc) = Box::into_unique(b); + (leaked.as_ptr(), alloc) } #[unstable( @@ -472,13 +720,30 @@ impl<T: ?Sized> Box<T> { )] #[inline] #[doc(hidden)] - pub fn into_unique(b: Box<T>) -> Unique<T> { + 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 go through `leak` which creates a (unique) - // mutable reference. Turning *that* to a raw pointer behaves correctly. - Box::leak(b).into() + // so all raw pointer methods have to leak the box. Turning *that* to a raw pointer + // behaves correctly. + let b = mem::ManuallyDrop::new(b); + + // The box is unitiliazed later when moving out the allocator. The pointer is stored + // beforehand. + let ptr = b.0; + let alloc = unsafe { ptr::read(&b.1) }; + (ptr, alloc) + } + + /// Returns a reference to the underlying allocator. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::alloc(&b)` instead of `b.alloc()`. This + /// is so that there is no conflict with a method on the inner type. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn alloc(b: &Self) -> &A { + &b.1 } /// Consumes and leaks the `Box`, returning a mutable reference, @@ -518,9 +783,9 @@ impl<T: ?Sized> Box<T> { /// ``` #[stable(feature = "box_leak", since = "1.26.0")] #[inline] - pub fn leak<'a>(b: Box<T>) -> &'a mut T + pub fn leak<'a>(b: Self) -> &'a mut T where - T: 'a, // Technically not needed, but kept to be explicit. + A: 'a, { unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() } } @@ -531,7 +796,7 @@ impl<T: ?Sized> Box<T> { /// /// This is also available via [`From`]. #[unstable(feature = "box_into_pin", issue = "62370")] - pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>> { + pub fn into_pin(boxed: Self) -> Pin<Self> { // It's not possible to move or replace the insides of a `Pin<Box<T>>` // when `T: !Unpin`, so it's safe to pin it directly without any // additional requirements. @@ -540,7 +805,7 @@ impl<T: ?Sized> Box<T> { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized> Drop for Box<T> { +unsafe impl<#[may_dangle] T: ?Sized, A: AllocRef> Drop for Box<T, A> { fn drop(&mut self) { // FIXME: Do nothing, drop is currently performed by compiler. } @@ -549,27 +814,27 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Box<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: Default> Default for Box<T> { /// Creates a `Box<T>`, with the `Default` value for T. - fn default() -> Box<T> { - box Default::default() + fn default() -> Self { + box T::default() } } #[stable(feature = "rust1", since = "1.0.0")] impl<T> Default for Box<[T]> { - fn default() -> Box<[T]> { + fn default() -> Self { Box::<[T; 0]>::new([]) } } #[stable(feature = "default_box_extra", since = "1.17.0")] impl Default for Box<str> { - fn default() -> Box<str> { + fn default() -> Self { unsafe { from_boxed_utf8_unchecked(Default::default()) } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Clone> Clone for Box<T> { +impl<T: Clone, A: AllocRef + Clone> Clone for Box<T, A> { /// Returns a new box with a `clone()` of this box's contents. /// /// # Examples @@ -586,8 +851,8 @@ impl<T: Clone> Clone for Box<T> { /// ``` #[rustfmt::skip] #[inline] - fn clone(&self) -> Box<T> { - box { (**self).clone() } + fn clone(&self) -> Self { + Self::new_in((**self).clone(), self.1.clone()) } /// Copies `source`'s contents into `self` without creating a new allocation. @@ -608,7 +873,7 @@ impl<T: Clone> Clone for Box<T> { /// assert_eq!(yp, &*y); /// ``` #[inline] - fn clone_from(&mut self, source: &Box<T>) { + fn clone_from(&mut self, source: &Self) { (**self).clone_from(&(**source)); } } @@ -623,58 +888,58 @@ impl Clone for Box<str> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized + PartialEq> PartialEq for Box<T> { +impl<T: ?Sized + PartialEq, A: AllocRef> PartialEq for Box<T, A> { #[inline] - fn eq(&self, other: &Box<T>) -> bool { + fn eq(&self, other: &Self) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &Box<T>) -> bool { + fn ne(&self, other: &Self) -> bool { PartialEq::ne(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> { +impl<T: ?Sized + PartialOrd, A: AllocRef> PartialOrd for Box<T, A> { #[inline] - fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { PartialOrd::partial_cmp(&**self, &**other) } #[inline] - fn lt(&self, other: &Box<T>) -> bool { + fn lt(&self, other: &Self) -> bool { PartialOrd::lt(&**self, &**other) } #[inline] - fn le(&self, other: &Box<T>) -> bool { + fn le(&self, other: &Self) -> bool { PartialOrd::le(&**self, &**other) } #[inline] - fn ge(&self, other: &Box<T>) -> bool { + fn ge(&self, other: &Self) -> bool { PartialOrd::ge(&**self, &**other) } #[inline] - fn gt(&self, other: &Box<T>) -> bool { + fn gt(&self, other: &Self) -> bool { PartialOrd::gt(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized + Ord> Ord for Box<T> { +impl<T: ?Sized + Ord, A: AllocRef> Ord for Box<T, A> { #[inline] - fn cmp(&self, other: &Box<T>) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized + Eq> Eq for Box<T> {} +impl<T: ?Sized + Eq, A: AllocRef> Eq for Box<T, A> {} #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized + Hash> Hash for Box<T> { +impl<T: ?Sized + Hash, A: AllocRef> Hash for Box<T, A> { fn hash<H: Hasher>(&self, state: &mut H) { (**self).hash(state); } } #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] -impl<T: ?Sized + Hasher> Hasher for Box<T> { +impl<T: ?Sized + Hasher, A: AllocRef> Hasher for Box<T, A> { fn finish(&self) -> u64 { (**self).finish() } @@ -739,11 +1004,11 @@ impl<T> From<T> for Box<T> { } #[stable(feature = "pin", since = "1.33.0")] -impl<T: ?Sized> From<Box<T>> for Pin<Box<T>> { +impl<T: ?Sized, A: AllocRef> From<Box<T, A>> for Pin<Box<T, A>> { /// Converts a `Box<T>` into a `Pin<Box<T>>` /// /// This conversion does not allocate on the heap and happens in place. - fn from(boxed: Box<T>) -> Self { + fn from(boxed: Box<T, A>) -> Self { Box::into_pin(boxed) } } @@ -814,7 +1079,7 @@ impl From<Cow<'_, str>> for Box<str> { } #[stable(feature = "boxed_str_conv", since = "1.19.0")] -impl From<Box<str>> for Box<[u8]> { +impl<A: AllocRef> From<Box<str, A>> for Box<[u8], A> { /// Converts a `Box<str>>` into a `Box<[u8]>` /// /// This conversion does not allocate on the heap and happens in place. @@ -832,8 +1097,9 @@ impl From<Box<str>> for Box<[u8]> { /// assert_eq!(boxed_slice, boxed_str); /// ``` #[inline] - fn from(s: Box<str>) -> Self { - unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) } + fn from(s: Box<str, A>) -> Self { + let (raw, alloc) = Box::into_raw_with_alloc(s); + unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } } } @@ -866,7 +1132,7 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> { } } -impl Box<dyn Any> { +impl<A: AllocRef> Box<dyn Any, A> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. @@ -886,11 +1152,11 @@ impl Box<dyn Any> { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` - pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<dyn Any>> { + pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> { if self.is::<T>() { unsafe { - let raw: *mut dyn Any = Box::into_raw(self); - Ok(Box::from_raw(raw as *mut T)) + let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_alloc(self); + Ok(Box::from_raw_in(raw as *mut T, alloc)) } } else { Err(self) @@ -898,7 +1164,7 @@ impl Box<dyn Any> { } } -impl Box<dyn Any + Send> { +impl<A: AllocRef> Box<dyn Any + Send, A> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. @@ -918,30 +1184,34 @@ impl Box<dyn Any + Send> { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` - pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<dyn Any + Send>> { - <Box<dyn Any>>::downcast(self).map_err(|s| unsafe { - // reapply the Send marker - Box::from_raw(Box::into_raw(s) as *mut (dyn Any + Send)) - }) + pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> { + if self.is::<T>() { + unsafe { + let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_alloc(self); + Ok(Box::from_raw_in(raw as *mut T, alloc)) + } + } else { + Err(self) + } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> { +impl<T: fmt::Display + ?Sized, A: AllocRef> fmt::Display for Box<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> { +impl<T: fmt::Debug + ?Sized, A: AllocRef> fmt::Debug for Box<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> fmt::Pointer for Box<T> { +impl<T: ?Sized, A: AllocRef> fmt::Pointer for Box<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // It's not possible to extract the inner Uniq directly from the Box, // instead we cast it to a *const which aliases the Unique @@ -951,7 +1221,7 @@ impl<T: ?Sized> fmt::Pointer for Box<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> Deref for Box<T> { +impl<T: ?Sized, A: AllocRef> Deref for Box<T, A> { type Target = T; fn deref(&self) -> &T { @@ -960,17 +1230,17 @@ impl<T: ?Sized> Deref for Box<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> DerefMut for Box<T> { +impl<T: ?Sized, A: AllocRef> DerefMut for Box<T, A> { fn deref_mut(&mut self) -> &mut T { &mut **self } } #[unstable(feature = "receiver_trait", issue = "none")] -impl<T: ?Sized> Receiver for Box<T> {} +impl<T: ?Sized, A: AllocRef> Receiver for Box<T, A> {} #[stable(feature = "rust1", since = "1.0.0")] -impl<I: Iterator + ?Sized> Iterator for Box<I> { +impl<I: Iterator + ?Sized, A: AllocRef> Iterator for Box<I, A> { type Item = I::Item; fn next(&mut self) -> Option<I::Item> { (**self).next() @@ -991,7 +1261,7 @@ trait BoxIter { fn last(self) -> Option<Self::Item>; } -impl<I: Iterator + ?Sized> BoxIter for Box<I> { +impl<I: Iterator + ?Sized, A: AllocRef> BoxIter for Box<I, A> { type Item = I::Item; default fn last(self) -> Option<I::Item> { #[inline] @@ -1006,14 +1276,14 @@ impl<I: Iterator + ?Sized> BoxIter for Box<I> { /// Specialization for sized `I`s that uses `I`s implementation of `last()` /// instead of the default. #[stable(feature = "rust1", since = "1.0.0")] -impl<I: Iterator> BoxIter for Box<I> { +impl<I: Iterator, A: AllocRef> BoxIter for Box<I, A> { fn last(self) -> Option<I::Item> { (*self).last() } } #[stable(feature = "rust1", since = "1.0.0")] -impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> { +impl<I: DoubleEndedIterator + ?Sized, A: AllocRef> DoubleEndedIterator for Box<I, A> { fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() } @@ -1022,7 +1292,7 @@ impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> { } } #[stable(feature = "rust1", since = "1.0.0")] -impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> { +impl<I: ExactSizeIterator + ?Sized, A: AllocRef> ExactSizeIterator for Box<I, A> { fn len(&self) -> usize { (**self).len() } @@ -1032,40 +1302,40 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> { } #[stable(feature = "fused", since = "1.26.0")] -impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {} +impl<I: FusedIterator + ?Sized, A: AllocRef> FusedIterator for Box<I, A> {} #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<A, F: FnOnce<A> + ?Sized> FnOnce<A> for Box<F> { - type Output = <F as FnOnce<A>>::Output; +impl<Args, F: FnOnce<Args> + ?Sized, A: AllocRef> FnOnce<Args> for Box<F, A> { + type Output = <F as FnOnce<Args>>::Output; - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - <F as FnOnce<A>>::call_once(*self, args) + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + <F as FnOnce<Args>>::call_once(*self, args) } } #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<A, F: FnMut<A> + ?Sized> FnMut<A> for Box<F> { - extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { - <F as FnMut<A>>::call_mut(self, args) +impl<Args, F: FnMut<Args> + ?Sized, A: AllocRef> FnMut<Args> for Box<F, A> { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + <F as FnMut<Args>>::call_mut(self, args) } } #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> { - extern "rust-call" fn call(&self, args: A) -> Self::Output { - <F as Fn<A>>::call(self, args) +impl<Args, F: Fn<Args> + ?Sized, A: AllocRef> Fn<Args> for Box<F, A> { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + <F as Fn<Args>>::call(self, args) } } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {} +impl<T: ?Sized + Unsize<U>, U: ?Sized, A: AllocRef> CoerceUnsized<Box<U, A>> for Box<T, A> {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] -impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {} +impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T, Global> {} #[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] -impl<A> FromIterator<A> for Box<[A]> { - fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self { +impl<I> FromIterator<I> for Box<[I]> { + fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self { iter.into_iter().collect::<Vec<_>>().into_boxed_slice() } } @@ -1086,28 +1356,28 @@ impl<T: Clone> Clone for Box<[T]> { } #[stable(feature = "box_borrow", since = "1.1.0")] -impl<T: ?Sized> borrow::Borrow<T> for Box<T> { +impl<T: ?Sized, A: AllocRef> borrow::Borrow<T> for Box<T, A> { fn borrow(&self) -> &T { &**self } } #[stable(feature = "box_borrow", since = "1.1.0")] -impl<T: ?Sized> borrow::BorrowMut<T> for Box<T> { +impl<T: ?Sized, A: AllocRef> borrow::BorrowMut<T> for Box<T, A> { fn borrow_mut(&mut self) -> &mut T { &mut **self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl<T: ?Sized> AsRef<T> for Box<T> { +impl<T: ?Sized, A: AllocRef> AsRef<T> for Box<T, A> { fn as_ref(&self) -> &T { &**self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl<T: ?Sized> AsMut<T> for Box<T> { +impl<T: ?Sized, A: AllocRef> AsMut<T> for Box<T, A> { fn as_mut(&mut self) -> &mut T { &mut **self } @@ -1136,10 +1406,10 @@ impl<T: ?Sized> AsMut<T> for Box<T> { * could have a method to project a Pin<T> from it. */ #[stable(feature = "pin", since = "1.33.0")] -impl<T: ?Sized> Unpin for Box<T> {} +impl<T: ?Sized, A: AllocRef> Unpin for Box<T, A> {} #[unstable(feature = "generator_trait", issue = "43122")] -impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> { +impl<G: ?Sized + Generator<R> + Unpin, R, A: AllocRef> Generator<R> for Box<G, A> { type Yield = G::Yield; type Return = G::Return; @@ -1149,7 +1419,7 @@ impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for Box<G> { } #[unstable(feature = "generator_trait", issue = "43122")] -impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> { +impl<G: ?Sized + Generator<R>, R, A: AllocRef> Generator<R> for Pin<Box<G, A>> { type Yield = G::Yield; type Return = G::Return; @@ -1159,7 +1429,7 @@ impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<Box<G>> { } #[stable(feature = "futures_api", since = "1.36.0")] -impl<F: ?Sized + Future + Unpin> Future for Box<F> { +impl<F: ?Sized + Future + Unpin, A: AllocRef> Future for Box<F, A> { type Output = F::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 880627e94c3..626521c2c3c 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -121,7 +121,7 @@ struct BoxedNode<K, V> { impl<K, V> BoxedNode<K, V> { fn from_leaf(node: Box<LeafNode<K, V>>) -> Self { - BoxedNode { ptr: Box::into_unique(node) } + BoxedNode { ptr: Box::into_unique(node).0 } } fn from_internal(node: Box<InternalNode<K, V>>) -> Self { diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 1844d3ae004..a60e676fda5 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -6,7 +6,7 @@ use core::cmp; use core::intrinsics; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::Drop; -use core::ptr::{NonNull, Unique}; +use core::ptr::{self, NonNull, Unique}; use core::slice; use crate::alloc::{handle_alloc_error, AllocRef, Global, Layout}; @@ -111,12 +111,36 @@ impl<T> RawVec<T, Global> { pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { unsafe { Self::from_raw_parts_in(ptr, capacity, Global) } } +} + +impl<T, A: AllocRef> RawVec<T, A> { + /// Like `new`, but parameterized over the choice of allocator for + /// the returned `RawVec`. + #[allow_internal_unstable(const_fn)] + pub const fn new_in(alloc: A) -> Self { + // `cap: 0` means "unallocated". zero-sized types are ignored. + Self { ptr: Unique::dangling(), cap: 0, alloc } + } + + /// Like `with_capacity`, but parameterized over the choice of + /// allocator for the returned `RawVec`. + #[inline] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self::allocate_in(capacity, AllocInit::Uninitialized, alloc) + } + + /// Like `with_capacity_zeroed`, but parameterized over the choice + /// of allocator for the returned `RawVec`. + #[inline] + pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { + Self::allocate_in(capacity, AllocInit::Zeroed, alloc) + } /// Converts a `Box<[T]>` into a `RawVec<T>`. - pub fn from_box(slice: Box<[T]>) -> Self { + pub fn from_box(slice: Box<[T], A>) -> Self { unsafe { - let mut slice = ManuallyDrop::new(slice); - RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len()) + let (slice, alloc) = Box::into_raw_with_alloc(slice); + RawVec::from_raw_parts_in(slice.as_mut_ptr(), slice.len(), alloc) } } @@ -132,7 +156,7 @@ impl<T> RawVec<T, Global> { /// /// Note, that the requested capacity and `self.capacity()` could differ, as /// an allocator could overallocate and return a greater memory block than requested. - pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>]> { + pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>], A> { // Sanity-check one half of the safety requirement (we cannot check the other half). debug_assert!( len <= self.capacity(), @@ -142,33 +166,9 @@ impl<T> RawVec<T, Global> { let me = ManuallyDrop::new(self); unsafe { let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len); - Box::from_raw(slice) + Box::from_raw_in(slice, ptr::read(&me.alloc)) } } -} - -impl<T, A: AllocRef> RawVec<T, A> { - /// Like `new`, but parameterized over the choice of allocator for - /// the returned `RawVec`. - #[allow_internal_unstable(const_fn)] - pub const fn new_in(alloc: A) -> Self { - // `cap: 0` means "unallocated". zero-sized types are ignored. - Self { ptr: Unique::dangling(), cap: 0, alloc } - } - - /// Like `with_capacity`, but parameterized over the choice of - /// allocator for the returned `RawVec`. - #[inline] - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Self::allocate_in(capacity, AllocInit::Uninitialized, alloc) - } - - /// Like `with_capacity_zeroed`, but parameterized over the choice - /// of allocator for the returned `RawVec`. - #[inline] - pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { - Self::allocate_in(capacity, AllocInit::Zeroed, alloc) - } fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { if mem::size_of::<T>() == 0 { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 939ebe074ed..72e5e0a8242 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1034,7 +1034,7 @@ impl<T: ?Sized> Rc<T> { fn from_box(v: Box<T>) -> Rc<T> { unsafe { - let box_unique = Box::into_unique(v); + let (box_unique, alloc) = Box::into_unique(v); let bptr = box_unique.as_ptr(); let value_size = size_of_val(&*bptr); @@ -1048,7 +1048,7 @@ impl<T: ?Sized> Rc<T> { ); // Free the allocation without dropping its contents - box_free(box_unique); + box_free(box_unique, alloc); Self::from_ptr(ptr) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 3a83aa7cbe5..d70de1163c9 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1006,7 +1006,7 @@ impl<T: ?Sized> Arc<T> { fn from_box(v: Box<T>) -> Arc<T> { unsafe { - let box_unique = Box::into_unique(v); + let (box_unique, alloc) = Box::into_unique(v); let bptr = box_unique.as_ptr(); let value_size = size_of_val(&*bptr); @@ -1020,7 +1020,7 @@ impl<T: ?Sized> Arc<T> { ); // Free the allocation without dropping its contents - box_free(box_unique); + box_free(box_unique, alloc); Self::from_ptr(ptr) } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 4535cf290a1..f01f8d6211f 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -53,10 +53,10 @@ - } - - bb4 (cleanup): { -- _3 = alloc::alloc::box_free::<Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- _3 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_2.1: std::alloc::Global)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 -- // + literal: Const { ty: unsafe fn(std::ptr::Unique<std::vec::Vec<u32>>) {alloc::alloc::box_free::<std::vec::Vec<u32>>}, val: Value(Scalar(<ZST>)) } +- // + literal: Const { ty: unsafe fn(std::ptr::Unique<std::vec::Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<std::vec::Vec<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) } } } diff --git a/src/test/ui/box/alloc-unstable-fail.rs b/src/test/ui/box/alloc-unstable-fail.rs new file mode 100644 index 00000000000..9427571648c --- /dev/null +++ b/src/test/ui/box/alloc-unstable-fail.rs @@ -0,0 +1,6 @@ +use std::boxed::Box; + +fn main() { + let _boxed: Box<u32, _> = Box::new(10); + //~^ ERROR use of unstable library feature 'allocator_api' +} diff --git a/src/test/ui/box/alloc-unstable-fail.stderr b/src/test/ui/box/alloc-unstable-fail.stderr new file mode 100644 index 00000000000..03ae36e8890 --- /dev/null +++ b/src/test/ui/box/alloc-unstable-fail.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/alloc-unstable-fail.rs:4:26 + | +LL | let _boxed: Box<u32, _> = Box::new(10); + | ^ + | + = note: see issue #32838 <https://github.com/rust-lang/rust/issues/32838> for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/box/alloc-unstable.rs b/src/test/ui/box/alloc-unstable.rs new file mode 100644 index 00000000000..66388d0d512 --- /dev/null +++ b/src/test/ui/box/alloc-unstable.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(allocator_api)] + +use std::boxed::Box; + +fn main() { + let _boxed: Box<u32, _> = Box::new(10); +} diff --git a/src/test/ui/box-into-boxed-slice-fail.rs b/src/test/ui/box/into-boxed-slice-fail.rs index 49dbb170f8e..49dbb170f8e 100644 --- a/src/test/ui/box-into-boxed-slice-fail.rs +++ b/src/test/ui/box/into-boxed-slice-fail.rs diff --git a/src/test/ui/box-into-boxed-slice-fail.stderr b/src/test/ui/box/into-boxed-slice-fail.stderr index 8cfa3668d92..7a5ba16461f 100644 --- a/src/test/ui/box-into-boxed-slice-fail.stderr +++ b/src/test/ui/box/into-boxed-slice-fail.stderr @@ -1,14 +1,14 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/box-into-boxed-slice-fail.rs:7:35 + --> $DIR/into-boxed-slice-fail.rs:7:35 | LL | let _ = Box::into_boxed_slice(boxed_slice); | ^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: required by `Box::<T>::into_boxed_slice` + = note: required by `Box::<T, A>::into_boxed_slice` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/box-into-boxed-slice-fail.rs:7:13 + --> $DIR/into-boxed-slice-fail.rs:7:13 | LL | let _ = Box::into_boxed_slice(boxed_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -17,16 +17,16 @@ LL | let _ = Box::into_boxed_slice(boxed_slice); = note: slice and array elements must have `Sized` type error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time - --> $DIR/box-into-boxed-slice-fail.rs:11:35 + --> $DIR/into-boxed-slice-fail.rs:11:35 | LL | let _ = Box::into_boxed_slice(boxed_trait); | ^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Debug` - = note: required by `Box::<T>::into_boxed_slice` + = note: required by `Box::<T, A>::into_boxed_slice` error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time - --> $DIR/box-into-boxed-slice-fail.rs:11:13 + --> $DIR/into-boxed-slice-fail.rs:11:13 | LL | let _ = Box::into_boxed_slice(boxed_trait); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/src/test/ui/box-into-boxed-slice.rs b/src/test/ui/box/into-boxed-slice.rs index 61b3d915253..61b3d915253 100644 --- a/src/test/ui/box-into-boxed-slice.rs +++ b/src/test/ui/box/into-boxed-slice.rs diff --git a/src/test/ui/box/leak-alloc.rs b/src/test/ui/box/leak-alloc.rs new file mode 100644 index 00000000000..2e73d6f1432 --- /dev/null +++ b/src/test/ui/box/leak-alloc.rs @@ -0,0 +1,29 @@ +#![feature(allocator_api)] + +use std::alloc::{AllocError, AllocRef, Layout, System}; +use std::ptr::NonNull; + +use std::boxed::Box; + +struct Allocator {} + +unsafe impl AllocRef for Allocator { + fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { + System.alloc(layout) + } + + unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) { + System.dealloc(ptr, layout) + } +} + +fn use_value(_: u32) {} + +fn main() { + let alloc = Allocator {}; + let boxed = Box::new_in(10, alloc.by_ref()); + let theref = Box::leak(boxed); + drop(alloc); + //~^ ERROR cannot move out of `alloc` because it is borrowed + use_value(*theref) +} diff --git a/src/test/ui/box/leak-alloc.stderr b/src/test/ui/box/leak-alloc.stderr new file mode 100644 index 00000000000..09beb181460 --- /dev/null +++ b/src/test/ui/box/leak-alloc.stderr @@ -0,0 +1,15 @@ +error[E0505]: cannot move out of `alloc` because it is borrowed + --> $DIR/leak-alloc.rs:26:10 + | +LL | let boxed = Box::new_in(10, alloc.by_ref()); + | ----- borrow of `alloc` occurs here +LL | let theref = Box::leak(boxed); +LL | drop(alloc); + | ^^^^^ move out of `alloc` occurs here +LL | +LL | use_value(*theref) + | ------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/box-new.rs b/src/test/ui/box/new.rs index be1a40cf779..be1a40cf779 100644 --- a/src/test/ui/box-new.rs +++ b/src/test/ui/box/new.rs diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr index 0959e155c57..20dc955ffe4 100644 --- a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr +++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -2,9 +2,10 @@ error[E0117]: only traits defined in the current crate can be implemented for ar --> $DIR/impl-foreign-for-fundamental[foreign].rs:10:1 | LL | impl Remote for Box<i32> { - | ^^^^^^^^^^^^^^^^-------- - | | | - | | `i32` is not defined in the current crate + | ^^^^^------^^^^^-------- + | | | | + | | | `i32` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead @@ -13,9 +14,10 @@ error[E0117]: only traits defined in the current crate can be implemented for ar --> $DIR/impl-foreign-for-fundamental[foreign].rs:14:1 | LL | impl<T> Remote for Box<Rc<T>> { - | ^^^^^^^^^^^^^^^^^^^---------- - | | | - | | `Rc` is not defined in the current crate + | ^^^^^^^^------^^^^^---------- + | | | | + | | | `Rc` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr index b4d559eb1f2..c1e2fdaf5e3 100644 --- a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr +++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -6,6 +6,7 @@ LL | impl Remote1<Box<String>> for i32 { | | | | | | | `i32` is not defined in the current crate | | `String` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead @@ -18,6 +19,7 @@ LL | impl Remote1<Box<Rc<i32>>> for f64 { | | | | | | | `f64` is not defined in the current crate | | `Rc` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead @@ -30,6 +32,7 @@ LL | impl<T> Remote1<Box<Rc<T>>> for f32 { | | | | | | | `f32` is not defined in the current crate | | `Rc` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/src/test/ui/error-codes/e0119/conflict-with-std.stderr b/src/test/ui/error-codes/e0119/conflict-with-std.stderr index 4b6b4430f32..9dc1a509cd0 100644 --- a/src/test/ui/error-codes/e0119/conflict-with-std.stderr +++ b/src/test/ui/error-codes/e0119/conflict-with-std.stderr @@ -5,8 +5,8 @@ LL | impl AsRef<Q> for Box<Q> { | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `alloc`: - - impl<T> AsRef<T> for Box<T> - where T: ?Sized; + - impl<T, A> AsRef<T> for Box<T, A> + where A: AllocRef, T: ?Sized; error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`: --> $DIR/conflict-with-std.rs:12:1 diff --git a/src/test/ui/issues/issue-14092.rs b/src/test/ui/issues/issue-14092.rs index 77da6badde9..3cfaa20a8b5 100644 --- a/src/test/ui/issues/issue-14092.rs +++ b/src/test/ui/issues/issue-14092.rs @@ -1,4 +1,4 @@ fn fn1(0: Box) {} - //~^ ERROR wrong number of type arguments: expected 1, found 0 [E0107] + //~^ ERROR wrong number of type arguments: expected at least 1, found 0 [E0107] fn main() {} diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr index 626830ece8c..b749c44780d 100644 --- a/src/test/ui/issues/issue-14092.stderr +++ b/src/test/ui/issues/issue-14092.stderr @@ -1,8 +1,8 @@ -error[E0107]: wrong number of type arguments: expected 1, found 0 +error[E0107]: wrong number of type arguments: expected at least 1, found 0 --> $DIR/issue-14092.rs:1:11 | LL | fn fn1(0: Box) {} - | ^^^ expected 1 type argument + | ^^^ expected at least 1 type argument error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr index adad480f92b..c873c20cca8 100644 --- a/src/test/ui/issues/issue-3601.stderr +++ b/src/test/ui/issues/issue-3601.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `Box(_)` not covered +error[E0004]: non-exhaustive patterns: `Box(_, _)` not covered --> $DIR/issue-3601.rs:30:44 | LL | box NodeKind::Element(ed) => match ed.kind { - | ^^^^^^^ pattern `Box(_)` not covered + | ^^^^^^^ pattern `Box(_, _)` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `Box<ElementKind>` diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index f1342181b37..fb24aadde08 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -1,13 +1,13 @@ -error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_>`: +error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_, _>`: --> $DIR/issue-41974.rs:7:1 | LL | impl<T> Drop for T where T: A { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `alloc`: - - impl<T> Drop for Box<T> - where T: ?Sized; - = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>` + - impl<T, A> Drop for Box<T, A> + where A: AllocRef, T: ?Sized; + = note: downstream crates may implement trait `A` for type `std::boxed::Box<_, _>` error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions --> $DIR/issue-41974.rs:7:18 diff --git a/src/test/ui/privacy/privacy-ns1.rs b/src/test/ui/privacy/privacy-ns1.rs index 614375e5e51..c7084bfd980 100644 --- a/src/test/ui/privacy/privacy-ns1.rs +++ b/src/test/ui/privacy/privacy-ns1.rs @@ -33,7 +33,7 @@ fn test_glob2() { use foo2::*; let _x: Box<Bar>; //~ ERROR wrong number of const arguments: expected 0, found 1 - //~^ ERROR wrong number of type arguments: expected 1, found 0 + //~^ ERROR wrong number of type arguments: expected at least 1, found 0 } // neither public diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index eda9d4c128d..ccbb5d5c90f 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -58,11 +58,11 @@ error[E0107]: wrong number of const arguments: expected 0, found 1 LL | let _x: Box<Bar>; | ^^^ unexpected const argument -error[E0107]: wrong number of type arguments: expected 1, found 0 +error[E0107]: wrong number of type arguments: expected at least 1, found 0 --> $DIR/privacy-ns1.rs:35:13 | LL | let _x: Box<Bar>; - | ^^^^^^^^ expected 1 type argument + | ^^^^^^^^ expected at least 1 type argument error: aborting due to 5 previous errors diff --git a/src/test/ui/privacy/privacy-ns2.rs b/src/test/ui/privacy/privacy-ns2.rs index 0546de873f3..b770c8f8f86 100644 --- a/src/test/ui/privacy/privacy-ns2.rs +++ b/src/test/ui/privacy/privacy-ns2.rs @@ -39,7 +39,7 @@ fn test_single2() { use foo2::Bar; let _x : Box<Bar>; //~ ERROR wrong number of const arguments: expected 0, found 1 - //~^ ERROR wrong number of type arguments: expected 1, found 0 + //~^ ERROR wrong number of type arguments: expected at least 1, found 0 let _x : Bar(); //~ ERROR expected type, found function `Bar` } @@ -47,7 +47,7 @@ fn test_list2() { use foo2::{Bar,Baz}; let _x: Box<Bar>; //~ ERROR wrong number of const arguments: expected 0, found 1 - //~^ ERROR wrong number of type arguments: expected 1, found 0 + //~^ ERROR wrong number of type arguments: expected at least 1, found 0 } // neither public diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index d7d9b835275..dbb269c0ba6 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -84,11 +84,11 @@ error[E0107]: wrong number of const arguments: expected 0, found 1 LL | let _x : Box<Bar>; | ^^^ unexpected const argument -error[E0107]: wrong number of type arguments: expected 1, found 0 +error[E0107]: wrong number of type arguments: expected at least 1, found 0 --> $DIR/privacy-ns2.rs:41:14 | LL | let _x : Box<Bar>; - | ^^^^^^^^ expected 1 type argument + | ^^^^^^^^ expected at least 1 type argument error[E0107]: wrong number of const arguments: expected 0, found 1 --> $DIR/privacy-ns2.rs:49:17 @@ -96,11 +96,11 @@ error[E0107]: wrong number of const arguments: expected 0, found 1 LL | let _x: Box<Bar>; | ^^^ unexpected const argument -error[E0107]: wrong number of type arguments: expected 1, found 0 +error[E0107]: wrong number of type arguments: expected at least 1, found 0 --> $DIR/privacy-ns2.rs:49:13 | LL | let _x: Box<Bar>; - | ^^^^^^^^ expected 1 type argument + | ^^^^^^^^ expected at least 1 type argument error: aborting due to 10 previous errors diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 423350cd936..2e23ddd9053 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,27 +1,30 @@ error[E0599]: no method named `clone` found for struct `Box<dyn Foo>` in the current scope --> $DIR/unique-object-noncopyable.rs:24:16 | -LL | trait Foo { - | --------- - | | - | doesn't satisfy `dyn Foo: Clone` - | doesn't satisfy `dyn Foo: Sized` +LL | trait Foo { + | --------- + | | + | doesn't satisfy `dyn Foo: Clone` + | doesn't satisfy `dyn Foo: Sized` ... -LL | let _z = y.clone(); - | ^^^^^ method not found in `Box<dyn Foo>` +LL | let _z = y.clone(); + | ^^^^^ method not found in `Box<dyn Foo>` | - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/core/src/clone.rs:LL:COL | -LL | pub struct Box<T: ?Sized>(Unique<T>); - | ------------------------------------- doesn't satisfy `Box<dyn Foo>: Clone` +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `Arc<Box<dyn Foo>>` here + | the method is available for `Rc<Box<dyn Foo>>` here | - ::: $SRC_DIR/core/src/clone.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Box<dyn Foo>>` here - | the method is available for `Rc<Box<dyn Foo>>` here +LL | / pub struct Box< +LL | | T: ?Sized, +LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global, +LL | | >(Unique<T>, A); + | |________________- doesn't satisfy `Box<dyn Foo>: Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: `dyn Foo: Sized` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index d39db225043..d533724a009 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,24 +1,27 @@ error[E0599]: no method named `clone` found for struct `Box<R>` in the current scope --> $DIR/unique-pinned-nocopy.rs:12:16 | -LL | struct R { - | -------- doesn't satisfy `R: Clone` +LL | struct R { + | -------- doesn't satisfy `R: Clone` ... -LL | let _j = i.clone(); - | ^^^^^ method not found in `Box<R>` +LL | let _j = i.clone(); + | ^^^^^ method not found in `Box<R>` | - ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/core/src/clone.rs:LL:COL | -LL | pub struct Box<T: ?Sized>(Unique<T>); - | ------------------------------------- doesn't satisfy `Box<R>: Clone` +LL | fn clone(&self) -> Self; + | ----- + | | + | the method is available for `Arc<Box<R>>` here + | the method is available for `Rc<Box<R>>` here | - ::: $SRC_DIR/core/src/clone.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL | -LL | fn clone(&self) -> Self; - | ----- - | | - | the method is available for `Arc<Box<R>>` here - | the method is available for `Rc<Box<R>>` here +LL | / pub struct Box< +LL | | T: ?Sized, +LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: AllocRef = Global, +LL | | >(Unique<T>, A); + | |________________- doesn't satisfy `Box<R>: Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: `R: Clone` |
