@@ -17,15 +17,23 @@ use super::{FusedIterator, TrustedLen};
17
17
18
18
/// Objects that have a notion of *successor* and *predecessor*
19
19
/// for the purpose of range iterators.
20
+ ///
21
+ /// This trait is `unsafe` because implementations of the `unsafe` trait `TrustedLen`
22
+ /// depend on its implementations being correct.
20
23
#[ unstable( feature = "step_trait" ,
21
24
reason = "recently redesigned" ,
22
25
issue = "42168" ) ]
23
- pub trait Step : Clone + PartialOrd + Sized {
26
+ pub unsafe trait Step : Clone + PartialOrd + Sized {
24
27
/// Returns the number of *successor* steps needed to get from `start` to `end`.
25
28
///
26
29
/// Returns `None` if that number would overflow `usize`
27
30
/// (or is infinite, if `end` would never be reached).
28
- /// Returns `Some(0)` if `start` comes after (is greater than) or equals `end`.
31
+ ///
32
+ /// This must hold for any `a`, `b`, and `n`:
33
+ ///
34
+ /// * `steps_between(&a, &b) == Some(0)` if and only if `a >= b`.
35
+ /// * `steps_between(&a, &b) == Some(n)` if and only if `a.forward(n) == Some(b)`
36
+ /// * `steps_between(&a, &b) == Some(n)` if and only if `b.backward(n) == Some(a)`
29
37
fn steps_between ( start : & Self , end : & Self ) -> Option < usize > ;
30
38
31
39
/// Returns the value that would be obtained by taking the *successor* of `self`,
@@ -35,6 +43,10 @@ pub trait Step: Clone + PartialOrd + Sized {
35
43
///
36
44
/// Note: `step_count == 1` is a common case,
37
45
/// used for example in `Iterator::next` for ranges.
46
+ ///
47
+ /// This must hold for any `a`, `n`, and `m` where `n + m` doesn’t overflow:
48
+ ///
49
+ /// * `a.forward(n).and_then(|x| x.forward(m)) == a.forward(n + m)`
38
50
fn forward ( & self , step_count : usize ) -> Option < Self > ;
39
51
40
52
/// Returns the value that would be obtained by taking the *predecessor* of `self`,
@@ -44,6 +56,10 @@ pub trait Step: Clone + PartialOrd + Sized {
44
56
///
45
57
/// Note: `step_count == 1` is a common case,
46
58
/// used for example in `Iterator::next_back` for ranges.
59
+ ///
60
+ /// This must hold for any `a`, `n`, and `m` where `n + m` doesn’t overflow:
61
+ ///
62
+ /// * `a.backward(n).and_then(|x| x.backward(m)) == a.backward(n + m)`
47
63
fn backward ( & self , step_count : usize ) -> Option < Self > ;
48
64
}
49
65
@@ -58,11 +74,9 @@ macro_rules! step_integer_impls {
58
74
#[ unstable( feature = "step_trait" ,
59
75
reason = "recently redesigned" ,
60
76
issue = "42168" ) ]
61
- impl Step for $narrower_unsigned {
77
+ unsafe impl Step for $narrower_unsigned {
62
78
#[ inline]
63
79
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
64
- // NOTE: the safety of `unsafe impl TrustedLen` depends on
65
- // this being correct!
66
80
if * start < * end {
67
81
// This relies on $narrower_unsigned <= usize
68
82
Some ( ( * end - * start) as usize )
@@ -91,11 +105,9 @@ macro_rules! step_integer_impls {
91
105
#[ unstable( feature = "step_trait" ,
92
106
reason = "recently redesigned" ,
93
107
issue = "42168" ) ]
94
- impl Step for $narrower_signed {
108
+ unsafe impl Step for $narrower_signed {
95
109
#[ inline]
96
110
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
97
- // NOTE: the safety of `unsafe impl TrustedLen` depends on
98
- // this being correct!
99
111
if * start < * end {
100
112
// This relies on $narrower_signed <= usize
101
113
//
@@ -157,11 +169,9 @@ macro_rules! step_integer_impls {
157
169
#[ unstable( feature = "step_trait" ,
158
170
reason = "recently redesigned" ,
159
171
issue = "42168" ) ]
160
- impl Step for $wider_unsigned {
172
+ unsafe impl Step for $wider_unsigned {
161
173
#[ inline]
162
174
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
163
- // NOTE: the safety of `unsafe impl TrustedLen` depends on
164
- // this being correct!
165
175
if * start < * end {
166
176
usize :: try_from( * end - * start) . ok( )
167
177
} else {
@@ -183,11 +193,9 @@ macro_rules! step_integer_impls {
183
193
#[ unstable( feature = "step_trait" ,
184
194
reason = "recently redesigned" ,
185
195
issue = "42168" ) ]
186
- impl Step for $wider_signed {
196
+ unsafe impl Step for $wider_signed {
187
197
#[ inline]
188
198
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
189
- // NOTE: the safety of `unsafe impl TrustedLen` depends on
190
- // this being correct!
191
199
if * start < * end {
192
200
match end. checked_sub( * start) {
193
201
Some ( diff) => usize :: try_from( diff) . ok( ) ,
@@ -248,22 +256,6 @@ macro_rules! range_incl_exact_iter_impl {
248
256
) * )
249
257
}
250
258
251
- macro_rules! range_trusted_len_impl {
252
- ( $( $t: ty) * ) => ( $(
253
- #[ unstable( feature = "trusted_len" , issue = "37572" ) ]
254
- unsafe impl TrustedLen for ops:: Range <$t> { }
255
- ) * )
256
- }
257
-
258
- macro_rules! range_incl_trusted_len_impl {
259
- ( $( $t: ty) * ) => ( $(
260
- #[ unstable( feature = "inclusive_range" ,
261
- reason = "recently added, follows RFC" ,
262
- issue = "28237" ) ]
263
- unsafe impl TrustedLen for ops:: RangeInclusive <$t> { }
264
- ) * )
265
- }
266
-
267
259
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
268
260
impl < A : Step > Iterator for ops:: Range < A > {
269
261
type Item = A ;
@@ -335,19 +327,6 @@ range_incl_exact_iter_impl! {
335
327
i8
336
328
}
337
329
338
- // These macros generate `TrustedLen` impls.
339
- //
340
- // They need to guarantee that .size_hint() is either exact, or that
341
- // the upper bound is None when it does not fit the type limits.
342
- range_trusted_len_impl ! {
343
- usize u8 u16 u32 u64 u128
344
- isize i8 i16 i32 i64 i128
345
- }
346
- range_incl_trusted_len_impl ! {
347
- usize u8 u16 u32 u64 u128
348
- isize i8 i16 i32 i64 i128
349
- }
350
-
351
330
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
352
331
impl < A : Step > DoubleEndedIterator for ops:: Range < A > {
353
332
#[ inline]
@@ -362,6 +341,9 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
362
341
}
363
342
}
364
343
344
+ #[ unstable( feature = "trusted_len" , issue = "37572" ) ]
345
+ unsafe impl < T : Step > TrustedLen for ops:: Range < T > { }
346
+
365
347
#[ unstable( feature = "fused" , issue = "35602" ) ]
366
348
impl < A : Step > FusedIterator for ops:: Range < A > { }
367
349
@@ -507,5 +489,10 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
507
489
}
508
490
}
509
491
492
+ #[ unstable( feature = "inclusive_range" ,
493
+ reason = "recently added, follows RFC" ,
494
+ issue = "28237" ) ]
495
+ unsafe impl < T : Step > TrustedLen for ops:: RangeInclusive < T > { }
496
+
510
497
#[ unstable( feature = "fused" , issue = "35602" ) ]
511
498
impl < A : Step > FusedIterator for ops:: RangeInclusive < A > { }
0 commit comments