From de91872a3337dddf9a0d27df7bfb64f3965c81b0 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 13 Aug 2016 14:42:36 -0400 Subject: [PATCH] Add a FusedIterator trait. This trait can be used to avoid the overhead of a fuse wrapper when an iterator is already well-behaved. Conforming to: RFC 1581 Closes: #35602 --- src/liballoc/boxed.rs | 4 + src/liballoc/lib.rs | 2 +- src/libcollections/binary_heap.rs | 11 ++- src/libcollections/btree/map.rs | 27 +++++- src/libcollections/btree/set.rs | 21 ++++- src/libcollections/enum_set.rs | 5 +- src/libcollections/lib.rs | 1 + src/libcollections/linked_list.rs | 11 ++- src/libcollections/str.rs | 4 + src/libcollections/string.rs | 5 +- src/libcollections/vec.rs | 8 +- src/libcollections/vec_deque.rs | 15 +++- src/libcore/char.rs | 18 ++++ src/libcore/iter/mod.rs | 130 +++++++++++++++++++++++++++-- src/libcore/iter/range.rs | 24 +++++- src/libcore/iter/sources.rs | 11 ++- src/libcore/iter/traits.rs | 16 ++++ src/libcore/option.rs | 14 +++- src/libcore/result.rs | 10 +++ src/libcore/slice.rs | 25 ++++++ src/libcore/str/mod.rs | 25 +++++- src/librustc_unicode/char.rs | 6 ++ src/librustc_unicode/lib.rs | 1 + src/librustc_unicode/u_str.rs | 9 +- src/libstd/ascii.rs | 4 + src/libstd/collections/hash/map.rs | 17 +++- src/libstd/collections/hash/set.rs | 28 ++++++- src/libstd/lib.rs | 1 + src/libstd/path.rs | 8 +- 29 files changed, 437 insertions(+), 24 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7ba5ca30941f4..dae12f6e8bdf7 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -61,6 +61,7 @@ use core::borrow; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; +use core::iter::FusedIterator; use core::marker::{self, Unsize}; use core::mem; use core::ops::{CoerceUnsized, Deref, DerefMut}; @@ -529,6 +530,9 @@ impl DoubleEndedIterator for Box { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Box {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Box {} + /// `FnBox` is a version of the `FnOnce` intended for use with boxed /// closure objects. The idea is that where one would normally store a diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 0293d5402c4c9..90037f813cda6 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -91,7 +91,7 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(unsize)] -#![cfg_attr(not(test), feature(raw, fn_traits, placement_new_protocol))] +#![cfg_attr(not(test), feature(fused, raw, fn_traits, placement_new_protocol))] #![cfg_attr(test, feature(test, box_heap))] // Allow testing this library diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index b9f5c6fcab909..42b29fa6e44ee 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -152,7 +152,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::ops::{Drop, Deref, DerefMut}; -use core::iter::FromIterator; +use core::iter::{FromIterator, FusedIterator}; use core::mem::swap; use core::mem::size_of; use core::ptr; @@ -981,6 +981,9 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Iter<'a, T> {} + /// An iterator that moves out of a `BinaryHeap`. #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -1014,6 +1017,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + /// An iterator that drains a `BinaryHeap`. #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, T: 'a> { @@ -1046,6 +1052,9 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl From> for BinaryHeap { fn from(vec: Vec) -> BinaryHeap { diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index c3a7d4023754a..7b09cd2115d58 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -11,7 +11,7 @@ use core::cmp::Ordering; use core::fmt::Debug; use core::hash::{Hash, Hasher}; -use core::iter::{FromIterator, Peekable}; +use core::iter::{FromIterator, Peekable, FusedIterator}; use core::marker::PhantomData; use core::ops::Index; use core::{fmt, intrinsics, mem, ptr}; @@ -1147,6 +1147,9 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} + impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a V)> { if self.length == 0 { @@ -1216,6 +1219,9 @@ impl<'a, K: 'a, V: 'a> ExactSizeIterator for IterMut<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} + impl IntoIterator for BTreeMap { type Item = (K, V); type IntoIter = IntoIter; @@ -1338,6 +1344,9 @@ impl ExactSizeIterator for IntoIter { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; @@ -1362,6 +1371,9 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} + impl<'a, K, V> Clone for Keys<'a, K, V> { fn clone(&self) -> Keys<'a, K, V> { Keys { inner: self.inner.clone() } @@ -1392,6 +1404,9 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Values<'a, K, V> {} + impl<'a, K, V> Clone for Values<'a, K, V> { fn clone(&self) -> Values<'a, K, V> { Values { inner: self.inner.clone() } @@ -1437,6 +1452,10 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} + + impl<'a, K, V> Range<'a, K, V> { unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { let handle = self.front; @@ -1511,6 +1530,9 @@ impl<'a, K, V> Range<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Range<'a, K, V> {} + impl<'a, K, V> Clone for Range<'a, K, V> { fn clone(&self) -> Range<'a, K, V> { Range { @@ -1574,6 +1596,9 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for RangeMut<'a, K, V> {} + impl<'a, K, V> RangeMut<'a, K, V> { unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { let handle = ptr::read(&self.back); diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 0f885bc2950a6..5d7b00f57c83b 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -15,7 +15,7 @@ use core::cmp::Ordering::{self, Less, Greater, Equal}; use core::cmp::{min, max}; use core::fmt::Debug; use core::fmt; -use core::iter::{Peekable, FromIterator}; +use core::iter::{Peekable, FromIterator, FusedIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub}; use borrow::Borrow; @@ -805,6 +805,8 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { fn len(&self) -> usize { self.iter.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { @@ -828,6 +830,8 @@ impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.iter.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} impl<'a, T> Clone for Range<'a, T> { fn clone(&self) -> Range<'a, T> { @@ -847,6 +851,9 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Range<'a, T> {} + /// Compare `x` and `y`, but return `short` if x is None and `long` if y is None fn cmp_opt(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering) -> Ordering { match (x, y) { @@ -890,6 +897,9 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T: Ord> FusedIterator for Difference<'a, T> {} + impl<'a, T> Clone for SymmetricDifference<'a, T> { fn clone(&self) -> SymmetricDifference<'a, T> { SymmetricDifference { @@ -920,6 +930,9 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T: Ord> FusedIterator for SymmetricDifference<'a, T> {} + impl<'a, T> Clone for Intersection<'a, T> { fn clone(&self) -> Intersection<'a, T> { Intersection { @@ -960,6 +973,9 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T: Ord> FusedIterator for Intersection<'a, T> {} + impl<'a, T> Clone for Union<'a, T> { fn clone(&self) -> Union<'a, T> { Union { @@ -991,3 +1007,6 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { (max(a_len, b_len), Some(a_len + b_len)) } } + +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T: Ord> FusedIterator for Union<'a, T> {} diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 0c66c0564c3ea..2456a04e40a3a 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -20,7 +20,7 @@ use core::marker; use core::fmt; -use core::iter::FromIterator; +use core::iter::{FromIterator, FusedIterator}; use core::ops::{Sub, BitOr, BitAnd, BitXor}; // FIXME(contentions): implement union family of methods? (general design may be @@ -266,6 +266,9 @@ impl Iterator for Iter { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Iter {} + impl FromIterator for EnumSet { fn from_iter>(iter: I) -> EnumSet { let mut ret = EnumSet::new(); diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 21387a1aa9554..2781059c1d543 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -37,6 +37,7 @@ #![feature(core_intrinsics)] #![feature(dropck_parametricity)] #![feature(fmt_internals)] +#![feature(fused)] #![feature(heap_api)] #![feature(inclusive_range)] #![feature(lang_items)] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 6842f02e0e19b..1f52af9f913e9 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -19,7 +19,7 @@ use alloc::boxed::{Box, IntermediateBox}; use core::cmp::Ordering; use core::fmt; use core::hash::{Hasher, Hash}; -use core::iter::FromIterator; +use core::iter::{FromIterator, FusedIterator}; use core::marker::PhantomData; use core::mem; use core::ops::{BoxPlace, InPlace, Place, Placer}; @@ -757,6 +757,9 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Iter<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; @@ -801,6 +804,9 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for IterMut<'a, T> {} + impl<'a, T> IterMut<'a, T> { /// Inserts the given element just after the element most recently returned by `.next()`. /// The inserted element does not appear in the iteration. @@ -908,6 +914,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for LinkedList { fn from_iter>(iter: I) -> Self { diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 4c64019de097e..999c84ba70538 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -23,6 +23,7 @@ use core::str as core_str; use core::str::pattern::Pattern; use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::mem; +use core::iter::FusedIterator; use rustc_unicode::str::{UnicodeStr, Utf16Encoder}; use vec_deque::VecDeque; @@ -136,6 +137,9 @@ impl<'a> Iterator for EncodeUtf16<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for EncodeUtf16<'a> {} + // Return the initial codepoint accumulator for the first byte. // The first byte is special, only want bottom 5 bits for width 2, 4 bits // for width 3, and 3 bits for width 4 diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 788c838cd3fc8..d4de726cfafd6 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -57,7 +57,7 @@ use core::fmt; use core::hash; -use core::iter::FromIterator; +use core::iter::{FromIterator, FusedIterator}; use core::mem; use core::ops::{self, Add, AddAssign, Index, IndexMut}; use core::ptr; @@ -1995,3 +1995,6 @@ impl<'a> DoubleEndedIterator for Drain<'a> { self.iter.next_back() } } + +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for Drain<'a> {} diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 522890a2e2682..a866cdeb7ec3e 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -68,7 +68,7 @@ use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; -use core::iter::FromIterator; +use core::iter::{FromIterator, FusedIterator}; use core::mem; use core::ops::{Index, IndexMut}; use core::ops; @@ -1845,6 +1845,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] impl Clone for IntoIter { fn clone(&self) -> IntoIter { @@ -1932,3 +1935,6 @@ impl<'a, T> Drop for Drain<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Drain<'a, T> {} + +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Drain<'a, T> {} diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 812a67a7e78ed..57e00576e45f4 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -20,7 +20,7 @@ use core::cmp::Ordering; use core::fmt; -use core::iter::{repeat, FromIterator}; +use core::iter::{repeat, FromIterator, FusedIterator}; use core::mem; use core::ops::{Index, IndexMut}; use core::ptr; @@ -1894,6 +1894,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Iter<'a, T> {} + + /// `VecDeque` mutable iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { @@ -1946,6 +1950,9 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for IterMut<'a, T> {} + /// A by-value VecDeque iterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] @@ -1980,6 +1987,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + /// A draining VecDeque iterator #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, T: 'a> { @@ -2069,6 +2079,9 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for VecDeque { fn eq(&self, other: &VecDeque) -> bool { diff --git a/src/libcore/char.rs b/src/libcore/char.rs index a3440fe8aa644..98b7632a220dd 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -18,6 +18,7 @@ use prelude::v1::*; use char_private::is_printable; +use iter::FusedIterator; use mem::transmute; // UTF-8 ranges and tags for encoding characters @@ -516,6 +517,9 @@ impl ExactSizeIterator for EscapeUnicode { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for EscapeUnicode {} + /// An iterator that yields the literal escape code of a `char`. /// /// This `struct` is created by the [`escape_default()`] method on [`char`]. See @@ -616,6 +620,9 @@ impl ExactSizeIterator for EscapeDefault { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for EscapeDefault {} + /// An iterator that yields the literal escape code of a `char`. /// /// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its @@ -637,6 +644,9 @@ impl Iterator for EscapeDebug { #[unstable(feature = "char_escape_debug", issue = "35068")] impl ExactSizeIterator for EscapeDebug { } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for EscapeDebug {} + /// An iterator over `u8` entries represending the UTF-8 encoding of a `char` /// value. /// @@ -675,6 +685,9 @@ impl Iterator for EncodeUtf8 { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for EncodeUtf8 {} + /// An iterator over `u16` entries represending the UTF-16 encoding of a `char` /// value. /// @@ -714,6 +727,8 @@ impl Iterator for EncodeUtf16 { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for EncodeUtf16 {} /// An iterator over an iterator of bytes of the characters the bytes represent /// as UTF-8 @@ -760,3 +775,6 @@ impl> Iterator for DecodeUtf8 { }) } } + +#[unstable(feature = "fused", issue = "35602")] +impl> FusedIterator for DecodeUtf8 {} diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d2de0d46d746b..cfe117c0b1d69 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -330,6 +330,8 @@ pub use self::sources::{Once, once}; pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::{ExactSizeIterator, Sum, Product}; +#[unstable(feature = "fused", issue = "35602")] +pub use self::traits::FusedIterator; mod iterator; mod range; @@ -370,6 +372,10 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { impl ExactSizeIterator for Rev where I: ExactSizeIterator + DoubleEndedIterator {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Rev + where I: FusedIterator + DoubleEndedIterator {} + /// An iterator that clones the elements of an underlying iterator. /// /// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its @@ -413,6 +419,11 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned where I: ExactSizeIterator, T: Clone {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, I, T: 'a> FusedIterator for Cloned + where I: FusedIterator, T: Clone +{} + /// An iterator that repeats endlessly. /// /// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its @@ -451,6 +462,9 @@ impl Iterator for Cycle where I: Clone + Iterator { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Cycle where I: Clone + Iterator {} + /// An iterator that strings two iterators together. /// /// This `struct` is created by the [`chain()`] method on [`Iterator`]. See its @@ -613,6 +627,13 @@ impl DoubleEndedIterator for Chain where } } +// Note: *both* must be fused to handle double-ended iterators. +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Chain + where A: FusedIterator, + B: FusedIterator, +{} + /// An iterator that iterates two other iterators simultaneously. /// /// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its @@ -823,6 +844,10 @@ unsafe impl TrustedRandomAccess for Zip } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Zip + where A: FusedIterator, B: FusedIterator, {} + /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map()`] method on [`Iterator`]. See its @@ -919,6 +944,10 @@ impl DoubleEndedIterator for Map where impl ExactSizeIterator for Map where F: FnMut(I::Item) -> B {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Map + where F: FnMut(I::Item) -> B {} + /// An iterator that filters the elements of `iter` with `predicate`. /// /// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its @@ -979,6 +1008,10 @@ impl DoubleEndedIterator for Filter } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Filter + where P: FnMut(&I::Item) -> bool {} + /// An iterator that uses `f` to both filter and map elements from `iter`. /// /// This `struct` is created by the [`filter_map()`] method on [`Iterator`]. See its @@ -1041,6 +1074,10 @@ impl DoubleEndedIterator for FilterMap } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for FilterMap + where F: FnMut(I::Item) -> Option {} + /// An iterator that yields the current count and the element during iteration. /// /// This `struct` is created by the [`enumerate()`] method on [`Iterator`]. See its @@ -1128,6 +1165,9 @@ unsafe impl TrustedRandomAccess for Enumerate } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Enumerate where I: FusedIterator {} + /// An iterator with a `peek()` that returns an optional reference to the next /// element. /// @@ -1195,6 +1235,9 @@ impl Iterator for Peekable { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Peekable {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Peekable {} + impl Peekable { /// Returns a reference to the next() value without advancing the iterator. /// @@ -1296,6 +1339,10 @@ impl Iterator for SkipWhile } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for SkipWhile + where I: FusedIterator, P: FnMut(&I::Item) -> bool {} + /// An iterator that only accepts elements while `predicate` is true. /// /// This `struct` is created by the [`take_while()`] method on [`Iterator`]. See its @@ -1351,6 +1398,10 @@ impl Iterator for TakeWhile } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for TakeWhile + where I: FusedIterator, P: FnMut(&I::Item) -> bool {} + /// An iterator that skips over `n` elements of `iter`. /// /// This `struct` is created by the [`skip()`] method on [`Iterator`]. See its @@ -1442,6 +1493,9 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Skip where I: FusedIterator {} + /// An iterator that only iterates over the first `n` iterations of `iter`. /// /// This `struct` is created by the [`take()`] method on [`Iterator`]. See its @@ -1503,6 +1557,8 @@ impl Iterator for Take where I: Iterator{ #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Take where I: ExactSizeIterator {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Take where I: FusedIterator {} /// An iterator to maintain state while iterating another iterator. /// @@ -1549,6 +1605,10 @@ impl Iterator for Scan where } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Scan + where I: FusedIterator, F: FnMut(&mut St, I::Item) -> Option {} + /// An iterator that maps each element to an iterator, and yields the elements /// of the produced iterators. /// @@ -1635,6 +1695,10 @@ impl DoubleEndedIterator for FlatMap wher } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for FlatMap + where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {} + /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// @@ -1651,12 +1715,15 @@ pub struct Fuse { done: bool } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Fuse where I: Iterator {} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Fuse where I: Iterator { type Item = ::Item; #[inline] - fn next(&mut self) -> Option<::Item> { + default fn next(&mut self) -> Option<::Item> { if self.done { None } else { @@ -1667,7 +1734,7 @@ impl Iterator for Fuse where I: Iterator { } #[inline] - fn nth(&mut self, n: usize) -> Option { + default fn nth(&mut self, n: usize) -> Option { if self.done { None } else { @@ -1678,7 +1745,7 @@ impl Iterator for Fuse where I: Iterator { } #[inline] - fn last(self) -> Option { + default fn last(self) -> Option { if self.done { None } else { @@ -1687,7 +1754,7 @@ impl Iterator for Fuse where I: Iterator { } #[inline] - fn count(self) -> usize { + default fn count(self) -> usize { if self.done { 0 } else { @@ -1696,7 +1763,7 @@ impl Iterator for Fuse where I: Iterator { } #[inline] - fn size_hint(&self) -> (usize, Option) { + default fn size_hint(&self) -> (usize, Option) { if self.done { (0, Some(0)) } else { @@ -1708,7 +1775,7 @@ impl Iterator for Fuse where I: Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator { #[inline] - fn next_back(&mut self) -> Option<::Item> { + default fn next_back(&mut self) -> Option<::Item> { if self.done { None } else { @@ -1719,6 +1786,53 @@ impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator { } } +unsafe impl TrustedRandomAccess for Fuse + where I: TrustedRandomAccess, +{ + unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { + self.iter.get_unchecked(i) + } +} + +#[unstable(feature = "fused", issue = "35602")] +impl Iterator for Fuse where I: FusedIterator { + #[inline] + fn next(&mut self) -> Option<::Item> { + self.iter.next() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.iter.nth(n) + } + + #[inline] + fn last(self) -> Option { + self.iter.last() + } + + #[inline] + fn count(self) -> usize { + self.iter.count() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[unstable(feature = "fused", reason = "recently added", issue = "35602")] +impl DoubleEndedIterator for Fuse + where I: DoubleEndedIterator + FusedIterator +{ + #[inline] + fn next_back(&mut self) -> Option<::Item> { + self.iter.next_back() + } +} + + #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Fuse where I: ExactSizeIterator {} @@ -1788,3 +1902,7 @@ impl DoubleEndedIterator for Inspect #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Inspect where F: FnMut(&I::Item) {} + +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Inspect + where F: FnMut(&I::Item) {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 079dfe2a81f80..48816bf66bbb7 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -16,7 +16,7 @@ use option::Option::{self, Some, None}; use marker::Sized; use usize; -use super::{DoubleEndedIterator, ExactSizeIterator, Iterator}; +use super::{DoubleEndedIterator, ExactSizeIterator, Iterator, FusedIterator}; /// Objects that can be stepped over in both directions. /// @@ -364,6 +364,10 @@ impl Iterator for StepBy> where } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for StepBy> + where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for StepBy> { type Item = A; @@ -401,6 +405,9 @@ impl Iterator for StepBy> { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for StepBy> {} + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] @@ -468,6 +475,9 @@ impl Iterator for StepBy> { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for StepBy> {} + macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -526,6 +536,10 @@ impl DoubleEndedIterator for ops::Range where } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for ops::Range + where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ops::RangeFrom where for<'a> &'a A: Add<&'a A, Output = A> @@ -540,6 +554,10 @@ impl Iterator for ops::RangeFrom where } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for ops::RangeFrom + where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} + #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] impl Iterator for ops::RangeInclusive where for<'a> &'a A: Add<&'a A, Output = A> @@ -638,3 +656,7 @@ impl DoubleEndedIterator for ops::RangeInclusive where n } } + +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for ops::RangeInclusive + where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index ecd4a78b9e760..a2a019a07dcf1 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -15,7 +15,7 @@ use marker; use option::Option::{self, Some, None}; use usize; -use super::{DoubleEndedIterator, IntoIterator, Iterator, ExactSizeIterator}; +use super::{DoubleEndedIterator, IntoIterator, Iterator, ExactSizeIterator, FusedIterator}; /// An iterator that repeats an element endlessly. /// @@ -44,6 +44,9 @@ impl DoubleEndedIterator for Repeat { fn next_back(&mut self) -> Option { Some(self.element.clone()) } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Repeat {} + /// Creates a new iterator that endlessly repeats a single element. /// /// The `repeat()` function repeats a single value over and over and over and @@ -138,6 +141,9 @@ impl ExactSizeIterator for Empty { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Empty {} + // not #[derive] because that adds a Clone bound on T, // which isn't necessary. #[stable(feature = "iter_empty", since = "1.2.0")] @@ -213,6 +219,9 @@ impl ExactSizeIterator for Once { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Once {} + /// Creates an iterator that yields an element exactly once. /// /// This is commonly used to adapt a single value into a [`chain()`] of other diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 4cbabe3f5edaf..0b6ab5a4bbb14 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -658,3 +658,19 @@ macro_rules! float_sum_product { integer_sum_product! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } float_sum_product! { f32 f64 } + +/// An iterator that always continues to yield `None` when exhausted. +/// +/// Calling next on a fused iterator that has returned `None` once is guaranteed +/// to return `None` again. This trait is should be implemented by all iterators +/// that behave this way because it allows for some significant optimizations. +/// +/// Note: In general, you should not use `FusedIterator` in generic bounds if +/// you need a fused iterator. Instead, you should just call `Iterator::fused()` +/// on the iterator. If the iterator is already fused, the additional `Fuse` +/// wrapper will be a no-op with no performance penalty. +#[unstable(feature = "fused", issue = "35602")] +pub trait FusedIterator: Iterator {} + +#[unstable(feature = "fused", issue = "35602")] +impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index fe508adb71380..51bbad085fba4 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -144,8 +144,8 @@ use self::Option::*; use clone::Clone; use convert::From; use default::Default; -use iter::ExactSizeIterator; -use iter::{Iterator, DoubleEndedIterator, FromIterator, IntoIterator}; +use iter::{Iterator, FromIterator, IntoIterator, ExactSizeIterator, DoubleEndedIterator}; +use iter::FusedIterator; use mem; use ops::FnOnce; use result::Result::{Ok, Err}; @@ -796,6 +796,7 @@ impl DoubleEndedIterator for Item { } impl ExactSizeIterator for Item {} +impl FusedIterator for Item {} /// An iterator over a reference of the contained item in an Option. #[stable(feature = "rust1", since = "1.0.0")] @@ -821,6 +822,9 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> ExactSizeIterator for Iter<'a, A> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, A> FusedIterator for Iter<'a, A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> Clone for Iter<'a, A> { fn clone(&self) -> Iter<'a, A> { @@ -852,6 +856,9 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, A> FusedIterator for IterMut<'a, A> {} + /// An iterator over the item contained inside an Option. #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] @@ -876,6 +883,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + ///////////////////////////////////////////////////////////////////////////// // FromIterator ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index c7ca70fc1622d..718fdf865a970 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -241,6 +241,7 @@ use self::Result::{Ok, Err}; use clone::Clone; use fmt; use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator}; +use iter::FusedIterator; use ops::FnOnce; use option::Option::{self, None, Some}; @@ -869,6 +870,9 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Iter<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { inner: self.inner } } @@ -901,6 +905,9 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for IterMut<'a, T> {} + /// An iterator over the value in a `Ok` variant of a `Result`. #[derive(Debug)] #[stable(feature = "rust1", since = "1.0.0")] @@ -928,6 +935,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} + ///////////////////////////////////////////////////////////////////////////// // FromIterator ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 3a820a14f1214..603f55a6e108e 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -992,6 +992,9 @@ iterator!{struct Iter -> *const T, &'a T} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Iter<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } } @@ -1110,6 +1113,9 @@ iterator!{struct IterMut -> *mut T, &'a mut T} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for IterMut<'a, T> {} + /// An internal abstraction over the splitting iterators, so that /// splitn, splitn_mut etc can be implemented once. #[doc(hidden)] @@ -1202,6 +1208,9 @@ impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {} + /// An iterator over the subslices of the vector which are separated /// by elements that match `pred`. #[stable(feature = "rust1", since = "1.0.0")] @@ -1292,6 +1301,9 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {} + /// An private iterator over subslices separated by elements that /// match a predicate function, splitting at most a fixed number of /// times. @@ -1408,6 +1420,10 @@ macro_rules! forward_iterator { self.inner.size_hint() } } + + #[unstable(feature = "fused", issue = "35602")] + impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> + where P: FnMut(&T) -> bool {} } } @@ -1506,6 +1522,9 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Windows<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Windows<'a, T> {} + /// An iterator over a slice in (non-overlapping) chunks (`size` elements at a /// time). /// @@ -1609,6 +1628,9 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Chunks<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for Chunks<'a, T> {} + /// An iterator over a slice in (non-overlapping) mutable chunks (`size` /// elements at a time). When the slice len is not evenly divided by the chunk /// size, the last slice of the iteration will be the remainder. @@ -1704,6 +1726,9 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T> FusedIterator for ChunksMut<'a, T> {} + // // Free functions // diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index fdcadd43a0fb6..e18aa07b75d8e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -23,7 +23,7 @@ use convert::AsRef; use default::Default; use fmt; use iter::ExactSizeIterator; -use iter::{Map, Cloned, Iterator, DoubleEndedIterator}; +use iter::{Map, Cloned, Iterator, DoubleEndedIterator, FusedIterator}; use marker::Sized; use mem; use ops::{Fn, FnMut, FnOnce}; @@ -454,6 +454,9 @@ impl<'a> DoubleEndedIterator for Chars<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for Chars<'a> {} + impl<'a> Chars<'a> { /// View the underlying data as a subslice of the original data. /// @@ -525,6 +528,9 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for CharIndices<'a> {} + impl<'a> CharIndices<'a> { /// View the underlying data as a subslice of the original data. /// @@ -593,6 +599,9 @@ impl<'a> ExactSizeIterator for Bytes<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for Bytes<'a> {} + /// This macro generates a Clone impl for string pattern API /// wrapper types of the form X<'a, P> macro_rules! derive_pattern_clone { @@ -739,6 +748,13 @@ macro_rules! generate_pattern_iterators { } } + #[unstable(feature = "fused", issue = "35602")] + impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {} + + #[unstable(feature = "fused", issue = "35602")] + impl<'a, P: Pattern<'a>> FusedIterator for $reverse_iterator<'a, P> + where P::Searcher: ReverseSearcher<'a> {} + generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*, $forward_iterator, $reverse_iterator, $iterty); @@ -1088,6 +1104,9 @@ impl<'a> DoubleEndedIterator for Lines<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for Lines<'a> {} + /// Created with the method [`lines_any()`]. /// /// [`lines_any()`]: ../../std/primitive.str.html#method.lines_any @@ -1151,6 +1170,10 @@ impl<'a> DoubleEndedIterator for LinesAny<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +#[allow(deprecated)] +impl<'a> FusedIterator for LinesAny<'a> {} + /* Section: Comparing strings */ diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs index 81856cb87c7c4..c2b7d7045ddd8 100644 --- a/src/librustc_unicode/char.rs +++ b/src/librustc_unicode/char.rs @@ -29,6 +29,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::char::CharExt as C; +use core::iter::FusedIterator; use core::fmt; use tables::{conversions, derived_property, general_category, property}; @@ -62,6 +63,9 @@ impl Iterator for ToLowercase { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for ToLowercase {} + /// Returns an iterator that yields the uppercase equivalent of a `char`. /// /// This `struct` is created by the [`to_uppercase()`] method on [`char`]. See @@ -80,6 +84,8 @@ impl Iterator for ToUppercase { } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for ToUppercase {} enum CaseMappingIter { Three(char, char, char), diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs index 3ae905eba279b..b812c262ac197 100644 --- a/src/librustc_unicode/lib.rs +++ b/src/librustc_unicode/lib.rs @@ -35,6 +35,7 @@ #![feature(char_escape_debug)] #![feature(core_char_ext)] #![feature(decode_utf8)] +#![feature(fused)] #![feature(lang_items)] #![feature(staged_api)] #![feature(unicode)] diff --git a/src/librustc_unicode/u_str.rs b/src/librustc_unicode/u_str.rs index 0bac44b837ff2..eb5b6feeb7ec4 100644 --- a/src/librustc_unicode/u_str.rs +++ b/src/librustc_unicode/u_str.rs @@ -14,7 +14,7 @@ //! methods provided by the unicode parts of the CharExt trait. use core::char; -use core::iter::Filter; +use core::iter::{Filter, FusedIterator}; use core::str::Split; /// An iterator over the non-whitespace substrings of a string, @@ -177,6 +177,10 @@ impl Iterator for Utf16Encoder } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for Utf16Encoder + where I: FusedIterator {} + impl<'a> Iterator for SplitWhitespace<'a> { type Item = &'a str; @@ -189,3 +193,6 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { self.inner.next_back() } } + +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for SplitWhitespace<'a> {} diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 0db91034eb5ac..070d7ca1eef0f 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -16,6 +16,7 @@ use prelude::v1::*; use mem; use ops::Range; +use iter::FusedIterator; /// Extension methods for ASCII-subset only operations on string slices. /// @@ -368,6 +369,9 @@ impl DoubleEndedIterator for EscapeDefault { } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for EscapeDefault {} +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for EscapeDefault {} + static ASCII_LOWERCASE_MAP: [u8; 256] = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index cf6f76f914a15..d844a213ce251 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -15,7 +15,7 @@ use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; use hash::{Hash, Hasher, BuildHasher, SipHasher13}; -use iter::FromIterator; +use iter::{FromIterator, FusedIterator}; use mem::{self, replace}; use ops::{Deref, Index}; use rand::{self, Rng}; @@ -1484,6 +1484,9 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for IterMut<'a, K, V> { type Item = (&'a K, &'a mut V); @@ -1495,6 +1498,8 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { @@ -1507,6 +1512,8 @@ impl Iterator for IntoIter { impl ExactSizeIterator for IntoIter { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Keys<'a, K, V> { @@ -1519,6 +1526,8 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Values<'a, K, V> { @@ -1531,6 +1540,8 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Values<'a, K, V> {} #[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { @@ -1543,6 +1554,8 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Drain<'a, K, V> { @@ -1555,6 +1568,8 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} impl<'a, K, V> Entry<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 837c5d8b8e18c..96efff86abf17 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -11,7 +11,7 @@ use borrow::Borrow; use fmt; use hash::{Hash, BuildHasher}; -use iter::{Chain, FromIterator}; +use iter::{Chain, FromIterator, FusedIterator}; use ops::{BitOr, BitAnd, BitXor, Sub}; use super::Recover; @@ -906,6 +906,8 @@ impl<'a, K> Iterator for Iter<'a, K> { impl<'a, K> ExactSizeIterator for Iter<'a, K> { fn len(&self) -> usize { self.iter.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K> FusedIterator for Iter<'a, K> {} #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { @@ -918,6 +920,8 @@ impl Iterator for IntoIter { impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.iter.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K> Iterator for Drain<'a, K> { @@ -930,6 +934,8 @@ impl<'a, K> Iterator for Drain<'a, K> { impl<'a, K> ExactSizeIterator for Drain<'a, K> { fn len(&self) -> usize { self.iter.len() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, K> FusedIterator for Drain<'a, K> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Intersection<'a, T, S> { @@ -961,6 +967,11 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T, S> FusedIterator for Intersection<'a, T, S> + where T: Eq + Hash, S: BuildHasher +{} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Difference<'a, T, S> { fn clone(&self) -> Difference<'a, T, S> { @@ -991,6 +1002,11 @@ impl<'a, T, S> Iterator for Difference<'a, T, S> } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T, S> FusedIterator for Difference<'a, T, S> + where T: Eq + Hash, S: BuildHasher +{} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { fn clone(&self) -> SymmetricDifference<'a, T, S> { @@ -1008,11 +1024,21 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> + where T: Eq + Hash, S: BuildHasher +{} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Union<'a, T, S> { fn clone(&self) -> Union<'a, T, S> { Union { iter: self.iter.clone() } } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a, T, S> FusedIterator for Union<'a, T, S> + where T: Eq + Hash, S: BuildHasher +{} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for Union<'a, T, S> where T: Eq + Hash, S: BuildHasher diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c05e0c3ca68df..9807e383c5ca1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -232,6 +232,7 @@ #![feature(float_from_str_radix)] #![feature(fn_traits)] #![feature(fnbox)] +#![feature(fused)] #![feature(hashmap_hasher)] #![feature(heap_api)] #![feature(inclusive_range)] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 2d19561139b58..bc8fd66a438f5 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -107,7 +107,7 @@ use fmt; use fs; use hash::{Hash, Hasher}; use io; -use iter; +use iter::{self, FusedIterator}; use mem; use ops::{self, Deref}; use string::String; @@ -858,6 +858,9 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for Iter<'a> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Components<'a> { type Item = Component<'a>; @@ -958,6 +961,9 @@ impl<'a> DoubleEndedIterator for Components<'a> { } } +#[unstable(feature = "fused", issue = "35602")] +impl<'a> FusedIterator for Components<'a> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> cmp::PartialEq for Components<'a> { fn eq(&self, other: &Components<'a>) -> bool {