I have the following code:
#[derive(Debug)]
struct S<'a> {
pub ss: Vec<String>,
pub rs: Vec<&'a str>, // each element in rs is a reference to the corresponding element in ss
}
impl<'a> S<'a> {
pub fn new() -> Self {
Self { ss: Vec::new(), rs: Vec::new() }
}
pub fn push(&mut self, s: String) {
self.ss.push(s);
self.rs.push(self.ss.last().unwrap());
}
}
fn main() {
let mut x = S::new();
let s = String::from("hello");
x.push(s);
// XXX: the following works!
// x.ss.push(s);
// x.rs.push(x.ss.last().unwrap());
// println!("hello world: {:#?}", x);
}
And the compiler generates the error:
Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:14:30
|
14 | self.rs.push(self.ss.last().unwrap());
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:12:17
|
12 | pub fn push(&mut self, s: String) {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:14:22
|
14 | self.rs.push(self.ss.last().unwrap());
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:7:6
|
7 | impl<'a> S<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:14:22
|
14 | self.rs.push(self.ss.last().unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground` due to previous error
However, the two lines below XXX does work!
How can I make the compiler happy?
Rust Playground
[EDIT]: of course, I have to admit that the design is flawed - what if an element is removed from ss
, then without other compiler aware guarantees, the corresponding reference in rs
would become dangling - the compiler can only be conservative here as to reject the code above. But, what about using unsafe Rust to achieve that, if the programmer can provide the safety guarantee?