X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=library%2Falloc%2Fsrc%2Fsync.rs;h=f7dc4d1094ca3f8b1a0d160435ba6aa2653fa828;hb=8c6bf2bee7914fd94f8ae5ec96234e8a2ce51958;hp=37e07eb5998b332ffdeb54f4fe675557800e289d;hpb=e2dcc28d3c64a3f8f4797132420685e2b26fe05b;p=rust.git diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 37e07eb5998..f7dc4d1094c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1261,49 +1261,6 @@ unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { } } - /// Create an `Arc<[T]>` by reusing the underlying memory - /// of a `Vec`. This will return the vector if the existing allocation - /// is not large enough. - #[cfg(not(no_global_oom_handling))] - fn try_from_vec_in_place(mut v: Vec) -> Result, Vec> { - let layout_elements = Layout::array::(v.len()).unwrap(); - let layout_allocation = Layout::array::(v.capacity()).unwrap(); - let layout_arcinner = arcinner_layout_for_value_layout(layout_elements); - let mut ptr = NonNull::new(v.as_mut_ptr()).expect("`Vec` stores `NonNull`"); - if layout_arcinner.size() > layout_allocation.size() - || layout_arcinner.align() > layout_allocation.align() - { - // Can't fit - calling `grow` would involve `realloc` - // (which copies the elements), followed by copying again. - return Err(v); - } - if layout_arcinner.size() < layout_allocation.size() - || layout_arcinner.align() < layout_allocation.align() - { - // We need to shrink the allocation so that it fits - // https://doc.rust-lang.org/nightly/std/alloc/trait.Allocator.html#memory-fitting - // SAFETY: - // - Vec allocates by requesting `Layout::array::(capacity)`, so this capacity matches - // - `layout_arcinner` is smaller - // If this fails, the ownership has not been transferred - if let Ok(p) = unsafe { Global.shrink(ptr.cast(), layout_allocation, layout_arcinner) } - { - ptr = p.cast(); - } else { - return Err(v); - } - } - // Make sure the vec's memory isn't deallocated now - let v = mem::ManuallyDrop::new(v); - let ptr: *mut ArcInner<[T]> = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), v.len()) as _; - unsafe { - ptr::copy(ptr.cast::(), &mut (*ptr).data as *mut [T] as *mut T, v.len()); - ptr::write(&mut (*ptr).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*ptr).weak, atomic::AtomicUsize::new(1)); - Ok(Self::from_ptr(ptr)) - } - } - /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. /// /// Behavior is undefined should the size be wrong. @@ -1630,10 +1587,11 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> { /// /// # Safety /// - /// Any other `Arc` or [`Weak`] pointers to the same allocation 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`. + /// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then + /// they must be must not be dereferenced or have active borrows for the duration + /// of the returned borrow, and their inner type must be exactly the same as the + /// inner type of this Rc (including lifetimes). This is trivially the case if no + /// such pointers exist, for example immediately after `Arc::new`. /// /// # Examples /// @@ -1648,6 +1606,38 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> { /// } /// assert_eq!(*x, "foo"); /// ``` + /// Other `Arc` pointers to the same allocation must be to the same type. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc = Arc::from("Hello, world!"); + /// let mut y: Arc<[u8]> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type is str, not [u8] + /// Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8 + /// } + /// println!("{}", &*x); // Invalid UTF-8 in a str + /// ``` + /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes. + /// ```no_run + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let x: Arc<&str> = Arc::new("Hello, world!"); + /// { + /// let s = String::from("Oh, no!"); + /// let mut y: Arc<&str> = x.clone().into(); + /// unsafe { + /// // this is Undefined Behavior, because x's inner type + /// // is &'long str, not &'short str + /// *Arc::get_mut_unchecked(&mut y) = &s; + /// } + /// } + /// println!("{}", &*x); // Use-after-free + /// ``` #[inline] #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { @@ -2615,17 +2605,12 @@ impl From> for Arc<[T]> { /// assert_eq!(&[1, 2, 3], &shared[..]); /// ``` #[inline] - fn from(v: Vec) -> Arc<[T]> { - match Arc::try_from_vec_in_place(v) { - Ok(rc) => rc, - Err(mut v) => { - unsafe { - let rc = Arc::copy_from_slice(&v); - // Allow the Vec to free its memory, but not destroy its contents - v.set_len(0); - rc - } - } + fn from(mut v: Vec) -> Arc<[T]> { + unsafe { + let rc = Arc::copy_from_slice(&v); + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + rc } } }