10
10
11
11
use convert:: TryFrom ;
12
12
use mem;
13
- use ops:: { self , Add , Sub } ;
13
+ use ops;
14
14
use usize;
15
15
16
16
use super :: { FusedIterator , TrustedLen } ;
@@ -36,14 +36,11 @@ pub trait Step: Clone + PartialOrd + Sized {
36
36
/// Replaces this step with `0`, returning itself
37
37
fn replace_zero ( & mut self ) -> Self ;
38
38
39
- /// Adds one to this step, returning the result
40
- fn add_one ( & self ) -> Self ;
41
-
42
- /// Subtracts one to this step, returning the result
43
- fn sub_one ( & self ) -> Self ;
44
-
45
39
/// Add an usize, returning None on overflow
46
40
fn add_usize ( & self , n : usize ) -> Option < Self > ;
41
+
42
+ /// Subtracts an usize, returning None on overflow
43
+ fn sub_usize ( & self , n : usize ) -> Option < Self > ;
47
44
}
48
45
49
46
// These are still macro-generated because the integer literals resolve to different types.
@@ -58,16 +55,6 @@ macro_rules! step_identical_methods {
58
55
fn replace_zero( & mut self ) -> Self {
59
56
mem:: replace( self , 0 )
60
57
}
61
-
62
- #[ inline]
63
- fn add_one( & self ) -> Self {
64
- Add :: add( * self , 1 )
65
- }
66
-
67
- #[ inline]
68
- fn sub_one( & self ) -> Self {
69
- Sub :: sub( * self , 1 )
70
- }
71
58
}
72
59
}
73
60
@@ -96,6 +83,14 @@ macro_rules! step_impl_unsigned {
96
83
}
97
84
}
98
85
86
+ #[ inline]
87
+ fn sub_usize( & self , n: usize ) -> Option <Self > {
88
+ match <$t>:: try_from( n) {
89
+ Ok ( n_as_t) => self . checked_sub( n_as_t) ,
90
+ Err ( _) => None ,
91
+ }
92
+ }
93
+
99
94
step_identical_methods!( ) ;
100
95
}
101
96
) * )
@@ -136,6 +131,23 @@ macro_rules! step_impl_signed {
136
131
Err ( _) => None ,
137
132
}
138
133
}
134
+ #[ inline]
135
+ fn sub_usize( & self , n: usize ) -> Option <Self > {
136
+ match <$unsigned>:: try_from( n) {
137
+ Ok ( n_as_unsigned) => {
138
+ // Wrapping in unsigned space handles cases like
139
+ // `-120_i8.add_usize(200) == Some(80_i8)`,
140
+ // even though 200_usize is out of range for i8.
141
+ let wrapped = ( * self as $unsigned) . wrapping_sub( n_as_unsigned) as $t;
142
+ if wrapped <= * self {
143
+ Some ( wrapped)
144
+ } else {
145
+ None // Subtraction underflowed
146
+ }
147
+ }
148
+ Err ( _) => None ,
149
+ }
150
+ }
139
151
140
152
step_identical_methods!( ) ;
141
153
}
@@ -158,6 +170,11 @@ macro_rules! step_impl_no_between {
158
170
self . checked_add( n as $t)
159
171
}
160
172
173
+ #[ inline]
174
+ fn sub_usize( & self , n: usize ) -> Option <Self > {
175
+ self . checked_sub( n as $t)
176
+ }
177
+
161
178
step_identical_methods!( ) ;
162
179
}
163
180
) * )
@@ -214,7 +231,8 @@ impl<A: Step> Iterator for ops::Range<A> {
214
231
#[ inline]
215
232
fn next ( & mut self ) -> Option < A > {
216
233
if self . start < self . end {
217
- let mut n = self . start . add_one ( ) ;
234
+ // `start + 1` should not overflow since `end` exists such that `start < end`
235
+ let mut n = self . start . add_usize ( 1 ) . expect ( "overflow in Range::next" ) ;
218
236
mem:: swap ( & mut n, & mut self . start ) ;
219
237
Some ( n)
220
238
} else {
@@ -234,7 +252,8 @@ impl<A: Step> Iterator for ops::Range<A> {
234
252
fn nth ( & mut self , n : usize ) -> Option < A > {
235
253
if let Some ( plus_n) = self . start . add_usize ( n) {
236
254
if plus_n < self . end {
237
- self . start = plus_n. add_one ( ) ;
255
+ // `plus_n + 1` should not overflow since `end` exists such that `plus_n < end`
256
+ self . start = plus_n. add_usize ( 1 ) . expect ( "overflow in Range::nth" ) ;
238
257
return Some ( plus_n)
239
258
}
240
259
}
@@ -263,7 +282,8 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
263
282
#[ inline]
264
283
fn next_back ( & mut self ) -> Option < A > {
265
284
if self . start < self . end {
266
- self . end = self . end . sub_one ( ) ;
285
+ // `end - 1` should not overflow since `start` exists such that `start < end`
286
+ self . end = self . end . sub_usize ( 1 ) . expect ( "overflow in Range::nth_back" ) ;
267
287
Some ( self . end . clone ( ) )
268
288
} else {
269
289
None
@@ -280,7 +300,8 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
280
300
281
301
#[ inline]
282
302
fn next ( & mut self ) -> Option < A > {
283
- let mut n = self . start . add_one ( ) ;
303
+ // Overflow can happen here. Panic when it does.
304
+ let mut n = self . start . add_usize ( 1 ) . expect ( "overflow in RangeFrom::next" ) ;
284
305
mem:: swap ( & mut n, & mut self . start ) ;
285
306
Some ( n)
286
307
}
@@ -292,8 +313,9 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
292
313
293
314
#[ inline]
294
315
fn nth ( & mut self , n : usize ) -> Option < A > {
316
+ // Overflow can happen here. Panic when it does.
295
317
let plus_n = self . start . add_usize ( n) . expect ( "overflow in RangeFrom::nth" ) ;
296
- self . start = plus_n. add_one ( ) ;
318
+ self . start = plus_n. add_usize ( 1 ) . expect ( "overflow in RangeFrom::nth" ) ;
297
319
Some ( plus_n)
298
320
}
299
321
}
@@ -311,7 +333,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
311
333
312
334
match self . start . partial_cmp ( & self . end ) {
313
335
Some ( Less ) => {
314
- let n = self . start . add_one ( ) ;
336
+ // `start + 1` should not overflow since `end` exists such that `start < end`
337
+ let n = self . start . add_usize ( 1 ) . expect ( "overflow in RangeInclusive::next" ) ;
315
338
Some ( mem:: replace ( & mut self . start , n) )
316
339
} ,
317
340
Some ( Equal ) => {
@@ -342,7 +365,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
342
365
343
366
match plus_n. partial_cmp ( & self . end ) {
344
367
Some ( Less ) => {
345
- self . start = plus_n. add_one ( ) ;
368
+ // `plus_n + 1` should not overflow since `end` exists such that `plus_n < end`
369
+ self . start = plus_n. add_usize ( 1 ) . expect ( "overflow in RangeInclusive::nth" ) ;
346
370
return Some ( plus_n)
347
371
}
348
372
Some ( Equal ) => {
@@ -368,7 +392,8 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
368
392
369
393
match self . start . partial_cmp ( & self . end ) {
370
394
Some ( Less ) => {
371
- let n = self . end . sub_one ( ) ;
395
+ // `end - 1` should not overflow since `start` exists such that `start < end`
396
+ let n = self . end . sub_usize ( 1 ) . expect ( "overflow in RangeInclusive::next_back" ) ;
372
397
Some ( mem:: replace ( & mut self . end , n) )
373
398
} ,
374
399
Some ( Equal ) => {
0 commit comments