trait object: specific use case of variance and/or coercion #108999
Description
Filing this as a bug report because that's my best guess for what I believe is an inconsistency. Or perhaps simply the reference would need to be updated to explain the following.
Note that I will use
<:
to denote a "subtype" relationship.
I tried this code:
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,
// }
}
}
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. Is this a bug?
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). Do we expect Rc::get_mut(&mut self.module_rc)
to work, given that (1) works?
Meta
rustc --version --verbose
:
rustc 1.68.0 (2c8cc3432 2023-03-06)
binary: rustc
commit-hash: 2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74
commit-date: 2023-03-06
host: aarch64-apple-darwin
release: 1.68.0
LLVM version: 15.0.6
Backtrace
error: lifetime may not live long enough
--> fool/src/main.rs:21:9
|
19 | fn mut_rc<'s>(&'s mut self) -> Option<&'s mut (dyn Module + 's)> {
| -- lifetime `'s` defined here
20 | // this doesn't work
21 | Rc::get_mut(&mut self.module_rc) // : Option<&'s mut (dyn Module + 'static)>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'s` must outlive `'static`
|
= note: requirement occurs because of a mutable reference to `dyn Module`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: could not compile `rust` due to previous error
Activity