Add OneSidedRangeBound to eliminate panic in split_point_of
See discussion in https://github.com/rust-lang/rust/pull/88502/files#r760177240
This commit is contained in:
parent
07cf20e987
commit
836a989820
3 changed files with 50 additions and 14 deletions
|
@ -182,10 +182,10 @@ pub use self::function::{Fn, FnMut, FnOnce};
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::index::{Index, IndexMut};
|
pub use self::index::{Index, IndexMut};
|
||||||
pub(crate) use self::index_range::IndexRange;
|
pub(crate) use self::index_range::IndexRange;
|
||||||
#[unstable(feature = "one_sided_range", issue = "69780")]
|
|
||||||
pub use self::range::OneSidedRange;
|
|
||||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||||
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
|
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
|
||||||
|
#[unstable(feature = "one_sided_range", issue = "69780")]
|
||||||
|
pub use self::range::{OneSidedRange, OneSidedRangeBound};
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
|
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
|
||||||
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
|
||||||
|
|
|
@ -979,6 +979,19 @@ impl<T> RangeBounds<T> for RangeToInclusive<&T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An internal helper for `split_off` functions indicating
|
||||||
|
/// which end a `OneSidedRange` is bounded on.
|
||||||
|
#[unstable(feature = "one_sided_range", issue = "69780")]
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
|
pub enum OneSidedRangeBound {
|
||||||
|
/// The range is bounded inclusively from below and is unbounded above.
|
||||||
|
StartInclusive,
|
||||||
|
/// The range is bounded exclusively from above and is unbounded below.
|
||||||
|
End,
|
||||||
|
/// The range is bounded inclusively from above and is unbounded below.
|
||||||
|
EndInclusive,
|
||||||
|
}
|
||||||
|
|
||||||
/// `OneSidedRange` is implemented for built-in range types that are unbounded
|
/// `OneSidedRange` is implemented for built-in range types that are unbounded
|
||||||
/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
|
/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
|
||||||
/// but `..`, `d..e`, and `f..=g` do not.
|
/// but `..`, `d..e`, and `f..=g` do not.
|
||||||
|
@ -986,13 +999,38 @@ impl<T> RangeBounds<T> for RangeToInclusive<&T> {
|
||||||
/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
|
/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
|
||||||
/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
|
/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
|
||||||
#[unstable(feature = "one_sided_range", issue = "69780")]
|
#[unstable(feature = "one_sided_range", issue = "69780")]
|
||||||
pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> {}
|
pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> {
|
||||||
|
/// An internal-only helper function for `split_off` and
|
||||||
|
/// `split_off_mut` that returns the bound of the one-sided range.
|
||||||
|
fn bound(self) -> (OneSidedRangeBound, T);
|
||||||
|
}
|
||||||
|
|
||||||
#[unstable(feature = "one_sided_range", issue = "69780")]
|
#[unstable(feature = "one_sided_range", issue = "69780")]
|
||||||
impl<T> OneSidedRange<T> for RangeTo<T> where Self: RangeBounds<T> {}
|
impl<T> OneSidedRange<T> for RangeTo<T>
|
||||||
|
where
|
||||||
|
Self: RangeBounds<T>,
|
||||||
|
{
|
||||||
|
fn bound(self) -> (OneSidedRangeBound, T) {
|
||||||
|
(OneSidedRangeBound::End, self.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[unstable(feature = "one_sided_range", issue = "69780")]
|
#[unstable(feature = "one_sided_range", issue = "69780")]
|
||||||
impl<T> OneSidedRange<T> for RangeFrom<T> where Self: RangeBounds<T> {}
|
impl<T> OneSidedRange<T> for RangeFrom<T>
|
||||||
|
where
|
||||||
|
Self: RangeBounds<T>,
|
||||||
|
{
|
||||||
|
fn bound(self) -> (OneSidedRangeBound, T) {
|
||||||
|
(OneSidedRangeBound::StartInclusive, self.start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[unstable(feature = "one_sided_range", issue = "69780")]
|
#[unstable(feature = "one_sided_range", issue = "69780")]
|
||||||
impl<T> OneSidedRange<T> for RangeToInclusive<T> where Self: RangeBounds<T> {}
|
impl<T> OneSidedRange<T> for RangeToInclusive<T>
|
||||||
|
where
|
||||||
|
Self: RangeBounds<T>,
|
||||||
|
{
|
||||||
|
fn bound(self) -> (OneSidedRangeBound, T) {
|
||||||
|
(OneSidedRangeBound::EndInclusive, self.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||||
use crate::intrinsics::{exact_div, unchecked_sub};
|
use crate::intrinsics::{exact_div, unchecked_sub};
|
||||||
use crate::mem::{self, SizedTypeProperties};
|
use crate::mem::{self, SizedTypeProperties};
|
||||||
use crate::num::NonZero;
|
use crate::num::NonZero;
|
||||||
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds, RangeInclusive};
|
use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive};
|
||||||
use crate::panic::const_panic;
|
use crate::panic::const_panic;
|
||||||
use crate::simd::{self, Simd};
|
use crate::simd::{self, Simd};
|
||||||
use crate::ub_checks::assert_unsafe_precondition;
|
use crate::ub_checks::assert_unsafe_precondition;
|
||||||
|
@ -83,14 +83,12 @@ pub use raw::{from_raw_parts, from_raw_parts_mut};
|
||||||
/// which to split. Returns `None` if the split index would overflow.
|
/// which to split. Returns `None` if the split index would overflow.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn split_point_of(range: impl OneSidedRange<usize>) -> Option<(Direction, usize)> {
|
fn split_point_of(range: impl OneSidedRange<usize>) -> Option<(Direction, usize)> {
|
||||||
use Bound::*;
|
use OneSidedRangeBound::{End, EndInclusive, StartInclusive};
|
||||||
|
|
||||||
Some(match (range.start_bound(), range.end_bound()) {
|
Some(match range.bound() {
|
||||||
(Unbounded, Excluded(i)) => (Direction::Front, *i),
|
(StartInclusive, i) => (Direction::Back, i),
|
||||||
(Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?),
|
(End, i) => (Direction::Front, i),
|
||||||
(Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?),
|
(EndInclusive, i) => (Direction::Front, i.checked_add(1)?),
|
||||||
(Included(i), Unbounded) => (Direction::Back, *i),
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue