---
# System prepended metadata

title: 'RFC 3627 concern: "No ref mut behind &" rule'

---

# RFC 3627 concern: "No `ref mut` behind `&`" rule

[RFC 3627](https://github.com/Jules-Bertholet/rfcs/blob/match-ergonomics-2024/text/3627-match-ergonomics-2024.md) specifies that we will never set the default binding mode to `ref mut` behind `&`.

On older editions this allows strictly more code to compile. But after applying the other rules in the RFC, this rule also prevents certain patterns from compiling in the new edition. We therefore cannot decide this question later without a backward incompatible change.

#### Patterns that work only without this rule

This means that the following code would not compile:

```rust!
//! Edition ≥ 2024: works only without this rule
let &[[&mut a]] = &[&mut [42]]; // a: i32
```

`&mut` in pattern needs to match against either:
- `&mut` in value at same position (there is none, so not possible)
- inherited `&mut` (which the rule downgrades to `&`)

Instead, the above code could be written as:

```rust!
//! Edition ≥ 2024: works with or without this rule (alternatives to above)
let &[[&a]] = &[&mut [42]]; // a: i32
let &[&mut [a]] = &[&mut [42]]; // a: i32
```

#### Patterns that work only with this rule

```rust!
//! All editions: works only with this rule
let &(i, j, [s]) = &(63, 42, &mut [String::from("🦀")]); // i: i32, j: i32, s: &String
```

Without the stated rule, the above code would try to bind `s` as a mutable reference to data inside of a shared reference, and thus fails with the error "cannot borrow data in a `&` reference as mutable". It could still be written in one of the following ways:

```rust!
//! Edition ≥ 2024: works with or without this rule (alternative to above)
let (&i, &j, [s]) = &(63, 42, &mut [String::from("🦀")]); // i: i32, j: i32, s: &String
```
```rust!
//! All editions: works with or without this rule (alternatives to above)
let &(i, j, [ref s]) = &(63, 42, &mut [String::from("🦀")]); // i: i32, j: i32, s: &String
let &(i, j, &mut [ref s]) = &(63, 42, &mut [String::from("🦀")]); // i: i32, j: i32, s: &String
```

## Arguments against

### Inability to match `&mut` with `&mut`

You would not be able to write `&mut` in a pattern where the default binding mode was set to `ref`, even if to match an `&mut` in the original value – unless that `&mut` was in the exact same position.

```rust
//! Edition ≥ 2024
let  [[&mut x]] =  [&mut [42]]; // This works
let &[[&mut x]] = &[&mut [42]]; // This is broken by the proposed rule (example given in RFC)
let  [[&mut x]] = &[&mut [42]]; // This is also broken by the rule
```

### Requires `&` matching `&mut` rule

Note that with `&` matching `&mut`, you can write:

```rust
//! Edition ≥ 2024
let  [[&x]] =  [&mut [42]]; // This works, with same meaning as example above
let &[[&x]] = &[&mut [42]]; // This also works
let  [[&x]] = &[&mut [42]]; // This as well (same meaning)
```

This alleviates the drawbacks of the proposed rule, but it requires an additional rule to do so. Note that this rule was already discussed as part of the RFC, with no concerns raised.

## Arguments in favor

### Smarter default

The RFC doesn't elaborate on this, but I think the strongest argument in favor of this rule from an ergonomics perspective is that it saves you from mutability errors. If you are binding to something by reference that happens to be behind `&&mut`, you want the compiler to do the thing that just works.

### Makes behavior more consistent

On all editions, when a structure pattern peels off a shared reference and the default binding mode is already `ref mut`, the binding mode gets set to `ref`:

```rust
//! All editions
let [a] = &mut &[42]; // x: &i32
```

But when the binding mode is set to `ref`, and a mutable reference is peeled off, the binding mode remains `ref`:

```rust
//! All editions
let [a] = &&mut [42]; // x: &i32
```

In other words, immutability usually takes precedence over mutability. This change, in addition to being generally useful, makes the match ergonomics rules more consistent by ensuring that immutability *always* takes precedence over mutability.

### Ensures that a desirable property is preserved

The current match ergonomics rules uphold the following desirable property:

> An `&mut` pattern is accepted if and only if removing the pattern would allow obtaining an `&mut` value.

For example:

```rust
//! All editions
let &mut a = &mut 42; // `a: i32`
let a = &mut 42; // `a: &mut i32`

let &[&mut a] = &[&mut 42]; // `a: i32`
//let &[a] = &[&mut 42]; // ERROR, but…
let &[ref a] = &[&mut 42]; // `a = &&mut i32` (so we did manage to obtain an `&mut i32` in some form)
```

Adopting the "no `ref mut` behind `&`" rule ensures that this property continues to hold for edition 2024:

```rust
//! Edition ≥ 2024
let &[[&mut x]] = &[&mut [42]]; // If we were allow this, with `x: i32` …
//let &[[x]] = &[&mut [42]]; // remove the `&mut` → ERROR, if the default binding mode is to be `ref mut`
// nothing we do will get us `&mut i32` in any form
```

## Possible actions

* Approve the RFC as-is with the "no `ref mut` behind `&`" rule.
* Ask for the "no `ref mut` behind `&`" rule to be removed, optionally along with the "`&` matches `&mut`" rule.
* Ask for a third option that allows us to "have our cake and eat it too". A couple of directions were suggested by Nadrieril:
  > This makes the model more complex, since we would need to distinguish "ref binding mode" from "ref binding mode that can be matched with `&mut`".

  and rpjohnst:

  > Another framing, rather than changing the binding modes at all, is to defer this sort of "`&mut` -> `&`" adjustment to an auto(de)ref-like mechanism at the site of the binding (or the next-inner pattern). This (again) corresponds more closely to how expressions work: we leave the types of deref place expressions alone, even when moving out of them would be an error, and instead we defer that issue to the containing expression, which may trigger a coercion.