Skip to content

Commit 274e299

Browse files
committed
Stablize slice::strip_prefix and strip_suffix, with SlicePattern
We hope later to extend `core::str::Pattern` to slices too, perhaps as part of stabilising that. We want to minimise the amount of type inference breakage when we do that, so we don't want to stabilise strip_prefix and strip_suffix taking a simple `&[T]`. @KodrAus suggested the approach of introducing a new perma-unstable trait, which reduces this future inference break risk. I found it necessary to make two impls of this trait, as the unsize coercion don't apply when hunting for trait implementations. Since SlicePattern's only method returns a reference, and the whole trait is just a wrapper for slices, I made the trait type be the non-reference type [T] or [T;N] rather than the reference. Otherwise the trait would have a lifetime parameter. I marked both the no-op conversion functions `#[inline]`. I'm not sure if that is necessary but it seemed at the very least harmless. Signed-off-by: Ian Jackson <[email protected]>
1 parent 0b644e4 commit 274e299

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

library/core/src/slice/mod.rs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,20 +1778,21 @@ impl<T> [T] {
17781778
/// # Examples
17791779
///
17801780
/// ```
1781-
/// #![feature(slice_strip)]
17821781
/// let v = &[10, 40, 30];
17831782
/// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
17841783
/// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
17851784
/// assert_eq!(v.strip_prefix(&[50]), None);
17861785
/// assert_eq!(v.strip_prefix(&[10, 50]), None);
17871786
/// ```
17881787
#[must_use = "returns the subslice without modifying the original"]
1789-
#[unstable(feature = "slice_strip", issue = "73413")]
1790-
pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
1788+
#[stable(feature = "slice_strip", since = "1.50.0")]
1789+
pub fn strip_prefix<P: SlicePattern<Item = T>>(&self, prefix: &P) -> Option<&[T]>
17911790
where
17921791
T: PartialEq,
17931792
{
1794-
let n = prefix.len();
1793+
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
1794+
let prefix = prefix.as_slice();
1795+
let n = prefix.as_slice().len();
17951796
if n <= self.len() {
17961797
let (head, tail) = self.split_at(n);
17971798
if head == prefix {
@@ -1811,19 +1812,20 @@ impl<T> [T] {
18111812
/// # Examples
18121813
///
18131814
/// ```
1814-
/// #![feature(slice_strip)]
18151815
/// let v = &[10, 40, 30];
18161816
/// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
18171817
/// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
18181818
/// assert_eq!(v.strip_suffix(&[50]), None);
18191819
/// assert_eq!(v.strip_suffix(&[50, 30]), None);
18201820
/// ```
18211821
#[must_use = "returns the subslice without modifying the original"]
1822-
#[unstable(feature = "slice_strip", issue = "73413")]
1823-
pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
1822+
#[stable(feature = "slice_strip", since = "1.50.0")]
1823+
pub fn strip_suffix<P: SlicePattern<Item = T>>(&self, suffix: &P) -> Option<&[T]>
18241824
where
18251825
T: PartialEq,
18261826
{
1827+
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
1828+
let suffix = suffix.as_slice();
18271829
let (len, n) = (self.len(), suffix.len());
18281830
if n <= len {
18291831
let (head, tail) = self.split_at(len - n);
@@ -3216,3 +3218,35 @@ impl<T> Default for &mut [T] {
32163218
&mut []
32173219
}
32183220
}
3221+
3222+
#[unstable(feature = "x", issue = "none")]
3223+
/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`. At a future
3224+
/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to
3225+
/// `str`) to slices, and then this trait will be replaced or abolished.
3226+
pub trait SlicePattern {
3227+
/// The element type of the slice being matched on.
3228+
type Item;
3229+
3230+
/// Currently, the consumers of `SlicePattern` need a slice.
3231+
fn as_slice(&self) -> &[Self::Item];
3232+
}
3233+
3234+
#[stable(feature = "slice_strip", since = "1.50.0")]
3235+
impl<T> SlicePattern for [T] {
3236+
type Item = T;
3237+
3238+
#[inline]
3239+
fn as_slice(&self) -> &[Self::Item] {
3240+
self
3241+
}
3242+
}
3243+
3244+
#[stable(feature = "slice_strip", since = "1.50.0")]
3245+
impl<T, const N: usize> SlicePattern for [T; N] {
3246+
type Item = T;
3247+
3248+
#[inline]
3249+
fn as_slice(&self) -> &[Self::Item] {
3250+
self
3251+
}
3252+
}

library/std/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@
307307
#![feature(slice_internals)]
308308
#![feature(slice_ptr_get)]
309309
#![feature(slice_ptr_len)]
310-
#![feature(slice_strip)]
311310
#![feature(staged_api)]
312311
#![feature(std_internals)]
313312
#![feature(stdsimd)]

0 commit comments

Comments
 (0)