about summary refs log tree commit diff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2020-10-12 15:52:46 +0100
committerIan Jackson <ijackson@chiark.greenend.org.uk>2020-12-27 00:50:46 +0000
commit274e2993cbbfe7182ff6b79064addf171cf5a5aa (patch)
treef042c71f96fa3b3f8f337642b08c437cd04265bd
parent0b644e419681835bd0f5871c3bfbd648aa04f157 (diff)
downloadrust-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.rs48
-rw-r--r--library/std/src/lib.rs1
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)]