Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0ac7fca

Browse files
committedJul 24, 2017
Implement TrustedLen for ranges of all T: Step, make Step an unsafe trait.
1 parent 0a62269 commit 0ac7fca

File tree

2 files changed

+31
-44
lines changed

2 files changed

+31
-44
lines changed
 

‎src/libcore/iter/range.rs

+30-43
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,23 @@ use super::{FusedIterator, TrustedLen};
1717

1818
/// Objects that have a notion of *successor* and *predecessor*
1919
/// 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.
2023
#[unstable(feature = "step_trait",
2124
reason = "recently redesigned",
2225
issue = "42168")]
23-
pub trait Step: Clone + PartialOrd + Sized {
26+
pub unsafe trait Step: Clone + PartialOrd + Sized {
2427
/// Returns the number of *successor* steps needed to get from `start` to `end`.
2528
///
2629
/// Returns `None` if that number would overflow `usize`
2730
/// (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)`
2937
fn steps_between(start: &Self, end: &Self) -> Option<usize>;
3038

3139
/// Returns the value that would be obtained by taking the *successor* of `self`,
@@ -35,6 +43,10 @@ pub trait Step: Clone + PartialOrd + Sized {
3543
///
3644
/// Note: `step_count == 1` is a common case,
3745
/// 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)`
3850
fn forward(&self, step_count: usize) -> Option<Self>;
3951

4052
/// Returns the value that would be obtained by taking the *predecessor* of `self`,
@@ -44,6 +56,10 @@ pub trait Step: Clone + PartialOrd + Sized {
4456
///
4557
/// Note: `step_count == 1` is a common case,
4658
/// 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)`
4763
fn backward(&self, step_count: usize) -> Option<Self>;
4864
}
4965

@@ -58,11 +74,9 @@ macro_rules! step_integer_impls {
5874
#[unstable(feature = "step_trait",
5975
reason = "recently redesigned",
6076
issue = "42168")]
61-
impl Step for $narrower_unsigned {
77+
unsafe impl Step for $narrower_unsigned {
6278
#[inline]
6379
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
64-
// NOTE: the safety of `unsafe impl TrustedLen` depends on
65-
// this being correct!
6680
if *start < *end {
6781
// This relies on $narrower_unsigned <= usize
6882
Some((*end - *start) as usize)
@@ -91,11 +105,9 @@ macro_rules! step_integer_impls {
91105
#[unstable(feature = "step_trait",
92106
reason = "recently redesigned",
93107
issue = "42168")]
94-
impl Step for $narrower_signed {
108+
unsafe impl Step for $narrower_signed {
95109
#[inline]
96110
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
97-
// NOTE: the safety of `unsafe impl TrustedLen` depends on
98-
// this being correct!
99111
if *start < *end {
100112
// This relies on $narrower_signed <= usize
101113
//
@@ -157,11 +169,9 @@ macro_rules! step_integer_impls {
157169
#[unstable(feature = "step_trait",
158170
reason = "recently redesigned",
159171
issue = "42168")]
160-
impl Step for $wider_unsigned {
172+
unsafe impl Step for $wider_unsigned {
161173
#[inline]
162174
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
163-
// NOTE: the safety of `unsafe impl TrustedLen` depends on
164-
// this being correct!
165175
if *start < *end {
166176
usize::try_from(*end - *start).ok()
167177
} else {
@@ -183,11 +193,9 @@ macro_rules! step_integer_impls {
183193
#[unstable(feature = "step_trait",
184194
reason = "recently redesigned",
185195
issue = "42168")]
186-
impl Step for $wider_signed {
196+
unsafe impl Step for $wider_signed {
187197
#[inline]
188198
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
189-
// NOTE: the safety of `unsafe impl TrustedLen` depends on
190-
// this being correct!
191199
if *start < *end {
192200
match end.checked_sub(*start) {
193201
Some(diff) => usize::try_from(diff).ok(),
@@ -248,22 +256,6 @@ macro_rules! range_incl_exact_iter_impl {
248256
)*)
249257
}
250258

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-
267259
#[stable(feature = "rust1", since = "1.0.0")]
268260
impl<A: Step> Iterator for ops::Range<A> {
269261
type Item = A;
@@ -335,19 +327,6 @@ range_incl_exact_iter_impl! {
335327
i8
336328
}
337329

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-
351330
#[stable(feature = "rust1", since = "1.0.0")]
352331
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
353332
#[inline]
@@ -362,6 +341,9 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
362341
}
363342
}
364343

344+
#[unstable(feature = "trusted_len", issue = "37572")]
345+
unsafe impl<T: Step> TrustedLen for ops::Range<T> {}
346+
365347
#[unstable(feature = "fused", issue = "35602")]
366348
impl<A: Step> FusedIterator for ops::Range<A> {}
367349

@@ -507,5 +489,10 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
507489
}
508490
}
509491

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+
510497
#[unstable(feature = "fused", issue = "35602")]
511498
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}

‎src/test/run-pass/impl-trait/example-calendar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate {
161161
}
162162
}
163163

164-
impl std::iter::Step for NaiveDate {
164+
unsafe impl std::iter::Step for NaiveDate {
165165
fn steps_between(_: &Self, _: &Self) -> Option<usize> {
166166
unimplemented!()
167167
}

0 commit comments

Comments
 (0)
Please sign in to comment.