diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index acae0daa86b6b..f90c7b71559b7 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -361,6 +361,17 @@ impl<'a, T: ?Sized + ToOwned> AsRef for Cow<'a, T> { } } +#[stable(feature = "generic_cow_from", since = "1.24.0")] +impl<'a, B, T> From<&'a B> for Cow<'a, T> +where + B: ?Sized + Borrow, + T: ?Sized + ToOwned, +{ + fn from(b: &'a B) -> Self { + Cow::Borrowed(b.borrow()) + } +} + #[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add<&'a str> for Cow<'a, str> { type Output = Cow<'a, str>; diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 8d99d0bc8f4dc..e7f4e36873d33 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2128,14 +2128,6 @@ impl<'a> From> for String { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> From<&'a str> for Cow<'a, str> { - #[inline] - fn from(s: &'a str) -> Cow<'a, str> { - Cow::Borrowed(s) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From for Cow<'a, str> { #[inline] diff --git a/src/liballoc/tests/borrow.rs b/src/liballoc/tests/borrow.rs new file mode 100644 index 0000000000000..291ea2ddf3f14 --- /dev/null +++ b/src/liballoc/tests/borrow.rs @@ -0,0 +1,74 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::path::{Path, PathBuf}; +use std::ffi::{CStr, CString, OsStr, OsString}; + +#[test] +fn test_cow_from() { + const MSG: &'static str = "Hello, World"; + let s = MSG.to_string(); + assert_eq!(Cow::::from(&s), Cow::Borrowed(MSG)); + assert_eq!(Cow::from(s.as_str()), Cow::Borrowed(MSG)); + assert_eq!( + Cow::from(s), + || -> Cow { Cow::Owned(MSG.to_string()) }() + ); + + const VALUES: &[u8] = &[1u8, 2, 3, 4, 5, 6, 7, 8]; + let v = VALUES.iter().map(|b| *b).collect::>(); + assert_eq!(Cow::<[u8]>::from(&v), Cow::Borrowed(VALUES)); + assert_eq!(Cow::from(v.as_slice()), Cow::Borrowed(VALUES)); + assert_eq!( + Cow::from(v), + || -> Cow<[u8]> { Cow::Owned(VALUES.iter().map(|b| *b).collect::>() )}() + ); + + let p = PathBuf::new(); + assert_eq!(Cow::::from(&p), Cow::Borrowed(Path::new(""))); + assert_eq!(Cow::from(p.as_path()), Cow::Borrowed(Path::new(""))); + assert_eq!( + Cow::from(p), + || -> Cow { Cow::Owned(PathBuf::new()) }() + ); + + let cstring = CString::new(MSG).unwrap(); + let cstr = { + const MSG_NULL_TERMINATED: &'static str = "Hello, World\0"; + CStr::from_bytes_with_nul(MSG_NULL_TERMINATED.as_bytes()).unwrap() + }; + assert_eq!(Cow::::from(&cstring), Cow::Borrowed(cstr)); + assert_eq!(Cow::from(cstring.as_c_str()), Cow::Borrowed(cstr)); + + let s = OsString::from(MSG.to_string()); + assert_eq!(Cow::::from(&s), Cow::Borrowed(OsStr::new(MSG))); + assert_eq!(Cow::from(s.as_os_str()), Cow::Borrowed(OsStr::new(MSG))); +} + +#[test] +fn test_generic_cow_from() { + struct VecWrapper { + _inner: Vec, + } + + impl VecWrapper { + fn new<'a, T: Into>>(val: T) -> Self { + VecWrapper { + _inner: val.into().into_owned(), + } + } + } + + let ints = vec![0i32, 1, 2, 3, 4, 5]; + let _vw0 = VecWrapper::new(ints.as_slice()); + let _vw1 = VecWrapper::new(&ints); + let _vw2 = VecWrapper::new(ints); +} diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 427a7adcbded1..c5cc17357eb73 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -40,6 +40,7 @@ use std::collections::hash_map::DefaultHasher; mod binary_heap; mod btree; +mod borrow; mod cow_str; mod fmt; mod heap; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index b26979c7f6d8c..7b20fd9739b9b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2233,13 +2233,6 @@ impl<'a> From<&'a str> for Vec { // Clone-on-write //////////////////////////////////////////////////////////////////////////////// -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { - fn from(s: &'a [T]) -> Cow<'a, [T]> { - Cow::Borrowed(s) - } -} - #[stable(feature = "cow_from_vec", since = "1.8.0")] impl<'a, T: Clone> From> for Cow<'a, [T]> { fn from(v: Vec) -> Cow<'a, [T]> { diff --git a/src/libstd/path.rs b/src/libstd/path.rs index ed102c2949ede..4ebb849bfa30f 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1445,14 +1445,6 @@ impl Default for PathBuf { } } -#[stable(feature = "cow_from_path", since = "1.6.0")] -impl<'a> From<&'a Path> for Cow<'a, Path> { - #[inline] - fn from(s: &'a Path) -> Cow<'a, Path> { - Cow::Borrowed(s) - } -} - #[stable(feature = "cow_from_path", since = "1.6.0")] impl<'a> From for Cow<'a, Path> { #[inline]