Description
This issue describes a bug fix regarding "cyclic closures". Specifically, we fixed a bug in rustc in which a closure type T was capable of directly invoking itself without going through a virtual call. This is not intended to be allowed: in order to keep closure inference tractable, closure types are intended to form a strict hierarchy with respect to one another, in terms of which other closures they can invoke.
What kind of code is affected
In fact, it is rather difficult to have a closure that directly invokes itself without going through a Fn
object or a fn
pointer type. It was however possible if you used an "fixed-point combinator" like this:
#![feature(conservative_impl_trait)]
fn fix<F>(f: F) -> impl Fn()
where F: Fn(&F)
{
move || f(&f)
}
fn main() {
let x = fix(|x| {
// in here, the closure has a shared reference to itself, `x`
});
x();
}
This hole has since been closed and the code above no longer compiles.
How can you fix it?
The easiest fix is to rewrite your closure into a top-level function, or into a method. In some cases, you may also be able to have your closure call itself by capturing a &Fn()
object or fn()
pointer that refers to itself. That is permitting, since the closure would be invoking itself via a virtual call, and hence does not directly reference its own type.
Why was there no warning period?
This bug was fixed was without a warning period, even though there is the potential that stable code was affected. This is not our normal practice. We chose in this case to take that action because:
(a) it was quite difficult to arrange a comprehensive warning
(b) crater run indicated no affected crates
(c) this is a bug fix
(d) we are able to direct users to this error message in the event of an error occurring
If however you were negatively affected, we very much apologize. We would like to hear about that. If for some reason you cannot update your code readily, we would consider backing out this change and re-applying it later after you've had some time to adapt, presuming the issue is found promptly enough for that to be practical.