Общее объяснение
Минимальное воспроизведение аналогичного выпуска:
fn move_and_print(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("Hello");
let print_cloned_s = || println!("{}", s.clone());
move_and_print(s);
print_cloned_s();
}
Компилятор жалуется:
error[E0505]: cannot move out of `s` because it is borrowed
Я хочу клонировать s
, чтобы избежать заимствования и, следовательно, получить возможность впоследствии его использовать. Итак, как компилятор может сказать, что s
заимствовано?
Это прежнее рассуждение совершенно верно, однако, есть тонкость: подпись Clone::clone
равна clone(&self) -> Self
. Поэтому, когда вызывается clone
, данные заимствуются функцией клона !
Решение состоит в том, чтобы клонировать данные до , создавая замыкание, а затем переместить их в замыкание:
fn move_and_print(s: String) {
println!("{}", s);
}
fn main() {
let s = String::from("Hello");
// I clone `s` BEFORE creating the closure:
let cloned_s = s.clone();
// Then I move the cloned data into the closure:
let print_cloned_s = move || println!("{}", cloned_s);
move_and_print(s);
print_cloned_s();
}
Решение вашей фактической ошибки
Как я уже сказал, вы должны клонировать конфигурацию и переместить этот клон в замыкание:
let cloned_config = config.clone();
application.connect_activate(move |app| {
build_ui(app, cloned_config.clone());
});
Вы также должны добавить второй вызов клона, чтобы позволить закрытию быть Fn
, а не FnOnce
. Действительно, если вы переместите вашу конфигурацию внутрь build_ui
, эту функцию нельзя использовать дважды. См. этот вопрос для получения дополнительной информации.
Если я хорошо понимаю ваши потребности, config
предназначена для конфигурации только для чтения, которая должна использоваться совместно. В этой ситуации я бы вообще не перемещал его, например, изменив подпись build_ui
на:
fn build_ui(application: >k::Application, config: &Config)