Hello, I'm trying to understand lifetime subtyping, and why the compiler is complaining about my code
struct FooRef<'o> {
pub foo_ref: &'o dyn DoesFoo<'o>,
}
struct FooRefSet<'o> {
pub foo_refs: Vec<FooRef<'o>>,
}
trait DoesFoo<'o> {
fn foo(&'o self, set: &mut FooRefSet<'o>);
}
struct SomeType {}
impl<'o> DoesFoo<'o> for SomeType {
fn foo(&'o self, set: &mut FooRefSet<'o>) {
set.foo_refs.push(FooRef { foo_ref: self })
}
}
struct Container<'o> {
pub foos: Vec<Box<dyn DoesFoo<'o>>>,
}
impl<'c, 'o: 'c> Container<'o> {
fn collect_foos(&'c self, set: &mut FooRefSet<'o>) {
for x in &self.foos {
x.foo(set);
}
}
}
fn main() {
let mut container = Container { foos: Vec::new() };
container.foos.push(Box::new(SomeType {}));
let mut set = FooRefSet {
foo_refs: Vec::new(),
};
container.collect_foos(&mut set);
}
When I try to compile this, I receive the error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src\main.rs:25:18
|
25 | for x in &self.foos {
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'c` as defined on the impl at 23:6...
--> src\main.rs:23:6
|
23 | impl<'c, 'o: 'c> Container<'o> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:25:18
|
25 | for x in &self.foos {
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'o` as defined on the impl at 23:10...
--> src\main.rs:23:10
|
23 | impl<'c, 'o: 'c> Container<'o> {
| ^^
note: ...so that the types are compatible
--> src\main.rs:26:15
|
26 | x.foo(set);
| ^^^
= note: expected `&'o dyn DoesFoo<'o>`
found `&dyn DoesFoo<'o>`
Since &self
in collect_foos
function has a lifetime of 'c
, I would assume it would be compatible with 'o
, but apparently my assumption is wrong. Could anyone help shed some light on why this doesn't work as I'm expecting? Thank you!