Generic hierarchical read-modify-write cache in Rust

I have an application that works fine with dyn so far, but I need to convert it to generic, so I created a minimal verifiable example of the problem. I would really appreciate your help.

Basically this represents a read-only cache that can later be flushed into the database (parent). The problem I'm facing now is that the current View (without generic) cannot be Send + Sync because the database layer underneath (the database transaction, specifically) cannot be Send + Sync because it's unnecessary and generally databases don't support that.

But now I have another parent that needs this to be Send + Sync when it's not using the database as parent.

So, to solve this problem, the only solution I found is to change ViewCow<'a> to ViewCow<'a, P>, where the dyn View becomes P, and P is ?Sized. In this model, I'm hoping that whether P is Send + Sync can be identified through P.

However, this isn't working as expected. As you see in the minimal verifiable example with generics (that doesn't compile). I'm arriving to a circular problem, where if I defined something as ?Sized, the match clause breaks. If I remove it, trait bounds are broken.

Can you please help me in getting this to compile?

TL;DR: this compiles.

The long story Part One is that you can't coerce a ?Sized to a dyn Trait, because unsized coercion requires "fattening" the pointer (storing the vtable pointer next to the data pointer), but that's impossible if you already have a fat pointer (since currently every fat pointer is made of exactly 2 pointers).

The Long Story Part Two is that for this reason, you should basically get rid of all the ?Sized bounds in most circumstances. So I removed all of those, expecting to use Box<dyn View> wherever required, by adding a forwarding impl View for Box<dyn View>. But then I wondered why the compiler complains that dyn View is unsized.

Turns out, in the ViewCow::Owned variant, you already stored a Box<P>. That's pretty much non-idiomatic and unnecessary, and it was in fact why the compiler complained. So I removed that as well, and now ViewCow::Owned only contains a P and not a Box<P>.

As a side note, you might also want to impl<P: View> View for &P and for &mut P as well.

Thank you very much for your response. I learned a lot from it.

I forgot a detail that there's a derive_child in the View which requires ?Sized. But since forgetting to mention that is totally my fault, I'll resolve this question and ask it again with that detail after a few attempts to get rid of it since it seems to be complicating things for no good reason.

Thanks again. Have a great day/evening. Cheers!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.