Ah, now I understand that part. Yes, that makes sense.
Okay, but at what price?
I think both your approach as well as my approach has downsides. Perhaps it's ultimately a matter of taste?
Exactly my point.

Returning a type is always a less complex API surface for callers than returning some
impl Trait
.
Using a trait is sometimes painful because it requires the user of a crate to bring all necessary traits in scope. See also: Pub use Trait as _ for more hygiene.
That's why I said earlier:

Side note: I hate how I have to import the trait in order to be able to use it. Maybe sealed traits should/could be automatically imported when you import a module?
With non-sealed traits (like GenericCow
), however, it can be a hygiene problem, as they might be implemented by other crates.
On the other hand:
- It's possible that
mmtkvdb
re-exportsderef_owned::GenericCow
, thusGenericCow
can be seen as part ofmmtkvdb
. Of course, then this argument still strikes:

My point here is that using
fn(impl GenericCow)
requires type hackery (e.g. inOwned
or another custom lookalike), because a standard usecase of "T as Cow::Owned
" requires knowledge of a) why this isn't already the case, requiring knowing b) how to implement aLiftOwned
to provide the obvious impl. Thus while the definition ofGenericCow
is itself straightforward, its use is not.
- But regarding "straightforwardness", I feel like
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Owned<T>(pub T);
impl<B> Borrow<B> for Owned<<B as ToOwned>::Owned>
where
B: ?Sized + ToOwned,
{
fn borrow(&self) -> &B {
self.0.borrow()
}
}
is less trickery than what was needed in your playground here:

Well, it wasn't so small after all. […] [playground]
(Even if this can be encapsulated/hidden from the user. But a maintainer of mmtkvdb
or a fork of it would have to overlook it.)
My mind has already been almost exploding several times. Understanding this issue was several days of work (but I learned a lot during that process, admittingly).
I think I was violating everything that this video would have taught me if I had seen it earlier (quote from another thread):
The reason of my asking is this video on yutube..
The Importance of Not Over-Optimizing in Rust
She says:
Beginners, to avoid painful things in rust
a. use owned vars
b. use clone()
c. compile as release
d. use rc() and arc()I had believing Rc is for experienced devs..
I feel like adding yet another (non-generic) wrapper structure makes things even worse for me.
- In practice, the lack of
MethodReceiver<T>
might not be so bad. Consider this:
struct Fancy;
impl Fancy {
fn fancy(&self) {
println!("YAY!")
}
}
struct SomeType;
trait Abstract {
type Retval; // no bounds at all
fn foo(&self) -> Self::Retval;
}
impl Abstract for SomeType {
type Retval = Fancy;
fn foo(&self) -> Self::Retval {
Fancy
}
}
fn main() {
let v = SomeType;
// we can call `.fancy()`, even if `Abstract::Retval` has no bounds
v.foo().fancy();
}
(Preliminary) Conclusion
I would like to give my own (preliminary) conclusion from this discussion:
- My original approach (e.g.
deref_owned
version 0.2.0) was flawed because it "abused"Deref
(seeIntoOwned
in version 0.2.0). (Many thanks to you for helping me figuring that out and being so patient with me.) - This has been solved by using
Borrow
instead (seeGenericCow
in version 0.8.0). - Ergonomics of
GenericCow
are somewhat limited. In the generic case, deref-coercion won't work and we need the weirdOwned
wrapper when providing an always-ownedGenericCow
value. - However, ergonomics aren't totally bad:
- In the concrete case, deref-coercion still works (see also Playground above) because for example
Owned
still implementsDeref
(without abusing it for wrong reasons and without impeding transitivity of dereferencing). - Writing
Owned(x)
instead ofCow::Owned(x)
isn't really that hard. In fact it's shorter.
- In the concrete case, deref-coercion still works (see also Playground above) because for example
- In the future, the
Owned
wrapper might or might not become superfluous. - Sometimes, providing concrete types instead of
impl Trait
may be beneficial. - Most people will just use
Cow
and not go crazy like I almost did.