Skip to content

Commit 2beb6a3

Browse files
committed
Auto merge of #65749 - Centril:insurance-policy, r=<try>
Insurance policy in case `iter.size_hint()` lies. Follow up to https://github.com/rust-lang/rust/pull/64949/files#r334235076. (If the perf impact is bad we can use `debug_assert!` instead.) The good news is that the UI tests pass locally so `iter.size_hint()` seems to be honest *thus far*. On the other hand, with the status quo we do not have an insurance policy should that change in some case. This is problematic because a) this could possibly make some program be accepted which shouldn't, b) the compiler itself could have memory unsafety if the correctness of the iterator is assumed in `unsafe { ... }` code (even though the blame lies with the `unsafe { ... }` block in question.) r? @RalfJung cc @nnethercote
2 parents 10a52c2 + c85bfc5 commit 2beb6a3

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

src/librustc/ty/context.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2866,25 +2866,27 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
28662866
-> Self::Output {
28672867
// This code is hot enough that it's worth specializing for the most
28682868
// common length lists, to avoid the overhead of `SmallVec` creation.
2869-
// The match arms are in order of frequency. The 1, 2, and 0 cases are
2870-
// typically hit in ~95% of cases. We assume that if the upper and
2871-
// lower bounds from `size_hint` agree they are correct.
2872-
Ok(match iter.size_hint() {
2873-
(1, Some(1)) => {
2874-
f(&[iter.next().unwrap()?])
2875-
}
2876-
(2, Some(2)) => {
2877-
let t0 = iter.next().unwrap()?;
2878-
let t1 = iter.next().unwrap()?;
2879-
f(&[t0, t1])
2880-
}
2881-
(0, Some(0)) => {
2882-
f(&[])
2883-
}
2884-
_ => {
2885-
f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?)
2886-
}
2887-
})
2869+
// In terms of frequency, lengths 1, 2, and 0 are typically hit in ~95% of cases.
2870+
let e0 = match iter.next() {
2871+
Some(x) => x?,
2872+
None => return Ok(f(&[])),
2873+
};
2874+
let e1 = match iter.next() {
2875+
None => return Ok(f(&[e0])),
2876+
Some(x) => x?,
2877+
};
2878+
let e2 = match iter.next() {
2879+
None => return Ok(f(&[e0, e1])),
2880+
Some(x) => x?,
2881+
};
2882+
let mut vec: SmallVec<[_; 8]> = SmallVec::with_capacity(3 + iter.size_hint().0);
2883+
vec.push(e0);
2884+
vec.push(e1);
2885+
vec.push(e2);
2886+
for result in iter {
2887+
vec.push(result?);
2888+
}
2889+
Ok(f(&vec))
28882890
}
28892891
}
28902892

0 commit comments

Comments
 (0)