2016-12-21 17 views
6

Tôi đang gặp sự cố với một chức năng cụ thể trong mã của mình. Tôi đang theo một hướng dẫn trong một nỗ lực để tìm hiểu Rust và SDL. Hướng dẫn này hơi cũ hơn và thư viện SDL đã thay đổi kể từ khi nó được viết, vì vậy tôi đang theo dõi trong khi cũng thích nghi nó với phiên bản mới nhất của Rust-SDL.Không thể suy ra tuổi thọ thích hợp cho autoref do các yêu cầu xung đột

vấn đề

Thời gian tồn tại là trong hàm này:

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

đặc biệt là với dòng self.ttf_context.load_font(Path::new(font_path), size as u16).ok(). Dòng nhận xét ở trên là phương thức tải phông chữ của phiên bản SDL cũ.

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> 

Đối tượng struct để thực hiện trông như thế này:

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

Phương pháp này đang cố gắng tải một phông chữ từ Phi của ttf_context và tải nó vào hashmap. Trình biên dịch Rust đề nghị tôi thêm một đời vào self trong các tham số chức năng, khi tôi làm điều đó, gây ra hiệu ứng xếp tầng để tăng thêm thời gian sống cho mọi phương thức gọi là nguyên bản, xuống đến main() và không giúp gì cả.

Vì tôi vẫn còn mới với Rust, tôi không chắc nơi xung đột cuộc đời cư trú hoặc lý do điều này xảy ra. Theo dự đoán, tôi nghĩ rằng đối tượng Font đang được tạo ra được cho là sẽ chết khi kết thúc phương thức đó, nhưng thay vào đó nó được nạp vào một hashmap với tuổi thọ là 'window và hai xung đột đó. Tuy nhiên, tôi không biết đủ về Rust để khắc phục điều đó, hoặc nếu điều đó đúng.

Trả lời

6

Dưới đây là một ví dụ nhỏ mà tái tạo các vấn đề:

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(); 
    |        ^^^^ 
    | 

Vấn đề thực sự là bạn đã xây dựng một trường hợp bất khả thi. Cụ thể, mã nêu rõ các điểm sau:

  1. Phi sẽ bao gồm tham chiếu đến Window. Tham chiếu đó sống suốt đời 'window.
  2. Phi sẽ bao gồm Font, chứa tham chiếu. Tham chiếu đó sống suốt đời 'window.
  3. FontLoader trả về một Font có chứa tham chiếu có tuổi thọ của trình tải. Điều này là do suy luận suốt đời, mà khi mở rộng trông giống như:

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

Sau đó, mã cố gắng tải một Font từ FontLoader trong Phi, mà không có tuổi thọ 'window và lưu trữ mà Font vào Phi. FontLoader (và do đó Font) không đủ dài để không thể lưu trữ trong Phi.

Trình biên dịch đã ngăn chính xác mã không chính xác.


nỗ lực tiếp theo của bạn có lẽ sẽ là để giới thiệu một đời thứ hai:

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

Điều này sẽ thực sự biên dịch, nhưng có lẽ không làm những gì bạn muốn. Xem Why can't I store a value and a reference to that value in the same struct? để biết thêm thông tin.

Nhiều khả năng, bạn muốn lấy một tham chiếu đến bộ nạp font chữ:

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

Ở đây, tôi đã đổi tên cuộc đời như nó không phải là đúng cho cửa sổ nữa.

+0

Tôi đã làm việc với sự giúp đỡ của bạn! Cảm ơn! –

+0

__FontLoader (và do đó Phông chữ) không đủ dài.__: Không phải là thời gian tồn tại của 'FontLoader' giống như Phi có chứa nó? –

+0

@CarlLevasseur có, thời gian tồn tại của 'FontLoader' và' chứa 'Phi' của nó giống nhau. Tại sao bạn hỏi? – Shepmaster

Các vấn đề liên quan