From 7e603d4e3b2551608a225e115da4e83559b94761 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 21 Oct 2016 16:51:59 +0200 Subject: [PATCH] Implement `From> for String` and `From> for Vec`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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`. 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` implementation is just added for consistency. I also tried a more general `impl<'a, O, B: ?Sized + ToOwned> From> for O`, but (the compiler thinks?) it conflicts with `From for T` the impl (after moving all of `collections::borrow` into `core::borrow` to work around trait coherence). --- src/libcollections/string.rs | 7 +++++++ src/libcollections/vec.rs | 7 +++++++ src/libcollectionstest/string.rs | 6 ++++++ src/libcollectionstest/vec.rs | 8 ++++++++ 4 files changed, 28 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 7a61451b900..ce9fec32917 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1860,6 +1860,13 @@ impl<'a> From<&'a str> for String { } } +#[stable(feature = "string_from_cow_str", since = "1.14.0")] +impl<'a> From> 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] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f3d78c20a4d..f7c3e8ea1ed 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1764,6 +1764,13 @@ impl<'a, T: Clone> From<&'a [T]> for Vec { } } +#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] +impl<'a, T> From> for Vec where [T]: ToOwned> { + fn from(s: Cow<'a, [T]>) -> Vec { + s.into_owned() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&'a str> for Vec { fn from(s: &'a str) -> Vec { diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs index 1652fb5a88d..98de33bdaa8 100644 --- a/src/libcollectionstest/string.rs +++ b/src/libcollectionstest/string.rs @@ -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"; diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 991c456fe74..9a04673d1da 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -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 }