Smart pointer which owns its target

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. :sweat_smile:

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);
}

(Playground)


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 Clone) to T to an owned type without doing 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.