Description
I will spend a bit of time minimizing this, but I'm filing an issue now while the details are fresh in my head, since I might not have time until tomorrow.
My crate has the following recursive function which takes a FnMut
pred
and then calls itself with &mut pred
. This causes an infinite chain of &mut &mut &mut ...
for the compiler when trying to resolve F: FnMut
. This seems natural enough except that this code has been present for at least 2 years, and has worked fine until the 2023-04-21 nightly. The 2023-04-20 will accept it.
Specifically the error is
error[E0275]: overflow evaluating the requirement `F: FnMut<(&Pk,)>`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`miniscript`)
= note: required for `&mut AAA` to implement `FnMut<(&Pk,)>`
= note: 128 redundant requirements hidden
= note: required for `&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut ...` to implement `FnMut<(&Pk,)>`
= note: the full type name has been written to '/store/home/apoelstra/code/rust-bitcoin/miniscript/master/target/release/deps/miniscript-79ed028b5570a04b.long-type-1335565870067577868.txt'
There is a workaround, which is to replace the offending &mut pred
with &mut |key| pred(key)
, but I don't understand exactly what type magic is going on here that makes one okay but not the other. It never occurred to me to use this form except that I showed this error to GPT4 and that's what it suggested I do.
My questions are then:
- Is this a regression in the compiler?
- Is my code at fault?
- Why does
&mut |key| pred(key)
break the recursion? Thoughout my codebase, but not here for some reason, I have a number of functions that take&mut F
withF: FnMut
rather than directly takingF
. I call these functions names likereal_for_each
and then call them from the API-exposedfor_each
which directly takesF
. Is this closure trick an alternative solution to avoiding compiler errors?