A crazy hypothesis:
std::borrow::ToOwned
could be entirely replaced with IntoOwned
if we replace bounds like
X: ToOwned<Owned = O>
with
for<'a> &'a X: IntoOwned<Owned = O>
.
Not sure about that one though.
Thus (if that was true), std
wouldn't need ToOwned
but only IntoOwned
.
Update:
I guess in practice this wouldn't work (edit: in all cases) until issue #20671 was fixed.
Update #2:
Let's try:
use std::borrow::Borrow;
use std::ops::Deref;
pub trait IntoOwned: Sized + Deref {
type Owned: Borrow<<Self as Deref>::Target>;
fn into_owned(self) -> Self::Owned;
}
impl<'a, T> IntoOwned for &'a T
where
T: ?Sized + ToOwned,
{
type Owned = <T as ToOwned>::Owned;
fn into_owned(self) -> Self::Owned {
self.to_owned()
}
}
fn classic_own<B>(b: &B) -> <B as ToOwned>::Owned
where
B: ?Sized + ToOwned,
{
b.to_owned()
}
fn crazy_own<B>(b: &B) -> <&B as IntoOwned>::Owned
where
B: ?Sized,
for<'a> &'a B: IntoOwned,
{
b.into_owned()
}
fn main() {
let some_slice: &[i32] = &[1, 2, 3] as &[i32];
let owned: Vec<i32> = some_slice.to_owned();
let classic: Vec<i32> = classic_own(some_slice);
assert_eq!(owned, classic);
let crazy: Vec<i32> = crazy_own(some_slice);
assert_eq!(owned, crazy);
}
Update #3:
The problem with std::borrow::ToOwned
is that while it may go from &T
to T
(where T: Clone
), it cannot go from SomeSmartPointer<T>
(that is to an owned type without doing Clone
) to T
an a potentially unnecessary clone. In that sense IntoOwned
lifts ToOwned
from working on ordinary references to working more generically on pointer-like types (including smart pointers).
Update #4:
Of course, this is related to specialization.