From d3770f864c4e41d36bc857a2be6817a5220c7680 Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 18:28:15 -0300 Subject: [PATCH 1/7] Add feature impl --- library/core/src/slice/iter.rs | 137 +++++++++++++++++++++++++++++++++ library/core/src/slice/mod.rs | 13 ++++ 2 files changed, 150 insertions(+) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index c5746157d01..3cabfd72aeb 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1305,6 +1305,143 @@ forward_iterator! { RSplitN: T, &'a [T] } forward_iterator! { SplitNMut: T, &'a mut [T] } forward_iterator! { RSplitNMut: T, &'a mut [T] } +/// An iterator over subslices separated by a given slice +/// +/// This struct is created by the [`split_pattern`] method on [slices]. +/// +/// # Example +/// +/// ``` +/// let slice = [10, 10, 40, 33, 30, 10, 40, 20]; +/// let pat = [10, 40]; +/// let mut iter = slice.split_pattern(&pat); +/// assert_eq!(iter.next(), Some(&[10][..])); +/// assert_eq!(iter.next(), Some(&[33, 30][..])); +/// assert_eq!(iter.next(), Some(&[20][..])); +/// assert_eq!(iter.next(), None); +/// ``` +/// +/// [`split_pattern`]: slice::split_pattern +/// [slices]: slice +#[unstable(feature = "split_pattern", issue = "49036")] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct SplitPattern<'a, 'b, T> +where + T: cmp::PartialEq, +{ + v: &'a [T], + pattern: &'b [T], + finished: bool, +} + +#[unstable(feature = "split_pattern", issue = "49036")] +impl<'a, 'b, T: cmp::PartialEq> SplitPattern<'a, 'b, T> { + #![allow(unused)] + #[inline] + pub(super) fn new(slice: &'a [T], pattern: &'b [T]) -> Self { + Self { v: slice, pattern, finished: false } + } +} + +#[unstable(feature = "split_pattern", issue = "49036")] +impl fmt::Debug for SplitPattern<'_, '_, T> +where + T: cmp::PartialEq, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitPattern") + .field("v", &self.v) + .field("pattern", &self.pattern) + .field("finished", &self.finished) + .finish() + } +} + +#[unstable(feature = "split_pattern", issue = "49036")] +impl Clone for SplitPattern<'_, '_, T> +where + T: cmp::PartialEq, +{ + fn clone(&self) -> Self { + SplitPattern { v: self.v, pattern: self.pattern, finished: self.finished } + } +} + +#[unstable(feature = "split_pattern", issue = "49036")] +impl<'a, 'b, T> Iterator for SplitPattern<'a, 'b, T> +where + T: cmp::PartialEq, +{ + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.finished { + return None; + } + + for i in 0..self.v.len() { + if self.v[i..].starts_with(&self.pattern) { + let (left, right) = (&self.v[0..i], &self.v[i + self.pattern.len()..]); + let ret = Some(left); + self.v = right; + return ret; + } + } + self.finish() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + // If the predicate doesn't match anything, we yield one slice. + // If it matches every element, we yield `len() + 1` empty slices. + (1, Some(self.v.len() + 1)) + } + } +} + +#[unstable(feature = "split_pattern", issue = "49036")] +impl<'a, 'b, T> DoubleEndedIterator for SplitPattern<'a, 'b, T> +where + T: cmp::PartialEq, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.finished { + return None; + } + + for i in (0..self.v.len()).rev() { + if self.v[..i].ends_with(&self.pattern) { + let (left, right) = (&self.v[i..], &self.v[..i - self.pattern.len()]); + let ret = Some(left); + self.v = right; + return ret; + } + } + self.finish() + } +} + +#[unstable(feature = "split_pattern", issue = "49036")] +impl<'a, 'b, T> SplitIter for SplitPattern<'a, 'b, T> +where + T: cmp::PartialEq, +{ + #[inline] + fn finish(&mut self) -> Option<&'a [T]> { + if self.finished { + None + } else { + self.finished = true; + Some(self.v) + } + } +} + /// An iterator over overlapping subslices of length `size`. /// /// This struct is created by the [`windows`] method on [slices]. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 90ddc9c1d85..1b996fc38d5 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -68,6 +68,8 @@ pub use iter::{RSplit, RSplitMut}; pub use iter::{RSplitN, RSplitNMut, Split, SplitMut, SplitN, SplitNMut}; #[stable(feature = "split_inclusive", since = "1.51.0")] pub use iter::{SplitInclusive, SplitInclusiveMut}; +#[unstable(feature = "split_pattern", issue = "49036")] +pub use iter::{SplitPattern}; #[stable(feature = "from_ref", since = "1.28.0")] pub use raw::{from_mut, from_ref}; #[unstable(feature = "slice_from_ptr_range", issue = "89792")] @@ -2484,6 +2486,7 @@ impl [T] { Some((&self[..index], &self[index + 1..])) } + /// Returns `true` if the slice contains an element with the given value. /// /// This operation is *O*(*n*). @@ -4042,6 +4045,15 @@ impl [T] { unsafe { self.align_to() } } + + /// Splits a slice by a pattern + #[unstable(feature = "split_pattern", issue = "49036")] + #[inline] + pub fn split_pattern<'a, 'b>(&'a self, pattern: &'b [T]) -> SplitPattern<'a, 'b, T> where T: PartialEq { + SplitPattern::new(&self, pattern) + } + + /// Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types, /// and a mutable suffix. /// @@ -4762,6 +4774,7 @@ impl [f32] { } } + #[cfg(not(test))] impl [f64] { /// Sorts the slice of floats. From 30699d5bfdeca66ebf20ea4c040c308ed33e320e Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 18:28:29 -0300 Subject: [PATCH 2/7] Add unstable feature defintion --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 380e36fe405..d3c1eafc2a9 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -592,6 +592,8 @@ declare_features! ( (unstable, simd_ffi, "1.0.0", Some(27731)), /// Allows specialization of implementations (RFC 1210). (incomplete, specialization, "1.7.0", Some(31844)), + /// Allows splitting a slice by another slice + (unstable, split_pattern, "CURRENT_RUSTC_VERSION", Some(49036)), /// Allows attributes on expressions and non-item statements. (unstable, stmt_expr_attributes, "1.6.0", Some(15701)), /// Allows lints part of the strict provenance effort. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1527600e764..35adb4db9e2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1864,6 +1864,7 @@ symbols! { soft, specialization, speed, + split_pattern, spotlight, sqrtf128, sqrtf16, From 5def45e72719cbb52f64e5262d20acfb86f7c854 Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 18:40:04 -0300 Subject: [PATCH 3/7] feature-gate ui test --- tests/ui/feature-gates/feature-gate-split-pattern.rs | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/ui/feature-gates/feature-gate-split-pattern.rs diff --git a/tests/ui/feature-gates/feature-gate-split-pattern.rs b/tests/ui/feature-gates/feature-gate-split-pattern.rs new file mode 100644 index 00000000000..1d1e3235fae --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-split-pattern.rs @@ -0,0 +1,5 @@ +pub fn main() { + let a = &[1, 2, 3, 4, 5]; + let b = &[2, 3]; + let mut c = a.split_pattern(b); +} From 2abf4ddf7c9df41681afe0c68d3b104e11c43fc1 Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 18:40:15 -0300 Subject: [PATCH 4/7] ./x fmt --- library/core/src/slice/mod.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 1b996fc38d5..2a42ad0f231 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -50,6 +50,8 @@ pub use index::SliceIndex; pub use index::{range, try_range}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; +#[unstable(feature = "split_pattern", issue = "49036")] +pub use iter::SplitPattern; #[unstable(feature = "array_chunks", issue = "74985")] pub use iter::{ArrayChunks, ArrayChunksMut}; #[stable(feature = "slice_group_by", since = "1.77.0")] @@ -68,8 +70,6 @@ pub use iter::{RSplit, RSplitMut}; pub use iter::{RSplitN, RSplitNMut, Split, SplitMut, SplitN, SplitNMut}; #[stable(feature = "split_inclusive", since = "1.51.0")] pub use iter::{SplitInclusive, SplitInclusiveMut}; -#[unstable(feature = "split_pattern", issue = "49036")] -pub use iter::{SplitPattern}; #[stable(feature = "from_ref", since = "1.28.0")] pub use raw::{from_mut, from_ref}; #[unstable(feature = "slice_from_ptr_range", issue = "89792")] @@ -2486,7 +2486,6 @@ impl [T] { Some((&self[..index], &self[index + 1..])) } - /// Returns `true` if the slice contains an element with the given value. /// /// This operation is *O*(*n*). @@ -4045,15 +4044,16 @@ impl [T] { unsafe { self.align_to() } } - /// Splits a slice by a pattern #[unstable(feature = "split_pattern", issue = "49036")] #[inline] - pub fn split_pattern<'a, 'b>(&'a self, pattern: &'b [T]) -> SplitPattern<'a, 'b, T> where T: PartialEq { + pub fn split_pattern<'a, 'b>(&'a self, pattern: &'b [T]) -> SplitPattern<'a, 'b, T> + where + T: PartialEq, + { SplitPattern::new(&self, pattern) } - /// Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types, /// and a mutable suffix. /// @@ -4774,7 +4774,6 @@ impl [f32] { } } - #[cfg(not(test))] impl [f64] { /// Sorts the slice of floats. From 8a6137d9fb0a031580420cecc380281335d0cec6 Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 19:03:43 -0300 Subject: [PATCH 5/7] ./x test --bless --- .../ui/feature-gates/feature-gate-split-pattern.rs | 2 +- .../feature-gates/feature-gate-split-pattern.stderr | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/ui/feature-gates/feature-gate-split-pattern.stderr diff --git a/tests/ui/feature-gates/feature-gate-split-pattern.rs b/tests/ui/feature-gates/feature-gate-split-pattern.rs index 1d1e3235fae..6aa857446cf 100644 --- a/tests/ui/feature-gates/feature-gate-split-pattern.rs +++ b/tests/ui/feature-gates/feature-gate-split-pattern.rs @@ -1,5 +1,5 @@ pub fn main() { let a = &[1, 2, 3, 4, 5]; let b = &[2, 3]; - let mut c = a.split_pattern(b); + let mut c = a.split_pattern(b); //~ ERROR use of unstable library feature 'split_pattern' } diff --git a/tests/ui/feature-gates/feature-gate-split-pattern.stderr b/tests/ui/feature-gates/feature-gate-split-pattern.stderr new file mode 100644 index 00000000000..ae3efd0b7e9 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-split-pattern.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature 'split_pattern' + --> $DIR/feature-gate-split-pattern.rs:4:19 + | +LL | let mut c = a.split_pattern(b); + | ^^^^^^^^^^^^^ + | + = note: see issue #49036 for more information + = help: add `#![feature(split_pattern)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 7add14af3621aed30c5a602e51c7de75e4929af7 Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 19:14:24 -0300 Subject: [PATCH 6/7] fix doc test --- library/core/src/slice/iter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 3cabfd72aeb..07093cf31f2 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -1312,6 +1312,7 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } /// # Example /// /// ``` +/// #![feature(split_pattern)] /// let slice = [10, 10, 40, 33, 30, 10, 40, 20]; /// let pat = [10, 40]; /// let mut iter = slice.split_pattern(&pat); From ef569a29c9b330fa2c8f18576c98e06bea977635 Mon Sep 17 00:00:00 2001 From: eduardorittner Date: Sun, 6 Oct 2024 19:54:40 -0300 Subject: [PATCH 7/7] Remove unnecessary tests Since it's a library feature it shouldn't be declared inside the compiler --- compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_span/src/symbol.rs | 1 - .../ui/feature-gates/feature-gate-split-pattern.rs | 5 ----- .../feature-gates/feature-gate-split-pattern.stderr | 13 ------------- 4 files changed, 21 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-split-pattern.rs delete mode 100644 tests/ui/feature-gates/feature-gate-split-pattern.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index d3c1eafc2a9..380e36fe405 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -592,8 +592,6 @@ declare_features! ( (unstable, simd_ffi, "1.0.0", Some(27731)), /// Allows specialization of implementations (RFC 1210). (incomplete, specialization, "1.7.0", Some(31844)), - /// Allows splitting a slice by another slice - (unstable, split_pattern, "CURRENT_RUSTC_VERSION", Some(49036)), /// Allows attributes on expressions and non-item statements. (unstable, stmt_expr_attributes, "1.6.0", Some(15701)), /// Allows lints part of the strict provenance effort. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 35adb4db9e2..1527600e764 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1864,7 +1864,6 @@ symbols! { soft, specialization, speed, - split_pattern, spotlight, sqrtf128, sqrtf16, diff --git a/tests/ui/feature-gates/feature-gate-split-pattern.rs b/tests/ui/feature-gates/feature-gate-split-pattern.rs deleted file mode 100644 index 6aa857446cf..00000000000 --- a/tests/ui/feature-gates/feature-gate-split-pattern.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn main() { - let a = &[1, 2, 3, 4, 5]; - let b = &[2, 3]; - let mut c = a.split_pattern(b); //~ ERROR use of unstable library feature 'split_pattern' -} diff --git a/tests/ui/feature-gates/feature-gate-split-pattern.stderr b/tests/ui/feature-gates/feature-gate-split-pattern.stderr deleted file mode 100644 index ae3efd0b7e9..00000000000 --- a/tests/ui/feature-gates/feature-gate-split-pattern.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: use of unstable library feature 'split_pattern' - --> $DIR/feature-gate-split-pattern.rs:4:19 - | -LL | let mut c = a.split_pattern(b); - | ^^^^^^^^^^^^^ - | - = note: see issue #49036 for more information - = help: add `#![feature(split_pattern)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`.