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
FnBoxis not required to call boxedFnOnceclosures; 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<FnOnce()>, 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<F: FnOnce() + ?Sized> FnBox for F {
fn call_box(self: Box<F>) {
(*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 Sizedness 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<dyn FnOnce()> implements FnOnce(), so you can call it like a normal closure, without using *:
impl<F: FnOnce() + ?Sized> FnBox for F {
fn call_box(self: Box<F>) {
self()
}
}