typeck: boxed closures can't capture by value#20244
Merged
Merged
Conversation
closes rust-lang#19141 closes rust-lang#20193 closes rust-lang#20228
bors
added a commit
that referenced
this pull request
Dec 27, 2014
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)~~ (2) 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>(_: F) where F: FnOnce() {} fn main() { is_uc(|| {}); // type checked as unboxed closure with kind `FnOnce` } ``` (2) I checked, and it's not possible because `check_unboxed_closure` expects a `kind` argument, but we can't supply that argument in this case (i.e. `let f = || {}`, what's the kind?). We could force the `FnOnce` kind in that case, but that's ad hoc. We should try to infer the kind depending on how the closure is used afterwards, but there is no inference mechanism to do that (at least, not right now).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 ismove || {/* */}(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 checkmove || {/* */}as an unboxed closure, butI think (haven't tried)(2) this is not feasible right now because we have a limited form of kind (FnvsFnMutvsFnOnce) 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:
(2) I checked, and it's not possible because
check_unboxed_closureexpects akindargument, but we can't supply that argument in this case (i.e.let f = || {}, what's the kind?). We could force theFnOncekind in that case, but that's ad hoc. We should try to infer the kind depending on how the closure is used afterwards, but there is no inference mechanism to do that (at least, not right now).