@@ -65,7 +65,7 @@ the rest of the rust manuals.
65
65
*/
66
66
67
67
use cmp;
68
- use num:: { Zero , One , Integer , CheckedAdd , CheckedSub , Saturating } ;
68
+ use num:: { Zero , One , Integer , CheckedAdd , CheckedSub , Saturating , ToPrimitive } ;
69
69
use option:: { Option , Some , None } ;
70
70
use ops:: { Add , Mul , Sub } ;
71
71
use cmp:: { Eq , Ord } ;
@@ -1829,7 +1829,8 @@ pub fn range<A: Add<A, A> + Ord + Clone + One>(start: A, stop: A) -> Range<A> {
1829
1829
Range { state : start, stop : stop, one : One :: one ( ) }
1830
1830
}
1831
1831
1832
- impl < A : Add < A , A > + Ord + Clone > Iterator < A > for Range < A > {
1832
+ // FIXME: #10414: Unfortunate type bound
1833
+ impl < A : Add < A , A > + Ord + Clone + ToPrimitive > Iterator < A > for Range < A > {
1833
1834
#[ inline]
1834
1835
fn next ( & mut self ) -> Option < A > {
1835
1836
if self . state < self . stop {
@@ -1841,13 +1842,42 @@ impl<A: Add<A, A> + Ord + Clone> Iterator<A> for Range<A> {
1841
1842
}
1842
1843
}
1843
1844
1844
- // FIXME: #8606 Implement size_hint() on Range
1845
- // Blocked on #8605 Need numeric trait for converting to `Option<uint>`
1845
+ #[ inline]
1846
+ fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1847
+ // This first checks if the elements are representable as i64. If they aren't, try u64 (to
1848
+ // handle cases like range(huge, huger)). We don't use uint/int because the difference of
1849
+ // the i64/u64 might lie within their range.
1850
+ let bound = match self . state . to_i64 ( ) {
1851
+ Some ( a) => {
1852
+ let sz = self . stop . to_i64 ( ) . map ( |b| b. checked_sub ( & a) ) ;
1853
+ match sz {
1854
+ Some ( Some ( bound) ) => bound. to_uint ( ) ,
1855
+ _ => None ,
1856
+ }
1857
+ } ,
1858
+ None => match self . state . to_u64 ( ) {
1859
+ Some ( a) => {
1860
+ let sz = self . stop . to_u64 ( ) . map ( |b| b. checked_sub ( & a) ) ;
1861
+ match sz {
1862
+ Some ( Some ( bound) ) => bound. to_uint ( ) ,
1863
+ _ => None
1864
+ }
1865
+ } ,
1866
+ None => None
1867
+ }
1868
+ } ;
1869
+
1870
+ match bound {
1871
+ Some ( b) => ( b, Some ( b) ) ,
1872
+ // Standard fallback for unbounded/unrepresentable bounds
1873
+ None => ( 0 , None )
1874
+ }
1875
+ }
1846
1876
}
1847
1877
1848
1878
/// `Integer` is required to ensure the range will be the same regardless of
1849
1879
/// the direction it is consumed.
1850
- impl < A : Integer + Ord + Clone > DoubleEndedIterator < A > for Range < A > {
1880
+ impl < A : Integer + Ord + Clone + ToPrimitive > DoubleEndedIterator < A > for Range < A > {
1851
1881
#[ inline]
1852
1882
fn next_back ( & mut self ) -> Option < A > {
1853
1883
if self . stop > self . state {
@@ -1868,11 +1898,12 @@ pub struct RangeInclusive<A> {
1868
1898
1869
1899
/// Return an iterator over the range [start, stop]
1870
1900
#[ inline]
1871
- pub fn range_inclusive < A : Add < A , A > + Ord + Clone + One > ( start : A , stop : A ) -> RangeInclusive < A > {
1901
+ pub fn range_inclusive < A : Add < A , A > + Ord + Clone + One + ToPrimitive > ( start : A , stop : A )
1902
+ -> RangeInclusive < A > {
1872
1903
RangeInclusive { range : range ( start, stop) , done : false }
1873
1904
}
1874
1905
1875
- impl < A : Add < A , A > + Eq + Ord + Clone > Iterator < A > for RangeInclusive < A > {
1906
+ impl < A : Add < A , A > + Eq + Ord + Clone + ToPrimitive > Iterator < A > for RangeInclusive < A > {
1876
1907
#[ inline]
1877
1908
fn next ( & mut self ) -> Option < A > {
1878
1909
match self . range . next ( ) {
@@ -1904,7 +1935,8 @@ impl<A: Add<A, A> + Eq + Ord + Clone> Iterator<A> for RangeInclusive<A> {
1904
1935
}
1905
1936
}
1906
1937
1907
- impl < A : Sub < A , A > + Integer + Ord + Clone > DoubleEndedIterator < A > for RangeInclusive < A > {
1938
+ impl < A : Sub < A , A > + Integer + Ord + Clone + ToPrimitive > DoubleEndedIterator < A >
1939
+ for RangeInclusive < A > {
1908
1940
#[ inline]
1909
1941
fn next_back ( & mut self ) -> Option < A > {
1910
1942
if self . range . stop > self . range . state {
@@ -2184,6 +2216,7 @@ mod tests {
2184
2216
2185
2217
use cmp;
2186
2218
use uint;
2219
+ use num;
2187
2220
2188
2221
#[ test]
2189
2222
fn test_counter_from_iter ( ) {
@@ -2801,12 +2834,51 @@ mod tests {
2801
2834
2802
2835
#[ test]
2803
2836
fn test_range ( ) {
2837
+ /// A mock type to check Range when ToPrimitive returns None
2838
+ struct Foo ;
2839
+
2840
+ impl ToPrimitive for Foo {
2841
+ fn to_i64 ( & self ) -> Option < i64 > { None }
2842
+ fn to_u64 ( & self ) -> Option < u64 > { None }
2843
+ }
2844
+
2845
+ impl Add < Foo , Foo > for Foo {
2846
+ fn add ( & self , _: & Foo ) -> Foo {
2847
+ Foo
2848
+ }
2849
+ }
2850
+
2851
+ impl Ord for Foo {
2852
+ fn lt ( & self , _: & Foo ) -> bool {
2853
+ false
2854
+ }
2855
+ }
2856
+
2857
+ impl Clone for Foo {
2858
+ fn clone ( & self ) -> Foo {
2859
+ Foo
2860
+ }
2861
+ }
2862
+
2863
+ impl num:: One for Foo {
2864
+ fn one ( ) -> Foo {
2865
+ Foo
2866
+ }
2867
+ }
2868
+
2804
2869
assert_eq ! ( range( 0 i, 5 ) . collect:: <~[ int] >( ) , ~[ 0 i, 1 , 2 , 3 , 4 ] ) ;
2870
+ assert_eq ! ( range( -10 i, -1 ) . collect:: <~[ int] >( ) , ~[ -10 , -9 , -8 , -7 , -6 , -5 , -4 , -3 , -2 ] ) ;
2805
2871
assert_eq ! ( range( 0 i, 5 ) . invert( ) . collect:: <~[ int] >( ) , ~[ 4 , 3 , 2 , 1 , 0 ] ) ;
2806
2872
assert_eq ! ( range( 200 , -5 ) . collect:: <~[ int] >( ) , ~[ ] ) ;
2807
2873
assert_eq ! ( range( 200 , -5 ) . invert( ) . collect:: <~[ int] >( ) , ~[ ] ) ;
2808
2874
assert_eq ! ( range( 200 , 200 ) . collect:: <~[ int] >( ) , ~[ ] ) ;
2809
2875
assert_eq ! ( range( 200 , 200 ) . invert( ) . collect:: <~[ int] >( ) , ~[ ] ) ;
2876
+
2877
+ assert_eq ! ( range( 0 i, 100 ) . size_hint( ) , ( 100 , Some ( 100 ) ) ) ;
2878
+ // this test is only meaningful when sizeof uint < sizeof u64
2879
+ assert_eq ! ( range( uint:: max_value - 1 , uint:: max_value) . size_hint( ) , ( 1 , Some ( 1 ) ) ) ;
2880
+ assert_eq ! ( range( -10 i, -1 ) . size_hint( ) , ( 9 , Some ( 9 ) ) ) ;
2881
+ assert_eq ! ( range( Foo , Foo ) . size_hint( ) , ( 0 , None ) ) ;
2810
2882
}
2811
2883
2812
2884
#[ test]
0 commit comments