@@ -60,7 +60,7 @@ use core::fmt;
60
60
use core:: hash:: { Hash , Hasher } ;
61
61
use core:: intrinsics:: { arith_offset, assume} ;
62
62
use core:: iter:: {
63
- FromIterator , InPlaceIterable , SourceIter , TrustedLen ,
63
+ FromIterator , TrustedLen ,
64
64
} ;
65
65
use core:: marker:: PhantomData ;
66
66
use core:: mem:: { self , ManuallyDrop , MaybeUninit } ;
@@ -101,6 +101,8 @@ use self::is_zero::IsZero;
101
101
102
102
mod is_zero;
103
103
104
+ mod source_iter_marker;
105
+
104
106
/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
105
107
///
106
108
/// # Examples
@@ -2356,109 +2358,6 @@ impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
2356
2358
}
2357
2359
}
2358
2360
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
-
2462
2361
impl < ' a , T : ' a , I > SpecFromIter < & ' a T , I > for Vec < T >
2463
2362
where
2464
2363
I : Iterator < Item = & ' a T > ,
0 commit comments