@@ -2163,7 +2163,7 @@ impl<T, A: Allocator> Vec<T, A> {
21632163 {
21642164 let len = self . len ( ) ;
21652165 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) ) ;
21672167 } else {
21682168 self . truncate ( new_len) ;
21692169 }
@@ -2491,16 +2491,6 @@ impl<T: Clone> ExtendWith<T> for ExtendElement<T> {
24912491 }
24922492}
24932493
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-
25042494impl < T , A : Allocator > Vec < T , A > {
25052495 #[ cfg( not( no_global_oom_handling) ) ]
25062496 /// Extend the vector by `n` values, using the given generator.
@@ -2870,6 +2860,40 @@ impl<T, A: Allocator> Vec<T, A> {
28702860 }
28712861 }
28722862
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+
28732897 /// Creates a splicing iterator that replaces the specified range in the vector
28742898 /// with the given `replace_with` iterator and yields the removed items.
28752899 /// `replace_with` does not need to be the same length as `range`.
0 commit comments