When using the unstable fn_traits
and unboxed_closures
features, the following code doesn't compile:
fn call_fn<F: FnOnce(usize) -> usize>(f: F) {
f(0);
}
struct Identity;
impl FnOnce<(usize)> for Identity {
type Output = usize;
extern "rust-call" fn call_once(self, (n): (usize)) -> usize {
n
}
}
fn main() {
call_fn(Identity);
}
The error message implies that the impl FnOnce
isn't implementing what we intend it to implement:
error[E0277]: expected a `std::ops::FnOnce<(usize,)>` closure, found `Identity`
--> src/main.rs:19:5
|
19 | call_fn(Identity);
| ^^^^^^^ expected an `FnOnce<(usize,)>` closure, found `Identity`
|
= help: the trait `std::ops::FnOnce<(usize,)>` is not implemented for `Identity`
note: required by `call_fn`
--> src/main.rs:4:1
|
4 | fn call_fn<F: FnOnce(usize) -> usize>(f: F) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, this code (where (usize)
is replaced by (usize,)
and similarly for the other tuples in the impl FnOnce
block) does compile:
impl FnOnce<(usize,)> for Identity {
type Output = usize;
extern "rust-call" fn call_once(self, (n,): (usize,)) -> usize {
n
}
}
Why is that? Why does the trailing comma matter?