@@ -22,21 +22,39 @@ where
2222 // empty, but the loop in extend_desugared() is not going to see the
2323 // vector being full in the few subsequent loop iterations.
2424 // So we get better branch prediction.
25- let mut vector = match iterator. next ( ) {
26- None => return Vec :: new ( ) ,
27- Some ( element) => {
28- let ( lower, _) = iterator. size_hint ( ) ;
29- let initial_capacity =
30- cmp:: max ( RawVec :: < T > :: MIN_NON_ZERO_CAP , lower. saturating_add ( 1 ) ) ;
31- let mut vector = Vec :: with_capacity ( initial_capacity) ;
32- unsafe {
33- // SAFETY: We requested capacity at least 1
34- ptr:: write ( vector. as_mut_ptr ( ) , element) ;
35- vector. set_len ( 1 ) ;
36- }
37- vector
38- }
25+ let ( low, high) = iterator. size_hint ( ) ;
26+ let Some ( first) = iterator. next ( ) else {
27+ return Vec :: new ( ) ;
3928 } ;
29+ // `push`'s growth strategy is (currently) to double the capacity if
30+ // there's no space available, so it can have up to 50% "wasted" space.
31+ // Thus if the upper-bound on the size_hint also wouldn't waste more
32+ // than that, just allocate it from the start. (After all, it's silly
33+ // to allocate 254 for a hint of `(254, Some(255)`.)
34+ let initial_capacity = {
35+ // This is written like this to not overflow on any well-behaved iterator,
36+ // even things like `repeat_n(val, isize::MAX as usize + 10)`
37+ // where `low * 2` would need checking.
38+ // A bad (but safe) iterator might have `low > high`, but if so it'll
39+ // produce a huge `extra` that'll probably fail the following check.
40+ let hint = if let Some ( high) = high
41+ && let extra = high - low
42+ && extra < low
43+ {
44+ high
45+ } else {
46+ low
47+ } ;
48+ cmp:: max ( RawVec :: < T > :: MIN_NON_ZERO_CAP , hint)
49+ } ;
50+ let mut vector = Vec :: with_capacity ( initial_capacity) ;
51+ // SAFETY: We requested capacity at least MIN_NON_ZERO_CAP, which
52+ // is never zero, so there's space for at least one element.
53+ unsafe {
54+ ptr:: write ( vector. as_mut_ptr ( ) , first) ;
55+ vector. set_len ( 1 ) ;
56+ }
57+
4058 // must delegate to spec_extend() since extend() itself delegates
4159 // to spec_from for empty Vecs
4260 <Vec < T > as SpecExtend < T , I > >:: spec_extend ( & mut vector, iterator) ;
0 commit comments