Cannot call implementations of the Fn* traits on references

Over the past few days I have been diving into the compiler with the goal of seeing if I can squash any bugs. Specifically I have been looking at, Issue #42736. I compiled my own stage1 compiler, used -Z treat-err-as-bug=1, and started working up the stack trace. Eventually I came across this hack,

rustc_hir_typeck::callee::FnCtxt::try_overloaded_call_step
at rust\compiler\rustc_hir_typeck\src\callee.rs:215

// Hack: we know that there are traits implementing Fn for &F
// where F:Fn and so forth. In the particular case of types
// like `f: &mut FnMut()`, if there is a call `f()`, we would
// normally translate to `FnMut::call_mut(&mut f, ())`, but
// that winds up potentially requiring the user to mark their
// variable as `mut` which feels unnecessary and unexpected.
//
//     fn foo(f: &mut impl FnMut()) { f() }
//            ^ without this hack `f` would have to be declared as mutable
//
// The simplest fix by far is to just ignore this case and deref again,
// so we wind up with `FnMut::call_mut(&mut *f, ())`.
ty::Ref(..) if autoderef.step_count() == 0 => {
    return None;
}

It seems like this would cause Issue #42736, but I am still learning, so I wanted to get other peoples' thoughts. And if it is the cause, how should I test to see if I can safely remove the hack?

Thanks in advance!

1 Like

If you’re curious about testing… Start with running the ui test suite, I guess? If that isn’t enough then making up more examples might help (and maybe contributing interesting missing cases to the test suite), and reasoning about the cases where this hack’s behavior can be relevant to make code work can be useful.

Ultimately, a crater run will find if any unforseen usage patterns are broken in user code out there.


That being said, in this case, the documentation inline already provides the relevant test case (calling f: &mut impl FnMut() without mut f marking) anyway, and I’d be surprised if the ui tests don’t have it as well.