Rust playground:
trait FnBox {
fn call_box(self: Box);
}
impl FnBox for F {
fn call_box(self: Box) {
(*s
Author's note: Since Rust 1.35, an adapter trait like
FnBox
is not required to call boxedFnOnce
closures; read to the end to see why.
FnBox
isn't implemented for FnOnce()
.
FnOnce()
has two meanings: as a trait, and as a type. In Box
, it's a (dynamic, unsized) type. Since Rust 1.27, the type can be written more explicitly as dyn FnOnce(). For the rest of this answer I will use dyn
in order to make clear when I'm talking about the trait and when about the dynamic type.
The impl
you wrote doesn't implement FnBox
for the type dyn FnOnce()
, because generic parameters have an implicit Sized bound. If we follow the advice of that question's answer and add + ?Sized
to F
, the compiler does give a slightly more helpful error message:
impl FnBox for F {
fn call_box(self: Box) {
(*self)()
}
}
error[E0161]: cannot move a value of type F: the size of F cannot be statically determined
--> src/main.rs:7:9
|
7 | (*self)()
| ^^^^^^^
Which does explicitly call out the place where Sized
ness is required.
In versions of Rust before 1.35, there was no way to fix this error; trait objects of FnOnce()
were just useless. However, today Box
implements FnOnce()
, so you can call it like a normal closure, without using *
:
impl FnBox for F {
fn call_box(self: Box) {
self()
}
}