diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2019-07-08 17:47:49 +0200 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2019-07-09 11:45:46 +0200 |
| commit | 01d93bf59523c4e5c00cf8933c551adc73953cd1 (patch) | |
| tree | 836602dd50be9b22864f3dba302ff2c9f8f48467 /src/liballoc | |
| parent | 5397dfce77f3b3d903580843af3da37615a44e74 (diff) | |
| download | rust-01d93bf59523c4e5c00cf8933c551adc73953cd1.tar.gz rust-01d93bf59523c4e5c00cf8933c551adc73953cd1.zip | |
Split the SliceConcat trait into Concat and Join
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/slice.rs | 74 | ||||
| -rw-r--r-- | src/liballoc/str.rs | 17 |
2 files changed, 69 insertions, 22 deletions
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 9a23cdc1768..d7a9f83ad24 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -494,10 +494,10 @@ impl<T> [T] { /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn concat<Separator: ?Sized>(&self) -> T::Output - where T: SliceConcat<Separator> + pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output + where Self: Concat<Item> { - SliceConcat::concat(self) + Concat::concat(self) } /// Flattens a slice of `T` into a single value `Self::Output`, placing a @@ -510,10 +510,10 @@ impl<T> [T] { /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); /// ``` #[stable(feature = "rename_connect_to_join", since = "1.3.0")] - pub fn join<Separator: ?Sized>(&self, sep: &Separator) -> T::Output - where T: SliceConcat<Separator> + pub fn join<Separator: ?Sized>(&self, sep: &Separator) -> <Self as Join<Separator>>::Output + where Self: Join<Separator> { - SliceConcat::join(self, sep) + Join::join(self, sep) } /// Flattens a slice of `T` into a single value `Self::Output`, placing a @@ -528,10 +528,10 @@ impl<T> [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] - pub fn connect<Separator: ?Sized>(&self, sep: &Separator) -> T::Output - where T: SliceConcat<Separator> + pub fn connect<Separator: ?Sized>(&self, sep: &Separator) -> <Self as Join<Separator>>::Output + where Self: Join<Separator> { - SliceConcat::join(self, sep) + Join::join(self, sep) } } @@ -578,28 +578,63 @@ impl [u8] { // Extension traits for slices over specific kinds of data //////////////////////////////////////////////////////////////////////////////// -/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat) -/// and [`[T]::join`](../../std/primitive.slice.html#method.join) +/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat). +/// +/// Note: the `Item` type parameter is not used in this trait, +/// but it allows impls to be more generic. +/// Without it, we get this error: +/// +/// ```error +/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica +/// --> src/liballoc/slice.rs:608:6 +/// | +/// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] { +/// | ^ unconstrained type parameter +/// ``` +/// +/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls, +/// such that multiple `T` types would apply: +/// +/// ``` +/// # #[allow(dead_code)] +/// pub struct Foo(Vec<u32>, Vec<String>); +/// +/// impl std::borrow::Borrow<[u32]> for Foo { +/// fn borrow(&self) -> &[u32] { &self.0 } +/// } +/// +/// impl std::borrow::Borrow<[String]> for Foo { +/// fn borrow(&self) -> &[String] { &self.1 } +/// } +/// ``` #[unstable(feature = "slice_concat_trait", issue = "27747")] -pub trait SliceConcat<Separator: ?Sized>: Sized { +pub trait Concat<Item: ?Sized> { #[unstable(feature = "slice_concat_trait", issue = "27747")] /// The resulting type after concatenation type Output; /// Implementation of [`[T]::concat`](../../std/primitive.slice.html#method.concat) #[unstable(feature = "slice_concat_trait", issue = "27747")] - fn concat(slice: &[Self]) -> Self::Output; + fn concat(slice: &Self) -> Self::Output; +} + +/// Helper trait for [`[T]::join`](../../std/primitive.slice.html#method.join) +#[unstable(feature = "slice_concat_trait", issue = "27747")] +pub trait Join<Separator: ?Sized> { + #[unstable(feature = "slice_concat_trait", issue = "27747")] + /// The resulting type after concatenation + type Output; /// Implementation of [`[T]::join`](../../std/primitive.slice.html#method.join) #[unstable(feature = "slice_concat_trait", issue = "27747")] - fn join(slice: &[Self], sep: &Separator) -> Self::Output; + fn join(slice: &Self, sep: &Separator) -> Self::Output; } #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V { +impl<T: Clone, V: Borrow<[T]>> Concat<T> for [V] { type Output = Vec<T>; - fn concat(slice: &[Self]) -> Vec<T> { + fn concat(slice: &Self) -> Vec<T> { let size = slice.iter().map(|slice| slice.borrow().len()).sum(); let mut result = Vec::with_capacity(size); for v in slice { @@ -607,8 +642,13 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V { } result } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<T: Clone, V: Borrow<[T]>> Join<T> for [V] { + type Output = Vec<T>; - fn join(slice: &[Self], sep: &T) -> Vec<T> { + fn join(slice: &Self, sep: &T) -> Vec<T> { let mut iter = slice.iter(); let first = match iter.next() { Some(first) => first, diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index b6512487ddd..726ac1907fa 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -37,7 +37,7 @@ use core::unicode::conversions; use crate::borrow::ToOwned; use crate::boxed::Box; -use crate::slice::{SliceConcat, SliceIndex}; +use crate::slice::{Concat, Join, SliceIndex}; use crate::string::String; use crate::vec::Vec; @@ -71,15 +71,22 @@ pub use core::str::SplitAsciiWhitespace; #[stable(feature = "str_escape", since = "1.34.0")] pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode}; +/// Note: `str` in `Concat<str>` is not meaningful here. +/// This type parameter of the trait only exists to enable another impl. #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl<S: Borrow<str>> SliceConcat<str> for S { +impl<S: Borrow<str>> Concat<str> for [S] { type Output = String; - fn concat(slice: &[Self]) -> String { - Self::join(slice, "") + fn concat(slice: &Self) -> String { + Join::join(slice, "") } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl<S: Borrow<str>> Join<str> for [S] { + type Output = String; - fn join(slice: &[Self], sep: &str) -> String { + fn join(slice: &Self, sep: &str) -> String { unsafe { String::from_utf8_unchecked( join_generic_copy(slice, sep.as_bytes()) ) } |
