我的代码中有特定功能的终身问题。我正在按照教程学习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>
该实现的struct对象如下所示:
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
加载字体并将其加载到hashmap中。 Rust编译器建议我在函数参数中为self
添加一个生命周期,当我这样做时,会导致级联效果,为每个调用原始方法的方法添加生命周期,一直到{{1}并且没有任何帮助。
由于我还不熟悉Rust,我不确定生命冲突所在的位置或为什么会发生这种情况。作为猜测,我认为正在生成的main()
对象应该在该方法结束时死亡,而是将其加载到生命周期为{{的hashmap中。 1}}和那两个冲突。但是,我对Rust没有足够的了解来解决这个问题,或者说这是否正确。
答案 0 :(得分:15)
这是一个重现问题的小例子:
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();
| ^^^^
|
问题确实是你构建了一个不可能的案例。具体来说,代码说明了这些要点:
Phi
将包含对Window
的引用。所提到的价值终生存在'window
。Phi
将包含Font
,其中包含引用。所提到的价值终生存在'window
。 FontLoader
返回Font
,其中包含对加载程序的生命周期的值的引用。这是由于终身推断,当扩展时看起来像:
impl FontLoader {
fn load<'a>(&'a self) -> Font<'a> {
Font(&self.0)
}
}
然后,代码尝试从Font
FontLoader
加载Phi
,不拥有生命周期'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);
}
}
中。
编译器已正确防止错误代码。
你的下一次尝试可能是引入第二次生命:
pd
这实际上会编译,但可能不会做你想要的。有关详细信息,请参阅Why can't I store a value and a reference to that value in the same struct?。
更有可能的是,您想要引用字体加载器:
sns
在这里,我已经重命名了生命周期,因为它不再严格用于窗口了。