From 5397dfce77f3b3d903580843af3da37615a44e74 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 8 Jul 2019 18:12:06 +0200 Subject: [PATCH 1/7] =?UTF-8?q?Remove=20obsolete=20=E2=80=9Cshould=20not?= =?UTF-8?q?=20have=20to=20exist=E2=80=9D=20reasons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/liballoc/slice.rs | 4 +--- src/liballoc/str.rs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index bc4ae16798478..9a23cdc1768f3 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -595,9 +595,7 @@ pub trait SliceConcat: Sized { fn join(slice: &[Self], sep: &Separator) -> Self::Output; } -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] +#[unstable(feature = "slice_concat_ext", issue = "27747")] impl> SliceConcat for V { type Output = Vec; diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 37a1046d0942d..b6512487ddd56 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -71,9 +71,7 @@ pub use core::str::SplitAsciiWhitespace; #[stable(feature = "str_escape", since = "1.34.0")] pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode}; -#[unstable(feature = "slice_concat_ext", - reason = "trait should not have to exist", - issue = "27747")] +#[unstable(feature = "slice_concat_ext", issue = "27747")] impl> SliceConcat for S { type Output = String; From 01d93bf59523c4e5c00cf8933c551adc73953cd1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 8 Jul 2019 17:47:49 +0200 Subject: [PATCH 2/7] Split the SliceConcat trait into Concat and Join --- src/liballoc/slice.rs | 74 +++++++++++++++++++++++++++++++++---------- 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 9a23cdc1768f3..d7a9f83ad242e 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -494,10 +494,10 @@ impl [T] { /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn concat(&self) -> T::Output - where T: SliceConcat + pub fn concat(&self) -> >::Output + where Self: Concat { - 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] { /// 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(&self, sep: &Separator) -> T::Output - where T: SliceConcat + pub fn join(&self, sep: &Separator) -> >::Output + where Self: Join { - 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] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] - pub fn connect(&self, sep: &Separator) -> T::Output - where T: SliceConcat + pub fn connect(&self, sep: &Separator) -> >::Output + where Self: Join { - 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> 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, Vec); +/// +/// 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: Sized { +pub trait Concat { #[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 { + #[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> SliceConcat for V { +impl> Concat for [V] { type Output = Vec; - fn concat(slice: &[Self]) -> Vec { + fn concat(slice: &Self) -> Vec { 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> SliceConcat for V { } result } +} + +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join for [V] { + type Output = Vec; - fn join(slice: &[Self], sep: &T) -> Vec { + fn join(slice: &Self, sep: &T) -> Vec { 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 b6512487ddd56..726ac1907fa86 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` is not meaningful here. +/// This type parameter of the trait only exists to enable another impl. #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl> SliceConcat for S { +impl> Concat 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> Join 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()) ) } From 283f6762caebb723a17ce82e1fc120928697cfb9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 8 Jul 2019 17:50:27 +0200 Subject: [PATCH 3/7] Take separator by value in `[T]::join` --- src/liballoc/slice.rs | 10 +++++----- src/liballoc/str.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index d7a9f83ad242e..1b18dbeda9c11 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -510,7 +510,7 @@ impl [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(&self, sep: &Separator) -> >::Output + pub fn join(&self, sep: Separator) -> >::Output where Self: Join { Join::join(self, sep) @@ -528,7 +528,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] - pub fn connect(&self, sep: &Separator) -> >::Output + pub fn connect(&self, sep: Separator) -> >::Output where Self: Join { Join::join(self, sep) @@ -620,14 +620,14 @@ pub trait Concat { /// Helper trait for [`[T]::join`](../../std/primitive.slice.html#method.join) #[unstable(feature = "slice_concat_trait", issue = "27747")] -pub trait Join { +pub trait Join { #[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")] @@ -645,7 +645,7 @@ impl> Concat for [V] { } #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl> Join for [V] { +impl> Join<&'_ T> for [V] { type Output = Vec; fn join(slice: &Self, sep: &T) -> Vec { diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 726ac1907fa86..f57cf96a64196 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -83,7 +83,7 @@ impl> Concat for [S] { } #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl> Join for [S] { +impl> Join<&'_ str> for [S] { type Output = String; fn join(slice: &Self, sep: &str) -> String { From b62a77b4905150b14c8b0fd6e685f528e4f90ea7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 8 Jul 2019 18:08:54 +0200 Subject: [PATCH 4/7] Add joining slices of slices with a slice separator, not just a single item --- src/liballoc/slice.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 1b18dbeda9c11..d475c628ff193 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -508,6 +508,7 @@ impl [T] { /// ``` /// assert_eq!(["hello", "world"].join(" "), "hello world"); /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]); + /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]); /// ``` #[stable(feature = "rename_connect_to_join", since = "1.3.0")] pub fn join(&self, sep: Separator) -> >::Output @@ -654,7 +655,7 @@ impl> Join<&'_ T> for [V] { Some(first) => first, None => return vec![], }; - let size = slice.iter().map(|slice| slice.borrow().len()).sum::() + slice.len() - 1; + let size = slice.iter().map(|v| v.borrow().len()).sum::() + slice.len() - 1; let mut result = Vec::with_capacity(size); result.extend_from_slice(first.borrow()); @@ -666,6 +667,29 @@ impl> Join<&'_ T> for [V] { } } +#[unstable(feature = "slice_concat_ext", issue = "27747")] +impl> Join<&'_ [T]> for [V] { + type Output = Vec; + + fn join(slice: &Self, sep: &[T]) -> Vec { + let mut iter = slice.iter(); + let first = match iter.next() { + Some(first) => first, + None => return vec![], + }; + let size = slice.iter().map(|v| v.borrow().len()).sum::() + + sep.len() * (slice.len() - 1); + let mut result = Vec::with_capacity(size); + result.extend_from_slice(first.borrow()); + + for v in iter { + result.extend_from_slice(sep); + result.extend_from_slice(v.borrow()) + } + result + } +} + //////////////////////////////////////////////////////////////////////////////// // Standard trait implementations for slices //////////////////////////////////////////////////////////////////////////////// From d0635ee5f74badbf72355b7e29d7f0723e8551da Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 9 Jul 2019 18:19:01 +0200 Subject: [PATCH 5/7] Update src/liballoc/slice.rs Co-Authored-By: Mazdak Farrokhzad --- src/liballoc/slice.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index d475c628ff193..848df2f9dcf90 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -646,7 +646,7 @@ impl> Concat for [V] { } #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl> Join<&'_ T> for [V] { +impl> Join<&T> for [V] { type Output = Vec; fn join(slice: &Self, sep: &T) -> Vec { From bbc9366c1a2d4d071b54cc1af23706a36741b444 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 9 Jul 2019 18:19:10 +0200 Subject: [PATCH 6/7] Update src/liballoc/slice.rs Co-Authored-By: Mazdak Farrokhzad --- src/liballoc/slice.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 848df2f9dcf90..881d499c0745b 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -668,7 +668,7 @@ impl> Join<&T> for [V] { } #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl> Join<&'_ [T]> for [V] { +impl> Join<&[T]> for [V] { type Output = Vec; fn join(slice: &Self, sep: &[T]) -> Vec { From 5f7768a976edc296c62479b936993b4dc9af065b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 9 Jul 2019 18:19:18 +0200 Subject: [PATCH 7/7] Update src/liballoc/str.rs Co-Authored-By: Mazdak Farrokhzad --- src/liballoc/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index f57cf96a64196..9a1342c30d502 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -83,7 +83,7 @@ impl> Concat for [S] { } #[unstable(feature = "slice_concat_ext", issue = "27747")] -impl> Join<&'_ str> for [S] { +impl> Join<&str> for [S] { type Output = String; fn join(slice: &Self, sep: &str) -> String {