fn fn_once<F>(func: F)
where
F: FnOnce(usize) -> bool,
{
println!("{}", func(3));
println!("{}", func(4));
}
fn main() {
let x = 3;
fn_once(|z| z == x)
}
Приведенный выше код сообщает об ошибке [E0382]: использование перемещенного значения: func.
Ошибка исчезает после добавления ограничения типажа Copy:
fn fn_once<F>(func: F)
where
F: FnOnce(usize) -> bool + Copy,
{
println!("{}", func(3));
println!("{}", func(4));
}
fn main() {
let x = 3;
fn_once(|z| z == x)
}
Мой вопрос: эта черта копирования получена автоматически, потому что я указал привязку к черте? Или само замыкание всегда имело свойство Copy, и оно вступает в силу только после указания привязки копирования?
Я хочу знать, какой механизм стоит за этим.

Замыкания, которые захватывают только типы Copy, автоматически реализуются Copy.
Но дженерики Rust проверяются по определениям. Не имеет значения, как вы это назовете (на самом деле, вы получите ошибку даже при компиляции fn_once в одиночку, без каких-либо вызывающих программ). Сигнатура функции должна быть достаточной, чтобы разрешить использование всего, что находится внутри. Поэтому, если вы не укажете Copy, компилятор предположит, что тип не будет Copy, и соответствующим образом проверит код.
Тем не менее, FnOnce предназначен для однократного вызова, он заложен в названии! Также указывать Copy, чтобы вы могли использовать его несколько раз, довольно бессмысленно. Вместо этого вам следует изменить FnOnce на Fn.
Fnслишком много,FnMutдостаточно.