Auto merge of #37326 - SimonSapin:from-cow, r=alexcrichton

Implement `From<Cow<str>> for String` and `From<Cow<[T]>> for Vec<T>`.

Motivation: the `selectors` crate is generic over a string type, in order to support all of `String`,  `string_cache::Atom`, and `gecko_string_cache::Atom`. Multiple trait bounds are used for the various operations done with these strings. One of these operations is creating a string (as efficiently as possible, re-using an existing memory allocation if possible) from `Cow<str>`.

The `std::convert::From` trait seems natural for this, but the relevant implementation was missing before this PR. To work around this I’ve added a `FromCowStr` trait in `selectors`, but with trait coherence that means one of `selectors` or `string_cache` needs to depend on the other to implement this trait. Using a trait from `std` would solve this.

The `Vec<T>` implementation is just added for consistency. I also tried a more general `impl<'a, O, B: ?Sized + ToOwned<Owned=O>> From<Cow<'a, B>> for O`, but (the compiler thinks?) it conflicts with `From<T> for T` the impl (after moving all of `collections::borrow` into `core::borrow` to work around trait coherence).
This commit is contained in:
bors 2016-10-22 19:47:05 -07:00 committed by GitHub
commit febfe7683b
4 changed files with 28 additions and 0 deletions

View File

@ -1860,6 +1860,13 @@ impl<'a> From<&'a str> for String {
}
}
#[stable(feature = "string_from_cow_str", since = "1.14.0")]
impl<'a> From<Cow<'a, str>> for String {
fn from(s: Cow<'a, str>) -> String {
s.into_owned()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for Cow<'a, str> {
#[inline]

View File

@ -1797,6 +1797,13 @@ impl<'a, T: Clone> From<&'a [T]> for Vec<T> {
}
}
#[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
impl<'a, T> From<Cow<'a, [T]>> for Vec<T> where [T]: ToOwned<Owned=Vec<T>> {
fn from(s: Cow<'a, [T]>) -> Vec<T> {
s.into_owned()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for Vec<u8> {
fn from(s: &'a str) -> Vec<u8> {

View File

@ -35,6 +35,12 @@ fn test_from_str() {
assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
}
#[test]
fn test_from_cow_str() {
assert_eq!(String::from(Cow::Borrowed("string")), "string");
assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
}
#[test]
fn test_unsized_to_string() {
let s: &str = "abc";

View File

@ -597,6 +597,14 @@ fn test_cow_from() {
}
}
#[test]
fn test_from_cow() {
let borrowed: &[_] = &["borrowed", "(slice)"];
let owned = vec!["owned", "(vec)"];
assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]);
assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]);
}
#[allow(dead_code)]
fn assert_covariance() {
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }