«замыкание может пережить текущую функцию» при использовании в качестве параметра - PullRequest
0 голосов
/ 20 апреля 2020

Я пытаюсь передать функцию в качестве параметра и вызвать ее внутри потока. Вот код, который я пытаюсь запустить:

use std::thread;

pub struct Image {
    pub data: Vec<u8>,
}

pub trait ImageHandler {
    fn get_image(&self) -> Option<Image>;
}

pub struct Window {
    pub id: usize,
}

impl ImageHandler for Window {
    fn get_image(&self) -> Option<Image> {
        None
    }
}

fn test(func: impl Fn() -> Option<Image> + Sync + Send + 'static) -> thread::JoinHandle<()> {
    thread::spawn(move || {
        let _image = func().unwrap();
    })
}

fn main() {
    let window = Window { id: 0 };
    test(&|| window.get_image());
}

Я получаю следующие ошибки:

error[E0373]: closure may outlive the current function, but it borrows `window`, which is owned by the current function
  --> src/main.rs:30:11
   |
30 |     test(&|| window.get_image());
   |           ^^ ------ `window` is borrowed here
   |           |
   |           may outlive borrowed value `window`
   |
note: function requires argument type to outlive `'static`
  --> src/main.rs:30:5
   |
30 |     test(&|| window.get_image());
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `window` (and any other referenced variables), use the `move` keyword
   |
30 |     test(&move || window.get_image());
   |           ^^^^^^^

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:30:11
   |
30 |     test(&|| window.get_image());
   |     ------^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
   |     |     |
   |     |     creates a temporary which is freed while still in use
   |     argument requires that borrow lasts for `'static`

Я полагаю, Fn должно быть stati c для отправки это поток, но когда я изменяю его время жизни на 'static, он жалуется. Также я не знаю, возможно ли использовать ImageHandler в качестве параметра. Я не мог понять это.

1 Ответ

0 голосов
/ 20 апреля 2020

Если замыкание может пережить текущий поток, оно должно стать владельцем необходимых ему переменных:

fn main() {
    let window = Window { id: 0 };
    test(move || window.get_image());
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9cbf953b79e80e280156688d083f94fb имеет игровую площадку.

Однако, поскольку (я полагаю) это всего лишь игрушечный пример, это исправление может относиться или не применяться к вашему реальному варианту использования. Если это станет более сложным, вы можете попытаться убедить компилятор, что вы знаете, что замыкание не переживет текущий поток (возможно, с использованием вспомогательных ящиков) или прибегнет к другим методам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...