Make Range implementation safe

This commit is contained in:
Jacob Pratt
2021-04-01 05:06:28 -04:00
parent 641c8cd875
commit a875876027
3 changed files with 24 additions and 31 deletions
+1 -1
View File
@@ -184,7 +184,7 @@ fn index(self) -> usize {
}
}
unsafe impl ::std::iter::Step for $type {
impl ::std::iter::Step for $type {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
<usize as ::std::iter::Step>::steps_between(
+22 -29
View File
@@ -9,15 +9,8 @@
///
/// The *successor* operation moves towards values that compare greater.
/// The *predecessor* operation moves towards values that compare lesser.
///
/// # Safety
///
/// This trait is `unsafe` because its implementation must be correct for
/// the safety of `unsafe trait TrustedLen` implementations, and the results
/// of using this trait can otherwise be trusted by `unsafe` code to be correct
/// and fulfill the listed obligations.
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
pub unsafe trait Step: Clone + PartialOrd + Sized {
pub trait Step: Clone + PartialOrd + Sized {
/// Returns the number of *successor* steps required to get from `start` to `end`.
///
/// Returns `None` if the number of steps would overflow `usize`
@@ -237,7 +230,7 @@ macro_rules! step_integer_impls {
$(
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
unsafe impl Step for $u_narrower {
impl Step for $u_narrower {
step_identical_methods!();
#[inline]
@@ -269,7 +262,7 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
unsafe impl Step for $i_narrower {
impl Step for $i_narrower {
step_identical_methods!();
#[inline]
@@ -333,7 +326,7 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
$(
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
unsafe impl Step for $u_wider {
impl Step for $u_wider {
step_identical_methods!();
#[inline]
@@ -358,7 +351,7 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
#[allow(unreachable_patterns)]
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
unsafe impl Step for $i_wider {
impl Step for $i_wider {
step_identical_methods!();
#[inline]
@@ -408,7 +401,7 @@ fn backward_checked(start: Self, n: usize) -> Option<Self> {
}
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
unsafe impl Step for char {
impl Step for char {
#[inline]
fn steps_between(&start: &char, &end: &char) -> Option<usize> {
let start = start as u32;
@@ -519,8 +512,8 @@ impl<A: Step> Iterator for ops::Range<A> {
#[inline]
fn next(&mut self) -> Option<A> {
if self.start < self.end {
// SAFETY: just checked precondition
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
let n =
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
Some(mem::replace(&mut self.start, n))
} else {
None
@@ -541,8 +534,8 @@ fn size_hint(&self) -> (usize, Option<usize>) {
fn nth(&mut self, n: usize) -> Option<A> {
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
if plus_n < self.end {
// SAFETY: just checked precondition
self.start = unsafe { Step::forward_unchecked(plus_n.clone(), 1) };
self.start =
Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld");
return Some(plus_n);
}
}
@@ -632,8 +625,8 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
if self.start < self.end {
// SAFETY: just checked precondition
self.end = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
self.end =
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
Some(self.end.clone())
} else {
None
@@ -644,8 +637,8 @@ fn next_back(&mut self) -> Option<A> {
fn nth_back(&mut self, n: usize) -> Option<A> {
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
if minus_n > self.start {
// SAFETY: just checked precondition
self.end = unsafe { Step::backward_unchecked(minus_n, 1) };
self.end =
Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld");
return Some(self.end.clone());
}
}
@@ -711,8 +704,8 @@ fn next(&mut self) -> Option<A> {
}
let is_iterating = self.start < self.end;
Some(if is_iterating {
// SAFETY: just checked precondition
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
let n =
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
mem::replace(&mut self.start, n)
} else {
self.exhausted = true;
@@ -774,8 +767,8 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
let mut accum = init;
while self.start < self.end {
// SAFETY: just checked precondition
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
let n =
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
let n = mem::replace(&mut self.start, n);
accum = f(accum, n)?;
}
@@ -828,8 +821,8 @@ fn next_back(&mut self) -> Option<A> {
}
let is_iterating = self.start < self.end;
Some(if is_iterating {
// SAFETY: just checked precondition
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
let n =
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
mem::replace(&mut self.end, n)
} else {
self.exhausted = true;
@@ -879,8 +872,8 @@ fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
let mut accum = init;
while self.start < self.end {
// SAFETY: just checked precondition
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
let n =
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
let n = mem::replace(&mut self.end, n);
accum = f(accum, n)?;
}
+1 -1
View File
@@ -157,7 +157,7 @@ fn add(self, other: &'b NaiveDate) -> NaiveDate {
}
}
unsafe impl std::iter::Step for NaiveDate {
impl std::iter::Step for NaiveDate {
fn steps_between(_: &Self, _: &Self) -> Option<usize> {
unimplemented!()
}