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:
parent
0b644e4196
commit
274e2993cb
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user