@@ -12,6 +12,7 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
1212use core:: borrow;
1313use core:: fmt;
1414use core:: cmp:: { self , Ordering } ;
15+ use core:: iter;
1516use core:: intrinsics:: abort;
1617use core:: mem:: { self , align_of, align_of_val, size_of_val} ;
1718use core:: ops:: { Deref , Receiver , CoerceUnsized , DispatchFromDyn } ;
@@ -21,7 +22,7 @@ use core::marker::{Unpin, Unsize, PhantomData};
2122use core:: hash:: { Hash , Hasher } ;
2223use core:: { isize, usize} ;
2324use core:: convert:: From ;
24- use core:: slice:: from_raw_parts_mut;
25+ use core:: slice:: { self , from_raw_parts_mut} ;
2526
2627use crate :: alloc:: { Global , Alloc , Layout , box_free, handle_alloc_error} ;
2728use crate :: boxed:: Box ;
@@ -587,21 +588,28 @@ impl<T: ?Sized> Arc<T> {
587588}
588589
589590impl < T : ?Sized > Arc < T > {
590- // Allocates an `ArcInner<T>` with sufficient space for an unsized value
591- unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut ArcInner < T > {
592- // Calculate layout using the given value.
591+ // Allocates an `ArcInner<T>` with sufficient space for
592+ // an unsized value where the value has the layout provided.
593+ //
594+ // The function `mem_to_arcinner` is called with the data pointer
595+ // and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
596+ unsafe fn allocate_for_unsized (
597+ value_layout : Layout ,
598+ mem_to_arcinner : impl FnOnce ( * mut u8 ) -> * mut ArcInner < T >
599+ ) -> * mut ArcInner < T > {
600+ // Calculate layout using the given value layout.
593601 // Previously, layout was calculated on the expression
594602 // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
595603 // reference (see #54908).
596604 let layout = Layout :: new :: < ArcInner < ( ) > > ( )
597- . extend ( Layout :: for_value ( & * ptr ) ) . unwrap ( ) . 0
605+ . extend ( value_layout ) . unwrap ( ) . 0
598606 . pad_to_align ( ) . unwrap ( ) ;
599607
600608 let mem = Global . alloc ( layout)
601609 . unwrap_or_else ( |_| handle_alloc_error ( layout) ) ;
602610
603611 // Initialize the ArcInner
604- let inner = set_data_ptr ( ptr as * mut T , mem. as_ptr ( ) as * mut u8 ) as * mut ArcInner < T > ;
612+ let inner = mem_to_arcinner ( mem. as_ptr ( ) ) ;
605613 debug_assert_eq ! ( Layout :: for_value( & * inner) , layout) ;
606614
607615 ptr:: write ( & mut ( * inner) . strong , atomic:: AtomicUsize :: new ( 1 ) ) ;
@@ -610,6 +618,15 @@ impl<T: ?Sized> Arc<T> {
610618 inner
611619 }
612620
621+ // Allocates an `ArcInner<T>` with sufficient space for an unsized value
622+ unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut ArcInner < T > {
623+ // Allocate for the `ArcInner<T>` using the given value.
624+ Self :: allocate_for_unsized (
625+ Layout :: for_value ( & * ptr) ,
626+ |mem| set_data_ptr ( ptr as * mut T , mem) as * mut ArcInner < T > ,
627+ )
628+ }
629+
613630 fn from_box ( v : Box < T > ) -> Arc < T > {
614631 unsafe {
615632 let box_unique = Box :: into_unique ( v) ;
@@ -632,6 +649,32 @@ impl<T: ?Sized> Arc<T> {
632649 }
633650}
634651
652+ impl < T > Arc < [ T ] > {
653+ // Allocates an `ArcInner<[T]>` with the given length.
654+ unsafe fn allocate_for_slice ( len : usize ) -> * mut ArcInner < [ T ] > {
655+ // FIXME(#60667): Deduplicate.
656+ fn slice_from_raw_parts_mut < T > ( data : * mut T , len : usize ) -> * mut [ T ] {
657+ #[ repr( C ) ]
658+ union Repr < T > {
659+ rust_mut : * mut [ T ] ,
660+ raw : FatPtr < T > ,
661+ }
662+
663+ #[ repr( C ) ]
664+ struct FatPtr < T > {
665+ data : * const T ,
666+ len : usize ,
667+ }
668+ unsafe { Repr { raw : FatPtr { data, len } } . rust_mut }
669+ }
670+
671+ Self :: allocate_for_unsized (
672+ Layout :: array :: < T > ( len) . unwrap ( ) ,
673+ |mem| slice_from_raw_parts_mut ( mem as * mut T , len) as * mut ArcInner < [ T ] > ,
674+ )
675+ }
676+ }
677+
635678// Sets the data pointer of a `?Sized` raw pointer.
636679//
637680// For a slice/trait object, this sets the `data` field and leaves the rest
@@ -646,8 +689,7 @@ impl<T> Arc<[T]> {
646689 //
647690 // Unsafe because the caller must either take ownership or bind `T: Copy`
648691 unsafe fn copy_from_slice ( v : & [ T ] ) -> Arc < [ T ] > {
649- let v_ptr = v as * const [ T ] ;
650- let ptr = Self :: allocate_for_ptr ( v_ptr) ;
692+ let ptr = Self :: allocate_for_slice ( v. len ( ) ) ;
651693
652694 ptr:: copy_nonoverlapping (
653695 v. as_ptr ( ) ,
@@ -656,16 +698,11 @@ impl<T> Arc<[T]> {
656698
657699 Self :: from_ptr ( ptr)
658700 }
659- }
660701
661- // Specialization trait used for From<&[T]>
662- trait ArcFromSlice < T > {
663- fn from_slice ( slice : & [ T ] ) -> Self ;
664- }
665-
666- impl < T : Clone > ArcFromSlice < T > for Arc < [ T ] > {
667- #[ inline]
668- default fn from_slice ( v : & [ T ] ) -> Self {
702+ /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size.
703+ ///
704+ /// Behavior is undefined should the size be wrong.
705+ unsafe fn from_iter_exact ( iter : impl iter:: Iterator < Item = T > , len : usize ) -> Arc < [ T ] > {
669706 // Panic guard while cloning T elements.
670707 // In the event of a panic, elements that have been written
671708 // into the new ArcInner will be dropped, then the memory freed.
@@ -687,32 +724,43 @@ impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
687724 }
688725 }
689726
690- unsafe {
691- let v_ptr = v as * const [ T ] ;
692- let ptr = Self :: allocate_for_ptr ( v_ptr) ;
727+ let ptr = Self :: allocate_for_slice ( len) ;
728+
729+ let mem = ptr as * mut _ as * mut u8 ;
730+ let layout = Layout :: for_value ( & * ptr) ;
693731
694- let mem = ptr as * mut _ as * mut u8 ;
695- let layout = Layout :: for_value ( & * ptr) ;
732+ // Pointer to first element
733+ let elems = & mut ( * ptr) . data as * mut [ T ] as * mut T ;
696734
697- // Pointer to first element
698- let elems = & mut ( * ptr) . data as * mut [ T ] as * mut T ;
735+ let mut guard = Guard {
736+ mem : NonNull :: new_unchecked ( mem) ,
737+ elems,
738+ layout,
739+ n_elems : 0 ,
740+ } ;
699741
700- let mut guard = Guard {
701- mem : NonNull :: new_unchecked ( mem) ,
702- elems : elems,
703- layout : layout,
704- n_elems : 0 ,
705- } ;
742+ for ( i, item) in iter. enumerate ( ) {
743+ ptr:: write ( elems. add ( i) , item) ;
744+ guard. n_elems += 1 ;
745+ }
706746
707- for ( i, item) in v. iter ( ) . enumerate ( ) {
708- ptr:: write ( elems. add ( i) , item. clone ( ) ) ;
709- guard. n_elems += 1 ;
710- }
747+ // All clear. Forget the guard so it doesn't free the new ArcInner.
748+ mem:: forget ( guard) ;
711749
712- // All clear. Forget the guard so it doesn't free the new ArcInner.
713- mem:: forget ( guard) ;
750+ Self :: from_ptr ( ptr)
751+ }
752+ }
714753
715- Self :: from_ptr ( ptr)
754+ // Specialization trait used for From<&[T]>
755+ trait ArcFromSlice < T > {
756+ fn from_slice ( slice : & [ T ] ) -> Self ;
757+ }
758+
759+ impl < T : Clone > ArcFromSlice < T > for Arc < [ T ] > {
760+ #[ inline]
761+ default fn from_slice ( v : & [ T ] ) -> Self {
762+ unsafe {
763+ Self :: from_iter_exact ( v. iter ( ) . cloned ( ) , v. len ( ) )
716764 }
717765 }
718766}
@@ -1792,9 +1840,88 @@ impl<T> From<Vec<T>> for Arc<[T]> {
17921840}
17931841
17941842#[ stable( feature = "shared_from_iter" , since = "1.37.0" ) ]
1795- impl < T > core:: iter:: FromIterator < T > for Arc < [ T ] > {
1796- fn from_iter < I : IntoIterator < Item = T > > ( iter : I ) -> Self {
1797- iter. into_iter ( ) . collect :: < Vec < T > > ( ) . into ( )
1843+ impl < T > iter:: FromIterator < T > for Arc < [ T ] > {
1844+ /// Takes each element in the `Iterator` and collects it into an `Arc<[T]>`.
1845+ ///
1846+ /// # Performance characteristics
1847+ ///
1848+ /// ## The general case
1849+ ///
1850+ /// In the general case, collecting into `Arc<[T]>` is done by first
1851+ /// collecting into a `Vec<T>`. That is, when writing the following:
1852+ ///
1853+ /// ```rust
1854+ /// # use std::sync::Arc;
1855+ /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect();
1856+ /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]);
1857+ /// ```
1858+ ///
1859+ /// this behaves as if we wrote:
1860+ ///
1861+ /// ```rust
1862+ /// # use std::sync::Arc;
1863+ /// let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0)
1864+ /// .collect::<Vec<_>>() // The first set of allocations happens here.
1865+ /// .into(); // A second allocation for `Arc<[T]>` happens here.
1866+ /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]);
1867+ /// ```
1868+ ///
1869+ /// This will allocate as many times as needed for constructing the `Vec<T>`
1870+ /// and then it will allocate once for turning the `Vec<T>` into the `Arc<[T]>`.
1871+ ///
1872+ /// ## Iterators of known length
1873+ ///
1874+ /// When your `Iterator` implements `TrustedLen` and is of an exact size,
1875+ /// a single allocation will be made for the `Arc<[T]>`. For example:
1876+ ///
1877+ /// ```rust
1878+ /// # use std::sync::Arc;
1879+ /// let evens: Arc<[u8]> = (0..10).collect(); // Just a single allocation happens here.
1880+ /// # assert_eq!(&*evens, &*(0..10).collect::<Vec<_>>());
1881+ /// ```
1882+ fn from_iter < I : iter:: IntoIterator < Item = T > > ( iter : I ) -> Self {
1883+ ArcFromIter :: from_iter ( iter. into_iter ( ) )
1884+ }
1885+ }
1886+
1887+ /// Specialization trait used for collecting into `Arc<[T]>`.
1888+ trait ArcFromIter < T , I > {
1889+ fn from_iter ( iter : I ) -> Self ;
1890+ }
1891+
1892+ impl < T , I : Iterator < Item = T > > ArcFromIter < T , I > for Arc < [ T ] > {
1893+ default fn from_iter ( iter : I ) -> Self {
1894+ iter. collect :: < Vec < T > > ( ) . into ( )
1895+ }
1896+ }
1897+
1898+ impl < T , I : iter:: TrustedLen < Item = T > > ArcFromIter < T , I > for Arc < [ T ] > {
1899+ default fn from_iter ( iter : I ) -> Self {
1900+ // This is the case for a `TrustedLen` iterator.
1901+ let ( low, high) = iter. size_hint ( ) ;
1902+ if let Some ( high) = high {
1903+ debug_assert_eq ! (
1904+ low, high,
1905+ "TrustedLen iterator's size hint is not exact: {:?}" ,
1906+ ( low, high)
1907+ ) ;
1908+
1909+ unsafe {
1910+ // SAFETY: We need to ensure that the iterator has an exact length and we have.
1911+ Arc :: from_iter_exact ( iter, low)
1912+ }
1913+ } else {
1914+ // Fall back to normal implementation.
1915+ iter. collect :: < Vec < T > > ( ) . into ( )
1916+ }
1917+ }
1918+ }
1919+
1920+ impl < ' a , T : ' a + Clone > ArcFromIter < & ' a T , slice:: Iter < ' a , T > > for Arc < [ T ] > {
1921+ fn from_iter ( iter : slice:: Iter < ' a , T > ) -> Self {
1922+ // Delegate to `impl<T: Clone> From<&[T]> for Arc<[T]>`
1923+ // which will use `ptr::copy_nonoverlapping`.
1924+ iter. as_slice ( ) . into ( )
17981925 }
17991926}
18001927
0 commit comments