thruun
thruun

Reputation: 501

Cannot infer an appropriate lifetime when building a struct with multiple references with the same lifetime

I've seen multiple posts like this or this but I think this is no duplicate. I guess I haven't quite understood how to use lifetimes to outlive one another. Here is a MWE:

struct Point;

pub struct Line<'a> {
    pub start: &'a Point,
    pub end: &'a Point,
}

impl<'a> Line<'a> {
    pub fn new(start: &Point, end: &Point) -> Self {
        Line {
            start: start,
            end: end,
        }
    }
}

fn main() {}

I get the error message

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:10:9
   |
10 |         Line {
   |         ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 9:51...
  --> src/main.rs:9:52
   |
9  |       pub fn new(start: &Point, end: &Point) -> Self {
   |  ____________________________________________________^
10 | |         Line {
11 | |             start: start,
12 | |             end: end,
13 | |         }
14 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:12:18
   |
12 |             end: end,
   |                  ^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 9:51...
  --> src/main.rs:9:52
   |
9  |       pub fn new(start: &Point, end: &Point) -> Self {
   |  ____________________________________________________^
10 | |         Line {
11 | |             start: start,
12 | |             end: end,
13 | |         }
14 | |     }
   | |_____^
note: ...so that expression is assignable (expected Line<'a>, found Line<'_>)
  --> src/main.rs:10:9
   |
10 | /         Line {
11 | |             start: start,
12 | |             end: end,
13 | |         }
   | |_________^

and I am completely lost about how to interpret it.

Upvotes: 1

Views: 515

Answers (1)

ljedrz
ljedrz

Reputation: 22283

You need to explicitly specify the lifetime of both parameters so that they are the same:

impl<'a> Line<'a> {
    pub fn new(start: &'a Point, end: &'a Point) -> Self {
        Line {
            start: start,
            end: end,
        }
    }
}

Otherwise the compiler cannot decide which input lifetime to choose for the output. I recommend the relevant Rust Book section on lifetime elision, especially the following 3 rules:

  • Each elided lifetime in a function’s arguments becomes a distinct lifetime parameter.
  • If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function.

  • If there are multiple input lifetimes, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.

Otherwise, it is an error to elide an output lifetime.

Upvotes: 3

Related Questions