Skip to content

Change the &mut T pattern to &mut. #179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 4, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions active/0000-and-mut-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
- Start Date: 23-07-2014
- RFC PR #: (leave this empty)
- Rust Issue #: (leave this empty)

# Summary

Change pattern matching on an `&mut T` to `&mut <pat>`, away from its
current `&<pat>` syntax.

# Motivation

Pattern matching mirrors construction for almost all types, *except*
`&mut`, which is constructed with `&mut <expr>` but destructured with
`&<pat>`. This is almost certainly an unnecessary inconsistency.

This can and does lead to confusion, since people expect the pattern
syntax to match construction, but a pattern like `&mut (ref mut x, _)` is
actually currently a parse error:

```rust
fn main() {
let &mut (ref mut x, _);
}
```

```
and-mut-pat.rs:2:10: 2:13 error: expected identifier, found path
and-mut-pat.rs:2 let &mut (ref mut x, _);
^~~
```


Another (rarer) way it can be confusing is the pattern `&mut x`. It is
expected that this binds `x` to the contents of `&mut T`
pointer... which it does, but as a mutable binding (it is parsed as
`&(mut x)`), meaning something like

```rust
for &mut x in some_iterator_over_and_mut {
println!("{}", x)
}
```

gives an unused mutability warning. NB. it's somewhat rare that one
would want to pattern match to directly bind a name to the contents of
a `&mut` (since the normal reason to have a `&mut` is to mutate the
thing it points at, but this pattern is (byte) copying the data out,
both before and after this change), but can occur if a type only
offers a `&mut` iterator, i.e. types for which a `&` one is no more
flexible than the `&mut` one.

# Detailed design

Add `<pat> := &mut <pat>` to the pattern grammar, and require that it is used
when matching on a `&mut T`.

# Drawbacks

It makes matching through a `&mut` more verbose: `for &mut (ref mut x,
p_) in v.mut_iter()` instead of `for &(ref mut x, _) in
v.mut_iter()`.

Macros wishing to pattern match on either `&` or `&mut` need to handle
each case, rather than performing both with a single `&`. However,
macros handling these types already need special `mut` vs. not
handling if they ever name the types, or if they use `ref` vs. `ref
mut` subpatterns.

It also makes obtaining the current behaviour (binding by-value the
contents of a reference to a mutable local) slightly harder. For a
`&mut T` the pattern becomes `&mut mut x`, and, at the moment, for a
`&T`, it must be matched with `&x` and then rebound with `let mut x =
x;` (since disambiguating like `&(mut x)` doesn't yet work). However,
based on some loose grepping of the Rust repo, both of these are very
rare.

# Alternatives

None.

# Unresolved questions

None.