mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Improve 'mut ' diagnostic.
This commit is contained in:
parent
dbbe3363c9
commit
42e895d4d9
@ -405,22 +405,13 @@ impl<'a> Parser<'a> {
|
||||
let mut pat = self.parse_pat(Some("identifier"))?;
|
||||
|
||||
// Add `mut` to any binding in the parsed pattern.
|
||||
struct AddMut;
|
||||
impl MutVisitor for AddMut {
|
||||
fn visit_pat(&mut self, pat: &mut P<Pat>) {
|
||||
if let PatKind::Ident(BindingMode::ByValue(ref mut m), ..) = pat.node {
|
||||
*m = Mutability::Mutable;
|
||||
}
|
||||
noop_visit_pat(pat, self);
|
||||
}
|
||||
}
|
||||
AddMut.visit_pat(&mut pat);
|
||||
let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat);
|
||||
|
||||
// Unwrap; If we don't have `mut $ident`, error.
|
||||
let pat = pat.into_inner();
|
||||
match &pat.node {
|
||||
PatKind::Ident(..) => {}
|
||||
_ => self.ban_mut_general_pat(mut_span, &pat),
|
||||
_ => self.ban_mut_general_pat(mut_span, &pat, changed_any_binding),
|
||||
}
|
||||
|
||||
Ok(pat.node)
|
||||
@ -442,17 +433,40 @@ impl<'a> Parser<'a> {
|
||||
self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable))
|
||||
}
|
||||
|
||||
/// Turn all by-value immutable bindings in a pattern into mutable bindings.
|
||||
/// Returns `true` if any change was made.
|
||||
fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
|
||||
struct AddMut(bool);
|
||||
impl MutVisitor for AddMut {
|
||||
fn visit_pat(&mut self, pat: &mut P<Pat>) {
|
||||
if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..)
|
||||
= pat.node
|
||||
{
|
||||
*m = Mutability::Mutable;
|
||||
self.0 = true;
|
||||
}
|
||||
noop_visit_pat(pat, self);
|
||||
}
|
||||
}
|
||||
|
||||
let mut add_mut = AddMut(false);
|
||||
add_mut.visit_pat(pat);
|
||||
add_mut.0
|
||||
}
|
||||
|
||||
/// Error on `mut $pat` where `$pat` is not an ident.
|
||||
fn ban_mut_general_pat(&self, lo: Span, pat: &Pat) {
|
||||
fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) {
|
||||
let span = lo.to(pat.span);
|
||||
self.struct_span_err(span, "`mut` must be attached to each individual binding")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"add `mut` to each binding",
|
||||
pprust::pat_to_string(&pat),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
let fix = pprust::pat_to_string(&pat);
|
||||
let (problem, suggestion) = if changed_any_binding {
|
||||
("`mut` must be attached to each individual binding", "add `mut` to each binding")
|
||||
} else {
|
||||
("`mut` must be followed by a named binding", "remove the `mut` prefix")
|
||||
};
|
||||
self.struct_span_err(span, problem)
|
||||
.span_suggestion(span, suggestion, fix, Applicability::MachineApplicable)
|
||||
.note("`mut` may be followed by `variable` and `variable @ pattern`")
|
||||
.emit()
|
||||
}
|
||||
|
||||
/// Eat any extraneous `mut`s and error + recover if we ate any.
|
||||
|
@ -5,5 +5,5 @@ fn main() {
|
||||
let mut b = 0;
|
||||
let mut _b = 0;
|
||||
let mut _ = 0;
|
||||
//~^ ERROR `mut` must be attached to each individual binding
|
||||
//~^ ERROR `mut` must be followed by a named binding
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
error: `mut` must be attached to each individual binding
|
||||
error: `mut` must be followed by a named binding
|
||||
--> $DIR/issue-32501.rs:7:9
|
||||
|
|
||||
LL | let mut _ = 0;
|
||||
| ^^^^^ help: add `mut` to each binding: `_`
|
||||
| ^^^^^ help: remove the `mut` prefix: `_`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,6 +6,9 @@
|
||||
#![allow(warnings)]
|
||||
|
||||
pub fn main() {
|
||||
let mut _ = 0; //~ ERROR `mut` must be followed by a named binding
|
||||
let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding
|
||||
|
||||
let mut mut x = 0;
|
||||
//~^ ERROR `mut` on a binding may not be repeated
|
||||
//~| remove the additional `mut`s
|
||||
|
@ -1,29 +1,49 @@
|
||||
error: `mut` must be followed by a named binding
|
||||
--> $DIR/mut-patterns.rs:9:9
|
||||
|
|
||||
LL | let mut _ = 0;
|
||||
| ^^^^^ help: remove the `mut` prefix: `_`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: `mut` must be followed by a named binding
|
||||
--> $DIR/mut-patterns.rs:10:9
|
||||
|
|
||||
LL | let mut (_, _) = (0, 0);
|
||||
| ^^^^^^^^^^ help: remove the `mut` prefix: `(_, _)`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: `mut` on a binding may not be repeated
|
||||
--> $DIR/mut-patterns.rs:9:13
|
||||
--> $DIR/mut-patterns.rs:12:13
|
||||
|
|
||||
LL | let mut mut x = 0;
|
||||
| ^^^ help: remove the additional `mut`s
|
||||
|
||||
error: `mut` must be attached to each individual binding
|
||||
--> $DIR/mut-patterns.rs:14:9
|
||||
--> $DIR/mut-patterns.rs:17:9
|
||||
|
|
||||
LL | let mut Foo { x: x } = Foo { x: 3 };
|
||||
| ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: `mut` must be attached to each individual binding
|
||||
--> $DIR/mut-patterns.rs:18:9
|
||||
--> $DIR/mut-patterns.rs:21:9
|
||||
|
|
||||
LL | let mut Foo { x } = Foo { x: 3 };
|
||||
| ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: `mut` on a binding may not be repeated
|
||||
--> $DIR/mut-patterns.rs:23:13
|
||||
--> $DIR/mut-patterns.rs:26:13
|
||||
|
|
||||
LL | let mut mut yield(become, await) = r#yield(0, 0);
|
||||
| ^^^ help: remove the additional `mut`s
|
||||
|
||||
error: expected identifier, found reserved keyword `yield`
|
||||
--> $DIR/mut-patterns.rs:23:17
|
||||
--> $DIR/mut-patterns.rs:26:17
|
||||
|
|
||||
LL | let mut mut yield(become, await) = r#yield(0, 0);
|
||||
| ^^^^^ expected identifier, found reserved keyword
|
||||
@ -33,7 +53,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0);
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected identifier, found reserved keyword `become`
|
||||
--> $DIR/mut-patterns.rs:23:23
|
||||
--> $DIR/mut-patterns.rs:26:23
|
||||
|
|
||||
LL | let mut mut yield(become, await) = r#yield(0, 0);
|
||||
| ^^^^^^ expected identifier, found reserved keyword
|
||||
@ -43,7 +63,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0);
|
||||
| ^^^^^^^^
|
||||
|
||||
error: expected identifier, found reserved keyword `await`
|
||||
--> $DIR/mut-patterns.rs:23:31
|
||||
--> $DIR/mut-patterns.rs:26:31
|
||||
|
|
||||
LL | let mut mut yield(become, await) = r#yield(0, 0);
|
||||
| ^^^^^ expected identifier, found reserved keyword
|
||||
@ -53,19 +73,23 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0);
|
||||
| ^^^^^^^
|
||||
|
||||
error: `mut` must be attached to each individual binding
|
||||
--> $DIR/mut-patterns.rs:23:9
|
||||
--> $DIR/mut-patterns.rs:26:9
|
||||
|
|
||||
LL | let mut mut yield(become, await) = r#yield(0, 0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: `mut` must be attached to each individual binding
|
||||
--> $DIR/mut-patterns.rs:32:9
|
||||
--> $DIR/mut-patterns.rs:35:9
|
||||
|
|
||||
LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f }))))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: expected identifier, found `x`
|
||||
--> $DIR/mut-patterns.rs:39:21
|
||||
--> $DIR/mut-patterns.rs:42:21
|
||||
|
|
||||
LL | let mut $p = 0;
|
||||
| ^^ expected identifier
|
||||
@ -73,5 +97,5 @@ LL | let mut $p = 0;
|
||||
LL | foo!(x);
|
||||
| -------- in this macro invocation
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub fn main() {
|
||||
ref Self => (),
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
mut Self => (),
|
||||
//~^ ERROR `mut` must be attached to each individual binding
|
||||
//~^ ERROR `mut` must be followed by a named binding
|
||||
//~| ERROR cannot find unit struct/variant or constant `Self`
|
||||
ref mut Self => (),
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
|
@ -10,11 +10,13 @@ error: expected identifier, found keyword `Self`
|
||||
LL | ref Self => (),
|
||||
| ^^^^ expected identifier, found keyword
|
||||
|
||||
error: `mut` must be attached to each individual binding
|
||||
error: `mut` must be followed by a named binding
|
||||
--> $DIR/self_type_keyword.rs:16:9
|
||||
|
|
||||
LL | mut Self => (),
|
||||
| ^^^^^^^^ help: add `mut` to each binding: `Self`
|
||||
| ^^^^^^^^ help: remove the `mut` prefix: `Self`
|
||||
|
|
||||
= note: `mut` may be followed by `variable` and `variable @ pattern`
|
||||
|
||||
error: expected identifier, found keyword `Self`
|
||||
--> $DIR/self_type_keyword.rs:19:17
|
||||
|
Loading…
Reference in New Issue
Block a user