diff options
| author | Josh Stone <jistone@redhat.com> | 2020-04-21 14:56:59 -0700 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2020-04-21 14:56:59 -0700 |
| commit | eeb687f20e86f2e2cf61ef89139c102cb92abfcb (patch) | |
| tree | e2a60e667c3e5f0633089e719552f5628f8c1f45 /src/libcore/tests | |
| parent | 45d050cde277b22a755847338f2acc2c7b834141 (diff) | |
| download | rust-eeb687f20e86f2e2cf61ef89139c102cb92abfcb.tar.gz rust-eeb687f20e86f2e2cf61ef89139c102cb92abfcb.zip | |
Don't fuse Chain in its second iterator
Only the "first" iterator is actually set `None` when exhausted, depending on whether you iterate forward or backward. This restores behavior similar to the former `ChainState`, where it would transition from `Both` to `Front`/`Back` and only continue from that side. However, if you mix directions, then this may still set both sides to `None`, totally fusing the iterator.
Diffstat (limited to 'src/libcore/tests')
| -rw-r--r-- | src/libcore/tests/iter.rs | 64 | ||||
| -rw-r--r-- | src/libcore/tests/lib.rs | 1 |
2 files changed, 40 insertions, 25 deletions
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 1a1dbcd7b87..7da02b11676 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -207,51 +207,65 @@ fn test_iterator_chain_find() { assert_eq!(iter.next(), None); } -#[test] -fn test_iterator_chain_size_hint() { - struct Iter { - is_empty: bool, - } +struct Toggle { + is_empty: bool, +} - impl Iterator for Iter { - type Item = (); +impl Iterator for Toggle { + type Item = (); - // alternates between `None` and `Some(())` - fn next(&mut self) -> Option<Self::Item> { - if self.is_empty { - self.is_empty = false; - None - } else { - self.is_empty = true; - Some(()) - } + // alternates between `None` and `Some(())` + fn next(&mut self) -> Option<Self::Item> { + if self.is_empty { + self.is_empty = false; + None + } else { + self.is_empty = true; + Some(()) } + } - fn size_hint(&self) -> (usize, Option<usize>) { - if self.is_empty { (0, Some(0)) } else { (1, Some(1)) } - } + fn size_hint(&self) -> (usize, Option<usize>) { + if self.is_empty { (0, Some(0)) } else { (1, Some(1)) } } +} - impl DoubleEndedIterator for Iter { - fn next_back(&mut self) -> Option<Self::Item> { - self.next() - } +impl DoubleEndedIterator for Toggle { + fn next_back(&mut self) -> Option<Self::Item> { + self.next() } +} +#[test] +fn test_iterator_chain_size_hint() { // this chains an iterator of length 0 with an iterator of length 1, // so after calling `.next()` once, the iterator is empty and the // state is `ChainState::Back`. `.size_hint()` should now disregard // the size hint of the left iterator - let mut iter = Iter { is_empty: true }.chain(once(())); + let mut iter = Toggle { is_empty: true }.chain(once(())); assert_eq!(iter.next(), Some(())); assert_eq!(iter.size_hint(), (0, Some(0))); - let mut iter = once(()).chain(Iter { is_empty: true }); + let mut iter = once(()).chain(Toggle { is_empty: true }); assert_eq!(iter.next_back(), Some(())); assert_eq!(iter.size_hint(), (0, Some(0))); } #[test] +fn test_iterator_chain_unfused() { + // Chain shouldn't be fused in its second iterator, depending on direction + let mut iter = NonFused::new(empty()).chain(Toggle { is_empty: true }); + iter.next().unwrap_none(); + iter.next().unwrap(); + iter.next().unwrap_none(); + + let mut iter = Toggle { is_empty: true }.chain(NonFused::new(empty())); + iter.next_back().unwrap_none(); + iter.next_back().unwrap(); + iter.next_back().unwrap_none(); +} + +#[test] fn test_zip_nth() { let xs = [0, 1, 2, 4, 5]; let ys = [10, 11, 12]; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 05f958cbe81..e7d36d327cd 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -42,6 +42,7 @@ #![feature(unwrap_infallible)] #![feature(leading_trailing_ones)] #![feature(const_forget)] +#![feature(option_unwrap_none)] extern crate test; |
