#rust
#Ржавчина
Вопрос:
Почему вызов коробочных замыканий работает так же, как вызов замыканий? Это из-за Deref реализации Box? Будет ли это работать со всеми интеллектуальными указателями? Когда я попробовал несколько примеров, чтобы лучше понять это, я получил следующую ошибку.
fn main() {
let mut x = String::new();
let y = || {
let t = amp;mut x;
};
let mut ww = Box::new(y);
(amp;mut ww)();
}
Это выдает ошибку
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
--> src/main.rs:22:13
|
22 | let y = || {
| ^^ this closure implements `FnMut`, not `Fn`
23 | let t = amp;mut x;
| - closure is `FnMut` because it mutates the variable `x` here
...
26 | (amp;mut ww)();
| ----------- the requirement to implement `Fn` derives from here
Любая документация о том, как работают коробочные закрытия, также была бы полезна.
Комментарии:
1. Да, это из-за реализаций
Deref
andDerefMut
. Однако по причинам, которые не сразу очевидны для меня, компилятор, похоже, не выполняет изменяемое разыменование, а только неизменяемое разыменование (отсюдаFn
FnMut
и ошибка vs) в этом случае. Если вы принудительно разыменовываете изменяемые разыменования с помощью оператора deref as(amp;mut *ww)()
, код компилируется.
Ответ №1:
Box реализует все функции FnX начиная с Rust 1.35 (подробнее здесь, источник), поэтому он должен быть вызываемым.
Похоже, что в этом конкретном случае компилятор недостаточно умен, чтобы удалить и преобразовать ваш тип, который amp;mut Box<Closure>
, как ожидается Box<impl FnMut() -> ()>
, будет выполнять вызов напрямую.
Это работает, хотя:
(ww as Box::<dyn FnMut() -> ()>)();
И это тоже работает:
ww.as_mut()()
Комментарии:
1. Это не совсем так.
impl<Args, F, A> FnOnce<Args> for Box<F, A>
реализация действительно существует. И если я преобразовал выше в объект traitBox<dyn FnOnce()>
, приведенный выше пример будет работать так, как есть, без каких-либо deref.2. Вы правы, спасибо, что указали, я обновил ответ.