Skip to content

Cromulent Copy closure captures - #4011

Open
Jules-Bertholet wants to merge 7 commits into
rust-lang:mainfrom
Jules-Bertholet:cromulent-copy-closure-captures
Open

Jules-Bertholet wants to merge 7 commits into
rust-lang:mainfrom
Jules-Bertholet:cromulent-copy-closure-captures

Conversation

@Jules-Bertholet

@Jules-Bertholet Jules-Bertholet commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Rendered

Change closure capture inference rules for Copy captures, allowing more code to compile without changing semantics for existing closures.

Some examples of closures that would start compiling:

fn callable(c: char) -> impl Fn() -> char {
    || c
}
fn main() {
    let cs: u32 = (0..0xCC).flat_map(|c| (0..c).map(|cc| c + cc)).sum();
    assert_eq!(cs, 4203318);
}

@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.

@Jules-Bertholet Jules-Bertholet changed the title RFC 4011: Cromulent Copy closure captures Cromulent Copy closure captures Oct 1, 2026
@rustbot rustbot added A-closures Proposals relating to closures / lambdas. T-lang Relevant to the language team, which will review and decide on the RFC. labels Oct 1, 2026
> 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.

@ds84182 ds84182 Oct 2, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Borrowck happens after we decided on closure captures. We need MIR to borrowck, but MIR building needs the set of closure captures.

@Jules-Bertholet

Copy link
Copy Markdown
Contributor Author

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.

@Jules-Bertholet
Jules-Bertholet force-pushed the cromulent-copy-closure-captures branch from d0d566b to e417f07 Compare October 2, 2026 21:20
@clarfonthey

Copy link
Copy Markdown
Contributor

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.

@Jules-Bertholet

Copy link
Copy Markdown
Contributor Author

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.
@Jules-Bertholet

Copy link
Copy Markdown
Contributor Author

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.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-closures Proposals relating to closures / lambdas. T-lang Relevant to the language team, which will review and decide on the RFC.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants