Skip to content

Misguiding help on error "mut must be attached to each individual binding" #80186

Closed
@tomprogrammer

Description

@tomprogrammer

I tried this code to create a mutable variable binding to tuple.0 while also dereferencing it in the same pattern. Of course this code is not correct. I think the intention can be guessed because of the order in which & and mut appear, especially in the parenthesized variant.

#![allow(unused_variables)]
fn main() {
    let tuple: (&u8, &[u8]) = (&0, &[0, 0]);
    let (mut &last, rest) = tuple;
    let (mut (&last), rest) = tuple;
    // `last` should be type of `u8`
    // EDIT: This can be minimized to:
    let mut &x = &0;
}

This is the correct code, where the tokens & and mut are separated by parentheses to avoid parsing as &mut. This is also perfectly logical since patterns are read from the outside inwards destructuring the given value. My fault was to interpret & and mut like operators which got me stuck at the code I've written above.

#![allow(unused_variables)]
fn main() {
    let tuple: (&u8, &[u8]) = (&0, &[0, 0]);
    let (&(mut last), rest) = tuple;
    // EDIT: This can be minimized to:
    let &(mut x) = &0;
}

The issue is that the help output by the compiler isn't actually helping much because it changes semantics of the code. The compiler suggests to use &mut which would dereference a mutable reference when used in a pattern. That is very different from dereferencing a shared reference and mutably binding a variable.

Since &mut consists of two tokens & and mut the compiler tries to show you that the two token are in the wrong order I guess. In my opinion this is less probable than trying to express the pattern &(mut variable) wrongly as mut &variable. For the variant mut (&variable) the help is not correct anyway since the compiler ignores the parentheses.

I propose to change the help text to suggest &(mut last) instead. I'm not sure whether there are cases where this help would be wrong also.

Current error and help:

error: `mut` must be attached to each individual binding
 --> src/main.rs:5:10
  |
4 |     let (mut &last, rest) = tuple;
  |          ^^^^^^^^^ help: add `mut` to each binding: `&mut last`
  |
  = note: `mut` may be followed by `variable` and `variable @ pattern`

error: `mut` must be attached to each individual binding
 --> src/main.rs:6:10
  |
5 |     let (mut (&last), rest) = tuple;
  |          ^^^^^^^^^^^ help: add `mut` to each binding: `(&mut last)`
  |
  = note: `mut` may be followed by `variable` and `variable @ pattern`

warning: unnecessary parentheses around pattern
 --> src/main.rs:6:10
  |
5 |     let (mut (&last), rest) = tuple;
  |          ^^^^^^^^^^^ help: remove these parentheses
  |
  = note: `#[warn(unused_parens)]` on by default

Meta

All the compiler channels produce the same output.
rustc --version --verbose:
Stable:

rustc 1.48.0 (7eac88abb 2020-11-16)
binary: rustc
commit-hash: 7eac88abb2e57e752f3302f02be5f3ce3d7adfb4
commit-date: 2020-11-16
host: x86_64-unknown-linux-gnu
release: 1.48.0
LLVM version: 11.0

Beta:

rustc 1.49.0-beta.4 (877c7cbe1 2020-12-10)
binary: rustc
commit-hash: 877c7cbe142a373f93d38a23741dcc3a0a17a2af
commit-date: 2020-12-10
host: x86_64-unknown-linux-gnu
release: 1.49.0-beta.4

Nightly:

rustc 1.50.0-nightly (f74583445 2020-12-18)
binary: rustc
commit-hash: f74583445702e2e27ec4415376f2c540a83d7ded
commit-date: 2020-12-18
host: x86_64-unknown-linux-gnu
release: 1.50.0-nightly

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-patternsRelating to patterns and pattern matchingA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-bugCategory: This is a bug.D-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