From 4e69e86ddf6a34eb332d90a166bd9cfbe59604e3 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 13 Feb 2019 17:38:37 +0900 Subject: [PATCH] Associate an allocator to boxes This turns `Box` into `Box`, with a `A: Alloc` bound for impls. Ideally, inherent methods like `Box::new` would be applied to `Box`, but as of now, that would be backwards incompatible because it would require type annotations in places where they currently aren't required. `impl FromIterator` is not covered because it relies on `Vec`, which would need allocator awareness. `DispatchFromDyn` is left out or being generic over `A` because there is no bound that would make it work currently. `FnBox` is left out because it's related to `DispatchFromDyn`. --- src/liballoc/alloc.rs | 51 +++- src/liballoc/boxed.rs | 283 ++++++++++++++------- src/liballoc/lib.rs | 1 + src/liballoc/raw_vec.rs | 12 +- src/liballoc/rc.rs | 4 +- src/liballoc/str.rs | 5 +- src/liballoc/sync.rs | 4 +- src/test/ui/e0119/conflict-with-std.stderr | 2 +- src/test/ui/issues/issue-14092.rs | 2 +- src/test/ui/issues/issue-14092.stderr | 4 +- src/test/ui/issues/issue-41974.stderr | 6 +- 11 files changed, 252 insertions(+), 122 deletions(-) diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index ddc6481eec78e..83c5e8959b3ca 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -3,6 +3,8 @@ #![stable(feature = "alloc_module", since = "1.28.0")] use core::intrinsics::{min_align_of_val, size_of_val}; +#[cfg(stage0)] +use core::marker::PhantomData; use core::ptr::{NonNull, Unique}; use core::usize; @@ -10,6 +12,26 @@ use core::usize; #[doc(inline)] pub use core::alloc::*; +#[cfg(stage0)] +#[unstable(feature = "allocator_api", issue = "32838")] +// pub to make the compiler happy wrt the trait being made public by the impls in e.g. boxed.rs. +pub trait Stage0Alloc = Alloc + Default; + +#[cfg(not(stage0))] +pub(crate) use Alloc as Stage0Alloc; + +#[cfg(stage0)] +pub(crate) fn stage0_phantom(_a: A) -> PhantomData { PhantomData } + +#[cfg(not(stage0))] +pub(crate) fn stage0_phantom(a: A) -> A { a } + +#[cfg(stage0)] +pub(crate) fn stage0_unphantom(_a: PhantomData) -> A { A::default() } + +#[cfg(not(stage0))] +pub(crate) fn stage0_unphantom(a: A) -> A { a } + extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them from the `#[global_allocator]` attribute if there is one, or uses the @@ -37,10 +59,14 @@ extern "Rust" { /// /// Note: while this type is unstable, the functionality it provides can be /// accessed through the [free functions in `alloc`](index.html#functions). +#[cfg(not(test))] #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] 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 @@ -144,6 +170,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { __rust_alloc_zeroed(layout.size(), layout.align()) } +#[cfg(not(test))] #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl Alloc for Global { #[inline] @@ -182,25 +209,27 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { align as *mut u8 } else { let layout = Layout::from_size_align_unchecked(size, align); - let ptr = alloc(layout); - if !ptr.is_null() { - ptr - } else { - handle_alloc_error(layout) + match Global.alloc(layout) { + Ok(ptr) => ptr.as_ptr(), + Err(_) => handle_alloc_error(layout), } } } +#[cfg(stage0)] +type BoxFreeAlloc = PhantomData; +#[cfg(not(stage0))] +type BoxFreeAlloc = A; + #[cfg_attr(not(test), lang = "box_free")] #[inline] -pub(crate) unsafe fn box_free(ptr: Unique) { - let ptr = ptr.as_ptr(); - let size = size_of_val(&*ptr); - let align = min_align_of_val(&*ptr); - // We do not allocate for Box when T is ZST, so deallocation is also not necessary. +pub(crate) unsafe fn box_free(ptr: Unique, a: BoxFreeAlloc) { + let size = size_of_val(&*ptr.as_ptr()); + let align = min_align_of_val(&*ptr.as_ptr()); + // We do not allocate for Box when T is ZST, so deallocation is also not necessary. if size != 0 { let layout = Layout::from_size_align_unchecked(size, align); - dealloc(ptr as *mut u8, layout); + stage0_unphantom(a).dealloc(NonNull::from(ptr).cast(), layout); } } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 207359ed6968f..b891cf1de9809 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -76,6 +76,8 @@ use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; use core::iter::{Iterator, FromIterator, FusedIterator}; +#[cfg(stage0)] +use core::marker::PhantomData; use core::marker::{Unpin, Unsize}; use core::mem; use core::pin::Pin; @@ -85,6 +87,9 @@ use core::ops::{ use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; +use crate::alloc::{ + Stage0Alloc as Alloc, Global, Layout, handle_alloc_error, stage0_phantom, stage0_unphantom +}; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -92,10 +97,20 @@ use crate::str::from_boxed_utf8_unchecked; /// A pointer type for heap allocation. /// /// See the [module-level documentation](../../std/boxed/index.html) for more. +#[cfg(not(stage0))] +#[lang = "owned_box"] +#[fundamental] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Box(Unique, pub(crate) A); + +// Use a variant with PhantomData in stage0, to satisfy the limitations of +// DispatchFromDyn in 1.35. +#[allow(missing_docs)] +#[cfg(stage0)] #[lang = "owned_box"] #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Box(Unique); +pub struct Box(Unique, pub(crate) PhantomData); impl Box { /// Allocates memory on the heap and then places `x` into it. @@ -122,6 +137,49 @@ impl Box { } } +impl Box { + /// Allocates memory in the given allocator and then places `x` into it. + /// + /// This doesn't actually allocate if `T` is zero-sized. + /// + /// # Examples + /// + /// ``` + /// # #![feature(allocator_api)] + /// use std::alloc::Global; + /// let five = Box::new_in(5, Global); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline(always)] + pub fn new_in(x: T, a: A) -> Box { + let mut a = a; + let layout = Layout::for_value(&x); + let size = layout.size(); + let ptr = if size == 0 { + Unique::empty() + } else { + unsafe { + let ptr = a.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + ptr.cast().into() + } + }; + // Move x into the location allocated above. This needs to happen + // for any size so that x is not dropped in some cases. + unsafe { + ptr::write(ptr.as_ptr() as *mut T, x); + } + Box(ptr, stage0_phantom(a)) + } + + /// Constructs a new `Pin>`. 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, a: A) -> Pin> { + Box::new_in(x, a).into() + } +} + impl Box { /// Constructs a box from a raw pointer. /// @@ -148,9 +206,48 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - Box(Unique::new_unchecked(raw)) + Box(Unique::new_unchecked(raw), stage0_phantom(Global)) + } +} + +impl Box { + /// Constructs a box from a raw pointer in the given allocator. + /// + /// This is similar to the [`Box::from_raw`] function, but assumes + /// the pointer was allocated with the given allocator. + /// + /// This function is unsafe because improper use may lead to + /// memory problems. For example, specifying the wrong allocator + /// may corrupt the allocator state. + /// + /// [`Box::from_raw`]: struct.Box.html#method.from_raw + /// + /// # Examples + /// + /// ``` + /// # #![feature(allocator_api)] + /// use std::alloc::Global; + /// let x = Box::new_in(5, Global); + /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw_in(ptr, Global) }; + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn from_raw_in(raw: *mut T, a: A) -> Self { + Box(Unique::new_unchecked(raw), stage0_phantom(a)) } + /// Maps a `Box` to `Box` by applying a function to the + /// raw pointer. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn map_raw *mut U>(b: Box, f: F) -> Box { + let a = ptr::read(&b.1); + Box::from_raw_in(f(Box::into_raw(b)), stage0_unphantom(a)) + } +} + +impl Box { /// Consumes the `Box`, returning a wrapped raw pointer. /// /// The pointer will be properly aligned and non-null. @@ -175,7 +272,7 @@ impl Box { /// ``` #[stable(feature = "box_raw", since = "1.4.0")] #[inline] - pub fn into_raw(b: Box) -> *mut T { + pub fn into_raw(b: Box) -> *mut T { Box::into_raw_non_null(b).as_ptr() } @@ -207,14 +304,14 @@ impl Box { /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] #[inline] - pub fn into_raw_non_null(b: Box) -> NonNull { + pub fn into_raw_non_null(b: Box) -> NonNull { Box::into_unique(b).into() } #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")] #[inline] #[doc(hidden)] - pub fn into_unique(mut b: Box) -> Unique { + pub fn into_unique(mut b: Box) -> Unique { // Box is kind-of a library type, but recognized as a "unique pointer" by // Stacked Borrows. This function here corresponds to "reborrowing to // a raw pointer", but there is no actual reborrow here -- so @@ -268,7 +365,7 @@ impl Box { /// ``` #[stable(feature = "box_leak", since = "1.26.0")] #[inline] - pub fn leak<'a>(b: Box) -> &'a mut T + pub fn leak<'a>(b: Box) -> &'a mut T where T: 'a // Technically not needed, but kept to be explicit. { @@ -281,7 +378,7 @@ impl Box { /// /// This is also available via [`From`]. #[unstable(feature = "box_into_pin", issue = "0")] - pub fn into_pin(boxed: Box) -> Pin> { + pub fn into_pin(boxed: Box) -> Pin> { // It's not possible to move or replace the insides of a `Pin>` // when `T: !Unpin`, so it's safe to pin it directly without any // additional requirements. @@ -290,36 +387,36 @@ impl Box { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized> Drop for Box { +unsafe impl<#[may_dangle] T: ?Sized, A> Drop for Box { fn drop(&mut self) { // FIXME: Do nothing, drop is currently performed by compiler. } } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for Box { - /// Creates a `Box`, with the `Default` value for T. - fn default() -> Box { - box Default::default() +impl Default for Box { + /// Creates a `Box`, with the `Default` value for T. + fn default() -> Box { + Box::new_in(Default::default(), A::default()) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for Box<[T]> { - fn default() -> Box<[T]> { - Box::<[T; 0]>::new([]) +impl Default for Box<[T], A> { + fn default() -> Box<[T], A> { + Box::<[T; 0], A>::new_in([], A::default()) } } #[stable(feature = "default_box_extra", since = "1.17.0")] -impl Default for Box { - fn default() -> Box { +impl Default for Box { + fn default() -> Box { unsafe { from_boxed_utf8_unchecked(Default::default()) } } } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Box { +impl Clone for Box { /// Returns a new box with a `clone()` of this box's contents. /// /// # Examples @@ -330,8 +427,8 @@ impl Clone for Box { /// ``` #[rustfmt::skip] #[inline] - fn clone(&self) -> Box { - box { (**self).clone() } + fn clone(&self) -> Box { + Box::new_in((**self).clone(), stage0_unphantom(self.1.clone())) } /// Copies `source`'s contents into `self` without creating a new allocation. /// @@ -346,17 +443,17 @@ impl Clone for Box { /// assert_eq!(*y, 5); /// ``` #[inline] - fn clone_from(&mut self, source: &Box) { + fn clone_from(&mut self, source: &Box) { (**self).clone_from(&(**source)); } } #[stable(feature = "box_slice_clone", since = "1.3.0")] -impl Clone for Box { +impl Clone for Box { fn clone(&self) -> Self { let len = self.len(); - let buf = RawVec::with_capacity(len); + let buf = RawVec::with_capacity_in(len, stage0_unphantom(self.1.clone())); unsafe { ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); from_boxed_utf8_unchecked(buf.into_box()) @@ -365,58 +462,58 @@ impl Clone for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for Box { +impl PartialEq for Box { #[inline] - fn eq(&self, other: &Box) -> bool { + fn eq(&self, other: &Box) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &Box) -> bool { + fn ne(&self, other: &Box) -> bool { PartialEq::ne(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Box { +impl PartialOrd for Box { #[inline] - fn partial_cmp(&self, other: &Box) -> Option { + fn partial_cmp(&self, other: &Box) -> Option { PartialOrd::partial_cmp(&**self, &**other) } #[inline] - fn lt(&self, other: &Box) -> bool { + fn lt(&self, other: &Box) -> bool { PartialOrd::lt(&**self, &**other) } #[inline] - fn le(&self, other: &Box) -> bool { + fn le(&self, other: &Box) -> bool { PartialOrd::le(&**self, &**other) } #[inline] - fn ge(&self, other: &Box) -> bool { + fn ge(&self, other: &Box) -> bool { PartialOrd::ge(&**self, &**other) } #[inline] - fn gt(&self, other: &Box) -> bool { + fn gt(&self, other: &Box) -> bool { PartialOrd::gt(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Box { +impl Ord for Box { #[inline] - fn cmp(&self, other: &Box) -> Ordering { + fn cmp(&self, other: &Box) -> Ordering { Ord::cmp(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Box {} +impl Eq for Box {} #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for Box { +impl Hash for Box { fn hash(&self, state: &mut H) { (**self).hash(state); } } #[stable(feature = "indirect_hasher_impl", since = "1.22.0")] -impl Hasher for Box { +impl Hasher for Box { fn finish(&self) -> u64 { (**self).finish() } @@ -462,7 +559,7 @@ impl Hasher for Box { } #[stable(feature = "from_for_ptrs", since = "1.6.0")] -impl From for Box { +impl From for Box { /// Converts a generic type `T` into a `Box` /// /// The conversion allocates on the heap and moves `t` @@ -476,22 +573,22 @@ impl From for Box { /// assert_eq!(Box::from(x), boxed); /// ``` fn from(t: T) -> Self { - Box::new(t) + Box::new_in(t, A::default()) } } #[stable(feature = "pin", since = "1.33.0")] -impl From> for Pin> { +impl From> for Pin> { /// Converts a `Box` into a `Pin>` /// /// This conversion does not allocate on the heap and happens in place. - fn from(boxed: Box) -> Self { + fn from(boxed: Box) -> Self { Box::into_pin(boxed) } } #[stable(feature = "box_from_slice", since = "1.17.0")] -impl From<&[T]> for Box<[T]> { +impl From<&[T]> for Box<[T], A> { /// Converts a `&[T]` into a `Box<[T]>` /// /// This conversion allocates on the heap @@ -505,15 +602,16 @@ impl From<&[T]> for Box<[T]> { /// /// println!("{:?}", boxed_slice); /// ``` - fn from(slice: &[T]) -> Box<[T]> { - let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; + fn from(slice: &[T]) -> Box<[T], A> { + let a = A::default(); + let mut boxed = unsafe { RawVec::with_capacity_in(slice.len(), a).into_box() }; boxed.copy_from_slice(slice); boxed } } #[stable(feature = "box_from_slice", since = "1.17.0")] -impl From<&str> for Box { +impl From<&str> for Box { /// Converts a `&str` into a `Box` /// /// This conversion allocates on the heap @@ -525,13 +623,13 @@ impl From<&str> for Box { /// println!("{}", boxed); /// ``` #[inline] - fn from(s: &str) -> Box { + fn from(s: &str) -> Box { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } } } #[stable(feature = "boxed_str_conv", since = "1.19.0")] -impl From> for Box<[u8]> { +impl From> for Box<[u8], A> { /// Converts a `Box>` into a `Box<[u8]>` /// /// This conversion does not allocate on the heap and happens in place. @@ -549,12 +647,12 @@ impl From> for Box<[u8]> { /// assert_eq!(boxed_slice, boxed_str); /// ``` #[inline] - fn from(s: Box) -> Self { - unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) } + fn from(s: Box) -> Self { + unsafe { Box::map_raw(s, |p| p as *mut [u8]) } } } -impl Box { +impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. @@ -576,19 +674,16 @@ impl Box { /// print_if_string(Box::new(0i8)); /// } /// ``` - pub fn downcast(self) -> Result, Box> { + pub fn downcast(self) -> Result, Box> { if self.is::() { - unsafe { - let raw: *mut dyn Any = Box::into_raw(self); - Ok(Box::from_raw(raw as *mut T)) - } + unsafe { Ok(Box::map_raw(self, |p| p as *mut T)) } } else { Err(self) } } } -impl Box { +impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. @@ -610,30 +705,30 @@ impl Box { /// print_if_string(Box::new(0i8)); /// } /// ``` - pub fn downcast(self) -> Result, Box> { - >::downcast(self).map_err(|s| unsafe { + pub fn downcast(self) -> Result, Box> { + >::downcast(self).map_err(|s| unsafe { // reapply the Send marker - Box::from_raw(Box::into_raw(s) as *mut (dyn Any + Send)) + Box::map_raw(s, |p| p as *mut (dyn Any + Send)) }) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for Box { +impl fmt::Display for Box { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Box { +impl fmt::Debug for Box { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Pointer for Box { +impl fmt::Pointer for Box { 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 @@ -643,7 +738,7 @@ impl fmt::Pointer for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for Box { +impl Deref for Box { type Target = T; fn deref(&self) -> &T { @@ -652,17 +747,17 @@ impl Deref for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl DerefMut for Box { +impl DerefMut for Box { fn deref_mut(&mut self) -> &mut T { &mut **self } } #[unstable(feature = "receiver_trait", issue = "0")] -impl Receiver for Box {} +impl Receiver for Box {} #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Box { +impl Iterator for Box { type Item = I::Item; fn next(&mut self) -> Option { (**self).next() @@ -675,7 +770,7 @@ impl Iterator for Box { } } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Box { +impl DoubleEndedIterator for Box { fn next_back(&mut self) -> Option { (**self).next_back() } @@ -684,7 +779,7 @@ impl DoubleEndedIterator for Box { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Box { +impl ExactSizeIterator for Box { fn len(&self) -> usize { (**self).len() } @@ -694,10 +789,10 @@ impl ExactSizeIterator for Box { } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Box {} +impl FusedIterator for Box {} #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized> FnOnce for Box { +impl + ?Sized, Alloc> FnOnce for Box { type Output = >::Output; extern "rust-call" fn call_once(self, args: A) -> Self::Output { @@ -706,14 +801,14 @@ impl + ?Sized> FnOnce for Box { } #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized> FnMut for Box { +impl + ?Sized, Alloc> FnMut for Box { extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { >::call_mut(self, args) } } #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized> Fn for Box { +impl + ?Sized, Alloc> Fn for Box { extern "rust-call" fn call(&self, args: A) -> Self::Output { >::call(self, args) } @@ -759,24 +854,26 @@ impl + ?Sized> Fn for Box { #[rustc_paren_sugar] #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -pub trait FnBox: FnOnce { +pub trait FnBox: FnOnce { /// Performs the call operation. - fn call_box(self: Box, args: A) -> Self::Output; + fn call_box(self: Box, args: Args) -> Self::Output; } +//FIXME: Make generic over A along with DispatchFromDyn. #[unstable(feature = "fnbox", reason = "will be deprecated if and when `Box` becomes usable", issue = "28796")] -impl FnBox for F - where F: FnOnce +impl FnBox for F + where F: FnOnce { - fn call_box(self: Box, args: A) -> F::Output { + fn call_box(self: Box, args: Args) -> F::Output { self.call_once(args) } } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Box {} +impl, U: ?Sized, A> CoerceUnsized> for Box {} +//FIXME: Make generic over A when the compiler supports it. #[unstable(feature = "dispatch_from_dyn", issue = "0")] impl, U: ?Sized> DispatchFromDyn> for Box {} @@ -788,10 +885,10 @@ impl FromIterator for Box<[A]> { } #[stable(feature = "box_slice_clone", since = "1.3.0")] -impl Clone for Box<[T]> { +impl Clone for Box<[T], A> { fn clone(&self) -> Self { let mut new = BoxBuilder { - data: RawVec::with_capacity(self.len()), + data: RawVec::with_capacity_in(self.len(), stage0_unphantom(self.1.clone())), len: 0, }; @@ -809,20 +906,20 @@ impl Clone for Box<[T]> { return unsafe { new.into_box() }; // Helper type for responding to panics correctly. - struct BoxBuilder { - data: RawVec, + struct BoxBuilder { + data: RawVec, len: usize, } - impl BoxBuilder { - unsafe fn into_box(self) -> Box<[T]> { + impl BoxBuilder { + unsafe fn into_box(self) -> Box<[T], A> { let raw = ptr::read(&self.data); mem::forget(self); raw.into_box() } } - impl Drop for BoxBuilder { + impl Drop for BoxBuilder { fn drop(&mut self) { let mut data = self.data.ptr(); let max = unsafe { data.add(self.len) }; @@ -839,28 +936,28 @@ impl Clone for Box<[T]> { } #[stable(feature = "box_borrow", since = "1.1.0")] -impl borrow::Borrow for Box { +impl borrow::Borrow for Box { fn borrow(&self) -> &T { &**self } } #[stable(feature = "box_borrow", since = "1.1.0")] -impl borrow::BorrowMut for Box { +impl borrow::BorrowMut for Box { fn borrow_mut(&mut self) -> &mut T { &mut **self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl AsRef for Box { +impl AsRef for Box { fn as_ref(&self) -> &T { &**self } } #[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] -impl AsMut for Box { +impl AsMut for Box { fn as_mut(&mut self) -> &mut T { &mut **self } @@ -889,10 +986,10 @@ impl AsMut for Box { * could have a method to project a Pin from it. */ #[stable(feature = "pin", since = "1.33.0")] -impl Unpin for Box { } +impl Unpin for Box { } #[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Box { +impl Generator for Box { type Yield = G::Yield; type Return = G::Return; @@ -902,7 +999,7 @@ impl Generator for Box { } #[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Pin> { +impl Generator for Pin> { type Yield = G::Yield; type Return = G::Return; @@ -912,7 +1009,7 @@ impl Generator for Pin> { } #[stable(feature = "futures_api", since = "1.36.0")] -impl Future for Box { +impl Future for Box { type Output = F::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index eb673488170b6..5aed6ae4844ed 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -67,6 +67,7 @@ #![allow(explicit_outlives_requirements)] #![cfg_attr(not(test), feature(generator_trait))] +#![cfg_attr(stage0, feature(trait_alias))] #![cfg_attr(test, feature(test))] #![feature(allocator_api)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index d1fc5ac3b30d4..96832143da19a 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -7,7 +7,7 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{Alloc, Layout, Global, handle_alloc_error}; +use crate::alloc::{Stage0Alloc as Alloc, Layout, Global, handle_alloc_error}; use crate::collections::CollectionAllocErr::{self, *}; use crate::boxed::Box; @@ -682,8 +682,8 @@ impl RawVec { } -impl RawVec { - /// Converts the entire buffer into `Box<[T]>`. +impl RawVec { + /// Converts the entire buffer into `Box<[T], A>`. /// /// While it is not *strictly* Undefined Behavior to call /// this procedure while some of the RawVec is uninitialized, @@ -691,10 +691,11 @@ impl RawVec { /// /// Note that this will correctly reconstitute any `cap` changes /// that may have been performed. (see description of type for details) - pub unsafe fn into_box(self) -> Box<[T]> { + pub unsafe fn into_box(self) -> Box<[T], A> { // NOTE: not calling `cap()` here, actually using the real `cap` field! let slice = slice::from_raw_parts_mut(self.ptr(), self.cap); - let output: Box<[T]> = Box::from_raw(slice); + let a = ptr::read(&self.a); + let output: Box<[T], A> = Box::from_raw_in(slice, a); mem::forget(self); output } @@ -750,6 +751,7 @@ fn capacity_overflow() -> ! { mod tests { use super::*; + #[cfg(not(stage0))] #[test] fn allocator_param() { use crate::alloc::AllocErr; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 68eecd97ea11a..05651e82fd4f0 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -247,7 +247,7 @@ use core::slice::from_raw_parts_mut; use core::convert::From; use core::usize; -use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; +use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error, stage0_phantom}; use crate::string::String; use crate::vec::Vec; @@ -713,7 +713,7 @@ impl Rc { value_size); // Free the allocation without dropping its contents - box_free(box_unique); + box_free::<_, Global>(box_unique, stage0_phantom(Global)); Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index f66ff894ae865..e7353edd1f9f5 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -35,6 +35,7 @@ use core::ptr; use core::iter::FusedIterator; use core::unicode::conversions; +use crate::alloc::{Stage0Alloc as Alloc, stage0_unphantom}; use crate::borrow::ToOwned; use crate::boxed::Box; use crate::slice::{SliceConcatExt, SliceIndex}; @@ -578,6 +579,6 @@ impl str { /// ``` #[stable(feature = "str_box_extras", since = "1.20.0")] #[inline] -pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { - Box::from_raw(Box::into_raw(v) as *mut str) +pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8], A>) -> Box { + Box::map_raw(v, |p| p as *mut str) } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 466e806663c7f..2b9669521d5b2 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -23,7 +23,7 @@ use core::{isize, usize}; use core::convert::From; use core::slice::from_raw_parts_mut; -use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; +use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error, stage0_phantom}; use crate::boxed::Box; use crate::rc::is_dangling; use crate::string::String; @@ -619,7 +619,7 @@ impl Arc { value_size); // Free the allocation without dropping its contents - box_free(box_unique); + box_free::<_, Global>(box_unique, stage0_phantom(Global)); Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } } diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr index 3e0c71e907481..7f8c4e6b32ac2 100644 --- a/src/test/ui/e0119/conflict-with-std.stderr +++ b/src/test/ui/e0119/conflict-with-std.stderr @@ -5,7 +5,7 @@ LL | impl AsRef for Box { | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `alloc`: - - impl std::convert::AsRef for std::boxed::Box + - impl std::convert::AsRef for std::boxed::Box where T: ?Sized; error[E0119]: conflicting implementations of trait `std::convert::From` for type `S`: diff --git a/src/test/ui/issues/issue-14092.rs b/src/test/ui/issues/issue-14092.rs index 77da6badde948..3cfaa20a8b5ab 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 626830ece8c11..b749c44780d96 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-41974.stderr b/src/test/ui/issues/issue-41974.stderr index 20121878a0754..3ca9ed724b56b 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 Drop for T where T: A { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `alloc`: - - impl std::ops::Drop for std::boxed::Box + - impl std::ops::Drop for std::boxed::Box where T: ?Sized; - = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `A` for type `std::boxed::Box<_, _>` error[E0120]: the Drop trait may only be implemented on structures --> $DIR/issue-41974.rs:7:18