abasar
abasar

Reputation: 135

cannot infer an appropriate lifetime for lifetime parameter with multiple references with the same lifetime inside a struct [E0495]

I had gotten an error in my code about lifetime inferrence, and I have been able to reduce the code to the following:

use std::collections::HashMap;

struct A<'a> {
    x: &'a mut HashMap<&'a str, i32>,
}

impl<'a> A<'a> {
    fn new(x: &'a mut HashMap<&'a str, i32>) -> Self {
        Self { x }
    }
    
    fn test(&mut self) {
        let a = A::new(self.x);
    }
}

fn main() {
}

The error that results from this is

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:13:17
   |
13 |         let a = A::new(self.x);
   |                 ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
  --> src/main.rs:12:5
   |
12 | /     fn test(&mut self) {
13 | |         let a = A::new(self.x);
14 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:13:24
   |
13 |         let a = A::new(self.x);
   |                        ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 7:6...
  --> src/main.rs:7:6
   |
7  | impl<'a> A<'a> {
   |      ^^
note: ...so that the expression is assignable
  --> src/main.rs:13:24
   |
13 |         let a = A::new(self.x);
   |                        ^^^^^^
   = note: expected `&mut std::collections::HashMap<&str, i32>`
              found `&mut std::collections::HashMap<&'a str, i32>`

I do not understand what is the error in this case, but I did find that if I add a lifetime 'b to struct A, such that the str reference in the HashMap has a lifetime of 'b, the codes does compile. Here is how the code looks like after the aforementioned change:

use std::collections::HashMap;

struct A<'a, 'b> {
    x: &'a mut HashMap<&'b str, i32>,
}

impl<'a, 'b> A<'a, 'b> {
    fn new(x: &'a mut HashMap<&'b str, i32>) -> Self {
        Self { x }
    }
    
    fn test(&mut self) {
        let a = A::new(self.x);
    }
}

fn main() {
}

However, I have no idea why that change works. To my understanding, having both lifetimes be 'a means that A must live as long as the HashMap, and the HashMap must live as long as the &strs that are used as its keys, which I see no issue with. I also do not see how the change adds any additional information for the compiler. Can anyone please shed some light for me on this situation?

Upvotes: 0

Views: 311

Answers (1)

dianhenglau
dianhenglau

Reputation: 504

Change the A::test() function into

fn test(&'a mut self) { // Add lifetime specification
    let a = A::new(self.x);
}

and it should work.

The compiler said it cannot infer lifetime for A::new(), and the first note mentioned "anonymous lifetime", that means the compiler doesn't know the lifetime of self.x in A::new(self.x). So we just need to tell the compiler that self has a lifetime of 'a.

Upvotes: 1

Related Questions