@@ -238,12 +238,13 @@ use core::cmp::Ordering;
238238use core:: fmt;
239239use core:: hash:: { Hash , Hasher } ;
240240use core:: intrinsics:: abort;
241+ use core:: iter;
241242use core:: marker:: { self , Unpin , Unsize , PhantomData } ;
242243use core:: mem:: { self , align_of, align_of_val, forget, size_of_val} ;
243244use core:: ops:: { Deref , Receiver , CoerceUnsized , DispatchFromDyn } ;
244245use core:: pin:: Pin ;
245246use core:: ptr:: { self , NonNull } ;
246- use core:: slice:: from_raw_parts_mut;
247+ use core:: slice:: { self , from_raw_parts_mut} ;
247248use core:: convert:: From ;
248249use core:: usize;
249250
@@ -698,21 +699,29 @@ impl Rc<dyn Any> {
698699}
699700
700701impl < T : ?Sized > Rc < T > {
701- // Allocates an `RcBox<T>` with sufficient space for an unsized value
702- unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut RcBox < T > {
703- // Calculate layout using the given value.
702+ // Allocates an `RcBox<T>` with sufficient space for
703+ // an unsized value where the value has the layout provided.
704+ //
705+ // The function `mem_to_rcbox` is called with the data pointer
706+ // and must return back a (potentially fat)-pointer for the `RcBox<T>`.
707+ unsafe fn allocate_for_unsized (
708+ value_layout : Layout ,
709+ mem_to_rcbox : impl FnOnce ( * mut u8 ) -> * mut RcBox < T >
710+ ) -> * mut RcBox < T > {
711+ // Calculate layout using the given value layout.
704712 // Previously, layout was calculated on the expression
705713 // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
706714 // reference (see #54908).
707715 let layout = Layout :: new :: < RcBox < ( ) > > ( )
708- . extend ( Layout :: for_value ( & * ptr ) ) . unwrap ( ) . 0
716+ . extend ( value_layout ) . unwrap ( ) . 0
709717 . pad_to_align ( ) . unwrap ( ) ;
710718
719+ // Allocate for the layout.
711720 let mem = Global . alloc ( layout)
712721 . unwrap_or_else ( |_| handle_alloc_error ( layout) ) ;
713722
714723 // Initialize the RcBox
715- let inner = set_data_ptr ( ptr as * mut T , mem. as_ptr ( ) as * mut u8 ) as * mut RcBox < T > ;
724+ let inner = mem_to_rcbox ( mem. as_ptr ( ) ) ;
716725 debug_assert_eq ! ( Layout :: for_value( & * inner) , layout) ;
717726
718727 ptr:: write ( & mut ( * inner) . strong , Cell :: new ( 1 ) ) ;
@@ -721,6 +730,15 @@ impl<T: ?Sized> Rc<T> {
721730 inner
722731 }
723732
733+ // Allocates an `RcBox<T>` with sufficient space for an unsized value
734+ unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut RcBox < T > {
735+ // Allocate for the `RcBox<T>` using the given value.
736+ Self :: allocate_for_unsized (
737+ Layout :: for_value ( & * ptr) ,
738+ |mem| set_data_ptr ( ptr as * mut T , mem) as * mut RcBox < T > ,
739+ )
740+ }
741+
724742 fn from_box ( v : Box < T > ) -> Rc < T > {
725743 unsafe {
726744 let box_unique = Box :: into_unique ( v) ;
@@ -743,6 +761,32 @@ impl<T: ?Sized> Rc<T> {
743761 }
744762}
745763
764+ impl < T > Rc < [ T ] > {
765+ // Allocates an `RcBox<[T]>` with the given length.
766+ unsafe fn allocate_for_slice ( len : usize ) -> * mut RcBox < [ T ] > {
767+ // FIXME(#60667): Deduplicate.
768+ fn slice_from_raw_parts_mut < T > ( data : * mut T , len : usize ) -> * mut [ T ] {
769+ #[ repr( C ) ]
770+ union Repr < T > {
771+ rust_mut : * mut [ T ] ,
772+ raw : FatPtr < T > ,
773+ }
774+
775+ #[ repr( C ) ]
776+ struct FatPtr < T > {
777+ data : * const T ,
778+ len : usize ,
779+ }
780+ unsafe { Repr { raw : FatPtr { data, len } } . rust_mut }
781+ }
782+
783+ Self :: allocate_for_unsized (
784+ Layout :: array :: < T > ( len) . unwrap ( ) ,
785+ |mem| slice_from_raw_parts_mut ( mem as * mut T , len) as * mut RcBox < [ T ] > ,
786+ )
787+ }
788+ }
789+
746790// Sets the data pointer of a `?Sized` raw pointer.
747791//
748792// For a slice/trait object, this sets the `data` field and leaves the rest
@@ -757,8 +801,7 @@ impl<T> Rc<[T]> {
757801 //
758802 // Unsafe because the caller must either take ownership or bind `T: Copy`
759803 unsafe fn copy_from_slice ( v : & [ T ] ) -> Rc < [ T ] > {
760- let v_ptr = v as * const [ T ] ;
761- let ptr = Self :: allocate_for_ptr ( v_ptr) ;
804+ let ptr = Self :: allocate_for_slice ( v. len ( ) ) ;
762805
763806 ptr:: copy_nonoverlapping (
764807 v. as_ptr ( ) ,
@@ -767,15 +810,11 @@ impl<T> Rc<[T]> {
767810
768811 Self :: from_ptr ( ptr)
769812 }
770- }
771813
772- trait RcFromSlice < T > {
773- fn from_slice ( slice : & [ T ] ) -> Self ;
774- }
775-
776- impl < T : Clone > RcFromSlice < T > for Rc < [ T ] > {
777- #[ inline]
778- default fn from_slice ( v : & [ T ] ) -> Self {
814+ /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size.
815+ ///
816+ /// Behavior is undefined should the size be wrong.
817+ unsafe fn from_iter_exact ( iter : impl iter:: Iterator < Item = T > , len : usize ) -> Rc < [ T ] > {
779818 // Panic guard while cloning T elements.
780819 // In the event of a panic, elements that have been written
781820 // into the new RcBox will be dropped, then the memory freed.
@@ -797,32 +836,42 @@ impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
797836 }
798837 }
799838
800- unsafe {
801- let v_ptr = v as * const [ T ] ;
802- let ptr = Self :: allocate_for_ptr ( v_ptr) ;
839+ let ptr = Self :: allocate_for_slice ( len) ;
803840
804- let mem = ptr as * mut _ as * mut u8 ;
805- let layout = Layout :: for_value ( & * ptr) ;
841+ let mem = ptr as * mut _ as * mut u8 ;
842+ let layout = Layout :: for_value ( & * ptr) ;
806843
807- // Pointer to first element
808- let elems = & mut ( * ptr) . value as * mut [ T ] as * mut T ;
844+ // Pointer to first element
845+ let elems = & mut ( * ptr) . value as * mut [ T ] as * mut T ;
809846
810- let mut guard = Guard {
811- mem : NonNull :: new_unchecked ( mem) ,
812- elems : elems,
813- layout : layout,
814- n_elems : 0 ,
815- } ;
847+ let mut guard = Guard {
848+ mem : NonNull :: new_unchecked ( mem) ,
849+ elems,
850+ layout,
851+ n_elems : 0 ,
852+ } ;
816853
817- for ( i, item) in v . iter ( ) . enumerate ( ) {
818- ptr:: write ( elems. add ( i) , item. clone ( ) ) ;
819- guard. n_elems += 1 ;
820- }
854+ for ( i, item) in iter. enumerate ( ) {
855+ ptr:: write ( elems. add ( i) , item) ;
856+ guard. n_elems += 1 ;
857+ }
821858
822- // All clear. Forget the guard so it doesn't free the new RcBox.
823- forget ( guard) ;
859+ // All clear. Forget the guard so it doesn't free the new RcBox.
860+ forget ( guard) ;
824861
825- Self :: from_ptr ( ptr)
862+ Self :: from_ptr ( ptr)
863+ }
864+ }
865+
866+ trait RcFromSlice < T > {
867+ fn from_slice ( slice : & [ T ] ) -> Self ;
868+ }
869+
870+ impl < T : Clone > RcFromSlice < T > for Rc < [ T ] > {
871+ #[ inline]
872+ default fn from_slice ( v : & [ T ] ) -> Self {
873+ unsafe {
874+ Self :: from_iter_exact ( v. iter ( ) . cloned ( ) , v. len ( ) )
826875 }
827876 }
828877}
@@ -1221,9 +1270,88 @@ impl<T> From<Vec<T>> for Rc<[T]> {
12211270}
12221271
12231272#[ stable( feature = "shared_from_iter" , since = "1.37.0" ) ]
1224- impl < T > core:: iter:: FromIterator < T > for Rc < [ T ] > {
1225- fn from_iter < I : IntoIterator < Item = T > > ( iter : I ) -> Self {
1226- iter. into_iter ( ) . collect :: < Vec < T > > ( ) . into ( )
1273+ impl < T > iter:: FromIterator < T > for Rc < [ T ] > {
1274+ /// Takes each element in the `Iterator` and collects it into an `Rc<[T]>`.
1275+ ///
1276+ /// # Performance characteristics
1277+ ///
1278+ /// ## The general case
1279+ ///
1280+ /// In the general case, collecting into `Rc<[T]>` is done by first
1281+ /// collecting into a `Vec<T>`. That is, when writing the following:
1282+ ///
1283+ /// ```rust
1284+ /// # use std::rc::Rc;
1285+ /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect();
1286+ /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]);
1287+ /// ```
1288+ ///
1289+ /// this behaves as if we wrote:
1290+ ///
1291+ /// ```rust
1292+ /// # use std::rc::Rc;
1293+ /// let evens: Rc<[u8]> = (0..10).filter(|&x| x % 2 == 0)
1294+ /// .collect::<Vec<_>>() // The first set of allocations happens here.
1295+ /// .into(); // A second allocation for `Rc<[T]>` happens here.
1296+ /// # assert_eq!(&*evens, &[0, 2, 4, 6, 8]);
1297+ /// ```
1298+ ///
1299+ /// This will allocate as many times as needed for constructing the `Vec<T>`
1300+ /// and then it will allocate once for turning the `Vec<T>` into the `Rc<[T]>`.
1301+ ///
1302+ /// ## Iterators of known length
1303+ ///
1304+ /// When your `Iterator` implements `TrustedLen` and is of an exact size,
1305+ /// a single allocation will be made for the `Rc<[T]>`. For example:
1306+ ///
1307+ /// ```rust
1308+ /// # use std::rc::Rc;
1309+ /// let evens: Rc<[u8]> = (0..10).collect(); // Just a single allocation happens here.
1310+ /// # assert_eq!(&*evens, &*(0..10).collect::<Vec<_>>());
1311+ /// ```
1312+ fn from_iter < I : iter:: IntoIterator < Item = T > > ( iter : I ) -> Self {
1313+ RcFromIter :: from_iter ( iter. into_iter ( ) )
1314+ }
1315+ }
1316+
1317+ /// Specialization trait used for collecting into `Rc<[T]>`.
1318+ trait RcFromIter < T , I > {
1319+ fn from_iter ( iter : I ) -> Self ;
1320+ }
1321+
1322+ impl < T , I : Iterator < Item = T > > RcFromIter < T , I > for Rc < [ T ] > {
1323+ default fn from_iter ( iter : I ) -> Self {
1324+ iter. collect :: < Vec < T > > ( ) . into ( )
1325+ }
1326+ }
1327+
1328+ impl < T , I : iter:: TrustedLen < Item = T > > RcFromIter < T , I > for Rc < [ T ] > {
1329+ default fn from_iter ( iter : I ) -> Self {
1330+ // This is the case for a `TrustedLen` iterator.
1331+ let ( low, high) = iter. size_hint ( ) ;
1332+ if let Some ( high) = high {
1333+ debug_assert_eq ! (
1334+ low, high,
1335+ "TrustedLen iterator's size hint is not exact: {:?}" ,
1336+ ( low, high)
1337+ ) ;
1338+
1339+ unsafe {
1340+ // SAFETY: We need to ensure that the iterator has an exact length and we have.
1341+ Rc :: from_iter_exact ( iter, low)
1342+ }
1343+ } else {
1344+ // Fall back to normal implementation.
1345+ iter. collect :: < Vec < T > > ( ) . into ( )
1346+ }
1347+ }
1348+ }
1349+
1350+ impl < ' a , T : ' a + Clone > RcFromIter < & ' a T , slice:: Iter < ' a , T > > for Rc < [ T ] > {
1351+ fn from_iter ( iter : slice:: Iter < ' a , T > ) -> Self {
1352+ // Delegate to `impl<T: Clone> From<&[T]> for Rc<[T]>`
1353+ // which will use `ptr::copy_nonoverlapping`.
1354+ iter. as_slice ( ) . into ( )
12271355 }
12281356}
12291357
0 commit comments