rust-lang/rust — pull request #20244 by japaric (2014-12-26 16:45:37+00:00)
Title: typeck: boxed closures can't capture by value

closes #19141
closes #20193
closes #20228

---

Currently whenever we encounter `let f = || {/* */}`, we *always* type check the RHS as a *boxed* closure. This is wrong when the RHS is `move || {/* */}` (because boxed closures can't capture by value) and generates all sort of badness during trans (see issues above). What we *should* do is always type check `move || {/* */}` as an *unboxed* closure, but I *think* (haven't tried) this is not feasible right now because we have a limited form of kind (`Fn` vs `FnMut` vs `FnOnce`) inference that only works when there is an expected type (1).

In this PR, I've chosen to generate a type error whenever `let f = move || {/* */}` is encountered. The error asks the user to annotate the kind of the unboxed closure (e.g. `move |:| {/* */}`). Once annotated, the compiler will type check the RHS as an unboxed closure which is what the user wants.

r? @nikomatsakis

(1) AIUI it only triggers in this scenario:

``` rust
fn is_uc(_: F) where F: FnOnce() {}

fn main() {
is_uc(|| {}); // type checked as unboxed closure with kind `FnOnce`
}
```