diff options
| author | phosphorus <steepout@qq.com> | 2019-08-19 00:34:02 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-19 00:34:02 -0500 |
| commit | 92f08b78a12ff119af853cb2bf58468208ea6a90 (patch) | |
| tree | b4636f43c056de11dd69130ce47039343a9f52c5 /src/liballoc | |
| parent | 963184bbb670c1ffa97fc28a98cd5e8473118859 (diff) | |
| parent | a807902dd6b4222179776c3f3c33da8dafdd4da1 (diff) | |
| download | rust-92f08b78a12ff119af853cb2bf58468208ea6a90.tar.gz rust-92f08b78a12ff119af853cb2bf58468208ea6a90.zip | |
Merge pull request #1 from rust-lang/master
Pull from newest repo
Diffstat (limited to 'src/liballoc')
40 files changed, 4310 insertions, 2439 deletions
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index bcb27bb5161..d1119f7b7c0 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -15,8 +15,8 @@ core = { path = "../libcore" } compiler_builtins = { version = "0.1.10", features = ['rustc-dep-of-std'] } [dev-dependencies] -rand = "0.6" -rand_xorshift = "0.1" +rand = "0.7" +rand_xorshift = "0.2" [[test]] name = "collectionstests" diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index ddc6481eec7..dc7fd1adc29 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -10,12 +10,15 @@ use core::usize; #[doc(inline)] pub use core::alloc::*; +#[cfg(test)] +mod tests; + extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them from the `#[global_allocator]` attribute if there is one, or uses the // default implementations in libstd (`__rdl_alloc` etc in `src/libstd/alloc.rs`) // otherwise. - #[allocator] + #[rustc_allocator] #[rustc_allocator_nounwind] fn __rust_alloc(size: usize, align: usize) -> *mut u8; #[rustc_allocator_nounwind] @@ -37,6 +40,8 @@ extern "Rust" { /// /// Note: while this type is unstable, the functionality it provides can be /// accessed through the [free functions in `alloc`](index.html#functions). +/// +/// [`Alloc`]: trait.Alloc.html #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] pub struct Global; @@ -54,6 +59,10 @@ pub struct Global; /// /// See [`GlobalAlloc::alloc`]. /// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc +/// /// # Examples /// /// ``` @@ -87,6 +96,10 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { /// # Safety /// /// See [`GlobalAlloc::dealloc`]. +/// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { @@ -105,6 +118,10 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { /// # Safety /// /// See [`GlobalAlloc::realloc`]. +/// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { @@ -124,6 +141,10 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// /// See [`GlobalAlloc::alloc_zeroed`]. /// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed +/// /// # Examples /// /// ``` @@ -226,36 +247,3 @@ pub fn handle_alloc_error(layout: Layout) -> ! { } unsafe { oom_impl(layout) } } - -#[cfg(test)] -mod tests { - extern crate test; - use test::Bencher; - use crate::boxed::Box; - use crate::alloc::{Global, Alloc, Layout, handle_alloc_error}; - - #[test] - fn allocate_zeroed() { - unsafe { - let layout = Layout::from_size_align(1024, 1).unwrap(); - let ptr = Global.alloc_zeroed(layout.clone()) - .unwrap_or_else(|_| handle_alloc_error(layout)); - - let mut i = ptr.cast::<u8>().as_ptr(); - let end = i.add(layout.size()); - while i < end { - assert_eq!(*i, 0); - i = i.offset(1); - } - Global.dealloc(ptr, layout); - } - } - - #[bench] - #[cfg(not(miri))] // Miri does not support benchmarks - fn alloc_owned_small(b: &mut Bencher) { - b.iter(|| { - let _: Box<_> = box 10; - }) - } -} diff --git a/src/liballoc/alloc/tests.rs b/src/liballoc/alloc/tests.rs new file mode 100644 index 00000000000..c69f4e49ee1 --- /dev/null +++ b/src/liballoc/alloc/tests.rs @@ -0,0 +1,30 @@ +use super::*; + +extern crate test; +use test::Bencher; +use crate::boxed::Box; + +#[test] +fn allocate_zeroed() { + unsafe { + let layout = Layout::from_size_align(1024, 1).unwrap(); + let ptr = Global.alloc_zeroed(layout.clone()) + .unwrap_or_else(|_| handle_alloc_error(layout)); + + let mut i = ptr.cast::<u8>().as_ptr(); + let end = i.add(layout.size()); + while i < end { + assert_eq!(*i, 0); + i = i.offset(1); + } + Global.dealloc(ptr, layout); + } +} + +#[bench] +#[cfg(not(miri))] // Miri does not support benchmarks +fn alloc_owned_small(b: &mut Bencher) { + b.iter(|| { + let _: Box<_> = box 10; + }) +} diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index f17fb8212ce..ef91d801dc7 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -186,12 +186,12 @@ const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; fn gen_random(len: usize) -> Vec<u64> { let mut rng = XorShiftRng::from_seed(SEED); - rng.sample_iter(&Standard).take(len).collect() + (&mut rng).sample_iter(&Standard).take(len).collect() } fn gen_random_bytes(len: usize) -> Vec<u8> { let mut rng = XorShiftRng::from_seed(SEED); - rng.sample_iter(&Standard).take(len).collect() + (&mut rng).sample_iter(&Standard).take(len).collect() } fn gen_mostly_ascending(len: usize) -> Vec<u64> { @@ -221,14 +221,14 @@ fn gen_strings(len: usize) -> Vec<String> { let mut v = vec![]; for _ in 0..len { let n = rng.gen::<usize>() % 20 + 1; - v.push(rng.sample_iter(&Alphanumeric).take(n).collect()); + v.push((&mut rng).sample_iter(&Alphanumeric).take(n).collect()); } v } fn gen_big_random(len: usize) -> Vec<[u64; 16]> { let mut rng = XorShiftRng::from_seed(SEED); - rng.sample_iter(&Standard).map(|x| [x; 16]).take(len).collect() + (&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect() } macro_rules! sort { diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index d5e15b3719c..a9c5bce4c25 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -329,8 +329,8 @@ impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> #[stable(feature = "rust1", since = "1.0.0")] impl<B: ?Sized> fmt::Debug for Cow<'_, B> - where B: fmt::Debug + ToOwned, - <B as ToOwned>::Owned: fmt::Debug +where + B: fmt::Debug + ToOwned<Owned: fmt::Debug>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -342,8 +342,8 @@ impl<B: ?Sized> fmt::Debug for Cow<'_, B> #[stable(feature = "rust1", since = "1.0.0")] impl<B: ?Sized> fmt::Display for Cow<'_, B> - where B: fmt::Display + ToOwned, - <B as ToOwned>::Owned: fmt::Display +where + B: fmt::Display + ToOwned<Owned: fmt::Display>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -355,8 +355,8 @@ impl<B: ?Sized> fmt::Display for Cow<'_, B> #[stable(feature = "default", since = "1.11.0")] impl<B: ?Sized> Default for Cow<'_, B> - where B: ToOwned, - <B as ToOwned>::Owned: Default +where + B: ToOwned<Owned: Default>, { /// Creates an owned Cow<'a, B> with the default value for the contained owned value. fn default() -> Self { diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 207359ed696..c61e3183409 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -1,19 +1,9 @@ //! A pointer type for heap allocation. //! -//! `Box<T>`, casually referred to as a 'box', provides the simplest form of +//! [`Box<T>`], casually referred to as a 'box', provides the simplest form of //! heap allocation in Rust. Boxes provide ownership for this allocation, and //! drop their contents when they go out of scope. //! -//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for -//! its allocation. It is valid to convert both ways between a [`Box`] and a -//! raw pointer allocated with the [`Global`] allocator, given that the -//! [`Layout`] used with the allocator is correct for the type. More precisely, -//! a `value: *mut T` that has been allocated with the [`Global`] allocator -//! with `Layout::for_value(&*value)` may be converted into a box using -//! `Box::<T>::from_raw(value)`. Conversely, the memory backing a `value: *mut -//! T` obtained from `Box::<T>::into_raw` may be deallocated using the -//! [`Global`] allocator with `Layout::for_value(&*value)`. -//! //! # Examples //! //! Move a value from the stack to the heap by creating a [`Box`]: @@ -58,20 +48,38 @@ //! //! It wouldn't work. This is because the size of a `List` depends on how many //! elements are in the list, and so we don't know how much memory to allocate -//! for a `Cons`. By introducing a `Box`, which has a defined size, we know how +//! for a `Cons`. By introducing a [`Box<T>`], which has a defined size, we know how //! big `Cons` needs to be. //! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for +//! its allocation. It is valid to convert both ways between a [`Box`] and a +//! raw pointer allocated with the [`Global`] allocator, given that the +//! [`Layout`] used with the allocator is correct for the type. More precisely, +//! a `value: *mut T` that has been allocated with the [`Global`] allocator +//! with `Layout::for_value(&*value)` may be converted into a box using +//! [`Box::<T>::from_raw(value)`]. Conversely, the memory backing a `value: *mut +//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the +//! [`Global`] allocator with [`Layout::for_value(&*value)`]. +//! +//! //! [dereferencing]: ../../std/ops/trait.Deref.html //! [`Box`]: struct.Box.html +//! [`Box<T>`]: struct.Box.html +//! [`Box::<T>::from_raw(value)`]: struct.Box.html#method.from_raw +//! [`Box::<T>::into_raw`]: struct.Box.html#method.into_raw //! [`Global`]: ../alloc/struct.Global.html //! [`Layout`]: ../alloc/struct.Layout.html +//! [`Layout::for_value(&*value)`]: ../alloc/struct.Layout.html#method.for_value #![stable(feature = "rust1", since = "1.0.0")] use core::any::Any; +use core::array::LengthAtMost32; use core::borrow; use core::cmp::Ordering; -use core::convert::From; +use core::convert::{From, TryFrom}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; @@ -83,8 +91,10 @@ use core::ops::{ CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState }; use core::ptr::{self, NonNull, Unique}; +use core::slice; use core::task::{Context, Poll}; +use crate::alloc::{self, Global, Alloc}; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -113,6 +123,34 @@ impl<T> Box<T> { box x } + /// Constructs a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Box<mem::MaybeUninit<T>> { + let layout = alloc::Layout::new::<mem::MaybeUninit<T>>(); + let ptr = unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + }; + Box(ptr.cast().into()) + } + /// Constructs a new `Pin<Box<T>>`. 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")] @@ -122,29 +160,148 @@ impl<T> Box<T> { } } +impl<T> Box<[T]> { + /// Constructs a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> { + let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + Box(Unique::from(slice)) + } +} + +impl<T> Box<mem::MaybeUninit<T>> { + /// Converts to `Box<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::<u32>::new_uninit(); + /// + /// let five: Box<u32> = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box<T> { + Box(Box::into_unique(self).cast()) + } +} + +impl<T> Box<[mem::MaybeUninit<T>]> { + /// Converts to `Box<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T]> { + Box(Unique::new_unchecked(Box::into_raw(self) as _)) + } +} + impl<T: ?Sized> Box<T> { /// Constructs a box from a raw pointer. /// /// 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. Since the - /// way `Box` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `Box` via the [`Box::into_raw`] function. + /// 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. /// - /// [`Box::into_raw`]: struct.Box.html#method.into_raw - /// /// # Examples - /// + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw`]: /// ``` /// let x = Box::new(5); /// let ptr = Box::into_raw(x); /// let x = unsafe { Box::from_raw(ptr) }; /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// use std::alloc::{alloc, Layout}; + /// + /// unsafe { + /// let ptr = alloc(Layout::new::<i32>()) as *mut i32; + /// *ptr = 5; + /// let x = Box::from_raw(ptr); + /// } + /// ``` + /// + /// [memory layout]: index.html#memory-layout + /// [`Layout`]: ../alloc/struct.Layout.html + /// [`Box::into_raw`]: struct.Box.html#method.into_raw #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { @@ -157,22 +314,40 @@ impl<T: ?Sized> Box<T> { /// /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `Box` with the [`Box::from_raw`] function. + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw`] function, allowing the `Box` destructor to perform + /// the cleanup. /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This /// is so that there is no conflict with a method on the inner type. /// - /// [`Box::from_raw`]: struct.Box.html#method.from_raw - /// /// # Examples - /// + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// for automatic cleanup: /// ``` - /// let x = Box::new(5); + /// let x = Box::new(String::from("Hello")); /// let ptr = Box::into_raw(x); + /// let x = unsafe { Box::from_raw(ptr) }; /// ``` + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: + /// ``` + /// use std::alloc::{dealloc, Layout}; + /// use std::ptr; + /// + /// let x = Box::new(String::from("Hello")); + /// let p = Box::into_raw(x); + /// unsafe { + /// ptr::drop_in_place(p); + /// dealloc(p as *mut u8, Layout::new::<String>()); + /// } + /// ``` + /// + /// [memory layout]: index.html#memory-layout + /// [`Box::from_raw`]: struct.Box.html#method.from_raw #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Box<T>) -> *mut T { @@ -184,7 +359,7 @@ impl<T: ?Sized> Box<T> { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the `NonNull<T>` pointer + /// easiest way to do so is to convert the `NonNull<T>` pointer /// into a raw pointer and back into a `Box` with the [`Box::from_raw`] /// function. /// @@ -203,6 +378,10 @@ impl<T: ?Sized> Box<T> { /// fn main() { /// let x = Box::new(5); /// let ptr = Box::into_raw_non_null(x); + /// + /// // Clean up the memory by converting the NonNull pointer back + /// // into a Box and letting the Box be dropped. + /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; /// } /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] @@ -214,15 +393,16 @@ impl<T: ?Sized> Box<T> { #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")] #[inline] #[doc(hidden)] - pub fn into_unique(mut b: Box<T>) -> Unique<T> { + pub fn into_unique(b: Box<T>) -> Unique<T> { + let mut unique = b.0; + mem::forget(b); // Box is kind-of a library type, but recognized as a "unique pointer" by // Stacked Borrows. This function here corresponds to "reborrowing to // a raw pointer", but there is no actual reborrow here -- so // without some care, the pointer we are returning here still carries - // the `Uniq` tag. We round-trip through a mutable reference to avoid that. - let unique = unsafe { b.0.as_mut() as *mut T }; - mem::forget(b); - unsafe { Unique::new_unchecked(unique) } + // the tag of `b`, with `Unique` permission. + // We round-trip through a mutable reference to avoid that. + unsafe { Unique::new_unchecked(unique.as_mut() as *mut T) } } /// Consumes and leaks the `Box`, returning a mutable reference, @@ -280,7 +460,7 @@ impl<T: ?Sized> Box<T> { /// This conversion does not allocate on the heap and happens in place. /// /// This is also available via [`From`]. - #[unstable(feature = "box_into_pin", issue = "0")] + #[unstable(feature = "box_into_pin", issue = "62370")] pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>> { // It's not possible to move or replace the insides of a `Pin<Box<T>>` // when `T: !Unpin`, so it's safe to pin it directly without any @@ -327,12 +507,19 @@ impl<T: Clone> Clone for Box<T> { /// ``` /// let x = Box::new(5); /// let y = x.clone(); + /// + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // But they are unique objects + /// assert_ne!(&*x as *const i32, &*y as *const i32); /// ``` #[rustfmt::skip] #[inline] fn clone(&self) -> Box<T> { box { (**self).clone() } } + /// Copies `source`'s contents into `self` without creating a new allocation. /// /// # Examples @@ -340,10 +527,15 @@ impl<T: Clone> Clone for Box<T> { /// ``` /// let x = Box::new(5); /// let mut y = Box::new(10); + /// let yp: *const i32 = &*y; /// /// y.clone_from(&x); /// - /// assert_eq!(*y, 5); + /// // The value is the same + /// assert_eq!(x, y); + /// + /// // And no allocation occurred + /// assert_eq!(yp, &*y); /// ``` #[inline] fn clone_from(&mut self, source: &Box<T>) { @@ -355,11 +547,10 @@ impl<T: Clone> Clone for Box<T> { #[stable(feature = "box_slice_clone", since = "1.3.0")] impl Clone for Box<str> { fn clone(&self) -> Self { - let len = self.len(); - let buf = RawVec::with_capacity(len); + // this makes a copy of the data + let buf: Box<[u8]> = self.as_bytes().into(); unsafe { - ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); - from_boxed_utf8_unchecked(buf.into_box()) + from_boxed_utf8_unchecked(buf) } } } @@ -506,9 +697,12 @@ impl<T: Copy> From<&[T]> for Box<[T]> { /// println!("{:?}", boxed_slice); /// ``` fn from(slice: &[T]) -> Box<[T]> { - let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() }; - boxed.copy_from_slice(slice); - boxed + let len = slice.len(); + let buf = RawVec::with_capacity(len); + unsafe { + ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len); + buf.into_box() + } } } @@ -554,6 +748,22 @@ impl From<Box<str>> for Box<[u8]> { } } +#[unstable(feature = "boxed_slice_try_from", issue = "0")] +impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> +where + [T; N]: LengthAtMost32, +{ + type Error = Box<[T]>; + + fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> { + if boxed_slice.len() == N { + Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + impl Box<dyn Any> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -674,6 +884,14 @@ impl<I: Iterator + ?Sized> Iterator for Box<I> { (**self).nth(n) } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl<I: Iterator + Sized> Iterator for Box<I> { + fn last(self) -> Option<I::Item> where I: Sized { + (*self).last() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> { fn next_back(&mut self) -> Option<I::Item> { @@ -719,61 +937,6 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> { } } -/// `FnBox` is a version of the `FnOnce` intended for use with boxed -/// closure objects. The idea is that where one would normally store a -/// `Box<dyn FnOnce()>` in a data structure, you should use -/// `Box<dyn FnBox()>`. The two traits behave essentially the same, except -/// that a `FnBox` closure can only be called if it is boxed. (Note -/// that `FnBox` may be deprecated in the future if `Box<dyn FnOnce()>` -/// closures become directly usable.) -/// -/// # Examples -/// -/// Here is a snippet of code which creates a hashmap full of boxed -/// once closures and then removes them one by one, calling each -/// closure as it is removed. Note that the type of the closures -/// stored in the map is `Box<dyn FnBox() -> i32>` and not `Box<dyn FnOnce() -/// -> i32>`. -/// -/// ``` -/// #![feature(fnbox)] -/// -/// use std::boxed::FnBox; -/// use std::collections::HashMap; -/// -/// fn make_map() -> HashMap<i32, Box<dyn FnBox() -> i32>> { -/// let mut map: HashMap<i32, Box<dyn FnBox() -> i32>> = HashMap::new(); -/// map.insert(1, Box::new(|| 22)); -/// map.insert(2, Box::new(|| 44)); -/// map -/// } -/// -/// fn main() { -/// let mut map = make_map(); -/// for i in &[1, 2] { -/// let f = map.remove(&i).unwrap(); -/// assert_eq!(f(), i * 22); -/// } -/// } -/// ``` -#[rustc_paren_sugar] -#[unstable(feature = "fnbox", - reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")] -pub trait FnBox<A>: FnOnce<A> { - /// Performs the call operation. - fn call_box(self: Box<Self>, args: A) -> Self::Output; -} - -#[unstable(feature = "fnbox", - reason = "will be deprecated if and when `Box<FnOnce>` becomes usable", issue = "28796")] -impl<A, F> FnBox<A> for F - where F: FnOnce<A> -{ - fn call_box(self: Box<F>, args: A) -> F::Output { - self.call_once(args) - } -} - #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {} diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 39fcfaa7893..3d04f30e7bd 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -231,6 +231,20 @@ use super::SpecExtend; /// assert_eq!(heap.pop(), Some(Reverse(5))); /// assert_eq!(heap.pop(), None); /// ``` +/// +/// # Time complexity +/// +/// | [push] | [pop] | [peek]/[peek\_mut] | +/// |--------|----------|--------------------| +/// | O(1)~ | O(log n) | O(1) | +/// +/// The value for `push` is an expected cost; the method documentation gives a +/// more detailed analysis. +/// +/// [push]: #method.push +/// [pop]: #method.pop +/// [peek]: #method.peek +/// [peek\_mut]: #method.peek_mut #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap<T> { data: Vec<T>, @@ -384,6 +398,10 @@ impl<T: Ord> BinaryHeap<T> { /// } /// assert_eq!(heap.peek(), Some(&2)); /// ``` + /// + /// # Time complexity + /// + /// 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<PeekMut<'_, T>> { if self.is_empty() { @@ -411,6 +429,11 @@ impl<T: Ord> BinaryHeap<T> { /// assert_eq!(heap.pop(), Some(1)); /// assert_eq!(heap.pop(), None); /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop` on a heap containing *n* elements is O(log + /// n). #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option<T> { self.data.pop().map(|mut item| { @@ -438,6 +461,22 @@ impl<T: Ord> BinaryHeap<T> { /// assert_eq!(heap.len(), 3); /// assert_eq!(heap.peek(), Some(&5)); /// ``` + /// + /// # Time complexity + /// + /// The expected cost of `push`, averaged over every possible ordering of + /// the elements being pushed, and over a sufficiently large number of + /// pushes, is O(1). This is the most meaningful cost metric when pushing + /// elements that are *not* already in any sorted pattern. + /// + /// The time complexity degrades if elements are pushed in predominantly + /// ascending order. In the worst case, elements are pushed in ascending + /// sorted order and the amortized cost per push is O(log n) against a heap + /// containing *n* elements. + /// + /// The worst case cost of a *single* call to `push` is O(n). The worst case + /// occurs when capacity is exhausted and needs a resize. The resize cost + /// has been amortized in the previous figures. #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, item: T) { let old_len = self.len(); @@ -650,6 +689,10 @@ impl<T> BinaryHeap<T> { /// assert_eq!(heap.peek(), Some(&5)); /// /// ``` + /// + /// # Time complexity + /// + /// Cost is O(1) in the worst case. #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&self) -> Option<&T> { self.data.get(0) @@ -994,8 +1037,8 @@ impl<'a, T> Iterator for Iter<'a, T> { } #[inline] - fn last(mut self) -> Option<&'a T> { - self.next_back() + fn last(self) -> Option<&'a T> { + self.iter.last() } } @@ -1052,11 +1095,6 @@ impl<T> Iterator for IntoIter<T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } - - #[inline] - fn last(mut self) -> Option<T> { - self.next_back() - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1103,11 +1141,6 @@ impl<T> Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } - - #[inline] - fn last(mut self) -> Option<T> { - self.next_back() - } } #[stable(feature = "drain", since = "1.6.0")] @@ -1130,6 +1163,9 @@ impl<T> FusedIterator for Drain<'_, T> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl<T: Ord> From<Vec<T>> for BinaryHeap<T> { + /// Converts a `Vec<T>` into a `BinaryHeap<T>`. + /// + /// This conversion happens in-place, and has `O(n)` time complexity. fn from(vec: Vec<T>) -> BinaryHeap<T> { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 414abb00ef1..1683b810556 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -75,10 +75,10 @@ use Entry::*; /// /// // look up the values associated with some keys. /// let to_find = ["Up!", "Office Space"]; -/// for book in &to_find { -/// match movie_reviews.get(book) { -/// Some(review) => println!("{}: {}", book, review), -/// None => println!("{} is unreviewed.", book) +/// for movie in &to_find { +/// match movie_reviews.get(movie) { +/// Some(review) => println!("{}: {}", movie, review), +/// None => println!("{} is unreviewed.", movie) /// } /// } /// @@ -200,7 +200,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> { } } - if self.len() == 0 { + if self.is_empty() { // Ideally we'd call `BTreeMap::new` here, but that has the `K: // Ord` constraint, which this method lacks. BTreeMap { @@ -759,19 +759,19 @@ impl<K: Ord, V> BTreeMap<K, V> { #[stable(feature = "btree_append", since = "1.11.0")] pub fn append(&mut self, other: &mut Self) { // Do we have to append anything at all? - if other.len() == 0 { + if other.is_empty() { return; } // We can just swap `self` and `other` if `self` is empty. - if self.len() == 0 { + if self.is_empty() { mem::swap(self, other); return; } // First, we merge `self` and `other` into a sorted sequence in linear time. - let self_iter = mem::replace(self, BTreeMap::new()).into_iter(); - let other_iter = mem::replace(other, BTreeMap::new()).into_iter(); + let self_iter = mem::take(self).into_iter(); + let other_iter = mem::take(other).into_iter(); let iter = MergeIter { left: self_iter.peekable(), right: other_iter.peekable(), @@ -1194,7 +1194,6 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { (self.length, Some(self.length)) } - #[inline] fn last(mut self) -> Option<(&'a K, &'a V)> { self.next_back() } @@ -1259,7 +1258,6 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { (self.length, Some(self.length)) } - #[inline] fn last(mut self) -> Option<(&'a K, &'a mut V)> { self.next_back() } @@ -1369,11 +1367,6 @@ impl<K, V> Iterator for IntoIter<K, V> { fn size_hint(&self) -> (usize, Option<usize>) { (self.length, Some(self.length)) } - - #[inline] - fn last(mut self) -> Option<(K, V)> { - self.next_back() - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1437,7 +1430,6 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { self.inner.size_hint() } - #[inline] fn last(mut self) -> Option<&'a K> { self.next_back() } @@ -1479,7 +1471,6 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { self.inner.size_hint() } - #[inline] fn last(mut self) -> Option<&'a V> { self.next_back() } @@ -1521,7 +1512,6 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { } } - #[inline] fn last(mut self) -> Option<(&'a K, &'a V)> { self.next_back() } @@ -1539,7 +1529,6 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { self.inner.size_hint() } - #[inline] fn last(mut self) -> Option<&'a mut V> { self.next_back() } @@ -1662,7 +1651,6 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { } } - #[inline] fn last(mut self) -> Option<(&'a K, &'a mut V)> { self.next_back() } @@ -2044,7 +2032,7 @@ impl<K, V> BTreeMap<K, V> { /// assert_eq!(keys, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { + pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.iter() } } @@ -2065,7 +2053,7 @@ impl<K, V> BTreeMap<K, V> { /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn values<'a>(&'a self) -> Values<'a, K, V> { + pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.iter() } } @@ -2569,8 +2557,8 @@ enum UnderflowResult<'a, K, V> { Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>), } -fn handle_underfull_node<'a, K, V>(node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>) - -> UnderflowResult<'a, K, V> { +fn handle_underfull_node<K, V>(node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>) + -> UnderflowResult<'_, K, V> { let parent = if let Ok(parent) = node.ascend() { parent } else { diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 581c66c7086..0b5a271dbea 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -106,8 +106,8 @@ impl<K, V> LeafNode<K, V> { LeafNode { // As a general policy, we leave fields uninitialized if they can be, as this should // be both slightly faster and easier to track in Valgrind. - keys: uninitialized_array![_; CAPACITY], - vals: uninitialized_array![_; CAPACITY], + keys: [MaybeUninit::UNINIT; CAPACITY], + vals: [MaybeUninit::UNINIT; CAPACITY], parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 @@ -159,7 +159,7 @@ impl<K, V> InternalNode<K, V> { unsafe fn new() -> Self { InternalNode { data: LeafNode::new(), - edges: uninitialized_array![_; 2*B], + edges: [MaybeUninit::UNINIT; 2*B] } } } @@ -394,7 +394,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { } /// Temporarily takes out another, immutable reference to the same node. - fn reborrow<'a>(&'a self) -> NodeRef<marker::Immut<'a>, K, V, Type> { + fn reborrow(&self) -> NodeRef<marker::Immut<'_>, K, V, Type> { NodeRef { height: self.height, node: self.node, diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 6f2467dfd6b..d3af910a82c 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -1019,8 +1019,6 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } - - #[inline] fn last(mut self) -> Option<&'a T> { self.next_back() } @@ -1049,11 +1047,6 @@ impl<T> Iterator for IntoIter<T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } - - #[inline] - fn last(mut self) -> Option<T> { - self.next_back() - } } #[stable(feature = "rust1", since = "1.0.0")] impl<T> DoubleEndedIterator for IntoIter<T> { @@ -1084,7 +1077,6 @@ impl<'a, T> Iterator for Range<'a, T> { self.iter.next().map(|(k, _)| k) } - #[inline] fn last(mut self) -> Option<&'a T> { self.next_back() } diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 40a82d6feaa..a14a3fe9994 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -23,6 +23,9 @@ use core::ptr::NonNull; use crate::boxed::Box; use super::SpecExtend; +#[cfg(test)] +mod tests; + /// A doubly-linked list with owned nodes. /// /// The `LinkedList` allows pushing and popping elements at either end @@ -237,15 +240,15 @@ impl<T> LinkedList<T> { // Not creating new mutable (unique!) references overlapping `element`. match node.prev { - Some(prev) => (*prev.as_ptr()).next = node.next.clone(), + Some(prev) => (*prev.as_ptr()).next = node.next, // this node is the head node - None => self.head = node.next.clone(), + None => self.head = node.next, }; match node.next { - Some(next) => (*next.as_ptr()).prev = node.prev.clone(), + Some(next) => (*next.as_ptr()).prev = node.prev, // this node is the tail node - None => self.tail = node.prev.clone(), + None => self.tail = node.prev, }; self.len -= 1; @@ -708,7 +711,7 @@ impl<T> LinkedList<T> { let len = self.len(); assert!(at <= len, "Cannot split off at a nonexistent index"); if at == 0 { - return mem::replace(self, Self::new()); + return mem::take(self); } else if at == len { return Self::new(); } @@ -832,6 +835,11 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option<usize>) { (self.len, Some(self.len)) } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -881,6 +889,11 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn size_hint(&self) -> (usize, Option<usize>) { (self.len, Some(self.len)) } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1234,273 +1247,3 @@ unsafe impl<T: Send> Send for IterMut<'_, T> {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<T: Sync> Sync for IterMut<'_, T> {} - -#[cfg(test)] -mod tests { - use std::thread; - use std::vec::Vec; - - use rand::{thread_rng, RngCore}; - - use super::{LinkedList, Node}; - - #[cfg(test)] - fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { - v.iter().cloned().collect() - } - - pub fn check_links<T>(list: &LinkedList<T>) { - unsafe { - let mut len = 0; - let mut last_ptr: Option<&Node<T>> = None; - let mut node_ptr: &Node<T>; - match list.head { - None => { - // tail node should also be None. - assert!(list.tail.is_none()); - assert_eq!(0, list.len); - return; - } - Some(node) => node_ptr = &*node.as_ptr(), - } - loop { - match (last_ptr, node_ptr.prev) { - (None, None) => {} - (None, _) => panic!("prev link for head"), - (Some(p), Some(pptr)) => { - assert_eq!(p as *const Node<T>, pptr.as_ptr() as *const Node<T>); - } - _ => panic!("prev link is none, not good"), - } - match node_ptr.next { - Some(next) => { - last_ptr = Some(node_ptr); - node_ptr = &*next.as_ptr(); - len += 1; - } - None => { - len += 1; - break; - } - } - } - - // verify that the tail node points to the last node. - let tail = list.tail.as_ref().expect("some tail node").as_ref(); - assert_eq!(tail as *const Node<T>, node_ptr as *const Node<T>); - // check that len matches interior links. - assert_eq!(len, list.len); - } - } - - #[test] - fn test_append() { - // Empty to empty - { - let mut m = LinkedList::<i32>::new(); - let mut n = LinkedList::new(); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 0); - assert_eq!(n.len(), 0); - } - // Non-empty to empty - { - let mut m = LinkedList::new(); - let mut n = LinkedList::new(); - n.push_back(2); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - assert_eq!(n.len(), 0); - check_links(&m); - } - // Empty to non-empty - { - let mut m = LinkedList::new(); - let mut n = LinkedList::new(); - m.push_back(2); - m.append(&mut n); - check_links(&m); - assert_eq!(m.len(), 1); - assert_eq!(m.pop_back(), Some(2)); - check_links(&m); - } - - // Non-empty to non-empty - let v = vec![1, 2, 3, 4, 5]; - let u = vec![9, 8, 1, 2, 3, 4, 5]; - let mut m = list_from(&v); - let mut n = list_from(&u); - m.append(&mut n); - check_links(&m); - let mut sum = v; - sum.extend_from_slice(&u); - assert_eq!(sum.len(), m.len()); - for elt in sum { - assert_eq!(m.pop_front(), Some(elt)) - } - assert_eq!(n.len(), 0); - // let's make sure it's working properly, since we - // did some direct changes to private members - n.push_back(3); - assert_eq!(n.len(), 1); - assert_eq!(n.pop_front(), Some(3)); - check_links(&n); - } - - #[test] - fn test_insert_prev() { - let mut m = list_from(&[0, 2, 4, 6, 8]); - let len = m.len(); - { - let mut it = m.iter_mut(); - it.insert_next(-2); - loop { - match it.next() { - None => break, - Some(elt) => { - it.insert_next(*elt + 1); - match it.peek_next() { - Some(x) => assert_eq!(*x, *elt + 2), - None => assert_eq!(8, *elt), - } - } - } - } - it.insert_next(0); - it.insert_next(1); - } - check_links(&m); - assert_eq!(m.len(), 3 + len * 2); - assert_eq!(m.into_iter().collect::<Vec<_>>(), - [-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg(not(miri))] // Miri does not support threads - fn test_send() { - let n = list_from(&[1, 2, 3]); - thread::spawn(move || { - check_links(&n); - let a: &[_] = &[&1, &2, &3]; - assert_eq!(a, &*n.iter().collect::<Vec<_>>()); - }) - .join() - .ok() - .unwrap(); - } - - #[test] - fn test_fuzz() { - for _ in 0..25 { - fuzz_test(3); - fuzz_test(16); - #[cfg(not(miri))] // Miri is too slow - fuzz_test(189); - } - } - - #[test] - fn test_26021() { - // There was a bug in split_off that failed to null out the RHS's head's prev ptr. - // This caused the RHS's dtor to walk up into the LHS at drop and delete all of - // its nodes. - // - // https://github.com/rust-lang/rust/issues/26021 - let mut v1 = LinkedList::new(); - v1.push_front(1); - v1.push_front(1); - v1.push_front(1); - v1.push_front(1); - let _ = v1.split_off(3); // Dropping this now should not cause laundry consumption - assert_eq!(v1.len(), 3); - - assert_eq!(v1.iter().len(), 3); - assert_eq!(v1.iter().collect::<Vec<_>>().len(), 3); - } - - #[test] - fn test_split_off() { - let mut v1 = LinkedList::new(); - v1.push_front(1); - v1.push_front(1); - v1.push_front(1); - v1.push_front(1); - - // test all splits - for ix in 0..1 + v1.len() { - let mut a = v1.clone(); - let b = a.split_off(ix); - check_links(&a); - check_links(&b); - a.extend(b); - assert_eq!(v1, a); - } - } - - #[cfg(test)] - fn fuzz_test(sz: i32) { - let mut m: LinkedList<_> = LinkedList::new(); - let mut v = vec![]; - for i in 0..sz { - check_links(&m); - let r: u8 = thread_rng().next_u32() as u8; - match r % 6 { - 0 => { - m.pop_back(); - v.pop(); - } - 1 => { - if !v.is_empty() { - m.pop_front(); - v.remove(0); - } - } - 2 | 4 => { - m.push_front(-i); - v.insert(0, -i); - } - 3 | 5 | _ => { - m.push_back(i); - v.push(i); - } - } - } - - check_links(&m); - - let mut i = 0; - for (a, &b) in m.into_iter().zip(&v) { - i += 1; - assert_eq!(a, b); - } - assert_eq!(i, v.len()); - } - - #[test] - fn drain_filter_test() { - let mut m: LinkedList<u32> = LinkedList::new(); - m.extend(&[1, 2, 3, 4, 5, 6]); - let deleted = m.drain_filter(|v| *v < 4).collect::<Vec<_>>(); - - check_links(&m); - - assert_eq!(deleted, &[1, 2, 3]); - assert_eq!(m.into_iter().collect::<Vec<_>>(), &[4, 5, 6]); - } - - #[test] - fn drain_to_empty_test() { - let mut m: LinkedList<u32> = LinkedList::new(); - m.extend(&[1, 2, 3, 4, 5, 6]); - let deleted = m.drain_filter(|_| true).collect::<Vec<_>>(); - - check_links(&m); - - assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]); - assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]); - } -} diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs new file mode 100644 index 00000000000..9a6c57d2869 --- /dev/null +++ b/src/liballoc/collections/linked_list/tests.rs @@ -0,0 +1,264 @@ +use super::*; + +use std::thread; +use std::vec::Vec; + +use rand::{thread_rng, RngCore}; + +fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { + v.iter().cloned().collect() +} + +pub fn check_links<T>(list: &LinkedList<T>) { + unsafe { + let mut len = 0; + let mut last_ptr: Option<&Node<T>> = None; + let mut node_ptr: &Node<T>; + match list.head { + None => { + // tail node should also be None. + assert!(list.tail.is_none()); + assert_eq!(0, list.len); + return; + } + Some(node) => node_ptr = &*node.as_ptr(), + } + loop { + match (last_ptr, node_ptr.prev) { + (None, None) => {} + (None, _) => panic!("prev link for head"), + (Some(p), Some(pptr)) => { + assert_eq!(p as *const Node<T>, pptr.as_ptr() as *const Node<T>); + } + _ => panic!("prev link is none, not good"), + } + match node_ptr.next { + Some(next) => { + last_ptr = Some(node_ptr); + node_ptr = &*next.as_ptr(); + len += 1; + } + None => { + len += 1; + break; + } + } + } + + // verify that the tail node points to the last node. + let tail = list.tail.as_ref().expect("some tail node").as_ref(); + assert_eq!(tail as *const Node<T>, node_ptr as *const Node<T>); + // check that len matches interior links. + assert_eq!(len, list.len); + } +} + +#[test] +fn test_append() { + // Empty to empty + { + let mut m = LinkedList::<i32>::new(); + let mut n = LinkedList::new(); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 0); + assert_eq!(n.len(), 0); + } + // Non-empty to empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + n.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + assert_eq!(n.len(), 0); + check_links(&m); + } + // Empty to non-empty + { + let mut m = LinkedList::new(); + let mut n = LinkedList::new(); + m.push_back(2); + m.append(&mut n); + check_links(&m); + assert_eq!(m.len(), 1); + assert_eq!(m.pop_back(), Some(2)); + check_links(&m); + } + + // Non-empty to non-empty + let v = vec![1, 2, 3, 4, 5]; + let u = vec![9, 8, 1, 2, 3, 4, 5]; + let mut m = list_from(&v); + let mut n = list_from(&u); + m.append(&mut n); + check_links(&m); + let mut sum = v; + sum.extend_from_slice(&u); + assert_eq!(sum.len(), m.len()); + for elt in sum { + assert_eq!(m.pop_front(), Some(elt)) + } + assert_eq!(n.len(), 0); + // let's make sure it's working properly, since we + // did some direct changes to private members + n.push_back(3); + assert_eq!(n.len(), 1); + assert_eq!(n.pop_front(), Some(3)); + check_links(&n); +} + +#[test] +fn test_insert_prev() { + let mut m = list_from(&[0, 2, 4, 6, 8]); + let len = m.len(); + { + let mut it = m.iter_mut(); + it.insert_next(-2); + loop { + match it.next() { + None => break, + Some(elt) => { + it.insert_next(*elt + 1); + match it.peek_next() { + Some(x) => assert_eq!(*x, *elt + 2), + None => assert_eq!(8, *elt), + } + } + } + } + it.insert_next(0); + it.insert_next(1); + } + check_links(&m); + assert_eq!(m.len(), 3 + len * 2); + assert_eq!(m.into_iter().collect::<Vec<_>>(), + [-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +#[cfg(not(miri))] // Miri does not support threads +fn test_send() { + let n = list_from(&[1, 2, 3]); + thread::spawn(move || { + check_links(&n); + let a: &[_] = &[&1, &2, &3]; + assert_eq!(a, &*n.iter().collect::<Vec<_>>()); + }) + .join() + .ok() + .unwrap(); +} + +#[test] +fn test_fuzz() { + for _ in 0..25 { + fuzz_test(3); + fuzz_test(16); + #[cfg(not(miri))] // Miri is too slow + fuzz_test(189); + } +} + +#[test] +fn test_26021() { + // There was a bug in split_off that failed to null out the RHS's head's prev ptr. + // This caused the RHS's dtor to walk up into the LHS at drop and delete all of + // its nodes. + // + // https://github.com/rust-lang/rust/issues/26021 + let mut v1 = LinkedList::new(); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + let _ = v1.split_off(3); // Dropping this now should not cause laundry consumption + assert_eq!(v1.len(), 3); + + assert_eq!(v1.iter().len(), 3); + assert_eq!(v1.iter().collect::<Vec<_>>().len(), 3); +} + +#[test] +fn test_split_off() { + let mut v1 = LinkedList::new(); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + v1.push_front(1); + + // test all splits + for ix in 0..1 + v1.len() { + let mut a = v1.clone(); + let b = a.split_off(ix); + check_links(&a); + check_links(&b); + a.extend(b); + assert_eq!(v1, a); + } +} + +fn fuzz_test(sz: i32) { + let mut m: LinkedList<_> = LinkedList::new(); + let mut v = vec![]; + for i in 0..sz { + check_links(&m); + let r: u8 = thread_rng().next_u32() as u8; + match r % 6 { + 0 => { + m.pop_back(); + v.pop(); + } + 1 => { + if !v.is_empty() { + m.pop_front(); + v.remove(0); + } + } + 2 | 4 => { + m.push_front(-i); + v.insert(0, -i); + } + 3 | 5 | _ => { + m.push_back(i); + v.push(i); + } + } + } + + check_links(&m); + + let mut i = 0; + for (a, &b) in m.into_iter().zip(&v) { + i += 1; + assert_eq!(a, b); + } + assert_eq!(i, v.len()); +} + +#[test] +fn drain_filter_test() { + let mut m: LinkedList<u32> = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.drain_filter(|v| *v < 4).collect::<Vec<_>>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3]); + assert_eq!(m.into_iter().collect::<Vec<_>>(), &[4, 5, 6]); +} + +#[test] +fn drain_to_empty_test() { + let mut m: LinkedList<u32> = LinkedList::new(); + m.extend(&[1, 2, 3, 4, 5, 6]); + let deleted = m.drain_filter(|_| true).collect::<Vec<_>>(); + + check_links(&m); + + assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]); + assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]); +} diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs index 5a33ddc14f0..f1f22fe48c5 100644 --- a/src/liballoc/collections/mod.rs +++ b/src/liballoc/collections/mod.rs @@ -41,32 +41,35 @@ pub use linked_list::LinkedList; #[doc(no_inline)] pub use vec_deque::VecDeque; -use crate::alloc::{AllocErr, LayoutErr}; +use crate::alloc::{Layout, LayoutErr}; -/// Augments `AllocErr` with a CapacityOverflow variant. +/// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub enum CollectionAllocErr { +pub enum TryReserveError { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). CapacityOverflow, - /// Error due to the allocator (see the `AllocErr` type's docs). - AllocErr, -} -#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -impl From<AllocErr> for CollectionAllocErr { - #[inline] - fn from(AllocErr: AllocErr) -> Self { - CollectionAllocErr::AllocErr - } + /// The memory allocator returned an error + AllocError { + /// The layout of allocation request that failed + layout: Layout, + + #[doc(hidden)] + #[unstable(feature = "container_error_extra", issue = "0", reason = "\ + Enable exposing the allocator’s custom error value \ + if an associated type is added in the future: \ + https://github.com/rust-lang/wg-allocators/issues/23")] + non_exhaustive: (), + }, } #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -impl From<LayoutErr> for CollectionAllocErr { +impl From<LayoutErr> for TryReserveError { #[inline] fn from(_: LayoutErr) -> Self { - CollectionAllocErr::CapacityOverflow + TryReserveError::CapacityOverflow } } diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 9a8d48083e6..7315963cc8b 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1,5 +1,3 @@ -// ignore-tidy-filelength - //! A double-ended queue implemented with a growable ring buffer. //! //! This queue has `O(1)` amortized inserts and removals from both ends of the @@ -9,6 +7,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use core::array::LengthAtMost32; use core::cmp::{self, Ordering}; use core::fmt; use core::iter::{repeat_with, FromIterator, FusedIterator}; @@ -19,10 +18,13 @@ use core::ptr::{self, NonNull}; use core::slice; use core::hash::{Hash, Hasher}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::raw_vec::RawVec; use crate::vec::Vec; +#[cfg(test)] +mod tests; + const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 #[cfg(target_pointer_width = "16")] @@ -98,7 +100,7 @@ impl<T> VecDeque<T> { // For zero sized types, we are always at maximum capacity MAXIMUM_ZST_CAPACITY } else { - self.buf.cap() + self.buf.capacity() } } @@ -314,10 +316,10 @@ impl<T> VecDeque<T> { } /// Frobs the head and tail sections around to handle the fact that we - /// just reallocated. Unsafe because it trusts old_cap. + /// just reallocated. Unsafe because it trusts old_capacity. #[inline] - unsafe fn handle_cap_increase(&mut self, old_cap: usize) { - let new_cap = self.cap(); + unsafe fn handle_capacity_increase(&mut self, old_capacity: usize) { + let new_capacity = self.cap(); // Move the shortest contiguous section of the ring buffer // T H @@ -336,15 +338,15 @@ impl<T> VecDeque<T> { if self.tail <= self.head { // A // Nop - } else if self.head < old_cap - self.tail { + } else if self.head < old_capacity - self.tail { // B - self.copy_nonoverlapping(old_cap, 0, self.head); - self.head += old_cap; + self.copy_nonoverlapping(old_capacity, 0, self.head); + self.head += old_capacity; debug_assert!(self.head > self.tail); } else { // C - let new_tail = new_cap - (old_cap - self.tail); - self.copy_nonoverlapping(new_tail, self.tail, old_cap - self.tail); + let new_tail = new_capacity - (old_capacity - self.tail); + self.copy_nonoverlapping(new_tail, self.tail, old_capacity - self.tail); self.tail = new_tail; debug_assert!(self.head < self.tail); } @@ -551,7 +553,7 @@ impl<T> VecDeque<T> { if new_cap > old_cap { self.buf.reserve_exact(used_cap, new_cap - used_cap); unsafe { - self.handle_cap_increase(old_cap); + self.handle_capacity_increase(old_cap); } } } @@ -574,10 +576,10 @@ impl<T> VecDeque<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// - /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> { /// let mut output = VecDeque::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -593,7 +595,7 @@ impl<T> VecDeque<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.try_reserve(additional) } @@ -612,10 +614,10 @@ impl<T> VecDeque<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// - /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> { /// let mut output = VecDeque::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -631,17 +633,17 @@ impl<T> VecDeque<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { let old_cap = self.cap(); let used_cap = self.len() + 1; let new_cap = used_cap.checked_add(additional) .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) - .ok_or(CollectionAllocErr::CapacityOverflow)?; + .ok_or(TryReserveError::CapacityOverflow)?; if new_cap > old_cap { self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; unsafe { - self.handle_cap_increase(old_cap); + self.handle_capacity_increase(old_cap); } } Ok(()) @@ -1197,6 +1199,31 @@ impl<T> VecDeque<T> { } } + /// Removes the last element from the `VecDeque` and returns it, or `None` if + /// it is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.pop_back(), None); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(buf.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option<T> { + if self.is_empty() { + None + } else { + self.head = self.wrap_sub(self.head, 1); + let head = self.head; + unsafe { Some(self.buffer_read(head)) } + } + } + /// Prepends an element to the `VecDeque`. /// /// # Examples @@ -1241,38 +1268,13 @@ impl<T> VecDeque<T> { unsafe { self.buffer_write(head, value) } } - /// Removes the last element from the `VecDeque` and returns it, or `None` if - /// it is empty. - /// - /// # Examples - /// - /// ``` - /// use std::collections::VecDeque; - /// - /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.pop_back(), None); - /// buf.push_back(1); - /// buf.push_back(3); - /// assert_eq!(buf.pop_back(), Some(3)); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn pop_back(&mut self) -> Option<T> { - if self.is_empty() { - None - } else { - self.head = self.wrap_sub(self.head, 1); - let head = self.head; - unsafe { Some(self.buffer_read(head)) } - } - } - #[inline] fn is_contiguous(&self) -> bool { self.tail <= self.head } - /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the - /// last element. + /// Removes an element from anywhere in the `VecDeque` and returns it, + /// replacing it with the first element. /// /// This does not preserve ordering, but is O(1). /// @@ -1286,28 +1288,28 @@ impl<T> VecDeque<T> { /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.swap_remove_back(0), None); + /// assert_eq!(buf.swap_remove_front(0), None); /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// assert_eq!(buf, [1, 2, 3]); /// - /// assert_eq!(buf.swap_remove_back(0), Some(1)); - /// assert_eq!(buf, [3, 2]); + /// assert_eq!(buf.swap_remove_front(2), Some(3)); + /// assert_eq!(buf, [2, 1]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] - pub fn swap_remove_back(&mut self, index: usize) -> Option<T> { + pub fn swap_remove_front(&mut self, index: usize) -> Option<T> { let length = self.len(); - if length > 0 && index < length - 1 { - self.swap(index, length - 1); + if length > 0 && index < length && index != 0 { + self.swap(index, 0); } else if index >= length { return None; } - self.pop_back() + self.pop_front() } - /// Removes an element from anywhere in the `VecDeque` and returns it, - /// replacing it with the first element. + /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the + /// last element. /// /// This does not preserve ordering, but is O(1). /// @@ -1321,24 +1323,24 @@ impl<T> VecDeque<T> { /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.swap_remove_front(0), None); + /// assert_eq!(buf.swap_remove_back(0), None); /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// assert_eq!(buf, [1, 2, 3]); /// - /// assert_eq!(buf.swap_remove_front(2), Some(3)); - /// assert_eq!(buf, [2, 1]); + /// assert_eq!(buf.swap_remove_back(0), Some(1)); + /// assert_eq!(buf, [3, 2]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] - pub fn swap_remove_front(&mut self, index: usize) -> Option<T> { + pub fn swap_remove_back(&mut self, index: usize) -> Option<T> { let length = self.len(); - if length > 0 && index < length && index != 0 { - self.swap(index, 0); + if length > 0 && index < length - 1 { + self.swap(index, length - 1); } else if index >= length { return None; } - self.pop_front() + self.pop_back() } /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices @@ -1887,7 +1889,7 @@ impl<T> VecDeque<T> { let old_cap = self.cap(); self.buf.double(); unsafe { - self.handle_cap_increase(old_cap); + self.handle_capacity_increase(old_cap); } debug_assert!(!self.is_full()); } @@ -1948,8 +1950,6 @@ impl<T> VecDeque<T> { /// # Examples /// /// ``` - /// #![feature(vecdeque_rotate)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = (0..10).collect(); @@ -1963,7 +1963,7 @@ impl<T> VecDeque<T> { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[unstable(feature = "vecdeque_rotate", issue = "56686")] + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] pub fn rotate_left(&mut self, mid: usize) { assert!(mid <= self.len()); let k = self.len() - mid; @@ -1993,8 +1993,6 @@ impl<T> VecDeque<T> { /// # Examples /// /// ``` - /// #![feature(vecdeque_rotate)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = (0..10).collect(); @@ -2008,7 +2006,7 @@ impl<T> VecDeque<T> { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[unstable(feature = "vecdeque_rotate", issue = "56686")] + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] pub fn rotate_right(&mut self, k: usize) { assert!(k <= self.len()); let mid = self.len() - k; @@ -2210,6 +2208,11 @@ impl<'a, T> Iterator for Iter<'a, T> { self.tail = self.head - iter.len(); final_res } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2323,6 +2326,11 @@ impl<'a, T> Iterator for IterMut<'a, T> { accum = front.iter_mut().fold(accum, &mut f); back.iter_mut().fold(accum, &mut f) } + + #[inline] + fn last(mut self) -> Option<&'a mut T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2565,13 +2573,14 @@ impl<A: PartialEq> PartialEq for VecDeque<A> { impl<A: Eq> Eq for VecDeque<A> {} macro_rules! __impl_slice_eq1 { - ($Lhs: ty, $Rhs: ty) => { - __impl_slice_eq1! { $Lhs, $Rhs, Sized } - }; - ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] - impl<A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> { - fn eq(&self, other: &$Rhs) -> bool { + impl<A, B, $($vars)*> PartialEq<$rhs> for $lhs + where + A: PartialEq<B>, + $($constraints)* + { + fn eq(&self, other: &$rhs) -> bool { if self.len() != other.len() { return false; } @@ -2583,26 +2592,12 @@ macro_rules! __impl_slice_eq1 { } } -__impl_slice_eq1! { VecDeque<A>, Vec<B> } -__impl_slice_eq1! { VecDeque<A>, &[B] } -__impl_slice_eq1! { VecDeque<A>, &mut [B] } - -macro_rules! array_impls { - ($($N: expr)+) => { - $( - __impl_slice_eq1! { VecDeque<A>, [B; $N] } - __impl_slice_eq1! { VecDeque<A>, &[B; $N] } - __impl_slice_eq1! { VecDeque<A>, &mut [B; $N] } - )+ - } -} - -array_impls! { - 0 1 2 3 4 5 6 7 8 9 - 10 11 12 13 14 15 16 17 18 19 - 20 21 22 23 24 25 26 27 28 29 - 30 31 32 -} +__impl_slice_eq1! { [] VecDeque<A>, Vec<B>, } +__impl_slice_eq1! { [] VecDeque<A>, &[B], } +__impl_slice_eq1! { [] VecDeque<A>, &mut [B], } +__impl_slice_eq1! { [const N: usize] VecDeque<A>, [B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [const N: usize] VecDeque<A>, &[B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [const N: usize] VecDeque<A>, &mut [B; N], [B; N]: LengthAtMost32 } #[stable(feature = "rust1", since = "1.0.0")] impl<A: PartialOrd> PartialOrd for VecDeque<A> { @@ -2713,6 +2708,14 @@ impl<T: fmt::Debug> fmt::Debug for VecDeque<T> { #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] impl<T> From<Vec<T>> for VecDeque<T> { + /// Turn a [`Vec<T>`] into a [`VecDeque<T>`]. + /// + /// [`Vec<T>`]: crate::vec::Vec + /// [`VecDeque<T>`]: crate::collections::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<T>` came from `From<VecDeque<T>>` and hasn't been reallocated. fn from(mut other: Vec<T>) -> Self { unsafe { let other_buf = other.as_mut_ptr(); @@ -2722,9 +2725,9 @@ impl<T> From<Vec<T>> for VecDeque<T> { // 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 - if !buf.cap().is_power_of_two() || (buf.cap() < (MINIMUM_CAPACITY + 1)) || - (buf.cap() == len) { - let cap = cmp::max(buf.cap() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + if !buf.capacity().is_power_of_two() || (buf.capacity() < (MINIMUM_CAPACITY + 1)) || + (buf.capacity() == len) { + let cap = cmp::max(buf.capacity() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); buf.reserve_exact(len, cap - len); } @@ -2739,6 +2742,35 @@ impl<T> From<Vec<T>> for VecDeque<T> { #[stable(feature = "vecdeque_vec_conversions", since = "1.10.0")] impl<T> From<VecDeque<T>> for Vec<T> { + /// Turn a [`VecDeque<T>`] into a [`Vec<T>`]. + /// + /// [`Vec<T>`]: crate::vec::Vec + /// [`VecDeque<T>`]: crate::collections::VecDeque + /// + /// This never needs to re-allocate, but does need to do O(n) data movement if + /// the circular buffer doesn't happen to be at the beginning of the allocation. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// // This one is O(1). + /// let deque: VecDeque<_> = (1..5).collect(); + /// let ptr = deque.as_slices().0.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// + /// // This one needs data rearranging. + /// let mut deque: VecDeque<_> = (1..5).collect(); + /// deque.push_front(9); + /// deque.push_front(8); + /// let ptr = deque.as_slices().1.as_ptr(); + /// let vec = Vec::from(deque); + /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]); + /// assert_eq!(vec.as_ptr(), ptr); + /// ``` fn from(other: VecDeque<T>) -> Self { unsafe { let buf = other.buf.ptr(); @@ -2807,387 +2839,3 @@ impl<T> From<VecDeque<T>> for Vec<T> { } } } - -#[cfg(test)] -mod tests { - use ::test; - - use super::VecDeque; - - #[bench] - #[cfg(not(miri))] // Miri does not support benchmarks - fn bench_push_back_100(b: &mut test::Bencher) { - let mut deq = VecDeque::with_capacity(101); - b.iter(|| { - for i in 0..100 { - deq.push_back(i); - } - deq.head = 0; - deq.tail = 0; - }) - } - - #[bench] - #[cfg(not(miri))] // Miri does not support benchmarks - fn bench_push_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::with_capacity(101); - b.iter(|| { - for i in 0..100 { - deq.push_front(i); - } - deq.head = 0; - deq.tail = 0; - }) - } - - #[bench] - #[cfg(not(miri))] // Miri does not support benchmarks - fn bench_pop_back_100(b: &mut test::Bencher) { - let mut deq = VecDeque::<i32>::with_capacity(101); - - b.iter(|| { - deq.head = 100; - deq.tail = 0; - while !deq.is_empty() { - test::black_box(deq.pop_back()); - } - }) - } - - #[bench] - #[cfg(not(miri))] // Miri does not support benchmarks - fn bench_pop_front_100(b: &mut test::Bencher) { - let mut deq = VecDeque::<i32>::with_capacity(101); - - b.iter(|| { - deq.head = 100; - deq.tail = 0; - while !deq.is_empty() { - test::black_box(deq.pop_front()); - } - }) - } - - #[test] - fn test_swap_front_back_remove() { - fn test(back: bool) { - // This test checks that every single combination of tail position and length is tested. - // Capacity 15 should be large enough to cover every case. - let mut tester = VecDeque::with_capacity(15); - let usable_cap = tester.capacity(); - let final_len = usable_cap / 2; - - for len in 0..final_len { - let expected: VecDeque<_> = if back { - (0..len).collect() - } else { - (0..len).rev().collect() - }; - for tail_pos in 0..usable_cap { - tester.tail = tail_pos; - tester.head = tail_pos; - if back { - for i in 0..len * 2 { - tester.push_front(i); - } - for i in 0..len { - assert_eq!(tester.swap_remove_back(i), Some(len * 2 - 1 - i)); - } - } else { - for i in 0..len * 2 { - tester.push_back(i); - } - for i in 0..len { - let idx = tester.len() - 1 - i; - assert_eq!(tester.swap_remove_front(idx), Some(len * 2 - 1 - i)); - } - } - assert!(tester.tail < tester.cap()); - assert!(tester.head < tester.cap()); - assert_eq!(tester, expected); - } - } - } - test(true); - test(false); - } - - #[test] - fn test_insert() { - // This test checks that every single combination of tail position, length, and - // insertion position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - - // len is the length *after* insertion - for len in 1..cap { - // 0, 1, 2, .., len - 1 - let expected = (0..).take(len).collect::<VecDeque<_>>(); - for tail_pos in 0..cap { - for to_insert in 0..len { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - if i != to_insert { - tester.push_back(i); - } - } - tester.insert(to_insert, to_insert); - assert!(tester.tail < tester.cap()); - assert!(tester.head < tester.cap()); - assert_eq!(tester, expected); - } - } - } - } - - #[test] - fn test_remove() { - // This test checks that every single combination of tail position, length, and - // removal position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - // len is the length *after* removal - for len in 0..cap - 1 { - // 0, 1, 2, .., len - 1 - let expected = (0..).take(len).collect::<VecDeque<_>>(); - for tail_pos in 0..cap { - for to_remove in 0..=len { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - if i == to_remove { - tester.push_back(1234); - } - tester.push_back(i); - } - if to_remove == len { - tester.push_back(1234); - } - tester.remove(to_remove); - assert!(tester.tail < tester.cap()); - assert!(tester.head < tester.cap()); - assert_eq!(tester, expected); - } - } - } - } - - #[test] - fn test_drain() { - let mut tester: VecDeque<usize> = VecDeque::with_capacity(7); - - let cap = tester.capacity(); - for len in 0..=cap { - for tail in 0..=cap { - for drain_start in 0..=len { - for drain_end in drain_start..=len { - tester.tail = tail; - tester.head = tail; - for i in 0..len { - tester.push_back(i); - } - - // Check that we drain the correct values - let drained: VecDeque<_> = tester.drain(drain_start..drain_end).collect(); - let drained_expected: VecDeque<_> = (drain_start..drain_end).collect(); - assert_eq!(drained, drained_expected); - - // We shouldn't have changed the capacity or made the - // head or tail out of bounds - assert_eq!(tester.capacity(), cap); - assert!(tester.tail < tester.cap()); - assert!(tester.head < tester.cap()); - - // We should see the correct values in the VecDeque - let expected: VecDeque<_> = (0..drain_start) - .chain(drain_end..len) - .collect(); - assert_eq!(expected, tester); - } - } - } - } - } - - #[test] - fn test_shrink_to_fit() { - // This test checks that every single combination of head and tail position, - // is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - tester.reserve(63); - let max_cap = tester.capacity(); - - for len in 0..=cap { - // 0, 1, 2, .., len - 1 - let expected = (0..).take(len).collect::<VecDeque<_>>(); - for tail_pos in 0..=max_cap { - tester.tail = tail_pos; - tester.head = tail_pos; - tester.reserve(63); - for i in 0..len { - tester.push_back(i); - } - tester.shrink_to_fit(); - assert!(tester.capacity() <= cap); - assert!(tester.tail < tester.cap()); - assert!(tester.head < tester.cap()); - assert_eq!(tester, expected); - } - } - } - - #[test] - fn test_split_off() { - // This test checks that every single combination of tail position, length, and - // split position is tested. Capacity 15 should be large enough to cover every case. - - let mut tester = VecDeque::with_capacity(15); - // can't guarantee we got 15, so have to get what we got. - // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else - // this test isn't covering what it wants to - let cap = tester.capacity(); - - // len is the length *before* splitting - for len in 0..cap { - // index to split at - for at in 0..=len { - // 0, 1, 2, .., at - 1 (may be empty) - let expected_self = (0..).take(at).collect::<VecDeque<_>>(); - // at, at + 1, .., len - 1 (may be empty) - let expected_other = (at..).take(len - at).collect::<VecDeque<_>>(); - - for tail_pos in 0..cap { - tester.tail = tail_pos; - tester.head = tail_pos; - for i in 0..len { - tester.push_back(i); - } - let result = tester.split_off(at); - assert!(tester.tail < tester.cap()); - assert!(tester.head < tester.cap()); - assert!(result.tail < result.cap()); - assert!(result.head < result.cap()); - assert_eq!(tester, expected_self); - assert_eq!(result, expected_other); - } - } - } - } - - #[test] - fn test_from_vec() { - use crate::vec::Vec; - for cap in 0..35 { - for len in 0..=cap { - let mut vec = Vec::with_capacity(cap); - vec.extend(0..len); - - let vd = VecDeque::from(vec.clone()); - assert!(vd.cap().is_power_of_two()); - assert_eq!(vd.len(), vec.len()); - assert!(vd.into_iter().eq(vec)); - } - } - } - - #[test] - fn test_vec_from_vecdeque() { - use crate::vec::Vec; - - fn create_vec_and_test_convert(cap: usize, offset: usize, len: usize) { - let mut vd = VecDeque::with_capacity(cap); - for _ in 0..offset { - vd.push_back(0); - vd.pop_front(); - } - vd.extend(0..len); - - let vec: Vec<_> = Vec::from(vd.clone()); - assert_eq!(vec.len(), vd.len()); - assert!(vec.into_iter().eq(vd)); - } - - #[cfg(not(miri))] // Miri is too slow - let max_pwr = 7; - #[cfg(miri)] - let max_pwr = 5; - - for cap_pwr in 0..max_pwr { - // Make capacity as a (2^x)-1, so that the ring size is 2^x - let cap = (2i32.pow(cap_pwr) - 1) as usize; - - // In these cases there is enough free space to solve it with copies - for len in 0..((cap + 1) / 2) { - // Test contiguous cases - for offset in 0..(cap - len) { - create_vec_and_test_convert(cap, offset, len) - } - - // Test cases where block at end of buffer is bigger than block at start - for offset in (cap - len)..(cap - (len / 2)) { - create_vec_and_test_convert(cap, offset, len) - } - - // Test cases where block at start of buffer is bigger than block at end - for offset in (cap - (len / 2))..cap { - create_vec_and_test_convert(cap, offset, len) - } - } - - // Now there's not (necessarily) space to straighten the ring with simple copies, - // the ring will use swapping when: - // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len)) - // right block size > free space && left block size > free space - for len in ((cap + 1) / 2)..cap { - // Test contiguous cases - for offset in 0..(cap - len) { - create_vec_and_test_convert(cap, offset, len) - } - - // Test cases where block at end of buffer is bigger than block at start - for offset in (cap - len)..(cap - (len / 2)) { - create_vec_and_test_convert(cap, offset, len) - } - - // Test cases where block at start of buffer is bigger than block at end - for offset in (cap - (len / 2))..cap { - create_vec_and_test_convert(cap, offset, len) - } - } - } - } - - #[test] - fn issue_53529() { - use crate::boxed::Box; - - let mut dst = VecDeque::new(); - dst.push_front(Box::new(1)); - dst.push_front(Box::new(2)); - assert_eq!(*dst.pop_back().unwrap(), 1); - - let mut src = VecDeque::new(); - src.push_front(Box::new(2)); - dst.append(&mut src); - for a in dst { - assert_eq!(*a, 2); - } - } - -} diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs new file mode 100644 index 00000000000..d2535239979 --- /dev/null +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -0,0 +1,379 @@ +use super::*; + +use ::test; + +#[bench] +#[cfg(not(miri))] // Miri does not support benchmarks +fn bench_push_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_back(i); + } + deq.head = 0; + deq.tail = 0; + }) +} + +#[bench] +#[cfg(not(miri))] // Miri does not support benchmarks +fn bench_push_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::with_capacity(101); + b.iter(|| { + for i in 0..100 { + deq.push_front(i); + } + deq.head = 0; + deq.tail = 0; + }) +} + +#[bench] +#[cfg(not(miri))] // Miri does not support benchmarks +fn bench_pop_back_100(b: &mut test::Bencher) { + let mut deq = VecDeque::<i32>::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_back()); + } + }) +} + +#[bench] +#[cfg(not(miri))] // Miri does not support benchmarks +fn bench_pop_front_100(b: &mut test::Bencher) { + let mut deq = VecDeque::<i32>::with_capacity(101); + + b.iter(|| { + deq.head = 100; + deq.tail = 0; + while !deq.is_empty() { + test::black_box(deq.pop_front()); + } + }) +} + +#[test] +fn test_swap_front_back_remove() { + fn test(back: bool) { + // This test checks that every single combination of tail position and length is tested. + // Capacity 15 should be large enough to cover every case. + let mut tester = VecDeque::with_capacity(15); + let usable_cap = tester.capacity(); + let final_len = usable_cap / 2; + + for len in 0..final_len { + let expected: VecDeque<_> = if back { + (0..len).collect() + } else { + (0..len).rev().collect() + }; + for tail_pos in 0..usable_cap { + tester.tail = tail_pos; + tester.head = tail_pos; + if back { + for i in 0..len * 2 { + tester.push_front(i); + } + for i in 0..len { + assert_eq!(tester.swap_remove_back(i), Some(len * 2 - 1 - i)); + } + } else { + for i in 0..len * 2 { + tester.push_back(i); + } + for i in 0..len { + let idx = tester.len() - 1 - i; + assert_eq!(tester.swap_remove_front(idx), Some(len * 2 - 1 - i)); + } + } + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } + } + test(true); + test(false); +} + +#[test] +fn test_insert() { + // This test checks that every single combination of tail position, length, and + // insertion position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + + // len is the length *after* insertion + for len in 1..cap { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::<VecDeque<_>>(); + for tail_pos in 0..cap { + for to_insert in 0..len { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i != to_insert { + tester.push_back(i); + } + } + tester.insert(to_insert, to_insert); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } + } +} + +#[test] +fn test_remove() { + // This test checks that every single combination of tail position, length, and + // removal position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *after* removal + for len in 0..cap - 1 { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::<VecDeque<_>>(); + for tail_pos in 0..cap { + for to_remove in 0..=len { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + if i == to_remove { + tester.push_back(1234); + } + tester.push_back(i); + } + if to_remove == len { + tester.push_back(1234); + } + tester.remove(to_remove); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } + } +} + +#[test] +fn test_drain() { + let mut tester: VecDeque<usize> = VecDeque::with_capacity(7); + + let cap = tester.capacity(); + for len in 0..=cap { + for tail in 0..=cap { + for drain_start in 0..=len { + for drain_end in drain_start..=len { + tester.tail = tail; + tester.head = tail; + for i in 0..len { + tester.push_back(i); + } + + // Check that we drain the correct values + let drained: VecDeque<_> = tester.drain(drain_start..drain_end).collect(); + let drained_expected: VecDeque<_> = (drain_start..drain_end).collect(); + assert_eq!(drained, drained_expected); + + // We shouldn't have changed the capacity or made the + // head or tail out of bounds + assert_eq!(tester.capacity(), cap); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + + // We should see the correct values in the VecDeque + let expected: VecDeque<_> = (0..drain_start) + .chain(drain_end..len) + .collect(); + assert_eq!(expected, tester); + } + } + } + } +} + +#[test] +fn test_shrink_to_fit() { + // This test checks that every single combination of head and tail position, + // is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + tester.reserve(63); + let max_cap = tester.capacity(); + + for len in 0..=cap { + // 0, 1, 2, .., len - 1 + let expected = (0..).take(len).collect::<VecDeque<_>>(); + for tail_pos in 0..=max_cap { + tester.tail = tail_pos; + tester.head = tail_pos; + tester.reserve(63); + for i in 0..len { + tester.push_back(i); + } + tester.shrink_to_fit(); + assert!(tester.capacity() <= cap); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert_eq!(tester, expected); + } + } +} + +#[test] +fn test_split_off() { + // This test checks that every single combination of tail position, length, and + // split position is tested. Capacity 15 should be large enough to cover every case. + + let mut tester = VecDeque::with_capacity(15); + // can't guarantee we got 15, so have to get what we got. + // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else + // this test isn't covering what it wants to + let cap = tester.capacity(); + + // len is the length *before* splitting + for len in 0..cap { + // index to split at + for at in 0..=len { + // 0, 1, 2, .., at - 1 (may be empty) + let expected_self = (0..).take(at).collect::<VecDeque<_>>(); + // at, at + 1, .., len - 1 (may be empty) + let expected_other = (at..).take(len - at).collect::<VecDeque<_>>(); + + for tail_pos in 0..cap { + tester.tail = tail_pos; + tester.head = tail_pos; + for i in 0..len { + tester.push_back(i); + } + let result = tester.split_off(at); + assert!(tester.tail < tester.cap()); + assert!(tester.head < tester.cap()); + assert!(result.tail < result.cap()); + assert!(result.head < result.cap()); + assert_eq!(tester, expected_self); + assert_eq!(result, expected_other); + } + } + } +} + +#[test] +fn test_from_vec() { + use crate::vec::Vec; + for cap in 0..35 { + for len in 0..=cap { + let mut vec = Vec::with_capacity(cap); + vec.extend(0..len); + + let vd = VecDeque::from(vec.clone()); + assert!(vd.cap().is_power_of_two()); + assert_eq!(vd.len(), vec.len()); + assert!(vd.into_iter().eq(vec)); + } + } +} + +#[test] +fn test_vec_from_vecdeque() { + use crate::vec::Vec; + + fn create_vec_and_test_convert(capacity: usize, offset: usize, len: usize) { + let mut vd = VecDeque::with_capacity(capacity); + for _ in 0..offset { + vd.push_back(0); + vd.pop_front(); + } + vd.extend(0..len); + + let vec: Vec<_> = Vec::from(vd.clone()); + assert_eq!(vec.len(), vd.len()); + assert!(vec.into_iter().eq(vd)); + } + + #[cfg(not(miri))] // Miri is too slow + let max_pwr = 7; + #[cfg(miri)] + let max_pwr = 5; + + for cap_pwr in 0..max_pwr { + // Make capacity as a (2^x)-1, so that the ring size is 2^x + let cap = (2i32.pow(cap_pwr) - 1) as usize; + + // In these cases there is enough free space to solve it with copies + for len in 0..((cap + 1) / 2) { + // Test contiguous cases + for offset in 0..(cap - len) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at end of buffer is bigger than block at start + for offset in (cap - len)..(cap - (len / 2)) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at start of buffer is bigger than block at end + for offset in (cap - (len / 2))..cap { + create_vec_and_test_convert(cap, offset, len) + } + } + + // Now there's not (necessarily) space to straighten the ring with simple copies, + // the ring will use swapping when: + // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len)) + // right block size > free space && left block size > free space + for len in ((cap + 1) / 2)..cap { + // Test contiguous cases + for offset in 0..(cap - len) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at end of buffer is bigger than block at start + for offset in (cap - len)..(cap - (len / 2)) { + create_vec_and_test_convert(cap, offset, len) + } + + // Test cases where block at start of buffer is bigger than block at end + for offset in (cap - (len / 2))..cap { + create_vec_and_test_convert(cap, offset, len) + } + } + } +} + +#[test] +fn issue_53529() { + use crate::boxed::Box; + + let mut dst = VecDeque::new(); + dst.push_front(Box::new(1)); + dst.push_front(Box::new(2)); + assert_eq!(*dst.pop_back().unwrap(), 1); + + let mut src = VecDeque::new(); + src.push_front(Box::new(2)); + dst.append(&mut src); + for a in dst { + assert_eq!(*a, 2); + } +} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2edd946ff11..4a48945adc3 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -10,9 +10,9 @@ //! //! ## Boxed values //! -//! The [`Box`](boxed/index.html) type is a smart pointer type. There can -//! only be one owner of a `Box`, and the owner can decide to mutate the -//! contents, which live on the heap. +//! The [`Box`] type is a smart pointer type. There can only be one owner of a +//! [`Box`], and the owner can decide to mutate the contents, which live on the +//! heap. //! //! This type can be sent among threads efficiently as the size of a `Box` value //! is the same as that of a pointer. Tree-like data structures are often built @@ -20,20 +20,20 @@ //! //! ## Reference counted pointers //! -//! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer -//! type intended for sharing memory within a thread. An `Rc` pointer wraps a -//! type, `T`, and only allows access to `&T`, a shared reference. +//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended +//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and +//! only allows access to `&T`, a shared reference. //! -//! This type is useful when inherited mutability (such as using `Box`) is too -//! constraining for an application, and is often paired with the `Cell` or -//! `RefCell` types in order to allow mutation. +//! This type is useful when inherited mutability (such as using [`Box`]) is too +//! constraining for an application, and is often paired with the [`Cell`] or +//! [`RefCell`] types in order to allow mutation. //! //! ## Atomically reference counted pointers //! -//! The [`Arc`](sync/index.html) type is the threadsafe equivalent of the `Rc` -//! type. It provides all the same functionality of `Rc`, except it requires -//! that the contained type `T` is shareable. Additionally, `Arc<T>` is itself -//! sendable while `Rc<T>` is not. +//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It +//! provides all the same functionality of [`Rc`], except it requires that the +//! contained type `T` is shareable. Additionally, [`Arc<T>`][`Arc`] is itself +//! sendable while [`Rc<T>`][`Rc`] is not. //! //! This type allows for shared access to the contained data, and is often //! paired with synchronization primitives such as mutexes to allow mutation of @@ -49,6 +49,12 @@ //! //! The [`alloc`](alloc/index.html) module defines the low-level interface to the //! default global allocator. It is not compatible with the libc allocator API. +//! +//! [`Arc`]: sync/index.html +//! [`Box`]: boxed/index.html +//! [`Cell`]: ../core/cell/index.html +//! [`Rc`]: rc/index.html +//! [`RefCell`]: ../core/cell/index.html #![allow(unused_attributes)] #![stable(feature = "alloc", since = "1.36.0")] @@ -62,9 +68,8 @@ #![warn(missing_docs)] #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings - -#![deny(rust_2018_idioms)] #![allow(explicit_outlives_requirements)] +#![allow(incomplete_features)] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] @@ -77,14 +82,18 @@ #![feature(box_syntax)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] +#![feature(const_generic_impls_guard)] +#![feature(const_generics)] +#![feature(const_in_array_repeat_expressions)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] -#![feature(custom_attribute)] +#![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(fundamental)] +#![feature(internal_uninit_const)] #![feature(lang_items)] #![feature(libc)] #![feature(nll)] @@ -94,6 +103,7 @@ #![feature(ptr_offset_from)] #![feature(rustc_attrs)] #![feature(receiver_trait)] +#![feature(slice_from_raw_parts)] #![feature(specialization)] #![feature(staged_api)] #![feature(std_internals)] @@ -109,10 +119,11 @@ #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] -#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] #![feature(try_trait)] -#![feature(iter_nth_back)] +#![feature(mem_take)] +#![feature(associated_type_bounds)] // Allow testing this library @@ -142,7 +153,7 @@ mod boxed { pub use std::boxed::Box; } #[cfg(test)] -mod boxed_test; +mod tests; pub mod collections; #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] pub mod sync; diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index dd128e096f9..0b5e186d4c7 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -42,7 +42,7 @@ macro_rules! vec { ($($x:expr),*) => ( <[_]>::into_vec(box [$($x),*]) ); - ($($x:expr,)*) => (vec![$($x),*]) + ($($x:expr,)*) => ($crate::vec![$($x),*]) } // HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is @@ -98,5 +98,5 @@ macro_rules! vec { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! format { - ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) + ($($arg:tt)*) => ($crate::fmt::format(::core::format_args!($($arg)*))) } diff --git a/src/liballoc/prelude/v1.rs b/src/liballoc/prelude/v1.rs index b6b01395ad6..3cb285bf049 100644 --- a/src/liballoc/prelude/v1.rs +++ b/src/liballoc/prelude/v1.rs @@ -6,6 +6,5 @@ #[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::borrow::ToOwned; #[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::boxed::Box; -#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::slice::SliceConcatExt; #[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::string::{String, ToString}; #[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::vec::Vec; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index d1fc5ac3b30..bc8a38f6b3a 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -7,10 +7,13 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{Alloc, Layout, Global, handle_alloc_error}; -use crate::collections::CollectionAllocErr::{self, *}; +use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error}; +use crate::collections::TryReserveError::{self, *}; use crate::boxed::Box; +#[cfg(test)] +mod tests; + /// A low-level utility for more ergonomically allocating, reallocating, and deallocating /// a buffer of memory on the heap without having to worry about all the corner cases /// involved. This type is excellent for building your own data structures like Vec and VecDeque. @@ -34,7 +37,7 @@ use crate::boxed::Box; /// that might occur with zero-sized types. /// /// However this means that you need to be careful when round-tripping this type -/// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`, +/// with a `Box<[T]>`: `capacity()` won't yield the len. However `with_capacity`, /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. @@ -65,25 +68,25 @@ impl<T, A: Alloc> RawVec<T, A> { /// Like `with_capacity` but parameterized over the choice of /// allocator for the returned RawVec. #[inline] - pub fn with_capacity_in(cap: usize, a: A) -> Self { - RawVec::allocate_in(cap, false, a) + pub fn with_capacity_in(capacity: usize, a: A) -> Self { + RawVec::allocate_in(capacity, false, a) } /// Like `with_capacity_zeroed` but parameterized over the choice /// of allocator for the returned RawVec. #[inline] - pub fn with_capacity_zeroed_in(cap: usize, a: A) -> Self { - RawVec::allocate_in(cap, true, a) + pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self { + RawVec::allocate_in(capacity, true, a) } - fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self { + fn allocate_in(capacity: usize, zeroed: bool, mut a: A) -> Self { unsafe { let elem_size = mem::size_of::<T>(); - let alloc_size = cap.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); + let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow()); - // handles ZSTs and `cap = 0` alike + // handles ZSTs and `capacity = 0` alike let ptr = if alloc_size == 0 { NonNull::<T>::dangling() } else { @@ -102,7 +105,7 @@ impl<T, A: Alloc> RawVec<T, A> { RawVec { ptr: ptr.into(), - cap, + cap: capacity, a, } } @@ -120,8 +123,8 @@ impl<T> RawVec<T, Global> { } /// Creates a RawVec (on the system heap) with exactly the - /// capacity and alignment requirements for a `[T; cap]`. This is - /// equivalent to calling RawVec::new when `cap` is 0 or T is + /// capacity and alignment requirements for a `[T; capacity]`. This is + /// equivalent to calling RawVec::new when `capacity` is 0 or T is /// zero-sized. Note that if `T` is zero-sized this means you will /// *not* get a RawVec with the requested capacity! /// @@ -135,14 +138,14 @@ impl<T> RawVec<T, Global> { /// /// Aborts on OOM #[inline] - pub fn with_capacity(cap: usize) -> Self { - RawVec::allocate_in(cap, false, Global) + pub fn with_capacity(capacity: usize) -> Self { + RawVec::allocate_in(capacity, false, Global) } /// Like `with_capacity` but guarantees the buffer is zeroed. #[inline] - pub fn with_capacity_zeroed(cap: usize) -> Self { - RawVec::allocate_in(cap, true, Global) + pub fn with_capacity_zeroed(capacity: usize) -> Self { + RawVec::allocate_in(capacity, true, Global) } } @@ -154,10 +157,10 @@ impl<T, A: Alloc> RawVec<T, A> { /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed. - pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self { + pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap, + cap: capacity, a, } } @@ -171,10 +174,10 @@ impl<T> RawVec<T, Global> { /// The ptr must be allocated (on the system heap), and with the given capacity. The /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). /// If the ptr and capacity come from a RawVec, then this is guaranteed. - pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self { + pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap, + cap: capacity, a: Global, } } @@ -191,7 +194,7 @@ impl<T> RawVec<T, Global> { impl<T, A: Alloc> RawVec<T, A> { /// Gets a raw pointer to the start of the allocation. Note that this is - /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must + /// Unique::empty() if `capacity = 0` or T is zero-sized. In the former case, you must /// be careful. pub fn ptr(&self) -> *mut T { self.ptr.as_ptr() @@ -201,7 +204,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// /// This will always be `usize::MAX` if `T` is zero-sized. #[inline(always)] - pub fn cap(&self) -> usize { + pub fn capacity(&self) -> usize { if mem::size_of::<T>() == 0 { !0 } else { @@ -240,7 +243,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// This function is ideal for when pushing elements one-at-a-time because /// you don't need to incur the costs of the more general computations /// reserve needs to do to guard against overflow. You do however need to - /// manually check if your `len == cap`. + /// manually check if your `len == capacity`. /// /// # Panics /// @@ -267,7 +270,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// /// impl<T> MyVec<T> { /// pub fn push(&mut self, elem: T) { - /// if self.len == self.buf.cap() { self.buf.double(); } + /// if self.len == self.buf.capacity() { self.buf.double(); } /// // double would have aborted or panicked if the len exceeded /// // `isize::MAX` so this is safe to do unchecked now. /// unsafe { @@ -381,20 +384,20 @@ impl<T, A: Alloc> 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_cap: usize, needed_extra_cap: usize) - -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) + -> Result<(), TryReserveError> { - self.reserve_internal(used_cap, needed_extra_cap, Fallible, Exact) + self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact) } /// Ensures that the buffer contains at least enough space to hold - /// `used_cap + needed_extra_cap` elements. If it doesn't already, + /// `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_cap` exceeds `self.cap()`, this may fail to actually allocate + /// 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. /// @@ -407,22 +410,23 @@ impl<T, A: Alloc> RawVec<T, A> { /// # Aborts /// /// Aborts on OOM - pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { - match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Exact) { + pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) { + match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } - /// Calculates the buffer's new size given that it'll hold `used_cap + - /// needed_extra_cap` elements. This logic is used in amortized reserve methods. + /// Calculates the buffer's new size given that it'll hold `used_capacity + + /// needed_extra_capacity` elements. This logic is used in amortized reserve methods. /// Returns `(new_capacity, new_alloc_size)`. - fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize) - -> Result<usize, CollectionAllocErr> { + fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize) + -> Result<usize, TryReserveError> { // Nothing we can really do about these checks :( - let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?; + let required_cap = used_capacity.checked_add(needed_extra_capacity) + .ok_or(CapacityOverflow)?; // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. let double_cap = self.cap * 2; // `double_cap` guarantees exponential growth. @@ -430,18 +434,18 @@ impl<T, A: Alloc> RawVec<T, A> { } /// The same as `reserve`, but returns on errors instead of panicking or aborting. - pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize) - -> Result<(), CollectionAllocErr> { - self.reserve_internal(used_cap, needed_extra_cap, Fallible, Amortized) + pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) + -> Result<(), TryReserveError> { + self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized) } /// Ensures that the buffer contains at least enough space to hold - /// `used_cap + needed_extra_cap` elements. If it doesn't already have + /// `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. /// - /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// 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. /// @@ -487,20 +491,20 @@ impl<T, A: Alloc> RawVec<T, A> { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` - pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { - match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Amortized) { + pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) { + match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } /// Attempts to ensure that the buffer contains at least enough space to hold - /// `used_cap + needed_extra_cap` elements. If it doesn't already have + /// `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. /// - /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// 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. /// @@ -511,7 +515,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// * 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_cap: usize, needed_extra_cap: usize) -> bool { + pub fn reserve_in_place(&mut self, used_capacity: usize, needed_extra_capacity: usize) -> bool { unsafe { // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. @@ -520,20 +524,20 @@ impl<T, A: Alloc> RawVec<T, A> { // Don't actually need any more capacity. If the current `cap` is 0, we can't // reallocate in place. - // Wrapping in case they give a bad `used_cap` + // Wrapping in case they give a bad `used_capacity` let old_layout = match self.current_layout() { Some(layout) => layout, None => return false, }; - if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + if self.capacity().wrapping_sub(used_capacity) >= needed_extra_capacity { return false; } - let new_cap = self.amortized_new_size(used_cap, needed_extra_cap) + let new_cap = self.amortized_new_size(used_capacity, needed_extra_capacity) .unwrap_or_else(|_| capacity_overflow()); - // Here, `cap < used_cap + needed_extra_cap <= new_cap` - // (regardless of whether `self.cap - used_cap` wrapped). + // Here, `cap < used_capacity + needed_extra_capacity <= new_cap` + // (regardless of whether `self.cap - used_capacity` wrapped). // Therefore we can safely call grow_in_place. let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0; @@ -632,29 +636,27 @@ use ReserveStrategy::*; impl<T, A: Alloc> RawVec<T, A> { fn reserve_internal( &mut self, - used_cap: usize, - needed_extra_cap: usize, + used_capacity: usize, + needed_extra_capacity: usize, fallibility: Fallibility, strategy: ReserveStrategy, - ) -> Result<(), CollectionAllocErr> { + ) -> Result<(), TryReserveError> { unsafe { - use crate::alloc::AllocErr; - // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to // panic. // Don't actually need any more capacity. - // Wrapping in case they gave a bad `used_cap`. - if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + // Wrapping in case they gave a bad `used_capacity`. + if self.capacity().wrapping_sub(used_capacity) >= needed_extra_capacity { return Ok(()); } // Nothing we can really do about these checks :( let new_cap = match strategy { - Exact => used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?, - Amortized => self.amortized_new_size(used_cap, needed_extra_cap)?, + Exact => used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?, + Amortized => self.amortized_new_size(used_capacity, needed_extra_capacity)?, }; let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?; @@ -668,12 +670,16 @@ impl<T, A: Alloc> RawVec<T, A> { None => self.a.alloc(new_layout), }; - match (&res, fallibility) { + let ptr = match (res, fallibility) { (Err(AllocErr), Infallible) => handle_alloc_error(new_layout), - _ => {} - } + (Err(AllocErr), Fallible) => return Err(TryReserveError::AllocError { + layout: new_layout, + non_exhaustive: (), + }), + (Ok(ptr), _) => ptr, + }; - self.ptr = res?.cast().into(); + self.ptr = ptr.cast().into(); self.cap = new_cap; Ok(()) @@ -685,14 +691,16 @@ impl<T, A: Alloc> RawVec<T, A> { impl<T> RawVec<T, Global> { /// Converts the entire buffer into `Box<[T]>`. /// - /// While it is not *strictly* Undefined Behavior to call - /// this procedure while some of the RawVec is uninitialized, - /// it certainly makes it trivial to trigger it. - /// /// Note that this will correctly reconstitute any `cap` changes /// that may have been performed. (see description of type for details) + /// + /// # Undefined Behavior + /// + /// All elements of `RawVec<T, Global>` must be initialized. Notice that + /// the rules around uninitialized boxed values are not finalized yet, + /// but until they are, it is advisable to avoid them. pub unsafe fn into_box(self) -> Box<[T]> { - // NOTE: not calling `cap()` here, actually using the real `cap` field! + // NOTE: not calling `capacity()` here, actually using the real `cap` field! let slice = slice::from_raw_parts_mut(self.ptr(), self.cap); let output: Box<[T]> = Box::from_raw(slice); mem::forget(self); @@ -731,7 +739,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> { // all 4GB in user-space. e.g., PAE or x32 #[inline] -fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { +fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize { Err(CapacityOverflow) } else { @@ -745,82 +753,3 @@ fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { fn capacity_overflow() -> ! { panic!("capacity overflow") } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn allocator_param() { - use crate::alloc::AllocErr; - - // Writing a test of integration between third-party - // allocators and RawVec is a little tricky because the RawVec - // API does not expose fallible allocation methods, so we - // cannot check what happens when allocator is exhausted - // (beyond detecting a panic). - // - // Instead, this just checks that the RawVec methods do at - // least go through the Allocator API when it reserves - // storage. - - // A dumb allocator that consumes a fixed amount of fuel - // before allocation attempts start failing. - struct BoundedAlloc { fuel: usize } - unsafe impl Alloc for BoundedAlloc { - unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { - let size = layout.size(); - if size > self.fuel { - return Err(AllocErr); - } - match Global.alloc(layout) { - ok @ Ok(_) => { self.fuel -= size; ok } - err @ Err(_) => err, - } - } - unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { - Global.dealloc(ptr, layout) - } - } - - let a = BoundedAlloc { fuel: 500 }; - let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a); - assert_eq!(v.a.fuel, 450); - v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel) - assert_eq!(v.a.fuel, 250); - } - - #[test] - fn reserve_does_not_overallocate() { - { - let mut v: RawVec<u32> = RawVec::new(); - // First `reserve` allocates like `reserve_exact` - v.reserve(0, 9); - assert_eq!(9, v.cap()); - } - - { - let mut v: RawVec<u32> = RawVec::new(); - v.reserve(0, 7); - assert_eq!(7, v.cap()); - // 97 if more than double of 7, so `reserve` should work - // like `reserve_exact`. - v.reserve(7, 90); - assert_eq!(97, v.cap()); - } - - { - let mut v: RawVec<u32> = RawVec::new(); - v.reserve(0, 12); - assert_eq!(12, v.cap()); - v.reserve(12, 3); - // 3 is less than half of 12, so `reserve` must grow - // exponentially. At the time of writing this test grow - // factor is 2, so new capacity is 24, however, grow factor - // of 1.5 is OK too. Hence `>= 18` in assert. - assert!(v.cap() >= 12 + 12 / 2); - } - } - - -} diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs new file mode 100644 index 00000000000..c389898d1ef --- /dev/null +++ b/src/liballoc/raw_vec/tests.rs @@ -0,0 +1,73 @@ +use super::*; + +#[test] +fn allocator_param() { + use crate::alloc::AllocErr; + + // Writing a test of integration between third-party + // allocators and RawVec is a little tricky because the RawVec + // API does not expose fallible allocation methods, so we + // cannot check what happens when allocator is exhausted + // (beyond detecting a panic). + // + // Instead, this just checks that the RawVec methods do at + // least go through the Allocator API when it reserves + // storage. + + // A dumb allocator that consumes a fixed amount of fuel + // before allocation attempts start failing. + struct BoundedAlloc { fuel: usize } + unsafe impl Alloc for BoundedAlloc { + unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { + let size = layout.size(); + if size > self.fuel { + return Err(AllocErr); + } + match Global.alloc(layout) { + ok @ Ok(_) => { self.fuel -= size; ok } + err @ Err(_) => err, + } + } + unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { + Global.dealloc(ptr, layout) + } + } + + let a = BoundedAlloc { fuel: 500 }; + let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a); + assert_eq!(v.a.fuel, 450); + v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel) + assert_eq!(v.a.fuel, 250); +} + +#[test] +fn reserve_does_not_overallocate() { + { + let mut v: RawVec<u32> = RawVec::new(); + // First `reserve` allocates like `reserve_exact` + v.reserve(0, 9); + assert_eq!(9, v.capacity()); + } + + { + let mut v: RawVec<u32> = RawVec::new(); + v.reserve(0, 7); + assert_eq!(7, v.capacity()); + // 97 if more than double of 7, so `reserve` should work + // like `reserve_exact`. + v.reserve(7, 90); + assert_eq!(97, v.capacity()); + } + + { + let mut v: RawVec<u32> = RawVec::new(); + v.reserve(0, 12); + assert_eq!(12, v.capacity()); + v.reserve(12, 3); + // 3 is less than half of 12, so `reserve` must grow + // exponentially. At the time of writing this test grow + // factor is 2, so new capacity is 24, however, grow factor + // of 1.5 is OK too. Hence `>= 18` in assert. + assert!(v.capacity() >= 12 + 12 / 2); + } +} diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0dffb19476f..2b222caf13f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -232,25 +232,30 @@ use crate::boxed::Box; use std::boxed::Box; use core::any::Any; +use core::array::LengthAtMost32; use core::borrow; use core::cell::Cell; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::abort; +use core::iter; use core::marker::{self, Unpin, Unsize, PhantomData}; -use core::mem::{self, align_of_val, forget, size_of_val}; +use core::mem::{self, align_of, align_of_val, forget, size_of_val}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; -use core::slice::from_raw_parts_mut; -use core::convert::From; +use core::slice::{self, from_raw_parts_mut}; +use core::convert::{From, TryFrom}; use core::usize; use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; use crate::string::String; use crate::vec::Vec; +#[cfg(test)] +mod tests; + struct RcBox<T: ?Sized> { strong: Cell<usize>, weak: Cell<usize>, @@ -286,6 +291,19 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {} #[unstable(feature = "dispatch_from_dyn", issue = "0")] impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {} +impl<T: ?Sized> Rc<T> { + fn from_inner(ptr: NonNull<RcBox<T>>) -> Self { + Self { + ptr, + phantom: PhantomData, + } + } + + unsafe fn from_ptr(ptr: *mut RcBox<T>) -> Self { + Self::from_inner(NonNull::new_unchecked(ptr)) + } +} + impl<T> Rc<T> { /// Constructs a new `Rc<T>`. /// @@ -298,17 +316,45 @@ impl<T> Rc<T> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> Rc<T> { - Rc { - // there is an implicit weak pointer owned by all the strong - // pointers, which ensures that the weak destructor never frees - // the allocation while the strong destructor is running, even - // if the weak pointer is stored inside the strong one. - ptr: Box::into_raw_non_null(box RcBox { - strong: Cell::new(1), - weak: Cell::new(1), - value, - }), - phantom: PhantomData, + // There is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + Self::from_inner(Box::into_raw_non_null(box RcBox { + strong: Cell::new(1), + weak: Cell::new(1), + value, + })) + } + + /// Constructs a new `Rc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::<T>(), + |mem| mem as *mut RcBox<mem::MaybeUninit<T>>, + )) } } @@ -362,6 +408,118 @@ impl<T> Rc<T> { } } +impl<T> Rc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> { + unsafe { + Rc::from_ptr(Rc::allocate_for_slice(len)) + } + } +} + +impl<T> Rc<mem::MaybeUninit<T>> { + /// Converts to `Rc<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<T> { + Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl<T> Rc<[mem::MaybeUninit<T>]> { + /// Converts to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T]> { + Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + } +} + impl<T: ?Sized> Rc<T> { /// Consumes the `Rc`, returning the wrapped pointer. /// @@ -375,9 +533,9 @@ impl<T: ?Sized> Rc<T> { /// ``` /// use std::rc::Rc; /// - /// let x = Rc::new(10); + /// let x = Rc::new("hello".to_owned()); /// let x_ptr = Rc::into_raw(x); - /// assert_eq!(unsafe { *x_ptr }, 10); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { @@ -401,13 +559,13 @@ impl<T: ?Sized> Rc<T> { /// ``` /// use std::rc::Rc; /// - /// let x = Rc::new(10); + /// let x = Rc::new("hello".to_owned()); /// let x_ptr = Rc::into_raw(x); /// /// unsafe { /// // Convert back to an `Rc` to prevent leak. /// let x = Rc::from_raw(x_ptr); - /// assert_eq!(*x, 10); + /// assert_eq!(&*x, "hello"); /// /// // Further calls to `Rc::from_raw(x_ptr)` would be memory unsafe. /// } @@ -416,20 +574,13 @@ impl<T: ?Sized> Rc<T> { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // Align the unsized value to the end of the RcBox. - // Because it is ?Sized, it will always be the last field in memory. - let align = align_of_val(&*ptr); - let layout = Layout::new::<RcBox<()>>(); - let offset = (layout.size() + layout.padding_needed_for(align)) as isize; + let offset = data_offset(ptr); // Reverse the offset to find the original RcBox. let fake_ptr = ptr as *mut RcBox<T>; let rc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Rc { - ptr: NonNull::new_unchecked(rc_ptr), - phantom: PhantomData, - } + Self::from_ptr(rc_ptr) } /// Consumes the `Rc`, returning the wrapped pointer as `NonNull<T>`. @@ -441,10 +592,10 @@ impl<T: ?Sized> Rc<T> { /// /// use std::rc::Rc; /// - /// let x = Rc::new(10); + /// let x = Rc::new("hello".to_owned()); /// let ptr = Rc::into_raw_non_null(x); - /// let deref = unsafe { *ptr.as_ref() }; - /// assert_eq!(deref, 10); + /// let deref = unsafe { ptr.as_ref() }; + /// assert_eq!(deref, "hello"); /// ``` #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] #[inline] @@ -552,13 +703,46 @@ impl<T: ?Sized> Rc<T> { pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { unsafe { - Some(&mut this.ptr.as_mut().value) + Some(Rc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Rc.html#method.get_mut + /// + /// # Safety + /// + /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().value + } + #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Rc`s point to the same value (not @@ -584,15 +768,18 @@ impl<T: ?Sized> Rc<T> { impl<T: Clone> Rc<T> { /// Makes a mutable reference into the given `Rc`. /// - /// If there are other `Rc` or [`Weak`][weak] pointers to the same value, - /// then `make_mut` will invoke [`clone`][clone] on the inner value to - /// ensure unique ownership. This is also referred to as clone-on-write. + /// If there are other `Rc` pointers to the same value, then `make_mut` will + /// [`clone`] the inner value to ensure unique ownership. This is also + /// referred to as clone-on-write. /// - /// See also [`get_mut`][get_mut], which will fail rather than cloning. + /// If there are no other `Rc` pointers to this value, then [`Weak`] + /// pointers to this value will be dissassociated. /// - /// [weak]: struct.Weak.html - /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone - /// [get_mut]: struct.Rc.html#method.get_mut + /// See also [`get_mut`], which will fail rather than cloning. + /// + /// [`Weak`]: struct.Weak.html + /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone + /// [`get_mut`]: struct.Rc.html#method.get_mut /// /// # Examples /// @@ -611,6 +798,23 @@ impl<T: Clone> Rc<T> { /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` + /// + /// [`Weak`] pointers will be dissassociated: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut data = Rc::new(75); + /// let weak = Rc::downgrade(&data); + /// + /// assert!(75 == *data); + /// assert!(75 == *weak.upgrade().unwrap()); + /// + /// *Rc::make_mut(&mut data) += 1; + /// + /// assert!(76 == *data); + /// assert!(weak.upgrade().is_none()); + /// ``` #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { @@ -667,7 +871,7 @@ impl Rc<dyn Any> { if (*self).is::<T>() { let ptr = self.ptr.cast::<RcBox<T>>(); forget(self); - Ok(Rc { ptr, phantom: PhantomData }) + Ok(Rc::from_inner(ptr)) } else { Err(self) } @@ -675,21 +879,29 @@ impl Rc<dyn Any> { } impl<T: ?Sized> Rc<T> { - // Allocates an `RcBox<T>` with sufficient space for an unsized value - unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> { - // Calculate layout using the given value. + /// Allocates an `RcBox<T>` with sufficient space for + /// a possibly-unsized value where the value has the layout provided. + /// + /// The function `mem_to_rcbox` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `RcBox<T>`. + unsafe fn allocate_for_layout( + value_layout: Layout, + mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T> + ) -> *mut RcBox<T> { + // Calculate layout using the given value layout. // Previously, layout was calculated on the expression // `&*(ptr as *const RcBox<T>)`, but this created a misaligned // reference (see #54908). let layout = Layout::new::<RcBox<()>>() - .extend(Layout::for_value(&*ptr)).unwrap().0 + .extend(value_layout).unwrap().0 .pad_to_align().unwrap(); + // Allocate for the layout. let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the RcBox - let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>; + let inner = mem_to_rcbox(mem.as_ptr()); debug_assert_eq!(Layout::for_value(&*inner), layout); ptr::write(&mut (*inner).strong, Cell::new(1)); @@ -698,6 +910,15 @@ impl<T: ?Sized> Rc<T> { inner } + /// Allocates an `RcBox<T>` with sufficient space for an unsized value + unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> { + // Allocate for the `RcBox<T>` using the given value. + Self::allocate_for_layout( + Layout::for_value(&*ptr), + |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>, + ) + } + fn from_box(v: Box<T>) -> Rc<T> { unsafe { let box_unique = Box::into_unique(v); @@ -715,44 +936,49 @@ impl<T: ?Sized> Rc<T> { // Free the allocation without dropping its contents box_free(box_unique); - Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } + Self::from_ptr(ptr) } } } -// Sets the data pointer of a `?Sized` raw pointer. -// -// For a slice/trait object, this sets the `data` field and leaves the rest -// unchanged. For a sized raw pointer, this simply sets the pointer. +impl<T> Rc<[T]> { + /// Allocates an `RcBox<[T]>` with the given length. + unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { + Self::allocate_for_layout( + Layout::array::<T>(len).unwrap(), + |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>, + ) + } +} + +/// Sets the data pointer of a `?Sized` raw pointer. +/// +/// For a slice/trait object, this sets the `data` field and leaves the rest +/// unchanged. For a sized raw pointer, this simply sets the pointer. unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T { ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); ptr } impl<T> Rc<[T]> { - // Copy elements from slice into newly allocated Rc<[T]> - // - // Unsafe because the caller must either take ownership or bind `T: Copy` + /// Copy elements from slice into newly allocated Rc<[T]> + /// + /// Unsafe because the caller must either take ownership or bind `T: Copy` unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { - let v_ptr = v as *const [T]; - let ptr = Self::allocate_for_ptr(v_ptr); + let ptr = Self::allocate_for_slice(v.len()); ptr::copy_nonoverlapping( v.as_ptr(), &mut (*ptr).value as *mut [T] as *mut T, v.len()); - Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } + Self::from_ptr(ptr) } -} - -trait RcFromSlice<T> { - fn from_slice(slice: &[T]) -> Self; -} -impl<T: Clone> RcFromSlice<T> for Rc<[T]> { - #[inline] - default fn from_slice(v: &[T]) -> Self { + /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + unsafe fn from_iter_exact(iter: impl iter::Iterator<Item = T>, len: usize) -> Rc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written // into the new RcBox will be dropped, then the memory freed. @@ -769,37 +995,48 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> { let slice = from_raw_parts_mut(self.elems, self.n_elems); ptr::drop_in_place(slice); - Global.dealloc(self.mem, self.layout.clone()); + Global.dealloc(self.mem, self.layout); } } } - unsafe { - let v_ptr = v as *const [T]; - let ptr = Self::allocate_for_ptr(v_ptr); + let ptr = Self::allocate_for_slice(len); - let mem = ptr as *mut _ as *mut u8; - let layout = Layout::for_value(&*ptr); + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); - // Pointer to first element - let elems = &mut (*ptr).value as *mut [T] as *mut T; + // Pointer to first element + let elems = &mut (*ptr).value as *mut [T] as *mut T; - let mut guard = Guard{ - mem: NonNull::new_unchecked(mem), - elems: elems, - layout: layout, - n_elems: 0, - }; + let mut guard = Guard { + mem: NonNull::new_unchecked(mem), + elems, + layout, + n_elems: 0, + }; - for (i, item) in v.iter().enumerate() { - ptr::write(elems.add(i), item.clone()); - guard.n_elems += 1; - } + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } - // All clear. Forget the guard so it doesn't free the new RcBox. - forget(guard); + // All clear. Forget the guard so it doesn't free the new RcBox. + forget(guard); + + Self::from_ptr(ptr) + } +} - Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } +/// Specialization trait used for `From<&[T]>`. +trait RcFromSlice<T> { + fn from_slice(slice: &[T]) -> Self; +} + +impl<T: Clone> RcFromSlice<T> for Rc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + unsafe { + Self::from_iter_exact(v.iter().cloned(), v.len()) } } } @@ -891,7 +1128,7 @@ impl<T: ?Sized> Clone for Rc<T> { #[inline] fn clone(&self) -> Rc<T> { self.inc_strong(); - Rc { ptr: self.ptr, phantom: PhantomData } + Self::from_inner(self.ptr) } } @@ -1197,6 +1434,114 @@ impl<T> From<Vec<T>> for Rc<[T]> { } } +#[unstable(feature = "boxed_slice_try_from", issue = "0")] +impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]> +where + [T; N]: LengthAtMost32, +{ + type Error = Rc<[T]>; + + fn try_from(boxed_slice: Rc<[T]>) -> Result<Self, Self::Error> { + if boxed_slice.len() == N { + Ok(unsafe { Rc::from_raw(Rc::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) + } + } +} + +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl<T> iter::FromIterator<T> for Rc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Rc<[T]>` is done by first + /// collecting into a `Vec<T>`. That is, when writing the following: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::<Vec<_>>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Rc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec<T>` + /// and then it will allocate once for turning the `Vec<T>` into the `Rc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Rc<[T]>`. For example: + /// + /// ```rust + /// # use std::rc::Rc; + /// let evens: Rc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::<Vec<_>>()); + /// ``` + fn from_iter<I: iter::IntoIterator<Item = T>>(iter: I) -> Self { + RcFromIter::from_iter(iter.into_iter()) + } +} + +/// Specialization trait used for collecting into `Rc<[T]>`. +trait RcFromIter<T, I> { + fn from_iter(iter: I) -> Self; +} + +impl<T, I: Iterator<Item = T>> RcFromIter<T, I> for Rc<[T]> { + default fn from_iter(iter: I) -> Self { + iter.collect::<Vec<T>>().into() + } +} + +impl<T, I: iter::TrustedLen<Item = T>> RcFromIter<T, I> for Rc<[T]> { + default fn from_iter(iter: I) -> Self { + // This is the case for a `TrustedLen` iterator. + let (low, high) = iter.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + + unsafe { + // SAFETY: We need to ensure that the iterator has an exact length and we have. + Rc::from_iter_exact(iter, low) + } + } else { + // Fall back to normal implementation. + iter.collect::<Vec<T>>().into() + } + } +} + +impl<'a, T: 'a + Clone> RcFromIter<&'a T, slice::Iter<'a, T>> for Rc<[T]> { + fn from_iter(iter: slice::Iter<'a, T>) -> Self { + // Delegate to `impl<T: Clone> From<&[T]> for Rc<[T]>`. + // + // In the case that `T: Copy`, we get to use `ptr::copy_nonoverlapping` + // which is even more performant. + // + // In the fall-back case we have `T: Clone`. This is still better + // than the `TrustedLen` implementation as slices have a known length + // and so we get to avoid calling `size_hint` and avoid the branching. + iter.as_slice().into() + } +} + /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the /// managed value. The value is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`. @@ -1262,6 +1607,143 @@ impl<T> Weak<T> { ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"), } } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`. + /// + /// It is up to the caller to ensure that the object is still alive when accessing it through + /// the pointer. + /// + /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::Rc; + /// use std::ptr; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_raw())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_raw(&self) -> *const T { + match self.inner() { + None => ptr::null(), + Some(inner) => { + let offset = data_offset_sized::<T>(); + let ptr = inner as *const RcBox<T>; + // Note: while the pointer we create may already point to dropped value, the + // allocation still lives (it must hold the weak point as long as we are alive). + // Therefore, the offset is OK to do, it won't get out of the allocation. + let ptr = unsafe { (ptr as *const u8).offset(offset) }; + ptr as *const T + } + } + } + + /// Consumes the `Weak<T>` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, preserving the original weak count. It + /// can be turned back into the `Weak<T>` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_raw`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// let weak = Rc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Rc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Rc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: struct.Weak.html#method.from_raw + /// [`as_raw`]: struct.Weak.html#method.as_raw + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn into_raw(self) -> *const T { + let result = self.as_raw(); + mem::forget(self); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak<T>`. + /// + /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is + /// returned. + /// + /// # Safety + /// + /// The pointer must represent one valid weak count. In other words, it must point to `T` which + /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached + /// 0. It is allowed for the strong count to be 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::{Rc, Weak}; + /// + /// let strong = Rc::new("hello".to_owned()); + /// + /// let raw_1 = Rc::downgrade(&strong).into_raw(); + /// let raw_2 = Rc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Rc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Rc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + /// [`into_raw`]: struct.Weak.html#method.into_raw + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`Rc`]: struct.Rc.html + /// [`Weak`]: struct.Weak.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + if ptr.is_null() { + Self::new() + } else { + // See Rc::from_raw for details + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut RcBox<T>; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { + ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"), + } + } + } } pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool { @@ -1303,7 +1785,7 @@ impl<T: ?Sized> Weak<T> { None } else { inner.inc_strong(); - Some(Rc { ptr: self.ptr, phantom: PhantomData }) + Some(Rc::from_inner(self.ptr)) } } @@ -1362,18 +1844,18 @@ impl<T: ?Sized> Weak<T> { /// /// ``` /// #![feature(weak_ptr_eq)] - /// use std::rc::{Rc, Weak}; + /// use std::rc::Rc; /// /// let first_rc = Rc::new(5); /// let first = Rc::downgrade(&first_rc); /// let second = Rc::downgrade(&first_rc); /// - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Rc::new(5); /// let third = Rc::downgrade(&third_rc); /// - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` /// /// Comparing `Weak::new`. @@ -1384,16 +1866,16 @@ impl<T: ?Sized> Weak<T> { /// /// let first = Weak::new(); /// let second = Weak::new(); - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Rc::new(()); /// let third = Rc::downgrade(&third_rc); - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] #[unstable(feature = "weak_ptr_eq", issue = "55981")] - pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() == other.ptr.as_ptr() + pub fn ptr_eq(&self, other: &Self) -> bool { + self.ptr.as_ptr() == other.ptr.as_ptr() } } @@ -1507,14 +1989,16 @@ trait RcBoxPtr<T: ?Sized> { #[inline] fn inc_strong(&self) { + let strong = self.strong(); + // We want to abort on overflow instead of dropping the value. // The reference count will never be zero when this is called; // nevertheless, we insert an abort here to hint LLVM at // an otherwise missed optimization. - if self.strong() == 0 || self.strong() == usize::max_value() { + if strong == 0 || strong == usize::max_value() { unsafe { abort(); } } - self.inner().strong.set(self.strong() + 1); + self.inner().strong.set(strong + 1); } #[inline] @@ -1529,14 +2013,16 @@ trait RcBoxPtr<T: ?Sized> { #[inline] fn inc_weak(&self) { + let weak = self.weak(); + // We want to abort on overflow instead of dropping the value. // The reference count will never be zero when this is called; // nevertheless, we insert an abort here to hint LLVM at // an otherwise missed optimization. - if self.weak() == 0 || self.weak() == usize::max_value() { + if weak == 0 || weak == usize::max_value() { unsafe { abort(); } } - self.inner().weak.set(self.weak() + 1); + self.inner().weak.set(weak + 1); } #[inline] @@ -1561,436 +2047,6 @@ impl<T: ?Sized> RcBoxPtr<T> for RcBox<T> { } } -#[cfg(test)] -mod tests { - use super::{Rc, Weak}; - use std::boxed::Box; - use std::cell::RefCell; - use std::option::Option::{self, None, Some}; - use std::result::Result::{Err, Ok}; - use std::mem::drop; - use std::clone::Clone; - use std::convert::From; - - #[test] - fn test_clone() { - let x = Rc::new(RefCell::new(5)); - let y = x.clone(); - *x.borrow_mut() = 20; - assert_eq!(*y.borrow(), 20); - } - - #[test] - fn test_simple() { - let x = Rc::new(5); - assert_eq!(*x, 5); - } - - #[test] - fn test_simple_clone() { - let x = Rc::new(5); - let y = x.clone(); - assert_eq!(*x, 5); - assert_eq!(*y, 5); - } - - #[test] - fn test_destructor() { - let x: Rc<Box<_>> = Rc::new(box 5); - assert_eq!(**x, 5); - } - - #[test] - fn test_live() { - let x = Rc::new(5); - let y = Rc::downgrade(&x); - assert!(y.upgrade().is_some()); - } - - #[test] - fn test_dead() { - let x = Rc::new(5); - let y = Rc::downgrade(&x); - drop(x); - assert!(y.upgrade().is_none()); - } - - #[test] - fn weak_self_cyclic() { - struct Cycle { - x: RefCell<Option<Weak<Cycle>>>, - } - - let a = Rc::new(Cycle { x: RefCell::new(None) }); - let b = Rc::downgrade(&a.clone()); - *a.x.borrow_mut() = Some(b); - - // hopefully we don't double-free (or leak)... - } - - #[test] - fn is_unique() { - let x = Rc::new(3); - assert!(Rc::is_unique(&x)); - let y = x.clone(); - assert!(!Rc::is_unique(&x)); - drop(y); - assert!(Rc::is_unique(&x)); - let w = Rc::downgrade(&x); - assert!(!Rc::is_unique(&x)); - drop(w); - assert!(Rc::is_unique(&x)); - } - - #[test] - fn test_strong_count() { - let a = Rc::new(0); - assert!(Rc::strong_count(&a) == 1); - let w = Rc::downgrade(&a); - assert!(Rc::strong_count(&a) == 1); - let b = w.upgrade().expect("upgrade of live rc failed"); - assert!(Rc::strong_count(&b) == 2); - assert!(Rc::strong_count(&a) == 2); - drop(w); - drop(a); - assert!(Rc::strong_count(&b) == 1); - let c = b.clone(); - assert!(Rc::strong_count(&b) == 2); - assert!(Rc::strong_count(&c) == 2); - } - - #[test] - fn test_weak_count() { - let a = Rc::new(0); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 0); - let w = Rc::downgrade(&a); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 1); - drop(w); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 0); - let c = a.clone(); - assert!(Rc::strong_count(&a) == 2); - assert!(Rc::weak_count(&a) == 0); - drop(c); - } - - #[test] - fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None); - assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); - - let a = Rc::new(0); - let w = Rc::downgrade(&a); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(1)); - let w2 = w.clone(); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(2)); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(2)); - drop(w); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(1)); - let a2 = a.clone(); - assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), Some(1)); - drop(a2); - drop(a); - assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), Some(1)); - drop(w2); - } - - #[test] - fn try_unwrap() { - let x = Rc::new(3); - assert_eq!(Rc::try_unwrap(x), Ok(3)); - let x = Rc::new(4); - let _y = x.clone(); - assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); - let x = Rc::new(5); - let _w = Rc::downgrade(&x); - assert_eq!(Rc::try_unwrap(x), Ok(5)); - } - - #[test] - fn into_from_raw() { - let x = Rc::new(box "hello"); - let y = x.clone(); - - let x_ptr = Rc::into_raw(x); - drop(y); - unsafe { - assert_eq!(**x_ptr, "hello"); - - let x = Rc::from_raw(x_ptr); - assert_eq!(**x, "hello"); - - assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); - } - } - - #[test] - fn test_into_from_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let rc: Rc<str> = Rc::from("foo"); - - let ptr = Rc::into_raw(rc.clone()); - let rc2 = unsafe { Rc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert_eq!(rc, rc2); - - let rc: Rc<dyn Display> = Rc::new(123); - - let ptr = Rc::into_raw(rc.clone()); - let rc2 = unsafe { Rc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert_eq!(rc2.to_string(), "123"); - } - - #[test] - fn get_mut() { - let mut x = Rc::new(3); - *Rc::get_mut(&mut x).unwrap() = 4; - assert_eq!(*x, 4); - let y = x.clone(); - assert!(Rc::get_mut(&mut x).is_none()); - drop(y); - assert!(Rc::get_mut(&mut x).is_some()); - let _w = Rc::downgrade(&x); - assert!(Rc::get_mut(&mut x).is_none()); - } - - #[test] - fn test_cowrc_clone_make_unique() { - let mut cow0 = Rc::new(75); - let mut cow1 = cow0.clone(); - let mut cow2 = cow1.clone(); - - assert!(75 == *Rc::make_mut(&mut cow0)); - assert!(75 == *Rc::make_mut(&mut cow1)); - assert!(75 == *Rc::make_mut(&mut cow2)); - - *Rc::make_mut(&mut cow0) += 1; - *Rc::make_mut(&mut cow1) += 2; - *Rc::make_mut(&mut cow2) += 3; - - assert!(76 == *cow0); - assert!(77 == *cow1); - assert!(78 == *cow2); - - // none should point to the same backing memory - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 != *cow2); - } - - #[test] - fn test_cowrc_clone_unique2() { - let mut cow0 = Rc::new(75); - let cow1 = cow0.clone(); - let cow2 = cow1.clone(); - - assert!(75 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - *Rc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - // cow1 and cow2 should share the same contents - // cow0 should have a unique reference - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 == *cow2); - } - - #[test] - fn test_cowrc_clone_weak() { - let mut cow0 = Rc::new(75); - let cow1_weak = Rc::downgrade(&cow0); - - assert!(75 == *cow0); - assert!(75 == *cow1_weak.upgrade().unwrap()); - - *Rc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(cow1_weak.upgrade().is_none()); - } - - #[test] - fn test_show() { - let foo = Rc::new(75); - assert_eq!(format!("{:?}", foo), "75"); - } - - #[test] - fn test_unsized() { - let foo: Rc<[i32]> = Rc::new([1, 2, 3]); - assert_eq!(foo, foo.clone()); - } - - #[test] - fn test_from_owned() { - let foo = 123; - let foo_rc = Rc::from(foo); - assert!(123 == *foo_rc); - } - - #[test] - fn test_new_weak() { - let foo: Weak<usize> = Weak::new(); - assert!(foo.upgrade().is_none()); - } - - #[test] - fn test_ptr_eq() { - let five = Rc::new(5); - let same_five = five.clone(); - let other_five = Rc::new(5); - - assert!(Rc::ptr_eq(&five, &same_five)); - assert!(!Rc::ptr_eq(&five, &other_five)); - } - - #[test] - fn test_from_str() { - let r: Rc<str> = Rc::from("foo"); - - assert_eq!(&r[..], "foo"); - } - - #[test] - fn test_copy_from_slice() { - let s: &[u32] = &[1, 2, 3]; - let r: Rc<[u32]> = Rc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); - } - - #[test] - fn test_clone_from_slice() { - #[derive(Clone, Debug, Eq, PartialEq)] - struct X(u32); - - let s: &[X] = &[X(1), X(2), X(3)]; - let r: Rc<[X]> = Rc::from(s); - - assert_eq!(&r[..], s); - } - - #[test] - #[should_panic] - fn test_clone_from_slice_panic() { - use std::string::{String, ToString}; - - struct Fail(u32, String); - - impl Clone for Fail { - fn clone(&self) -> Fail { - if self.0 == 2 { - panic!(); - } - Fail(self.0, self.1.clone()) - } - } - - let s: &[Fail] = &[ - Fail(0, "foo".to_string()), - Fail(1, "bar".to_string()), - Fail(2, "baz".to_string()), - ]; - - // Should panic, but not cause memory corruption - let _r: Rc<[Fail]> = Rc::from(s); - } - - #[test] - fn test_from_box() { - let b: Box<u32> = box 123; - let r: Rc<u32> = Rc::from(b); - - assert_eq!(*r, 123); - } - - #[test] - fn test_from_box_str() { - use std::string::String; - - let s = String::from("foo").into_boxed_str(); - let r: Rc<str> = Rc::from(s); - - assert_eq!(&r[..], "foo"); - } - - #[test] - fn test_from_box_slice() { - let s = vec![1, 2, 3].into_boxed_slice(); - let r: Rc<[u32]> = Rc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); - } - - #[test] - fn test_from_box_trait() { - use std::fmt::Display; - use std::string::ToString; - - let b: Box<dyn Display> = box 123; - let r: Rc<dyn Display> = Rc::from(b); - - assert_eq!(r.to_string(), "123"); - } - - #[test] - fn test_from_box_trait_zero_sized() { - use std::fmt::Debug; - - let b: Box<dyn Debug> = box (); - let r: Rc<dyn Debug> = Rc::from(b); - - assert_eq!(format!("{:?}", r), "()"); - } - - #[test] - fn test_from_vec() { - let v = vec![1, 2, 3]; - let r: Rc<[u32]> = Rc::from(v); - - assert_eq!(&r[..], [1, 2, 3]); - } - - #[test] - fn test_downcast() { - use std::any::Any; - - let r1: Rc<dyn Any> = Rc::new(i32::max_value()); - let r2: Rc<dyn Any> = Rc::new("abc"); - - assert!(r1.clone().downcast::<u32>().is_err()); - - let r1i32 = r1.downcast::<i32>(); - assert!(r1i32.is_ok()); - assert_eq!(r1i32.unwrap(), Rc::new(i32::max_value())); - - assert!(r2.clone().downcast::<i32>().is_err()); - - let r2str = r2.downcast::<&'static str>(); - assert!(r2str.is_ok()); - assert_eq!(r2str.unwrap(), Rc::new("abc")); - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> borrow::Borrow<T> for Rc<T> { fn borrow(&self) -> &T { @@ -2007,3 +2063,22 @@ impl<T: ?Sized> AsRef<T> for Rc<T> { #[stable(feature = "pin", since = "1.33.0")] impl<T: ?Sized> Unpin for Rc<T> { } + +unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize { + // Align the unsized value to the end of the `RcBox`. + // Because it is ?Sized, it will always be the last field in memory. + data_offset_align(align_of_val(&*ptr)) +} + +/// Computes the offset of the data field within `RcBox`. +/// +/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. +fn data_offset_sized<T>() -> isize { + data_offset_align(align_of::<T>()) +} + +#[inline] +fn data_offset_align(align: usize) -> isize { + let layout = Layout::new::<RcBox<()>>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} diff --git a/src/liballoc/rc/tests.rs b/src/liballoc/rc/tests.rs new file mode 100644 index 00000000000..6fd3f909357 --- /dev/null +++ b/src/liballoc/rc/tests.rs @@ -0,0 +1,439 @@ +use super::*; + +use std::boxed::Box; +use std::cell::RefCell; +use std::option::Option::{self, None, Some}; +use std::result::Result::{Err, Ok}; +use std::mem::drop; +use std::clone::Clone; +use std::convert::{From, TryInto}; + +#[test] +fn test_clone() { + let x = Rc::new(RefCell::new(5)); + let y = x.clone(); + *x.borrow_mut() = 20; + assert_eq!(*y.borrow(), 20); +} + +#[test] +fn test_simple() { + let x = Rc::new(5); + assert_eq!(*x, 5); +} + +#[test] +fn test_simple_clone() { + let x = Rc::new(5); + let y = x.clone(); + assert_eq!(*x, 5); + assert_eq!(*y, 5); +} + +#[test] +fn test_destructor() { + let x: Rc<Box<_>> = Rc::new(box 5); + assert_eq!(**x, 5); +} + +#[test] +fn test_live() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Rc::new(5); + let y = Rc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: RefCell<Option<Weak<Cycle>>>, + } + + let a = Rc::new(Cycle { x: RefCell::new(None) }); + let b = Rc::downgrade(&a.clone()); + *a.x.borrow_mut() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn is_unique() { + let x = Rc::new(3); + assert!(Rc::is_unique(&x)); + let y = x.clone(); + assert!(!Rc::is_unique(&x)); + drop(y); + assert!(Rc::is_unique(&x)); + let w = Rc::downgrade(&x); + assert!(!Rc::is_unique(&x)); + drop(w); + assert!(Rc::is_unique(&x)); +} + +#[test] +fn test_strong_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + let b = w.upgrade().expect("upgrade of live rc failed"); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Rc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Rc::strong_count(&b) == 2); + assert!(Rc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Rc::new(0); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let w = Rc::downgrade(&a); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 1); + drop(w); + assert!(Rc::strong_count(&a) == 1); + assert!(Rc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Rc::strong_count(&a) == 2); + assert!(Rc::weak_count(&a) == 0); + drop(c); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None); + assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); + + let a = Rc::new(0); + let w = Rc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), Some(1)); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), Some(2)); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), Some(2)); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), Some(1)); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), Some(1)); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), Some(1)); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Rc::new(3); + assert_eq!(Rc::try_unwrap(x), Ok(3)); + let x = Rc::new(4); + let _y = x.clone(); + assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_from_raw() { + let x = Rc::new(box "hello"); + let y = x.clone(); + + let x_ptr = Rc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Rc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let rc: Rc<str> = Rc::from("foo"); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(rc, rc2); + + let rc: Rc<dyn Display> = Rc::new(123); + + let ptr = Rc::into_raw(rc.clone()); + let rc2 = unsafe { Rc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(rc2.to_string(), "123"); +} + +#[test] +fn get_mut() { + let mut x = Rc::new(3); + *Rc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Rc::get_mut(&mut x).is_none()); + drop(y); + assert!(Rc::get_mut(&mut x).is_some()); + let _w = Rc::downgrade(&x); + assert!(Rc::get_mut(&mut x).is_none()); +} + +#[test] +fn test_cowrc_clone_make_unique() { + let mut cow0 = Rc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Rc::make_mut(&mut cow0)); + assert!(75 == *Rc::make_mut(&mut cow1)); + assert!(75 == *Rc::make_mut(&mut cow2)); + + *Rc::make_mut(&mut cow0) += 1; + *Rc::make_mut(&mut cow1) += 2; + *Rc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowrc_clone_unique2() { + let mut cow0 = Rc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowrc_clone_weak() { + let mut cow0 = Rc::new(75); + let cow1_weak = Rc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Rc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +#[test] +fn test_show() { + let foo = Rc::new(75); + assert_eq!(format!("{:?}", foo), "75"); +} + +#[test] +fn test_unsized() { + let foo: Rc<[i32]> = Rc::new([1, 2, 3]); + assert_eq!(foo, foo.clone()); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_rc = Rc::from(foo); + assert!(123 == *foo_rc); +} + +#[test] +fn test_new_weak() { + let foo: Weak<usize> = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Rc::new(5); + let same_five = five.clone(); + let other_five = Rc::new(5); + + assert!(Rc::ptr_eq(&five, &same_five)); + assert!(!Rc::ptr_eq(&five, &other_five)); +} + +#[test] +fn test_from_str() { + let r: Rc<str> = Rc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Rc<[X]> = Rc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = &[ + Fail(0, "foo".to_string()), + Fail(1, "bar".to_string()), + Fail(2, "baz".to_string()), + ]; + + // Should panic, but not cause memory corruption + let _r: Rc<[Fail]> = Rc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box<u32> = box 123; + let r: Rc<u32> = Rc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Rc<str> = Rc::from(s); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box<dyn Display> = box 123; + let r: Rc<dyn Display> = Rc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box<dyn Debug> = box (); + let r: Rc<dyn Debug> = Rc::from(b); + + assert_eq!(format!("{:?}", r), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Rc<dyn Any> = Rc::new(i32::max_value()); + let r2: Rc<dyn Any> = Rc::new("abc"); + + assert!(r1.clone().downcast::<u32>().is_err()); + + let r1i32 = r1.downcast::<i32>(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Rc::new(i32::max_value())); + + assert!(r2.clone().downcast::<i32>().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Rc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + let a: Result<Rc<[u32; 3]>, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 6eac8487401..881d499c074 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -123,12 +123,12 @@ pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut}; //////////////////////////////////////////////////////////////////////////////// // HACK(japaric) needed for the implementation of `vec!` macro during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::into_vec; // HACK(japaric) needed for the implementation of `Vec::clone` during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::to_vec; @@ -137,17 +137,16 @@ pub use hack::to_vec; // `core::slice::SliceExt` - we need to supply these functions for the // `test_permutations` test mod hack { - use core::mem; - use crate::boxed::Box; use crate::vec::Vec; #[cfg(test)] use crate::string::ToString; - pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> { + pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> { unsafe { - let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); - mem::forget(b); + let len = b.len(); + let b = Box::into_raw(b); + let xs = Vec::from_raw_parts(b as *mut T, len, len); xs } } @@ -376,7 +375,7 @@ impl<T> [T] { pub fn to_vec(&self) -> Vec<T> where T: Clone { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::to_vec(self) } @@ -397,7 +396,7 @@ impl<T> [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn into_vec(self: Box<Self>) -> Vec<T> { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::into_vec(self) } @@ -485,6 +484,57 @@ impl<T> [T] { } buf } + + /// Flattens a slice of `T` into a single value `Self::Output`. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(["hello", "world"].concat(), "helloworld"); + /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output + where Self: Concat<Item> + { + Concat::concat(self) + } + + /// Flattens a slice of `T` into a single value `Self::Output`, placing a + /// given separator between each. + /// + /// # Examples + /// + /// ``` + /// assert_eq!(["hello", "world"].join(" "), "hello world"); + /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); + /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]); + /// ``` + #[stable(feature = "rename_connect_to_join", since = "1.3.0")] + pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output + where Self: Join<Separator> + { + Join::join(self, sep) + } + + /// Flattens a slice of `T` into a single value `Self::Output`, placing a + /// given separator between each. + /// + /// # Examples + /// + /// ``` + /// # #![allow(deprecated)] + /// assert_eq!(["hello", "world"].connect(" "), "hello world"); + /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] + pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output + where Self: Join<Separator> + { + Join::join(self, sep) + } + } #[lang = "slice_u8_alloc"] @@ -528,85 +578,84 @@ impl [u8] { //////////////////////////////////////////////////////////////////////////////// // Extension traits for slices over specific kinds of data //////////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] -/// An extension trait for concatenating slices + +/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat). /// -/// While this trait is unstable, the methods are stable. `SliceConcatExt` is -/// included in the [standard library prelude], so you can use [`join()`] and -/// [`concat()`] as if they existed on `[T]` itself. +/// Note: the `Item` type parameter is not used in this trait, +/// but it allows impls to be more generic. +/// Without it, we get this error: /// -/// [standard library prelude]: ../../std/prelude/index.html -/// [`join()`]: #tymethod.join -/// [`concat()`]: #tymethod.concat -pub trait SliceConcatExt<T: ?Sized> { - #[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] +/// ```error +/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica +/// --> src/liballoc/slice.rs:608:6 +/// | +/// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] { +/// | ^ unconstrained type parameter +/// ``` +/// +/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls, +/// such that multiple `T` types would apply: +/// +/// ``` +/// # #[allow(dead_code)] +/// pub struct Foo(Vec<u32>, Vec<String>); +/// +/// impl std::borrow::Borrow<[u32]> for Foo { +/// fn borrow(&self) -> &[u32] { &self.0 } +/// } +/// +/// impl std::borrow::Borrow<[String]> for Foo { +/// fn borrow(&self) -> &[String] { &self.1 } +/// } +/// ``` +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Concat<Item: ?Sized> { + #[unstable(feature = "slice_concat_trait", issue = "27747")] /// The resulting type after concatenation type Output; - /// Flattens a slice of `T` into a single value `Self::Output`. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(["hello", "world"].concat(), "helloworld"); - /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn concat(&self) -> Self::Output; + /// Implementation of [`[T]::concat`](../../std/primitive.slice.html#method.concat) + #[unstable(feature = "slice_concat_trait", issue = "27747")] + fn concat(slice: &Self) -> Self::Output; +} - /// Flattens a slice of `T` into a single value `Self::Output`, placing a - /// given separator between each. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(["hello", "world"].join(" "), "hello world"); - /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); - /// ``` - #[stable(feature = "rename_connect_to_join", since = "1.3.0")] - fn join(&self, sep: &T) -> Self::Output; +/// Helper trait for [`[T]::join`](../../std/primitive.slice.html#method.join) +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Join<Separator> { + #[unstable(feature = "slice_concat_trait", issue = "27747")] + /// The resulting type after concatenation + type Output; - /// Flattens a slice of `T` into a single value `Self::Output`, placing a - /// given separator between each. - /// - /// # Examples - /// - /// ``` - /// # #![allow(deprecated)] - /// assert_eq!(["hello", "world"].connect(" "), "hello world"); - /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] - fn connect(&self, sep: &T) -> Self::Output; + /// Implementation of [`[T]::join`](../../std/primitive.slice.html#method.join) + #[unstable(feature = "slice_concat_trait", issue = "27747")] + fn join(slice: &Self, sep: Separator) -> Self::Output; } -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] -impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] { +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<T: Clone, V: Borrow<[T]>> Concat<T> for [V] { type Output = Vec<T>; - fn concat(&self) -> Vec<T> { - let size = self.iter().map(|slice| slice.borrow().len()).sum(); + fn concat(slice: &Self) -> Vec<T> { + let size = slice.iter().map(|slice| slice.borrow().len()).sum(); let mut result = Vec::with_capacity(size); - for v in self { + for v in slice { result.extend_from_slice(v.borrow()) } result } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<T: Clone, V: Borrow<[T]>> Join<&T> for [V] { + type Output = Vec<T>; - fn join(&self, sep: &T) -> Vec<T> { - let mut iter = self.iter(); + fn join(slice: &Self, sep: &T) -> Vec<T> { + let mut iter = slice.iter(); let first = match iter.next() { Some(first) => first, None => return vec![], }; - let size = self.iter().map(|slice| slice.borrow().len()).sum::<usize>() + self.len() - 1; + let size = slice.iter().map(|v| v.borrow().len()).sum::<usize>() + slice.len() - 1; let mut result = Vec::with_capacity(size); result.extend_from_slice(first.borrow()); @@ -616,9 +665,28 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] { } result } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<T: Clone, V: Borrow<[T]>> Join<&[T]> for [V] { + type Output = Vec<T>; + + fn join(slice: &Self, sep: &[T]) -> Vec<T> { + let mut iter = slice.iter(); + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + let size = slice.iter().map(|v| v.borrow().len()).sum::<usize>() + + sep.len() * (slice.len() - 1); + let mut result = Vec::with_capacity(size); + result.extend_from_slice(first.borrow()); - fn connect(&self, sep: &T) -> Vec<T> { - self.join(sep) + for v in iter { + result.extend_from_slice(sep); + result.extend_from_slice(v.borrow()) + } + result } } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index f66ff894ae8..9a1342c30d5 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -37,7 +37,7 @@ use core::unicode::conversions; use crate::borrow::ToOwned; use crate::boxed::Box; -use crate::slice::{SliceConcatExt, SliceIndex}; +use crate::slice::{Concat, Join, SliceIndex}; use crate::string::String; use crate::vec::Vec; @@ -71,25 +71,26 @@ pub use core::str::SplitAsciiWhitespace; #[stable(feature = "str_escape", since = "1.34.0")] pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode}; -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] -impl<S: Borrow<str>> SliceConcatExt<str> for [S] { +/// Note: `str` in `Concat<str>` is not meaningful here. +/// This type parameter of the trait only exists to enable another impl. +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<S: Borrow<str>> Concat<str> for [S] { type Output = String; - fn concat(&self) -> String { - self.join("") + fn concat(slice: &Self) -> String { + Join::join(slice, "") } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<S: Borrow<str>> Join<&str> for [S] { + type Output = String; - fn join(&self, sep: &str) -> String { + fn join(slice: &Self, sep: &str) -> String { unsafe { - String::from_utf8_unchecked( join_generic_copy(self, sep.as_bytes()) ) + String::from_utf8_unchecked( join_generic_copy(slice, sep.as_bytes()) ) } } - - fn connect(&self, sep: &str) -> String { - self.join(sep) - } } macro_rules! spezialize_for_lengths { @@ -130,7 +131,7 @@ macro_rules! copy_slice_and_advance { // Optimized join implementation that works for both Vec<T> (T: Copy) and String's inner vec // Currently (2018-05-13) there is a bug with type inference and specialization (see issue #36262) -// For this reason SliceConcatExt<T> is not specialized for T: Copy and SliceConcatExt<str> is the +// For this reason SliceConcat<T> is not specialized for T: Copy and SliceConcat<str> is the // only user of this function. It is left in place for the time when that is fixed. // // the bounds for String-join are S: Borrow<str> and for Vec-join Borrow<[T]> @@ -207,7 +208,7 @@ impl ToOwned for str { } fn clone_into(&self, target: &mut String) { - let mut b = mem::replace(target, String::new()).into_bytes(); + let mut b = mem::take(target).into_bytes(); self.as_bytes().clone_into(&mut b); *target = unsafe { String::from_utf8_unchecked(b) } } @@ -431,6 +432,13 @@ impl str { /// /// assert_eq!(new_year, new_year.to_uppercase()); /// ``` + /// + /// One character can become multiple: + /// ``` + /// let s = "tschüß"; + /// + /// assert_eq!("TSCHÜSS", s.to_uppercase()); + /// ``` #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_uppercase(&self) -> String { let mut s = String::with_capacity(self.len()); diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index e74d37c1c2b..b65f191836e 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -56,7 +56,7 @@ use core::ptr; use core::str::{pattern::Pattern, lossy}; use crate::borrow::{Cow, ToOwned}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::boxed::Box; use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use crate::vec::Vec; @@ -552,7 +552,7 @@ impl String { /// assert_eq!("Hello �World", output); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { + pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); let (first_valid, first_broken) = if let Some(chunk) = iter.next() { @@ -937,9 +937,9 @@ impl String { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &str) -> Result<String, CollectionAllocErr> { + /// fn process_data(data: &str) -> Result<String, TryReserveError> { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -953,7 +953,7 @@ impl String { /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve(additional) } @@ -975,9 +975,9 @@ impl String { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &str) -> Result<String, CollectionAllocErr> { + /// fn process_data(data: &str) -> Result<String, TryReserveError> { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -991,7 +991,7 @@ impl String { /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve_exact(additional) } @@ -1838,6 +1838,7 @@ impl PartialEq for String { macro_rules! impl_eq { ($lhs:ty, $rhs: ty) => { #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] impl<'a, 'b> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) } @@ -1846,6 +1847,7 @@ macro_rules! impl_eq { } #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unused_lifetimes)] impl<'a, 'b> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) } @@ -2385,6 +2387,7 @@ impl Iterator for Drain<'_> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } + #[inline] fn last(mut self) -> Option<char> { self.next_back() diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 90c7859b3db..341172136e2 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -7,21 +7,23 @@ //! [arc]: struct.Arc.html use core::any::Any; +use core::array::LengthAtMost32; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; use core::fmt; use core::cmp::{self, Ordering}; +use core::iter; use core::intrinsics::abort; -use core::mem::{self, align_of_val, size_of_val}; +use core::mem::{self, align_of, align_of_val, size_of_val}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::pin::Pin; use core::ptr::{self, NonNull}; use core::marker::{Unpin, Unsize, PhantomData}; use core::hash::{Hash, Hasher}; use core::{isize, usize}; -use core::convert::From; -use core::slice::from_raw_parts_mut; +use core::convert::{From, TryFrom}; +use core::slice::{self, from_raw_parts_mut}; use crate::alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; use crate::boxed::Box; @@ -29,6 +31,9 @@ use crate::rc::is_dangling; use crate::string::String; use crate::vec::Vec; +#[cfg(test)] +mod tests; + /// A soft limit on the amount of references that may be made to an `Arc`. /// /// Going above this limit will abort your program (although not @@ -206,6 +211,19 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {} #[unstable(feature = "dispatch_from_dyn", issue = "0")] impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {} +impl<T: ?Sized> Arc<T> { + fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self { + Self { + ptr, + phantom: PhantomData, + } + } + + unsafe fn from_ptr(ptr: *mut ArcInner<T>) -> Self { + Self::from_inner(NonNull::new_unchecked(ptr)) + } +} + /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the /// managed value. The value is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`. @@ -290,7 +308,38 @@ impl<T> Arc<T> { weak: atomic::AtomicUsize::new(1), data, }; - Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } + Self::from_inner(Box::into_raw_non_null(x)) + } + + /// Constructs a new `Arc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::<T>(), + |mem| mem as *mut ArcInner<mem::MaybeUninit<T>>, + )) + } } /// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then @@ -343,6 +392,118 @@ impl<T> Arc<T> { } } +impl<T> Arc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> { + unsafe { + Arc::from_ptr(Arc::allocate_for_slice(len)) + } + } +} + +impl<T> Arc<mem::MaybeUninit<T>> { + /// Converts to `Arc<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<T> { + Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl<T> Arc<[mem::MaybeUninit<T>]> { + /// Converts to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + } +} + impl<T: ?Sized> Arc<T> { /// Consumes the `Arc`, returning the wrapped pointer. /// @@ -356,9 +517,9 @@ impl<T: ?Sized> Arc<T> { /// ``` /// use std::sync::Arc; /// - /// let x = Arc::new(10); + /// let x = Arc::new("hello".to_owned()); /// let x_ptr = Arc::into_raw(x); - /// assert_eq!(unsafe { *x_ptr }, 10); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { @@ -382,13 +543,13 @@ impl<T: ?Sized> Arc<T> { /// ``` /// use std::sync::Arc; /// - /// let x = Arc::new(10); + /// let x = Arc::new("hello".to_owned()); /// let x_ptr = Arc::into_raw(x); /// /// unsafe { /// // Convert back to an `Arc` to prevent leak. /// let x = Arc::from_raw(x_ptr); - /// assert_eq!(*x, 10); + /// assert_eq!(&*x, "hello"); /// /// // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe. /// } @@ -397,20 +558,13 @@ impl<T: ?Sized> Arc<T> { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // Align the unsized value to the end of the ArcInner. - // Because it is ?Sized, it will always be the last field in memory. - let align = align_of_val(&*ptr); - let layout = Layout::new::<ArcInner<()>>(); - let offset = (layout.size() + layout.padding_needed_for(align)) as isize; + let offset = data_offset(ptr); // Reverse the offset to find the original ArcInner. let fake_ptr = ptr as *mut ArcInner<T>; let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Arc { - ptr: NonNull::new_unchecked(arc_ptr), - phantom: PhantomData, - } + Self::from_ptr(arc_ptr) } /// Consumes the `Arc`, returning the wrapped pointer as `NonNull<T>`. @@ -422,10 +576,10 @@ impl<T: ?Sized> Arc<T> { /// /// use std::sync::Arc; /// - /// let x = Arc::new(10); + /// let x = Arc::new("hello".to_owned()); /// let ptr = Arc::into_raw_non_null(x); - /// let deref = unsafe { *ptr.as_ref() }; - /// assert_eq!(deref, 10); + /// let deref = unsafe { ptr.as_ref() }; + /// assert_eq!(deref, "hello"); /// ``` #[unstable(feature = "rc_into_raw_non_null", issue = "47336")] #[inline] @@ -581,21 +735,28 @@ impl<T: ?Sized> Arc<T> { } impl<T: ?Sized> Arc<T> { - // Allocates an `ArcInner<T>` with sufficient space for an unsized value - unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> { - // Calculate layout using the given value. + /// Allocates an `ArcInner<T>` with sufficient space for + /// a possibly-unsized value where the value has the layout provided. + /// + /// The function `mem_to_arcinner` is called with the data pointer + /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`. + unsafe fn allocate_for_layout( + value_layout: Layout, + mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T> + ) -> *mut ArcInner<T> { + // Calculate layout using the given value layout. // Previously, layout was calculated on the expression // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned // reference (see #54908). let layout = Layout::new::<ArcInner<()>>() - .extend(Layout::for_value(&*ptr)).unwrap().0 + .extend(value_layout).unwrap().0 .pad_to_align().unwrap(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the ArcInner - let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>; + let inner = mem_to_arcinner(mem.as_ptr()); debug_assert_eq!(Layout::for_value(&*inner), layout); ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); @@ -604,6 +765,15 @@ impl<T: ?Sized> Arc<T> { inner } + /// Allocates an `ArcInner<T>` with sufficient space for an unsized value. + unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> { + // Allocate for the `ArcInner<T>` using the given value. + Self::allocate_for_layout( + Layout::for_value(&*ptr), + |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>, + ) + } + fn from_box(v: Box<T>) -> Arc<T> { unsafe { let box_unique = Box::into_unique(v); @@ -621,45 +791,49 @@ impl<T: ?Sized> Arc<T> { // Free the allocation without dropping its contents box_free(box_unique); - Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } + Self::from_ptr(ptr) } } } -// Sets the data pointer of a `?Sized` raw pointer. -// -// For a slice/trait object, this sets the `data` field and leaves the rest -// unchanged. For a sized raw pointer, this simply sets the pointer. +impl<T> Arc<[T]> { + /// Allocates an `ArcInner<[T]>` with the given length. + unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { + Self::allocate_for_layout( + Layout::array::<T>(len).unwrap(), + |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>, + ) + } +} + +/// Sets the data pointer of a `?Sized` raw pointer. +/// +/// For a slice/trait object, this sets the `data` field and leaves the rest +/// unchanged. For a sized raw pointer, this simply sets the pointer. unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T { ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); ptr } impl<T> Arc<[T]> { - // Copy elements from slice into newly allocated Arc<[T]> - // - // Unsafe because the caller must either take ownership or bind `T: Copy` + /// Copy elements from slice into newly allocated Arc<[T]> + /// + /// Unsafe because the caller must either take ownership or bind `T: Copy`. unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { - let v_ptr = v as *const [T]; - let ptr = Self::allocate_for_ptr(v_ptr); + let ptr = Self::allocate_for_slice(v.len()); ptr::copy_nonoverlapping( v.as_ptr(), &mut (*ptr).data as *mut [T] as *mut T, v.len()); - Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } + Self::from_ptr(ptr) } -} - -// Specialization trait used for From<&[T]> -trait ArcFromSlice<T> { - fn from_slice(slice: &[T]) -> Self; -} -impl<T: Clone> ArcFromSlice<T> for Arc<[T]> { - #[inline] - default fn from_slice(v: &[T]) -> Self { + /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. + /// + /// Behavior is undefined should the size be wrong. + unsafe fn from_iter_exact(iter: impl iter::Iterator<Item = T>, len: usize) -> Arc<[T]> { // Panic guard while cloning T elements. // In the event of a panic, elements that have been written // into the new ArcInner will be dropped, then the memory freed. @@ -676,37 +850,48 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> { let slice = from_raw_parts_mut(self.elems, self.n_elems); ptr::drop_in_place(slice); - Global.dealloc(self.mem.cast(), self.layout.clone()); + Global.dealloc(self.mem.cast(), self.layout); } } } - unsafe { - let v_ptr = v as *const [T]; - let ptr = Self::allocate_for_ptr(v_ptr); + let ptr = Self::allocate_for_slice(len); - let mem = ptr as *mut _ as *mut u8; - let layout = Layout::for_value(&*ptr); + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); - // Pointer to first element - let elems = &mut (*ptr).data as *mut [T] as *mut T; + // Pointer to first element + let elems = &mut (*ptr).data as *mut [T] as *mut T; - let mut guard = Guard{ - mem: NonNull::new_unchecked(mem), - elems: elems, - layout: layout, - n_elems: 0, - }; + let mut guard = Guard { + mem: NonNull::new_unchecked(mem), + elems, + layout, + n_elems: 0, + }; - for (i, item) in v.iter().enumerate() { - ptr::write(elems.add(i), item.clone()); - guard.n_elems += 1; - } + for (i, item) in iter.enumerate() { + ptr::write(elems.add(i), item); + guard.n_elems += 1; + } - // All clear. Forget the guard so it doesn't free the new ArcInner. - mem::forget(guard); + // All clear. Forget the guard so it doesn't free the new ArcInner. + mem::forget(guard); - Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } + Self::from_ptr(ptr) + } +} + +/// Specialization trait used for `From<&[T]>`. +trait ArcFromSlice<T> { + fn from_slice(slice: &[T]) -> Self; +} + +impl<T: Clone> ArcFromSlice<T> for Arc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + unsafe { + Self::from_iter_exact(v.iter().cloned(), v.len()) } } } @@ -764,7 +949,7 @@ impl<T: ?Sized> Clone for Arc<T> { } } - Arc { ptr: self.ptr, phantom: PhantomData } + Self::from_inner(self.ptr) } } @@ -903,13 +1088,46 @@ impl<T: ?Sized> Arc<T> { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - Some(&mut this.ptr.as_mut().data) + Some(Arc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Arc.html#method.get_mut + /// + /// # Safety + /// + /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Arc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[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 + } + /// Determine whether this is the unique reference (including weak refs) to /// the underlying data. /// @@ -1043,7 +1261,7 @@ impl Arc<dyn Any + Send + Sync> { if (*self).is::<T>() { let ptr = self.ptr.cast::<ArcInner<T>>(); mem::forget(self); - Ok(Arc { ptr, phantom: PhantomData }) + Ok(Arc::from_inner(ptr)) } else { Err(self) } @@ -1071,6 +1289,144 @@ impl<T> Weak<T> { ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"), } } + + /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`. + /// + /// It is up to the caller to ensure that the object is still alive when accessing it through + /// the pointer. + /// + /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::Arc; + /// use std::ptr; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// // Both point to the same object + /// assert!(ptr::eq(&*strong, weak.as_raw())); + /// // The strong here keeps it alive, so we can still access the object. + /// assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// + /// drop(strong); + /// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to + /// // undefined behaviour. + /// // assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_raw(&self) -> *const T { + match self.inner() { + None => ptr::null(), + Some(inner) => { + let offset = data_offset_sized::<T>(); + let ptr = inner as *const ArcInner<T>; + // Note: while the pointer we create may already point to dropped value, the + // allocation still lives (it must hold the weak point as long as we are alive). + // Therefore, the offset is OK to do, it won't get out of the allocation. + let ptr = unsafe { (ptr as *const u8).offset(offset) }; + ptr as *const T + } + } + } + + /// Consumes the `Weak<T>` and turns it into a raw pointer. + /// + /// This converts the weak pointer into a raw pointer, preserving the original weak count. It + /// can be turned back into the `Weak<T>` with [`from_raw`]. + /// + /// The same restrictions of accessing the target of the pointer as with + /// [`as_raw`] apply. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// let weak = Arc::downgrade(&strong); + /// let raw = weak.into_raw(); + /// + /// assert_eq!(1, Arc::weak_count(&strong)); + /// assert_eq!("hello", unsafe { &*raw }); + /// + /// drop(unsafe { Weak::from_raw(raw) }); + /// assert_eq!(0, Arc::weak_count(&strong)); + /// ``` + /// + /// [`from_raw`]: struct.Weak.html#method.from_raw + /// [`as_raw`]: struct.Weak.html#method.as_raw + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn into_raw(self) -> *const T { + let result = self.as_raw(); + mem::forget(self); + result + } + + /// Converts a raw pointer previously created by [`into_raw`] back into + /// `Weak<T>`. + /// + /// This can be used to safely get a strong reference (by calling [`upgrade`] + /// later) or to deallocate the weak count by dropping the `Weak<T>`. + /// + /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is + /// returned. + /// + /// # Safety + /// + /// The pointer must represent one valid weak count. In other words, it must point to `T` which + /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached + /// 0. It is allowed for the strong count to be 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::{Arc, Weak}; + /// + /// let strong = Arc::new("hello".to_owned()); + /// + /// let raw_1 = Arc::downgrade(&strong).into_raw(); + /// let raw_2 = Arc::downgrade(&strong).into_raw(); + /// + /// assert_eq!(2, Arc::weak_count(&strong)); + /// + /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap()); + /// assert_eq!(1, Arc::weak_count(&strong)); + /// + /// drop(strong); + /// + /// // Decrement the last weak count. + /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); + /// ``` + /// + /// [`null`]: ../../std/ptr/fn.null.html + /// [`into_raw`]: struct.Weak.html#method.into_raw + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`Weak`]: struct.Weak.html + /// [`Arc`]: struct.Arc.html + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + if ptr.is_null() { + Self::new() + } else { + // See Arc::from_raw for details + let offset = data_offset(ptr); + let fake_ptr = ptr as *mut ArcInner<T>; + let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); + Weak { + ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"), + } + } + } } impl<T: ?Sized> Weak<T> { @@ -1126,11 +1482,7 @@ impl<T: ?Sized> Weak<T> { // Relaxed is valid for the same reason it is on Arc's Clone impl match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) { - Ok(_) => return Some(Arc { - // null checked above - ptr: self.ptr, - phantom: PhantomData, - }), + Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above Err(old) => n = old, } } @@ -1215,18 +1567,18 @@ impl<T: ?Sized> Weak<T> { /// /// ``` /// #![feature(weak_ptr_eq)] - /// use std::sync::{Arc, Weak}; + /// use std::sync::Arc; /// /// let first_rc = Arc::new(5); /// let first = Arc::downgrade(&first_rc); /// let second = Arc::downgrade(&first_rc); /// - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Arc::new(5); /// let third = Arc::downgrade(&third_rc); /// - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` /// /// Comparing `Weak::new`. @@ -1237,16 +1589,16 @@ impl<T: ?Sized> Weak<T> { /// /// let first = Weak::new(); /// let second = Weak::new(); - /// assert!(Weak::ptr_eq(&first, &second)); + /// assert!(first.ptr_eq(&second)); /// /// let third_rc = Arc::new(()); /// let third = Arc::downgrade(&third_rc); - /// assert!(!Weak::ptr_eq(&first, &third)); + /// assert!(!first.ptr_eq(&third)); /// ``` #[inline] #[unstable(feature = "weak_ptr_eq", issue = "55981")] - pub fn ptr_eq(this: &Self, other: &Self) -> bool { - this.ptr.as_ptr() == other.ptr.as_ptr() + pub fn ptr_eq(&self, other: &Self) -> bool { + self.ptr.as_ptr() == other.ptr.as_ptr() } } @@ -1651,486 +2003,111 @@ impl<T> From<Vec<T>> for Arc<[T]> { } } -#[cfg(test)] -mod tests { - use std::boxed::Box; - use std::clone::Clone; - use std::sync::mpsc::channel; - use std::mem::drop; - use std::ops::Drop; - use std::option::Option::{self, None, Some}; - use std::sync::atomic::{self, Ordering::{Acquire, SeqCst}}; - use std::thread; - use std::sync::Mutex; - use std::convert::From; - - use super::{Arc, Weak}; - use crate::vec::Vec; - - struct Canary(*mut atomic::AtomicUsize); - - impl Drop for Canary { - fn drop(&mut self) { - unsafe { - match *self { - Canary(c) => { - (*c).fetch_add(1, SeqCst); - } - } - } - } - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg(not(miri))] // Miri does not support threads - fn manually_share_arc() { - let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let arc_v = Arc::new(v); - - let (tx, rx) = channel(); - - let _t = thread::spawn(move || { - let arc_v: Arc<Vec<i32>> = rx.recv().unwrap(); - assert_eq!((*arc_v)[3], 4); - }); - - tx.send(arc_v.clone()).unwrap(); - - assert_eq!((*arc_v)[2], 3); - assert_eq!((*arc_v)[4], 5); - } - - #[test] - fn test_arc_get_mut() { - let mut x = Arc::new(3); - *Arc::get_mut(&mut x).unwrap() = 4; - assert_eq!(*x, 4); - let y = x.clone(); - assert!(Arc::get_mut(&mut x).is_none()); - drop(y); - assert!(Arc::get_mut(&mut x).is_some()); - let _w = Arc::downgrade(&x); - assert!(Arc::get_mut(&mut x).is_none()); - } - - #[test] - fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None); - assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); - - let a = Arc::new(0); - let w = Arc::downgrade(&a); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(1)); - let w2 = w.clone(); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(2)); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(2)); - drop(w); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(1)); - let a2 = a.clone(); - assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), Some(1)); - drop(a2); - drop(a); - assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), Some(1)); - drop(w2); - } - - #[test] - fn try_unwrap() { - let x = Arc::new(3); - assert_eq!(Arc::try_unwrap(x), Ok(3)); - let x = Arc::new(4); - let _y = x.clone(); - assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); - let x = Arc::new(5); - let _w = Arc::downgrade(&x); - assert_eq!(Arc::try_unwrap(x), Ok(5)); - } - - #[test] - fn into_from_raw() { - let x = Arc::new(box "hello"); - let y = x.clone(); - - let x_ptr = Arc::into_raw(x); - drop(y); - unsafe { - assert_eq!(**x_ptr, "hello"); - - let x = Arc::from_raw(x_ptr); - assert_eq!(**x, "hello"); - - assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); - } - } - - #[test] - fn test_into_from_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Arc<str> = Arc::from("foo"); - - let ptr = Arc::into_raw(arc.clone()); - let arc2 = unsafe { Arc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert_eq!(arc, arc2); - - let arc: Arc<dyn Display> = Arc::new(123); - - let ptr = Arc::into_raw(arc.clone()); - let arc2 = unsafe { Arc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert_eq!(arc2.to_string(), "123"); - } - - #[test] - fn test_cowarc_clone_make_mut() { - let mut cow0 = Arc::new(75); - let mut cow1 = cow0.clone(); - let mut cow2 = cow1.clone(); - - assert!(75 == *Arc::make_mut(&mut cow0)); - assert!(75 == *Arc::make_mut(&mut cow1)); - assert!(75 == *Arc::make_mut(&mut cow2)); - - *Arc::make_mut(&mut cow0) += 1; - *Arc::make_mut(&mut cow1) += 2; - *Arc::make_mut(&mut cow2) += 3; - - assert!(76 == *cow0); - assert!(77 == *cow1); - assert!(78 == *cow2); - - // none should point to the same backing memory - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 != *cow2); - } - - #[test] - fn test_cowarc_clone_unique2() { - let mut cow0 = Arc::new(75); - let cow1 = cow0.clone(); - let cow2 = cow1.clone(); - - assert!(75 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - *Arc::make_mut(&mut cow0) += 1; - assert!(76 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - // cow1 and cow2 should share the same contents - // cow0 should have a unique reference - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 == *cow2); - } - - #[test] - fn test_cowarc_clone_weak() { - let mut cow0 = Arc::new(75); - let cow1_weak = Arc::downgrade(&cow0); - - assert!(75 == *cow0); - assert!(75 == *cow1_weak.upgrade().unwrap()); - - *Arc::make_mut(&mut cow0) += 1; +#[unstable(feature = "boxed_slice_try_from", issue = "0")] +impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]> +where + [T; N]: LengthAtMost32, +{ + type Error = Arc<[T]>; - assert!(76 == *cow0); - assert!(cow1_weak.upgrade().is_none()); - } - - #[test] - fn test_live() { - let x = Arc::new(5); - let y = Arc::downgrade(&x); - assert!(y.upgrade().is_some()); - } - - #[test] - fn test_dead() { - let x = Arc::new(5); - let y = Arc::downgrade(&x); - drop(x); - assert!(y.upgrade().is_none()); - } - - #[test] - fn weak_self_cyclic() { - struct Cycle { - x: Mutex<Option<Weak<Cycle>>>, - } - - let a = Arc::new(Cycle { x: Mutex::new(None) }); - let b = Arc::downgrade(&a.clone()); - *a.x.lock().unwrap() = Some(b); - - // hopefully we don't double-free (or leak)... - } - - #[test] - fn drop_arc() { - let mut canary = atomic::AtomicUsize::new(0); - let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); - drop(x); - assert!(canary.load(Acquire) == 1); - } - - #[test] - fn drop_arc_weak() { - let mut canary = atomic::AtomicUsize::new(0); - let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); - let arc_weak = Arc::downgrade(&arc); - assert!(canary.load(Acquire) == 0); - drop(arc); - assert!(canary.load(Acquire) == 1); - drop(arc_weak); - } - - #[test] - fn test_strong_count() { - let a = Arc::new(0); - assert!(Arc::strong_count(&a) == 1); - let w = Arc::downgrade(&a); - assert!(Arc::strong_count(&a) == 1); - let b = w.upgrade().expect(""); - assert!(Arc::strong_count(&b) == 2); - assert!(Arc::strong_count(&a) == 2); - drop(w); - drop(a); - assert!(Arc::strong_count(&b) == 1); - let c = b.clone(); - assert!(Arc::strong_count(&b) == 2); - assert!(Arc::strong_count(&c) == 2); - } - - #[test] - fn test_weak_count() { - let a = Arc::new(0); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 0); - let w = Arc::downgrade(&a); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 1); - let x = w.clone(); - assert!(Arc::weak_count(&a) == 2); - drop(w); - drop(x); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 0); - let c = a.clone(); - assert!(Arc::strong_count(&a) == 2); - assert!(Arc::weak_count(&a) == 0); - let d = Arc::downgrade(&c); - assert!(Arc::weak_count(&c) == 1); - assert!(Arc::strong_count(&c) == 2); - - drop(a); - drop(c); - drop(d); - } - - #[test] - fn show_arc() { - let a = Arc::new(5); - assert_eq!(format!("{:?}", a), "5"); - } - - // Make sure deriving works with Arc<T> - #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] - struct Foo { - inner: Arc<i32>, - } - - #[test] - fn test_unsized() { - let x: Arc<[i32]> = Arc::new([1, 2, 3]); - assert_eq!(format!("{:?}", x), "[1, 2, 3]"); - let y = Arc::downgrade(&x.clone()); - drop(x); - assert!(y.upgrade().is_none()); - } - - #[test] - fn test_from_owned() { - let foo = 123; - let foo_arc = Arc::from(foo); - assert!(123 == *foo_arc); - } - - #[test] - fn test_new_weak() { - let foo: Weak<usize> = Weak::new(); - assert!(foo.upgrade().is_none()); - } - - #[test] - fn test_ptr_eq() { - let five = Arc::new(5); - let same_five = five.clone(); - let other_five = Arc::new(5); - - assert!(Arc::ptr_eq(&five, &same_five)); - assert!(!Arc::ptr_eq(&five, &other_five)); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - #[cfg(not(miri))] // Miri does not support threads - fn test_weak_count_locked() { - let mut a = Arc::new(atomic::AtomicBool::new(false)); - let a2 = a.clone(); - let t = thread::spawn(move || { - for _i in 0..1000000 { - Arc::get_mut(&mut a); - } - a.store(true, SeqCst); - }); - - while !a2.load(SeqCst) { - let n = Arc::weak_count(&a2); - assert!(n < 2, "bad weak count: {}", n); + fn try_from(boxed_slice: Arc<[T]>) -> Result<Self, Self::Error> { + if boxed_slice.len() == N { + Ok(unsafe { Arc::from_raw(Arc::into_raw(boxed_slice) as *mut [T; N]) }) + } else { + Err(boxed_slice) } - t.join().unwrap(); } +} - #[test] - fn test_from_str() { - let r: Arc<str> = Arc::from("foo"); - - assert_eq!(&r[..], "foo"); - } - - #[test] - fn test_copy_from_slice() { - let s: &[u32] = &[1, 2, 3]; - let r: Arc<[u32]> = Arc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); +#[stable(feature = "shared_from_iter", since = "1.37.0")] +impl<T> iter::FromIterator<T> for Arc<[T]> { + /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`. + /// + /// # Performance characteristics + /// + /// ## The general case + /// + /// In the general case, collecting into `Arc<[T]>` is done by first + /// collecting into a `Vec<T>`. That is, when writing the following: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect(); + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// this behaves as if we wrote: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0) + /// .collect::<Vec<_>>() // The first set of allocations happens here. + /// .into(); // A second allocation for `Arc<[T]>` happens here. + /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]); + /// ``` + /// + /// This will allocate as many times as needed for constructing the `Vec<T>` + /// and then it will allocate once for turning the `Vec<T>` into the `Arc<[T]>`. + /// + /// ## Iterators of known length + /// + /// When your `Iterator` implements `TrustedLen` and is of an exact size, + /// a single allocation will be made for the `Arc<[T]>`. For example: + /// + /// ```rust + /// # use std::sync::Arc; + /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here. + /// # assert_eq!(&*evens, &*(0..10).collect::<Vec<_>>()); + /// ``` + fn from_iter<I: iter::IntoIterator<Item = T>>(iter: I) -> Self { + ArcFromIter::from_iter(iter.into_iter()) } +} - #[test] - fn test_clone_from_slice() { - #[derive(Clone, Debug, Eq, PartialEq)] - struct X(u32); - - let s: &[X] = &[X(1), X(2), X(3)]; - let r: Arc<[X]> = Arc::from(s); +/// Specialization trait used for collecting into `Arc<[T]>`. +trait ArcFromIter<T, I> { + fn from_iter(iter: I) -> Self; +} - assert_eq!(&r[..], s); +impl<T, I: Iterator<Item = T>> ArcFromIter<T, I> for Arc<[T]> { + default fn from_iter(iter: I) -> Self { + iter.collect::<Vec<T>>().into() } +} - #[test] - #[should_panic] - fn test_clone_from_slice_panic() { - use std::string::{String, ToString}; - - struct Fail(u32, String); +impl<T, I: iter::TrustedLen<Item = T>> ArcFromIter<T, I> for Arc<[T]> { + default fn from_iter(iter: I) -> Self { + // This is the case for a `TrustedLen` iterator. + let (low, high) = iter.size_hint(); + if let Some(high) = high { + debug_assert_eq!( + low, high, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); - impl Clone for Fail { - fn clone(&self) -> Fail { - if self.0 == 2 { - panic!(); - } - Fail(self.0, self.1.clone()) + unsafe { + // SAFETY: We need to ensure that the iterator has an exact length and we have. + Arc::from_iter_exact(iter, low) } + } else { + // Fall back to normal implementation. + iter.collect::<Vec<T>>().into() } - - let s: &[Fail] = &[ - Fail(0, "foo".to_string()), - Fail(1, "bar".to_string()), - Fail(2, "baz".to_string()), - ]; - - // Should panic, but not cause memory corruption - let _r: Arc<[Fail]> = Arc::from(s); - } - - #[test] - fn test_from_box() { - let b: Box<u32> = box 123; - let r: Arc<u32> = Arc::from(b); - - assert_eq!(*r, 123); - } - - #[test] - fn test_from_box_str() { - use std::string::String; - - let s = String::from("foo").into_boxed_str(); - let r: Arc<str> = Arc::from(s); - - assert_eq!(&r[..], "foo"); - } - - #[test] - fn test_from_box_slice() { - let s = vec![1, 2, 3].into_boxed_slice(); - let r: Arc<[u32]> = Arc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); - } - - #[test] - fn test_from_box_trait() { - use std::fmt::Display; - use std::string::ToString; - - let b: Box<dyn Display> = box 123; - let r: Arc<dyn Display> = Arc::from(b); - - assert_eq!(r.to_string(), "123"); - } - - #[test] - fn test_from_box_trait_zero_sized() { - use std::fmt::Debug; - - let b: Box<dyn Debug> = box (); - let r: Arc<dyn Debug> = Arc::from(b); - - assert_eq!(format!("{:?}", r), "()"); } +} - #[test] - fn test_from_vec() { - let v = vec![1, 2, 3]; - let r: Arc<[u32]> = Arc::from(v); - - assert_eq!(&r[..], [1, 2, 3]); - } - - #[test] - fn test_downcast() { - use std::any::Any; - - let r1: Arc<dyn Any + Send + Sync> = Arc::new(i32::max_value()); - let r2: Arc<dyn Any + Send + Sync> = Arc::new("abc"); - - assert!(r1.clone().downcast::<u32>().is_err()); - - let r1i32 = r1.downcast::<i32>(); - assert!(r1i32.is_ok()); - assert_eq!(r1i32.unwrap(), Arc::new(i32::max_value())); - - assert!(r2.clone().downcast::<i32>().is_err()); - - let r2str = r2.downcast::<&'static str>(); - assert!(r2str.is_ok()); - assert_eq!(r2str.unwrap(), Arc::new("abc")); +impl<'a, T: 'a + Clone> ArcFromIter<&'a T, slice::Iter<'a, T>> for Arc<[T]> { + fn from_iter(iter: slice::Iter<'a, T>) -> Self { + // Delegate to `impl<T: Clone> From<&[T]> for Arc<[T]>`. + // + // In the case that `T: Copy`, we get to use `ptr::copy_nonoverlapping` + // which is even more performant. + // + // In the fall-back case we have `T: Clone`. This is still better + // than the `TrustedLen` implementation as slices have a known length + // and so we get to avoid calling `size_hint` and avoid the branching. + iter.as_slice().into() } } @@ -2150,3 +2127,23 @@ impl<T: ?Sized> AsRef<T> for Arc<T> { #[stable(feature = "pin", since = "1.33.0")] impl<T: ?Sized> Unpin for Arc<T> { } + +/// Computes the offset of the data field within `ArcInner`. +unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize { + // Align the unsized value to the end of the `ArcInner`. + // Because it is `?Sized`, it will always be the last field in memory. + data_offset_align(align_of_val(&*ptr)) +} + +/// Computes the offset of the data field within `ArcInner`. +/// +/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. +fn data_offset_sized<T>() -> isize { + data_offset_align(align_of::<T>()) +} + +#[inline] +fn data_offset_align(align: usize) -> isize { + let layout = Layout::new::<ArcInner<()>>(); + (layout.size() + layout.padding_needed_for(align)) as isize +} diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs new file mode 100644 index 00000000000..9220f5e0333 --- /dev/null +++ b/src/liballoc/sync/tests.rs @@ -0,0 +1,492 @@ +use super::*; + +use std::boxed::Box; +use std::clone::Clone; +use std::sync::mpsc::channel; +use std::mem::drop; +use std::ops::Drop; +use std::option::Option::{self, None, Some}; +use std::sync::atomic::{self, Ordering::{Acquire, SeqCst}}; +use std::thread; +use std::sync::Mutex; +use std::convert::{From, TryInto}; + +use crate::vec::Vec; + +struct Canary(*mut atomic::AtomicUsize); + +impl Drop for Canary { + fn drop(&mut self) { + unsafe { + match *self { + Canary(c) => { + (*c).fetch_add(1, SeqCst); + } + } + } + } +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +#[cfg(not(miri))] // Miri does not support threads +fn manually_share_arc() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let arc_v = Arc::new(v); + + let (tx, rx) = channel(); + + let _t = thread::spawn(move || { + let arc_v: Arc<Vec<i32>> = rx.recv().unwrap(); + assert_eq!((*arc_v)[3], 4); + }); + + tx.send(arc_v.clone()).unwrap(); + + assert_eq!((*arc_v)[2], 3); + assert_eq!((*arc_v)[4], 5); +} + +#[test] +fn test_arc_get_mut() { + let mut x = Arc::new(3); + *Arc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Arc::get_mut(&mut x).is_none()); + drop(y); + assert!(Arc::get_mut(&mut x).is_some()); + let _w = Arc::downgrade(&x); + assert!(Arc::get_mut(&mut x).is_none()); +} + +#[test] +fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None); + assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); + + let a = Arc::new(0); + let w = Arc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), Some(1)); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), Some(2)); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), Some(2)); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), Some(1)); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), Some(1)); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), Some(1)); + drop(w2); +} + +#[test] +fn try_unwrap() { + let x = Arc::new(3); + assert_eq!(Arc::try_unwrap(x), Ok(3)); + let x = Arc::new(4); + let _y = x.clone(); + assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); + let x = Arc::new(5); + let _w = Arc::downgrade(&x); + assert_eq!(Arc::try_unwrap(x), Ok(5)); +} + +#[test] +fn into_from_raw() { + let x = Arc::new(box "hello"); + let y = x.clone(); + + let x_ptr = Arc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Arc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } +} + +#[test] +fn test_into_from_raw_unsized() { + use std::fmt::Display; + use std::string::ToString; + + let arc: Arc<str> = Arc::from("foo"); + + let ptr = Arc::into_raw(arc.clone()); + let arc2 = unsafe { Arc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }, "foo"); + assert_eq!(arc, arc2); + + let arc: Arc<dyn Display> = Arc::new(123); + + let ptr = Arc::into_raw(arc.clone()); + let arc2 = unsafe { Arc::from_raw(ptr) }; + + assert_eq!(unsafe { &*ptr }.to_string(), "123"); + assert_eq!(arc2.to_string(), "123"); +} + +#[test] +fn test_cowarc_clone_make_mut() { + let mut cow0 = Arc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Arc::make_mut(&mut cow0)); + assert!(75 == *Arc::make_mut(&mut cow1)); + assert!(75 == *Arc::make_mut(&mut cow2)); + + *Arc::make_mut(&mut cow0) += 1; + *Arc::make_mut(&mut cow1) += 2; + *Arc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); +} + +#[test] +fn test_cowarc_clone_unique2() { + let mut cow0 = Arc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Arc::make_mut(&mut cow0) += 1; + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); +} + +#[test] +fn test_cowarc_clone_weak() { + let mut cow0 = Arc::new(75); + let cow1_weak = Arc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Arc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); +} + +#[test] +fn test_live() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + assert!(y.upgrade().is_some()); +} + +#[test] +fn test_dead() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn weak_self_cyclic() { + struct Cycle { + x: Mutex<Option<Weak<Cycle>>>, + } + + let a = Arc::new(Cycle { x: Mutex::new(None) }); + let b = Arc::downgrade(&a.clone()); + *a.x.lock().unwrap() = Some(b); + + // hopefully we don't double-free (or leak)... +} + +#[test] +fn drop_arc() { + let mut canary = atomic::AtomicUsize::new(0); + let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + drop(x); + assert!(canary.load(Acquire) == 1); +} + +#[test] +fn drop_arc_weak() { + let mut canary = atomic::AtomicUsize::new(0); + let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let arc_weak = Arc::downgrade(&arc); + assert!(canary.load(Acquire) == 0); + drop(arc); + assert!(canary.load(Acquire) == 1); + drop(arc_weak); +} + +#[test] +fn test_strong_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + let b = w.upgrade().expect(""); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Arc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&c) == 2); +} + +#[test] +fn test_weak_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 1); + let x = w.clone(); + assert!(Arc::weak_count(&a) == 2); + drop(w); + drop(x); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Arc::strong_count(&a) == 2); + assert!(Arc::weak_count(&a) == 0); + let d = Arc::downgrade(&c); + assert!(Arc::weak_count(&c) == 1); + assert!(Arc::strong_count(&c) == 2); + + drop(a); + drop(c); + drop(d); +} + +#[test] +fn show_arc() { + let a = Arc::new(5); + assert_eq!(format!("{:?}", a), "5"); +} + +// Make sure deriving works with Arc<T> +#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] +struct Foo { + inner: Arc<i32>, +} + +#[test] +fn test_unsized() { + let x: Arc<[i32]> = Arc::new([1, 2, 3]); + assert_eq!(format!("{:?}", x), "[1, 2, 3]"); + let y = Arc::downgrade(&x.clone()); + drop(x); + assert!(y.upgrade().is_none()); +} + +#[test] +fn test_from_owned() { + let foo = 123; + let foo_arc = Arc::from(foo); + assert!(123 == *foo_arc); +} + +#[test] +fn test_new_weak() { + let foo: Weak<usize> = Weak::new(); + assert!(foo.upgrade().is_none()); +} + +#[test] +fn test_ptr_eq() { + let five = Arc::new(5); + let same_five = five.clone(); + let other_five = Arc::new(5); + + assert!(Arc::ptr_eq(&five, &same_five)); + assert!(!Arc::ptr_eq(&five, &other_five)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +#[cfg(not(miri))] // Miri does not support threads +fn test_weak_count_locked() { + let mut a = Arc::new(atomic::AtomicBool::new(false)); + let a2 = a.clone(); + let t = thread::spawn(move || { + for _i in 0..1000000 { + Arc::get_mut(&mut a); + } + a.store(true, SeqCst); + }); + + while !a2.load(SeqCst) { + let n = Arc::weak_count(&a2); + assert!(n < 2, "bad weak count: {}", n); + } + t.join().unwrap(); +} + +#[test] +fn test_from_str() { + let r: Arc<str> = Arc::from("foo"); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Arc<[X]> = Arc::from(s); + + assert_eq!(&r[..], s); +} + +#[test] +#[should_panic] +fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = &[ + Fail(0, "foo".to_string()), + Fail(1, "bar".to_string()), + Fail(2, "baz".to_string()), + ]; + + // Should panic, but not cause memory corruption + let _r: Arc<[Fail]> = Arc::from(s); +} + +#[test] +fn test_from_box() { + let b: Box<u32> = box 123; + let r: Arc<u32> = Arc::from(b); + + assert_eq!(*r, 123); +} + +#[test] +fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Arc<str> = Arc::from(s); + + assert_eq!(&r[..], "foo"); +} + +#[test] +fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box<dyn Display> = box 123; + let r: Arc<dyn Display> = Arc::from(b); + + assert_eq!(r.to_string(), "123"); +} + +#[test] +fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box<dyn Debug> = box (); + let r: Arc<dyn Debug> = Arc::from(b); + + assert_eq!(format!("{:?}", r), "()"); +} + +#[test] +fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); +} + +#[test] +fn test_downcast() { + use std::any::Any; + + let r1: Arc<dyn Any + Send + Sync> = Arc::new(i32::max_value()); + let r2: Arc<dyn Any + Send + Sync> = Arc::new("abc"); + + assert!(r1.clone().downcast::<u32>().is_err()); + + let r1i32 = r1.downcast::<i32>(); + assert!(r1i32.is_ok()); + assert_eq!(r1i32.unwrap(), Arc::new(i32::max_value())); + + assert!(r2.clone().downcast::<i32>().is_err()); + + let r2str = r2.downcast::<&'static str>(); + assert!(r2str.is_ok()); + assert_eq!(r2str.unwrap(), Arc::new("abc")); +} + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + let a: Result<Arc<[u32; 3]>, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result<Arc<[u32; 2]>, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/tests.rs index 654eabd0703..ed46ba8a1b9 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/tests.rs @@ -1,6 +1,7 @@ //! Test for `boxed` mod. use core::any::Any; +use core::convert::TryInto; use core::ops::Deref; use core::result::Result::{Err, Ok}; use core::clone::Clone; @@ -138,3 +139,15 @@ fn boxed_slice_from_iter() { assert_eq!(boxed.len(), 100); assert_eq!(boxed[7], 7); } + +#[test] +fn test_array_from_slice() { + let v = vec![1, 2, 3]; + let r: Box<[u32]> = v.into_boxed_slice(); + + let a: Result<Box<[u32; 3]>, _> = r.clone().try_into(); + assert!(a.is_ok()); + + let a: Result<Box<[u32; 2]>, _> = r.clone().try_into(); + assert!(a.is_err()); +} diff --git a/src/liballoc/tests/arc.rs b/src/liballoc/tests/arc.rs index 2759b1b1cac..cf2ad2a8e60 100644 --- a/src/liballoc/tests/arc.rs +++ b/src/liballoc/tests/arc.rs @@ -2,6 +2,8 @@ use std::any::Any; use std::sync::{Arc, Weak}; use std::cell::RefCell; use std::cmp::PartialEq; +use std::iter::TrustedLen; +use std::mem; #[test] fn uninhabited() { @@ -85,3 +87,122 @@ fn eq() { assert!(!(x != x)); assert_eq!(*x.0.borrow(), 0); } + +// The test code below is identical to that in `rc.rs`. +// For better maintainability we therefore define this type alias. +type Rc<T> = Arc<T>; + +const SHARED_ITER_MAX: u16 = 100; + +fn assert_trusted_len<I: TrustedLen>(_: &I) {} + +#[test] +fn shared_from_iter_normal() { + // Exercise the base implementation for non-`TrustedLen` iterators. + { + // `Filter` is never `TrustedLen` since we don't + // know statically how many elements will be kept: + let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new); + + // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::<Vec<_>>(); + let rc = iter.collect::<Rc<[_]>>(); + assert_eq!(&*vec, &*rc); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. +} + +#[test] +fn shared_from_iter_trustedlen_normal() { + // Exercise the `TrustedLen` implementation under normal circumstances + // where `size_hint()` matches `(_, Some(exact_len))`. + { + let iter = (0..SHARED_ITER_MAX).map(Box::new); + assert_trusted_len(&iter); + + // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::<Vec<_>>(); + let rc = iter.collect::<Rc<[_]>>(); + assert_eq!(&*vec, &*rc); + assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc)); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. + + // Try a ZST to make sure it is handled well. + { + let iter = (0..SHARED_ITER_MAX).map(|_| ()); + let vec = iter.clone().collect::<Vec<_>>(); + let rc = iter.collect::<Rc<[_]>>(); + assert_eq!(&*vec, &*rc); + assert_eq!(0, mem::size_of_val(&*rc)); + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } +} + +#[test] +#[should_panic = "I've almost got 99 problems."] +fn shared_from_iter_trustedlen_panic() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. + let iter = (0..SHARED_ITER_MAX) + .map(|val| { + match val { + 98 => panic!("I've almost got 99 problems."), + _ => Box::new(val), + } + }); + assert_trusted_len(&iter); + let _ = iter.collect::<Rc<[_]>>(); + + panic!("I am unreachable."); +} + +#[test] +fn shared_from_iter_trustedlen_no_fuse() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner. + struct Iter(std::vec::IntoIter<Option<Box<u8>>>); + + unsafe impl TrustedLen for Iter {} + + impl Iterator for Iter { + fn size_hint(&self) -> (usize, Option<usize>) { + (2, Some(2)) + } + + type Item = Box<u8>; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().flatten() + } + } + + let vec = vec![ + Some(Box::new(42)), + Some(Box::new(24)), + None, + Some(Box::new(12)), + ]; + let iter = Iter(vec.into_iter()); + assert_trusted_len(&iter); + assert_eq!( + &[Box::new(42), Box::new(24)], + &*iter.collect::<Rc<[_]>>() + ); +} diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 844afe87076..266a0d055d5 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -689,7 +689,10 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_large_random_sorted() { + #[cfg(not(miri))] // Miri is too slow let mut data = rand_data(1529); + #[cfg(miri)] + let mut data = rand_data(529); // special case with maximum height. data.sort(); diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index d52814118b3..62ccb53fcea 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -10,7 +10,7 @@ fn test_clone_eq() { m.insert(1); m.insert(2); - assert!(m.clone() == m); + assert_eq!(m.clone(), m); } #[test] @@ -28,7 +28,7 @@ fn test_hash() { y.insert(2); y.insert(1); - assert!(hash(&x) == hash(&y)); + assert_eq!(hash(&x), hash(&y)); } fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) @@ -69,6 +69,11 @@ fn test_intersection() { check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]); + + if cfg!(miri) { // Miri is too slow + return; + } + let large = (0..1000).collect::<Vec<_>>(); check_intersection(&[], &large, &[]); check_intersection(&large, &[], &[]); @@ -98,6 +103,11 @@ fn test_difference() { check_difference(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 14, 23, 34, 38, 39, 50], &[11, 22, 33, 40, 42]); + + if cfg!(miri) { // Miri is too slow + return; + } + let large = (0..1000).collect::<Vec<_>>(); check_difference(&[], &large, &[]); check_difference(&[-1], &large, &[-1]); @@ -143,8 +153,8 @@ fn test_union() { #[test] // Only tests the simple function definition with respect to intersection fn test_is_disjoint() { - let one = [1].into_iter().collect::<BTreeSet<_>>(); - let two = [2].into_iter().collect::<BTreeSet<_>>(); + let one = [1].iter().collect::<BTreeSet<_>>(); + let two = [2].iter().collect::<BTreeSet<_>>(); assert!(one.is_disjoint(&two)); } @@ -166,6 +176,17 @@ fn test_is_subset() { assert_eq!(is_subset(&[1, 2], &[1]), false); assert_eq!(is_subset(&[1, 2], &[1, 2]), true); assert_eq!(is_subset(&[1, 2], &[2, 3]), false); + assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 11, 34, 22, 38, 33, 42, 39, 40]), + true); + assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 34, 38, 22, 11]), + false); + + if cfg!(miri) { // Miri is too slow + return; + } + let large = (0..1000).collect::<Vec<_>>(); assert_eq!(is_subset(&[], &large), true); assert_eq!(is_subset(&large, &[]), false); @@ -371,7 +392,10 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_large_random_sorted() { + #[cfg(not(miri))] // Miri is too slow let mut data = rand_data(1529); + #[cfg(miri)] + let mut data = rand_data(529); // special case with maximum height. data.sort(); diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs index c225ebfa96b..904b3e7e1b0 100644 --- a/src/liballoc/tests/heap.rs +++ b/src/liballoc/tests/heap.rs @@ -1,6 +1,6 @@ use std::alloc::{Global, Alloc, Layout, System}; -/// Issue #45955. +/// Issue #45955 and #62251. #[test] fn alloc_system_overaligned_request() { check_overalign_requests(System) @@ -12,21 +12,23 @@ fn std_heap_overaligned_request() { } fn check_overalign_requests<T: Alloc>(mut allocator: T) { - let size = 8; - let align = 16; // greater than size - let iterations = 100; - unsafe { - let pointers: Vec<_> = (0..iterations).map(|_| { - allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() - }).collect(); - for &ptr in &pointers { - assert_eq!((ptr.as_ptr() as usize) % align, 0, - "Got a pointer less aligned than requested") - } + for &align in &[4, 8, 16, 32] { // less than and bigger than `MIN_ALIGN` + for &size in &[align/2, align-1] { // size less than alignment + let iterations = 128; + unsafe { + let pointers: Vec<_> = (0..iterations).map(|_| { + allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() + }).collect(); + for &ptr in &pointers { + assert_eq!((ptr.as_ptr() as usize) % align, 0, + "Got a pointer less aligned than requested") + } - // Clean up - for &ptr in &pointers { - allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) + // Clean up + for &ptr in &pointers { + allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) + } + } } } } diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index b736750c576..5723a30c0f3 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -2,12 +2,13 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] +#![feature(option_flattening)] #![feature(pattern)] #![feature(repeat_generic_slice)] +#![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(vecdeque_rotate)] -#![deny(rust_2018_idioms)] +#![feature(associated_type_bounds)] use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs index 0fbfbdccd45..8a26454c389 100644 --- a/src/liballoc/tests/linked_list.rs +++ b/src/liballoc/tests/linked_list.rs @@ -40,12 +40,10 @@ fn test_basic() { assert_eq!(n.pop_front(), Some(1)); } -#[cfg(test)] fn generate_test() -> LinkedList<i32> { list_from(&[0, 1, 2, 3, 4, 5, 6]) } -#[cfg(test)] fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { v.iter().cloned().collect() } diff --git a/src/liballoc/tests/rc.rs b/src/liballoc/tests/rc.rs index 18f82e80410..7854ca0fc16 100644 --- a/src/liballoc/tests/rc.rs +++ b/src/liballoc/tests/rc.rs @@ -2,6 +2,8 @@ use std::any::Any; use std::rc::{Rc, Weak}; use std::cell::RefCell; use std::cmp::PartialEq; +use std::mem; +use std::iter::TrustedLen; #[test] fn uninhabited() { @@ -85,3 +87,118 @@ fn eq() { assert!(!(x != x)); assert_eq!(*x.0.borrow(), 0); } + +const SHARED_ITER_MAX: u16 = 100; + +fn assert_trusted_len<I: TrustedLen>(_: &I) {} + +#[test] +fn shared_from_iter_normal() { + // Exercise the base implementation for non-`TrustedLen` iterators. + { + // `Filter` is never `TrustedLen` since we don't + // know statically how many elements will be kept: + let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new); + + // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::<Vec<_>>(); + let rc = iter.collect::<Rc<[_]>>(); + assert_eq!(&*vec, &*rc); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. +} + +#[test] +fn shared_from_iter_trustedlen_normal() { + // Exercise the `TrustedLen` implementation under normal circumstances + // where `size_hint()` matches `(_, Some(exact_len))`. + { + let iter = (0..SHARED_ITER_MAX).map(Box::new); + assert_trusted_len(&iter); + + // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: + let vec = iter.clone().collect::<Vec<_>>(); + let rc = iter.collect::<Rc<[_]>>(); + assert_eq!(&*vec, &*rc); + assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc)); + + // Clone a bit and let these get dropped. + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } // Drop what hasn't been here. + + // Try a ZST to make sure it is handled well. + { + let iter = (0..SHARED_ITER_MAX).map(|_| ()); + let vec = iter.clone().collect::<Vec<_>>(); + let rc = iter.collect::<Rc<[_]>>(); + assert_eq!(&*vec, &*rc); + assert_eq!(0, mem::size_of_val(&*rc)); + { + let _rc_2 = rc.clone(); + let _rc_3 = rc.clone(); + let _rc_4 = Rc::downgrade(&_rc_3); + } + } +} + +#[test] +#[should_panic = "I've almost got 99 problems."] +fn shared_from_iter_trustedlen_panic() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. + let iter = (0..SHARED_ITER_MAX) + .map(|val| { + match val { + 98 => panic!("I've almost got 99 problems."), + _ => Box::new(val), + } + }); + assert_trusted_len(&iter); + let _ = iter.collect::<Rc<[_]>>(); + + panic!("I am unreachable."); +} + +#[test] +fn shared_from_iter_trustedlen_no_fuse() { + // Exercise the `TrustedLen` implementation when `size_hint()` matches + // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner. + struct Iter(std::vec::IntoIter<Option<Box<u8>>>); + + unsafe impl TrustedLen for Iter {} + + impl Iterator for Iter { + fn size_hint(&self) -> (usize, Option<usize>) { + (2, Some(2)) + } + + type Item = Box<u8>; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().flatten() + } + } + + let vec = vec![ + Some(Box::new(42)), + Some(Box::new(24)), + None, + Some(Box::new(12)), + ]; + let iter = Iter(vec.into_iter()); + assert_trusted_len(&iter); + assert_eq!( + &[Box::new(42), Box::new(24)], + &*iter.collect::<Rc<[_]>>() + ); +} diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index b197516403f..4332b2e90fd 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1109,6 +1109,16 @@ fn test_iterator_last() { } #[test] +fn test_chars_debug() { + let s = "ศไทย中华Việt Nam"; + let c = s.chars(); + assert_eq!( + format!("{:?}", c), + r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"# + ); +} + +#[test] fn test_bytesator() { let s = "ศไทย中华Việt Nam"; let v = [ @@ -1628,10 +1638,12 @@ mod pattern { } } - fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str, - right: Vec<SearchStep>) - where P::Searcher: ReverseSearcher<'a> - { + fn cmp_search_to_vec<'a>( + rev: bool, + pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>, + haystack: &'a str, + right: Vec<SearchStep> + ) { let mut searcher = pat.into_searcher(haystack); let mut v = vec![]; loop { diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 765210e5aa6..55edf56345b 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; use std::mem::size_of; use std::{usize, isize}; @@ -566,11 +566,11 @@ fn test_try_reserve() { } else { panic!("usize::MAX should trigger an overflow!") } } else { // Check isize::MAX + 1 is an OOM - if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } // Check usize::MAX is an OOM - if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -590,7 +590,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -629,10 +629,10 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!") } } else { - if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } - if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -651,7 +651,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 545332bcd6a..29a22aa0315 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1,10 +1,8 @@ -#![cfg(not(miri))] - use std::borrow::Cow; use std::mem::size_of; use std::{usize, isize}; use std::vec::{Drain, IntoIter}; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; struct DropCounter<'a> { count: &'a mut u32, @@ -947,6 +945,115 @@ fn drain_filter_complex() { } #[test] +#[cfg(not(miri))] // Miri does not support catching panics +fn drain_filter_consumed_panic() { + use std::rc::Rc; + use std::sync::Mutex; + + struct Check { + index: usize, + drop_counts: Rc<Mutex<Vec<usize>>>, + }; + + impl Drop for Check { + fn drop(&mut self) { + self.drop_counts.lock().unwrap()[self.index] += 1; + println!("drop: {}", self.index); + } + } + + let check_count = 10; + let drop_counts = Rc::new(Mutex::new(vec![0_usize; check_count])); + let mut data: Vec<Check> = (0..check_count) + .map(|index| Check { index, drop_counts: Rc::clone(&drop_counts) }) + .collect(); + + let _ = std::panic::catch_unwind(move || { + let filter = |c: &mut Check| { + if c.index == 2 { + panic!("panic at index: {}", c.index); + } + // Verify that if the filter could panic again on another element + // that it would not cause a double panic and all elements of the + // vec would still be dropped exactly once. + if c.index == 4 { + panic!("panic at index: {}", c.index); + } + c.index < 6 + }; + let drain = data.drain_filter(filter); + + // NOTE: The DrainFilter is explictly consumed + drain.for_each(drop); + }); + + let drop_counts = drop_counts.lock().unwrap(); + assert_eq!(check_count, drop_counts.len()); + + for (index, count) in drop_counts.iter().cloned().enumerate() { + assert_eq!(1, count, "unexpected drop count at index: {} (count: {})", index, count); + } +} + +#[test] +#[cfg(not(miri))] // Miri does not support catching panics +fn drain_filter_unconsumed_panic() { + use std::rc::Rc; + use std::sync::Mutex; + + struct Check { + index: usize, + drop_counts: Rc<Mutex<Vec<usize>>>, + }; + + impl Drop for Check { + fn drop(&mut self) { + self.drop_counts.lock().unwrap()[self.index] += 1; + println!("drop: {}", self.index); + } + } + + let check_count = 10; + let drop_counts = Rc::new(Mutex::new(vec![0_usize; check_count])); + let mut data: Vec<Check> = (0..check_count) + .map(|index| Check { index, drop_counts: Rc::clone(&drop_counts) }) + .collect(); + + let _ = std::panic::catch_unwind(move || { + let filter = |c: &mut Check| { + if c.index == 2 { + panic!("panic at index: {}", c.index); + } + // Verify that if the filter could panic again on another element + // that it would not cause a double panic and all elements of the + // vec would still be dropped exactly once. + if c.index == 4 { + panic!("panic at index: {}", c.index); + } + c.index < 6 + }; + let _drain = data.drain_filter(filter); + + // NOTE: The DrainFilter is dropped without being consumed + }); + + let drop_counts = drop_counts.lock().unwrap(); + assert_eq!(check_count, drop_counts.len()); + + for (index, count) in drop_counts.iter().cloned().enumerate() { + assert_eq!(1, count, "unexpected drop count at index: {} (count: {})", index, count); + } +} + +#[test] +fn drain_filter_unconsumed() { + let mut vec = vec![1, 2, 3, 4]; + let drain = vec.drain_filter(|&mut x| x % 2 != 0); + drop(drain); + assert_eq!(vec, [2, 4]); +} + +#[test] fn test_reserve_exact() { // This is all the same as test_reserve @@ -971,6 +1078,7 @@ fn test_reserve_exact() { } #[test] +#[cfg(not(miri))] // Miri does not support signalling OOM fn test_try_reserve() { // These are the interesting cases: @@ -1013,11 +1121,11 @@ fn test_try_reserve() { } else { panic!("usize::MAX should trigger an overflow!") } } else { // Check isize::MAX + 1 is an OOM - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } // Check usize::MAX is an OOM - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -1037,7 +1145,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -1060,7 +1168,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should fail in the mul-by-size @@ -1073,6 +1181,7 @@ fn test_try_reserve() { } #[test] +#[cfg(not(miri))] // Miri does not support signalling OOM fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. @@ -1100,10 +1209,10 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!") } } else { - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -1122,7 +1231,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { @@ -1143,7 +1252,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { @@ -1151,3 +1260,24 @@ fn test_try_reserve_exact() { } } + +#[test] +fn test_stable_push_pop() { + // Test that, if we reserved enough space, adding and removing elements does not + // invalidate references into the vector (such as `v0`). This test also + // runs in Miri, which would detect such problems. + let mut v = Vec::with_capacity(10); + v.push(13); + + // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. + let v0 = unsafe { &*(&v[0] as *const _) }; + + // Now do a bunch of things and occasionally use `v0` again to assert it is still valid. + v.push(1); + v.push(2); + v.insert(1, 1); + assert_eq!(*v0, 13); + v.remove(1); + v.pop().unwrap(); + assert_eq!(*v0, 13); +} diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index e0fe10a55f5..d49b553fc02 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; use std::collections::{VecDeque, vec_deque::Drain}; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; use std::mem::size_of; use std::{usize, isize}; @@ -44,7 +44,6 @@ fn test_simple() { assert_eq!(d[3], 4); } -#[cfg(test)] fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) { let mut deq = VecDeque::new(); assert_eq!(deq.len(), 0); @@ -1169,7 +1168,7 @@ fn test_try_reserve() { // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } } @@ -1189,7 +1188,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -1212,7 +1211,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should fail in the mul-by-size @@ -1257,7 +1256,7 @@ fn test_try_reserve_exact() { // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } } @@ -1276,7 +1275,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { @@ -1297,7 +1296,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index c0cdffe596b..d2798955c46 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -56,6 +56,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use core::array::LengthAtMost32; use core::cmp::{self, Ordering}; use core::fmt; use core::hash::{self, Hash}; @@ -69,7 +70,7 @@ use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; use crate::borrow::{ToOwned, Cow}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::boxed::Box; use crate::raw_vec::RawVec; @@ -432,7 +433,7 @@ impl<T> Vec<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn capacity(&self) -> usize { - self.buf.cap() + self.buf.capacity() } /// Reserves capacity for at least `additional` more elements to be inserted @@ -497,9 +498,9 @@ impl<T> Vec<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -515,7 +516,7 @@ impl<T> Vec<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve(self.len, additional) } @@ -537,9 +538,9 @@ impl<T> Vec<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -555,7 +556,7 @@ impl<T> Vec<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve_exact(self.len, additional) } @@ -735,6 +736,75 @@ impl<T> Vec<T> { self } + /// Returns a raw pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// # Examples + /// + /// ``` + /// let x = vec![1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: #method.as_mut_ptr + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { assume(!ptr.is_null()); } + ptr + } + + /// Returns an unsafe mutable pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec<i32> = Vec::with_capacity(size); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// *x_ptr.add(i) = i as i32; + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0,1,2,3]); + /// ``` + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { assume(!ptr.is_null()); } + ptr + } + /// Forces the length of the vector to `new_len`. /// /// This is a low-level operation that maintains none of the normal @@ -878,7 +948,7 @@ impl<T> Vec<T> { assert!(index <= len); // space for the new element - if len == self.buf.cap() { + if len == self.buf.capacity() { self.reserve(1); } @@ -1029,7 +1099,7 @@ impl<T> Vec<T> { pub fn push(&mut self, value: T) { // This will panic or abort if we would allocate > isize::MAX bytes // or if the length increment would overflow for zero-sized types. - if self.len == self.buf.cap() { + if self.len == self.buf.capacity() { self.reserve(1); } unsafe { @@ -1094,7 +1164,7 @@ impl<T> Vec<T> { let count = (*other).len(); self.reserve(count); let len = self.len(); - ptr::copy_nonoverlapping(other as *const T, self.get_unchecked_mut(len), count); + ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count); self.len += count; } @@ -1298,6 +1368,40 @@ impl<T> Vec<T> { self.truncate(new_len); } } + + /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, + /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime + /// `'a`. If the type has only static references, or none at all, then this + /// may be chosen to be `'static`. + /// + /// This function is similar to the `leak` function on `Box`. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// #![feature(vec_leak)] + /// + /// fn main() { + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = Vec::leak(x); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); + /// } + /// ``` + #[unstable(feature = "vec_leak", issue = "62195")] + #[inline] + pub fn leak<'a>(vec: Vec<T>) -> &'a mut [T] + where + T: 'a // Technically not needed, but kept to be explicit. + { + Box::leak(vec.into_boxed_slice()) + } } impl<T: Clone> Vec<T> { @@ -1706,9 +1810,7 @@ impl<T> ops::Deref for Vec<T> { fn deref(&self) -> &[T] { unsafe { - let p = self.buf.ptr(); - assume(!p.is_null()); - slice::from_raw_parts(p, self.len) + slice::from_raw_parts(self.as_ptr(), self.len) } } } @@ -1717,9 +1819,7 @@ impl<T> ops::Deref for Vec<T> { impl<T> ops::DerefMut for Vec<T> { fn deref_mut(&mut self) -> &mut [T] { unsafe { - let ptr = self.buf.ptr(); - assume(!ptr.is_null()); - slice::from_raw_parts_mut(ptr, self.len) + slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } } } @@ -1754,13 +1854,12 @@ impl<T> IntoIterator for Vec<T> { fn into_iter(mut self) -> IntoIter<T> { unsafe { let begin = self.as_mut_ptr(); - assume(!begin.is_null()); let end = if mem::size_of::<T>() == 0 { arith_offset(begin as *const i8, self.len() as isize) as *const T } else { begin.add(self.len()) as *const T }; - let cap = self.buf.cap(); + let cap = self.buf.capacity(); mem::forget(self); IntoIter { buf: NonNull::new_unchecked(begin), @@ -1954,16 +2053,14 @@ impl<T> Vec<T> { /// with the given `replace_with` iterator and yields the removed items. /// `replace_with` does not need to be the same length as `range`. /// - /// Note 1: The element range is removed even if the iterator is not - /// consumed until the end. + /// The element range is removed even if the iterator is not consumed until the end. /// - /// Note 2: It is unspecified how many elements are removed from the vector, + /// It is unspecified how many elements are removed from the vector /// if the `Splice` value is leaked. /// - /// Note 3: The input iterator `replace_with` is only consumed - /// when the `Splice` value is dropped. + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. /// - /// Note 4: This is optimal if: + /// This is optimal if: /// /// * The tail (elements in the vector after `range`) is empty, /// * or `replace_with` yields fewer elements than `range`’s length @@ -2056,6 +2153,7 @@ impl<T> Vec<T> { del: 0, old_len, pred: filter, + panic_flag: false, } } } @@ -2074,47 +2172,36 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> { } macro_rules! __impl_slice_eq1 { - ($Lhs: ty, $Rhs: ty) => { - __impl_slice_eq1! { $Lhs, $Rhs, Sized } - }; - ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> { + impl<A, B, $($vars)*> PartialEq<$rhs> for $lhs + where + A: PartialEq<B>, + $($constraints)* + { #[inline] - fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] } + fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } #[inline] - fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] } + fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } } } } -__impl_slice_eq1! { Vec<A>, Vec<B> } -__impl_slice_eq1! { Vec<A>, &'b [B] } -__impl_slice_eq1! { Vec<A>, &'b mut [B] } -__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone } -__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone } -__impl_slice_eq1! { Cow<'a, [A]>, Vec<B>, Clone } +__impl_slice_eq1! { [] Vec<A>, Vec<B>, } +__impl_slice_eq1! { [] Vec<A>, &[B], } +__impl_slice_eq1! { [] Vec<A>, &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<B>, A: Clone } +__impl_slice_eq1! { [const N: usize] Vec<A>, [B; N], [B; N]: LengthAtMost32 } +__impl_slice_eq1! { [const N: usize] Vec<A>, &[B; N], [B; N]: LengthAtMost32 } -macro_rules! array_impls { - ($($N: expr)+) => { - $( - // NOTE: some less important impls are omitted to reduce code bloat - __impl_slice_eq1! { Vec<A>, [B; $N] } - __impl_slice_eq1! { Vec<A>, &'b [B; $N] } - // __impl_slice_eq1! { Vec<A>, &'b mut [B; $N] } - // __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone } - // __impl_slice_eq1! { Cow<'a, [A]>, &'b [B; $N], Clone } - // __impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B; $N], Clone } - )+ - } -} - -array_impls! { - 0 1 2 3 4 5 6 7 8 9 - 10 11 12 13 14 15 16 17 18 19 - 20 21 22 23 24 25 26 27 28 29 - 30 31 32 -} +// NOTE: some less important impls are omitted to reduce code bloat +// FIXME(Centril): Reconsider this? +//__impl_slice_eq1! { [const N: usize] Vec<A>, &mut [B; N], [B; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], [B; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], [B; N]: LengthAtMost32 } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], [B; N]: LengthAtMost32 } /// Implements comparison of vectors, lexicographically. #[stable(feature = "rust1", since = "1.0.0")] @@ -2395,11 +2482,6 @@ impl<T> Iterator for IntoIter<T> { fn count(self) -> usize { self.len() } - - #[inline] - fn last(mut self) -> Option<T> { - self.next_back() - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2519,11 +2601,6 @@ impl<T> Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } - - #[inline] - fn last(mut self) -> Option<T> { - self.next_back() - } } #[stable(feature = "drain", since = "1.6.0")] @@ -2593,10 +2670,6 @@ impl<I: Iterator> Iterator for Splice<'_, I> { fn size_hint(&self) -> (usize, Option<usize>) { self.drain.size_hint() } - - fn last(mut self) -> Option<Self::Item> { - self.next_back() - } } #[stable(feature = "vec_splice", since = "1.21.0")] @@ -2697,10 +2770,20 @@ pub struct DrainFilter<'a, T, F> where F: FnMut(&mut T) -> bool, { vec: &'a mut Vec<T>, + /// 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. del: usize, + /// The original length of `vec` prior to draining. old_len: usize, + /// The filter test predicate. pred: F, + /// A flag that indicates a panic has occured in the filter test prodicate. + /// This is used as a hint in the drop implmentation to prevent consumption + /// of the remainder of the `DrainFilter`. Any unprocessed items will be + /// backshifted in the `vec`, but no further items will be dropped or + /// tested by the filter predicate. + panic_flag: bool, } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] @@ -2711,20 +2794,23 @@ impl<T, F> Iterator for DrainFilter<'_, T, F> fn next(&mut self) -> Option<T> { unsafe { - while self.idx != self.old_len { + while self.idx < self.old_len { let i = self.idx; - self.idx += 1; let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - if (self.pred)(&mut v[i]) { + self.panic_flag = true; + let drained = (self.pred)(&mut v[i]); + self.panic_flag = false; + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.idx += 1; + if drained { self.del += 1; return Some(ptr::read(&v[i])); } else if self.del > 0 { let del = self.del; let src: *const T = &v[i]; let dst: *mut T = &mut v[i - del]; - // This is safe because self.vec has length 0 - // thus its elements will not have Drop::drop - // called on them in the event of a panic. ptr::copy_nonoverlapping(src, dst, 1); } } @@ -2742,9 +2828,46 @@ impl<T, F> Drop for DrainFilter<'_, T, F> where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - self.for_each(drop); - unsafe { - self.vec.set_len(self.old_len - self.del); + struct BackshiftOnDrop<'a, 'b, T, F> + where + F: FnMut(&mut T) -> bool, + { + drain: &'b mut DrainFilter<'a, T, F>, + } + + impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F> + where + F: FnMut(&mut T) -> bool + { + fn drop(&mut self) { + unsafe { + if self.drain.idx < self.drain.old_len && self.drain.del > 0 { + // This is a pretty messed up state, and there isn't really an + // obviously right thing to do. We don't want to keep trying + // to execute `pred`, so we just backshift all the unprocessed + // elements and tell the vec that they still exist. The backshift + // is required to prevent a double-drop of the last successfully + // drained item prior to a panic in the predicate. + let ptr = self.drain.vec.as_mut_ptr(); + let src = ptr.add(self.drain.idx); + let dst = src.sub(self.drain.del); + let tail_len = self.drain.old_len - self.drain.idx; + src.copy_to(dst, tail_len); + } + self.drain.vec.set_len(self.drain.old_len - self.drain.del); + } + } + } + + let backshift = BackshiftOnDrop { + drain: self + }; + + // Attempt to consume any remaining elements if the filter predicate + // has not yet panicked. We'll backshift any remaining elements + // whether we've already panicked or if the consumption here panics. + if !backshift.drain.panic_flag { + backshift.drain.for_each(drop); } } } |
