Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace SliceConcatExt trait with inherent methods and SliceConcat helper trait #62403

Merged
merged 1 commit into from
Jul 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/liballoc/prelude/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@

#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::borrow::ToOwned;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::boxed::Box;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::slice::SliceConcatExt;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::string::{String, ToString};
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::vec::Vec;
129 changes: 69 additions & 60 deletions src/liballoc/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,56 @@ impl<T> [T] {
}
buf
}

/// Flattens a slice of `T` into a single value `Self::Output`.
///
/// # Examples
///
/// ```
/// assert_eq!(["hello", "world"].concat(), "helloworld");
/// 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>
{
SliceConcat::concat(self)
}

/// Flattens a slice of `T` into a single value `Self::Output`, placing a
/// given separator between each.
///
/// # Examples
///
/// ```
/// assert_eq!(["hello", "world"].join(" "), "hello world");
/// 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>
{
SliceConcat::join(self, sep)
}

/// Flattens a slice of `T` into a single value `Self::Output`, placing a
/// given separator between each.
///
/// # Examples
///
/// ```
/// # #![allow(deprecated)]
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
/// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
/// ```
#[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>
{
SliceConcat::join(self, sep)
}

}

#[lang = "slice_u8_alloc"]
Expand Down Expand Up @@ -527,87 +577,46 @@ impl [u8] {
////////////////////////////////////////////////////////////////////////////////
// Extension traits for slices over specific kinds of data
////////////////////////////////////////////////////////////////////////////////
#[unstable(feature = "slice_concat_ext",
reason = "trait should not have to exist",
issue = "27747")]
/// An extension trait for concatenating slices
///
/// While this trait is unstable, the methods are stable. `SliceConcatExt` is
/// included in the [standard library prelude], so you can use [`join()`] and
/// [`concat()`] as if they existed on `[T]` itself.
///
/// [standard library prelude]: ../../std/prelude/index.html
/// [`join()`]: #tymethod.join
/// [`concat()`]: #tymethod.concat
pub trait SliceConcatExt<T: ?Sized> {
#[unstable(feature = "slice_concat_ext",
reason = "trait should not have to exist",
issue = "27747")]

/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat)
/// and [`[T]::join`](../../std/primitive.slice.html#method.join)
#[unstable(feature = "slice_concat_trait", issue = "27747")]
pub trait SliceConcat<Separator: ?Sized>: Sized {
#[unstable(feature = "slice_concat_trait", issue = "27747")]
/// The resulting type after concatenation
type Output;

/// Flattens a slice of `T` into a single value `Self::Output`.
///
/// # Examples
///
/// ```
/// assert_eq!(["hello", "world"].concat(), "helloworld");
/// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn concat(&self) -> Self::Output;

/// Flattens a slice of `T` into a single value `Self::Output`, placing a
/// given separator between each.
///
/// # Examples
///
/// ```
/// assert_eq!(["hello", "world"].join(" "), "hello world");
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
/// ```
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
fn join(&self, sep: &T) -> Self::Output;
/// Implementation of [`[T]::concat`](../../std/primitive.slice.html#method.concat)
#[unstable(feature = "slice_concat_trait", issue = "27747")]
fn concat(slice: &[Self]) -> Self::Output;

/// Flattens a slice of `T` into a single value `Self::Output`, placing a
/// given separator between each.
///
/// # Examples
///
/// ```
/// # #![allow(deprecated)]
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
/// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
fn connect(&self, sep: &T) -> Self::Output {
self.join(sep)
}
/// 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;
}

#[unstable(feature = "slice_concat_ext",
reason = "trait should not have to exist",
issue = "27747")]
impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] {
impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V {
type Output = Vec<T>;

fn concat(&self) -> Vec<T> {
let size = self.iter().map(|slice| slice.borrow().len()).sum();
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 self {
for v in slice {
result.extend_from_slice(v.borrow())
}
result
}

fn join(&self, sep: &T) -> Vec<T> {
let mut iter = self.iter();
fn join(slice: &[Self], sep: &T) -> Vec<T> {
let mut iter = slice.iter();
let first = match iter.next() {
Some(first) => first,
None => return vec![],
};
let size = self.iter().map(|slice| slice.borrow().len()).sum::<usize>() + self.len() - 1;
let size = slice.iter().map(|slice| slice.borrow().len()).sum::<usize>() + slice.len() - 1;
let mut result = Vec::with_capacity(size);
result.extend_from_slice(first.borrow());

Expand Down
14 changes: 7 additions & 7 deletions src/liballoc/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use core::unicode::conversions;

use crate::borrow::ToOwned;
use crate::boxed::Box;
use crate::slice::{SliceConcatExt, SliceIndex};
use crate::slice::{SliceConcat, SliceIndex};
use crate::string::String;
use crate::vec::Vec;

Expand Down Expand Up @@ -74,16 +74,16 @@ pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode};
#[unstable(feature = "slice_concat_ext",
reason = "trait should not have to exist",
issue = "27747")]
impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
impl<S: Borrow<str>> SliceConcat<str> for S {
type Output = String;

fn concat(&self) -> String {
self.join("")
fn concat(slice: &[Self]) -> String {
Self::join(slice, "")
}

fn join(&self, sep: &str) -> String {
fn join(slice: &[Self], sep: &str) -> String {
unsafe {
String::from_utf8_unchecked( join_generic_copy(self, sep.as_bytes()) )
String::from_utf8_unchecked( join_generic_copy(slice, sep.as_bytes()) )
}
}
}
Expand Down Expand Up @@ -126,7 +126,7 @@ macro_rules! copy_slice_and_advance {

// Optimized join implementation that works for both Vec<T> (T: Copy) and String's inner vec
// Currently (2018-05-13) there is a bug with type inference and specialization (see issue #36262)
// For this reason SliceConcatExt<T> is not specialized for T: Copy and SliceConcatExt<str> is the
// For this reason SliceConcat<T> is not specialized for T: Copy and SliceConcat<str> is the
// only user of this function. It is left in place for the time when that is fixed.
//
// the bounds for String-join are S: Borrow<str> and for Vec-join Borrow<[T]>
Expand Down
3 changes: 0 additions & 3 deletions src/libstd/prelude/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//! that may succeed or fail. Like [`Option`], its variants are exported as
//! well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//! reasons, but shouldn't have to exist. It provides a few useful methods on
//! slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//! vector.
Expand Down
3 changes: 0 additions & 3 deletions src/libstd/prelude/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ pub use crate::boxed::Box;
pub use crate::borrow::ToOwned;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::slice::SliceConcatExt;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::string::{String, ToString};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
Expand Down