trait Wrap {}
impl<T> Wrap for T where T: Fn(&()) {}
fn wants_wrapped_closure(_: Box<Wrap>) {}
fn main() {
wants_wrapped_closure(Box::new(|_| ()));
}
This works, BTW.
fn wants_wrapped_closure(_: Box<Fn(&())>) {}
fn main() {
wants_wrapped_closure(Box::new(|_| ()));
}
After a bit more poking around, it looks like the first example, where the function takes a unit reference but returns unit, can be fixed by specifying the type of the argument.
OTOH, if I take and return a unit reference, it will not work no matter what I do (sans eliminating the Wrap
trait):
trait Wrap {}
impl<T> Wrap for T where T: Fn(&()) -> &() {}
fn wants_wrapped_closure(_: Box<Wrap>) {}
fn main() {
wants_wrapped_closure(Box::new(|a: &()| -> &() { a }));
}
I suspect this is because technically, Fn can be implemented for more than one possible set of argument types, since Args
is a type parameter of the trait and not an associated type.
Nope, should've looked at the playpen for the error.
This is a known limitation that you need to annotate the type of borrowed arguments in a closure for them to satisfy any HRTBs.
Known limitation: Confusing type error due to strange inferred type for a closure argument · Issue #41078 · rust-lang/rust · GitHub
As others have noted, this is a known bug unfortunately.
One workaround is to explicitly annotate the closure type using other means, e.g.
fn main() {
fn annotate<F: Fn(&()) -> &()>(f: F) -> F { f }
wants_wrapped_closure(Box::new(annotate(|a| a)));
}