Skip to content

Commit a875876

Browse files
committed
Make Range implementation safe
1 parent 641c8cd commit a875876

File tree

3 files changed

+24
-31
lines changed

3 files changed

+24
-31
lines changed

compiler/rustc_index/src/vec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ macro_rules! newtype_index {
184184
}
185185
}
186186

187-
unsafe impl ::std::iter::Step for $type {
187+
impl ::std::iter::Step for $type {
188188
#[inline]
189189
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
190190
<usize as ::std::iter::Step>::steps_between(

library/core/src/iter/range.rs

+22-29
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,8 @@ use super::{FusedIterator, TrustedLen, TrustedRandomAccess};
99
///
1010
/// The *successor* operation moves towards values that compare greater.
1111
/// The *predecessor* operation moves towards values that compare lesser.
12-
///
13-
/// # Safety
14-
///
15-
/// This trait is `unsafe` because its implementation must be correct for
16-
/// the safety of `unsafe trait TrustedLen` implementations, and the results
17-
/// of using this trait can otherwise be trusted by `unsafe` code to be correct
18-
/// and fulfill the listed obligations.
1912
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
20-
pub unsafe trait Step: Clone + PartialOrd + Sized {
13+
pub trait Step: Clone + PartialOrd + Sized {
2114
/// Returns the number of *successor* steps required to get from `start` to `end`.
2215
///
2316
/// Returns `None` if the number of steps would overflow `usize`
@@ -237,7 +230,7 @@ macro_rules! step_integer_impls {
237230
$(
238231
#[allow(unreachable_patterns)]
239232
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
240-
unsafe impl Step for $u_narrower {
233+
impl Step for $u_narrower {
241234
step_identical_methods!();
242235

243236
#[inline]
@@ -269,7 +262,7 @@ macro_rules! step_integer_impls {
269262

270263
#[allow(unreachable_patterns)]
271264
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
272-
unsafe impl Step for $i_narrower {
265+
impl Step for $i_narrower {
273266
step_identical_methods!();
274267

275268
#[inline]
@@ -333,7 +326,7 @@ macro_rules! step_integer_impls {
333326
$(
334327
#[allow(unreachable_patterns)]
335328
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
336-
unsafe impl Step for $u_wider {
329+
impl Step for $u_wider {
337330
step_identical_methods!();
338331

339332
#[inline]
@@ -358,7 +351,7 @@ macro_rules! step_integer_impls {
358351

359352
#[allow(unreachable_patterns)]
360353
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
361-
unsafe impl Step for $i_wider {
354+
impl Step for $i_wider {
362355
step_identical_methods!();
363356

364357
#[inline]
@@ -408,7 +401,7 @@ step_integer_impls! {
408401
}
409402

410403
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
411-
unsafe impl Step for char {
404+
impl Step for char {
412405
#[inline]
413406
fn steps_between(&start: &char, &end: &char) -> Option<usize> {
414407
let start = start as u32;
@@ -519,8 +512,8 @@ impl<A: Step> Iterator for ops::Range<A> {
519512
#[inline]
520513
fn next(&mut self) -> Option<A> {
521514
if self.start < self.end {
522-
// SAFETY: just checked precondition
523-
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
515+
let n =
516+
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
524517
Some(mem::replace(&mut self.start, n))
525518
} else {
526519
None
@@ -541,8 +534,8 @@ impl<A: Step> Iterator for ops::Range<A> {
541534
fn nth(&mut self, n: usize) -> Option<A> {
542535
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
543536
if plus_n < self.end {
544-
// SAFETY: just checked precondition
545-
self.start = unsafe { Step::forward_unchecked(plus_n.clone(), 1) };
537+
self.start =
538+
Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld");
546539
return Some(plus_n);
547540
}
548541
}
@@ -632,8 +625,8 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
632625
#[inline]
633626
fn next_back(&mut self) -> Option<A> {
634627
if self.start < self.end {
635-
// SAFETY: just checked precondition
636-
self.end = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
628+
self.end =
629+
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
637630
Some(self.end.clone())
638631
} else {
639632
None
@@ -644,8 +637,8 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
644637
fn nth_back(&mut self, n: usize) -> Option<A> {
645638
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
646639
if minus_n > self.start {
647-
// SAFETY: just checked precondition
648-
self.end = unsafe { Step::backward_unchecked(minus_n, 1) };
640+
self.end =
641+
Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld");
649642
return Some(self.end.clone());
650643
}
651644
}
@@ -711,8 +704,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
711704
}
712705
let is_iterating = self.start < self.end;
713706
Some(if is_iterating {
714-
// SAFETY: just checked precondition
715-
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
707+
let n =
708+
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
716709
mem::replace(&mut self.start, n)
717710
} else {
718711
self.exhausted = true;
@@ -774,8 +767,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
774767
let mut accum = init;
775768

776769
while self.start < self.end {
777-
// SAFETY: just checked precondition
778-
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
770+
let n =
771+
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
779772
let n = mem::replace(&mut self.start, n);
780773
accum = f(accum, n)?;
781774
}
@@ -828,8 +821,8 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
828821
}
829822
let is_iterating = self.start < self.end;
830823
Some(if is_iterating {
831-
// SAFETY: just checked precondition
832-
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
824+
let n =
825+
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
833826
mem::replace(&mut self.end, n)
834827
} else {
835828
self.exhausted = true;
@@ -879,8 +872,8 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
879872
let mut accum = init;
880873

881874
while self.start < self.end {
882-
// SAFETY: just checked precondition
883-
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
875+
let n =
876+
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
884877
let n = mem::replace(&mut self.end, n);
885878
accum = f(accum, n)?;
886879
}

src/test/ui/impl-trait/example-calendar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate {
157157
}
158158
}
159159

160-
unsafe impl std::iter::Step for NaiveDate {
160+
impl std::iter::Step for NaiveDate {
161161
fn steps_between(_: &Self, _: &Self) -> Option<usize> {
162162
unimplemented!()
163163
}

0 commit comments

Comments
 (0)