Auto merge of #137908 - scottmcm:another-size-hint-attempt, r= · rust-lang/rust@272c07f (original) (raw)
`@@ -22,21 +22,39 @@ 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::::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();
`
39
28
`};
`
``
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::::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
+
40
58
`// must delegate to spec_extend() since extend() itself delegates
`
41
59
`// to spec_from for empty Vecs
`
42
60
` <Vec as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
`