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 3 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 3 commits into
rust-lang:mainfrom
Dnreikronos:ergonomic_clones_dotuse_capture_by_ref

Conversation

@Dnreikronos
Copy link
Copy Markdown
Contributor

@Dnreikronos Dnreikronos commented Jun 1, 2026

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.

When a method call fails to resolve, the suggestion machinery probes
all traits for a method with the same name and builds a trait
reference for the providing trait to detect duplicate trait items
coming from multiple crate versions. It passed only the receiver type
as the single argument, which is correct only for traits whose sole
generic parameter is `Self`. For a trait with further parameters (for
example `Borrow<Borrowed>`), or when the receiver type is unknown, the
argument list no longer matched the trait's generics and tripped the
`debug_assert_args_compatible` assertion, producing an ICE.

Build the argument list with `GenericArgs::for_item` instead, using
the receiver type for `Self` when known and fresh inference variables
for the remaining parameters.
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.
@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
Copy link
Copy Markdown
Collaborator

rustbot commented Jun 1, 2026

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

4 participants