Skip to content

Commit

Permalink
Rollup merge of #98431 - WaffleLapkin:mut_pat_suggestions, r=compiler…
Browse files Browse the repository at this point in the history
…-errors

Suggest defining variable as mutable on `&mut _` type mismatch in pats

Suggest writing `mut a` where `&mut a` was written but a non-ref type provided.

Since we still don't have "apply either one of the suggestions but not both" kind of thing, the interaction with the suggestion of removing `&[mut]` or moving it to the type is weird, and idk how to make it better..

r? ``@compiler-errors``
  • Loading branch information
matthiaskrgr authored Jun 25, 2022
2 parents ea07b96 + 1dfb53b commit 1f923c2
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 1 deletion.
51 changes: 51 additions & 0 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ast::Mutability::Not => "",
};

let mut_var_suggestion = 'block: {
if !matches!(mutbl, ast::Mutability::Mut) {
break 'block None;
}

let ident_kind = match binding_parent {
hir::Node::Param(_) => "parameter",
hir::Node::Local(_) => "variable",
hir::Node::Arm(_) => "binding",

// Provide diagnostics only if the parent pattern is struct-like,
// i.e. where `mut binding` makes sense
hir::Node::Pat(Pat { kind, .. }) => match kind {
PatKind::Struct(..)
| PatKind::TupleStruct(..)
| PatKind::Or(..)
| PatKind::Tuple(..)
| PatKind::Slice(..) => "binding",

PatKind::Wild
| PatKind::Binding(..)
| PatKind::Path(..)
| PatKind::Box(..)
| PatKind::Ref(..)
| PatKind::Lit(..)
| PatKind::Range(..) => break 'block None,
},

// Don't provide suggestions in other cases
_ => break 'block None,
};

Some((
pat.span,
format!("to declare a mutable {ident_kind} use"),
format!("mut {binding}"),
))

};

match binding_parent {
// Check that there is explicit type (ie this is not a closure param with inferred type)
// so we don't suggest moving something to the type that does not exist
Expand All @@ -675,6 +715,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
],
Applicability::MachineApplicable
);

if let Some((sp, msg, sugg)) = mut_var_suggestion {
err.span_note(sp, format!("{msg}: `{sugg}`"));
}
}
hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => {
// rely on match ergonomics or it might be nested `&&pat`
Expand All @@ -684,6 +728,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"",
Applicability::MaybeIncorrect,
);

if let Some((sp, msg, sugg)) = mut_var_suggestion {
err.span_note(sp, format!("{msg}: `{sugg}`"));
}
}
_ if let Some((sp, msg, sugg)) = mut_var_suggestion => {
err.span_suggestion(sp, msg, sugg, Applicability::MachineApplicable);
}
_ => {} // don't provide suggestions in other cases #55175
}
Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/mismatched_types/ref-pat-suggestions.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,17 @@ fn main() {
let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types
let _ = |&_a: &u32| (); //~ ERROR mismatched types
let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types

#[allow(unused_mut)]
{
struct S(u8);

let mut _a = 0; //~ ERROR mismatched types
let S(_b) = S(0); //~ ERROR mismatched types
let (_c,) = (0,); //~ ERROR mismatched types

match 0 {
_d => {} //~ ERROR mismatched types
}
}
}
13 changes: 13 additions & 0 deletions src/test/ui/mismatched_types/ref-pat-suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,17 @@ fn main() {
let _ = |&mut &_a: &mut u32| (); //~ ERROR mismatched types
let _ = |&&mut _a: &u32| (); //~ ERROR mismatched types
let _ = |&mut &mut _a: &mut u32| (); //~ ERROR mismatched types

#[allow(unused_mut)]
{
struct S(u8);

let &mut _a = 0; //~ ERROR mismatched types
let S(&mut _b) = S(0); //~ ERROR mismatched types
let (&mut _c,) = (0,); //~ ERROR mismatched types

match 0 {
&mut _d => {} //~ ERROR mismatched types
}
}
}
92 changes: 91 additions & 1 deletion src/test/ui/mismatched_types/ref-pat-suggestions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ LL | fn _f1(&mut _a: u32) {}
|
= note: expected type `u32`
found mutable reference `&mut _`
note: to declare a mutable parameter use: `mut _a`
--> $DIR/ref-pat-suggestions.rs:4:8
|
LL | fn _f1(&mut _a: u32) {}
| ^^^^^^^
help: to take parameter `_a` by reference, move `&mut` to the type
|
LL - fn _f1(&mut _a: u32) {}
Expand Down Expand Up @@ -122,6 +127,11 @@ LL | let _: fn(u32) = |&mut _a| ();
|
= note: expected type `u32`
found mutable reference `&mut _`
note: to declare a mutable parameter use: `mut _a`
--> $DIR/ref-pat-suggestions.rs:12:23
|
LL | let _: fn(u32) = |&mut _a| ();
| ^^^^^^^
help: consider removing `&mut` from the pattern
|
LL - let _: fn(u32) = |&mut _a| ();
Expand Down Expand Up @@ -222,6 +232,11 @@ LL | let _ = |&mut _a: u32| ();
|
= note: expected type `u32`
found mutable reference `&mut _`
note: to declare a mutable parameter use: `mut _a`
--> $DIR/ref-pat-suggestions.rs:19:14
|
LL | let _ = |&mut _a: u32| ();
| ^^^^^^^
help: to take parameter `_a` by reference, move `&mut` to the type
|
LL - let _ = |&mut _a: u32| ();
Expand Down Expand Up @@ -292,6 +307,81 @@ LL - let _ = |&mut &mut _a: &mut u32| ();
LL + let _ = |&mut _a: &mut u32| ();
|

error: aborting due to 18 previous errors
error[E0308]: mismatched types
--> $DIR/ref-pat-suggestions.rs:29:13
|
LL | let &mut _a = 0;
| ^^^^^^^ - this expression has type `{integer}`
| |
| expected integer, found `&mut _`
| help: to declare a mutable variable use: `mut _a`
|
= note: expected type `{integer}`
found mutable reference `&mut _`

error[E0308]: mismatched types
--> $DIR/ref-pat-suggestions.rs:30:15
|
LL | let S(&mut _b) = S(0);
| ^^^^^^^ ---- this expression has type `S`
| |
| expected `u8`, found `&mut _`
|
= note: expected type `u8`
found mutable reference `&mut _`
note: to declare a mutable binding use: `mut _b`
--> $DIR/ref-pat-suggestions.rs:30:15
|
LL | let S(&mut _b) = S(0);
| ^^^^^^^
help: consider removing `&mut` from the pattern
|
LL - let S(&mut _b) = S(0);
LL + let S(_b) = S(0);
|

error[E0308]: mismatched types
--> $DIR/ref-pat-suggestions.rs:31:14
|
LL | let (&mut _c,) = (0,);
| ^^^^^^^ ---- this expression has type `({integer},)`
| |
| expected integer, found `&mut _`
|
= note: expected type `{integer}`
found mutable reference `&mut _`
note: to declare a mutable binding use: `mut _c`
--> $DIR/ref-pat-suggestions.rs:31:14
|
LL | let (&mut _c,) = (0,);
| ^^^^^^^
help: consider removing `&mut` from the pattern
|
LL - let (&mut _c,) = (0,);
LL + let (_c,) = (0,);
|

error[E0308]: mismatched types
--> $DIR/ref-pat-suggestions.rs:34:13
|
LL | match 0 {
| - this expression has type `{integer}`
LL | &mut _d => {}
| ^^^^^^^ expected integer, found `&mut _`
|
= note: expected type `{integer}`
found mutable reference `&mut _`
note: to declare a mutable binding use: `mut _d`
--> $DIR/ref-pat-suggestions.rs:34:13
|
LL | &mut _d => {}
| ^^^^^^^
help: consider removing `&mut` from the pattern
|
LL - &mut _d => {}
LL + _d => {}
|

error: aborting due to 22 previous errors

For more information about this error, try `rustc --explain E0308`.
5 changes: 5 additions & 0 deletions src/test/ui/pattern/for-loop-bad-item.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ LL | for ((_, _), (&mut c, _)) in &mut map {
|
= note: expected type `char`
found mutable reference `&mut _`
note: to declare a mutable binding use: `mut c`
--> $DIR/for-loop-bad-item.rs:7:19
|
LL | for ((_, _), (&mut c, _)) in &mut map {
| ^^^^^^
help: consider removing `&mut` from the pattern
|
LL - for ((_, _), (&mut c, _)) in &mut map {
Expand Down

0 comments on commit 1f923c2

Please sign in to comment.