@@ -60,7 +60,7 @@ use core::fmt;
6060use core:: hash:: { Hash , Hasher } ;
6161use core:: intrinsics:: { arith_offset, assume} ;
6262use core:: iter:: {
63- FromIterator , InPlaceIterable , SourceIter , TrustedLen ,
63+ FromIterator , TrustedLen ,
6464} ;
6565use core:: marker:: PhantomData ;
6666use core:: mem:: { self , ManuallyDrop , MaybeUninit } ;
@@ -101,6 +101,8 @@ use self::is_zero::IsZero;
101101
102102mod is_zero;
103103
104+ mod source_iter_marker;
105+
104106/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
105107///
106108/// # Examples
@@ -2356,109 +2358,6 @@ impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
23562358 }
23572359}
23582360
2359- fn write_in_place_with_drop < T > (
2360- src_end : * const T ,
2361- ) -> impl FnMut ( InPlaceDrop < T > , T ) -> Result < InPlaceDrop < T > , !> {
2362- move |mut sink, item| {
2363- unsafe {
2364- // the InPlaceIterable contract cannot be verified precisely here since
2365- // try_fold has an exclusive reference to the source pointer
2366- // all we can do is check if it's still in range
2367- debug_assert ! ( sink. dst as * const _ <= src_end, "InPlaceIterable contract violation" ) ;
2368- ptr:: write ( sink. dst , item) ;
2369- sink. dst = sink. dst . add ( 1 ) ;
2370- }
2371- Ok ( sink)
2372- }
2373- }
2374-
2375- /// Specialization marker for collecting an iterator pipeline into a Vec while reusing the
2376- /// source allocation, i.e. executing the pipeline in place.
2377- ///
2378- /// The SourceIter parent trait is necessary for the specializing function to access the allocation
2379- /// which is to be reused. But it is not sufficient for the specialization to be valid. See
2380- /// additional bounds on the impl.
2381- #[ rustc_unsafe_specialization_marker]
2382- trait SourceIterMarker : SourceIter < Source : AsIntoIter > { }
2383-
2384- // The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of
2385- // Adapter<Adapter<Adapter<IntoIter>>> (all owned by core/std). Additional bounds
2386- // on the adapter implementations (beyond `impl<I: Trait> Trait for Adapter<I>`) only depend on other
2387- // traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator).
2388- // I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which
2389- // several other specializations already depend on.
2390- impl < T > SourceIterMarker for T where T : SourceIter < Source : AsIntoIter > + InPlaceIterable { }
2391-
2392- impl < T , I > SpecFromIter < T , I > for Vec < T >
2393- where
2394- I : Iterator < Item = T > + SourceIterMarker ,
2395- {
2396- default fn from_iter ( mut iterator : I ) -> Self {
2397- // Additional requirements which cannot expressed via trait bounds. We rely on const eval
2398- // instead:
2399- // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic
2400- // b) size match as required by Alloc contract
2401- // c) alignments match as required by Alloc contract
2402- if mem:: size_of :: < T > ( ) == 0
2403- || mem:: size_of :: < T > ( )
2404- != mem:: size_of :: < <<I as SourceIter >:: Source as AsIntoIter >:: Item > ( )
2405- || mem:: align_of :: < T > ( )
2406- != mem:: align_of :: < <<I as SourceIter >:: Source as AsIntoIter >:: Item > ( )
2407- {
2408- // fallback to more generic implementations
2409- return SpecFromIterNested :: from_iter ( iterator) ;
2410- }
2411-
2412- let ( src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe {
2413- let inner = iterator. as_inner ( ) . as_into_iter ( ) ;
2414- (
2415- inner. buf . as_ptr ( ) ,
2416- inner. ptr ,
2417- inner. buf . as_ptr ( ) as * mut T ,
2418- inner. end as * const T ,
2419- inner. cap ,
2420- )
2421- } ;
2422-
2423- // use try-fold since
2424- // - it vectorizes better for some iterator adapters
2425- // - unlike most internal iteration methods, it only takes a &mut self
2426- // - it lets us thread the write pointer through its innards and get it back in the end
2427- let sink = InPlaceDrop { inner : dst_buf, dst : dst_buf } ;
2428- let sink = iterator
2429- . try_fold :: < _ , _ , Result < _ , !> > ( sink, write_in_place_with_drop ( dst_end) )
2430- . unwrap ( ) ;
2431- // iteration succeeded, don't drop head
2432- let dst = ManuallyDrop :: new ( sink) . dst ;
2433-
2434- let src = unsafe { iterator. as_inner ( ) . as_into_iter ( ) } ;
2435- // check if SourceIter contract was upheld
2436- // caveat: if they weren't we may not even make it to this point
2437- debug_assert_eq ! ( src_buf, src. buf. as_ptr( ) ) ;
2438- // check InPlaceIterable contract. This is only possible if the iterator advanced the
2439- // source pointer at all. If it uses unchecked access via TrustedRandomAccess
2440- // then the source pointer will stay in its initial position and we can't use it as reference
2441- if src. ptr != src_ptr {
2442- debug_assert ! (
2443- dst as * const _ <= src. ptr,
2444- "InPlaceIterable contract violation, write pointer advanced beyond read pointer"
2445- ) ;
2446- }
2447-
2448- // drop any remaining values at the tail of the source
2449- src. drop_remaining ( ) ;
2450- // but prevent drop of the allocation itself once IntoIter goes out of scope
2451- src. forget_allocation ( ) ;
2452-
2453- let vec = unsafe {
2454- let len = dst. offset_from ( dst_buf) as usize ;
2455- Vec :: from_raw_parts ( dst_buf, len, cap)
2456- } ;
2457-
2458- vec
2459- }
2460- }
2461-
24622361impl < ' a , T : ' a , I > SpecFromIter < & ' a T , I > for Vec < T >
24632362where
24642363 I : Iterator < Item = & ' a T > ,
0 commit comments