rust-lang / rust-lang/rust

Inconsistent reborrowing when accessing a struct field of type `&mut`.

Open
#152,699 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug needs-triage T-compiler T-lang T-types
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

When I assign a struct field of type &mut i32 to a variable, sometimes rust reborrows it for me, and sometimes it doesn't. This reborrowing should be done consistently or not at all.

In the below code, functions works1 and works2 compile fine, but fails1 through fails6 produce a compile error.

struct Thing<'a>(&'a mut i32);
impl Drop for Thing<'_> {
    fn drop(&mut self) {}
}

fn works1(t: Thing) {
    let mut _x = &mut 1;
    _x = t.0;
}

fn works2(t: Thing) {
    let mut _x: &mut i32;
    _x = t.0;
}

fn fails1(t: Thing) {
    let mut _x;
    _x = t.0;
}

fn fails2(t: Thing) {
    let mut _x = t.0;
}

fn fails3(t: Thing) {
    let Thing(mut _x) = t;
}

fn fails4(t: Thing) {
    let mut _x;
    Thing(_x) = t;
}

fn fails5(t: Thing) {
    let mut _x = &mut 1;
    Thing(_x) = t;
}

fn fails6(t: Thing) {
    let mut _x: &mut i32;
    Thing(_x) = t;
}
Error output
error[E0509]: cannot move out of type `Thing<'_>`, which implements the `Drop` trait
  --> src/lib.rs:18:10
   |
18 |     _x = t.0;
   |          ^^^
   |          |
   |          cannot move out of here
   |          move occurs because `t.0` has type `&mut i32`, which does not implement the `Copy` trait

error[E0509]: cannot move out of type `Thing<'_>`, which implements the `Drop` trait
  --> src/lib.rs:22:18
   |
22 |     let mut _x = t.0;
   |                  ^^^
   |                  |
   |                  cannot move out of here
   |                  move occurs because `t.0` has type `&mut i32`, which does not implement the `Copy` trait
   |
help: consider borrowing here
   |
22 |     let mut _x = &t.0;
   |                  +

error[E0509]: cannot move out of type `Thing<'_>`, which implements the `Drop` trait
  --> src/lib.rs:26:25
   |
26 |     let Thing(mut _x) = t;
   |               ------    ^ cannot move out of here
   |               |
   |               data moved here
   |               move occurs because `_x` has type `&mut i32`, which does not implement the `Copy` trait
   |
help: consider borrowing the pattern binding
   |
26 |     let Thing(ref mut _x) = t;
   |               +++

error[E0509]: cannot move out of type `Thing<'_>`, which implements the `Drop` trait
  --> src/lib.rs:31:17
   |
31 |     Thing(_x) = t;
   |           --    ^ cannot move out of here
   |           |
   |           data moved here
   |           move occurs because the place has type `&mut i32`, which does not implement the `Copy` trait
   |
help: consider borrowing the pattern binding
   |
31 |     Thing(ref _x) = t;
   |           +++

error[E0509]: cannot move out of type `Thing<'_>`, which implements the `Drop` trait
  --> src/lib.rs:36:17
   |
36 |     Thing(_x) = t;
   |           --    ^ cannot move out of here
   |           |
   |           data moved here
   |           move occurs because the place has type `&mut i32`, which does not implement the `Copy` trait
   |
help: consider borrowing the pattern binding
   |
36 |     Thing(ref _x) = t;
   |           +++

error[E0509]: cannot move out of type `Thing<'_>`, which implements the `Drop` trait
  --> src/lib.rs:41:17
   |
41 |     Thing(_x) = t;
   |           --    ^ cannot move out of here
   |           |
   |           data moved here
   |           move occurs because the place has type `&mut i32`, which does not implement the `Copy` trait
   |
help: consider borrowing the pattern binding
   |
41 |     Thing(ref _x) = t;
   |           +++

For more information about this error, try `rustc --explain E0509`.
error: could not compile `playground` (lib) due to 6 previous errors
Meta

Reproducible on the playground with version 1.95.0-nightly (2026-02-12 47611e16044c68ef27ba)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the six failing cases and the two working cases from src/lib.rs in the playground using the reported nightly version, then compare their E0509 diagnostics. Read the E0509 explanation and trace the compiler handling of field access and destructuring for a Drop type; done means the reborrowing behavior is consistent and the relevant cases compile or fail as intended.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.