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 <ijackson@chiark.greenend.org.uk>
This commit is contained in:
Ian Jackson 2020-10-12 15:52:46 +01:00
parent 0b644e4196
commit 274e2993cb
2 changed files with 41 additions and 8 deletions

View File

@ -1778,7 +1778,6 @@ impl<T> [T] {
/// # Examples
///
/// ```
/// #![feature(slice_strip)]
/// let v = &[10, 40, 30];
/// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
/// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
@ -1786,12 +1785,14 @@ impl<T> [T] {
/// assert_eq!(v.strip_prefix(&[10, 50]), None);
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[unstable(feature = "slice_strip", issue = "73413")]
pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
#[stable(feature = "slice_strip", since = "1.50.0")]
pub fn strip_prefix<P: SlicePattern<Item = T>>(&self, prefix: &P) -> Option<&[T]>
where
T: PartialEq,
{
let n = prefix.len();
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
let prefix = prefix.as_slice();
let n = prefix.as_slice().len();
if n <= self.len() {
let (head, tail) = self.split_at(n);
if head == prefix {
@ -1811,7 +1812,6 @@ impl<T> [T] {
/// # Examples
///
/// ```
/// #![feature(slice_strip)]
/// let v = &[10, 40, 30];
/// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
/// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
@ -1819,11 +1819,13 @@ impl<T> [T] {
/// assert_eq!(v.strip_suffix(&[50, 30]), None);
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[unstable(feature = "slice_strip", issue = "73413")]
pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
#[stable(feature = "slice_strip", since = "1.50.0")]
pub fn strip_suffix<P: SlicePattern<Item = T>>(&self, suffix: &P) -> Option<&[T]>
where
T: PartialEq,
{
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
let suffix = suffix.as_slice();
let (len, n) = (self.len(), suffix.len());
if n <= len {
let (head, tail) = self.split_at(len - n);
@ -3216,3 +3218,35 @@ impl<T> Default for &mut [T] {
&mut []
}
}
#[unstable(feature = "x", issue = "none")]
/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`. At a future
/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to
/// `str`) to slices, and then this trait will be replaced or abolished.
pub trait SlicePattern {
/// The element type of the slice being matched on.
type Item;
/// Currently, the consumers of `SlicePattern` need a slice.
fn as_slice(&self) -> &[Self::Item];
}
#[stable(feature = "slice_strip", since = "1.50.0")]
impl<T> SlicePattern for [T] {
type Item = T;
#[inline]
fn as_slice(&self) -> &[Self::Item] {
self
}
}
#[stable(feature = "slice_strip", since = "1.50.0")]
impl<T, const N: usize> SlicePattern for [T; N] {
type Item = T;
#[inline]
fn as_slice(&self) -> &[Self::Item] {
self
}
}

View File

@ -307,7 +307,6 @@
#![feature(slice_internals)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_strip)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stdsimd)]