}
}
- /// Create an `Arc<[T]>` by reusing the underlying memory
- /// of a `Vec<T>`. 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<T>) -> Result<Arc<[T]>, Vec<T>> {
- let layout_elements = Layout::array::<T>(v.len()).unwrap();
- let layout_allocation = Layout::array::<T>(v.capacity()).unwrap();
- let layout_arcinner = arcinner_layout_for_value_layout(layout_elements);
- let mut ptr = NonNull::new(v.as_mut_ptr()).expect("`Vec<T>` stores `NonNull<T>`");
- 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::<T>(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::<T>(), &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.
///
/// # 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
///
/// }
/// 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<str> = 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 {
/// assert_eq!(&[1, 2, 3], &shared[..]);
/// ```
#[inline]
- fn from(v: Vec<T>) -> 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<T>) -> 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
}
}
}