Consider the following example code:
#[derive(Clone)]
struct DataRef<'a> {
text: &'a str,
}
#[derive(Clone)]
struct DataOwned {
text: String,
}
I am going to implement ToOwned for DataRef in this way:
impl ToOwned for DataRef<'_> {
type Owned = DataOwned;
fn to_owned(&self) -> DataOwned {
DataOwned {
text: self.text.to_owned(),
}
}
}
Literally, it makes sense right? But there are some problems.
The first problem is, since ToOwned provides a blanket implementation:
impl<T> ToOwned for T where T: Clone { ... }
the above code will give a compile error:
error[E0119]: conflicting implementations of trait `std::borrow::ToOwned` for type `DataRef<'_>`
--> src/main.rs:13:1
|
13 | impl ToOwned for DataRef<'_> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `alloc`:
- impl<T> ToOwned for T
where T: Clone;
Well, we can make some compromises. Let's remove #[derive(Clone)] from DataRef. (However, I can't do that in my real case, because it's a breaking change and doesn't make sense)
And then the second problem, the associated type Owned of ToOwned requires that it implements Borrow<Self>.
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
...
}
If we implement Borrow for DataOwned as it is defined:
impl<'a> Borrow<DataRef<'a>> for DataOwned {
fn borrow(&self) -> &DataRef<'a> {
DataRef { text: &self.text }
}
}
this is obviously impossible, because we cannot store a DataRef somewhere.
So my questions are:
Is there any way to implement
ToOwnedfor the above example?Consider the problems above, is
ToOwnednot supposed to be implemented manually by users? Because I can't imagine a real example to oppose this point.(Optional Answer) If changes to the definition of std
ToOwnedare allowed, are there any possible improvements to make it better? (Unstable and unimplemented Rust features are allowed)
borrow::ToOwnedis closely tied toborrow:Cow<T>, which requiresT: ToOwned. There areimplofPartialEq,Ordand such forCow, which is where theBorrowrequirement comes from: BecauseBorrowguarantees that the owned and the borrowed variant behave the same,Cowcan compare and order to itself, irrespective of whether the values are of the borrowed or owned variant.Cowworks becauseToOwnedandBorrowmake it possible to go seamlessly from one to the other. Can you give some details on why you want to implementToOwned?