diff options
| author | Ian Jackson <ijackson@chiark.greenend.org.uk> | 2020-10-12 15:52:46 +0100 |
|---|---|---|
| committer | Ian Jackson <ijackson@chiark.greenend.org.uk> | 2020-12-27 00:50:46 +0000 |
| commit | 274e2993cbbfe7182ff6b79064addf171cf5a5aa (patch) | |
| tree | f042c71f96fa3b3f8f337642b08c437cd04265bd | |
| parent | 0b644e419681835bd0f5871c3bfbd648aa04f157 (diff) | |
| download | rust-274e2993cbbfe7182ff6b79064addf171cf5a5aa.tar.gz rust-274e2993cbbfe7182ff6b79064addf171cf5a5aa.zip | |
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>
| -rw-r--r-- | library/core/src/slice/mod.rs | 48 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 1 |
2 files changed, 41 insertions, 8 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index f5af48e0dd2..0556bb1e633 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -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 + } +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5bc5ddaa5fe..6c3c2fd53d8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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)] |
