summary refs log tree commit diff
path: root/src/libcoretest
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2015-08-25 03:56:35 +0200
committerUlrik Sverdrup <bluss@users.noreply.github.com>2015-08-25 19:07:24 +0200
commit35eb3e8b79c60ec18e724c7a68625d7cdf9300c0 (patch)
treecbe9683058388284c4b11e0579c719eef98827b1 /src/libcoretest
parent4c996499a1bcf747b12f8290eeff3024e59da529 (diff)
downloadrust-35eb3e8b79c60ec18e724c7a68625d7cdf9300c0.tar.gz
rust-35eb3e8b79c60ec18e724c7a68625d7cdf9300c0.zip
Correct iterator adaptor Chain
The iterator protocol specifies that the iteration ends with the return
value `None` from `.next()` (or `.next_back()`) and it is unspecified
what further calls return. The chain adaptor must account for this in
its DoubleEndedIterator implementation.

It uses three states:

- Both `a` and `b` are valid
- Only the Front iterator (`a`) is valid
- Only the Back iterator (`b`) is valid

The fourth state (neither iterator is valid) only occurs after Chain has
returned None once, so we don't need to store this state.

Fixes #26316
Diffstat (limited to 'src/libcoretest')
-rw-r--r--src/libcoretest/iter.rs20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index ea65c118e5e..87e69581c54 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -729,6 +729,26 @@ fn test_double_ended_chain() {
     assert_eq!(it.next_back().unwrap(), &5);
     assert_eq!(it.next_back().unwrap(), &7);
     assert_eq!(it.next_back(), None);
+
+
+    // test that .chain() is well behaved with an unfused iterator
+    struct CrazyIterator(bool);
+    impl CrazyIterator { fn new() -> CrazyIterator { CrazyIterator(false) } }
+    impl Iterator for CrazyIterator {
+        type Item = i32;
+        fn next(&mut self) -> Option<i32> {
+            if self.0 { Some(99) } else { self.0 = true; None }
+        }
+    }
+
+    impl DoubleEndedIterator for CrazyIterator {
+        fn next_back(&mut self) -> Option<i32> {
+            self.next()
+        }
+    }
+
+    assert_eq!(CrazyIterator::new().chain(0..10).rev().last(), Some(0));
+    assert!((0..10).chain(CrazyIterator::new()).rev().any(|i| i == 0));
 }
 
 #[test]