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