Cannot infer an appropriate lifetime for autoref due to conflicting requirements
Solution 1:
Here's a smaller example that reproduces the problem:
struct FontLoader(String);
struct Font<'a>(&'a str);
impl FontLoader {
fn load(&self) -> Font {
Font(&self.0)
}
}
struct Window;
struct Phi<'window> {
window: &'window Window,
loader: FontLoader,
font: Option<Font<'window>>,
}
impl<'window> Phi<'window> {
fn do_the_thing(&mut self) {
let font = self.loader.load();
self.font = Some(font);
}
}
fn main() {}
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:20:32
|
20 | let font = self.loader.load();
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 19:5...
--> src/main.rs:19:5
|
19 | fn do_the_thing(&mut self) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:20:20
|
20 | let font = self.loader.load();
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'window` as defined on the impl at 18:6...
--> src/main.rs:18:6
|
18 | impl<'window> Phi<'window> {
| ^^^^^^^
note: ...so that the expression is assignable
--> src/main.rs:21:21
|
21 | self.font = Some(font);
| ^^^^^^^^^^
= note: expected `Option<Font<'window>>`
found `Option<Font<'_>>`
The problem is indeed that you have constructed an impossible case. Specifically, the code states these points:
-
Phi
is going to include a reference to aWindow
. That referred-to value lives for the lifetime'window
. -
Phi
is going to include aFont
, which contains a reference. That referred-to value lives for the lifetime'window
. -
FontLoader
returns aFont
which contains a reference to a value with the lifetime of the loader. This is due to lifetime inference, which when expanded looks like:impl FontLoader { fn load<'a>(&'a self) -> Font<'a> { Font(&self.0) } }
I highly encourage adding
#![deny(rust_2018_idioms)]
to your crate, which will disallow this specific type of lifetime inference.
Then the code attempts to load a Font
from the FontLoader
in Phi
, which does not have the lifetime 'window
and store that Font
into Phi
. FontLoader
(and thus Font
) does not live long enough, so it cannot be stored in Phi
.
The compiler has correctly prevented incorrect code.
Your next attempt would probably be to introduce a second lifetime:
struct Phi<'window, 'font> {
window: &'window Window,
loader: FontLoader,
font: Option<Font<'font>>,
}
impl<'window, 'font> Phi<'window, 'font> {
fn do_the_thing(&'font mut self) {
let font = self.loader.load();
self.font = Some(font);
}
}
This will actually compile, but probably doesn't do what you want. See Why can't I store a value and a reference to that value in the same struct? for further information.
More likely, you want to take a reference to the font loader:
struct Phi<'a> {
window: &'a Window,
loader: &'a FontLoader,
font: Option<Font<'a>>,
}
impl<'a> Phi<'a> {
fn do_the_thing(&mut self) {
let font = self.loader.load();
self.font = Some(font);
}
}
Here, I've renamed the lifetime as it isn't strictly for the window anymore.