Обход лимитов времени жизни переменных, заимствованных закрытием - PullRequest
0 голосов
/ 25 мая 2020

Я использую следующий код для запуска моей функции render::exec при каждом возникновении события RedrawRequested (выпущенного Glium):

event_loop.run(move |event, _, control_flow| {
    match event {
        Event::RedrawRequested(_) => {
            let mut target = display.draw();
            render::exec(&mut target, &mut ctx, &font, &mut cache);
            target.finish().unwrap();
        }

        // ...

        _ => ()
    }
});

Проблема в том, что я получение следующей ошибки в ссылке &font:

borrowed data cannot be stored outside of its closure

font действительно создается перед вызовом event_loop.run, поскольку это структура rusttype::Font, которая мне нужна для отображения текста внутри моего приложения Glium. Я понимаю, что, поскольку это закрытие move, данные из font будут освобождены в конце, поэтому средство проверки заимствований не позволяет создавать font вне закрытия, потому что это не гарантирует, что закрытие не будет вызываться более одного раза (и действительно, вызывается более одного раза).

Я попытался обойти это, удалив move ключевое слово, но затем возникает следующая ошибка для каждой из переменных, которые я заимствую из закрытия:

closure may outlive the current function, but it borrows `ctx`, which is owned by the current function
may outlive borrowed value `ctx`

Я понимаю, что, поскольку средство проверки заимствований не может гарантировать, что эти переменные прослужат как минимум до тех пор, пока закрытие, оно не позволит ссылаться на последнее изнутри первого.

Следовательно, Мне нужен способ гарантировать, что эти переменные будут длиться как минимум до закрытия . Один из способов сделать это обычно - передать их в качестве параметров в закрытие, но я фактически не могу изменить список передаваемых параметров, так как я использую event_loop.run, который имеет следующую сигнатуру:

pub fn run<F>(self, event_handler: F) -> !
where F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget<T>, &mut ControlFlow)

Я просмотрел документацию Glutin и не смог найти способ сохранить какие-либо данные в EventLoop (это тип, который дает разыменование EventLoopWindowTarget), ни в ControlFlow, который передается как параметр

1 Ответ

1 голос
/ 25 мая 2020
Шрифт

действительно создается перед вызовом event_l oop .run, поскольку это структура rusttype :: Font, которая мне нужна для визуализации текста внутри моего приложения Glium. Я понимаю, что, поскольку это закрытие хода, данные из шрифта будут освобождены в конце, поэтому средство проверки заимствований не позволяет создавать шрифт за пределами закрытия, потому что не гарантируется, что закрытие не будет вызываться более одного раза (и действительно, оно вызывается более одного раза).

Это неверно. Его не волнует, что font создается до закрытия, потому что он перемещается в после закрытия. Аналогично вызов закрытия более одного раза, не имеет значения, шрифт теперь принадлежит замыканию.

Замыкание - это структура со связанной функцией, все переменные, которые являются частью среды, действительно установлены как члены структуры, из которой они могут быть извлечены при вызове функции для заполнения свободных переменных. Вот и все. У него нет конкретной c проблемы с созданием элементов за пределами закрытия (как еще вы закрыли бы их?) Или с многократным вызовом закрытий.

let font = Font;
let t: u8 = (0..5).map(move |_| Font::thing(&font)).sum();

Ошибка говорит о том, что внутри закрытие, вы занимаетесь чем-то и пытаетесь переместить этот заем за пределы закрытия.

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