diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index d31c73cc1bd8d..b1134b556ba2d 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/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::{NonNull, Unique}; +#[cfg(not(test))] +use core::intrinsics; +#[cfg(not(test))] +use core::ptr::NonNull; + +use core::intrinsics::{min_align_of_val, size_of_val}; +use core::ptr::Unique; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] @@ -40,8 +45,12 @@ extern "Rust" { /// [`AllocRef`]: trait.AllocRef.html #[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 @@ -162,6 +171,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { } #[unstable(feature = "allocator_api", issue = "32838")] +#[cfg(not(test))] unsafe impl AllocRef for Global { #[inline] fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result { @@ -278,11 +288,11 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { // well. // For example if `Box` is changed to `struct Box(Unique, A)`, // this function has to be changed to `fn box_free(Unique, A)` as well. -pub(crate) unsafe fn box_free(ptr: Unique) { +pub(crate) unsafe fn box_free(ptr: Unique, mut alloc: A) { 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) } /// Abort on memory allocation error or failure. diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b3a771a721d22..3e6005cddee52 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -148,6 +148,7 @@ use core::task::{Context, Poll}; use crate::alloc::{self, AllocInit, AllocRef, Global}; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; +use crate::string::String; use crate::vec::Vec; /// A pointer type for heap allocation. @@ -156,9 +157,9 @@ use crate::vec::Vec; #[lang = "owned_box"] #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Box(Unique); +pub struct Box(Unique, A); -impl Box { +impl Box { /// Allocates memory on the heap and then places `x` into it. /// /// This doesn't actually allocate if `T` is zero-sized. @@ -170,7 +171,7 @@ impl Box { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - pub fn new(x: T) -> Box { + pub fn new(x: T) -> Self { box x } @@ -192,15 +193,105 @@ impl Box { /// /// assert_eq!(*five, 5) /// ``` + #[inline] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { + Self::new_uninit_in(Global) + } + + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let zero = Box::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[inline] + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Box> { + Self::new_zeroed_in(Global) + } + + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[inline(always)] + #[stable(feature = "pin", since = "1.33.0")] + pub fn pin(x: T) -> Pin { + (box x).into() + } +} + +impl Box { + /// Allocates memory with the provided allocator and 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, mut alloc: A) -> Self { + let layout = alloc::Layout::new::(); + let ptr = alloc + .alloc(layout, AllocInit::Uninitialized) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + .ptr + .cast(); + let ptr: *mut T = ptr.as_ptr(); + unsafe { + ptr.write(x); + Box::from_raw_in(ptr, alloc) + } + } + + /// Constructs a new box with uninitialized contents in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// #![feature(new_uninit)] + /// + /// use std::alloc::System; + /// + /// let mut five = Box::::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")] + pub fn new_uninit_in(mut alloc: A) -> Box, A> { let layout = alloc::Layout::new::>(); - let ptr = Global + let ptr = alloc .alloc(layout, AllocInit::Uninitialized) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) .ptr .cast(); - unsafe { Box::from_raw(ptr.as_ptr()) } + unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } } /// Constructs a new `Box` with uninitialized contents, with the memory @@ -212,32 +303,27 @@ impl Box { /// # Examples /// /// ``` + /// #![feature(allocator_api)] /// #![feature(new_uninit)] /// - /// let zero = Box::::new_zeroed(); + /// use std::alloc::System; + /// + /// let zero = Box::::new_zeroed_in(System); /// let zero = unsafe { zero.assume_init() }; /// /// assert_eq!(*zero, 0) /// ``` /// /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed - #[unstable(feature = "new_uninit", issue = "63291")] - pub fn new_zeroed() -> Box> { + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_zeroed_in(mut alloc: A) -> Box, A> { let layout = alloc::Layout::new::>(); - let ptr = Global + let ptr = alloc .alloc(layout, AllocInit::Zeroed) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) .ptr .cast(); - unsafe { Box::from_raw(ptr.as_ptr()) } - } - - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then - /// `x` will be pinned in memory and unable to be moved. - #[stable(feature = "pin", since = "1.33.0")] - #[inline(always)] - pub fn pin(x: T) -> Pin> { - (box x).into() + unsafe { Box::from_raw_in(ptr.as_ptr(), alloc) } } /// Converts a `Box` into a `Box<[T]>` @@ -245,9 +331,10 @@ impl Box { /// 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) -> Box<[T]> { + pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + let (raw, alloc) = Box::into_raw_with_alloc(boxed); // *mut T and *mut [T; 1] have the same size and alignment - unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1] as *mut [T]) } + unsafe { Box::from_raw_in(raw as *mut [T; 1] as *mut [T], alloc) } } } @@ -272,13 +359,24 @@ impl Box<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` + #[inline] #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - unsafe { RawVec::with_capacity(len).into_box(len) } + Self::new_uninit_slice_in(len, Global) } } -impl Box> { +impl Box<[T], A> { + /// Behaves like [`new_uninit_slice`] but generic over the allocator. + /// + /// [`new_uninit_slice`]: #method.new_uninit_slice + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } + } +} + +impl Box, A> { /// Converts to `Box`. /// /// # Safety @@ -309,12 +407,13 @@ impl Box> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Box { - Box::from_raw(Box::into_raw(self) as *mut T) + pub unsafe fn assume_init(self) -> Box { + let (raw, alloc) = Box::into_raw_with_alloc(self); + Box::from_raw_in(raw as *mut T, alloc) } } -impl Box<[mem::MaybeUninit]> { +impl Box<[mem::MaybeUninit], A> { /// Converts to `Box<[T]>`. /// /// # Safety @@ -347,8 +446,9 @@ impl Box<[mem::MaybeUninit]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] #[inline] - pub unsafe fn assume_init(self) -> Box<[T]> { - 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); + Box::from_raw_in(raw as *mut [T], alloc) } } @@ -392,7 +492,58 @@ 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), Global) + } +} + +impl Box { + /// Constructs a box from a raw pointer allocated by the provided 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 global allocator: + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::{Layout, AllocRef, AllocInit, System}; + /// + /// unsafe { + /// let ptr = System.alloc(Layout::new::(), AllocInit::Uninitialized)?.ptr.as_ptr(); + /// *ptr = 5; + /// let x = Box::from_raw_in(ptr, System); + /// } + /// # Ok::<_, std::alloc::AllocErr>(()) + /// ``` + /// + /// [memory layout]: index.html#memory-layout + /// [`Layout`]: ../alloc/struct.Layout.html + /// [`Box::into_raw`]: struct.Box.html#method.into_raw + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + Box(Unique::new_unchecked(raw), alloc) } /// Consumes the `Box`, returning a wrapped raw pointer. @@ -437,13 +588,18 @@ impl Box { /// [`Box::from_raw`]: struct.Box.html#method.from_raw #[stable(feature = "box_raw", since = "1.4.0")] #[inline] - pub fn into_raw(b: Box) -> *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 + } + + /// Behaves like [`into_raw`] but also returns the allocator + /// + /// [`into_raw`]: #method.into_raw + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn into_raw_with_alloc(b: Self) -> (*mut T, A) { + let (leaked, alloc) = Box::into_unique_with_alloc(b); + (leaked.as_ptr(), alloc) } /// Consumes the `Box`, returning the wrapped pointer as `NonNull`. @@ -481,13 +637,8 @@ impl Box { reason = "use `Box::leak(b).into()` or `NonNull::from(Box::leak(b))` instead" )] #[inline] - pub fn into_raw_non_null(b: Box) -> NonNull { - // 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() + pub fn into_raw_non_null(b: Self) -> NonNull { + Self::into_unique_with_alloc(b).0.into() } #[unstable( @@ -497,13 +648,25 @@ impl Box { )] #[inline] #[doc(hidden)] - pub fn into_unique(b: Box) -> Unique { + pub fn into_unique(b: Self) -> Unique { + Self::into_unique_with_alloc(b).0 + } + + #[unstable( + feature = "ptr_internals", + issue = "none", + reason = "use `Box::leak(b).into()` or `Unique::from(Box::leak(b))` instead" + )] + #[inline] + #[doc(hidden)] + pub fn into_unique_with_alloc(b: Self) -> (Unique, 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() + let (leaked, alloc) = Box::leak_with_alloc(b); + (leaked.into(), alloc) } /// Consumes and leaks the `Box`, returning a mutable reference, @@ -545,20 +708,51 @@ 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: Self) -> &'a mut T where T: 'a, // Technically not needed, but kept to be explicit. { unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() } } + /// Behaves like [`leak`] but also returns the allocator + /// + /// [`leak`]: #method.leak + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn leak_with_alloc<'a>(b: Self) -> (&'a mut T, A) + where + T: 'a, // Technically not needed, but kept to be explicit. + { + let mut manually_drop = mem::ManuallyDrop::new(b); + let alloc = unsafe { ptr::read(&manually_drop.1) }; + let reference = unsafe { &mut *manually_drop.0.as_ptr() }; + (reference, alloc) + } + + /// Returns a shared reference to the allocator backing this `Box`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc(&self) -> &A { + &self.1 + } + + /// Returns a mutable reference to the allocator backing this `Box`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc_mut(&mut self) -> &mut A { + &mut self.1 + } +} + +impl Box { /// Converts a `Box` into a `Pin>` /// /// This conversion does not allocate on the heap and happens in place. /// /// This is also available via [`From`]. #[unstable(feature = "box_into_pin", issue = "62370")] - pub fn into_pin(boxed: Box) -> Pin> { + pub fn into_pin(boxed: Self) -> 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. @@ -567,7 +761,7 @@ 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: AllocRef> Drop for Box { fn drop(&mut self) { // FIXME: Do nothing, drop is currently performed by compiler. } @@ -576,27 +770,27 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Box { #[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() + fn default() -> Self { + box T::default() } } #[stable(feature = "rust1", since = "1.0.0")] impl 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 { - fn default() -> Box { - unsafe { from_boxed_utf8_unchecked(Default::default()) } + fn default() -> Self { + unsafe { from_boxed_utf8_unchecked(Box::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 @@ -611,10 +805,9 @@ impl Clone for Box { /// // But they are unique objects /// assert_ne!(&*x as *const i32, &*y as *const i32); /// ``` - #[rustfmt::skip] #[inline] - fn clone(&self) -> Box { - box { (**self).clone() } + fn clone(&self) -> Self { + Self::new_in((**self).clone(), self.alloc().clone()) } /// Copies `source`'s contents into `self` without creating a new allocation. @@ -635,73 +828,77 @@ impl Clone for Box { /// assert_eq!(yp, &*y); /// ``` #[inline] - fn clone_from(&mut self, source: &Box) { + fn clone_from(&mut self, source: &Self) { (**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 { - // this makes a copy of the data - let buf: Box<[u8]> = self.as_bytes().into(); - unsafe { from_boxed_utf8_unchecked(buf) } + let slice = self.as_bytes(); + let len = slice.len(); + let buf = RawVec::with_capacity_in(len, self.alloc().clone()); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + from_boxed_utf8_unchecked(buf.into_box(slice.len()).assume_init()) + } } } #[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: &Self) -> 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() } @@ -766,11 +963,11 @@ impl From for Box { } #[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) } } @@ -790,9 +987,9 @@ impl From<&[T]> for Box<[T]> { /// /// println!("{:?}", boxed_slice); /// ``` - fn from(slice: &[T]) -> Box<[T]> { + fn from(slice: &[T]) -> Self { let len = slice.len(); - let buf = RawVec::with_capacity(len); + let buf = RawVec::with_capacity_in(len, Global); unsafe { ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); buf.into_box(slice.len()).assume_init() @@ -813,13 +1010,33 @@ impl From<&str> for Box { /// println!("{}", boxed); /// ``` #[inline] - fn from(s: &str) -> Box { + fn from(s: &str) -> Self { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } } } +#[stable(feature = "box_from_str", since = "1.20.0")] +impl From> for Box { + /// Converts the given `String` to a boxed `str` slice that is owned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let s1: String = String::from("hello world"); + /// let s2: Box = Box::from(s1); + /// let s3: String = String::from(s2); + /// + /// assert_eq!("hello world", s3) + /// ``` + fn from(s: String) -> Self { + s.into_boxed_str() + } +} + #[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. @@ -837,8 +1054,9 @@ 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 { + let (raw, alloc) = Box::into_raw_with_alloc(s); + unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } } } @@ -858,7 +1076,7 @@ where } } -impl Box { +impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. @@ -878,11 +1096,11 @@ impl Box { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` - pub fn downcast(self) -> Result, Box> { + pub fn downcast(self) -> Result, Self> { if self.is::() { 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) @@ -890,7 +1108,7 @@ impl Box { } } -impl Box { +impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. @@ -910,30 +1128,34 @@ impl Box { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` - 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)) - }) + pub fn downcast(self) -> Result, Self> { + if self.is::() { + 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 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 @@ -943,7 +1165,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 { @@ -952,17 +1174,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 = "none")] -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() @@ -983,7 +1205,7 @@ trait BoxIter { fn last(self) -> Option; } -impl BoxIter for Box { +impl BoxIter for Box { type Item = I::Item; default fn last(self) -> Option { #[inline] @@ -998,14 +1220,14 @@ impl BoxIter for Box { /// Specialization for sized `I`s that uses `I`s implementation of `last()` /// instead of the default. #[stable(feature = "rust1", since = "1.0.0")] -impl BoxIter for Box { +impl BoxIter for Box { fn last(self) -> Option { (*self).last() } } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Box { +impl DoubleEndedIterator for Box { fn next_back(&mut self) -> Option { (**self).next_back() } @@ -1014,7 +1236,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() } @@ -1024,74 +1246,74 @@ 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 { - type Output = >::Output; +impl + ?Sized, A: AllocRef> FnOnce for Box { + type Output = >::Output; - extern "rust-call" fn call_once(self, args: A) -> Self::Output { - >::call_once(*self, args) + extern "rust-call" fn call_once(self, args: Args) -> Self::Output { + >::call_once(*self, args) } } #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized> FnMut for Box { - extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { - >::call_mut(self, args) +impl + ?Sized, A: AllocRef> FnMut for Box { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { + >::call_mut(self, args) } } #[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl + ?Sized> Fn for Box { - extern "rust-call" fn call(&self, args: A) -> Self::Output { - >::call(self, args) +impl + ?Sized, A: AllocRef> Fn for Box { + extern "rust-call" fn call(&self, args: Args) -> Self::Output { + >::call(self, args) } } #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Box {} +impl, A: AllocRef, U: ?Sized> CoerceUnsized> for Box {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U: ?Sized> DispatchFromDyn> for Box {} #[stable(feature = "boxed_slice_from_iter", since = "1.32.0")] -impl FromIterator for Box<[A]> { - fn from_iter>(iter: T) -> Self { +impl FromIterator for Box<[I]> { + fn from_iter>(iter: T) -> Self { iter.into_iter().collect::>().into_boxed_slice() } } #[stable(feature = "box_slice_clone", since = "1.3.0")] -impl Clone for Box<[T]> { +impl Clone for Box<[T], A> { fn clone(&self) -> Self { - self.to_vec().into_boxed_slice() + self.to_vec_in(self.alloc().clone()).into_boxed_slice() } } #[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 } @@ -1120,10 +1342,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 + Unpin, R> Generator for Box { +impl + Unpin, R, A: AllocRef> Generator for Box { type Yield = G::Yield; type Return = G::Return; @@ -1133,7 +1355,7 @@ impl + Unpin, R> Generator for Box { } #[unstable(feature = "generator_trait", issue = "43122")] -impl, R> Generator for Pin> { +impl, R, A: AllocRef> Generator for Pin> { type Yield = G::Yield; type Return = G::Return; @@ -1143,7 +1365,7 @@ impl, R> 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/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index a3ef998918433..3261eb523cb21 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -150,6 +150,7 @@ use core::mem::{self, size_of, swap, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::ptr; +use crate::alloc::{AllocRef, Global}; use crate::slice; use crate::vec::{self, Vec}; @@ -245,8 +246,8 @@ use super::SpecExtend; /// [peek]: #method.peek /// [peek\_mut]: #method.peek_mut #[stable(feature = "rust1", since = "1.0.0")] -pub struct BinaryHeap { - data: Vec, +pub struct BinaryHeap { + data: Vec, } /// Structure wrapping a mutable reference to the greatest item on a @@ -258,20 +259,20 @@ pub struct BinaryHeap { /// [`peek_mut`]: struct.BinaryHeap.html#method.peek_mut /// [`BinaryHeap`]: struct.BinaryHeap.html #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -pub struct PeekMut<'a, T: 'a + Ord> { - heap: &'a mut BinaryHeap, +pub struct PeekMut<'a, T: 'a + Ord, A: 'a + AllocRef = Global> { + heap: &'a mut BinaryHeap, sift: bool, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for PeekMut<'_, T> { +impl fmt::Debug for PeekMut<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish() } } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -impl Drop for PeekMut<'_, T> { +impl Drop for PeekMut<'_, T, A> { fn drop(&mut self) { if self.sift { self.heap.sift_down(0); @@ -280,7 +281,7 @@ impl Drop for PeekMut<'_, T> { } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -impl Deref for PeekMut<'_, T> { +impl Deref for PeekMut<'_, T, A> { type Target = T; fn deref(&self) -> &T { debug_assert!(!self.heap.is_empty()); @@ -290,7 +291,7 @@ impl Deref for PeekMut<'_, T> { } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -impl DerefMut for PeekMut<'_, T> { +impl DerefMut for PeekMut<'_, T, A> { fn deref_mut(&mut self) -> &mut T { debug_assert!(!self.heap.is_empty()); // SAFE: PeekMut is only instantiated for non-empty heaps @@ -298,10 +299,10 @@ impl DerefMut for PeekMut<'_, T> { } } -impl<'a, T: Ord> PeekMut<'a, T> { +impl<'a, T: Ord, A: AllocRef> PeekMut<'a, T, A> { /// Removes the peeked value from the heap and returns it. #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")] - pub fn pop(mut this: PeekMut<'a, T>) -> T { + pub fn pop(mut this: Self) -> T { let value = this.heap.pop().unwrap(); this.sift = false; value @@ -309,7 +310,7 @@ impl<'a, T: Ord> PeekMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for BinaryHeap { +impl Clone for BinaryHeap { fn clone(&self) -> Self { BinaryHeap { data: self.data.clone() } } @@ -329,7 +330,7 @@ impl Default for BinaryHeap { } #[stable(feature = "binaryheap_debug", since = "1.4.0")] -impl fmt::Debug for BinaryHeap { +impl fmt::Debug for BinaryHeap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } @@ -347,9 +348,10 @@ impl BinaryHeap { /// let mut heap = BinaryHeap::new(); /// heap.push(4); /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> BinaryHeap { - BinaryHeap { data: vec![] } + pub fn new() -> Self { + Self::new_in(Global) } /// Creates an empty `BinaryHeap` with a specific capacity. @@ -366,9 +368,55 @@ impl BinaryHeap { /// let mut heap = BinaryHeap::with_capacity(10); /// heap.push(4); /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> BinaryHeap { - BinaryHeap { data: Vec::with_capacity(capacity) } + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } +} + +impl BinaryHeap { + /// Creates an empty `BinaryHeap` as a max-heap in the provided allocator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::BinaryHeap; + + /// let mut heap = BinaryHeap::new_in(System); + /// heap.push(4); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_in(alloc: A) -> Self { + Self { data: Vec::new_in(alloc) } + } + + /// Creates an empty `BinaryHeap` with a specific capacity in the provided allocator. + /// This preallocates enough memory for `capacity` elements, + /// so that the `BinaryHeap` does not have to be reallocated + /// until it contains at least that many values. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::BinaryHeap; + + /// let mut heap = BinaryHeap::with_capacity_in(10, System); + /// heap.push(4); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self { data: Vec::with_capacity_in(capacity, alloc) } } /// Returns a mutable reference to the greatest item in the binary heap, or @@ -400,7 +448,7 @@ impl BinaryHeap { /// /// Cost is `O(1)` in the worst case. #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] - pub fn peek_mut(&mut self) -> Option> { + pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: true }) } } @@ -491,7 +539,7 @@ impl BinaryHeap { /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]); /// ``` #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] - pub fn into_sorted_vec(mut self) -> Vec { + pub fn into_sorted_vec(mut self) -> Vec { let mut end = self.len(); while end > 1 { end -= 1; @@ -662,7 +710,7 @@ impl BinaryHeap { /// ``` #[inline] #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] - pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> { + pub fn drain_sorted(&mut self) -> DrainSorted<'_, T, A> { DrainSorted { inner: self } } @@ -695,7 +743,7 @@ impl BinaryHeap { } } -impl BinaryHeap { +impl BinaryHeap { /// Returns an iterator visiting all values in the underlying vector, in /// arbitrary order. /// @@ -732,7 +780,7 @@ impl BinaryHeap { /// assert_eq!(heap.into_iter_sorted().take(2).collect::>(), vec![5, 4]); /// ``` #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] - pub fn into_iter_sorted(self) -> IntoIterSorted { + pub fn into_iter_sorted(self) -> IntoIterSorted { IntoIterSorted { inner: self } } @@ -779,6 +827,20 @@ impl BinaryHeap { self.data.capacity() } + /// Returns a shared reference to the allocator backing this `BinaryHeap`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc(&self) -> &A { + self.data.alloc() + } + + /// Returns a mutable reference to the allocator backing this `BinaryHeap`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc_mut(&mut self) -> &mut A { + self.data.alloc_mut() + } + /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the /// given `BinaryHeap`. Does nothing if the capacity is already sufficient. /// @@ -893,7 +955,7 @@ impl BinaryHeap { /// } /// ``` #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] - pub fn into_vec(self) -> Vec { + pub fn into_vec(self) -> Vec { self.into() } @@ -959,7 +1021,7 @@ impl BinaryHeap { /// ``` #[inline] #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self) -> Drain<'_, T> { + pub fn drain(&mut self) -> Drain<'_, T, A> { Drain { iter: self.data.drain(..) } } @@ -1127,19 +1189,19 @@ impl FusedIterator for Iter<'_, T> {} /// [`BinaryHeap`]: struct.BinaryHeap.html #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] -pub struct IntoIter { - iter: vec::IntoIter, +pub struct IntoIter { + iter: vec::IntoIter, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; #[inline] @@ -1154,7 +1216,7 @@ impl Iterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() @@ -1162,23 +1224,23 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { +impl ExactSizeIterator for IntoIter { fn is_empty(&self) -> bool { self.iter.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter {} #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] #[derive(Clone, Debug)] -pub struct IntoIterSorted { - inner: BinaryHeap, +pub struct IntoIterSorted { + inner: BinaryHeap, } #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl Iterator for IntoIterSorted { +impl Iterator for IntoIterSorted { type Item = T; #[inline] @@ -1194,13 +1256,13 @@ impl Iterator for IntoIterSorted { } #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl ExactSizeIterator for IntoIterSorted {} +impl ExactSizeIterator for IntoIterSorted {} #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl FusedIterator for IntoIterSorted {} +impl FusedIterator for IntoIterSorted {} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIterSorted {} +unsafe impl TrustedLen for IntoIterSorted {} /// A draining iterator over the elements of a `BinaryHeap`. /// @@ -1211,12 +1273,12 @@ unsafe impl TrustedLen for IntoIterSorted {} /// [`BinaryHeap`]: struct.BinaryHeap.html #[stable(feature = "drain", since = "1.6.0")] #[derive(Debug)] -pub struct Drain<'a, T: 'a> { - iter: vec::Drain<'a, T>, +pub struct Drain<'a, T: 'a, A: 'a + AllocRef = Global> { + iter: vec::Drain<'a, T, A>, } #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T> { +impl Iterator for Drain<'_, T, A> { type Item = T; #[inline] @@ -1231,7 +1293,7 @@ impl Iterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T> { +impl DoubleEndedIterator for Drain<'_, T, A> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() @@ -1239,14 +1301,14 @@ impl DoubleEndedIterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T> { +impl ExactSizeIterator for Drain<'_, T, A> { fn is_empty(&self) -> bool { self.iter.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T> {} +impl FusedIterator for Drain<'_, T, A> {} /// A draining iterator over the elements of a `BinaryHeap`. /// @@ -1257,17 +1319,17 @@ impl FusedIterator for Drain<'_, T> {} /// [`BinaryHeap`]: struct.BinaryHeap.html #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] #[derive(Debug)] -pub struct DrainSorted<'a, T: Ord> { - inner: &'a mut BinaryHeap, +pub struct DrainSorted<'a, T: Ord, A: AllocRef = Global> { + inner: &'a mut BinaryHeap, } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl<'a, T: Ord> Drop for DrainSorted<'a, T> { +impl<'a, T: Ord, A: AllocRef> Drop for DrainSorted<'a, T, A> { /// Removes heap elements in heap order. fn drop(&mut self) { - struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>); + struct DropGuard<'r, 'a, T: Ord, A: AllocRef>(&'r mut DrainSorted<'a, T, A>); - impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> { + impl<'r, 'a, T: Ord, A: AllocRef> Drop for DropGuard<'r, 'a, T, A> { fn drop(&mut self) { while self.0.inner.pop().is_some() {} } @@ -1282,7 +1344,7 @@ impl<'a, T: Ord> Drop for DrainSorted<'a, T> { } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl Iterator for DrainSorted<'_, T> { +impl Iterator for DrainSorted<'_, T, A> { type Item = T; #[inline] @@ -1298,20 +1360,20 @@ impl Iterator for DrainSorted<'_, T> { } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl ExactSizeIterator for DrainSorted<'_, T> {} +impl ExactSizeIterator for DrainSorted<'_, T, A> {} #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl FusedIterator for DrainSorted<'_, T> {} +impl FusedIterator for DrainSorted<'_, T, A> {} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for DrainSorted<'_, T> {} +unsafe impl TrustedLen for DrainSorted<'_, T, A> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] -impl From> for BinaryHeap { +impl From> for BinaryHeap { /// Converts a `Vec` into a `BinaryHeap`. /// /// This conversion happens in-place, and has `O(n)` time complexity. - fn from(vec: Vec) -> BinaryHeap { + fn from(vec: Vec) -> Self { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); heap @@ -1319,8 +1381,8 @@ impl From> for BinaryHeap { } #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] -impl From> for Vec { - fn from(heap: BinaryHeap) -> Vec { +impl From> for Vec { + fn from(heap: BinaryHeap) -> Vec { heap.data } } @@ -1333,9 +1395,9 @@ impl FromIterator for BinaryHeap { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for BinaryHeap { +impl IntoIterator for BinaryHeap { type Item = T; - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Creates a consuming iterator, that is, one that moves each value out of /// the binary heap in arbitrary order. The binary heap cannot be used @@ -1355,13 +1417,13 @@ impl IntoIterator for BinaryHeap { /// println!("{}", x); /// } /// ``` - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> Self::IntoIter { IntoIter { iter: self.data.into_iter() } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a BinaryHeap { +impl<'a, T, A: AllocRef> IntoIterator for &'a BinaryHeap { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1371,26 +1433,26 @@ impl<'a, T> IntoIterator for &'a BinaryHeap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for BinaryHeap { +impl Extend for BinaryHeap { #[inline] fn extend>(&mut self, iter: I) { >::spec_extend(self, iter); } } -impl> SpecExtend for BinaryHeap { +impl, A: AllocRef> SpecExtend for BinaryHeap { default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter.into_iter()); } } -impl SpecExtend> for BinaryHeap { - fn spec_extend(&mut self, ref mut other: BinaryHeap) { +impl SpecExtend> for BinaryHeap { + fn spec_extend(&mut self, ref mut other: Self) { self.append(other); } } -impl BinaryHeap { +impl BinaryHeap { fn extend_desugared>(&mut self, iter: I) { let iterator = iter.into_iter(); let (lower, _) = iterator.size_hint(); @@ -1402,7 +1464,7 @@ impl BinaryHeap { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap { +impl<'a, T: 'a + Ord + Copy, A: 'a + AllocRef> Extend<&'a T> for BinaryHeap { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 113df80d0c215..3539176eba6c4 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -12,6 +12,7 @@ use core::{fmt, ptr}; use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef}; use super::search::{self, SearchResult::*}; use super::unwrap_unchecked; +use crate::alloc::{AllocRef, Global}; use Entry::*; use UnderflowResult::*; @@ -122,13 +123,13 @@ use UnderflowResult::*; /// *stat += random_stat_buff(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct BTreeMap { - root: Option>, +pub struct BTreeMap { + root: Option>, length: usize, } #[stable(feature = "btree_drop", since = "1.7.0")] -unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap { +unsafe impl<#[may_dangle] K, #[may_dangle] V, A: AllocRef> Drop for BTreeMap { fn drop(&mut self) { unsafe { drop(ptr::read(self).into_iter()); @@ -1535,7 +1536,7 @@ impl ExactSizeIterator for IterMut<'_, K, V> { impl FusedIterator for IterMut<'_, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for BTreeMap { +impl IntoIterator for BTreeMap { type Item = (K, V); type IntoIter = IntoIter; diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 5569c293e2f66..c635a625a41f2 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -142,10 +142,11 @@ impl BoxedNode { /// An owned tree. /// /// Note that this does not have a destructor, and must be cleaned up manually. -pub struct Root { +pub struct Root { node: BoxedNode, /// The number of levels below the root node. height: usize, + alloc: PhantomData, } unsafe impl Sync for Root {} @@ -154,7 +155,11 @@ unsafe impl Send for Root {} impl Root { /// Returns a new owned tree, with its own root node that is initially empty. pub fn new_leaf() -> Self { - Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 } + Root { + node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), + height: 0, + alloc: PhantomData, + } } pub fn as_ref(&self) -> NodeRef, K, V, marker::LeafOrInternal> { @@ -174,7 +179,9 @@ impl Root { _marker: PhantomData, } } +} +impl Root { pub fn into_ref(self) -> NodeRef { NodeRef { height: self.height, @@ -183,7 +190,9 @@ impl Root { _marker: PhantomData, } } +} +impl Root { /// Adds a new internal node with a single edge, pointing to the previous root, and make that /// new node the root. This increases the height by 1 and is the opposite of `pop_level`. pub fn push_level(&mut self) -> NodeRef, K, V, marker::Internal> { @@ -615,7 +624,8 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { ForceResult::Internal(internal) => { let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1).as_ptr()); - let mut new_root = Root { node: edge, height: internal.height - 1 }; + let mut new_root = + Root { node: edge, height: internal.height - 1, alloc: PhantomData }; (*new_root.as_mut().as_leaf_mut()).parent = ptr::null(); Some(new_root) } @@ -647,7 +657,8 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { 0, ); - let mut new_root = Root { node: edge, height: internal.height - 1 }; + let mut new_root = + Root { node: edge, height: internal.height - 1, alloc: PhantomData }; (*new_root.as_mut().as_leaf_mut()).parent = ptr::null(); for i in 0..old_len { @@ -1026,7 +1037,12 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::KV> (*self.node.as_leaf_mut()).len = self.idx as u16; new_node.len = new_len as u16; - (self.node, k, v, Root { node: BoxedNode::from_leaf(new_node), height: 0 }) + ( + self.node, + k, + v, + Root { node: BoxedNode::from_leaf(new_node), height: 0, alloc: PhantomData }, + ) } } @@ -1081,7 +1097,8 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: (*self.node.as_leaf_mut()).len = self.idx as u16; new_node.data.len = new_len as u16; - let mut new_root = Root { node: BoxedNode::from_internal(new_node), height }; + let mut new_root = + Root { node: BoxedNode::from_internal(new_node), height, alloc: PhantomData }; for i in 0..(new_len + 1) { Handle::new_edge(new_root.as_mut().cast_unchecked(), i).correct_parent_link(); diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index dee5fb878ff2a..876a17f2ab26e 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -2,14 +2,16 @@ // to TreeMap use core::borrow::Borrow; -use core::cmp::Ordering::{Equal, Greater, Less}; +use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::{max, min}; use core::fmt::{self, Debug}; +use core::hash; use core::iter::{FromIterator, FusedIterator, Peekable}; use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub}; use super::map::{BTreeMap, Keys}; use super::Recover; +use crate::alloc::{AllocRef, Global}; // FIXME(conventions): implement bounded iterators @@ -56,10 +58,44 @@ use super::Recover; /// println!("{}", book); /// } /// ``` -#[derive(Hash, PartialEq, Eq, Ord, PartialOrd)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct BTreeSet { - map: BTreeMap, +pub struct BTreeSet { + map: BTreeMap, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for BTreeSet { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.map.eq(&other.map) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for BTreeSet {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for BTreeSet { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.map.partial_cmp(&other.map) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for BTreeSet { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.map.cmp(&other.map) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for BTreeSet { + #[inline] + fn hash(&self, state: &mut H) { + self.map.hash(state) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index cc0f07b822741..c5d7b6ca68683 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -21,6 +21,7 @@ use core::mem; use core::ptr::NonNull; use super::SpecExtend; +use crate::alloc::{AllocRef, Global}; use crate::boxed::Box; #[cfg(test)] @@ -35,11 +36,12 @@ mod tests; /// array-based containers are generally faster, /// more memory efficient, and make better use of CPU cache. #[stable(feature = "rust1", since = "1.0.0")] -pub struct LinkedList { +pub struct LinkedList { head: Option>>, tail: Option>>, len: usize, marker: PhantomData>>, + alloc: PhantomData, } struct Node { @@ -134,7 +136,7 @@ impl Node { } // private methods -impl LinkedList { +impl LinkedList { /// Adds the given node to the front of the list. #[inline] fn push_front_node(&mut self, mut node: Box>) { @@ -216,7 +218,10 @@ impl LinkedList { node }) } +} +// private methods +impl LinkedList { /// Unlinks the specified node from the current list. /// /// Warning: this will not check that the provided node belongs to the current list. @@ -310,6 +315,7 @@ impl LinkedList { tail: first_part_tail, len: at, marker: PhantomData, + alloc: PhantomData, }; // Fix the head ptr of the second part @@ -346,6 +352,7 @@ impl LinkedList { tail: second_part_tail, len: self.len - at, marker: PhantomData, + alloc: PhantomData, }; // Fix the tail ptr of the first part @@ -382,7 +389,7 @@ impl LinkedList { #[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> Self { - LinkedList { head: None, tail: None, len: 0, marker: PhantomData } + LinkedList { head: None, tail: None, len: 0, marker: PhantomData, alloc: PhantomData } } /// Moves all elements from `other` to the end of the list. @@ -964,11 +971,11 @@ impl LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for LinkedList { +unsafe impl<#[may_dangle] T, A: AllocRef> Drop for LinkedList { fn drop(&mut self) { - struct DropGuard<'a, T>(&'a mut LinkedList); + struct DropGuard<'a, T, A: AllocRef>(&'a mut LinkedList); - impl<'a, T> Drop for DropGuard<'a, T> { + impl<'a, T, A: AllocRef> Drop for DropGuard<'a, T, A> { fn drop(&mut self) { // Continue the same loop we do below. This only runs when a destructor has // panicked. If another one panics this will abort. @@ -1517,6 +1524,7 @@ impl<'a, T> CursorMut<'a, T> { tail: Some(unlinked_node), len: 1, marker: PhantomData, + alloc: PhantomData, }) } } diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 2f50234b6d582..df7d241ab3675 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -11,21 +11,24 @@ use core::array::LengthAtMost32; use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{Hash, Hasher}; -use core::iter::{once, repeat_with, FromIterator, FusedIterator}; +use core::iter::{once, repeat_with, FromIterator}; use core::mem::{self, replace, ManuallyDrop}; use core::ops::Bound::{Excluded, Included, Unbounded}; -use core::ops::{Index, IndexMut, RangeBounds, Try}; +use core::ops::{Index, IndexMut, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice; +use crate::alloc::{AllocRef, Global}; use crate::collections::TryReserveError; use crate::raw_vec::RawVec; use crate::vec::Vec; #[stable(feature = "drain", since = "1.6.0")] -pub use self::drain::Drain; +pub use self::iter::Drain; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::iter::{IntoIter, Iter, IterMut}; -mod drain; +mod iter; #[cfg(test)] mod tests; @@ -52,7 +55,7 @@ const MAXIMUM_ZST_CAPACITY: usize = 1 << (64 - 1); // Largest possible power of /// [`append`]: #method.append #[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")] #[stable(feature = "rust1", since = "1.0.0")] -pub struct VecDeque { +pub struct VecDeque { // tail and head are pointers into the buffer. Tail always points // to the first element that could be read, Head always points // to where data should be written. @@ -60,7 +63,7 @@ pub struct VecDeque { // is defined as the distance between the two. tail: usize, head: usize, - buf: RawVec, + buf: RawVec, } /// PairSlices pairs up equal length slice parts of two deques @@ -85,7 +88,7 @@ struct PairSlices<'a, 'b, T> { } impl<'a, 'b, T> PairSlices<'a, 'b, T> { - fn from(to: &'a mut VecDeque, from: &'b VecDeque) -> Self { + fn from(to: &'a mut VecDeque, from: &'b VecDeque) -> Self { let (a0, a1) = to.as_mut_slices(); let (b0, b1) = from.as_slices(); PairSlices { a0, a1, b0, b1 } @@ -125,9 +128,13 @@ impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for VecDeque { - fn clone(&self) -> VecDeque { - self.iter().cloned().collect() +impl Clone for VecDeque { + fn clone(&self) -> VecDeque { + let iterator = self.into_iter().cloned(); + let (lower, _) = iterator.size_hint(); + let mut deq = VecDeque::with_capacity_in(lower, self.alloc().clone()); + deq.extend(iterator); + deq } fn clone_from(&mut self, other: &Self) { @@ -147,7 +154,7 @@ impl Clone for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for VecDeque { +unsafe impl<#[may_dangle] T, A: AllocRef> Drop for VecDeque { fn drop(&mut self) { /// Runs the destructor for all items in the slice when it gets dropped (normally or /// during unwinding). @@ -180,7 +187,7 @@ impl Default for VecDeque { } } -impl VecDeque { +impl VecDeque { /// Marginally more convenient #[inline] fn ptr(&self) -> *mut T { @@ -466,9 +473,10 @@ impl VecDeque { /// /// let vector: VecDeque = VecDeque::new(); /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> VecDeque { - VecDeque::with_capacity(INITIAL_CAPACITY) + pub fn new() -> Self { + Self::new_in(Global) } /// Creates an empty `VecDeque` with space for at least `capacity` elements. @@ -480,13 +488,48 @@ impl VecDeque { /// /// let vector: VecDeque = VecDeque::with_capacity(10); /// ``` + #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> VecDeque { + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } +} + +impl VecDeque { + /// Creates an empty `VecDeque` in the provided allocator. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let vector: VecDeque = VecDeque::new(); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_in(alloc: A) -> Self { + VecDeque::with_capacity_in(INITIAL_CAPACITY, alloc) + } + + /// Creates an empty `VecDeque` with space for at least `capacity` elements in the provided + /// allocator. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::VecDeque; + /// + /// let vector: VecDeque = VecDeque::with_capacity_in(10, System); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { // +1 since the ringbuffer always leaves one space empty let cap = cmp::max(capacity + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); assert!(cap > capacity, "capacity overflow"); - VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity(cap) } + VecDeque { tail: 0, head: 0, buf: RawVec::with_capacity_in(cap, alloc) } } /// Provides a reference to the element at the given index. @@ -592,6 +635,20 @@ impl VecDeque { self.cap() - 1 } + /// Returns a shared reference to the allocator backing this `VecDeque`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc(&self) -> &A { + self.buf.alloc() + } + + /// Returns a mutable reference to the allocator backing this `VecDeque`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc_mut(&mut self) -> &mut A { + self.buf.alloc_mut() + } + /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the /// given `VecDeque`. Does nothing if the capacity is already sufficient. /// @@ -1089,7 +1146,7 @@ impl VecDeque { /// ``` #[inline] #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self, range: R) -> Drain<'_, T> + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> where R: RangeBounds, { @@ -1859,76 +1916,6 @@ impl VecDeque { elem } - /// Splits the `VecDeque` into two at the given index. - /// - /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`, - /// and the returned `VecDeque` contains elements `[at, len)`. - /// - /// Note that the capacity of `self` does not change. - /// - /// Element at index 0 is the front of the queue. - /// - /// # Panics - /// - /// Panics if `at > len`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::VecDeque; - /// - /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect(); - /// let buf2 = buf.split_off(1); - /// assert_eq!(buf, [1]); - /// assert_eq!(buf2, [2, 3]); - /// ``` - #[inline] - #[must_use = "use `.truncate()` if you don't need the other half"] - #[stable(feature = "split_off", since = "1.4.0")] - pub fn split_off(&mut self, at: usize) -> Self { - let len = self.len(); - assert!(at <= len, "`at` out of bounds"); - - let other_len = len - at; - let mut other = VecDeque::with_capacity(other_len); - - unsafe { - let (first_half, second_half) = self.as_slices(); - - let first_len = first_half.len(); - let second_len = second_half.len(); - if at < first_len { - // `at` lies in the first half. - let amount_in_first = first_len - at; - - ptr::copy_nonoverlapping(first_half.as_ptr().add(at), other.ptr(), amount_in_first); - - // just take all of the second half. - ptr::copy_nonoverlapping( - second_half.as_ptr(), - other.ptr().add(amount_in_first), - second_len, - ); - } else { - // `at` lies in the second half, need to factor in the elements we skipped - // in the first half. - let offset = at - first_len; - let amount_in_second = second_len - offset; - ptr::copy_nonoverlapping( - second_half.as_ptr().add(offset), - other.ptr(), - amount_in_second, - ); - } - } - - // Cleanup where the ends of the buffers are - self.head = self.wrap_sub(self.head, other_len); - other.head = other.wrap_index(other_len); - - other - } - /// Moves all the elements of `other` into `self`, leaving `other` empty. /// /// # Panics @@ -2302,7 +2289,79 @@ impl VecDeque { } } -impl VecDeque { +impl VecDeque { + /// Splits the `VecDeque` into two at the given index. + /// + /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`, + /// and the returned `VecDeque` contains elements `[at, len)`. + /// + /// Note that the capacity of `self` does not change. + /// + /// Element at index 0 is the front of the queue. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect(); + /// let buf2 = buf.split_off(1); + /// assert_eq!(buf, [1]); + /// assert_eq!(buf2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + pub fn split_off(&mut self, at: usize) -> Self { + let len = self.len(); + assert!(at <= len, "`at` out of bounds"); + + let other_len = len - at; + let mut other = VecDeque::with_capacity_in(other_len, self.alloc().clone()); + + unsafe { + let (first_half, second_half) = self.as_slices(); + + let first_len = first_half.len(); + let second_len = second_half.len(); + if at < first_len { + // `at` lies in the first half. + let amount_in_first = first_len - at; + + ptr::copy_nonoverlapping(first_half.as_ptr().add(at), other.ptr(), amount_in_first); + + // just take all of the second half. + ptr::copy_nonoverlapping( + second_half.as_ptr(), + other.ptr().add(amount_in_first), + second_len, + ); + } else { + // `at` lies in the second half, need to factor in the elements we skipped + // in the first half. + let offset = at - first_len; + let amount_in_second = second_len - offset; + ptr::copy_nonoverlapping( + second_half.as_ptr().add(offset), + other.ptr(), + amount_in_second, + ); + } + } + + // Cleanup where the ends of the buffers are + self.head = self.wrap_sub(self.head, other_len); + other.head = other.wrap_index(other_len); + + other + } +} + +impl VecDeque { /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len, /// either by removing excess elements from the back or by appending clones of `value` /// to the back. @@ -2381,324 +2440,9 @@ fn count(tail: usize, head: usize, size: usize) -> usize { (head.wrapping_sub(tail)) & (size - 1) } -/// An iterator over the elements of a `VecDeque`. -/// -/// This `struct` is created by the [`iter`] method on [`VecDeque`]. See its -/// documentation for more. -/// -/// [`iter`]: struct.VecDeque.html#method.iter -/// [`VecDeque`]: struct.VecDeque.html -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Iter<'a, T: 'a> { - ring: &'a [T], - tail: usize, - head: usize, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Iter<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - f.debug_tuple("Iter").field(&front).field(&back).finish() - } -} - -// FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Iter<'_, T> { - fn clone(&self) -> Self { - Iter { ring: self.ring, tail: self.tail, head: self.head } - } -} - #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Iterator for Iter<'a, T> { - type Item = &'a T; - - #[inline] - fn next(&mut self) -> Option<&'a T> { - if self.tail == self.head { - return None; - } - let tail = self.tail; - self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); - unsafe { Some(self.ring.get_unchecked(tail)) } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = count(self.tail, self.head, self.ring.len()); - (len, Some(len)) - } - - fn fold(self, mut accum: Acc, mut f: F) -> Acc - where - F: FnMut(Acc, Self::Item) -> Acc, - { - let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - accum = front.iter().fold(accum, &mut f); - back.iter().fold(accum, &mut f) - } - - fn try_fold(&mut self, init: B, mut f: F) -> R - where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, - { - let (mut iter, final_res); - if self.tail <= self.head { - // single slice self.ring[self.tail..self.head] - iter = self.ring[self.tail..self.head].iter(); - final_res = iter.try_fold(init, &mut f); - } else { - // two slices: self.ring[self.tail..], self.ring[..self.head] - let (front, back) = self.ring.split_at(self.tail); - let mut back_iter = back.iter(); - let res = back_iter.try_fold(init, &mut f); - let len = self.ring.len(); - self.tail = (self.ring.len() - back_iter.len()) & (len - 1); - iter = front[..self.head].iter(); - final_res = iter.try_fold(res?, &mut f); - } - self.tail = self.head - iter.len(); - final_res - } - - fn nth(&mut self, n: usize) -> Option { - if n >= count(self.tail, self.head, self.ring.len()) { - self.tail = self.head; - None - } else { - self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); - self.next() - } - } - - #[inline] - fn last(mut self) -> Option<&'a T> { - self.next_back() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> DoubleEndedIterator for Iter<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<&'a T> { - if self.tail == self.head { - return None; - } - self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); - unsafe { Some(self.ring.get_unchecked(self.head)) } - } - - fn rfold(self, mut accum: Acc, mut f: F) -> Acc - where - F: FnMut(Acc, Self::Item) -> Acc, - { - let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - accum = back.iter().rfold(accum, &mut f); - front.iter().rfold(accum, &mut f) - } - - fn try_rfold(&mut self, init: B, mut f: F) -> R - where - Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, - { - let (mut iter, final_res); - if self.tail <= self.head { - // single slice self.ring[self.tail..self.head] - iter = self.ring[self.tail..self.head].iter(); - final_res = iter.try_rfold(init, &mut f); - } else { - // two slices: self.ring[self.tail..], self.ring[..self.head] - let (front, back) = self.ring.split_at(self.tail); - let mut front_iter = front[..self.head].iter(); - let res = front_iter.try_rfold(init, &mut f); - self.head = front_iter.len(); - iter = back.iter(); - final_res = iter.try_rfold(res?, &mut f); - } - self.head = self.tail + iter.len(); - final_res - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Iter<'_, T> { - fn is_empty(&self) -> bool { - self.head == self.tail - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Iter<'_, T> {} - -/// A mutable iterator over the elements of a `VecDeque`. -/// -/// This `struct` is created by the [`iter_mut`] method on [`VecDeque`]. See its -/// documentation for more. -/// -/// [`iter_mut`]: struct.VecDeque.html#method.iter_mut -/// [`VecDeque`]: struct.VecDeque.html -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IterMut<'a, T: 'a> { - ring: &'a mut [T], - tail: usize, - head: usize, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for IterMut<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let (front, back) = RingSlices::ring_slices(&*self.ring, self.head, self.tail); - f.debug_tuple("IterMut").field(&front).field(&back).finish() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Iterator for IterMut<'a, T> { - type Item = &'a mut T; - - #[inline] - fn next(&mut self) -> Option<&'a mut T> { - if self.tail == self.head { - return None; - } - let tail = self.tail; - self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); - - unsafe { - let elem = self.ring.get_unchecked_mut(tail); - Some(&mut *(elem as *mut _)) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = count(self.tail, self.head, self.ring.len()); - (len, Some(len)) - } - - fn fold(self, mut accum: Acc, mut f: F) -> Acc - where - F: FnMut(Acc, Self::Item) -> Acc, - { - let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - accum = front.iter_mut().fold(accum, &mut f); - back.iter_mut().fold(accum, &mut f) - } - - fn nth(&mut self, n: usize) -> Option { - if n >= count(self.tail, self.head, self.ring.len()) { - self.tail = self.head; - None - } else { - self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); - self.next() - } - } - - #[inline] - fn last(mut self) -> Option<&'a mut T> { - self.next_back() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<&'a mut T> { - if self.tail == self.head { - return None; - } - self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); - - unsafe { - let elem = self.ring.get_unchecked_mut(self.head); - Some(&mut *(elem as *mut _)) - } - } - - fn rfold(self, mut accum: Acc, mut f: F) -> Acc - where - F: FnMut(Acc, Self::Item) -> Acc, - { - let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); - accum = back.iter_mut().rfold(accum, &mut f); - front.iter_mut().rfold(accum, &mut f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IterMut<'_, T> { - fn is_empty(&self) -> bool { - self.head == self.tail - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IterMut<'_, T> {} - -/// An owning iterator over the elements of a `VecDeque`. -/// -/// This `struct` is created by the [`into_iter`] method on [`VecDeque`] -/// (provided by the `IntoIterator` trait). See its documentation for more. -/// -/// [`into_iter`]: struct.VecDeque.html#method.into_iter -/// [`VecDeque`]: struct.VecDeque.html -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { - inner: VecDeque, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoIter").field(&self.inner).finish() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.inner.pop_front() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = self.inner.len(); - (len, Some(len)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - self.inner.pop_back() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { - fn is_empty(&self) -> bool { - self.inner.is_empty() - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for VecDeque { - fn eq(&self, other: &VecDeque) -> bool { +impl PartialEq> for VecDeque { + fn eq(&self, other: &VecDeque) -> bool { if self.len() != other.len() { return false; } @@ -2736,14 +2480,14 @@ impl PartialEq for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for VecDeque {} +impl Eq for VecDeque {} macro_rules! __impl_slice_eq1 { ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] - impl PartialEq<$rhs> for $lhs + impl PartialEq<$rhs> for $lhs where - A: PartialEq, + T: PartialEq, $($constraints)* { fn eq(&self, other: &$rhs) -> bool { @@ -2758,30 +2502,30 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [] VecDeque, Vec, } -__impl_slice_eq1! { [] VecDeque, &[B], } -__impl_slice_eq1! { [] VecDeque, &mut [B], } -__impl_slice_eq1! { [const N: usize] VecDeque, [B; N], [B; N]: LengthAtMost32 } -__impl_slice_eq1! { [const N: usize] VecDeque, &[B; N], [B; N]: LengthAtMost32 } -__impl_slice_eq1! { [const N: usize] VecDeque, &mut [B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [A1: AllocRef, A2: AllocRef] VecDeque, Vec, } +__impl_slice_eq1! { [A: AllocRef] VecDeque, &[U], } +__impl_slice_eq1! { [A: AllocRef] VecDeque, &mut [U], } +__impl_slice_eq1! { [A: AllocRef, const N: usize] VecDeque, [U; N], [U; N]: LengthAtMost32 } +__impl_slice_eq1! { [A: AllocRef, const N: usize] VecDeque, &[U; N], [U; N]: LengthAtMost32 } +__impl_slice_eq1! { [A: AllocRef, const N: usize] VecDeque, &mut [U; N], [U; N]: LengthAtMost32 } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for VecDeque { - fn partial_cmp(&self, other: &VecDeque) -> Option { +impl PartialOrd> for VecDeque { + fn partial_cmp(&self, other: &VecDeque) -> Option { self.iter().partial_cmp(other.iter()) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for VecDeque { +impl Ord for VecDeque { #[inline] - fn cmp(&self, other: &VecDeque) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other.iter()) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for VecDeque { +impl Hash for VecDeque { fn hash(&self, state: &mut H) { self.len().hash(state); let (a, b) = self.as_slices(); @@ -2791,26 +2535,26 @@ impl Hash for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Index for VecDeque { - type Output = A; +impl Index for VecDeque { + type Output = T; #[inline] - fn index(&self, index: usize) -> &A { + fn index(&self, index: usize) -> &T { self.get(index).expect("Out of bounds access") } } #[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for VecDeque { +impl IndexMut for VecDeque { #[inline] - fn index_mut(&mut self, index: usize) -> &mut A { + fn index_mut(&mut self, index: usize) -> &mut T { self.get_mut(index).expect("Out of bounds access") } } #[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for VecDeque { - fn from_iter>(iter: T) -> VecDeque { +impl FromIterator for VecDeque { + fn from_iter>(iter: I) -> Self { let iterator = iter.into_iter(); let (lower, _) = iterator.size_hint(); let mut deq = VecDeque::with_capacity(lower); @@ -2820,40 +2564,40 @@ impl FromIterator for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for VecDeque { +impl IntoIterator for VecDeque { type Item = T; - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by /// value. - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> Self::IntoIter { IntoIter { inner: self } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a VecDeque { +impl<'a, T, A: AllocRef> IntoIterator for &'a VecDeque { type Item = &'a T; type IntoIter = Iter<'a, T>; - fn into_iter(self) -> Iter<'a, T> { + fn into_iter(self) -> Self::IntoIter { self.iter() } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a mut VecDeque { +impl<'a, T, A: AllocRef> IntoIterator for &'a mut VecDeque { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; - fn into_iter(self) -> IterMut<'a, T> { + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for VecDeque { - fn extend>(&mut self, iter: T) { +impl Extend for VecDeque { + fn extend>(&mut self, iter: I) { // This function should be the moral equivalent of: // // for item in iter.into_iter() { @@ -2876,21 +2620,21 @@ impl Extend for VecDeque { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque { +impl<'a, T: 'a + Copy, A: AllocRef> Extend<&'a T> for VecDeque { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for VecDeque { +impl fmt::Debug for VecDeque { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self).finish() } } #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] -impl From> for VecDeque { +impl From> for VecDeque { /// Turn a [`Vec`] into a [`VecDeque`]. /// /// [`Vec`]: crate::vec::Vec @@ -2899,12 +2643,10 @@ impl From> for VecDeque { /// This avoids reallocating where possible, but the conditions for that are /// strict, and subject to change, and so shouldn't be relied upon unless the /// `Vec` came from `From>` and hasn't been reallocated. - fn from(other: Vec) -> Self { + fn from(other: Vec) -> Self { unsafe { - let mut other = ManuallyDrop::new(other); - let other_buf = other.as_mut_ptr(); - let mut buf = RawVec::from_raw_parts(other_buf, other.capacity()); - let len = other.len(); + let (ptr, len, capacity, alloc) = Vec::into_raw_parts_with_alloc(other); + let mut buf = RawVec::from_raw_parts_in(ptr, capacity, alloc); // We need to extend the buf if it's not a power of two, too small // or doesn't have at least one free space @@ -2916,13 +2658,13 @@ impl From> for VecDeque { buf.reserve_exact(len, cap - len); } - VecDeque { tail: 0, head: len, buf } + Self { tail: 0, head: len, buf } } } } #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] -impl From> for Vec { +impl From> for Vec { /// Turn a [`VecDeque`] into a [`Vec`]. /// /// [`Vec`]: crate::vec::Vec @@ -2952,19 +2694,20 @@ impl From> for Vec { /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]); /// assert_eq!(vec.as_ptr(), ptr); /// ``` - fn from(mut other: VecDeque) -> Self { + fn from(mut other: VecDeque) -> Self { other.make_contiguous(); unsafe { let other = ManuallyDrop::new(other); - let buf = other.buf.ptr(); + let ptr = other.buf.ptr(); let len = other.len(); let cap = other.cap(); + let alloc = ptr::read(other.alloc()); if other.head != 0 { - ptr::copy(buf.add(other.tail), buf, len); + ptr::copy(ptr.add(other.tail), ptr, len); } - Vec::from_raw_parts(buf, len, cap) + Vec::from_raw_parts_in(ptr, len, cap, alloc) } } } diff --git a/src/liballoc/collections/vec_deque/drain.rs b/src/liballoc/collections/vec_deque/drain.rs deleted file mode 100644 index 1ae94de75adb7..0000000000000 --- a/src/liballoc/collections/vec_deque/drain.rs +++ /dev/null @@ -1,126 +0,0 @@ -use core::iter::FusedIterator; -use core::ptr::{self, NonNull}; -use core::{fmt, mem}; - -use super::{count, Iter, VecDeque}; - -/// A draining iterator over the elements of a `VecDeque`. -/// -/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its -/// documentation for more. -/// -/// [`drain`]: struct.VecDeque.html#method.drain -/// [`VecDeque`]: struct.VecDeque.html -#[stable(feature = "drain", since = "1.6.0")] -pub struct Drain<'a, T: 'a> { - pub(crate) after_tail: usize, - pub(crate) after_head: usize, - pub(crate) iter: Iter<'a, T>, - pub(crate) deque: NonNull>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain") - .field(&self.after_tail) - .field(&self.after_head) - .field(&self.iter) - .finish() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T> {} -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T> {} - -#[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T> { - fn drop(&mut self) { - struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); - - impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { - fn drop(&mut self) { - self.0.for_each(drop); - - let source_deque = unsafe { self.0.deque.as_mut() }; - - // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head - // - // T t h H - // [. . . o o x x o o . . .] - // - let orig_tail = source_deque.tail; - let drain_tail = source_deque.head; - let drain_head = self.0.after_tail; - let orig_head = self.0.after_head; - - let tail_len = count(orig_tail, drain_tail, source_deque.cap()); - let head_len = count(drain_head, orig_head, source_deque.cap()); - - // Restore the original head value - source_deque.head = orig_head; - - match (tail_len, head_len) { - (0, 0) => { - source_deque.head = 0; - source_deque.tail = 0; - } - (0, _) => { - source_deque.tail = drain_head; - } - (_, 0) => { - source_deque.head = drain_tail; - } - _ => unsafe { - if tail_len <= head_len { - source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); - source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); - } else { - source_deque.head = source_deque.wrap_add(drain_tail, head_len); - source_deque.wrap_copy(drain_tail, drain_head, head_len); - } - }, - } - } - } - - while let Some(item) = self.next() { - let guard = DropGuard(self); - drop(item); - mem::forget(guard); - } - - DropGuard(self); - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| unsafe { ptr::read(elt) }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|elt| unsafe { ptr::read(elt) }) - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T> {} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T> {} diff --git a/src/liballoc/collections/vec_deque/iter.rs b/src/liballoc/collections/vec_deque/iter.rs new file mode 100644 index 0000000000000..9b0ba2cdc773f --- /dev/null +++ b/src/liballoc/collections/vec_deque/iter.rs @@ -0,0 +1,444 @@ +use core::fmt; +use core::iter::FusedIterator; +use core::mem; +use core::ops::Try; +use core::ptr::{self, NonNull}; + +use super::{count, wrap_index, RingSlices, VecDeque}; +use crate::alloc::{AllocRef, Global}; + +/// An iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`iter`] method on [`VecDeque`]. See its +/// documentation for more. +/// +/// [`iter`]: struct.VecDeque.html#method.iter +/// [`VecDeque`]: struct.VecDeque.html +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Iter<'a, T: 'a> { + pub(super) ring: &'a [T], + pub(super) tail: usize, + pub(super) head: usize, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Iter<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + f.debug_tuple("Iter").field(&front).field(&back).finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { ring: self.ring, tail: self.tail, head: self.head } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + unsafe { Some(self.ring.get_unchecked(tail)) } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = count(self.tail, self.head, self.ring.len()); + (len, Some(len)) + } + + fn fold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = front.iter().fold(accum, &mut f); + back.iter().fold(accum, &mut f) + } + + fn try_fold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let (mut iter, final_res); + if self.tail <= self.head { + // single slice self.ring[self.tail..self.head] + iter = self.ring[self.tail..self.head].iter(); + final_res = iter.try_fold(init, &mut f); + } else { + // two slices: self.ring[self.tail..], self.ring[..self.head] + let (front, back) = self.ring.split_at(self.tail); + let mut back_iter = back.iter(); + let res = back_iter.try_fold(init, &mut f); + let len = self.ring.len(); + self.tail = (self.ring.len() - back_iter.len()) & (len - 1); + iter = front[..self.head].iter(); + final_res = iter.try_fold(res?, &mut f); + } + self.tail = self.head - iter.len(); + final_res + } + + fn nth(&mut self, n: usize) -> Option { + if n >= count(self.tail, self.head, self.ring.len()) { + self.tail = self.head; + None + } else { + self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); + self.next() + } + } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + if self.tail == self.head { + return None; + } + self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); + unsafe { Some(self.ring.get_unchecked(self.head)) } + } + + fn rfold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = back.iter().rfold(accum, &mut f); + front.iter().rfold(accum, &mut f) + } + + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let (mut iter, final_res); + if self.tail <= self.head { + // single slice self.ring[self.tail..self.head] + iter = self.ring[self.tail..self.head].iter(); + final_res = iter.try_rfold(init, &mut f); + } else { + // two slices: self.ring[self.tail..], self.ring[..self.head] + let (front, back) = self.ring.split_at(self.tail); + let mut front_iter = front[..self.head].iter(); + let res = front_iter.try_rfold(init, &mut f); + self.head = front_iter.len(); + iter = back.iter(); + final_res = iter.try_rfold(res?, &mut f); + } + self.head = self.tail + iter.len(); + final_res + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Iter<'_, T> { + fn is_empty(&self) -> bool { + self.head == self.tail + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Iter<'_, T> {} + +/// A mutable iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`iter_mut`] method on [`VecDeque`]. See its +/// documentation for more. +/// +/// [`iter_mut`]: struct.VecDeque.html#method.iter_mut +/// [`VecDeque`]: struct.VecDeque.html +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IterMut<'a, T: 'a> { + pub(super) ring: &'a mut [T], + pub(super) tail: usize, + pub(super) head: usize, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IterMut<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (front, back) = RingSlices::ring_slices(&*self.ring, self.head, self.tail); + f.debug_tuple("IterMut").field(&front).field(&back).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Iterator for IterMut<'a, T> { + type Item = &'a mut T; + + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + let tail = self.tail; + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); + + unsafe { + let elem = self.ring.get_unchecked_mut(tail); + Some(&mut *(elem as *mut _)) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = count(self.tail, self.head, self.ring.len()); + (len, Some(len)) + } + + fn fold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = front.iter_mut().fold(accum, &mut f); + back.iter_mut().fold(accum, &mut f) + } + + fn nth(&mut self, n: usize) -> Option { + if n >= count(self.tail, self.head, self.ring.len()) { + self.tail = self.head; + None + } else { + self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); + self.next() + } + } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + if self.tail == self.head { + return None; + } + self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); + + unsafe { + let elem = self.ring.get_unchecked_mut(self.head); + Some(&mut *(elem as *mut _)) + } + } + + fn rfold(self, mut accum: Acc, mut f: F) -> Acc + where + F: FnMut(Acc, Self::Item) -> Acc, + { + let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); + accum = back.iter_mut().rfold(accum, &mut f); + front.iter_mut().rfold(accum, &mut f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IterMut<'_, T> { + fn is_empty(&self) -> bool { + self.head == self.tail + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IterMut<'_, T> {} + +/// An owning iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`into_iter`] method on [`VecDeque`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: struct.VecDeque.html#method.into_iter +/// [`VecDeque`]: struct.VecDeque.html +#[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter { + pub(super) inner: VecDeque, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.inner).finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.inner.len(); + (len, Some(len)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.pop_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.inner.is_empty() + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +/// A draining iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its +/// documentation for more. +/// +/// [`drain`]: struct.VecDeque.html#method.drain +/// [`VecDeque`]: struct.VecDeque.html +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain<'a, T: 'a, A: AllocRef = Global> { + pub(super) after_tail: usize, + pub(super) after_head: usize, + pub(super) iter: Iter<'a, T>, + pub(super) deque: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain") + .field(&self.after_tail) + .field(&self.after_head) + .field(&self.iter) + .finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + struct DropGuard<'r, 'a, T, A: AllocRef>(&'r mut Drain<'a, T, A>); + + impl<'r, 'a, T, A: AllocRef> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + self.0.for_each(drop); + + let source_deque = unsafe { self.0.deque.as_mut() }; + + // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head + // + // T t h H + // [. . . o o x x o o . . .] + // + let orig_tail = source_deque.tail; + let drain_tail = source_deque.head; + let drain_head = self.0.after_tail; + let orig_head = self.0.after_head; + + let tail_len = count(orig_tail, drain_tail, source_deque.cap()); + let head_len = count(drain_head, orig_head, source_deque.cap()); + + // Restore the original head value + source_deque.head = orig_head; + + match (tail_len, head_len) { + (0, 0) => { + source_deque.head = 0; + source_deque.tail = 0; + } + (0, _) => { + source_deque.tail = drain_head; + } + (_, 0) => { + source_deque.head = drain_tail; + } + _ => unsafe { + if tail_len <= head_len { + source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); + source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); + } else { + source_deque.head = source_deque.wrap_add(drain_tail, head_len); + source_deque.wrap_copy(drain_tail, drain_head, head_len); + } + }, + } + } + } + + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt) }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index a8e19c9cbaa86..d85a5c044a9df 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -5,7 +5,7 @@ use core::alloc::MemoryBlock; use core::cmp; 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::{ @@ -560,9 +560,7 @@ impl RawVec { self.set_memory(memory); Ok(()) } -} -impl RawVec { /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. /// /// Note that this will correctly reconstitute any `cap` changes @@ -575,7 +573,7 @@ impl RawVec { /// /// 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]> { + pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit], A> { // Sanity-check one half of the safety requirement (we cannot check the other half). debug_assert!( len <= self.capacity(), @@ -584,7 +582,7 @@ impl RawVec { let me = ManuallyDrop::new(self); let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); - Box::from_raw(slice) + Box::from_raw_in(slice, ptr::read(&me.alloc)) } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 2f9505ec79ffa..ca7c552af29dd 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -281,9 +281,10 @@ struct RcBox { /// [get_mut]: #method.get_mut #[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Rc { +pub struct Rc { ptr: NonNull>, phantom: PhantomData>, + alloc: PhantomData, } #[stable(feature = "rust1", since = "1.0.0")] @@ -299,7 +300,7 @@ impl, U: ?Sized> DispatchFromDyn> for Rc {} impl Rc { fn from_inner(ptr: NonNull>) -> Self { - Self { ptr, phantom: PhantomData } + Self { ptr, phantom: PhantomData, alloc: PhantomData } } unsafe fn from_ptr(ptr: *mut RcBox) -> Self { @@ -997,7 +998,7 @@ impl Rc { ); // Free the allocation without dropping its contents - box_free(box_unique); + box_free(box_unique, Global); Self::from_ptr(ptr) } @@ -1114,7 +1115,7 @@ impl Deref for Rc { impl Receiver for Rc {} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { +unsafe impl<#[may_dangle] T: ?Sized, A: AllocRef> Drop for Rc { /// Drops the `Rc`. /// /// This will decrement the strong reference count. If the strong reference @@ -2074,7 +2075,7 @@ trait RcBoxPtr { } } -impl RcBoxPtr for Rc { +impl RcBoxPtr for Rc { #[inline(always)] fn inner(&self) -> &RcBox { unsafe { self.ptr.as_ref() } diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 53477288b59ee..f724afc6a96a0 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -91,6 +91,7 @@ use core::cmp::Ordering::{self, Less}; use core::mem::{self, size_of}; use core::ptr; +use crate::alloc::AllocRef; use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; @@ -128,13 +129,14 @@ pub use hack::into_vec; // HACK(japaric) needed for the implementation of `Vec::clone` during testing // N.B., see the `hack` module in this file for more details. #[cfg(test)] -pub use hack::to_vec; +pub use hack::{to_vec, to_vec_in}; // HACK(japaric): With cfg(test) `impl [T]` is not available, these three // functions are actually methods that are in `impl [T]` but not in // `core::slice::SliceExt` - we need to supply these functions for the // `test_permutations` test mod hack { + use crate::alloc::{AllocRef, Global}; use crate::boxed::Box; #[cfg(test)] use crate::string::ToString; @@ -143,11 +145,11 @@ mod hack { // We shouldn't add inline attribute to this since this is used in // `vec!` macro mostly and causes perf regression. See #71204 for // discussion and perf results. - pub fn into_vec(b: Box<[T]>) -> Vec { + pub fn into_vec(b: Box<[T], A>) -> Vec { unsafe { let len = b.len(); - let b = Box::into_raw(b); - Vec::from_raw_parts(b as *mut T, len, len) + let (b, a) = Box::into_raw_with_alloc(b); + Vec::from_raw_parts_in(b as *mut T, len, len, a) } } @@ -156,7 +158,15 @@ mod hack { where T: Clone, { - let mut vector = Vec::with_capacity(s.len()); + to_vec_in(s, Global) + } + + #[inline] + pub fn to_vec_in(s: &[T], alloc: A) -> Vec + where + T: Clone, + { + let mut vector = Vec::with_capacity_in(s.len(), alloc); vector.extend_from_slice(s); vector } @@ -395,6 +405,29 @@ impl [T] { hack::to_vec(self) } + /// Copies `self` into a new `Vec`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let s = [10, 40, 30]; + /// let x = s.to_vec_in(System); + /// // Here, `s` and `x` can be modified independently. + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn to_vec_in(&self, alloc: A) -> Vec + where + T: Clone, + { + // N.B., see the `hack` module in this file for more details. + hack::to_vec_in(self, alloc) + } + /// Converts `self` into a vector without clones or allocation. /// /// The resulting vector can be converted back into a box via @@ -411,7 +444,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn into_vec(self: Box) -> Vec { + pub fn into_vec(self: Box) -> Vec { // N.B., see the `hack` module in this file for more details. hack::into_vec(self) } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 70860c09a2c31..5d9dd1658eefe 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -27,6 +27,7 @@ // It's cleaner to just turn off the unused_imports warning than to fix them. #![allow(unused_imports)] +use core::alloc::AllocRef; use core::borrow::{Borrow, BorrowMut}; use core::iter::FusedIterator; use core::mem; @@ -182,7 +183,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for String { +impl Borrow for String { #[inline] fn borrow(&self) -> &str { &self[..] @@ -190,7 +191,7 @@ impl Borrow for String { } #[stable(feature = "string_borrow_mut", since = "1.36.0")] -impl BorrowMut for String { +impl BorrowMut for String { #[inline] fn borrow_mut(&mut self) -> &mut str { &mut self[..] @@ -582,6 +583,7 @@ 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 { + let (raw, alloc) = Box::into_raw_with_alloc(v); + Box::from_raw_in(raw as *mut str, alloc) } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index f3fe1adebb141..969f79d573d96 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -47,6 +47,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; +use core::cmp::Ordering; use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; @@ -55,6 +56,7 @@ use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds}; use core::ptr; use core::str::{lossy, pattern::Pattern}; +use crate::alloc::{AllocRef, Global}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::collections::TryReserveError; @@ -277,11 +279,10 @@ use crate::vec::Vec; /// [`&str`]: ../../std/primitive.str.html /// [`Deref`]: ../../std/ops/trait.Deref.html /// [`as_str()`]: struct.String.html#method.as_str -#[derive(PartialOrd, Eq, Ord)] #[cfg_attr(not(test), rustc_diagnostic_item = "string_type")] #[stable(feature = "rust1", since = "1.0.0")] -pub struct String { - vec: Vec, +pub struct String { + vec: Vec, } /// A possible error value when converting a `String` from a UTF-8 byte vector. @@ -320,12 +321,33 @@ pub struct String { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct FromUtf8Error { - bytes: Vec, +#[derive(Clone)] +pub struct FromUtf8Error { + bytes: Vec, error: Utf8Error, } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for FromUtf8Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FromUtf8Error") + .field("bytes", &self.bytes) + .field("error", &self.error) + .finish() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq> for FromUtf8Error { + #[inline] + fn eq(&self, other: &FromUtf8Error) -> bool { + self.bytes.eq(&other.bytes) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for FromUtf8Error {} + /// A possible error value when converting a `String` from a UTF-16 byte slice. /// /// This type is the error type for the [`from_utf16`] method on [`String`]. @@ -370,8 +392,8 @@ impl String { #[inline] #[rustc_const_stable(feature = "const_string_new", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn new() -> String { - String { vec: Vec::new() } + pub const fn new() -> Self { + Self { vec: Vec::new() } } /// Creates a new empty `String` with a particular capacity. @@ -413,8 +435,8 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> String { - String { vec: Vec::with_capacity(capacity) } + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) } // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is @@ -423,80 +445,10 @@ impl String { // NB see the slice::hack module in slice.rs for more information #[inline] #[cfg(test)] - pub fn from_str(_: &str) -> String { + pub fn from_str(_: &str) -> Self { panic!("not available with cfg(test)"); } - /// Converts a vector of bytes to a `String`. - /// - /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes - /// ([`Vec`]) is made of bytes, so this function converts between the - /// two. Not all byte slices are valid `String`s, however: `String` - /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that - /// the bytes are valid UTF-8, and then does the conversion. - /// - /// If you are sure that the byte slice is valid UTF-8, and you don't want - /// to incur the overhead of the validity check, there is an unsafe version - /// of this function, [`from_utf8_unchecked`], which has the same behavior - /// but skips the check. - /// - /// This method will take care to not copy the vector, for efficiency's - /// sake. - /// - /// If you need a [`&str`] instead of a `String`, consider - /// [`str::from_utf8`]. - /// - /// The inverse of this method is [`into_bytes`]. - /// - /// # Errors - /// - /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the - /// provided bytes are not UTF-8. The vector you moved in is also included. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// // some bytes, in a vector - /// let sparkle_heart = vec![240, 159, 146, 150]; - /// - /// // We know these bytes are valid, so we'll use `unwrap()`. - /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); - /// - /// assert_eq!("💖", sparkle_heart); - /// ``` - /// - /// Incorrect bytes: - /// - /// ``` - /// // some invalid bytes, in a vector - /// let sparkle_heart = vec![0, 159, 146, 150]; - /// - /// assert!(String::from_utf8(sparkle_heart).is_err()); - /// ``` - /// - /// See the docs for [`FromUtf8Error`] for more details on what you can do - /// with this error. - /// - /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked - /// [`String`]: struct.String.html - /// [`u8`]: ../../std/primitive.u8.html - /// [`Vec`]: ../../std/vec/struct.Vec.html - /// [`&str`]: ../../std/primitive.str.html - /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html - /// [`into_bytes`]: struct.String.html#method.into_bytes - /// [`FromUtf8Error`]: struct.FromUtf8Error.html - /// [`Err`]: ../../std/result/enum.Result.html#variant.Err - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf8(vec: Vec) -> Result { - match str::from_utf8(&vec) { - Ok(..) => Ok(String { vec }), - Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), - } - } - /// Converts a slice of bytes to a string, including invalid characters. /// /// Strings are made of bytes ([`u8`]), and a slice of bytes @@ -601,11 +553,269 @@ impl String { /// 0xD800, 0x0069, 0x0063]; /// assert!(String::from_utf16(v).is_err()); /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16(v: &[u16]) -> Result { + Self::from_utf16_in(v, Global) + } + + /// Decode a UTF-16 encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: #method.from_utf8_lossy + /// [`Cow<'a, str>`]: ../borrow/enum.Cow.html + /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0xDD1E, 0x0069, 0x0063, + /// 0xD834]; + /// + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16_lossy(v)); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn from_utf16_lossy(v: &[u16]) -> Self { + Self::from_utf16_lossy_in(v, Global) + } + + /// Creates a new `String` from a length, capacity, and pointer. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * The memory at `ptr` needs to have been previously allocated by the + /// same allocator the standard library uses, with a required alignment of exactly 1. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `String` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::mem; + /// + /// unsafe { + /// let s = String::from("hello"); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent automatically dropping the String's data + /// let mut s = mem::ManuallyDrop::new(s); + /// + /// let ptr = s.as_mut_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// + /// let s = String::from_raw_parts(ptr, len, capacity); + /// + /// assert_eq!(String::from("hello"), s); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> Self { + Self::from_raw_parts_in(buf, length, capacity, Global) + } +} + +impl String { + /// Creates a new empty `String` in the provided allocator. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, it may cause excessive allocation later when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity`]: #method.with_capacity + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let s = String::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_in(alloc: A) -> Self { + String { vec: Vec::new_in(alloc) } + } + + /// Creates a new empty `String` with a particular capacity in the provided allocator. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold `capacity` bytes. This is useful when you may be + /// appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity`]: #method.capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new`] method. + /// + /// [`new`]: #method.new + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut s = String::with_capacity_in(10, System); + /// + /// // The String contains no chars, even though it has capacity for more + /// assert_eq!(s.len(), 0); + /// + /// // These are all done without reallocating... + /// let cap = s.capacity(); + /// for _ in 0..10 { + /// s.push('a'); + /// } + /// + /// assert_eq!(s.capacity(), cap); + /// + /// // ...but this may make the string reallocate + /// s.push('a'); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + String { vec: Vec::with_capacity_in(capacity, alloc) } + } + + /// Converts a vector of bytes to a `String`. + /// + /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes + /// ([`Vec`]) is made of bytes, so this function converts between the + /// two. Not all byte slices are valid `String`s, however: `String` + /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that + /// the bytes are valid UTF-8, and then does the conversion. + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want + /// to incur the overhead of the validity check, there is an unsafe version + /// of this function, [`from_utf8_unchecked`], which has the same behavior + /// but skips the check. + /// + /// This method will take care to not copy the vector, for efficiency's + /// sake. + /// + /// If you need a [`&str`] instead of a `String`, consider + /// [`str::from_utf8`]. + /// + /// The inverse of this method is [`into_bytes`]. + /// + /// # Errors + /// + /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the + /// provided bytes are not UTF-8. The vector you moved in is also included. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// // We know these bytes are valid, so we'll use `unwrap()`. + /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// // some invalid bytes, in a vector + /// let sparkle_heart = vec![0, 159, 146, 150]; + /// + /// assert!(String::from_utf8(sparkle_heart).is_err()); + /// ``` + /// + /// See the docs for [`FromUtf8Error`] for more details on what you can do + /// with this error. + /// + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked + /// [`String`]: struct.String.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`Vec`]: ../../std/vec/struct.Vec.html + /// [`&str`]: ../../std/primitive.str.html + /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html + /// [`into_bytes`]: struct.String.html#method.into_bytes + /// [`FromUtf8Error`]: struct.FromUtf8Error.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf16(v: &[u16]) -> Result { + pub fn from_utf8(vec: Vec) -> Result> { + match str::from_utf8(&vec) { + Ok(..) => Ok(Self { vec }), + Err(e) => Err(FromUtf8Error { bytes: vec, error: e }), + } + } + + /// Decode a UTF-16 encoded vector `v` into a `String` in the provided allocator, returning + /// [`Err`] if `v` contains any invalid data. + /// + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// // 𝄞music + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0x0073, 0x0069, 0x0063]; + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16_in(v, System).unwrap()); + /// + /// // 𝄞muic + /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, + /// 0xD800, 0x0069, 0x0063]; + /// assert!(String::from_utf16_in(v, System).is_err()); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn from_utf16_in(v: &[u16], alloc: A) -> Result { // This isn't done via collect::>() for performance reasons. // FIXME: the function can be simplified again when #48994 is closed. - let mut ret = String::with_capacity(v.len()); + let mut ret = Self::with_capacity_in(v.len(), alloc); for c in decode_utf16(v.iter().cloned()) { if let Ok(c) = c { ret.push(c); @@ -616,7 +826,7 @@ impl String { Ok(ret) } - /// Decode a UTF-16 encoded slice `v` into a `String`, replacing + /// Decode a UTF-16 encoded slice `v` into a `String` in the provided allocator, replacing /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. /// /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], @@ -632,18 +842,24 @@ impl String { /// Basic usage: /// /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// /// // 𝄞music /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, /// 0x0073, 0xDD1E, 0x0069, 0x0063, /// 0xD834]; /// /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), - /// String::from_utf16_lossy(v)); + /// String::from_utf16_lossy_in(v, System)); /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf16_lossy(v: &[u16]) -> String { - decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect() + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn from_utf16_lossy_in(v: &[u16], alloc: A) -> Self { + let mut buf = String::new_in(alloc); + buf.extend(decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))); + buf } /// Decomposes a `String` into its raw components. @@ -677,6 +893,14 @@ impl String { self.vec.into_raw_parts() } + /// Behaves like [`into_raw_parts`] but also returns the allocator. + /// + /// [`into_raw_parts`]: #method.into_raw_parts + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_parts_with_alloc(self) -> (*mut u8, usize, usize, A) { + self.vec.into_raw_parts_with_alloc() + } + /// Creates a new `String` from a length, capacity, and pointer. /// /// # Safety @@ -703,10 +927,14 @@ impl String { /// Basic usage: /// /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; /// use std::mem; /// /// unsafe { - /// let s = String::from("hello"); + /// let mut s = String::new_in(System); + /// s.push_str("hello"); /// // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent automatically dropping the String's data @@ -716,15 +944,20 @@ impl String { /// let len = s.len(); /// let capacity = s.capacity(); /// - /// let s = String::from_raw_parts(ptr, len, capacity); + /// let s = String::from_raw_parts_in(ptr, len, capacity, System); /// /// assert_eq!(String::from("hello"), s); /// } /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { - String { vec: Vec::from_raw_parts(buf, length, capacity) } + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_parts_in( + buf: *mut u8, + length: usize, + capacity: usize, + alloc: A, + ) -> Self { + Self { vec: Vec::from_raw_parts_in(buf, length, capacity, alloc) } } /// Converts a vector of bytes to a `String` without checking that the @@ -757,8 +990,8 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { - String { vec: bytes } + pub unsafe fn from_utf8_unchecked(bytes: Vec) -> Self { + Self { vec: bytes } } /// Converts a `String` into a byte vector. @@ -777,7 +1010,7 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_bytes(self) -> Vec { + pub fn into_bytes(self) -> Vec { self.vec } @@ -854,6 +1087,20 @@ impl String { self.vec.capacity() } + /// Returns a shared reference to the allocator backing this `String`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc(&self) -> &A { + self.vec.alloc() + } + + /// Returns a mutable reference to the allocator backing this `String`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc_mut(&mut self) -> &mut A { + self.vec.alloc_mut() + } + /// Ensures that this `String`'s capacity is at least `additional` bytes /// larger than its length. /// @@ -1393,7 +1640,7 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { + pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { &mut self.vec } @@ -1438,38 +1685,6 @@ impl String { self.len() == 0 } - /// Splits the string into two at the given index. - /// - /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and - /// the returned `String` contains bytes `[at, len)`. `at` must be on the - /// boundary of a UTF-8 code point. - /// - /// Note that the capacity of `self` does not change. - /// - /// # Panics - /// - /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last - /// code point of the string. - /// - /// # Examples - /// - /// ``` - /// # fn main() { - /// let mut hello = String::from("Hello, World!"); - /// let world = hello.split_off(7); - /// assert_eq!(hello, "Hello, "); - /// assert_eq!(world, "World!"); - /// # } - /// ``` - #[inline] - #[stable(feature = "string_split_off", since = "1.16.0")] - #[must_use = "use `.truncate()` if you don't need the other half"] - pub fn split_off(&mut self, at: usize) -> String { - assert!(self.is_char_boundary(at)); - let other = self.vec.split_off(at); - unsafe { String::from_utf8_unchecked(other) } - } - /// Truncates this `String`, removing all contents. /// /// While this means the `String` will have a length of zero, it does not @@ -1525,7 +1740,7 @@ impl String { /// assert_eq!(s, ""); /// ``` #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self, range: R) -> Drain<'_> + pub fn drain(&mut self, range: R) -> Drain<'_, A> where R: RangeBounds, { @@ -1622,13 +1837,47 @@ impl String { /// ``` #[stable(feature = "box_str", since = "1.4.0")] #[inline] - pub fn into_boxed_str(self) -> Box { + pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); unsafe { from_boxed_utf8_unchecked(slice) } } } -impl FromUtf8Error { +impl String { + /// Splits the string into two at the given index. + /// + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Panics + /// + /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last + /// code point of the string. + /// + /// # Examples + /// + /// ``` + /// # fn main() { + /// let mut hello = String::from("Hello, World!"); + /// let world = hello.split_off(7); + /// assert_eq!(hello, "Hello, "); + /// assert_eq!(world, "World!"); + /// # } + /// ``` + #[inline] + #[stable(feature = "string_split_off", since = "1.16.0")] + #[must_use = "use `.truncate()` if you don't need the other half"] + pub fn split_off(&mut self, at: usize) -> Self { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); + unsafe { String::from_utf8_unchecked(other) } + } +} + +impl FromUtf8Error { /// Returns a slice of [`u8`]s bytes that were attempted to convert to a `String`. /// /// # Examples @@ -1667,7 +1916,7 @@ impl FromUtf8Error { /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_bytes(self) -> Vec { + pub fn into_bytes(self) -> Vec { self.bytes } @@ -1703,7 +1952,7 @@ impl FromUtf8Error { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for FromUtf8Error { +impl fmt::Display for FromUtf8Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.error, f) } @@ -1717,7 +1966,7 @@ impl fmt::Display for FromUtf16Error { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for String { +impl Clone for String { fn clone(&self) -> Self { String { vec: self.vec.clone() } } @@ -1792,7 +2041,7 @@ impl<'a> FromIterator> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for String { +impl Extend for String { fn extend>(&mut self, iter: I) { let iterator = iter.into_iter(); let (lower_bound, _) = iterator.size_hint(); @@ -1802,28 +2051,28 @@ impl Extend for String { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a> Extend<&'a char> for String { +impl<'a, A: AllocRef> Extend<&'a char> for String { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Extend<&'a str> for String { +impl<'a, A: AllocRef> Extend<&'a str> for String { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); } } #[stable(feature = "extend_string", since = "1.4.0")] -impl Extend for String { - fn extend>(&mut self, iter: I) { +impl Extend> for String { + fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } } #[stable(feature = "herd_cows", since = "1.19.0")] -impl<'a> Extend> for String { +impl<'a, A: AllocRef> Extend> for String { fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } @@ -1841,7 +2090,7 @@ impl<'a> Extend> for String { reason = "API not fully fleshed out and ready to be stabilized", issue = "27721" )] -impl<'a, 'b> Pattern<'a> for &'b String { +impl<'a, 'b, A: AllocRef> Pattern<'a> for &'b String { type Searcher = <&'b str as Pattern<'a>>::Searcher; fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher { @@ -1875,22 +2124,41 @@ impl<'a, 'b> Pattern<'a> for &'b String { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for String { +impl PartialEq> for String { #[inline] - fn eq(&self, other: &String) -> bool { + fn eq(&self, other: &String) -> bool { PartialEq::eq(&self[..], &other[..]) } #[inline] - fn ne(&self, other: &String) -> bool { + fn ne(&self, other: &String) -> bool { PartialEq::ne(&self[..], &other[..]) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for String {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd> for String { + #[inline] + fn partial_cmp(&self, other: &String) -> Option { + self.vec.partial_cmp(&other.vec) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for String { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.vec.cmp(&other.vec) + } +} + macro_rules! impl_eq { - ($lhs:ty, $rhs: ty) => { + ([$($vars:tt)*] $lhs:ty, $rhs: ty) => { #[stable(feature = "rust1", since = "1.0.0")] #[allow(unused_lifetimes)] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl<'a, 'b, $($vars)*> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) @@ -1903,7 +2171,7 @@ macro_rules! impl_eq { #[stable(feature = "rust1", since = "1.0.0")] #[allow(unused_lifetimes)] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl<'a, 'b, $($vars)*> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) @@ -1916,11 +2184,11 @@ macro_rules! impl_eq { }; } -impl_eq! { String, str } -impl_eq! { String, &'a str } -impl_eq! { Cow<'a, str>, str } -impl_eq! { Cow<'a, str>, &'b str } -impl_eq! { Cow<'a, str>, String } +impl_eq! { [A: AllocRef] String, str } +impl_eq! { [A: AllocRef] String, &'a str } +impl_eq! { [] Cow<'a, str>, str } +impl_eq! { [] Cow<'a, str>, &'b str } +impl_eq! { [A: AllocRef] Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] impl Default for String { @@ -1932,7 +2200,7 @@ impl Default for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for String { +impl fmt::Display for String { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&**self, f) @@ -1940,7 +2208,7 @@ impl fmt::Display for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for String { +impl fmt::Debug for String { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) @@ -1948,7 +2216,7 @@ impl fmt::Debug for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for String { +impl hash::Hash for String { #[inline] fn hash(&self, hasher: &mut H) { (**self).hash(hasher) @@ -1993,11 +2261,11 @@ impl hash::Hash for String { /// let c = a.to_string() + b; /// ``` #[stable(feature = "rust1", since = "1.0.0")] -impl Add<&str> for String { - type Output = String; +impl Add<&str> for String { + type Output = Self; #[inline] - fn add(mut self, other: &str) -> String { + fn add(mut self, other: &str) -> Self { self.push_str(other); self } @@ -2007,7 +2275,7 @@ impl Add<&str> for String { /// /// This has the same behavior as the [`push_str`][String::push_str] method. #[stable(feature = "stringaddassign", since = "1.12.0")] -impl AddAssign<&str> for String { +impl AddAssign<&str> for String { #[inline] fn add_assign(&mut self, other: &str) { self.push_str(other); @@ -2015,7 +2283,7 @@ impl AddAssign<&str> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl ops::Index> for String { type Output = str; #[inline] @@ -2024,7 +2292,7 @@ impl ops::Index> for String { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl ops::Index> for String { type Output = str; #[inline] @@ -2033,7 +2301,7 @@ impl ops::Index> for String { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl ops::Index> for String { type Output = str; #[inline] @@ -2042,7 +2310,7 @@ impl ops::Index> for String { } } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for String { +impl ops::Index for String { type Output = str; #[inline] @@ -2051,7 +2319,7 @@ impl ops::Index for String { } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::Index> for String { +impl ops::Index> for String { type Output = str; #[inline] @@ -2060,7 +2328,7 @@ impl ops::Index> for String { } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::Index> for String { +impl ops::Index> for String { type Output = str; #[inline] @@ -2070,42 +2338,42 @@ impl ops::Index> for String { } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::Range) -> &mut str { &mut self[..][index] } } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { &mut self[..][index] } } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { &mut self[..][index] } } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::IndexMut for String { +impl ops::IndexMut for String { #[inline] fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str { unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { IndexMut::index_mut(&mut **self, index) } } #[stable(feature = "inclusive_range", since = "1.26.0")] -impl ops::IndexMut> for String { +impl ops::IndexMut> for String { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { IndexMut::index_mut(&mut **self, index) @@ -2113,7 +2381,7 @@ impl ops::IndexMut> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for String { +impl ops::Deref for String { type Target = str; #[inline] @@ -2123,7 +2391,7 @@ impl ops::Deref for String { } #[stable(feature = "derefmut_for_string", since = "1.3.0")] -impl ops::DerefMut for String { +impl ops::DerefMut for String { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } @@ -2218,7 +2486,7 @@ impl ToString for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for String { +impl AsRef for String { #[inline] fn as_ref(&self) -> &str { self @@ -2226,7 +2494,7 @@ impl AsRef for String { } #[stable(feature = "string_as_mut", since = "1.43.0")] -impl AsMut for String { +impl AsMut for String { #[inline] fn as_mut(&mut self) -> &mut str { self @@ -2234,7 +2502,7 @@ impl AsMut for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[u8]> for String { +impl AsRef<[u8]> for String { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() @@ -2244,7 +2512,7 @@ impl AsRef<[u8]> for String { #[stable(feature = "rust1", since = "1.0.0")] impl From<&str> for String { #[inline] - fn from(s: &str) -> String { + fn from(s: &str) -> Self { s.to_owned() } } @@ -2255,15 +2523,15 @@ impl From<&mut str> for String { /// /// The result is allocated on the heap. #[inline] - fn from(s: &mut str) -> String { + fn from(s: &mut str) -> Self { s.to_owned() } } #[stable(feature = "from_ref_string", since = "1.35.0")] -impl From<&String> for String { +impl From<&Self> for String { #[inline] - fn from(s: &String) -> String { + fn from(s: &Self) -> Self { s.clone() } } @@ -2271,7 +2539,7 @@ impl From<&String> for String { // note: test pulls in libstd, which causes errors here #[cfg(not(test))] #[stable(feature = "string_from_box", since = "1.18.0")] -impl From> for String { +impl From> for String { /// Converts the given boxed `str` slice to a `String`. /// It is notable that the `str` slice is owned. /// @@ -2286,28 +2554,9 @@ impl From> for String { /// /// assert_eq!("hello world", s3) /// ``` - fn from(s: Box) -> String { - s.into_string() - } -} - -#[stable(feature = "box_from_str", since = "1.20.0")] -impl From for Box { - /// Converts the given `String` to a boxed `str` slice that is owned. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let s1: String = String::from("hello world"); - /// let s2: Box = Box::from(s1); - /// let s3: String = String::from(s2); - /// - /// assert_eq!("hello world", s3) - /// ``` - fn from(s: String) -> Box { - s.into_boxed_str() + fn from(s: Box) -> Self { + let s: Box<[u8], A> = s.into(); + unsafe { Self::from_utf8_unchecked(s.into()) } } } @@ -2364,7 +2613,7 @@ impl<'a> FromIterator for Cow<'a, str> { } #[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] -impl From for Vec { +impl From> for Vec { /// Converts the given `String` to a vector `Vec` that holds values of type `u8`. /// /// # Examples @@ -2379,13 +2628,13 @@ impl From for Vec { /// println!("{}", b); /// } /// ``` - fn from(string: String) -> Vec { + fn from(string: String) -> Vec { string.into_bytes() } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Write for String { +impl fmt::Write for String { #[inline] fn write_str(&mut self, s: &str) -> fmt::Result { self.push_str(s); @@ -2407,9 +2656,9 @@ impl fmt::Write for String { /// [`drain`]: struct.String.html#method.drain /// [`String`]: struct.String.html #[stable(feature = "drain", since = "1.6.0")] -pub struct Drain<'a> { +pub struct Drain<'a, A: AllocRef = Global> { /// Will be used as &'a mut String in the destructor - string: *mut String, + string: *mut String, /// Start of part to remove start: usize, /// End of part to remove @@ -2419,19 +2668,19 @@ pub struct Drain<'a> { } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_> { +impl fmt::Debug for Drain<'_, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Drain { .. }") } } #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_> {} +unsafe impl Sync for Drain<'_, A> {} #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_> {} +unsafe impl Send for Drain<'_, A> {} #[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_> { +impl Drop for Drain<'_, A> { fn drop(&mut self) { unsafe { // Use Vec::drain. "Reaffirm" the bounds checks to avoid @@ -2445,7 +2694,7 @@ impl Drop for Drain<'_> { } #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_> { +impl Iterator for Drain<'_, A> { type Item = char; #[inline] @@ -2464,7 +2713,7 @@ impl Iterator for Drain<'_> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_> { +impl DoubleEndedIterator for Drain<'_, A> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() @@ -2472,4 +2721,4 @@ impl DoubleEndedIterator for Drain<'_> { } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_> {} +impl FusedIterator for Drain<'_, A> {} diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 19d289c87fd9f..8d6f3309b73ab 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -209,9 +209,10 @@ macro_rules! acquire { /// [rc_examples]: ../../std/rc/index.html#examples #[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] #[stable(feature = "rust1", since = "1.0.0")] -pub struct Arc { +pub struct Arc { ptr: NonNull>, phantom: PhantomData>, + alloc: PhantomData, } #[stable(feature = "rust1", since = "1.0.0")] @@ -227,7 +228,7 @@ impl, U: ?Sized> DispatchFromDyn> for Arc {} impl Arc { fn from_inner(ptr: NonNull>) -> Self { - Self { ptr, phantom: PhantomData } + Self { ptr, phantom: PhantomData, alloc: PhantomData } } unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { @@ -849,29 +850,6 @@ impl Arc { mem::drop(Arc::from_raw(ptr)); } - #[inline] - fn inner(&self) -> &ArcInner { - // This unsafety is ok because while this arc is alive we're guaranteed - // that the inner pointer is valid. Furthermore, we know that the - // `ArcInner` structure itself is `Sync` because the inner data is - // `Sync` as well, so we're ok loaning out an immutable pointer to these - // contents. - unsafe { self.ptr.as_ref() } - } - - // Non-inlined part of `drop`. - #[inline(never)] - unsafe fn drop_slow(&mut self) { - // Destroy the data at this time, even though we may not free the box - // allocation itself (there may still be weak pointers lying around). - ptr::drop_in_place(&mut self.ptr.as_mut().data); - - if self.inner().weak.fetch_sub(1, Release) == 1 { - acquire!(self.inner().weak); - Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) - } - } - #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Arc`s point to the same allocation @@ -896,6 +874,31 @@ impl Arc { } } +impl Arc { + #[inline] + fn inner(&self) -> &ArcInner { + // This unsafety is ok because while this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` because the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. + unsafe { self.ptr.as_ref() } + } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + // Destroy the data at this time, even though we may not free the box + // allocation itself (there may still be weak pointers lying around). + ptr::drop_in_place(&mut self.ptr.as_mut().data); + + if self.inner().weak.fetch_sub(1, Release) == 1 { + acquire!(self.inner().weak); + Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) + } + } +} + impl Arc { /// Allocates an `ArcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided. @@ -950,7 +953,7 @@ impl Arc { ); // Free the allocation without dropping its contents - box_free(box_unique); + box_free(box_unique, Global); Self::from_ptr(ptr) } @@ -1308,7 +1311,7 @@ impl Arc { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { +unsafe impl<#[may_dangle] T: ?Sized, A: AllocRef> Drop for Arc { /// Drops the `Arc`. /// /// This will decrement the strong reference count. If the strong reference diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index cbfbf4d1cd32d..7fff6bd8b2c91 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -72,7 +72,8 @@ use core::ops::{self, Index, IndexMut, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; -use crate::borrow::{Cow, ToOwned}; +use crate::alloc::{AllocRef, Global}; +use crate::borrow::Cow; use crate::boxed::Box; use crate::collections::TryReserveError; use crate::raw_vec::RawVec; @@ -297,8 +298,8 @@ use crate::raw_vec::RawVec; /// [owned slice]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] -pub struct Vec { - buf: RawVec, +pub struct Vec { + buf: RawVec, len: usize, } @@ -320,7 +321,7 @@ impl Vec { #[inline] #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn new() -> Vec { + pub const fn new() -> Self { Vec { buf: RawVec::NEW, len: 0 } } @@ -354,49 +355,139 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> Vec { - Vec { buf: RawVec::with_capacity(capacity), len: 0 } + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) } - /// Decomposes a `Vec` into its raw components. + /// Creates a `Vec` directly from the raw components of another vector. /// - /// Returns the raw pointer to the underlying data, the length of - /// the vector (in elements), and the allocated capacity of the - /// data (in elements). These are the same arguments in the same - /// order as the arguments to [`from_raw_parts`]. + /// # Safety /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `Vec` with the [`from_raw_parts`] function, allowing - /// the destructor to perform the cleanup. + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: /// - /// [`from_raw_parts`]: #method.from_raw_parts + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satsify the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: ../../std/string/struct.String.html + /// [`dealloc`]: ../../alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc /// /// # Examples /// /// ``` - /// #![feature(vec_into_raw_parts)] - /// let v: Vec = vec![-1, 0, 1]; + /// use std::ptr; + /// use std::mem; /// - /// let (ptr, len, cap) = v.into_raw_parts(); + /// let v = vec![1, 2, 3]; /// - /// let rebuilt = unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr = ptr as *mut u32; + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); /// - /// Vec::from_raw_parts(ptr, len, cap) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } /// ``` - #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] - pub fn into_raw_parts(self) -> (*mut T, usize, usize) { - let mut me = ManuallyDrop::new(self); - (me.as_mut_ptr(), me.len(), me.capacity()) + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + Self::from_raw_parts_in(ptr, length, capacity, Global) } +} - /// Creates a `Vec` directly from the raw components of another vector. +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut vec: Vec = Vec::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + Vec { buf: RawVec::new_in(alloc), len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut vec = Vec::with_capacity_in(10, System); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } + } + + /// Creates a `Vec` directly from the raw components of another vector. /// /// # Safety /// @@ -411,6 +502,7 @@ impl Vec { /// allocated and deallocated with the same layout.) /// * `length` needs to be less than or equal to `capacity`. /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * `alloc` needs th be the allocator the pointer was allocated with. /// /// Violating these may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe @@ -432,10 +524,17 @@ impl Vec { /// # Examples /// /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; /// use std::ptr; /// use std::mem; /// - /// let v = vec![1, 2, 3]; + // FIXME Update this when vec! can take an allocator + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); /// // FIXME Update this when vec_into_raw_parts is stabilized /// // Prevent running `v`'s destructor so we are in complete control @@ -454,13 +553,61 @@ impl Vec { /// } /// /// // Put everything back together into a Vec - /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, System); /// assert_eq!(rebuilt, [4, 5, 6]); /// } /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec { - Vec { buf: RawVec::from_raw_parts(ptr, capacity), len: length } + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { + Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: #method.from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + + /// Behaves like [`into_raw_parts`] but also returns the allocator. + /// + /// [`into_raw_parts`]: #method.into_raw_parts + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { + let mut me = ManuallyDrop::new(self); + let alloc = unsafe { ptr::read(me.alloc()) }; + (me.as_mut_ptr(), me.len(), me.capacity(), alloc) } /// Returns the number of elements the vector can hold without @@ -478,6 +625,20 @@ impl Vec { self.buf.capacity() } + /// Returns a shared reference to the allocator backing this `Vec`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc(&self) -> &A { + self.buf.alloc() + } + + /// Returns a mutable reference to the allocator backing this `Vec`. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn alloc_mut(&mut self) -> &mut A { + self.buf.alloc_mut() + } + /// Reserves capacity for at least `additional` more elements to be inserted /// in the given `Vec`. The collection may reserve more space to avoid /// frequent reallocations. After calling `reserve`, capacity will be @@ -675,7 +836,7 @@ impl Vec { /// assert_eq!(slice.into_vec().capacity(), 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_boxed_slice(mut self) -> Box<[T]> { + pub fn into_boxed_slice(mut self) -> Box<[T], A> { unsafe { self.shrink_to_fit(); let me = ManuallyDrop::new(self); @@ -1293,7 +1454,7 @@ impl Vec { /// assert_eq!(v, &[]); /// ``` #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self, range: R) -> Drain<'_, T> + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> where R: RangeBounds, { @@ -1404,51 +1565,6 @@ impl Vec { self.len() == 0 } - /// Splits the collection into two at the given index. - /// - /// Returns a newly allocated vector containing the elements in the range - /// `[at, len)`. After the call, the original vector will be left containing - /// the elements `[0, at)` with its previous capacity unchanged. - /// - /// # Panics - /// - /// Panics if `at > len`. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1,2,3]; - /// let vec2 = vec.split_off(1); - /// assert_eq!(vec, [1]); - /// assert_eq!(vec2, [2, 3]); - /// ``` - #[inline] - #[must_use = "use `.truncate()` if you don't need the other half"] - #[stable(feature = "split_off", since = "1.4.0")] - pub fn split_off(&mut self, at: usize) -> Self { - #[cold] - #[inline(never)] - fn assert_failed(at: usize, len: usize) -> ! { - panic!("`at` split index (is {}) should be <= len (is {})", at, len); - } - - if at > self.len() { - assert_failed(at, self.len()); - } - - let other_len = self.len - at; - let mut other = Vec::with_capacity(other_len); - - // Unsafely `set_len` and copy items to `other`. - unsafe { - self.set_len(at); - other.set_len(other_len); - - ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); - } - other - } - /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the @@ -1516,7 +1632,7 @@ impl Vec { /// ``` #[unstable(feature = "vec_leak", issue = "62195")] #[inline] - pub fn leak<'a>(vec: Vec) -> &'a mut [T] + pub fn leak<'a>(vec: Self) -> &'a mut [T] where T: 'a, // Technically not needed, but kept to be explicit. { @@ -1524,7 +1640,54 @@ impl Vec { } } -impl Vec { +impl Vec { + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1,2,3]; + /// let vec2 = vec.split_off(1); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + pub fn split_off(&mut self, at: usize) -> Self { + #[cold] + #[inline(never)] + fn assert_failed(at: usize, len: usize) -> ! { + panic!("`at` split index (is {}) should be <= len (is {})", at, len); + } + + if at > self.len() { + assert_failed(at, self.len()); + } + + let other_len = self.len - at; + let mut other = Vec::with_capacity_in(other_len, self.alloc().clone()); + + // Unsafely `set_len` and copy items to `other`. + unsafe { + self.set_len(at); + other.set_len(other_len); + + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); + } + other + } +} + +impl Vec { /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the @@ -1587,7 +1750,7 @@ impl Vec { } } -impl Vec { +impl Vec { /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. /// /// If `new_len` is greater than `len`, the `Vec` is extended by the @@ -1670,7 +1833,7 @@ impl T> ExtendWith for ExtendFunc { } } -impl Vec { +impl Vec { /// Extend the vector by `n` values, using the given generator. fn extend_with>(&mut self, n: usize, mut value: E) { self.reserve(n); @@ -1730,7 +1893,7 @@ impl Drop for SetLenOnDrop<'_> { } } -impl Vec { +impl Vec { /// Removes consecutive repeated elements in the vector according to the /// [`PartialEq`] trait implementation. /// @@ -1752,7 +1915,7 @@ impl Vec { } } -impl Vec { +impl Vec { /// Removes the first instance of `item` from the vector if the item exists. /// /// # Examples @@ -1780,32 +1943,39 @@ impl Vec { //////////////////////////////////////////////////////////////////////////////// #[doc(hidden)] +#[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_elem(elem: T, n: usize) -> Vec { - ::from_elem(elem, n) + from_elem_in(elem, n, Global) +} + +#[doc(hidden)] +#[unstable(feature = "allocator_api", issue = "32838")] +pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { + >::from_elem(elem, n, alloc) } // Specialization trait used for Vec::from_elem -trait SpecFromElem: Sized { - fn from_elem(elem: Self, n: usize) -> Vec; +trait SpecFromElem: Sized { + fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; } -impl SpecFromElem for T { - default fn from_elem(elem: Self, n: usize) -> Vec { - let mut v = Vec::with_capacity(n); +impl SpecFromElem for T { + default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(n, alloc); v.extend_with(n, ExtendElement(elem)); v } } -impl SpecFromElem for u8 { +impl SpecFromElem for u8 { #[inline] - fn from_elem(elem: u8, n: usize) -> Vec { + fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { if elem == 0 { - return Vec { buf: RawVec::with_capacity_zeroed(n), len: n }; + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } unsafe { - let mut v = Vec::with_capacity(n); + let mut v = Vec::with_capacity_in(n, alloc); ptr::write_bytes(v.as_mut_ptr(), elem, n); v.set_len(n); v @@ -1813,13 +1983,13 @@ impl SpecFromElem for u8 { } } -impl SpecFromElem for T { +impl SpecFromElem for T { #[inline] - fn from_elem(elem: T, n: usize) -> Vec { + fn from_elem(elem: T, n: usize, alloc: A) -> Vec { if elem.is_zero() { - return Vec { buf: RawVec::with_capacity_zeroed(n), len: n }; + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } - let mut v = Vec::with_capacity(n); + let mut v = Vec::with_capacity_in(n, alloc); v.extend_with(n, ExtendElement(elem)); v } @@ -1904,10 +2074,10 @@ unsafe impl IsZero for Option> { //////////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Vec { +impl Clone for Vec { #[cfg(not(test))] - fn clone(&self) -> Vec { - <[T]>::to_vec(&**self) + fn clone(&self) -> Self { + <[T]>::to_vec_in(&**self, self.alloc().clone()) } // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is @@ -1915,17 +2085,13 @@ impl Clone for Vec { // `slice::to_vec` function which is only available with cfg(test) // NB see the slice::hack module in slice.rs for more information #[cfg(test)] - fn clone(&self) -> Vec { - crate::slice::to_vec(&**self) - } - - fn clone_from(&mut self, other: &Vec) { - other.as_slice().clone_into(self); + fn clone(&self) -> Self { + crate::slice::to_vec_in(&**self, self.alloc().clone()) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for Vec { +impl Hash for Vec { #[inline] fn hash(&self, state: &mut H) { Hash::hash(&**self, state) @@ -1937,7 +2103,7 @@ impl Hash for Vec { message = "vector indices are of type `usize` or ranges of `usize`", label = "vector indices are of type `usize` or ranges of `usize`" )] -impl> Index for Vec { +impl, A: AllocRef> Index for Vec { type Output = I::Output; #[inline] @@ -1951,7 +2117,7 @@ impl> Index for Vec { message = "vector indices are of type `usize` or ranges of `usize`", label = "vector indices are of type `usize` or ranges of `usize`" )] -impl> IndexMut for Vec { +impl, A: AllocRef> IndexMut for Vec { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { IndexMut::index_mut(&mut **self, index) @@ -1959,7 +2125,7 @@ impl> IndexMut for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for Vec { +impl ops::Deref for Vec { type Target = [T]; fn deref(&self) -> &[T] { @@ -1968,7 +2134,7 @@ impl ops::Deref for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::DerefMut for Vec { +impl ops::DerefMut for Vec { fn deref_mut(&mut self) -> &mut [T] { unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } } @@ -1977,15 +2143,15 @@ impl ops::DerefMut for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { #[inline] - fn from_iter>(iter: I) -> Vec { - >::from_iter(iter.into_iter()) + fn from_iter>(iter: I) -> Self { + >::from_iter(iter.into_iter(), Global) } } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Vec { +impl IntoIterator for Vec { type Item = T; - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Creates a consuming iterator, that is, one that moves each value out of /// the vector (from start to end). The vector cannot be used after calling @@ -2001,7 +2167,7 @@ impl IntoIterator for Vec { /// } /// ``` #[inline] - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> IntoIter { unsafe { let mut me = ManuallyDrop::new(self); let begin = me.as_mut_ptr(); @@ -2011,19 +2177,21 @@ impl IntoIterator for Vec { begin.add(me.len()) as *const T }; let cap = me.buf.capacity(); + let alloc = ptr::read(me.alloc()); IntoIter { buf: NonNull::new_unchecked(begin), phantom: PhantomData, cap, ptr: begin, end, + alloc, } } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a Vec { +impl<'a, T, A: AllocRef> IntoIterator for &'a Vec { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; @@ -2033,7 +2201,7 @@ impl<'a, T> IntoIterator for &'a Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a mut Vec { +impl<'a, T, A: AllocRef> IntoIterator for &'a mut Vec { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; @@ -2043,34 +2211,34 @@ impl<'a, T> IntoIterator for &'a mut Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for Vec { +impl Extend for Vec { #[inline] fn extend>(&mut self, iter: I) { - >::spec_extend(self, iter.into_iter()) + >::spec_extend(self, iter.into_iter()) } } // Specialization trait used for Vec::from_iter and Vec::extend -trait SpecExtend { - fn from_iter(iter: I) -> Self; +trait SpecExtend { + fn from_iter(iter: I, alloc: A) -> Self; fn spec_extend(&mut self, iter: I); } -impl SpecExtend for Vec +impl SpecExtend for Vec where I: Iterator, { - default fn from_iter(mut iterator: I) -> Self { + default fn from_iter(mut iterator: I, alloc: A) -> Self { // Unroll the first iteration, as the vector is going to be // expanded on this iteration in every case when the iterable is not // empty, but the loop in extend_desugared() is not going to see the // vector being full in the few subsequent loop iterations. // So we get better branch prediction. let mut vector = match iterator.next() { - None => return Vec::new(), + None => return Vec::new_in(alloc), Some(element) => { let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower.saturating_add(1)); + let mut vector = Vec::with_capacity_in(lower.saturating_add(1), alloc); unsafe { ptr::write(vector.as_mut_ptr(), element); vector.set_len(1); @@ -2078,7 +2246,7 @@ where vector } }; - as SpecExtend>::spec_extend(&mut vector, iterator); + as SpecExtend>::spec_extend(&mut vector, iterator); vector } @@ -2087,12 +2255,12 @@ where } } -impl SpecExtend for Vec +impl SpecExtend for Vec where I: TrustedLen, { - default fn from_iter(iterator: I) -> Self { - let mut vector = Vec::new(); + default fn from_iter(iterator: I, alloc: A) -> Self { + let mut vector = Vec::new_in(alloc); vector.spec_extend(iterator); vector } @@ -2126,18 +2294,18 @@ where } } -impl SpecExtend> for Vec { - fn from_iter(iterator: IntoIter) -> Self { +impl SpecExtend, A> for Vec { + fn from_iter(iterator: IntoIter, alloc: A) -> Self { // A common case is passing a vector into a function which immediately // re-collects into a vector. We can short circuit this if the IntoIter // has not been advanced at all. if iterator.buf.as_ptr() as *const _ == iterator.ptr { unsafe { let it = ManuallyDrop::new(iterator); - Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap) + Vec::from_raw_parts_in(it.buf.as_ptr(), it.len(), it.cap, alloc) } } else { - let mut vector = Vec::new(); + let mut vector = Vec::new_in(alloc); vector.spec_extend(iterator); vector } @@ -2151,13 +2319,13 @@ impl SpecExtend> for Vec { } } -impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec +impl<'a, T: 'a, I, A: AllocRef> SpecExtend<&'a T, I, A> for Vec where I: Iterator, T: Clone, { - default fn from_iter(iterator: I) -> Self { - SpecExtend::from_iter(iterator.cloned()) + default fn from_iter(iterator: I, alloc: A) -> Self { + SpecExtend::from_iter(iterator.cloned(), alloc) } default fn spec_extend(&mut self, iterator: I) { @@ -2165,7 +2333,7 @@ where } } -impl<'a, T: 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec +impl<'a, T: 'a, A: AllocRef> SpecExtend<&'a T, slice::Iter<'a, T>, A> for Vec where T: Copy, { @@ -2181,7 +2349,7 @@ where } } -impl Vec { +impl Vec { fn extend_desugared>(&mut self, mut iterator: I) { // This is the case for a general iterator. // @@ -2239,7 +2407,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "vec_splice", since = "1.21.0")] - pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter> + pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> where R: RangeBounds, I: IntoIterator, @@ -2293,7 +2461,7 @@ impl Vec { /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); /// ``` #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] - pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F> + pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -2315,7 +2483,7 @@ impl Vec { /// /// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { +impl<'a, T: 'a + Copy, A: AllocRef> Extend<&'a T> for Vec { fn extend>(&mut self, iter: I) { self.spec_extend(iter.into_iter()) } @@ -2324,9 +2492,9 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { macro_rules! __impl_slice_eq1 { ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq<$rhs> for $lhs + impl PartialEq<$rhs> for $lhs where - A: PartialEq, + T: PartialEq, $($constraints)* { #[inline] @@ -2337,14 +2505,14 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { [] Vec, Vec, } -__impl_slice_eq1! { [] Vec, &[B], } -__impl_slice_eq1! { [] Vec, &mut [B], } -__impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } -__impl_slice_eq1! { [const N: usize] Vec, [B; N], [B; N]: LengthAtMost32 } -__impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [A1: AllocRef, A2: AllocRef] Vec, Vec, } +__impl_slice_eq1! { [A: AllocRef] Vec, &[U], } +__impl_slice_eq1! { [A: AllocRef] Vec, &mut [U], } +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U], T: Clone } +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U], T: Clone } +__impl_slice_eq1! { [A: AllocRef] Cow<'_, [T]>, Vec, T: Clone } +__impl_slice_eq1! { [A: AllocRef, const N: usize] Vec, [U; N], [U; N]: LengthAtMost32 } +__impl_slice_eq1! { [A: AllocRef, const N: usize] Vec, &[U; N], [U; N]: LengthAtMost32 } // NOTE: some less important impls are omitted to reduce code bloat // FIXME(Centril): Reconsider this? @@ -2355,27 +2523,27 @@ __impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } /// Implements comparison of vectors, lexicographically. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Vec { +impl PartialOrd> for Vec { #[inline] - fn partial_cmp(&self, other: &Vec) -> Option { + fn partial_cmp(&self, other: &Vec) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Vec {} +impl Eq for Vec {} /// Implements ordering of vectors, lexicographically. #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Vec { +impl Ord for Vec { #[inline] - fn cmp(&self, other: &Vec) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for Vec { +unsafe impl<#[may_dangle] T, A: AllocRef> Drop for Vec { fn drop(&mut self) { unsafe { // use drop for [T] @@ -2390,41 +2558,41 @@ unsafe impl<#[may_dangle] T> Drop for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Vec { /// Creates an empty `Vec`. - fn default() -> Vec { + fn default() -> Self { Vec::new() } } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Vec { +impl fmt::Debug for Vec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef> for Vec { - fn as_ref(&self) -> &Vec { +impl AsRef for Vec { + fn as_ref(&self) -> &Self { self } } #[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut> for Vec { - fn as_mut(&mut self) -> &mut Vec { +impl AsMut for Vec { + fn as_mut(&mut self) -> &mut Self { self } } #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[T]> for Vec { +impl AsRef<[T]> for Vec { fn as_ref(&self) -> &[T] { self } } #[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut<[T]> for Vec { +impl AsMut<[T]> for Vec { fn as_mut(&mut self) -> &mut [T] { self } @@ -2433,11 +2601,11 @@ impl AsMut<[T]> for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl From<&[T]> for Vec { #[cfg(not(test))] - fn from(s: &[T]) -> Vec { + fn from(s: &[T]) -> Self { s.to_vec() } #[cfg(test)] - fn from(s: &[T]) -> Vec { + fn from(s: &[T]) -> Self { crate::slice::to_vec(s) } } @@ -2445,11 +2613,11 @@ impl From<&[T]> for Vec { #[stable(feature = "vec_from_mut", since = "1.19.0")] impl From<&mut [T]> for Vec { #[cfg(not(test))] - fn from(s: &mut [T]) -> Vec { + fn from(s: &mut [T]) -> Self { s.to_vec() } #[cfg(test)] - fn from(s: &mut [T]) -> Vec { + fn from(s: &mut [T]) -> Self { crate::slice::to_vec(s) } } @@ -2460,21 +2628,21 @@ where [T; N]: LengthAtMost32, { #[cfg(not(test))] - fn from(s: [T; N]) -> Vec { + fn from(s: [T; N]) -> Self { <[T]>::into_vec(box s) } #[cfg(test)] - fn from(s: [T; N]) -> Vec { - crate::slice::into_vec(box s) + fn from(s: [T; N]) -> Self { + crate::slice::into_vec(Box::new(s)) } } #[stable(feature = "vec_from_cow_slice", since = "1.14.0")] impl<'a, T> From> for Vec where - [T]: ToOwned>, + T: Clone, { - fn from(s: Cow<'a, [T]>) -> Vec { + fn from(s: Cow<'a, [T]>) -> Self { s.into_owned() } } @@ -2482,8 +2650,8 @@ where // note: test pulls in libstd, which causes errors here #[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] -impl From> for Vec { - fn from(s: Box<[T]>) -> Vec { +impl From> for Vec { + fn from(s: Box<[T], A>) -> Self { s.into_vec() } } @@ -2491,16 +2659,16 @@ impl From> for Vec { // note: test pulls in libstd, which causes errors here #[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] -impl From> for Box<[T]> { - fn from(v: Vec) -> Box<[T]> { +impl From> for Box<[T], A> { + fn from(v: Vec) -> Box<[T], A> { v.into_boxed_slice() } } #[stable(feature = "rust1", since = "1.0.0")] impl From<&str> for Vec { - fn from(s: &str) -> Vec { - From::from(s.as_bytes()) + fn from(s: &str) -> Self { + Self::from(s.as_bytes()) } } @@ -2523,8 +2691,8 @@ impl<'a, T: Clone> From> for Cow<'a, [T]> { } #[stable(feature = "cow_from_vec_ref", since = "1.28.0")] -impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { - fn from(v: &'a Vec) -> Cow<'a, [T]> { +impl<'a, T: Clone, A: AllocRef> From<&'a Vec> for Cow<'a, [T]> { + fn from(v: &'a Vec) -> Cow<'a, [T]> { Cow::Borrowed(v.as_slice()) } } @@ -2551,22 +2719,23 @@ where /// [`Vec`]: struct.Vec.html /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { +pub struct IntoIter { buf: NonNull, phantom: PhantomData, cap: usize, ptr: *const T, end: *const T, + alloc: A, } #[stable(feature = "vec_intoiter_debug", since = "1.13.0")] -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.as_slice()).finish() } } -impl IntoIter { +impl IntoIter { /// Returns the remaining items of this iterator as a slice. /// /// # Examples @@ -2607,12 +2776,12 @@ impl IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for IntoIter {} +unsafe impl Send for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for IntoIter {} +unsafe impl Sync for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; #[inline] @@ -2656,7 +2825,7 @@ impl Iterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { unsafe { @@ -2680,34 +2849,43 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { +impl ExactSizeIterator for IntoIter { fn is_empty(&self) -> bool { self.ptr == self.end } } #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIter {} +unsafe impl TrustedLen for IntoIter {} #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] -impl Clone for IntoIter { - fn clone(&self) -> IntoIter { - self.as_slice().to_owned().into_iter() +impl Clone for IntoIter { + #[cfg(not(test))] + fn clone(&self) -> Self { + self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + } + + #[cfg(test)] + fn clone(&self) -> Self { + crate::slice::to_vec_in(self.as_slice(), self.alloc.clone()).into_iter() } } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for IntoIter { +unsafe impl<#[may_dangle] T, A: AllocRef> Drop for IntoIter { fn drop(&mut self) { - struct DropGuard<'a, T>(&'a mut IntoIter); + struct DropGuard<'a, T, A: AllocRef>(&'a mut IntoIter); - impl Drop for DropGuard<'_, T> { + impl Drop for DropGuard<'_, T, A> { fn drop(&mut self) { - // RawVec handles deallocation - let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) }; + unsafe { + // RawVec handles deallocation + let alloc = ptr::read(&self.0.alloc); + let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + } } } @@ -2727,24 +2905,24 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter { /// [`drain`]: struct.Vec.html#method.drain /// [`Vec`]: struct.Vec.html #[stable(feature = "drain", since = "1.6.0")] -pub struct Drain<'a, T: 'a> { +pub struct Drain<'a, T: 'a, A: 'a + AllocRef = Global> { /// Index of tail to preserve tail_start: usize, /// Length of tail tail_len: usize, /// Current remaining range to remove iter: slice::Iter<'a, T>, - vec: NonNull>, + vec: NonNull>, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T> { +impl fmt::Debug for Drain<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() } } -impl<'a, T> Drain<'a, T> { +impl<'a, T, A: AllocRef> Drain<'a, T, A> { /// Returns the remaining items of this iterator as a slice. /// /// # Examples @@ -2764,12 +2942,12 @@ impl<'a, T> Drain<'a, T> { } #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T> {} +unsafe impl Sync for Drain<'_, T, A> {} #[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T> {} +unsafe impl Send for Drain<'_, T, A> {} #[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T> { +impl Iterator for Drain<'_, T, A> { type Item = T; #[inline] @@ -2783,7 +2961,7 @@ impl Iterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T> { +impl DoubleEndedIterator for Drain<'_, T, A> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) @@ -2791,13 +2969,13 @@ impl DoubleEndedIterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T> { +impl Drop for Drain<'_, T, A> { fn drop(&mut self) { /// Continues dropping the remaining elements in the `Drain`, then moves back the /// un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); + struct DropGuard<'r, 'a, T, A: AllocRef>(&'r mut Drain<'a, T, A>); - impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { + impl<'r, 'a, T, A: AllocRef> Drop for DropGuard<'r, 'a, T, A> { fn drop(&mut self) { // Continue the same loop we have below. If the loop already finished, this does // nothing. @@ -2833,17 +3011,17 @@ impl Drop for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T> { +impl ExactSizeIterator for Drain<'_, T, A> { fn is_empty(&self) -> bool { self.iter.is_empty() } } #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for Drain<'_, T> {} +unsafe impl TrustedLen for Drain<'_, T, A> {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T> {} +impl FusedIterator for Drain<'_, T, A> {} /// A splicing iterator for `Vec`. /// @@ -2854,13 +3032,13 @@ impl FusedIterator for Drain<'_, T> {} /// [`Vec`]: struct.Vec.html #[derive(Debug)] #[stable(feature = "vec_splice", since = "1.21.0")] -pub struct Splice<'a, I: Iterator + 'a> { - drain: Drain<'a, I::Item>, +pub struct Splice<'a, I: Iterator + 'a, A: AllocRef = Global> { + drain: Drain<'a, I::Item, A>, replace_with: I, } #[stable(feature = "vec_splice", since = "1.21.0")] -impl Iterator for Splice<'_, I> { +impl Iterator for Splice<'_, I, A> { type Item = I::Item; fn next(&mut self) -> Option { @@ -2873,17 +3051,17 @@ impl Iterator for Splice<'_, I> { } #[stable(feature = "vec_splice", since = "1.21.0")] -impl DoubleEndedIterator for Splice<'_, I> { +impl DoubleEndedIterator for Splice<'_, I, A> { fn next_back(&mut self) -> Option { self.drain.next_back() } } #[stable(feature = "vec_splice", since = "1.21.0")] -impl ExactSizeIterator for Splice<'_, I> {} +impl ExactSizeIterator for Splice<'_, I, A> {} #[stable(feature = "vec_splice", since = "1.21.0")] -impl Drop for Splice<'_, I> { +impl Drop for Splice<'_, I, A> { fn drop(&mut self) { self.drain.by_ref().for_each(drop); @@ -2924,7 +3102,7 @@ impl Drop for Splice<'_, I> { } /// Private helper methods for `Splice::drop` -impl Drain<'_, T> { +impl Drain<'_, T, A> { /// The range from `self.vec.len` to `self.tail_start` contains elements /// that have been moved out. /// Fill that range as much as possible with new elements from the `replace_with` iterator. @@ -2964,11 +3142,11 @@ impl Drain<'_, T> { /// An iterator produced by calling `drain_filter` on Vec. #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[derive(Debug)] -pub struct DrainFilter<'a, T, F> +pub struct DrainFilter<'a, T, F, A: AllocRef = Global> where F: FnMut(&mut T) -> bool, { - vec: &'a mut Vec, + vec: &'a mut Vec, /// The index of the item that will be inspected by the next call to `next`. idx: usize, /// The number of items that have been drained (removed) thus far. @@ -2986,7 +3164,7 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F> +impl Iterator for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -3024,19 +3202,19 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F> +impl Drop for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F> + struct BackshiftOnDrop<'a, 'b, T, F, A: AllocRef> where F: FnMut(&mut T) -> bool, { - drain: &'b mut DrainFilter<'a, T, F>, + drain: &'b mut DrainFilter<'a, T, F, A>, } - impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F> + impl<'a, 'b, T, F, A: AllocRef> Drop for BackshiftOnDrop<'a, 'b, T, F, A> where F: FnMut(&mut T) -> bool, { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index e6da7426eb4af..93169ad32c92d 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -4,6 +4,7 @@ use self::Entry::*; use hashbrown::hash_map as base; +use crate::alloc::{AllocRef, Global}; use crate::borrow::Borrow; use crate::cell::Cell; use crate::collections::TryReserveError; @@ -11,6 +12,7 @@ use crate::fmt::{self, Debug}; #[allow(deprecated)] use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; use crate::iter::{FromIterator, FusedIterator}; +use crate::marker::PhantomData; use crate::ops::Index; use crate::sys; @@ -200,8 +202,9 @@ use crate::sys; #[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")] #[stable(feature = "rust1", since = "1.0.0")] -pub struct HashMap { +pub struct HashMap { base: base::HashMap, + alloc: PhantomData, } impl HashMap { @@ -264,7 +267,7 @@ impl HashMap { #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_hasher(hash_builder: S) -> HashMap { - HashMap { base: base::HashMap::with_hasher(hash_builder) } + HashMap { base: base::HashMap::with_hasher(hash_builder), alloc: PhantomData } } /// Creates an empty `HashMap` with the specified capacity, using `hash_builder` @@ -291,7 +294,10 @@ impl HashMap { #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap { - HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) } + HashMap { + base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder), + alloc: PhantomData, + } } /// Returns the number of elements the map can hold without reallocating. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index c1a57f2ce6129..ff0b84a9fd77a 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1,3 +1,4 @@ +use crate::alloc::{AllocRef, Global}; use crate::borrow::Borrow; use crate::collections::TryReserveError; use crate::fmt; @@ -107,8 +108,8 @@ use super::map::{self, HashMap, Keys, RandomState}; #[derive(Clone)] #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")] #[stable(feature = "rust1", since = "1.0.0")] -pub struct HashSet { - map: HashMap, +pub struct HashSet { + map: HashMap, } impl HashSet { diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 0a4802fb2c80d..5b002362b7d9e 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1,8 +1,10 @@ +use crate::alloc::{AllocRef, Global}; use crate::ascii; use crate::borrow::{Borrow, Cow}; use crate::cmp::Ordering; use crate::error::Error; use crate::fmt::{self, Write}; +use crate::hash; use crate::io; use crate::mem; use crate::memchr; @@ -114,13 +116,55 @@ use crate::sys; /// of `CString` instances can lead to invalid memory accesses, memory leaks, /// and other memory errors. -#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct CString { +pub struct CString { // Invariant 1: the slice ends with a zero byte and has a length of at least one. // Invariant 2: the slice contains only one zero byte. // Improper usage of unsafe function can break Invariant 2, but not Invariant 1. - inner: Box<[u8]>, + inner: Box<[u8], A>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for CString { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.inner.eq(&other.inner) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for CString {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for CString { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.inner.partial_cmp(&other.inner) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for CString { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.inner.cmp(&other.inner) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for CString { + #[inline] + fn hash(&self, state: &mut H) { + self.inner.hash(state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for CString { + #[inline] + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } } /// Representation of a borrowed C string. @@ -638,7 +682,7 @@ impl CString { // memory-unsafe code from working by accident. Inline // to prevent LLVM from optimizing it away in debug builds. #[stable(feature = "cstring_drop", since = "1.13.0")] -impl Drop for CString { +impl Drop for CString { #[inline] fn drop(&mut self) { unsafe { diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 4fde33169733e..fbc8374478a5c 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -1,3 +1,4 @@ +use crate::alloc::{AllocRef, Global}; use crate::borrow::{Borrow, Cow}; use crate::cmp; use crate::fmt; @@ -75,10 +76,17 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// [`push`]: #method.push /// [`as_os_str`]: #method.as_os_str /// [conversions]: index.html#conversions -#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct OsString { - inner: Buf, +pub struct OsString { + inner: Buf, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for OsString { + #[inline] + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } } /// Borrowed reference to an OS string (see [`OsString`]). diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 173d6d1cfa7ef..50d6ea3484b14 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -69,6 +69,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::alloc::{AllocRef, Global}; use crate::borrow::{Borrow, Cow}; use crate::cmp; use crate::error::Error; @@ -1079,7 +1080,6 @@ impl FusedIterator for Ancestors<'_> {} /// ``` /// /// Which method works best depends on what kind of situation you're in. -#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] // FIXME: // `PathBuf::as_mut_vec` current implementation relies @@ -1087,8 +1087,16 @@ impl FusedIterator for Ancestors<'_> {} // When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`. // Anyway, `PathBuf` representation and layout are considered implementation detail, are // not documented and must not be relied upon. -pub struct PathBuf { - inner: OsString, +pub struct PathBuf { + inner: OsString, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for PathBuf { + #[inline] + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } } impl PathBuf { diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index 2f5fc72ab44c2..c30eb8ea99ed8 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -1,16 +1,33 @@ +use crate::alloc::{AllocRef, Global}; /// The underlying OsString/OsStr implementation on Windows is a /// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. use crate::borrow::Cow; use crate::fmt; +use crate::hash; use crate::mem; use crate::rc::Rc; use crate::sync::Arc; use crate::sys_common::wtf8::{Wtf8, Wtf8Buf}; use crate::sys_common::{AsInner, FromInner, IntoInner}; -#[derive(Clone, Hash)] -pub struct Buf { - pub inner: Wtf8Buf, +pub struct Buf { + pub inner: Wtf8Buf, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for Buf { + #[inline] + fn hash(&self, state: &mut H) { + self.inner.hash(state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Buf { + #[inline] + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } } impl IntoInner for Buf { diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index 984c032e2a388..f68735e5794fc 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -1,9 +1,11 @@ //! The underlying OsString/OsStr implementation on Unix and many other //! systems: just a `Vec`/`[u8]`. +use crate::alloc::{AllocRef, Global}; use crate::borrow::Cow; use crate::ffi::{OsStr, OsString}; use crate::fmt; +use crate::hash; use crate::mem; use crate::rc::Rc; use crate::str; @@ -13,9 +15,22 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; use core::str::lossy::Utf8Lossy; -#[derive(Clone, Hash)] -pub(crate) struct Buf { - pub inner: Vec, +pub(crate) struct Buf { + pub inner: Vec, +} + +impl Clone for Buf { + #[inline] + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } +} + +impl hash::Hash for Buf { + #[inline] + fn hash(&self, state: &mut H) { + self.inner.hash(state) + } } // FIXME: diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index a98407da44850..a8bbe0ea88fd0 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -17,8 +17,10 @@ use core::str::next_code_point; +use crate::alloc::{AllocRef, Global}; use crate::borrow::Cow; use crate::char; +use crate::cmp::Ordering; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::iter::FromIterator; @@ -110,9 +112,43 @@ impl CodePoint { /// /// Similar to `String`, but can additionally contain surrogate code points /// if they’re not in a surrogate pair. -#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] -pub struct Wtf8Buf { - bytes: Vec, +pub struct Wtf8Buf { + bytes: Vec, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Wtf8Buf { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.bytes.eq(&other.bytes) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Wtf8Buf {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Wtf8Buf { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + self.bytes.partial_cmp(&other.bytes) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Wtf8Buf { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + self.bytes.cmp(&other.bytes) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Wtf8Buf { + #[inline] + fn clone(&self) -> Self { + Self { bytes: self.bytes.clone() } + } } impl ops::Deref for Wtf8Buf { diff --git a/src/test/debuginfo/pretty-huge-vec.rs b/src/test/debuginfo/pretty-huge-vec.rs index 2e3386b7a360e..e7f8249d96dd1 100644 --- a/src/test/debuginfo/pretty-huge-vec.rs +++ b/src/test/debuginfo/pretty-huge-vec.rs @@ -10,22 +10,22 @@ // gdb-command: run // gdb-command: print vec -// gdb-check:$1 = Vec(len: 1000000000, cap: 1000000000) = {[...]...} +// gdb-check:$1 = Vec(len: 1000000000, cap: 1000000000) = {[...]...} // gdb-command: print slice // gdb-check:$2 = &[u8](len: 1000000000) = {[...]...} - #![allow(unused_variables)] fn main() { - // Vec let mut vec: Vec = Vec::with_capacity(1_000_000_000); - unsafe{ vec.set_len(1_000_000_000) } + unsafe { vec.set_len(1_000_000_000) } let slice = &vec[..]; zzz(); // #break } -fn zzz() { () } +fn zzz() { + () +} diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs index 1f4ff00100a23..7893aea47f871 100644 --- a/src/test/debuginfo/pretty-std-collections.rs +++ b/src/test/debuginfo/pretty-std-collections.rs @@ -15,30 +15,30 @@ // gdb-command: run // gdb-command: print btree_set -// gdb-check:$1 = BTreeSet(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} +// gdb-check:$1 = BTreeSet(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} // gdb-command: print empty_btree_set -// gdb-check:$2 = BTreeSet(len: 0) +// gdb-check:$2 = BTreeSet(len: 0) // gdb-command: print btree_map -// gdb-check:$3 = BTreeMap(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14} +// gdb-check:$3 = BTreeMap(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14} // gdb-command: print empty_btree_map -// gdb-check:$4 = BTreeMap(len: 0) +// gdb-check:$4 = BTreeMap(len: 0) // gdb-command: print option_btree_map -// gdb-check:$5 = BTreeMap>(len: 2) = {[false] = [...], [true] = [...]} +// gdb-check:$5 = BTreeMap, alloc::alloc::Global>(len: 2) = {[false] = [...], [true] = [...]} // (abbreviated because both values vary wildly over gdb versions and/or linux distributions) // gdb-command: print nasty_btree_map -// gdb-check:$6 = BTreeMap(len: 15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]} +// gdb-check:$6 = BTreeMap(len: 15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]} // (abbreviated because it's boring but we need enough elements to include internal nodes) // gdb-command: print vec_deque -// gdb-check:$7 = VecDeque(len: 3, cap: 8) = {5, 3, 7} +// gdb-check:$7 = VecDeque(len: 3, cap: 8) = {5, 3, 7} // gdb-command: print vec_deque2 -// gdb-check:$8 = VecDeque(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8} +// gdb-check:$8 = VecDeque(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8} #![allow(unused_variables)] use std::collections::BTreeMap; diff --git a/src/test/debuginfo/pretty-uninitialized-vec.rs b/src/test/debuginfo/pretty-uninitialized-vec.rs index 37aae65d42b69..7ef40a9a93d3c 100644 --- a/src/test/debuginfo/pretty-uninitialized-vec.rs +++ b/src/test/debuginfo/pretty-uninitialized-vec.rs @@ -10,17 +10,16 @@ // gdb-command: run // gdb-command: print vec -// gdb-check:$1 = Vec(len: [...], cap: [...])[...] - +// gdb-check:$1 = Vec(len: [...], cap: [...])[...] #![allow(unused_variables)] fn main() { - let vec; zzz(); // #break vec = vec![0]; - } -fn zzz() { () } +fn zzz() { + () +} diff --git a/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff index 607dd468e598b..833aaadeaa923 100644 --- a/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff +++ b/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff @@ -69,7 +69,7 @@ - bb4 (cleanup): { - _3 = const alloc::alloc::box_free::>(move (_2.0: std::ptr::Unique>)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // ty::Const -- // + ty: unsafe fn(std::ptr::Unique>) {alloc::alloc::box_free::>} +- // + ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>} - // + val: Value(Scalar()) - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 diff --git a/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff index e83ca36706af7..1213dd844d393 100644 --- a/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff +++ b/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff @@ -67,13 +67,13 @@ - } - - bb4 (cleanup): { -- _3 = const alloc::alloc::box_free::>(move (_2.0: std::ptr::Unique>)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- _3 = const alloc::alloc::box_free::, std::alloc::Global>(move (_2.0: std::ptr::Unique>), move (_2.1: std::alloc::Global)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // ty::Const -- // + ty: unsafe fn(std::ptr::Unique>) {alloc::alloc::box_free::>} +- // + ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>} - // + val: Value(Scalar()) - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 -- // + literal: Const { ty: unsafe fn(std::ptr::Unique>) {alloc::alloc::box_free::>}, val: Value(Scalar()) } +- // + literal: Const { ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } } } diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index 6f4a48c83c05b..ef42f1b090e40 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -4,7 +4,7 @@ extern crate impl_trait_aux; // @has impl_trait/fn.func.html -// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)" +// @has - '//pre[@class="rust fn"]' "pub fn func<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func; @@ -31,7 +31,7 @@ pub use impl_trait_aux::func4; pub use impl_trait_aux::async_fn; // @has impl_trait/struct.Foo.html -// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" +// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//code[@id="method.v"]' 'where' pub use impl_trait_aux::Foo; diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 3f6702da2a4a2..6059d1142a14b 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -131,7 +131,7 @@ LL | type Ty = Vec<[u8]>; | ::: $SRC_DIR/liballoc/vec.rs:LL:COL | -LL | pub struct Vec { +LL | pub struct Vec { | - required by this bound in `std::vec::Vec` | = help: the trait `std::marker::Sized` is not implemented for `[u8]` diff --git a/src/test/ui/bad/bad-const-type.stderr b/src/test/ui/bad/bad-const-type.stderr index f667779fab58f..d3da6bd771897 100644 --- a/src/test/ui/bad/bad-const-type.stderr +++ b/src/test/ui/bad/bad-const-type.stderr @@ -6,6 +6,9 @@ LL | static i: String = 10; | | | expected struct `std::string::String`, found integer | help: try using a conversion method: `10.to_string()` + | + = note: expected struct `std::string::String` + found type `{integer}` error: aborting due to previous error diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 5c169af4eb8ae..a9bfe8e9adab1 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -17,7 +17,7 @@ LL | let x: Vec = Vec::new(); | ::: $SRC_DIR/liballoc/vec.rs:LL:COL | -LL | pub struct Vec { +LL | pub struct Vec { | - required by this bound in `std::vec::Vec` | = help: the trait `std::marker::Sized` is not implemented for `dyn Trait` diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index b45f2a6282136..87be29ab26fe3 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -8,6 +8,9 @@ LL | fn f() -> String { LL | 0u8; LL | "bla".to_string(); | - help: consider removing this semicolon + | + = note: expected struct `std::string::String` + found unit type `()` error[E0308]: mismatched types --> $DIR/consider-removing-last-semi.rs:6:11 @@ -19,6 +22,9 @@ LL | fn g() -> String { LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: consider removing this semicolon + | + = note: expected struct `std::string::String` + found unit type `()` error: aborting due to 2 previous errors diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 707d24cd6ab23..78bdba4d34341 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -8,6 +8,9 @@ LL | fn foo() -> String { ... LL | ; | - help: consider removing this semicolon + | + = note: expected struct `std::string::String` + found unit type `()` error[E0308]: mismatched types --> $DIR/issue-13428.rs:11:13 @@ -19,6 +22,9 @@ LL | fn bar() -> String { LL | "foobar".to_string() LL | ; | - help: consider removing this semicolon + | + = note: expected struct `std::string::String` + found unit type `()` error: aborting due to 2 previous errors diff --git a/src/test/ui/box-into-boxed-slice-fail.stderr b/src/test/ui/box-into-boxed-slice-fail.stderr index dfc4999958a57..476e372faf385 100644 --- a/src/test/ui/box-into-boxed-slice-fail.stderr +++ b/src/test/ui/box-into-boxed-slice-fail.stderr @@ -6,7 +6,7 @@ LL | let _ = Box::into_boxed_slice(boxed_slice); | = help: the trait `std::marker::Sized` is not implemented for `[u8]` = note: to learn more, visit - = note: required by `std::boxed::Box::::into_boxed_slice` + = note: required by `std::boxed::Box::::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:8:13 @@ -26,7 +26,7 @@ LL | let _ = Box::into_boxed_slice(boxed_trait); | = help: the trait `std::marker::Sized` is not implemented for `dyn std::fmt::Debug` = note: to learn more, visit - = note: required by `std::boxed::Box::::into_boxed_slice` + = note: required by `std::boxed::Box::::into_boxed_slice` error[E0277]: the size for values of type `dyn std::fmt::Debug` cannot be known at compilation time --> $DIR/box-into-boxed-slice-fail.rs:12:13 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 bd1a933b7668e..7960eab0b0d59 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` 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 Remote for Box> { - | ^^^^^^^^^^^^^^^^^^^---------- - | | | - | | `std::rc::Rc` is not defined in the current crate + | ^^^^^^^^------^^^^^---------- + | | | | + | | | `std::rc::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 3ca40e007292c..cd12e2fe441ec 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> for i32 { | | | | | | | `i32` is not defined in the current crate | | `std::string::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>> for f64 { | | | | | | | `f64` is not defined in the current crate | | `std::rc::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 Remote1>> for f32 { | | | | | | | `f32` is not defined in the current crate | | `std::rc::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/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr index b3621a27acb71..56f52165609fa 100644 --- a/src/test/ui/conversion-methods.stderr +++ b/src/test/ui/conversion-methods.stderr @@ -7,6 +7,9 @@ LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—"; | | expected struct `std::string::String`, found `&str` | | help: try using a conversion method: `"'Tis a fond Ambush—".to_string()` | expected due to this + | + = note: expected struct `std::string::String` + found reference `&'static str` error[E0308]: mismatched types --> $DIR/conversion-methods.rs:6:40 @@ -17,6 +20,9 @@ LL | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise"); | | expected struct `std::path::PathBuf`, found `&std::path::Path` | | help: try using a conversion method: `Path::new("/ern/her/own/surprise").to_path_buf()` | expected due to this + | + = note: expected struct `std::path::PathBuf` + found reference `&std::path::Path` error[E0308]: mismatched types --> $DIR/conversion-methods.rs:9:40 @@ -27,6 +33,9 @@ LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we sugge | | expected struct `std::string::String`, found integer | | help: try using a conversion method: `2.to_string()` | expected due to this + | + = note: expected struct `std::string::String` + found type `{integer}` error[E0308]: mismatched types --> $DIR/conversion-methods.rs:12:47 diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 89fd7aae3bea0..ab71540923219 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -4,8 +4,11 @@ error[E0308]: mismatched types LL | foo(s); | ^ | | - | expected struct `std::string::String`, found `&std::string::String` + | expected struct `std::string::String`, found reference | help: try using a conversion method: `s.to_string()` + | + = note: expected struct `std::string::String` + found reference `&std::string::String` error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:14:10 @@ -22,8 +25,11 @@ error[E0308]: mismatched types LL | foo(&"aaa".to_owned()); | ^^^^^^^^^^^^^^^^^ | | - | expected struct `std::string::String`, found `&std::string::String` + | expected struct `std::string::String`, found reference | help: consider removing the borrow: `"aaa".to_owned()` + | + = note: expected struct `std::string::String` + found reference `&std::string::String` error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:32:9 @@ -31,8 +37,11 @@ error[E0308]: mismatched types LL | foo(&mut "aaa".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ | | - | expected struct `std::string::String`, found `&mut std::string::String` + | expected struct `std::string::String`, found mutable reference | help: consider removing the borrow: `"aaa".to_owned()` + | + = note: expected struct `std::string::String` + found mutable reference `&mut std::string::String` error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:2:20 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 3e0c71e907481..1ae01d0b8e5c2 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 for Box { | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `alloc`: - - impl std::convert::AsRef for std::boxed::Box - where T: ?Sized; + - impl std::convert::AsRef for std::boxed::Box + where A: std::alloc::AllocRef, T: ?Sized; error[E0119]: conflicting implementations of trait `std::convert::From` for type `S`: --> $DIR/conflict-with-std.rs:12:1 diff --git a/src/test/ui/estr-subtyping.stderr b/src/test/ui/estr-subtyping.stderr index e5dbab6441cb9..e9efa14ca97b6 100644 --- a/src/test/ui/estr-subtyping.stderr +++ b/src/test/ui/estr-subtyping.stderr @@ -6,6 +6,9 @@ LL | wants_uniq(x); | | | expected struct `std::string::String`, found `&str` | help: try using a conversion method: `x.to_string()` + | + = note: expected struct `std::string::String` + found reference `&str` error: aborting due to previous error 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-20433.stderr b/src/test/ui/issues/issue-20433.stderr index 1dab637e489db..ca33a3b336f79 100644 --- a/src/test/ui/issues/issue-20433.stderr +++ b/src/test/ui/issues/issue-20433.stderr @@ -6,7 +6,7 @@ LL | fn iceman(c: Vec<[i32]>) {} | ::: $SRC_DIR/liballoc/vec.rs:LL:COL | -LL | pub struct Vec { +LL | pub struct Vec { | - required by this bound in `std::vec::Vec` | = help: the trait `std::marker::Sized` is not implemented for `[i32]` diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr index 6b2a5d76243d8..4173473c52fd8 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 `std::boxed::Box` diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index d082e0a6b5dc4..481c791661ca6 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 - where T: ?Sized; - = note: downstream crates may implement trait `A` for type `std::boxed::Box<_>` + - impl std::ops::Drop for std::boxed::Box + where A: std::alloc::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/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs index bbfdd9c538946..c65622ad7aed0 100644 --- a/src/test/ui/issues/issue-53348.rs +++ b/src/test/ui/issues/issue-53348.rs @@ -3,13 +3,13 @@ fn main() { let v2 = Vec::new(); - v.into_iter().map(|s|s.to_owned()).collect::>(); + v.into_iter().map(|s| s.to_owned()).collect::>(); let mut a = String::new(); for i in v { a = *i.to_string(); - //~^ ERROR mismatched types - //~| NOTE expected struct `std::string::String`, found `str` + //~^ ERROR mismatched types [E0308] + //~| expected struct `std::string::String`, found `str` v2.push(a); } } diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr index 433fe40ea03ce..a3cd1767e219b 100644 --- a/src/test/ui/issues/issue-53348.stderr +++ b/src/test/ui/issues/issue-53348.stderr @@ -3,6 +3,9 @@ error[E0308]: mismatched types | LL | a = *i.to_string(); | ^^^^^^^^^^^^^^ expected struct `std::string::String`, found `str` + | + = note: expected struct `std::string::String` + found type `str` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-53692.stderr b/src/test/ui/issues/issue-53692.stderr index b83fb346b14ef..a59a235fca2a6 100644 --- a/src/test/ui/issues/issue-53692.stderr +++ b/src/test/ui/issues/issue-53692.stderr @@ -20,6 +20,9 @@ LL | let string: String = s.clone(); | | expected struct `std::string::String`, found `&str` | | help: try using a conversion method: `s.to_string()` | expected due to this + | + = note: expected struct `std::string::String` + found reference `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-61106.stderr b/src/test/ui/issues/issue-61106.stderr index 163aa816ab789..308eac1109241 100644 --- a/src/test/ui/issues/issue-61106.stderr +++ b/src/test/ui/issues/issue-61106.stderr @@ -6,6 +6,9 @@ LL | foo(x.clone()); | | | expected `&str`, found struct `std::string::String` | help: consider borrowing here: `&x` + | + = note: expected reference `&str` + found struct `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json-bom-plus-crlf-multifile.stderr index 8d3c316e467bd..ebe81cb894c48 100644 --- a/src/test/ui/json-bom-plus-crlf-multifile.stderr +++ b/src/test/ui/json-bom-plus-crlf-multifile.stderr @@ -16,7 +16,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types "} {"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -36,7 +37,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types "} {"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -56,7 +58,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types "} {"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -76,7 +79,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` +found unit type `()`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr index ed6b583f329d6..ffb418a402349 100644 --- a/src/test/ui/json-bom-plus-crlf.stderr +++ b/src/test/ui/json-bom-plus-crlf.stderr @@ -16,7 +16,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types "} {"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -36,7 +37,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types "} {"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -56,7 +58,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` + found type `{integer}`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types "} {"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -76,7 +79,8 @@ This error occurs when the compiler is unable to infer the concrete type of a variable. It can occur in several cases, the most common being a mismatch between two types: the type the author explicitly assigned, and the type the compiler inferred. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"expected struct `std::string::String` +found unit type `()`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index c73130643db7b..5c6ba152c1613 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -82,6 +82,9 @@ LL | 1+2 | | | expected struct `std::string::String`, found integer | help: try using a conversion method: `(1+2).to_string()` + | + = note: expected struct `std::string::String` + found type `{integer}` error[E0308]: mismatched types --> $DIR/abridged.rs:59:5 @@ -93,6 +96,9 @@ LL | -2 | | | expected struct `std::string::String`, found integer | help: try using a conversion method: `(-2).to_string()` + | + = note: expected struct `std::string::String` + found type `{integer}` error: aborting due to 8 previous errors diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index 6cbb59dc22031..6dc90140b6132 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -115,6 +115,9 @@ LL | let recovery_witness: String = 0; | | expected struct `std::string::String`, found integer | | help: try using a conversion method: `0.to_string()` | expected due to this + | + = note: expected struct `std::string::String` + found type `{integer}` error: aborting due to 16 previous errors diff --git a/src/test/ui/pattern/pat-type-err-formal-param.stderr b/src/test/ui/pattern/pat-type-err-formal-param.stderr index 2d7eb62faef2b..8385f66c91f73 100644 --- a/src/test/ui/pattern/pat-type-err-formal-param.stderr +++ b/src/test/ui/pattern/pat-type-err-formal-param.stderr @@ -5,6 +5,9 @@ LL | fn foo(Tuple(_): String) {} | ^^^^^^^^ ------ expected due to this | | | expected struct `std::string::String`, found struct `Tuple` + | + = note: expected struct `std::string::String` + found struct `Tuple` error: aborting due to previous error diff --git a/src/test/ui/privacy/privacy-ns1.rs b/src/test/ui/privacy/privacy-ns1.rs index 614375e5e51d5..c7084bfd98049 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; //~ 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 4d2af735fa6b9..f4f6ff38ab921 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -70,11 +70,11 @@ error[E0107]: wrong number of const arguments: expected 0, found 1 LL | let _x: Box; | ^^^ 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; - | ^^^^^^^^ 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 0546de873f340..b770c8f8f8610 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; //~ 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; //~ 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 f1aa523742ae4..4e88456a3dc30 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -96,11 +96,11 @@ error[E0107]: wrong number of const arguments: expected 0, found 1 LL | let _x : Box; | ^^^ 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; - | ^^^^^^^^ 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 @@ -108,11 +108,11 @@ error[E0107]: wrong number of const arguments: expected 0, found 1 LL | let _x: Box; | ^^^ 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; - | ^^^^^^^^ expected 1 type argument + | ^^^^^^^^ expected at least 1 type argument error: aborting due to 10 previous errors diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index d1960a8aab300..d10869039db64 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -5,6 +5,9 @@ LL | let x: usize = String::new(); | ----- ^^^^^^^^^^^^^ expected `usize`, found struct `std::string::String` | | | expected due to this + | + = note: expected type `usize` + found struct `std::string::String` error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:9:19 @@ -15,6 +18,9 @@ LL | let x: &str = String::new(); | | expected `&str`, found struct `std::string::String` | | help: consider borrowing here: `&String::new()` | expected due to this + | + = note: expected reference `&str` + found struct `std::string::String` error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:12:10 @@ -47,8 +53,10 @@ error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9 | LL | s = format!("foo"); - | ^^^^^^^^^^^^^^ expected `&mut std::string::String`, found struct `std::string::String` + | ^^^^^^^^^^^^^^ expected mutable reference, found struct `std::string::String` | + = note: expected mutable reference `&mut std::string::String` + found struct `std::string::String` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index 184d9644c83ab..6f4dd70748d28 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | stream.write_fmt(format!("message received")) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::fmt::Arguments`, found struct `std::string::String` | + = note: expected struct `std::fmt::Arguments<'_>` + found struct `std::string::String` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 8caa5bea4ac1e..d038207fa5446 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -72,6 +72,9 @@ LL | let _ = a + b; | | | expected `&str`, found struct `std::string::String` | help: consider borrowing here: `&b` + | + = note: expected reference `&str` + found struct `std::string::String` error[E0369]: cannot add `std::string::String` to `&std::string::String` --> $DIR/issue-39018.rs:30:15 diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr index ab336b14d2948..773e3cbe7fe66 100644 --- a/src/test/ui/suggestions/const-in-struct-pat.stderr +++ b/src/test/ui/suggestions/const-in-struct-pat.stderr @@ -10,6 +10,8 @@ LL | let Thing { foo } = t; | expected struct `std::string::String`, found struct `foo` | `foo` is interpreted as a unit struct, not a new binding | + = note: expected struct `std::string::String` + found struct `foo` help: bind the struct field to a different name instead | LL | let Thing { foo: other_foo } = t; diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr index b0cef952b2107..4ccb0306b427b 100644 --- a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr +++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -6,6 +6,8 @@ LL | | "abc" LL | | }; | |______^ expected `&str`, found struct `std::string::String` | + = note: expected reference `&str` + found struct `std::string::String` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr index 44fac16260afc..2f28527f2f4aa 100644 --- a/src/test/ui/suggestions/format-borrow.stderr +++ b/src/test/ui/suggestions/format-borrow.stderr @@ -4,9 +4,12 @@ error[E0308]: mismatched types LL | let a: String = &String::from("a"); | ------ ^^^^^^^^^^^^^^^^^^ | | | - | | expected struct `std::string::String`, found `&std::string::String` + | | expected struct `std::string::String`, found reference | | help: consider removing the borrow: `String::from("a")` | expected due to this + | + = note: expected struct `std::string::String` + found reference `&std::string::String` error[E0308]: mismatched types --> $DIR/format-borrow.rs:4:21 @@ -14,9 +17,12 @@ error[E0308]: mismatched types LL | let b: String = &format!("b"); | ------ ^^^^^^^^^^^^^ | | | - | | expected struct `std::string::String`, found `&std::string::String` + | | expected struct `std::string::String`, found reference | | help: consider removing the borrow: `format!("b")` | expected due to this + | + = note: expected struct `std::string::String` + found reference `&std::string::String` error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-52820.stderr b/src/test/ui/suggestions/issue-52820.stderr index 5ad6597b82e6e..acd81c817eef0 100644 --- a/src/test/ui/suggestions/issue-52820.stderr +++ b/src/test/ui/suggestions/issue-52820.stderr @@ -6,6 +6,9 @@ LL | guts, | | | expected struct `std::string::String`, found `&str` | help: try using a conversion method: `guts: guts.to_string()` + | + = note: expected struct `std::string::String` + found reference `&str` error[E0308]: mismatched types --> $DIR/issue-52820.rs:10:17 @@ -15,6 +18,9 @@ LL | brains: guts.clone(), | | | expected struct `std::string::String`, found `&str` | help: try using a conversion method: `guts.to_string()` + | + = note: expected struct `std::string::String` + found reference `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-59819.stderr b/src/test/ui/suggestions/issue-59819.stderr index b20327a9ff833..2be035982b56b 100644 --- a/src/test/ui/suggestions/issue-59819.stderr +++ b/src/test/ui/suggestions/issue-59819.stderr @@ -27,6 +27,9 @@ LL | let g: String = f; | | expected struct `std::string::String`, found struct `Bar` | | help: try using a conversion method: `f.to_string()` | expected due to this + | + = note: expected struct `std::string::String` + found struct `Bar` error: aborting due to 3 previous errors diff --git a/src/test/ui/switched-expectations.stderr b/src/test/ui/switched-expectations.stderr index dca9c6ce4d324..125da30a7a287 100644 --- a/src/test/ui/switched-expectations.stderr +++ b/src/test/ui/switched-expectations.stderr @@ -3,6 +3,9 @@ error[E0308]: mismatched types | LL | let ref string: String = var; | ^^^ expected struct `std::string::String`, found `i32` + | + = note: expected struct `std::string::String` + found type `i32` error: aborting due to previous error diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs index c0d39c59014ec..3aad085f08972 100644 --- a/src/test/ui/type/ascription/issue-34255-1.rs +++ b/src/test/ui/type/ascription/issue-34255-1.rs @@ -7,7 +7,7 @@ impl Reactor { input_cells: Vec::new() //~^ ERROR cannot find value `input_cells` in this scope //~| ERROR parenthesized type parameters may only be used with a `Fn` trait - //~| ERROR wrong number of type arguments: expected 1, found 0 + //~| ERROR wrong number of type arguments: expected at least 1, found 0 } } diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr index 7895cf77fc0bf..402e54d2a95dd 100644 --- a/src/test/ui/type/ascription/issue-34255-1.stderr +++ b/src/test/ui/type/ascription/issue-34255-1.stderr @@ -10,11 +10,11 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait LL | input_cells: Vec::new() | ^^^^^ only `Fn` traits may use parentheses -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-34255-1.rs:7:22 | LL | input_cells: Vec::new() - | ^^^^^^^^^^ expected 1 type argument + | ^^^^^^^^^^ expected at least 1 type argument error: aborting due to 3 previous errors diff --git a/src/test/ui/typeck/issue-67971.stderr b/src/test/ui/typeck/issue-67971.stderr index 36ad3fcb342a8..d987bf1bbc2fc 100644 --- a/src/test/ui/typeck/issue-67971.stderr +++ b/src/test/ui/typeck/issue-67971.stderr @@ -11,6 +11,9 @@ LL | fn foo(ctx: &mut S) -> String { | --- ^^^^^^ expected struct `std::string::String`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `std::string::String` + found unit type `()` error: aborting due to 2 previous errors diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 161e25bb8c5f1..a2d76159dab5e 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -12,8 +12,8 @@ LL | let _z = y.clone(); | ::: $SRC_DIR/liballoc/boxed.rs:LL:COL | -LL | pub struct Box(Unique); - | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` +LL | pub struct Box(Unique, A); + | -------------------------------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | ::: $SRC_DIR/libcore/clone.rs:LL:COL | diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 38c110c04c479..b1c0386e6a87e 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -9,8 +9,8 @@ LL | let _j = i.clone(); | ::: $SRC_DIR/liballoc/boxed.rs:LL:COL | -LL | pub struct Box(Unique); - | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` +LL | pub struct Box(Unique, A); + | -------------------------------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | ::: $SRC_DIR/libcore/clone.rs:LL:COL |