From e9d49b2bfc4e4c327987bb9d2a65b113b10100de Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 10 Jun 2022 23:18:42 +0400 Subject: [PATCH 1/5] Fix suggestions for `&a: T` parameters Previously we were suggesting stuff like `fn f( &u32) {}` --- compiler/rustc_typeck/src/check/pat.rs | 55 ++-- src/test/ui/destructure-trait-ref.stderr | 12 +- .../mismatched_types/issue-38371-unfixable.rs | 5 + .../issue-38371-unfixable.stderr | 21 ++ .../ui/mismatched_types/issue-38371.fixed | 18 ++ src/test/ui/mismatched_types/issue-38371.rs | 29 +- .../ui/mismatched_types/issue-38371.stderr | 47 ++- .../ref-pat-suggestions.fixed | 24 ++ .../mismatched_types/ref-pat-suggestions.rs | 24 ++ .../ref-pat-suggestions.stderr | 297 ++++++++++++++++++ src/test/ui/pattern/for-loop-bad-item.stderr | 6 +- .../ui/suggestions/match-ergonomics.stderr | 26 +- 12 files changed, 476 insertions(+), 88 deletions(-) create mode 100644 src/test/ui/mismatched_types/issue-38371-unfixable.rs create mode 100644 src/test/ui/mismatched_types/issue-38371-unfixable.stderr create mode 100644 src/test/ui/mismatched_types/issue-38371.fixed create mode 100644 src/test/ui/mismatched_types/ref-pat-suggestions.fixed create mode 100644 src/test/ui/mismatched_types/ref-pat-suggestions.rs create mode 100644 src/test/ui/mismatched_types/ref-pat-suggestions.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5eba95b495dd7..8727ae4ea51ae 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -649,39 +649,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn borrow_pat_suggestion( - &self, - err: &mut Diagnostic, - pat: &Pat<'_>, - inner: &Pat<'_>, - expected: Ty<'tcx>, - ) { + fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>, inner: &Pat<'_>) { let tcx = self.tcx; - if let PatKind::Binding(..) = inner.kind { + if let PatKind::Ref(_, mutbl) = pat.kind + && let PatKind::Binding(_, _, binding, ..) = inner.kind { let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); let binding_parent = tcx.hir().get(binding_parent_id); - debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent); + debug!(?inner, ?pat, ?binding_parent); + + let mutability = match mutbl { + ast::Mutability::Mut => "mut", + ast::Mutability::Not => "", + }; + match binding_parent { - hir::Node::Param(hir::Param { span, .. }) - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) => - { - err.span_suggestion( - *span, - &format!("did you mean `{snippet}`"), - format!(" &{expected}"), - Applicability::MachineApplicable, + hir::Node::Param(hir::Param { ty_span, .. }) if binding.span.hi() <= ty_span.lo() => { + err.multipart_suggestion_verbose( + format!("to take parameter by ref, move `&{mutability}` to the type"), + vec![ + (pat.span.until(inner.span), "".to_owned()), + (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), + ], + Applicability::MachineApplicable ); } - hir::Node::Arm(_) | hir::Node::Pat(_) => { + hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => { // rely on match ergonomics or it might be nested `&&pat` - if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { - err.span_suggestion( - pat.span, - "you can probably remove the explicit borrow", - snippet, - Applicability::MaybeIncorrect, - ); - } + err.span_suggestion_verbose( + pat.span.until(inner.span), + format!("consider removing `&{mutability}` from the pattern"), + "", + Applicability::MaybeIncorrect, + ); } _ => {} // don't provide suggestions in other cases #55175 } @@ -1853,7 +1852,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Take region, inner-type from expected type if we can, // to avoid creating needless variables. This also helps with - // the bad interactions of the given hack detailed in (note_1). + // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); match *expected.kind() { ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty), @@ -1869,7 +1868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, pat, inner, expected); + self.borrow_pat_suggestion(&mut err, pat, inner); err.emit(); } (rptr_ty, inner_ty) diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr index 302917ca02e00..1291517928e3d 100644 --- a/src/test/ui/destructure-trait-ref.stderr +++ b/src/test/ui/destructure-trait-ref.stderr @@ -23,10 +23,14 @@ LL | let &&x = &1isize as &dyn T; | ^^ ----------------- this expression has type `&dyn T` | | | expected trait object `dyn T`, found reference - | help: you can probably remove the explicit borrow: `x` | = note: expected trait object `dyn T` found reference `&_` +help: consider removing `&` from the pattern + | +LL - let &&x = &1isize as &dyn T; +LL + let &x = &1isize as &dyn T; + | error[E0308]: mismatched types --> $DIR/destructure-trait-ref.rs:36:11 @@ -35,10 +39,14 @@ LL | let &&&x = &(&1isize as &dyn T); | ^^ -------------------- this expression has type `&&dyn T` | | | expected trait object `dyn T`, found reference - | help: you can probably remove the explicit borrow: `x` | = note: expected trait object `dyn T` found reference `&_` +help: consider removing `&` from the pattern + | +LL - let &&&x = &(&1isize as &dyn T); +LL + let &&x = &(&1isize as &dyn T); + | error[E0308]: mismatched types --> $DIR/destructure-trait-ref.rs:40:13 diff --git a/src/test/ui/mismatched_types/issue-38371-unfixable.rs b/src/test/ui/mismatched_types/issue-38371-unfixable.rs new file mode 100644 index 0000000000000..c4316bfdd18dc --- /dev/null +++ b/src/test/ui/mismatched_types/issue-38371-unfixable.rs @@ -0,0 +1,5 @@ +fn ugh(&[bar]: &u32) {} //~ ERROR expected an array or slice + +fn bgh(&&bar: u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/mismatched_types/issue-38371-unfixable.stderr b/src/test/ui/mismatched_types/issue-38371-unfixable.stderr new file mode 100644 index 0000000000000..3c5e765abfbe2 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-38371-unfixable.stderr @@ -0,0 +1,21 @@ +error[E0529]: expected an array or slice, found `u32` + --> $DIR/issue-38371-unfixable.rs:1:9 + | +LL | fn ugh(&[bar]: &u32) {} + | ^^^^^ pattern cannot match with input type `u32` + +error[E0308]: mismatched types + --> $DIR/issue-38371-unfixable.rs:3:8 + | +LL | fn bgh(&&bar: u32) {} + | ^^^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0529. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/issue-38371.fixed b/src/test/ui/mismatched_types/issue-38371.fixed new file mode 100644 index 0000000000000..0e20835bef05f --- /dev/null +++ b/src/test/ui/mismatched_types/issue-38371.fixed @@ -0,0 +1,18 @@ +// run-rustfix +// see also issue-38371-unfixable.rs +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct Foo {} + +fn foo(_a: &Foo) {} //~ ERROR mismatched types + +fn bar(_a: Foo) {} + +fn qux(_a: &Foo) {} + +fn zar(&_a: &Foo) {} + +fn agh(&_a: &u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/mismatched_types/issue-38371.rs b/src/test/ui/mismatched_types/issue-38371.rs index d2cd2b88ab706..fb9e4c173e7a8 100644 --- a/src/test/ui/mismatched_types/issue-38371.rs +++ b/src/test/ui/mismatched_types/issue-38371.rs @@ -1,27 +1,18 @@ -struct Foo { -} +// run-rustfix +// see also issue-38371-unfixable.rs +#![allow(dead_code)] -fn foo(&foo: Foo) { //~ ERROR mismatched types -} +#[derive(Copy, Clone)] +struct Foo {} -fn bar(foo: Foo) { -} +fn foo(&_a: Foo) {} //~ ERROR mismatched types -fn qux(foo: &Foo) { -} +fn bar(_a: Foo) {} -fn zar(&foo: &Foo) { -} +fn qux(_a: &Foo) {} -// The somewhat unexpected help message in this case is courtesy of -// match_default_bindings. -fn agh(&&bar: &u32) { //~ ERROR mismatched types -} +fn zar(&_a: &Foo) {} -fn bgh(&&bar: u32) { //~ ERROR mismatched types -} - -fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice -} +fn agh(&&_a: &u32) {} //~ ERROR mismatched types fn main() {} diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 5d2ce9302ece6..5a0146dfd210b 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -1,46 +1,35 @@ error[E0308]: mismatched types - --> $DIR/issue-38371.rs:4:8 + --> $DIR/issue-38371.rs:8:8 | -LL | fn foo(&foo: Foo) { - | ^^^^----- - | | | - | | expected due to this +LL | fn foo(&_a: Foo) {} + | ^^^ --- expected due to this + | | | expected struct `Foo`, found reference - | help: did you mean `foo`: `&Foo` | = note: expected struct `Foo` found reference `&_` +help: to take parameter by ref, move `&` to the type + | +LL - fn foo(&_a: Foo) {} +LL + fn foo(_a: &Foo) {} + | error[E0308]: mismatched types - --> $DIR/issue-38371.rs:18:9 + --> $DIR/issue-38371.rs:16:9 | -LL | fn agh(&&bar: &u32) { - | ^^^^ ---- expected due to this +LL | fn agh(&&_a: &u32) {} + | ^^^ ---- expected due to this | | | expected `u32`, found reference - | help: you can probably remove the explicit borrow: `bar` - | - = note: expected type `u32` - found reference `&_` - -error[E0308]: mismatched types - --> $DIR/issue-38371.rs:21:8 - | -LL | fn bgh(&&bar: u32) { - | ^^^^^ --- expected due to this - | | - | expected `u32`, found reference | = note: expected type `u32` found reference `&_` - -error[E0529]: expected an array or slice, found `u32` - --> $DIR/issue-38371.rs:24:9 +help: consider removing `&` from the pattern | -LL | fn ugh(&[bar]: &u32) { - | ^^^^^ pattern cannot match with input type `u32` +LL - fn agh(&&_a: &u32) {} +LL + fn agh(&_a: &u32) {} + | -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0529. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed new file mode 100644 index 0000000000000..e9472b5194384 --- /dev/null +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +fn _f0(_a: &u32) {} //~ ERROR mismatched types +fn _f1(_a: &mut u32) {} //~ ERROR mismatched types +fn _f2(&_a: &u32) {} //~ ERROR mismatched types +fn _f3(&mut _a: &mut u32) {} //~ ERROR mismatched types +fn _f4(&_a: &u32) {} //~ ERROR mismatched types +fn _f5(&mut _a: &mut u32) {} //~ ERROR mismatched types + +fn main() { + let _: fn(u32) = |_a| (); //~ ERROR mismatched types + let _: fn(u32) = |_a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + + let _ = |_a: &u32| (); //~ ERROR mismatched types + let _ = |_a: &mut u32| (); //~ ERROR mismatched types + let _ = |&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types + let _ = |&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types +} diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.rs b/src/test/ui/mismatched_types/ref-pat-suggestions.rs new file mode 100644 index 0000000000000..49d88d13e01b3 --- /dev/null +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.rs @@ -0,0 +1,24 @@ +// run-rustfix + +fn _f0(&_a: u32) {} //~ ERROR mismatched types +fn _f1(&mut _a: u32) {} //~ ERROR mismatched types +fn _f2(&&_a: &u32) {} //~ ERROR mismatched types +fn _f3(&mut &_a: &mut u32) {} //~ ERROR mismatched types +fn _f4(&&mut _a: &u32) {} //~ ERROR mismatched types +fn _f5(&mut &mut _a: &mut u32) {} //~ ERROR mismatched types + +fn main() { + let _: fn(u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &_a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&&mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types + + let _ = |&_a: u32| (); //~ ERROR mismatched types + let _ = |&mut _a: u32| (); //~ ERROR mismatched types + let _ = |&&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut &_a: &mut u32| (); //~ ERROR mismatched types + let _ = |&&mut _a: &u32| (); //~ ERROR mismatched types + let _ = |&mut &mut _a: &mut u32| (); //~ ERROR mismatched types +} diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr new file mode 100644 index 0000000000000..6ce1f9602ddb3 --- /dev/null +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr @@ -0,0 +1,297 @@ +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:3:8 + | +LL | fn _f0(&_a: u32) {} + | ^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: to take parameter by ref, move `&` to the type + | +LL - fn _f0(&_a: u32) {} +LL + fn _f0(_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:4:8 + | +LL | fn _f1(&mut _a: u32) {} + | ^^^^^^^ --- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: to take parameter by ref, move `&mut` to the type + | +LL - fn _f1(&mut _a: u32) {} +LL + fn _f1(_a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:5:9 + | +LL | fn _f2(&&_a: &u32) {} + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn _f2(&&_a: &u32) {} +LL + fn _f2(&_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:6:13 + | +LL | fn _f3(&mut &_a: &mut u32) {} + | ^^^ -------- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn _f3(&mut &_a: &mut u32) {} +LL + fn _f3(&mut _a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:7:9 + | +LL | fn _f4(&&mut _a: &u32) {} + | ^^^^^^^ ---- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - fn _f4(&&mut _a: &u32) {} +LL + fn _f4(&_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:8:13 + | +LL | fn _f5(&mut &mut _a: &mut u32) {} + | ^^^^^^^ -------- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - fn _f5(&mut &mut _a: &mut u32) {} +LL + fn _f5(&mut _a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:11:23 + | +LL | let _: fn(u32) = |&_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(u32) = |&_a| (); +LL + let _: fn(u32) = |_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:12:23 + | +LL | let _: fn(u32) = |&mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(u32) = |&mut _a| (); +LL + let _: fn(u32) = |_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:13:25 + | +LL | let _: fn(&u32) = |&&_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(&u32) = |&&_a| (); +LL + let _: fn(&u32) = |&_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:14:33 + | +LL | let _: fn(&mut u32) = |&mut &_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(&mut u32) = |&mut &_a| (); +LL + let _: fn(&mut u32) = |&mut _a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:15:25 + | +LL | let _: fn(&u32) = |&&mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(&u32) = |&&mut _a| (); +LL + let _: fn(&u32) = |&_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:16:33 + | +LL | let _: fn(&mut u32) = |&mut &mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(&mut u32) = |&mut &mut _a| (); +LL + let _: fn(&mut u32) = |&mut _a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:18:14 + | +LL | let _ = |&_a: u32| (); + | ^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: to take parameter by ref, move `&` to the type + | +LL - let _ = |&_a: u32| (); +LL + let _ = |_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:19:14 + | +LL | let _ = |&mut _a: u32| (); + | ^^^^^^^ --- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: to take parameter by ref, move `&mut` to the type + | +LL - let _ = |&mut _a: u32| (); +LL + let _ = |_a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:20:15 + | +LL | let _ = |&&_a: &u32| (); + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _ = |&&_a: &u32| (); +LL + let _ = |&_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:21:19 + | +LL | let _ = |&mut &_a: &mut u32| (); + | ^^^ -------- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _ = |&mut &_a: &mut u32| (); +LL + let _ = |&mut _a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:22:15 + | +LL | let _ = |&&mut _a: &u32| (); + | ^^^^^^^ ---- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _ = |&&mut _a: &u32| (); +LL + let _ = |&_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:23:19 + | +LL | let _ = |&mut &mut _a: &mut u32| (); + | ^^^^^^^ -------- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _ = |&mut &mut _a: &mut u32| (); +LL + let _ = |&mut _a: &mut u32| (); + | + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/for-loop-bad-item.stderr b/src/test/ui/pattern/for-loop-bad-item.stderr index 9410e4da8d2af..886d815d70bea 100644 --- a/src/test/ui/pattern/for-loop-bad-item.stderr +++ b/src/test/ui/pattern/for-loop-bad-item.stderr @@ -5,10 +5,14 @@ LL | for ((_, _), (&mut c, _)) in &mut map { | ^^^^^^ -------- this is an iterator with items of type `(&(char, char), &mut (char, char))` | | | expected `char`, found `&mut _` - | help: you can probably remove the explicit borrow: `c` | = note: expected type `char` found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - for ((_, _), (&mut c, _)) in &mut map { +LL + for ((_, _), (c, _)) in &mut map { + | error[E0308]: mismatched types --> $DIR/for-loop-bad-item.rs:14:14 diff --git a/src/test/ui/suggestions/match-ergonomics.stderr b/src/test/ui/suggestions/match-ergonomics.stderr index 4eab2df30801e..a9342f9fc309d 100644 --- a/src/test/ui/suggestions/match-ergonomics.stderr +++ b/src/test/ui/suggestions/match-ergonomics.stderr @@ -4,13 +4,15 @@ error[E0308]: mismatched types LL | match &x[..] { | ------ this expression has type `&[i32]` LL | [&v] => {}, - | ^^ - | | - | expected `i32`, found reference - | help: you can probably remove the explicit borrow: `v` + | ^^ expected `i32`, found reference | = note: expected type `i32` found reference `&_` +help: consider removing `&` from the pattern + | +LL - [&v] => {}, +LL + [v] => {}, + | error[E0529]: expected an array or slice, found `Vec` --> $DIR/match-ergonomics.rs:8:9 @@ -34,13 +36,15 @@ error[E0308]: mismatched types LL | match y { | - this expression has type `i32` LL | &v => {}, - | ^^ - | | - | expected `i32`, found reference - | help: you can probably remove the explicit borrow: `v` + | ^^ expected `i32`, found reference | = note: expected type `i32` found reference `&_` +help: consider removing `&` from the pattern + | +LL - &v => {}, +LL + v => {}, + | error[E0308]: mismatched types --> $DIR/match-ergonomics.rs:40:13 @@ -49,10 +53,14 @@ LL | if let [&v] = &x[..] {} | ^^ ------ this expression has type `&[i32]` | | | expected `i32`, found reference - | help: you can probably remove the explicit borrow: `v` | = note: expected type `i32` found reference `&_` +help: consider removing `&` from the pattern + | +LL - if let [&v] = &x[..] {} +LL + if let [v] = &x[..] {} + | error: aborting due to 5 previous errors From 2411692ab69922f16f24657b8c2e4f49e7a2932a Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:03:46 +0400 Subject: [PATCH 2/5] Make preconditions of `check_pat_ref` & `borrow_pat_suggestion` clearer --- compiler/rustc_typeck/src/check/pat.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 8727ae4ea51ae..836cdb4206a60 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -649,9 +649,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>, inner: &Pat<'_>) { + // Precondition: pat is a Ref(_) pattern + fn borrow_pat_suggestion(&self, err: &mut Diagnostic, pat: &Pat<'_>) { let tcx = self.tcx; - if let PatKind::Ref(_, mutbl) = pat.kind + if let PatKind::Ref(inner, mutbl) = pat.kind && let PatKind::Binding(_, _, binding, ..) = inner.kind { let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); let binding_parent = tcx.hir().get(binding_parent_id); @@ -1835,6 +1836,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { box_ty } + // Precondition: Pat is Ref(inner) fn check_pat_ref( &self, pat: &'tcx Pat<'tcx>, @@ -1868,7 +1870,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, pat, inner); + self.borrow_pat_suggestion(&mut err, pat); err.emit(); } (rptr_ty, inner_ty) From 451e0301d88feb3836177217c8d103d197b2b774 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:31:47 +0400 Subject: [PATCH 3/5] Improve suggestion wording --- compiler/rustc_typeck/src/check/pat.rs | 2 +- src/test/ui/mismatched_types/issue-38371.stderr | 2 +- src/test/ui/mismatched_types/ref-pat-suggestions.stderr | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 836cdb4206a60..5ecdbdadefd09 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -666,7 +666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match binding_parent { hir::Node::Param(hir::Param { ty_span, .. }) if binding.span.hi() <= ty_span.lo() => { err.multipart_suggestion_verbose( - format!("to take parameter by ref, move `&{mutability}` to the type"), + format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index 5a0146dfd210b..003f17cda1553 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -8,7 +8,7 @@ LL | fn foo(&_a: Foo) {} | = note: expected struct `Foo` found reference `&_` -help: to take parameter by ref, move `&` to the type +help: to take parameter `_a` by reference, move `&` to the type | LL - fn foo(&_a: Foo) {} LL + fn foo(_a: &Foo) {} diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr index 6ce1f9602ddb3..0516bad49abf3 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr @@ -8,7 +8,7 @@ LL | fn _f0(&_a: u32) {} | = note: expected type `u32` found reference `&_` -help: to take parameter by ref, move `&` to the type +help: to take parameter `_a` by reference, move `&` to the type | LL - fn _f0(&_a: u32) {} LL + fn _f0(_a: &u32) {} @@ -24,7 +24,7 @@ LL | fn _f1(&mut _a: u32) {} | = note: expected type `u32` found mutable reference `&mut _` -help: to take parameter by ref, move `&mut` to the type +help: to take parameter `_a` by reference, move `&mut` to the type | LL - fn _f1(&mut _a: u32) {} LL + fn _f1(_a: &mut u32) {} @@ -206,7 +206,7 @@ LL | let _ = |&_a: u32| (); | = note: expected type `u32` found reference `&_` -help: to take parameter by ref, move `&` to the type +help: to take parameter `_a` by reference, move `&` to the type | LL - let _ = |&_a: u32| (); LL + let _ = |_a: &u32| (); @@ -222,7 +222,7 @@ LL | let _ = |&mut _a: u32| (); | = note: expected type `u32` found mutable reference `&mut _` -help: to take parameter by ref, move `&mut` to the type +help: to take parameter `_a` by reference, move `&mut` to the type | LL - let _ = |&mut _a: u32| (); LL + let _ = |_a: &mut u32| (); From dc2977e630c233866459399f0ff773505372803d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:49:53 +0400 Subject: [PATCH 4/5] check for inferred params in a clearer way --- compiler/rustc_typeck/src/check/pat.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5ecdbdadefd09..2fadf9c893804 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -664,7 +664,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match binding_parent { - hir::Node::Param(hir::Param { ty_span, .. }) if binding.span.hi() <= ty_span.lo() => { + // 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 + hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => { err.multipart_suggestion_verbose( format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ From 33ccd76562fe549e147bfccd0f5666505401ae0d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 13 Jun 2022 13:51:03 +0400 Subject: [PATCH 5/5] Remove trailing whitespace --- compiler/rustc_typeck/src/check/pat.rs | 2 +- src/test/ui/mismatched_types/ref-pat-suggestions.fixed | 2 +- src/test/ui/mismatched_types/ref-pat-suggestions.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 2fadf9c893804..59d8776ca23a5 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so we don't suggest moving something to the type that does not exist hir::Node::Param(hir::Param { ty_span, .. }) if binding.span != *ty_span => { err.multipart_suggestion_verbose( - format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), + format!("to take parameter `{binding}` by reference, move `&{mutability}` to the type"), vec![ (pat.span.until(inner.span), "".to_owned()), (ty_span.shrink_to_lo(), format!("&{}", mutbl.prefix_str())), diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed index e9472b5194384..ab8483eef49fa 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed @@ -13,7 +13,7 @@ fn main() { let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types - let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types let _ = |_a: &u32| (); //~ ERROR mismatched types let _ = |_a: &mut u32| (); //~ ERROR mismatched types diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.rs b/src/test/ui/mismatched_types/ref-pat-suggestions.rs index 49d88d13e01b3..7e55539aa3d1b 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.rs +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.rs @@ -13,7 +13,7 @@ fn main() { let _: fn(&u32) = |&&_a| (); //~ ERROR mismatched types let _: fn(&mut u32) = |&mut &_a| (); //~ ERROR mismatched types let _: fn(&u32) = |&&mut _a| (); //~ ERROR mismatched types - let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types let _ = |&_a: u32| (); //~ ERROR mismatched types let _ = |&mut _a: u32| (); //~ ERROR mismatched types