Skip to content

Commit

Permalink
Auto merge of #80205 - tomprogrammer:prettyprint-pattern-mut-binding,…
Browse files Browse the repository at this point in the history
… r=davidtwco

Fix pretty printing an AST representing `&(mut ident)`

The PR fixes a misguiding help diagnostic in the parser that I reported in #80186. I discovered that the parsers recovery and reporting logic was correct but the pretty printer produced wrong code for the example. (Details in #80186 (comment))

Example:
```rust
#![allow(unused_variables)]
fn main() {
    let mut &x = &0;
}
```

The AST fragment

`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..), Mutability::Not)`

was printed to be `&mut ident`. But this wouldn't round trip through parsing again, because then it would be:

`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Not), ..), Mutability::Mut)`

Now the pretty-printer prints `&(mut ident)`. Reparsing that code results in the AST fragment

`PatKind::Ref(PatKind::Paren(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..)), Mutability::Not)`

which I think should behave like the original pattern.

Old diagnostic:
```
error: `mut` must be attached to each individual binding
 --> src/main.rs:3:9
  |
3 |     let mut &x = &0;
  |         ^^^^^^ help: add `mut` to each binding: `&mut x`
  |
  = note: `mut` may be followed by `variable` and `variable @ pattern`
```

New diagnostic:

```
error: `mut` must be attached to each individual binding
 --> src/main.rs:3:9
  |
3 |     let mut &x = &0;
  |         ^^^^^^ help: add `mut` to each binding: `&(mut x)`
  |
  = note: `mut` may be followed by `variable` and `variable @ pattern`
```

Fixes #80186
  • Loading branch information
bors committed Dec 21, 2020
2 parents 463ce40 + b05ab18 commit 1e88a17
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
10 changes: 9 additions & 1 deletion compiler/rustc_ast_pretty/src/pprust/state.rs
Expand Up @@ -2420,7 +2420,15 @@ impl<'a> State<'a> {
if mutbl == ast::Mutability::Mut {
self.s.word("mut ");
}
self.print_pat(inner);
if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) =
inner.kind
{
self.popen();
self.print_pat(inner);
self.pclose();
} else {
self.print_pat(inner);
}
}
PatKind::Lit(ref e) => self.print_expr(&**e),
PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
Expand Down
@@ -0,0 +1,9 @@
// Regression test for correct pretty-printing of an AST representing `&(mut x)` in help
// suggestion diagnostic.

fn main() {
let mut &x = &0;
//~^ ERROR `mut` must be attached to each individual binding
//~| HELP add `mut` to each binding
//~| SUGGESTION &(mut x)
}
10 changes: 10 additions & 0 deletions src/test/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr
@@ -0,0 +1,10 @@
error: `mut` must be attached to each individual binding
--> $DIR/issue-80186-mut-binding-help-suggestion.rs:5:9
|
LL | let mut &x = &0;
| ^^^^^^ help: add `mut` to each binding: `&(mut x)`
|
= note: `mut` may be followed by `variable` and `variable @ pattern`

error: aborting due to previous error

0 comments on commit 1e88a17

Please sign in to comment.