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!
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
?
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 argumentT
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 theOwned
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: