Smart pointer which owns its target

I don't understand everything you wrote (yet?). But if I understand you right, then you acknowledge that Owned is a necessary workaround as of today's Rust but could be made superfluous if one day we could implement IntoOwned<T> for T while also implementing IntoOwned<<T as ToOwned>::Owned> for &T?

How would that translate to my example here?

Would this be just:

trait Parse<T: ?Sized> {
    type Pointer<'a>: IntoOwned<<Self as ToOwned>::Owned> + Borrow<Self> + Debug
    where
        Self: 'a;
    fn parse(&self) -> Option<Self::Pointer<'_>>;
}

?

I guess that could work (but breaks deref). Now you could say:

Why do I want deref coercion? Because if I work solely with references, deref works too! If I work with Cow, then deref works also. If I always return an owned value (without wrapper), then deref doesn't work but I don't need it either. So yes, this is about ergonomics! :smile:

Following your proposal, I don't always return an owned value, a smart-pointer, or a reference (for each of those three, ergonomics would be nice). Instead I return an unhandy "thing", which requires .borrow() or .into_owned() to be used.

I feel like the abstraction you made doesn't cover &'a T correctly (which is Deref). I.e. when I can't use &'a T but have to use that "thing" (sorry for the terminology, I have no better word for it), then I lose ergonomics. Thus the "thing" isn't a proper generalization of &'a T.

Maybe that can be solved somehow though?

Maybe it is because std lacks IntoOwned? :see_no_evil:

I see what you mean:

  • optimization because it can avoid an unnecessary clone (i.e. if we would just set T = Self)
  • generalization because IntoOwned doesn't require a type argument T

You mean that IntoOwned should automatically be implemented for i32 or any other "plain owned type"?

Even if that was possible, I wonder if there's a solution for ergonomics:

[…] if I work solely with references, deref works too! If I work with Cow, then deref works also. If I always return an owned value (without wrapper), then deref doesn't work but I don't need it either.

Following your proposal, [...] I return an unhandy "thing", which requires .borrow() or .into_owned() to be used.

Don't get me wrong, I think it would be great if:

  • IntoOwned could be implemented for any "owned" T (without the Owned wrapper).
  • Ergnomics of my example here are not impaired.

You could say Owned isn't very ergonomic either, but I'd like to point out that having to use Owned in that example is limited to the trait implementation and doesn't need to be known by its users or be reflected in the interface somehow (except Deref).


Update:

Note that while Owned is needed in case of the GAT, it's not needed in the following example anymore:

In the above example, Owned can be omitted, i.e.:

generic_fn("Echo".to_string());

works just fine.

(Edit: This doesn't work anymore in the recent version 0.4.0 of deref_owned, see test source, where the Owned wrapper is needed again, and the following post for a motivation.)

(Test case in source code of deref_owned)

I really only need Owned in case of the GAT, where I feel the terminology "smart pointer to its owned value" would be fitting: