Repository navigation
Cromulent Copy closure captures - #4011
Jules-Bertholet wants to merge 13 commits into
Conversation
Copy closure capturesCopy closure captures
| > 4. Mutable borrow (`MutBorrow`) --- The place expression is captured as a [mutable reference](https://doc.rust-lang.org/reference/types/pointer.html#mutable-references-mut). | ||
| > 5. Move (`ByValue`) --- The place expression is captured by [moving the value](https://doc.rust-lang.org/reference/expressions.html#moved-and-copied-types) into the closure. | ||
| > | ||
| > Place expressions from the environment are captured from the first mode that is compatible with how the captured value is used inside the closure body. The mode is not affected by the code surrounding the closure, such as the lifetimes of involved variables or fields, or of the closure itself. |
There was a problem hiding this comment.
I think this needs to be aware of lifetimes, otherwise it'll be easy to accidentally bloat the size of closures that previously borrowed instead of copied. If some place outlives the closure, capture by reference.
There was a problem hiding this comment.
Borrowck happens after we decided on closure captures. We need MIR to borrowck, but MIR building needs the set of closure captures.
|
I've added a note about potential breakage around the auto traits a closure is inferred to implement, and how we could resolve that breakage. |
d0d566b to
e417f07
Compare
|
Thank you for creating an RFC that taught me what the word cromulent means. By which I mean you did not provide this information, but upon seeing the RFC, I looked it up. |
|
I've updated the RFC to clarify that capturing values behind a reference still happens by-reference: let x = &([0; 1024],);
let c = || {
let y = x.0; // x.0 captured by ImmBorrow
}; |
These aren't actually a problem; if `&T` implements them, so does T.
|
I've now implemented this RFC: rust-lang/rust#163717 The RFC text has been updated with lessons from the implementation. |
`ByMove` is not possible to create in this position, so these two formulations are equivalent.
7bbe2d2 to
c4d2536
Compare
I've now gotten rid of this breakage entirely. |
|
I've added a special case for the comparison operators ( |
|
(only saw this due to looking at the list of most recent RFCs by accident, while looking something else up) This reminds me of an idea @nikomatsakis and I have discussed at some point, but which may not be written down anywhere AFAIK: Here, let a = "a".to_string();
let concat_a_b = {
let b = "b".to_string();
|| format!("{a}{b}")
}; // <- `b` drops here today, causing an error.
println!("{}", concat_a_b());
// Ideally, this would also work
// (i.e. `a` wouldn't need to be moved into the closure).
println!("{a}");The error is even quite precise about what's going on:
Capture modes need to be known strictly before borrowck, and also, in the past, there have been decisions made against borrowck information controlling behavior (which is why But even during typeck, In many cases, slapping the So a potential simple ruleset for a conservatively correct approximation of "guaranteed to fail borrowck because of scoping" (modulo dead code? not sure what the actual limits are), may be:
As the expectation is that borrowck would fail, those rules could be used to determine that capture mode should be Whether that kind of change should be made, is a different matter entirely, and there's a chance it's been proposed elsewhere already (and rejected/postponed), I have not looked into whether that had happened. |
|
I'd say you're cheating on the "borrowck shouldn't influence captures" rule by morally doing a bit of lexical borrow-checking on HIR :p Interesting angle nevertheless. |
Rendered
Change closure capture inference rules for
Copycaptures, allowing more code to compile without changing semantics for existing closures.Some examples of closures that would start compiling:
Implementation: rust-lang/rust#163717
@rustbot label T-lang A-closures
Important
Since RFCs involve many conversations at once that can be difficult to follow, please use review comment threads on the text changes instead of direct comments on the RFC.
If you don't have a particular section of the RFC to comment on, you can click on the "Comment on this file" button on the top-right corner of the diff, to the right of the "Viewed" checkbox. This will create a separate thread even if others have commented on the file too.