Skip to content

ergonomic_clones_dotuse_capture_by_ref: Capture upvar by ref for .use in non-move closures#157270

Open
Dnreikronos wants to merge 2 commits into
rust-lang:mainfrom
Dnreikronos:ergonomic_clones_dotuse_capture_by_ref
Open

ergonomic_clones_dotuse_capture_by_ref: Capture upvar by ref for .use in non-move closures#157270
Dnreikronos wants to merge 2 commits into
rust-lang:mainfrom
Dnreikronos:ergonomic_clones_dotuse_capture_by_ref

Conversation

@Dnreikronos

@Dnreikronos Dnreikronos commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Fixes #157141

A plain || { x.use } closure was cloning the captured value one time too many: once when the closure is built, then once per call. So two invocations produced three clones.

The capture analysis marked the upvar as ByUse, which clones the value into the closure at construction time, and the .use in the body still clones on every call. But for a closure without a move or use keyword, a ByUse capture can only come from a .use expression in the body. A use || capture clause is handled separately in adjust_for_use_closure. The ast::CaptureBy::Use docs already spell this out: a regular || x.use should not produce a Use capture, it should look at the type and treat x.use as a copy/clone/move as appropriate.

So in adjust_for_non_move_closure, capture such places by immutable borrow instead. The .use then clones once per evaluation and nothing is cloned into the closure up front, matching the count you get from a direct x.use or a move || closure. use || and move || are unaffected.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 1, 2026
@rustbot

rustbot commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

r? @folkertdev

rustbot has assigned @folkertdev.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 73 candidates
  • Random selection from 17 candidates

@folkertdev

Copy link
Copy Markdown
Contributor

r? types

@rustbot rustbot added the T-types Relevant to the types team, which will review and decide on the PR/issue. label Jun 1, 2026
@rustbot rustbot assigned jackh726 and unassigned folkertdev Jun 1, 2026
@Dnreikronos

Copy link
Copy Markdown
Contributor Author

hi, @jackh726!
does you need something from my side to help with the review?

@jackh726

Copy link
Copy Markdown
Member

The first commit looks completely unrelated? Can you split that into a separate PR? The .use fix looks fine - but these changes should be split.

A plain `|| { x.use }` closure marked the upvar capture as `ByUse`,
which clones the value into the closure at construction time. The
`.use` in the body then clones again on every call, so the value was
cloned once more than the number of invocations.

A `ByUse` capture in a non-`move`/`use` closure can only originate from
a `.use` expression in the body; a `use ||` capture clause is handled by
`adjust_for_use_closure` instead. Capture such places by immutable
borrow so the `.use` clones once per evaluation and nothing is cloned
into the closure at construction.
@Dnreikronos
Dnreikronos force-pushed the ergonomic_clones_dotuse_capture_by_ref branch from 1b52868 to 0806c0a Compare June 25, 2026 13:14
@rustbot

rustbot commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@Dnreikronos

Copy link
Copy Markdown
Contributor Author

The first commit looks completely unrelated? Can you split that into a separate PR? The .use fix looks fine - but these changes should be split.

thanks, yeah fair. i rebased on current main and the unrelated method-suggestion commit dropped out.

idk how i missed that in the stack before. imo this looks cleaner now: the pr should only have the .use fix and the ui test. lgtm from my side.

@Dnreikronos

Copy link
Copy Markdown
Contributor Author

hi @jackh726!
need something from my side to continue with the work here?

@Dnreikronos

Copy link
Copy Markdown
Contributor Author

@rustbot reroll

@rustbot rustbot assigned mejrs and unassigned jackh726 Jul 13, 2026
@mejrs

mejrs commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@nikomatsakis I'm reading rust-lang/rfcs#3968 but I'm not clear on whether the use syntax is going away eventually. Is this PR what we want?

Anyway, I'm not qualified to review this, so
r? types

@rustbot rustbot assigned oli-obk and unassigned mejrs Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.use expressions inside closures have surprising behavior

6 participants