Open
Description
I tried this code:
#![feature(fn_traits, unboxed_closures)]
pub struct Foo<F>(F); // a simple newtype over closure object, nothing more
impl<F: FnOnce(A) -> B, A, B> FnOnce<(A,)> for Foo<F> {
type Output = B;
extern "rust-call" fn call_once(self, (a,): (A,)) -> B {
(self.0)(a)
}
}
impl<F: FnMut(A) -> B, A, B> FnMut<(A,)> for Foo<F> {
extern "rust-call" fn call_mut(&mut self, (a,): (A,)) -> B {
(&mut self.0)(a)
}
}
impl<F: Fn(A) -> B, A, B> Fn<(A,)> for Foo<F> {
extern "rust-call" fn call(&self, (a,): (A,)) -> B {
(&self.0)(a)
}
}
fn main() {
let mut s = String::new();
// This works
{
let mut closure = |()| s.push_str("");
(move |x| closure(x))(());
}
// This doesn't!
{
let closure = |()| s.push_str("");
(Foo(closure))(());
}
}
I expected to see this happen: FnMut
gets picked up as the next candidate fitting for closure call, code compiles succesfully.
Instead, this happened: the closest candidate in method resolution should be Self
, if anything, but, evidently, &Self
is preferred instead. It would be justifiable for closures specifically if the code could be compiled. It doesn't seem to align with anything known so far about either closures or method call expressions. Removing Fn impl makes the code compile successfully, but it shouldn't be considered at all due to unsatisfied F: Fn
bound.
Meta
rustc version: 1.76.0 nightly
Main tracking issue: #29625