Consider the following (playground)
trait Module {}
struct Foo {
module_box: Box<dyn Module + 'static>,
module_rc: Rc<dyn Module + 'static>,
}
impl Foo {
fn mut_box<'s>(&'s mut self) -> &'s mut (dyn Module + 's) {
// this works
self.module_box.as_mut() // : &'s mut (dyn Module + 'static)
}
fn mut_rc<'s>(&'s mut self) -> Option<&'s mut (dyn Module + 's)> {
// this doesn't work
Rc::get_mut(&mut self.module_rc) // : Option<&'s mut (dyn Module + 'static)>
// but this does
// match Rc::get_mut(&mut self.module_rc) {
// Some(m) => Some(m),
// None => None,
// }
}
}
Note: I will use
<:
to denote a subtype relationship
I have 2 related questions:
- why does the
mut_box()
implementation work? - why doesn't the
mut_rc()
implement work?
For (1), I first assumed that subtyping/variance was the reason, since (dyn Module + 'static) <: (dyn Module + 's)
(although I wasn't able to 100% confirm). However, according to the reference, &'a mut T
is invariant over T
; so if I'm reading this correctly, &'s mut (dyn Module + 'static)
is NOT a subtype of &'s mut (dyn Module + 's)
. I then thought maybe an implicit coercion could then explain why it compiled, but was not able to find one in the list of coercion types.
Question (2) is very similar, except that the whole thing is wrapped in an Option
, which seems to be the reason why it fails; the commented-out code unwraps the Option
, which I believe sends us back to (1).