Open
Description
I tried this code:
#![feature(unboxed_closures)]
#![feature(fn_traits)]
struct Wrapper<F>(F);
impl<Args, F:FnOnce<Args>> FnOnce<Args> for Wrapper<F> {
type Output = F::Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
self.0.call_once(args)
}
}
// Uncomment this implementation and the code in main() breaks... what?
/*
impl<Args, F:FnMut<Args>> FnMut<Args> for Wrapper<F> where Self:FnOnce<Args, Output=F::Output> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> <Self as FnOnce<Args>>::Output {
self.0.call_mut(args)
}
}
*/
fn main() {
struct Stuff;
let stuff = Stuff;
let f = ||drop(stuff);
let g = Wrapper(f);
g();
}
I expected to see this happen: Whether the commented code is commented or not, the code should compile
Instead, this happened: If the commented code is uncommented, it fails to compile. The error is
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
--> src/main.rs:25:13
|
25 | let f = ||drop(stuff);
| ^^^^^^^-----^
| | |
| | closure is `FnOnce` because it moves the variable `stuff` out of its environment
| this closure implements `FnOnce`, not `FnMut`
26 | let g = Wrapper(f);
27 | g();
| --- the requirement to implement `FnMut` derives from here
For more information about this error, try `rustc --explain E0525`.
From my understanding, the error message kind of makes sense. f
indeed doesn't implement FnMut
, so g
doesn't either. However, g
still implements FnOnce
, which can be used here. It seems that the existence of FnMut
implementation makes the compiler blind to the FnOnce
implementation.
Similar thing can happen when both FnMut
and Fn
implementation exists but Fn
is not implemented due to unsatisfied trait bound.
Meta
rustc --version --verbose
:
1.57.0-nightly
(2021-09-15 2c7bc5e33c25e29058cb)