简体   繁体   English

由于需求冲突,无法为 autoref 推断适当的生命周期

[英]Cannot infer an appropriate lifetime for autoref due to conflicting requirements

I'm having lifetime issues with a particular function in my code.我在我的代码中遇到了特定功能的终身问题。 I'm following a tutorial in an attempt to learn Rust and SDL.我正在学习 Rust 和 SDL 的教程。 The tutorial was slightly older and the SDL library has changed since its been written, so I'm following along while also adapting it towards the latest version of Rust-SDL.本教程稍早,并且 SDL 库自编写以来发生了变化,因此我正在跟进,同时还将其调整为最新版本的 Rust-SDL。

The lifetime problem is in this function:生命周期问题在这个函数中:

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)
    })
}

particularly with the line self.ttf_context.load_font(Path::new(font_path), size as u16).ok() .特别是self.ttf_context.load_font(Path::new(font_path), size as u16).ok() The commented line above it is the old SDL version's font loading method.它上面的注释行是旧 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>

The struct object for that implementation looks like this:该实现的结构对象如下所示:

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>>
}

The method is trying to load a font from Phi's ttf_context and load it into the hashmap.该方法试图从 Phi 的ttf_context加载字体并将其加载到哈希图中。 The Rust compiler suggested I add a lifetime to self in the function parameters, which, when I did that, caused a cascading effect to adding lifetimes to every method calling the original one, all the way down to main() and didn't help anything. Rust 编译器建议我在函数参数中为self添加一个生命周期,当我这样做时,会导致级联效应为调用原始方法的每个方法添加生命周期,一直到main()并且没有帮助任何事物。

Since I'm still new to Rust, I'm not sure where the lifetime conflict resides or why this is happening.由于我还是 Rust 的新手,我不确定生命周期冲突在哪里或为什么会发生这种情况。 As a guess, I'm thinking that the Font object that is being generated is supposed to die with the end of that method but instead it's being loaded into a hashmap with a lifetime of 'window and those two conflict.作为猜测,我认为正在生成的Font对象应该在该方法结束时消失,但它被加载到一个生命周期为'window和这两个冲突的哈希图中。 I don't know enough about Rust to fix that, though, or if that's even correct.不过,我对 Rust 的了解不够,无法解决这个问题,或者这是否正确。

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:具体来说,代码说明了以下几点:

  1. Phi is going to include a reference to a Window . Phi将包含对Window的引用。 That referred-to value lives for the lifetime 'window .被引用的值在生命周期'window

  2. Phi is going to include a Font , which contains a reference. Phi将包含一个Font ,其中包含一个引用。 That referred-to value lives for the lifetime 'window .被引用的值在生命周期'window

  3. FontLoader returns a Font which contains a reference to a value with the lifetime of the loader . FontLoader返回一个Font ,其中包含对具有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.我强烈建议将#![deny(rust_2018_idioms)]到您的箱子中,这将禁止这种特定类型的生命周期推断。

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 .然后代码尝试从PhiFontLoader加载一个Font ,它没有生命周期'window并将该Font存储到Phi FontLoader (and thus Font ) does not live long enough, so it cannot be stored in Phi . FontLoader (以及Font )的寿命不够长,所以它不能存储在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.在这里,我重命名了生命周期,因为它不再严格用于窗口。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rust:由于要求冲突,无法推断 autoref 的适当生命周期 - Rust: cannot infer an appropriate lifetime for autoref due to conflicting requirements 尝试将具有生命周期的返回值设置为结构时,由于存在冲突的要求,无法推断出 autoref 的适当生命周期 - Cannot infer an appropriate lifetime for autoref due to conflicting requirements when tried to set a return value with lifetime to a struct `由于需求冲突,无法为 autoref 推断适当的生命周期`,但由于特征定义约束,无法更改任何内容 - `cannot infer an appropriate lifetime for autoref due to conflicting requirements` but can't change anything due to trait definition constraints 创建引用错误的递归列表“由于要求冲突,无法推断 autoref 的适当生命周期” - Creating a recursive list of references errors with "cannot infer an appropriate lifetime for autoref due to conflicting requirements" 错误:由于需求冲突,无法推断autoref的适当生命周期[E0495] - error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495] Rust:错误[E0495]:由于需求冲突,无法为 autoref 推断合适的生命周期 - Rust: error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements 由于需求冲突,无法推断出合适的生命周期 - Cannot infer an appropriate lifetime due to conflicting requirements 尝试实现迭代器:由于需求冲突而无法推断出适当的生存期 - Trying to implement an iterator: cannot infer an appropriate lifetime due to conflicting requirements 由于需求冲突,无法推断出自动强制的适当寿命 - cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements 由于需求冲突,无法为借用表达式推断出适当的生命周期 - cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM