Skip to content

Reborrow &mut on every move - #163494

Open
Jules-Bertholet wants to merge 7 commits into
rust-lang:mainfrom
Jules-Bertholet:universal-mut-reborrow
Open

Jules-Bertholet wants to merge 7 commits into
rust-lang:mainfrom
Jules-Bertholet:universal-mut-reborrow

Conversation

@Jules-Bertholet

@Jules-Bertholet Jules-Bertholet commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

View all comments


Reference PR:

From the Reference:

Moved and copied types

When a place expression is evaluated in a value expression context, or is bound by value in a pattern, it denotes the value held in that memory location.

If the type of that value implements Copy, then the value will be copied.

In the remaining situations, if that type is Sized, then it may be possible to move the value.

[…]

This PR adds one exception to the above rules: if the type of the value is an &mut _ mutable reference, the value will now always be reborrowed instead of moved. (Reference PR: rust-lang/reference#2373)

This allows the following to compile:

fn generic(_: impl Sized) {}
fn assert_fnmut(_: &mut impl FnMut()) {}

struct Foo<T>(T);

fn main() {
    let mut_ref = &mut ();
    generic(mut_ref);
    {
        mut_ref
    };
    let _local = mut_ref;
    let _ = || mut_ref;
    let mut _tup: (&mut (),) = (&mut (),);
    _tup.0 = mut_ref;
    Foo(mut_ref);
    Foo { 0: mut_ref };
    let mut f = || {
        let _y: &mut _ = mut_ref;
    };
    f();
    f();
    assert_fnmut(&mut f);
    generic(mut_ref);

    let mut_ref_ref = &mut &mut ();
    generic(*mut_ref_ref);
    let _local = *mut_ref_ref;
    let _ = || *mut_ref_ref;
    let mut _tup: (&mut (),) = (&mut (),);
    _tup.0 = *mut_ref_ref;
    Foo(*mut_ref_ref);
    Foo { 0: *mut_ref_ref };
    let mut f = || {
        let _y: &mut _ = *mut_ref_ref;
    };
    f();
    f();
    assert_fnmut(&mut f);
    generic(*mut_ref_ref);
}

Unfortunately, the following continues to not compile:

fn assert_fnmut(_: &mut impl FnMut()) {}
fn main() {
    let x = &mut ();
    let mut f = || {
        //~^ ERROR expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` [E0525]
        let _y = x;
    };
    f();
    f();
    assert_fnmut(f);
}

This last case is unfortunately very difficult to fix at present. See #47478 for discussion.

When #![feature(reborrow)] (#145612) is enabled, we also insert reborrows for concrete types implementing Reborrow.

Depends on #164014

@rustbot label A-MIR A-borrow-checker T-lang needs-fcp S-blocked

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 29, 2026

@lcnr lcnr left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should then probably also remove the explicit reborrows in HIR typeck?

View changes since this review

@dianne

dianne commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

should then probably also remove the explicit reborrows in HIR typeck?

would that work without changing closure upvar inference to match? e.g. I think this closure captures x by mut ref (and accordingly is a FnMut) only because _y's declaration has a type annotation on it that causes coercing to insert a reborrow:

fn main() {
    let x = &mut ();
    let mut f = || {
        let _y: &mut _ = x;
    };
    f();
    f();
}

without the annotation, it captures x by value and fails to compile

edit: oh, of course, this makes the MIR for constructing the closure do the reborrow since it uses consume_by_copy_reborrow_or_move

edit 2: but it'd still be inferred to be a FnOnce, wouldn't it, if it has by-value captures?

@rust-log-analyzer

This comment has been minimized.

@Jules-Bertholet
Jules-Bertholet marked this pull request as ready for review September 29, 2026 18:06
@rustbot

rustbot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in match lowering

cc @Nadrieril

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 29, 2026
@rustbot

rustbot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

r? @adwinwhite

rustbot has assigned @adwinwhite.
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 77 candidates
  • Random selection from 19 candidates

@rustbot rustbot added A-borrow-checker Area: The borrow checker A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. T-lang Relevant to the language team labels Sep 29, 2026
@Jules-Bertholet

Copy link
Copy Markdown
Contributor Author

#163494 (comment): I don't understand MIR optimizations, don't feel confident touching these tests. Someone who knows more than I do will need to take a look

@rust-log-analyzer

This comment has been minimized.

@Jules-Bertholet

Copy link
Copy Markdown
Contributor Author

@rustbot label F-reborrow

@rustbot rustbot added the F-reborrow `#![feature(reborrow)]`; see #145612 label Sep 29, 2026
@Jules-Bertholet
Jules-Bertholet force-pushed the universal-mut-reborrow branch 2 times, most recently from a1b8771 to ebd28ba Compare September 29, 2026 19:11
@rustbot

rustbot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

This PR changes a file inside tests/crashes. If a crash was fixed, please move into the corresponding ui subdir and add 'Fixes #' to the PR description to autoclose the issue upon merge.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@adwinwhite

Copy link
Copy Markdown
Contributor

r? @dianne if you don't mind, or types

@rustbot rustbot assigned dianne and unassigned adwinwhite Oct 16, 2026
@rustbot

rustbot commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

clippy is developed in its own repository. If possible, consider making this change to rust-lang/rust-clippy instead.

cc @rust-lang/clippy

@rustbot rustbot added the S-blocked Status: Blocked on something else such as an RFC or other implementation work. label Oct 24, 2026
@rustbot rustbot added the T-clippy Relevant to the Clippy team. label Oct 24, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@traviscross traviscross added the needs-reference-pr This language change needs an approved Reference PR to proceed. label Oct 28, 2026
@rust-bors

This comment has been minimized.

Except inside closures, where we need to keep capture inference stable.
Gets rid of MIR bloat, and improves diagnostics.
These are dead code now!
We don't need these anymore,
now that the reborrows get inserted in MIR.

We keep them around in HIR for closure capture inference.
@rustbot

rustbot commented Oct 30, 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.

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-borrow-checker Area: The borrow checker A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html F-reborrow `#![feature(reborrow)]`; see #145612 I-lang-nominated Nominated for discussion during a lang team meeting. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. needs-reference-pr This language change needs an approved Reference PR to proceed. P-lang-drag-2 Lang team prioritization drag level 2.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. S-blocked Status: Blocked on something else such as an RFC or other implementation work. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team 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.