簡體   English   中英

由於需求沖突,無法為 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<'_>>`

問題確實是您構建了一個不可能的案例。 具體來說,代碼說明了以下幾點:

  1. Phi將包含對Window的引用。 被引用的值在生命周期'window

  2. Phi將包含一個Font ,其中包含一個引用。 被引用的值在生命周期'window

  3. FontLoader返回一個Font ,其中包含對具有loader生命周期值的引用。 這是由於生命周期推斷,擴展后看起來像:

     impl FontLoader { fn load<'a>(&'a self) -> Font<'a> { Font(&self.0) } }

    我強烈建議將#![deny(rust_2018_idioms)]到您的箱子中,這將禁止這種特定類型的生命周期推斷。

然后代碼嘗試從PhiFontLoader加載一個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);
    }
}

在這里,我重命名了生命周期,因為它不再嚴格用於窗口。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM