88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ use convert:: TryFrom ;
1112use mem;
1213use ops:: { self , Add , Sub } ;
1314use usize;
@@ -21,7 +22,7 @@ use super::{FusedIterator, TrustedLen};
2122#[ unstable( feature = "step_trait" ,
2223 reason = "likely to be replaced by finer-grained traits" ,
2324 issue = "42168" ) ]
24- pub trait Step : PartialOrd + Sized {
25+ pub trait Step : Clone + PartialOrd + Sized {
2526 /// Returns the number of steps between two step objects. The count is
2627 /// inclusive of `start` and exclusive of `end`.
2728 ///
@@ -40,6 +41,9 @@ pub trait Step: PartialOrd + Sized {
4041
4142 /// Subtracts one to this step, returning the result
4243 fn sub_one ( & self ) -> Self ;
44+
45+ /// Add an usize, returning None on overflow
46+ fn add_usize ( & self , n : usize ) -> Option < Self > ;
4347}
4448
4549// These are still macro-generated because the integer literals resolve to different types.
@@ -84,12 +88,20 @@ macro_rules! step_impl_unsigned {
8488 }
8589 }
8690
91+ #[ inline]
92+ fn add_usize( & self , n: usize ) -> Option <Self > {
93+ match <$t>:: try_from( n) {
94+ Ok ( n_as_t) => self . checked_add( n_as_t) ,
95+ Err ( _) => None ,
96+ }
97+ }
98+
8799 step_identical_methods!( ) ;
88100 }
89101 ) * )
90102}
91103macro_rules! step_impl_signed {
92- ( $( $t: ty) * ) => ( $(
104+ ( $( [ $t: ty : $unsigned : ty ] ) * ) => ( $(
93105 #[ unstable( feature = "step_trait" ,
94106 reason = "likely to be replaced by finer-grained traits" ,
95107 issue = "42168" ) ]
@@ -107,6 +119,24 @@ macro_rules! step_impl_signed {
107119 }
108120 }
109121
122+ #[ inline]
123+ fn add_usize( & self , n: usize ) -> Option <Self > {
124+ match <$unsigned>:: try_from( n) {
125+ Ok ( n_as_unsigned) => {
126+ // Wrapping in unsigned space handles cases like
127+ // `-120_i8.add_usize(200) == Some(80_i8)`,
128+ // even though 200_usize is out of range for i8.
129+ let wrapped = ( * self as $unsigned) . wrapping_add( n_as_unsigned) as $t;
130+ if wrapped >= * self {
131+ Some ( wrapped)
132+ } else {
133+ None // Addition overflowed
134+ }
135+ }
136+ Err ( _) => None ,
137+ }
138+ }
139+
110140 step_identical_methods!( ) ;
111141 }
112142 ) * )
@@ -123,17 +153,22 @@ macro_rules! step_impl_no_between {
123153 None
124154 }
125155
156+ #[ inline]
157+ fn add_usize( & self , n: usize ) -> Option <Self > {
158+ self . checked_add( n as $t)
159+ }
160+
126161 step_identical_methods!( ) ;
127162 }
128163 ) * )
129164}
130165
131166step_impl_unsigned ! ( usize u8 u16 u32 ) ;
132- step_impl_signed ! ( isize i8 i16 i32 ) ;
167+ step_impl_signed ! ( [ isize : usize ] [ i8 : u8 ] [ i16 : u16 ] [ i32 : u32 ] ) ;
133168#[ cfg( target_pointer_width = "64" ) ]
134169step_impl_unsigned ! ( u64 ) ;
135170#[ cfg( target_pointer_width = "64" ) ]
136- step_impl_signed ! ( i64 ) ;
171+ step_impl_signed ! ( [ i64 : u64 ] ) ;
137172// If the target pointer width is not 64-bits, we
138173// assume here that it is less than 64-bits.
139174#[ cfg( not( target_pointer_width = "64" ) ) ]
@@ -194,6 +229,19 @@ impl<A: Step> Iterator for ops::Range<A> {
194229 None => ( 0 , None )
195230 }
196231 }
232+
233+ #[ inline]
234+ fn nth ( & mut self , n : usize ) -> Option < A > {
235+ if let Some ( plus_n) = self . start . add_usize ( n) {
236+ if plus_n < self . end {
237+ self . start = plus_n. add_one ( ) ;
238+ return Some ( plus_n)
239+ }
240+ }
241+
242+ self . start = self . end . clone ( ) ;
243+ None
244+ }
197245}
198246
199247// These macros generate `ExactSizeIterator` impls for various range types.
@@ -211,7 +259,7 @@ range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
211259range_incl_trusted_len_impl ! ( usize isize u8 i8 u16 i16 u32 i32 i64 u64 ) ;
212260
213261#[ stable( feature = "rust1" , since = "1.0.0" ) ]
214- impl < A : Step + Clone > DoubleEndedIterator for ops:: Range < A > {
262+ impl < A : Step > DoubleEndedIterator for ops:: Range < A > {
215263 #[ inline]
216264 fn next_back ( & mut self ) -> Option < A > {
217265 if self . start < self . end {
@@ -241,6 +289,13 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
241289 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
242290 ( usize:: MAX , None )
243291 }
292+
293+ #[ inline]
294+ fn nth ( & mut self , n : usize ) -> Option < A > {
295+ let plus_n = self . start . add_usize ( n) . expect ( "overflow in RangeFrom::nth" ) ;
296+ self . start = plus_n. add_one ( ) ;
297+ Some ( plus_n)
298+ }
244299}
245300
246301#[ unstable( feature = "fused" , issue = "35602" ) ]
@@ -279,6 +334,30 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
279334 None => ( 0 , None ) ,
280335 }
281336 }
337+
338+ #[ inline]
339+ fn nth ( & mut self , n : usize ) -> Option < A > {
340+ if let Some ( plus_n) = self . start . add_usize ( n) {
341+ use cmp:: Ordering :: * ;
342+
343+ match plus_n. partial_cmp ( & self . end ) {
344+ Some ( Less ) => {
345+ self . start = plus_n. add_one ( ) ;
346+ return Some ( plus_n)
347+ }
348+ Some ( Equal ) => {
349+ self . start . replace_one ( ) ;
350+ self . end . replace_zero ( ) ;
351+ return Some ( plus_n)
352+ }
353+ _ => { }
354+ }
355+ }
356+
357+ self . start . replace_one ( ) ;
358+ self . end . replace_zero ( ) ;
359+ None
360+ }
282361}
283362
284363#[ unstable( feature = "inclusive_range" , reason = "recently added, follows RFC" , issue = "28237" ) ]
0 commit comments