由于需求冲突,无法推断出 autoref 的适当生命周期
Cannot infer an appropriate lifetime for autoref due to conflicting requirements
我的代码中的某个特定函数存在终生问题。我正在按照教程尝试学习 Rust 和 SDL。该教程稍旧一些,SDL 库自编写以来已经发生了变化,所以我会继续学习,同时也会根据最新版本的 Rust-SDL 对其进行调整。
生命周期问题在这个函数中:
pub fn ttf_str_sprite(&mut self, text: &str, font_path: &'static str, size: i32, color: Color) -> Option<Sprite> {
if let Some(font) = self.cached_fonts.get(&(font_path, size)) {
return font.render(text).blended(color).ok()
.and_then(|surface| self.renderer.create_texture_from_surface(&surface).ok())
.map(Sprite::new)
}
//::sdl2_ttf::Font::from_file(Path::new(font_path), size).ok()
self.ttf_context.load_font(Path::new(font_path), size as u16).ok()
.and_then(|font| {
self.cached_fonts.insert((font_path, size), font);
self.ttf_str_sprite(text, font_path, size, color)
})
}
特别是 self.ttf_context.load_font(Path::new(font_path), size as u16).ok()
行。上面的注释行是老SDL版本的字体加载方式。
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\phi/mod.rs:57:26
|
57 | self.ttf_context.load_font(Path::new(font_path), size as u16).ok()
| ^^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn ttf_str_sprite(&'window mut self, text: &str, font_path: &'static str,
size: i32, color: Color) -> Option<Sprite>
该实现的结构对象如下所示:
pub struct Phi<'window> {
pub events: Events,
pub renderer: Renderer<'window>,
pub ttf_context: Sdl2TtfContext,
cached_fonts: HashMap<(&'static str, i32), ::sdl2_ttf::Font<'window>>
}
该方法试图从 Phi 的 ttf_context
加载字体并将其加载到哈希图中。 Rust 编译器建议我在函数参数中向 self
添加生命周期,当我这样做时,会产生级联效应,为每个调用原始方法的方法添加生命周期,一直到 main()
并没有任何帮助。
由于我对 Rust 还是个新手,所以我不确定生命周期冲突在哪里或为什么会发生这种情况。作为一个猜测,我认为正在生成的 Font
对象应该在该方法结束时消失,而是被加载到生命周期为 'window
的哈希图中,而这两个冲突。不过,我对 Rust 了解不够,无法解决这个问题,或者这是否正确。
这是一个重现问题的小例子:
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<'_>>`
问题确实是你构造了一个不可能的情况。具体来说,代码说明了以下几点:
Phi
将包含对 Window
的引用。该参考价值终生存在 'window
.
Phi
将包含一个 Font
,其中包含一个引用。该参考价值终生存在 'window
.
FontLoader
returns 一个 Font
,其中包含对加载器 生命周期 的值的引用。这是由于生命周期推断,展开后如下所示:
impl FontLoader {
fn load<'a>(&'a self) -> Font<'a> {
Font(&self.0)
}
}
我强烈建议将 #![deny(rust_2018_idioms)]
添加到您的箱子中,这将禁止这种特定类型的生命周期推断。
然后代码尝试从 Phi
中的 FontLoader
加载一个 Font
, 没有 的生命周期 'window
并将 Font
存储到 Phi
中。 FontLoader
(因此 Font
)的寿命不够长,因此无法存储在 Phi
.
中
编译器正确地防止了不正确的代码。
您的下一次尝试可能是引入第二人生:
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);
}
}
这实际上可以编译,但可能不会执行您想要的操作。有关详细信息,请参阅 。
更有可能的是,您想引用字体加载器:
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);
}
}
在这里,我重命名了生命周期,因为它不再严格用于 window。
我的代码中的某个特定函数存在终生问题。我正在按照教程尝试学习 Rust 和 SDL。该教程稍旧一些,SDL 库自编写以来已经发生了变化,所以我会继续学习,同时也会根据最新版本的 Rust-SDL 对其进行调整。
生命周期问题在这个函数中:
pub fn ttf_str_sprite(&mut self, text: &str, font_path: &'static str, size: i32, color: Color) -> Option<Sprite> {
if let Some(font) = self.cached_fonts.get(&(font_path, size)) {
return font.render(text).blended(color).ok()
.and_then(|surface| self.renderer.create_texture_from_surface(&surface).ok())
.map(Sprite::new)
}
//::sdl2_ttf::Font::from_file(Path::new(font_path), size).ok()
self.ttf_context.load_font(Path::new(font_path), size as u16).ok()
.and_then(|font| {
self.cached_fonts.insert((font_path, size), font);
self.ttf_str_sprite(text, font_path, size, color)
})
}
特别是 self.ttf_context.load_font(Path::new(font_path), size as u16).ok()
行。上面的注释行是老SDL版本的字体加载方式。
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src\phi/mod.rs:57:26
|
57 | self.ttf_context.load_font(Path::new(font_path), size as u16).ok()
| ^^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn ttf_str_sprite(&'window mut self, text: &str, font_path: &'static str,
size: i32, color: Color) -> Option<Sprite>
该实现的结构对象如下所示:
pub struct Phi<'window> {
pub events: Events,
pub renderer: Renderer<'window>,
pub ttf_context: Sdl2TtfContext,
cached_fonts: HashMap<(&'static str, i32), ::sdl2_ttf::Font<'window>>
}
该方法试图从 Phi 的 ttf_context
加载字体并将其加载到哈希图中。 Rust 编译器建议我在函数参数中向 self
添加生命周期,当我这样做时,会产生级联效应,为每个调用原始方法的方法添加生命周期,一直到 main()
并没有任何帮助。
由于我对 Rust 还是个新手,所以我不确定生命周期冲突在哪里或为什么会发生这种情况。作为一个猜测,我认为正在生成的 Font
对象应该在该方法结束时消失,而是被加载到生命周期为 'window
的哈希图中,而这两个冲突。不过,我对 Rust 了解不够,无法解决这个问题,或者这是否正确。
这是一个重现问题的小例子:
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<'_>>`
问题确实是你构造了一个不可能的情况。具体来说,代码说明了以下几点:
Phi
将包含对Window
的引用。该参考价值终生存在'window
.Phi
将包含一个Font
,其中包含一个引用。该参考价值终生存在'window
.FontLoader
returns 一个Font
,其中包含对加载器 生命周期 的值的引用。这是由于生命周期推断,展开后如下所示:impl FontLoader { fn load<'a>(&'a self) -> Font<'a> { Font(&self.0) } }
我强烈建议将
#![deny(rust_2018_idioms)]
添加到您的箱子中,这将禁止这种特定类型的生命周期推断。
然后代码尝试从 Phi
中的 FontLoader
加载一个 Font
, 没有 的生命周期 'window
并将 Font
存储到 Phi
中。 FontLoader
(因此 Font
)的寿命不够长,因此无法存储在 Phi
.
编译器正确地防止了不正确的代码。
您的下一次尝试可能是引入第二人生:
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);
}
}
这实际上可以编译,但可能不会执行您想要的操作。有关详细信息,请参阅
更有可能的是,您想引用字体加载器:
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);
}
}
在这里,我重命名了生命周期,因为它不再严格用于 window。