Skip to content

Commit 6dd1c87

Browse files
cramertjgitbot
authored and
gitbot
committed
Add OneSidedRangeBound to eliminate panic in split_point_of
See discussion in https://github.com/rust-lang/rust/pull/88502/files#r760177240
1 parent 3aebe12 commit 6dd1c87

File tree

3 files changed

+51
-15
lines changed

3 files changed

+51
-15
lines changed

core/src/ops/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ pub use self::function::{Fn, FnMut, FnOnce};
182182
#[stable(feature = "rust1", since = "1.0.0")]
183183
pub use self::index::{Index, IndexMut};
184184
pub(crate) use self::index_range::IndexRange;
185-
#[unstable(feature = "one_sided_range", issue = "69780")]
186-
pub use self::range::OneSidedRange;
187185
#[stable(feature = "inclusive_range", since = "1.26.0")]
188186
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
187+
#[unstable(feature = "one_sided_range", issue = "69780")]
188+
pub use self::range::{OneSidedRange, OneSidedRangeBound};
189189
#[stable(feature = "rust1", since = "1.0.0")]
190190
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
191191
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]

core/src/ops/range.rs

+42-4
Original file line numberDiff line numberDiff line change
@@ -979,20 +979,58 @@ impl<T> RangeBounds<T> for RangeToInclusive<&T> {
979979
}
980980
}
981981

982+
/// An internal helper for `split_off` functions indicating
983+
/// which end a `OneSidedRange` is bounded on.
984+
#[unstable(feature = "one_sided_range", issue = "69780")]
985+
#[allow(missing_debug_implementations)]
986+
pub enum OneSidedRangeBound {
987+
/// The range is bounded inclusively from below and is unbounded above.
988+
StartInclusive,
989+
/// The range is bounded exclusively from above and is unbounded below.
990+
End,
991+
/// The range is bounded inclusively from above and is unbounded below.
992+
EndInclusive,
993+
}
994+
982995
/// `OneSidedRange` is implemented for built-in range types that are unbounded
983996
/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
984997
/// but `..`, `d..e`, and `f..=g` do not.
985998
///
986999
/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
9871000
/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
9881001
#[unstable(feature = "one_sided_range", issue = "69780")]
989-
pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> {}
1002+
pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> {
1003+
/// An internal-only helper function for `split_off` and
1004+
/// `split_off_mut` that returns the bound of the one-sided range.
1005+
fn bound(self) -> (OneSidedRangeBound, T);
1006+
}
9901007

9911008
#[unstable(feature = "one_sided_range", issue = "69780")]
992-
impl<T> OneSidedRange<T> for RangeTo<T> where Self: RangeBounds<T> {}
1009+
impl<T> OneSidedRange<T> for RangeTo<T>
1010+
where
1011+
Self: RangeBounds<T>,
1012+
{
1013+
fn bound(self) -> (OneSidedRangeBound, T) {
1014+
(OneSidedRangeBound::End, self.end)
1015+
}
1016+
}
9931017

9941018
#[unstable(feature = "one_sided_range", issue = "69780")]
995-
impl<T> OneSidedRange<T> for RangeFrom<T> where Self: RangeBounds<T> {}
1019+
impl<T> OneSidedRange<T> for RangeFrom<T>
1020+
where
1021+
Self: RangeBounds<T>,
1022+
{
1023+
fn bound(self) -> (OneSidedRangeBound, T) {
1024+
(OneSidedRangeBound::StartInclusive, self.start)
1025+
}
1026+
}
9961027

9971028
#[unstable(feature = "one_sided_range", issue = "69780")]
998-
impl<T> OneSidedRange<T> for RangeToInclusive<T> where Self: RangeBounds<T> {}
1029+
impl<T> OneSidedRange<T> for RangeToInclusive<T>
1030+
where
1031+
Self: RangeBounds<T>,
1032+
{
1033+
fn bound(self) -> (OneSidedRangeBound, T) {
1034+
(OneSidedRangeBound::EndInclusive, self.end)
1035+
}
1036+
}

core/src/slice/mod.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
1010
use crate::intrinsics::{exact_div, unchecked_sub};
1111
use crate::mem::{self, SizedTypeProperties};
1212
use crate::num::NonZero;
13-
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds, RangeInclusive};
13+
use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive};
1414
use crate::panic::const_panic;
1515
use crate::simd::{self, Simd};
1616
use crate::ub_checks::assert_unsafe_precondition;
@@ -83,14 +83,12 @@ pub use raw::{from_raw_parts, from_raw_parts_mut};
8383
/// which to split. Returns `None` if the split index would overflow.
8484
#[inline]
8585
fn split_point_of(range: impl OneSidedRange<usize>) -> Option<(Direction, usize)> {
86-
use Bound::*;
87-
88-
Some(match (range.start_bound(), range.end_bound()) {
89-
(Unbounded, Excluded(i)) => (Direction::Front, *i),
90-
(Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?),
91-
(Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?),
92-
(Included(i), Unbounded) => (Direction::Back, *i),
93-
_ => unreachable!(),
86+
use OneSidedRangeBound::{End, EndInclusive, StartInclusive};
87+
88+
Some(match range.bound() {
89+
(StartInclusive, i) => (Direction::Back, i),
90+
(End, i) => (Direction::Front, i),
91+
(EndInclusive, i) => (Direction::Front, i.checked_add(1)?),
9492
})
9593
}
9694

0 commit comments

Comments
 (0)