rust-lang / rust-lang/rust

Incorrect span and invalid suggestion for errors from moving into pattern bindings with mixed binding modes

Open
#143,437 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics A-patterns D-imprecise-spans D-invalid-suggestion T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
fn main() {
    let mut x: Result<u8, &mut u8> = Ok(0);
    let (Ok(_y) | &mut Err(_y)) = &mut x;
}
Current output
error[E0507]: cannot move out of a mutable reference
 --> src/main.rs:3:35
  |
3 |     let (Ok(_y) | &mut Err(_y)) = &mut x;
  |             --                    ^^^^^^
  |             |
  |             data moved here
  |             move occurs because `_y` has type `&mut u8`, which does not implement the `Copy` trait
  |
help: consider borrowing the pattern binding
  |
3 |     let (Ok(ref _y) | &mut Err(_y)) = &mut x;
  |             +++
Rationale and extra context

A couple things are going wrong here.

  1. Since MirBorrowckContext::add_move_error_suggestions is only given the Locals that are moved into and not the exact pattern bindings that were the culprits, it goes with the leftmost occurrence. Normally, each instance of a variable binding in an or-pattern has the same binding mode, so this works fine. In this instance though, the left _y is bound by-ref-mut, so the error points to it instead of the right _y that's bound by-move.
  2. In order to provide a valid suggestion that doesn't change the type of _y, both instances of _y would have to be given an explicit ref mut binding mode, requiring more involved changes to the pattern. I'm not sure it's worth giving a structured suggestion in this case, but at least a help that's correct would be better than a suggestion that's wrong. Here's an example of what could be done to get the pattern to work without changing the scrutinee:
let &mut (Ok(ref mut _y) | Err(&mut ref mut _y)) = &mut x;

Alternatively, this could maybe be approached as a match ergonomics issue instead of a diagnostics issue: usually using a &mut ref implicitly reborrows, but pattern bindings will move unless you write &mut ref mut x. Of course, by-move pattern bindings are used specifically for moving, so I don't think the answer is "make patterns implicitly reborrow", but I'm not totally sure that the current state of affairs is the best it could be either. cc @Nadrieril

@rustbot label +D-imprecise-spans +D-invalid-suggestion +A-patterns

Rust Version
rustc 1.90.0-nightly (da58c0513 2025-07-03)
binary: rustc
commit-hash: da58c051315268a197ce280f6ba07bbd03c66535
commit-date: 2025-07-03
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7

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 minimized Rust example, then inspect MirBorrowckContext::add_move_error_suggestions in compiler/rustc_borrowck/src/diagnostics/move_errors.rs. Trace how moved Locals are mapped to pattern bindings; done means the diagnostic identifies the binding that moves and does not emit an invalid suggestion for mixed binding modes.

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.