Skip to content

Commit 01d93bf

Browse files
committed
Split the SliceConcat trait into Concat and Join
1 parent 5397dfc commit 01d93bf

File tree

2 files changed

+69
-22
lines changed

2 files changed

+69
-22
lines changed

src/liballoc/slice.rs

+57-17
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,10 @@ impl<T> [T] {
494494
/// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
495495
/// ```
496496
#[stable(feature = "rust1", since = "1.0.0")]
497-
pub fn concat<Separator: ?Sized>(&self) -> T::Output
498-
where T: SliceConcat<Separator>
497+
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
498+
where Self: Concat<Item>
499499
{
500-
SliceConcat::concat(self)
500+
Concat::concat(self)
501501
}
502502

503503
/// Flattens a slice of `T` into a single value `Self::Output`, placing a
@@ -510,10 +510,10 @@ impl<T> [T] {
510510
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
511511
/// ```
512512
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
513-
pub fn join<Separator: ?Sized>(&self, sep: &Separator) -> T::Output
514-
where T: SliceConcat<Separator>
513+
pub fn join<Separator: ?Sized>(&self, sep: &Separator) -> <Self as Join<Separator>>::Output
514+
where Self: Join<Separator>
515515
{
516-
SliceConcat::join(self, sep)
516+
Join::join(self, sep)
517517
}
518518

519519
/// Flattens a slice of `T` into a single value `Self::Output`, placing a
@@ -528,10 +528,10 @@ impl<T> [T] {
528528
/// ```
529529
#[stable(feature = "rust1", since = "1.0.0")]
530530
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
531-
pub fn connect<Separator: ?Sized>(&self, sep: &Separator) -> T::Output
532-
where T: SliceConcat<Separator>
531+
pub fn connect<Separator: ?Sized>(&self, sep: &Separator) -> <Self as Join<Separator>>::Output
532+
where Self: Join<Separator>
533533
{
534-
SliceConcat::join(self, sep)
534+
Join::join(self, sep)
535535
}
536536

537537
}
@@ -578,37 +578,77 @@ impl [u8] {
578578
// Extension traits for slices over specific kinds of data
579579
////////////////////////////////////////////////////////////////////////////////
580580

581-
/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat)
582-
/// and [`[T]::join`](../../std/primitive.slice.html#method.join)
581+
/// Helper trait for [`[T]::concat`](../../std/primitive.slice.html#method.concat).
582+
///
583+
/// Note: the `Item` type parameter is not used in this trait,
584+
/// but it allows impls to be more generic.
585+
/// Without it, we get this error:
586+
///
587+
/// ```error
588+
/// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica
589+
/// --> src/liballoc/slice.rs:608:6
590+
/// |
591+
/// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] {
592+
/// | ^ unconstrained type parameter
593+
/// ```
594+
///
595+
/// This is because there could exist `V` types with multiple `Borrow<[_]>` impls,
596+
/// such that multiple `T` types would apply:
597+
///
598+
/// ```
599+
/// # #[allow(dead_code)]
600+
/// pub struct Foo(Vec<u32>, Vec<String>);
601+
///
602+
/// impl std::borrow::Borrow<[u32]> for Foo {
603+
/// fn borrow(&self) -> &[u32] { &self.0 }
604+
/// }
605+
///
606+
/// impl std::borrow::Borrow<[String]> for Foo {
607+
/// fn borrow(&self) -> &[String] { &self.1 }
608+
/// }
609+
/// ```
583610
#[unstable(feature = "slice_concat_trait", issue = "27747")]
584-
pub trait SliceConcat<Separator: ?Sized>: Sized {
611+
pub trait Concat<Item: ?Sized> {
585612
#[unstable(feature = "slice_concat_trait", issue = "27747")]
586613
/// The resulting type after concatenation
587614
type Output;
588615

589616
/// Implementation of [`[T]::concat`](../../std/primitive.slice.html#method.concat)
590617
#[unstable(feature = "slice_concat_trait", issue = "27747")]
591-
fn concat(slice: &[Self]) -> Self::Output;
618+
fn concat(slice: &Self) -> Self::Output;
619+
}
620+
621+
/// Helper trait for [`[T]::join`](../../std/primitive.slice.html#method.join)
622+
#[unstable(feature = "slice_concat_trait", issue = "27747")]
623+
pub trait Join<Separator: ?Sized> {
624+
#[unstable(feature = "slice_concat_trait", issue = "27747")]
625+
/// The resulting type after concatenation
626+
type Output;
592627

593628
/// Implementation of [`[T]::join`](../../std/primitive.slice.html#method.join)
594629
#[unstable(feature = "slice_concat_trait", issue = "27747")]
595-
fn join(slice: &[Self], sep: &Separator) -> Self::Output;
630+
fn join(slice: &Self, sep: &Separator) -> Self::Output;
596631
}
597632

598633
#[unstable(feature = "slice_concat_ext", issue = "27747")]
599-
impl<T: Clone, V: Borrow<[T]>> SliceConcat<T> for V {
634+
impl<T: Clone, V: Borrow<[T]>> Concat<T> for [V] {
600635
type Output = Vec<T>;
601636

602-
fn concat(slice: &[Self]) -> Vec<T> {
637+
fn concat(slice: &Self) -> Vec<T> {
603638
let size = slice.iter().map(|slice| slice.borrow().len()).sum();
604639
let mut result = Vec::with_capacity(size);
605640
for v in slice {
606641
result.extend_from_slice(v.borrow())
607642
}
608643
result
609644
}
645+
}
646+
647+
#[unstable(feature = "slice_concat_ext", issue = "27747")]
648+
impl<T: Clone, V: Borrow<[T]>> Join<T> for [V] {
649+
type Output = Vec<T>;
610650

611-
fn join(slice: &[Self], sep: &T) -> Vec<T> {
651+
fn join(slice: &Self, sep: &T) -> Vec<T> {
612652
let mut iter = slice.iter();
613653
let first = match iter.next() {
614654
Some(first) => first,

src/liballoc/str.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use core::unicode::conversions;
3737

3838
use crate::borrow::ToOwned;
3939
use crate::boxed::Box;
40-
use crate::slice::{SliceConcat, SliceIndex};
40+
use crate::slice::{Concat, Join, SliceIndex};
4141
use crate::string::String;
4242
use crate::vec::Vec;
4343

@@ -71,15 +71,22 @@ pub use core::str::SplitAsciiWhitespace;
7171
#[stable(feature = "str_escape", since = "1.34.0")]
7272
pub use core::str::{EscapeDebug, EscapeDefault, EscapeUnicode};
7373

74+
/// Note: `str` in `Concat<str>` is not meaningful here.
75+
/// This type parameter of the trait only exists to enable another impl.
7476
#[unstable(feature = "slice_concat_ext", issue = "27747")]
75-
impl<S: Borrow<str>> SliceConcat<str> for S {
77+
impl<S: Borrow<str>> Concat<str> for [S] {
7678
type Output = String;
7779

78-
fn concat(slice: &[Self]) -> String {
79-
Self::join(slice, "")
80+
fn concat(slice: &Self) -> String {
81+
Join::join(slice, "")
8082
}
83+
}
84+
85+
#[unstable(feature = "slice_concat_ext", issue = "27747")]
86+
impl<S: Borrow<str>> Join<str> for [S] {
87+
type Output = String;
8188

82-
fn join(slice: &[Self], sep: &str) -> String {
89+
fn join(slice: &Self, sep: &str) -> String {
8390
unsafe {
8491
String::from_utf8_unchecked( join_generic_copy(slice, sep.as_bytes()) )
8592
}

0 commit comments

Comments
 (0)