From fa5a3c35dcda3c82d0c10837cdcbf747e833eabd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 9 Feb 2020 13:19:06 +0000 Subject: [PATCH] Don't parse `mut a @ b` as `mut a @ mut b` --- src/librustc_parse/parser/pat.rs | 11 ++++++---- .../nested-binding-mode-lint.rs | 13 ++++++++++++ .../nested-binding-modes-mut.rs | 13 ++++++++++++ .../nested-binding-modes-mut.stderr | 21 +++++++++++++++++++ .../nested-binding-modes-ref.rs | 13 ++++++++++++ .../nested-binding-modes-ref.stderr | 15 +++++++++++++ 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs create mode 100644 src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs create mode 100644 src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr create mode 100644 src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs create mode 100644 src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index e07b0733739d1..985185230f26a 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -542,11 +542,14 @@ impl<'a> Parser<'a> { } fn visit_pat(&mut self, pat: &mut P) { - if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Not), ..) = - pat.kind - { - *m = Mutability::Mut; + if let PatKind::Ident(ref mut bm, ..) = pat.kind { + if let BindingMode::ByValue(ref mut m @ Mutability::Not) = bm { + *m = Mutability::Mut; + } self.0 = true; + // Don't recurse into the subpattern, mut on the outer + // binding doesn't affect the inner bindings. + return; } noop_visit_pat(pat, self); } diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs b/src/test/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs new file mode 100644 index 0000000000000..497d94a3db0d9 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(bindings_after_at)] +#![deny(unused_mut)] + +fn main() { + let mut is_mut @ not_mut = 42; + &mut is_mut; + ¬_mut; + let not_mut @ mut is_mut = 42; + &mut is_mut; + ¬_mut; +} diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs new file mode 100644 index 0000000000000..54f04117f7def --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs @@ -0,0 +1,13 @@ +#![feature(bindings_after_at)] + +fn main() { + let mut is_mut @ not_mut = 42; + &mut is_mut; + &mut not_mut; + //~^ ERROR cannot borrow + + let not_mut @ mut is_mut = 42; + &mut is_mut; + &mut not_mut; + //~^ ERROR cannot borrow +} diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr new file mode 100644 index 0000000000000..a8d5e4c4c69cc --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr @@ -0,0 +1,21 @@ +error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable + --> $DIR/nested-binding-modes-mut.rs:6:5 + | +LL | let mut is_mut @ not_mut = 42; + | ------- help: consider changing this to be mutable: `mut not_mut` +LL | &mut is_mut; +LL | &mut not_mut; + | ^^^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable + --> $DIR/nested-binding-modes-mut.rs:11:5 + | +LL | let not_mut @ mut is_mut = 42; + | -------------------- help: consider changing this to be mutable: `mut not_mut` +LL | &mut is_mut; +LL | &mut not_mut; + | ^^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs new file mode 100644 index 0000000000000..d5086aec93ec3 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs @@ -0,0 +1,13 @@ +#![feature(bindings_after_at)] + +fn main() { + let ref is_ref @ is_val = 42; + *is_ref; + *is_val; + //~^ ERROR cannot be dereferenced + + let is_val @ ref is_ref = 42; + *is_ref; + *is_val; + //~^ ERROR cannot be dereferenced +} diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr new file mode 100644 index 0000000000000..9cc928d214993 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr @@ -0,0 +1,15 @@ +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/nested-binding-modes-ref.rs:6:5 + | +LL | *is_val; + | ^^^^^^^ + +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/nested-binding-modes-ref.rs:11:5 + | +LL | *is_val; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0614`.