diff options
| author | Rich Kadel <richkadel@google.com> | 2020-06-10 12:19:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-10 12:19:36 -0700 |
| commit | d139a720a2c0ad7066c43edad6ec6c2aa9613740 (patch) | |
| tree | f94c254be282b464db805e6fa9042266d66c47b9 /src/liballoc | |
| parent | a6127e3fde9e8d24388847ad1b442a4337f19965 (diff) | |
| parent | bb8674837a9cc5225020e07fc3f164762bb4c11c (diff) | |
| download | rust-d139a720a2c0ad7066c43edad6ec6c2aa9613740.tar.gz rust-d139a720a2c0ad7066c43edad6ec6c2aa9613740.zip | |
Merge pull request #2 from rust-lang/master
update from origin 2020-06-10
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/boxed.rs | 27 | ||||
| -rw-r--r-- | src/liballoc/collections/binary_heap.rs | 20 | ||||
| -rw-r--r-- | src/liballoc/collections/btree/map.rs | 10 | ||||
| -rw-r--r-- | src/liballoc/collections/btree/set.rs | 10 | ||||
| -rw-r--r-- | src/liballoc/collections/linked_list.rs | 10 | ||||
| -rw-r--r-- | src/liballoc/collections/vec_deque.rs | 20 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 1 | ||||
| -rw-r--r-- | src/liballoc/raw_vec.rs | 172 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 28 | ||||
| -rw-r--r-- | src/liballoc/string.rs | 35 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 68 | ||||
| -rw-r--r-- | src/liballoc/tests/boxed.rs | 33 | ||||
| -rw-r--r-- | src/liballoc/tests/vec.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/vec.rs | 74 |
14 files changed, 319 insertions, 191 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 8ef6090c743..22c344323a2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -865,6 +865,25 @@ impl From<Box<str>> for Box<[u8]> { } } +#[stable(feature = "box_from_array", since = "1.45.0")] +impl<T, const N: usize> From<[T; N]> for Box<[T]> +where + [T; N]: LengthAtMost32, +{ + /// Converts a `[T; N]` into a `Box<[T]>` + /// + /// This conversion moves the array to newly heap-allocated memory. + /// + /// # Examples + /// ```rust + /// let boxed: Box<[u8]> = Box::from([4, 2]); + /// println!("{:?}", boxed); + /// ``` + fn from(array: [T; N]) -> Box<[T]> { + box array + } +} + #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> where @@ -1090,6 +1109,14 @@ impl<T: Clone> Clone for Box<[T]> { fn clone(&self) -> Self { self.to_vec().into_boxed_slice() } + + fn clone_from(&mut self, other: &Self) { + if self.len() == other.len() { + self.clone_from_slice(&other); + } else { + *self = other.clone(); + } + } } #[stable(feature = "box_borrow", since = "1.1.0")] diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index a3ef9989184..c2fe4691b34 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1376,6 +1376,16 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> { fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { <Self as SpecExtend<I>>::spec_extend(self, iter); } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> { @@ -1406,4 +1416,14 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index c6cb39b1bf5..fa1c09d9ece 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1901,6 +1901,11 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> { self.insert(k, v); }); } + + #[inline] + fn extend_one(&mut self, (k, v): (K, V)) { + self.insert(k, v); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -1908,6 +1913,11 @@ impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap<K, V> { fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) { self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); } + + #[inline] + fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { + self.insert(k, v); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index dee5fb878ff..525ef38c32f 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -1152,6 +1152,11 @@ impl<T: Ord> Extend<T> for BTreeSet<T> { self.insert(elem); }); } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.insert(elem); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -1159,6 +1164,11 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet<T> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.insert(elem); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index cc0f07b8227..85f2505f756 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1748,6 +1748,11 @@ impl<T> Extend<T> for LinkedList<T> { fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { <Self as SpecExtend<I>>::spec_extend(self, iter); } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.push_back(elem); + } } impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> { @@ -1767,6 +1772,11 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.push_back(elem); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 540649c61b3..ae54d3971ba 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2881,6 +2881,16 @@ impl<A> Extend<A> for VecDeque<A> { } } } + + #[inline] + fn extend_one(&mut self, elem: A) { + self.push_back(elem); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -2888,6 +2898,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque<T> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &elem: &T) { + self.push_back(elem); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 7aaa91ee10d..9bcfc9457f5 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -93,6 +93,7 @@ #![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(fundamental)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 2bd4733db42..805dbfe2775 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -9,7 +9,7 @@ use core::ptr::{NonNull, Unique}; use core::slice; use crate::alloc::{ - handle_alloc_error, AllocErr, + handle_alloc_error, AllocInit::{self, *}, AllocRef, Global, Layout, ReallocPlacement::{self, *}, @@ -118,6 +118,30 @@ impl<T> RawVec<T, Global> { RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len()) } } + + /// Converts the entire buffer into `Box<[MaybeUninit<T>]>` with the specified `len`. + /// + /// Note that this will correctly reconstitute any `cap` changes + /// that may have been performed. (See description of type for details.) + /// + /// # Safety + /// + /// * `len` must be greater than or equal to the most recently requested capacity, and + /// * `len` must be less than or equal to `self.capacity()`. + /// + /// Note, that the requested capacity and `self.capacity()` could differ, as + /// an allocator could overallocate and return a greater memory block than requested. + pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>]> { + // Sanity-check one half of the safety requirement (we cannot check the other half). + debug_assert!( + len <= self.capacity(), + "`len` must be smaller than or equal to `self.capacity()`" + ); + + let me = ManuallyDrop::new(self); + let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len); + Box::from_raw(slice) + } } impl<T, A: AllocRef> RawVec<T, A> { @@ -211,13 +235,13 @@ impl<T, A: AllocRef> RawVec<T, A> { } } - /// Ensures that the buffer contains at least enough space to hold - /// `used_capacity + needed_extra_capacity` elements. If it doesn't already have - /// enough capacity, will reallocate enough space plus comfortable slack - /// space to get amortized `O(1)` behavior. Will limit this behavior - /// if it would needlessly cause itself to panic. + /// Ensures that the buffer contains at least enough space to hold `len + + /// additional` elements. If it doesn't already have enough capacity, will + /// reallocate enough space plus comfortable slack space to get amortized + /// `O(1)` behavior. Will limit this behavior if it would needlessly cause + /// itself to panic. /// - /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate + /// If `len` exceeds `self.capacity()`, this may fail to actually allocate /// the requested space. This is not really unsafe, but the unsafe /// code *you* write that relies on the behavior of this function may break. /// @@ -263,8 +287,8 @@ impl<T, A: AllocRef> RawVec<T, A> { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` - pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) { - match self.try_reserve(used_capacity, needed_extra_capacity) { + pub fn reserve(&mut self, len: usize, additional: usize) { + match self.try_reserve(len, additional) { Err(CapacityOverflow) => capacity_overflow(), Err(AllocError { layout, .. }) => handle_alloc_error(layout), Ok(()) => { /* yay */ } @@ -272,55 +296,23 @@ impl<T, A: AllocRef> RawVec<T, A> { } /// The same as `reserve`, but returns on errors instead of panicking or aborting. - pub fn try_reserve( - &mut self, - used_capacity: usize, - needed_extra_capacity: usize, - ) -> Result<(), TryReserveError> { - if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow_amortized(used_capacity, needed_extra_capacity, MayMove) + pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional) { + self.grow_amortized(len, additional) } else { Ok(()) } } - /// Attempts to ensure that the buffer contains at least enough space to hold - /// `used_capacity + needed_extra_capacity` elements. If it doesn't already have - /// enough capacity, will reallocate in place enough space plus comfortable slack - /// space to get amortized `O(1)` behavior. Will limit this behaviour - /// if it would needlessly cause itself to panic. + /// Ensures that the buffer contains at least enough space to hold `len + + /// additional` elements. If it doesn't already, will reallocate the + /// minimum possible amount of memory necessary. Generally this will be + /// exactly the amount of memory necessary, but in principle the allocator + /// is free to give back more than we asked for. /// - /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate - /// the requested space. This is not really unsafe, but the unsafe - /// code *you* write that relies on the behavior of this function may break. - /// - /// Returns `true` if the reallocation attempt has succeeded. - /// - /// # Panics - /// - /// * Panics if the requested capacity exceeds `usize::MAX` bytes. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. - pub fn reserve_in_place(&mut self, used_capacity: usize, needed_extra_capacity: usize) -> bool { - // This is more readable than putting this in one line: - // `!self.needs_to_grow(...) || self.grow(...).is_ok()` - if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow_amortized(used_capacity, needed_extra_capacity, InPlace).is_ok() - } else { - true - } - } - - /// Ensures that the buffer contains at least enough space to hold - /// `used_capacity + needed_extra_capacity` elements. If it doesn't already, - /// will reallocate the minimum possible amount of memory necessary. - /// Generally this will be exactly the amount of memory necessary, - /// but in principle the allocator is free to give back more than - /// we asked for. - /// - /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate - /// the requested space. This is not really unsafe, but the unsafe - /// code *you* write that relies on the behavior of this function may break. + /// If `len` exceeds `self.capacity()`, this may fail to actually allocate + /// the requested space. This is not really unsafe, but the unsafe code + /// *you* write that relies on the behavior of this function may break. /// /// # Panics /// @@ -331,8 +323,8 @@ impl<T, A: AllocRef> RawVec<T, A> { /// # Aborts /// /// Aborts on OOM. - pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) { - match self.try_reserve_exact(used_capacity, needed_extra_capacity) { + pub fn reserve_exact(&mut self, len: usize, additional: usize) { + match self.try_reserve_exact(len, additional) { Err(CapacityOverflow) => capacity_overflow(), Err(AllocError { layout, .. }) => handle_alloc_error(layout), Ok(()) => { /* yay */ } @@ -342,14 +334,10 @@ impl<T, A: AllocRef> RawVec<T, A> { /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. pub fn try_reserve_exact( &mut self, - used_capacity: usize, - needed_extra_capacity: usize, + len: usize, + additional: usize, ) -> Result<(), TryReserveError> { - if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow_exact(used_capacity, needed_extra_capacity) - } else { - Ok(()) - } + if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } } /// Shrinks the allocation down to the specified amount. If the given amount @@ -374,8 +362,8 @@ impl<T, A: AllocRef> RawVec<T, A> { impl<T, A: AllocRef> RawVec<T, A> { /// Returns if the buffer needs to grow to fulfill the needed extra capacity. /// Mainly used to make inlining reserve-calls possible without inlining `grow`. - fn needs_to_grow(&self, used_capacity: usize, needed_extra_capacity: usize) -> bool { - needed_extra_capacity > self.capacity().wrapping_sub(used_capacity) + fn needs_to_grow(&self, len: usize, additional: usize) -> bool { + additional > self.capacity().wrapping_sub(len) } fn capacity_from_bytes(excess: usize) -> usize { @@ -395,14 +383,9 @@ impl<T, A: AllocRef> RawVec<T, A> { // so that all of the code that depends on `T` is within it, while as much // of the code that doesn't depend on `T` as possible is in functions that // are non-generic over `T`. - fn grow_amortized( - &mut self, - used_capacity: usize, - needed_extra_capacity: usize, - placement: ReallocPlacement, - ) -> Result<(), TryReserveError> { + fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { // This is ensured by the calling contexts. - debug_assert!(needed_extra_capacity > 0); + debug_assert!(additional > 0); if mem::size_of::<T>() == 0 { // Since we return a capacity of `usize::MAX` when `elem_size` is @@ -411,8 +394,7 @@ impl<T, A: AllocRef> RawVec<T, A> { } // Nothing we can really do about these checks, sadly. - let required_cap = - used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; + let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?; // This guarantees exponential growth. The doubling cannot overflow // because `cap <= isize::MAX` and the type of `cap` is `usize`. @@ -437,7 +419,7 @@ impl<T, A: AllocRef> RawVec<T, A> { let new_layout = Layout::array::<T>(cap); // `finish_grow` is non-generic over `T`. - let memory = finish_grow(new_layout, placement, self.current_memory(), &mut self.alloc)?; + let memory = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; self.set_memory(memory); Ok(()) } @@ -445,22 +427,18 @@ impl<T, A: AllocRef> RawVec<T, A> { // The constraints on this method are much the same as those on // `grow_amortized`, but this method is usually instantiated less often so // it's less critical. - fn grow_exact( - &mut self, - used_capacity: usize, - needed_extra_capacity: usize, - ) -> Result<(), TryReserveError> { + fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { if mem::size_of::<T>() == 0 { // Since we return a capacity of `usize::MAX` when the type size is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow); } - let cap = used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; + let cap = len.checked_add(additional).ok_or(CapacityOverflow)?; let new_layout = Layout::array::<T>(cap); // `finish_grow` is non-generic over `T`. - let memory = finish_grow(new_layout, MayMove, self.current_memory(), &mut self.alloc)?; + let memory = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; self.set_memory(memory); Ok(()) } @@ -494,7 +472,6 @@ impl<T, A: AllocRef> RawVec<T, A> { // much smaller than the number of `T` types.) fn finish_grow<A>( new_layout: Result<Layout, LayoutErr>, - placement: ReallocPlacement, current_memory: Option<(NonNull<u8>, Layout)>, alloc: &mut A, ) -> Result<MemoryBlock, TryReserveError> @@ -508,44 +485,15 @@ where let memory = if let Some((ptr, old_layout)) = current_memory { debug_assert_eq!(old_layout.align(), new_layout.align()); - unsafe { alloc.grow(ptr, old_layout, new_layout.size(), placement, Uninitialized) } + unsafe { alloc.grow(ptr, old_layout, new_layout.size(), MayMove, Uninitialized) } } else { - match placement { - MayMove => alloc.alloc(new_layout, Uninitialized), - InPlace => Err(AllocErr), - } + alloc.alloc(new_layout, Uninitialized) } .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?; Ok(memory) } -impl<T> RawVec<T, Global> { - /// Converts the entire buffer into `Box<[MaybeUninit<T>]>` with the specified `len`. - /// - /// Note that this will correctly reconstitute any `cap` changes - /// that may have been performed. (See description of type for details.) - /// - /// # Safety - /// - /// * `len` must be greater than or equal to the most recently requested capacity, and - /// * `len` must be less than or equal to `self.capacity()`. - /// - /// Note, that the requested capacity and `self.capacity()` could differ, as - /// an allocator could overallocate and return a greater memory block than requested. - pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>]> { - // Sanity-check one half of the safety requirement (we cannot check the other half). - debug_assert!( - len <= self.capacity(), - "`len` must be smaller than or equal to `self.capacity()`" - ); - - let me = ManuallyDrop::new(self); - let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len); - Box::from_raw(slice) - } -} - unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> { /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. fn drop(&mut self) { diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index ad96a138d7e..925bc7d3c02 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -580,8 +580,6 @@ impl<T: ?Sized> Rc<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::rc::Rc; /// /// let x = Rc::new("hello".to_owned()); @@ -590,7 +588,7 @@ impl<T: ?Sized> Rc<T> { /// assert_eq!(x_ptr, Rc::as_ptr(&y)); /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr); let fake_ptr = ptr as *mut T; @@ -1681,8 +1679,6 @@ impl<T> Weak<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::rc::Rc; /// use std::ptr; /// @@ -1700,7 +1696,7 @@ impl<T> Weak<T> { /// ``` /// /// [`null`]: ../../std/ptr/fn.null.html - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { let offset = data_offset_sized::<T>(); let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset); @@ -1718,8 +1714,6 @@ impl<T> Weak<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::rc::{Rc, Weak}; /// /// let strong = Rc::new("hello".to_owned()); @@ -1735,7 +1729,7 @@ impl<T> Weak<T> { /// /// [`from_raw`]: struct.Weak.html#method.from_raw /// [`as_ptr`]: struct.Weak.html#method.as_ptr - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { let result = self.as_ptr(); mem::forget(self); @@ -1762,8 +1756,6 @@ impl<T> Weak<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::rc::{Rc, Weak}; /// /// let strong = Rc::new("hello".to_owned()); @@ -1788,7 +1780,7 @@ impl<T> Weak<T> { /// [`Weak`]: struct.Weak.html /// [`new`]: struct.Weak.html#method.new /// [`forget`]: ../../std/mem/fn.forget.html - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { if ptr.is_null() { Self::new() @@ -2043,11 +2035,7 @@ trait RcBoxPtr<T: ?Sized> { // nevertheless, we insert an abort here to hint LLVM at // an otherwise missed optimization. if strong == 0 || strong == usize::max_value() { - // remove `unsafe` on bootstrap bump - #[cfg_attr(not(bootstrap), allow(unused_unsafe))] - unsafe { - abort(); - } + abort(); } self.inner().strong.set(strong + 1); } @@ -2071,11 +2059,7 @@ trait RcBoxPtr<T: ?Sized> { // nevertheless, we insert an abort here to hint LLVM at // an otherwise missed optimization. if weak == 0 || weak == usize::max_value() { - // remove `unsafe` on bootstrap bump - #[cfg_attr(not(bootstrap), allow(unused_unsafe))] - unsafe { - abort(); - } + abort(); } self.inner().weak.set(weak + 1); } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index f3fe1adebb1..0378ff5362a 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1799,6 +1799,16 @@ impl Extend<char> for String { self.reserve(lower_bound); iterator.for_each(move |c| self.push(c)); } + + #[inline] + fn extend_one(&mut self, c: char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -1806,6 +1816,16 @@ impl<'a> Extend<&'a char> for String { fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &c: &'a char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1813,6 +1833,11 @@ impl<'a> Extend<&'a str> for String { fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); } + + #[inline] + fn extend_one(&mut self, s: &'a str) { + self.push_str(s); + } } #[stable(feature = "extend_string", since = "1.4.0")] @@ -1820,6 +1845,11 @@ impl Extend<String> for String { fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } + + #[inline] + fn extend_one(&mut self, s: String) { + self.push_str(&s); + } } #[stable(feature = "herd_cows", since = "1.19.0")] @@ -1827,6 +1857,11 @@ impl<'a> Extend<Cow<'a, str>> for String { fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } + + #[inline] + fn extend_one(&mut self, s: Cow<'a, str>) { + self.push_str(&s); + } } /// A convenience impl that delegates to the impl for `&str`. diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index b7be8042ea4..cd4172d6a2d 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -579,8 +579,6 @@ impl<T: ?Sized> Arc<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::sync::Arc; /// /// let x = Arc::new("hello".to_owned()); @@ -589,7 +587,7 @@ impl<T: ?Sized> Arc<T> { /// assert_eq!(x_ptr, Arc::as_ptr(&y)); /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr); let fake_ptr = ptr as *mut T; @@ -867,12 +865,10 @@ impl<T: ?Sized> Arc<T> { 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); + ptr::drop_in_place(Self::get_mut_unchecked(self)); - 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())) - } + // Drop the weak ref collectively held by all strong references + drop(Weak { ptr: self.ptr }); } #[inline] @@ -1097,11 +1093,7 @@ impl<T: ?Sized> Clone for Arc<T> { // We abort because such a program is incredibly degenerate, and we // don't care to support it. if old_size > MAX_REFCOUNT { - // remove `unsafe` on bootstrap bump - #[cfg_attr(not(bootstrap), allow(unused_unsafe))] - unsafe { - abort(); - } + abort(); } Self::from_inner(self.ptr) @@ -1204,7 +1196,7 @@ impl<T: Clone> Arc<T> { // As with `get_mut()`, the unsafety is ok because our reference was // either unique to begin with, or became one upon cloning the contents. - unsafe { &mut this.ptr.as_mut().data } + unsafe { Self::get_mut_unchecked(this) } } } @@ -1280,7 +1272,9 @@ impl<T: ?Sized> Arc<T> { #[inline] #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { - &mut this.ptr.as_mut().data + // We are careful to *not* create a reference covering the "count" fields, as + // this would alias with concurrent access to the reference counts (e.g. by `Weak`). + &mut (*this.ptr.as_ptr()).data } /// Determine whether this is the unique reference (including weak refs) to @@ -1449,8 +1443,6 @@ impl<T> Weak<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::sync::Arc; /// use std::ptr; /// @@ -1468,7 +1460,7 @@ impl<T> Weak<T> { /// ``` /// /// [`null`]: ../../std/ptr/fn.null.html - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { let offset = data_offset_sized::<T>(); let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset); @@ -1486,8 +1478,6 @@ impl<T> Weak<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::sync::{Arc, Weak}; /// /// let strong = Arc::new("hello".to_owned()); @@ -1503,7 +1493,7 @@ impl<T> Weak<T> { /// /// [`from_raw`]: struct.Weak.html#method.from_raw /// [`as_ptr`]: struct.Weak.html#method.as_ptr - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { let result = self.as_ptr(); mem::forget(self); @@ -1531,8 +1521,6 @@ impl<T> Weak<T> { /// # Examples /// /// ``` - /// #![feature(weak_into_raw)] - /// /// use std::sync::{Arc, Weak}; /// /// let strong = Arc::new("hello".to_owned()); @@ -1557,7 +1545,7 @@ impl<T> Weak<T> { /// [`Weak`]: struct.Weak.html /// [`Arc`]: struct.Arc.html /// [`forget`]: ../../std/mem/fn.forget.html - #[unstable(feature = "weak_into_raw", issue = "60728")] + #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { if ptr.is_null() { Self::new() @@ -1571,6 +1559,13 @@ impl<T> Weak<T> { } } +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a atomic::AtomicUsize, + strong: &'a atomic::AtomicUsize, +} + impl<T: ?Sized> Weak<T> { /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying /// dropping of the inner value if successful. @@ -1617,11 +1612,7 @@ impl<T: ?Sized> Weak<T> { // See comments in `Arc::clone` for why we do this (for `mem::forget`). if n > MAX_REFCOUNT { - // remove `unsafe` on bootstrap bump - #[cfg_attr(not(bootstrap), allow(unused_unsafe))] - unsafe { - abort(); - } + abort(); } // Relaxed is valid for the same reason it is on Arc's Clone impl @@ -1678,8 +1669,18 @@ impl<T: ?Sized> Weak<T> { /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, /// (i.e., when this `Weak` was created by `Weak::new`). #[inline] - fn inner(&self) -> Option<&ArcInner<T>> { - if is_dangling(self.ptr) { None } else { Some(unsafe { self.ptr.as_ref() }) } + fn inner(&self) -> Option<WeakInner<'_>> { + if is_dangling(self.ptr) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Arc` + // is dropped, the data field will be dropped in-place). + Some(unsafe { + let ptr = self.ptr.as_ptr(); + WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } + }) + } } /// Returns `true` if the two `Weak`s point to the same allocation (similar to @@ -1758,10 +1759,7 @@ impl<T: ?Sized> Clone for Weak<T> { // See comments in Arc::clone() for why we do this (for mem::forget). if old_size > MAX_REFCOUNT { - #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump - unsafe { - abort(); - } + abort(); } Weak { ptr: self.ptr } diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs index 66782ecbeb7..5377485da8f 100644 --- a/src/liballoc/tests/boxed.rs +++ b/src/liballoc/tests/boxed.rs @@ -16,3 +16,36 @@ fn unitialized_zero_size_box() { NonNull::<MaybeUninit<String>>::dangling().as_ptr(), ); } + +#[derive(Clone, PartialEq, Eq, Debug)] +struct Dummy { + _data: u8, +} + +#[test] +fn box_clone_and_clone_from_equivalence() { + for size in (0..8).map(|i| 2usize.pow(i)) { + let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); + let clone = control.clone(); + let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); + copy.clone_from(&control); + assert_eq!(control, clone); + assert_eq!(control, copy); + } +} + +/// This test might give a false positive in case the box realocates, but the alocator keeps the +/// original pointer. +/// +/// On the other hand it won't give a false negative, if it fails than the memory was definitly not +/// reused +#[test] +fn box_clone_from_ptr_stability() { + for size in (0..8).map(|i| 2usize.pow(i)) { + let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); + let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); + let copy_raw = copy.as_ptr() as usize; + copy.clone_from(&control); + assert_eq!(copy.as_ptr() as usize, copy_raw); + } +} diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index b16044d9640..b73fd95ab6a 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -16,7 +16,7 @@ impl Drop for DropCounter<'_> { #[test] fn test_small_vec_struct() { - assert!(size_of::<Vec<u8>>() == size_of::<usize>() * 3); + assert_eq!(size_of::<Vec<u8>>(), size_of::<usize>() * 3); } #[test] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d26cd77aae4..2226737757b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -343,14 +343,19 @@ impl<T> Vec<T> { /// /// // The vector contains no items, even though it has capacity for more /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); /// /// // These are all done without reallocating... /// for i in 0..10 { /// vec.push(i); /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); /// /// // ...but this may make the vector reallocate /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -979,7 +984,7 @@ impl<T> Vec<T> { // bounds check above succeeds there must be a last element (which // can be self[index] itself). let last = ptr::read(self.as_ptr().add(len - 1)); - let hole: *mut T = self.as_mut_ptr().add(index); + let hole = self.as_mut_ptr().add(index); self.set_len(len - 1); ptr::replace(hole, last) } @@ -1901,6 +1906,22 @@ unsafe impl<T: ?Sized> IsZero for Option<Box<T>> { //////////////////////////////////////////////////////////////////////////////// #[stable(feature = "rust1", since = "1.0.0")] +impl<T> ops::Deref for Vec<T> { + type Target = [T]; + + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<T> ops::DerefMut for Vec<T> { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl<T: Clone> Clone for Vec<T> { #[cfg(not(test))] fn clone(&self) -> Vec<T> { @@ -1956,22 +1977,6 @@ impl<T, I: SliceIndex<[T]>> IndexMut<I> for Vec<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> ops::Deref for Vec<T> { - type Target = [T]; - - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<T> ops::DerefMut for Vec<T> { - fn deref_mut(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] impl<T> FromIterator<T> for Vec<T> { #[inline] fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> { @@ -2045,6 +2050,16 @@ impl<T> Extend<T> for Vec<T> { fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { <Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter()) } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } // Specialization trait used for Vec::from_iter and Vec::extend @@ -2316,6 +2331,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.spec_extend(iter.into_iter()) } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } macro_rules! __impl_slice_eq1 { @@ -2603,6 +2628,13 @@ impl<T> IntoIter<T> { } } +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl<T> AsRef<[T]> for IntoIter<T> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<T: Send> Send for IntoIter<T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -2945,12 +2977,12 @@ impl<T> Drain<'_, T> { } /// Makes room for inserting more elements before the tail. - unsafe fn move_tail(&mut self, extra_capacity: usize) { + unsafe fn move_tail(&mut self, additional: usize) { let vec = self.vec.as_mut(); - let used_capacity = self.tail_start + self.tail_len; - vec.buf.reserve(used_capacity, extra_capacity); + let len = self.tail_start + self.tail_len; + vec.buf.reserve(len, additional); - let new_tail_start = self.tail_start + extra_capacity; + let new_tail_start = self.tail_start + additional; let src = vec.as_ptr().add(self.tail_start); let dst = vec.as_mut_ptr().add(new_tail_start); ptr::copy(src, dst, self.tail_len); |
