Shared access: both as concrete type and as trait

Hello. I have a trait T and a Struct S implementing T. I also have an instance of S, s, which I’m accessing as Arc<RwLock<Box<dyn T>>. Can I somehow simultaneously access it as Arc<RwLock<S>>? Some of the accesses know the concrete type, and some don’t. In a sense I want to share the lock, but allow access both as trait and concrete type. I can’t figure out how to do it. I guess I could use downcasting à la, but that feels like a workaround when some code paths already know the concrete type.

A Arc<RwLock<S>> can coerce into a Arc<RwLock<dyn T>>, so you can just store the concrete version and if needed pass it to a function that needs the dyn version and it will coerce to the dyn version for you.

@RustyYato Oh, that’s great! I can’t seem to get it to work though, could you help out? My naive attempt:

Remove the Box, sorry I made a mistake when copying. Fixed it now. A Arc<RwLock<S>> can coerce into a Arc<RwLock<dyn T>>, not a Arc<RwLock<Box<dyn T>>>

Thank you. That works. So one doesn’t need Box anymore now with dyn?

No, it’s just that RwLock, like many other pointer lile types in Rust have a ?Sized bound on its generic parameter, this means that it can handle unsized types like trait objects.

Other notable examples include Arc, Rc, Box, Cell, RefCell, Mutex, & and &mut. And you can even coerce nested pointer like types.

1 Like

Interesting. I’ll investigate. Thank you!

1 Like

Worth noting that RwLock isn’t a pointer type. It stores its data directly inside the struct, so if T is unsized, so is RwLock<T>. The only reason Arc<RwLock<dyn Trait>> works is because Arc is a pointer type, so it can handle the unsized RwLock<dyn Trait>.

1 Like

Yes, I forgot about that, same thing with Mutex, Cell, and RefCell, they can only be used in conjunction with a pointer like type