about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2019-10-26 02:45:57 +0900
committerGitHub <noreply@github.com>2019-10-26 02:45:57 +0900
commit7068c2d4e9af54c1e1a2fae2a7d17786c49fea7d (patch)
treed09174d556f7ae8ea90168673d9e28269b90f48d
parenta808ba374f7fdf6fea3f0bde9ce09f98f0db7d2d (diff)
parentdfcfca28ad1321aff82503ebfffd40cf6476a7a2 (diff)
downloadrust-7068c2d4e9af54c1e1a2fae2a7d17786c49fea7d.tar.gz
rust-7068c2d4e9af54c1e1a2fae2a7d17786c49fea7d.zip
Rollup merge of #65749 - Centril:insurance-policy, r=RalfJung
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
-rw-r--r--src/librustc/ty/context.rs6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index f958a7e357b..0f7d5d9a25e 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2930,14 +2930,18 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
         // lower bounds from `size_hint` agree they are correct.
         Ok(match iter.size_hint() {
             (1, Some(1)) => {
-                f(&[iter.next().unwrap()?])
+                let t0 = iter.next().unwrap()?;
+                assert!(iter.next().is_none());
+                f(&[t0])
             }
             (2, Some(2)) => {
                 let t0 = iter.next().unwrap()?;
                 let t1 = iter.next().unwrap()?;
+                assert!(iter.next().is_none());
                 f(&[t0, t1])
             }
             (0, Some(0)) => {
+                assert!(iter.next().is_none());
                 f(&[])
             }
             _ => {