@@ -2163,7 +2163,7 @@ impl<T, A: Allocator> Vec<T, A> {
2163
2163
{
2164
2164
let len = self . len ( ) ;
2165
2165
if new_len > len {
2166
- self . extend_with ( new_len - len, ExtendFunc ( f ) ) ;
2166
+ self . extend_trusted ( iter :: repeat_with ( f ) . take ( new_len - len) ) ;
2167
2167
} else {
2168
2168
self . truncate ( new_len) ;
2169
2169
}
@@ -2491,16 +2491,6 @@ impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
2491
2491
}
2492
2492
}
2493
2493
2494
- struct ExtendFunc < F > ( F ) ;
2495
- impl < T , F : FnMut ( ) -> T > ExtendWith < T > for ExtendFunc < F > {
2496
- fn next ( & mut self ) -> T {
2497
- ( self . 0 ) ( )
2498
- }
2499
- fn last ( mut self ) -> T {
2500
- ( self . 0 ) ( )
2501
- }
2502
- }
2503
-
2504
2494
impl < T , A : Allocator > Vec < T , A > {
2505
2495
#[ cfg( not( no_global_oom_handling) ) ]
2506
2496
/// Extend the vector by `n` values, using the given generator.
@@ -2870,6 +2860,40 @@ impl<T, A: Allocator> Vec<T, A> {
2870
2860
}
2871
2861
}
2872
2862
2863
+ // specific extend for `TrustedLen` iterators, called both by the specializations
2864
+ // and internal places where resolving specialization makes compilation slower
2865
+ #[ cfg( not( no_global_oom_handling) ) ]
2866
+ fn extend_trusted ( & mut self , iterator : impl iter:: TrustedLen < Item = T > ) {
2867
+ let ( low, high) = iterator. size_hint ( ) ;
2868
+ if let Some ( additional) = high {
2869
+ debug_assert_eq ! (
2870
+ low,
2871
+ additional,
2872
+ "TrustedLen iterator's size hint is not exact: {:?}" ,
2873
+ ( low, high)
2874
+ ) ;
2875
+ self . reserve ( additional) ;
2876
+ unsafe {
2877
+ let ptr = self . as_mut_ptr ( ) ;
2878
+ let mut local_len = SetLenOnDrop :: new ( & mut self . len ) ;
2879
+ iterator. for_each ( move |element| {
2880
+ ptr:: write ( ptr. add ( local_len. current_len ( ) ) , element) ;
2881
+ // Since the loop executes user code which can panic we have to update
2882
+ // the length every step to correctly drop what we've written.
2883
+ // NB can't overflow since we would have had to alloc the address space
2884
+ local_len. increment_len ( 1 ) ;
2885
+ } ) ;
2886
+ }
2887
+ } else {
2888
+ // Per TrustedLen contract a `None` upper bound means that the iterator length
2889
+ // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway.
2890
+ // Since the other branch already panics eagerly (via `reserve()`) we do the same here.
2891
+ // This avoids additional codegen for a fallback code path which would eventually
2892
+ // panic anyway.
2893
+ panic ! ( "capacity overflow" ) ;
2894
+ }
2895
+ }
2896
+
2873
2897
/// Creates a splicing iterator that replaces the specified range in the vector
2874
2898
/// with the given `replace_with` iterator and yields the removed items.
2875
2899
/// `replace_with` does not need to be the same length as `range`.
0 commit comments