Skip to content

Rename slice::take... methods to split_off... #136555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions library/core/src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ pub use self::function::{Fn, FnMut, FnOnce};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::index::{Index, IndexMut};
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")]
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")]
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
Expand Down
46 changes: 42 additions & 4 deletions library/core/src/ops/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,20 +979,58 @@ 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
/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
/// but `..`, `d..e`, and `f..=g` do not.
///
/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
#[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")]
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")]
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")]
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)
}
}
69 changes: 35 additions & 34 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::intrinsics::{exact_div, unchecked_sub};
use crate::mem::{self, SizedTypeProperties};
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::simd::{self, Simd};
use crate::ub_checks::assert_unsafe_precondition;
Expand Down Expand Up @@ -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.
Copy link
Contributor

@thaliaarchi thaliaarchi Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, you missed the take and take_mut in this comment (not able to be shown in the snippet).

#[inline]
fn split_point_of(range: impl OneSidedRange<usize>) -> Option<(Direction, usize)> {
use Bound::*;

Some(match (range.start_bound(), range.end_bound()) {
(Unbounded, Excluded(i)) => (Direction::Front, *i),
(Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?),
(Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?),
(Included(i), Unbounded) => (Direction::Back, *i),
_ => unreachable!(),
use OneSidedRangeBound::{End, EndInclusive, StartInclusive};

Some(match range.bound() {
(StartInclusive, i) => (Direction::Back, i),
(End, i) => (Direction::Front, i),
(EndInclusive, i) => (Direction::Front, i.checked_add(1)?),
})
}

Expand Down Expand Up @@ -4294,25 +4292,25 @@ impl<T> [T] {
///
/// # Examples
///
/// Taking the first three elements of a slice:
/// Splitting off the first three elements of a slice:
///
/// ```
/// #![feature(slice_take)]
///
/// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
/// let mut first_three = slice.take(..3).unwrap();
/// let mut first_three = slice.split_off(..3).unwrap();
///
/// assert_eq!(slice, &['d']);
/// assert_eq!(first_three, &['a', 'b', 'c']);
/// ```
///
/// Taking the last two elements of a slice:
/// Splitting off the last two elements of a slice:
///
/// ```
/// #![feature(slice_take)]
///
/// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
/// let mut tail = slice.take(2..).unwrap();
/// let mut tail = slice.split_off(2..).unwrap();
///
/// assert_eq!(slice, &['a', 'b']);
/// assert_eq!(tail, &['c', 'd']);
Expand All @@ -4325,16 +4323,19 @@ impl<T> [T] {
///
/// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
///
/// assert_eq!(None, slice.take(5..));
/// assert_eq!(None, slice.take(..5));
/// assert_eq!(None, slice.take(..=4));
/// assert_eq!(None, slice.split_off(5..));
/// assert_eq!(None, slice.split_off(..5));
/// assert_eq!(None, slice.split_off(..=4));
/// let expected: &[char] = &['a', 'b', 'c', 'd'];
/// assert_eq!(Some(expected), slice.take(..4));
/// assert_eq!(Some(expected), slice.split_off(..4));
/// ```
#[inline]
#[must_use = "method does not modify the slice if the range is out of bounds"]
#[unstable(feature = "slice_take", issue = "62280")]
pub fn take<'a, R: OneSidedRange<usize>>(self: &mut &'a Self, range: R) -> Option<&'a Self> {
pub fn split_off<'a, R: OneSidedRange<usize>>(
self: &mut &'a Self,
range: R,
) -> Option<&'a Self> {
let (direction, split_index) = split_point_of(range)?;
if split_index > self.len() {
return None;
Expand Down Expand Up @@ -4363,13 +4364,13 @@ impl<T> [T] {
///
/// # Examples
///
/// Taking the first three elements of a slice:
/// Splitting off the first three elements of a slice:
///
/// ```
/// #![feature(slice_take)]
///
/// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
/// let mut first_three = slice.take_mut(..3).unwrap();
/// let mut first_three = slice.split_off_mut(..3).unwrap();
///
/// assert_eq!(slice, &mut ['d']);
/// assert_eq!(first_three, &mut ['a', 'b', 'c']);
Expand All @@ -4381,7 +4382,7 @@ impl<T> [T] {
/// #![feature(slice_take)]
///
/// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
/// let mut tail = slice.take_mut(2..).unwrap();
/// let mut tail = slice.split_off_mut(2..).unwrap();
///
/// assert_eq!(slice, &mut ['a', 'b']);
/// assert_eq!(tail, &mut ['c', 'd']);
Expand All @@ -4394,16 +4395,16 @@ impl<T> [T] {
///
/// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
///
/// assert_eq!(None, slice.take_mut(5..));
/// assert_eq!(None, slice.take_mut(..5));
/// assert_eq!(None, slice.take_mut(..=4));
/// assert_eq!(None, slice.split_off_mut(5..));
/// assert_eq!(None, slice.split_off_mut(..5));
/// assert_eq!(None, slice.split_off_mut(..=4));
/// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd'];
/// assert_eq!(Some(expected), slice.take_mut(..4));
/// assert_eq!(Some(expected), slice.split_off_mut(..4));
/// ```
#[inline]
#[must_use = "method does not modify the slice if the range is out of bounds"]
#[unstable(feature = "slice_take", issue = "62280")]
pub fn take_mut<'a, R: OneSidedRange<usize>>(
pub fn split_off_mut<'a, R: OneSidedRange<usize>>(
self: &mut &'a mut Self,
range: R,
) -> Option<&'a mut Self> {
Expand Down Expand Up @@ -4435,14 +4436,14 @@ impl<T> [T] {
/// #![feature(slice_take)]
///
/// let mut slice: &[_] = &['a', 'b', 'c'];
/// let first = slice.take_first().unwrap();
/// let first = slice.split_off_first().unwrap();
///
/// assert_eq!(slice, &['b', 'c']);
/// assert_eq!(first, &'a');
/// ```
#[inline]
#[unstable(feature = "slice_take", issue = "62280")]
pub fn take_first<'a>(self: &mut &'a Self) -> Option<&'a T> {
pub fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> {
let (first, rem) = self.split_first()?;
*self = rem;
Some(first)
Expand All @@ -4459,15 +4460,15 @@ impl<T> [T] {
/// #![feature(slice_take)]
///
/// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
/// let first = slice.take_first_mut().unwrap();
/// let first = slice.split_off_first_mut().unwrap();
/// *first = 'd';
///
/// assert_eq!(slice, &['b', 'c']);
/// assert_eq!(first, &'d');
/// ```
#[inline]
#[unstable(feature = "slice_take", issue = "62280")]
pub fn take_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
pub fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
let (first, rem) = mem::take(self).split_first_mut()?;
*self = rem;
Some(first)
Expand All @@ -4484,14 +4485,14 @@ impl<T> [T] {
/// #![feature(slice_take)]
///
/// let mut slice: &[_] = &['a', 'b', 'c'];
/// let last = slice.take_last().unwrap();
/// let last = slice.split_off_last().unwrap();
///
/// assert_eq!(slice, &['a', 'b']);
/// assert_eq!(last, &'c');
/// ```
#[inline]
#[unstable(feature = "slice_take", issue = "62280")]
pub fn take_last<'a>(self: &mut &'a Self) -> Option<&'a T> {
pub fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> {
let (last, rem) = self.split_last()?;
*self = rem;
Some(last)
Expand All @@ -4508,15 +4509,15 @@ impl<T> [T] {
/// #![feature(slice_take)]
///
/// let mut slice: &mut [_] = &mut ['a', 'b', 'c'];
/// let last = slice.take_last_mut().unwrap();
/// let last = slice.split_off_last_mut().unwrap();
/// *last = 'd';
///
/// assert_eq!(slice, &['a', 'b']);
/// assert_eq!(last, &'d');
/// ```
#[inline]
#[unstable(feature = "slice_take", issue = "62280")]
pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
pub fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> {
let (last, rem) = mem::take(self).split_last_mut()?;
*self = rem;
Some(last)
Expand Down
Loading
Loading