@@ -2870,6 +2870,41 @@ impl<T, A: Allocator> Vec<T, A> {
28702870 }
28712871 }
28722872
2873+ // specific extend for `TrustedLen` iterators, called both by the specializations
2874+ // and internal places where resolving specialization makes compilation slower
2875+ #[ cfg( not( no_global_oom_handling) ) ]
2876+ fn extend_trusted ( & mut self , iterator : impl iter:: TrustedLen < Item = T > ) {
2877+ let ( low, high) = iterator. size_hint ( ) ;
2878+ if let Some ( additional) = high {
2879+ debug_assert_eq ! (
2880+ low,
2881+ additional,
2882+ "TrustedLen iterator's size hint is not exact: {:?}" ,
2883+ ( low, high)
2884+ ) ;
2885+ self . reserve ( additional) ;
2886+ unsafe {
2887+ let mut ptr = self . as_mut_ptr ( ) . add ( self . len ( ) ) ;
2888+ let mut local_len = SetLenOnDrop :: new ( & mut self . len ) ;
2889+ iterator. for_each ( move |element| {
2890+ ptr:: write ( ptr, element) ;
2891+ ptr = ptr. add ( 1 ) ;
2892+ // Since the loop executes user code which can panic we have to bump the pointer
2893+ // after each step.
2894+ // NB can't overflow since we would have had to alloc the address space
2895+ local_len. increment_len ( 1 ) ;
2896+ } ) ;
2897+ }
2898+ } else {
2899+ // Per TrustedLen contract a `None` upper bound means that the iterator length
2900+ // truly exceeds usize::MAX, which would eventually lead to a capacity overflow anyway.
2901+ // Since the other branch already panics eagerly (via `reserve()`) we do the same here.
2902+ // This avoids additional codegen for a fallback code path which would eventually
2903+ // panic anyway.
2904+ panic ! ( "capacity overflow" ) ;
2905+ }
2906+ }
2907+
28732908 /// Creates a splicing iterator that replaces the specified range in the vector
28742909 /// with the given `replace_with` iterator and yields the removed items.
28752910 /// `replace_with` does not need to be the same length as `range`.
0 commit comments