Skip to content

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

Open
@dianne

Description

@dianne

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-patternsRelating to patterns and pattern matchingD-imprecise-spansDiagnostics: spans don't point to exactly the erroneous codeD-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions