I am under the impression that if ref2
is derived from ref1
, then ref1
needs to outlive ref2
, as the example:
struct Foo<'a> {
x: &'a mut i32,
}
impl<'a> Foo<'a> {
fn x(&mut self) -> &'a mut i32 { self.x }
}
fn main() {}
This will generate an error
error: lifetime may not live long enough
--> src/main.rs:6:38
|
5 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
6 | fn x(&mut self) -> &'a mut i32 { self.x }
| - ^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
| |
| let's call the lifetime of this reference `'1`
error: could not compile `playground` due to previous error
and deleting 'a like fn x(&mut self) -> &mut i32 { self.x }
will fix it, elision rule making self outlive the returned.
But this code can be compiled:
use std::collections::HashMap;
#[derive(Copy, Clone)]
struct Function<'a> {
name: &'a str,
}
struct Context<'a> {
program: HashMap<&'a str, Function<'a>>,
call_stack: Vec<Function<'a>>,
}
impl<'a> Context<'a> {
fn get_function(&mut self, fun_name: &str) -> Result<Function<'a>, ()> { // line 1
self.program
.get(fun_name)
.map(|f| *f)
.ok_or(())
}
fn call(&mut self, fun_name: &'a str) -> Result<(), ()> {
let fun = self.get_function(fun_name)?;
self.call_stack.push(fun);
Ok(())
}
}
fn main() {}
For line 1, though the returned Result<Function<'a>, ()>
requires 'a
, the lifetimes of self
and fun_name
are not required to outlive 'a. In fact, if 'a is added to self
and fun_name
(code), there will be an error: error[E0499]: cannot borrow
self.call_stackas mutable more than once at a time
.
Why Rust has different constraints for the two snippets?
Are there any documentation giving you a complete mental model of how lifetime works? Though I am sorta familiar with lifetime, It seems to surprise me from time to time