about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2021-01-04 01:08:13 +0100
committerThe8472 <git@infinite-source.de>2021-01-04 01:12:21 +0100
commitaf2983a9122138cb9055b79fda54e72f71599a6f (patch)
tree6ff318a71a32aa8a518f83a24cd2f54db744f548
parent80184183ba0a53aa4f491753de9502acd3d6920c (diff)
downloadrust-af2983a9122138cb9055b79fda54e72f71599a6f.tar.gz
rust-af2983a9122138cb9055b79fda54e72f71599a6f.zip
TrustedRandomAaccess spec composes incorrectly for nested iter::Zips
After partially consuming a Zip adapter and then wrapping it into
another Zip where the adapters use their TrustedRandomAccess specializations
leads to the outer adapter returning elements which should have already been
consumed.
-rw-r--r--library/core/src/iter/adapters/zip.rs1
-rw-r--r--library/core/tests/iter.rs21
-rw-r--r--library/core/tests/lib.rs1
3 files changed, 23 insertions, 0 deletions
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 8cd4c775231..55670452200 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -286,6 +286,7 @@ where
 
     #[inline]
     unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
+        let idx = self.index + idx;
         // SAFETY: the caller must uphold the contract for
         // `Iterator::__iterator_get_unchecked`.
         unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs
index 7376e7848ef..5caba1ad229 100644
--- a/library/core/tests/iter.rs
+++ b/library/core/tests/iter.rs
@@ -2,6 +2,7 @@
 
 use core::cell::Cell;
 use core::convert::TryFrom;
+use core::iter::TrustedRandomAccess;
 use core::iter::*;
 
 /// An iterator wrapper that panics whenever `next` or `next_back` is called
@@ -602,6 +603,26 @@ fn test_zip_nth_back_side_effects_exhausted() {
 }
 
 #[test]
+fn test_zip_trusted_random_access_composition() {
+    let a = [0, 1, 2, 3, 4];
+    let b = a;
+    let c = a;
+
+    let a = a.iter().copied();
+    let b = b.iter().copied();
+    let mut c = c.iter().copied();
+    c.next();
+
+    let mut z1 = a.zip(b);
+    assert_eq!(z1.next().unwrap(), (0, 0));
+
+    let mut z2 = z1.zip(c);
+    fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
+    assert_trusted_random_access(&z2);
+    assert_eq!(z2.next().unwrap(), ((1, 1), 1));
+}
+
+#[test]
 fn test_iterator_step_by() {
     // Identity
     let mut it = (0..).step_by(1).take(3);
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index e01aaa4cbf1..4c90844e07d 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -73,6 +73,7 @@
 #![feature(const_option)]
 #![feature(integer_atomics)]
 #![feature(slice_group_by)]
+#![feature(trusted_random_access)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;