Rollup merge of #60393 - estebank:pat-sugg, r=oli-obk
Do not suggest incorrect syntax on pattern type error due to borrow Fix #55174.
This commit is contained in:
commit
3e536e8ac6
@ -1,8 +1,8 @@
|
||||
use crate::check::{FnCtxt, Expectation, Diverges, Needs};
|
||||
use crate::check::coercion::CoerceMany;
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
use errors::Applicability;
|
||||
use rustc::hir::{self, PatKind};
|
||||
use errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc::hir::{self, PatKind, Pat};
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc::infer;
|
||||
@ -377,15 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// Look for a case like `fn foo(&foo: u32)` and suggest
|
||||
// `fn foo(foo: &u32)`
|
||||
if let Some(mut err) = err {
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Ok(snippet) = tcx.sess.source_map()
|
||||
.span_to_snippet(pat.span)
|
||||
{
|
||||
err.help(&format!("did you mean `{}: &{}`?",
|
||||
&snippet[1..],
|
||||
expected));
|
||||
}
|
||||
}
|
||||
self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
|
||||
err.emit();
|
||||
}
|
||||
(rptr_ty, inner_ty)
|
||||
@ -517,6 +509,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// subtyping.
|
||||
}
|
||||
|
||||
fn borrow_pat_suggestion(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
pat: &Pat,
|
||||
inner: &Pat,
|
||||
expected: Ty<'tcx>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
|
||||
let parent = tcx.hir().get_by_hir_id(parent_id);
|
||||
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
|
||||
match parent {
|
||||
hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
|
||||
hir::Node::ForeignItem(hir::ForeignItem {
|
||||
node: hir::ForeignItemKind::Fn(..), ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
|
||||
hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
|
||||
// this pat is likely an argument
|
||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
|
||||
// FIXME: turn into structured suggestion, will need a span that also
|
||||
// includes the the arg's type.
|
||||
err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
|
||||
}
|
||||
}
|
||||
hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {} // don't provide suggestions in other cases #55175
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
|
||||
if let PatKind::Binding(..) = inner.node {
|
||||
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
|
||||
|
@ -20,21 +20,25 @@ error[E0308]: mismatched types
|
||||
--> $DIR/destructure-trait-ref.rs:31:10
|
||||
|
|
||||
LL | let &&x = &1isize as &T;
|
||||
| ^^ expected trait T, found reference
|
||||
| ^^
|
||||
| |
|
||||
| expected trait T, found reference
|
||||
| help: you can probably remove the explicit borrow: `x`
|
||||
|
|
||||
= note: expected type `dyn T`
|
||||
found type `&_`
|
||||
= help: did you mean `x: &dyn T`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/destructure-trait-ref.rs:36:11
|
||||
|
|
||||
LL | let &&&x = &(&1isize as &T);
|
||||
| ^^ expected trait T, found reference
|
||||
| ^^
|
||||
| |
|
||||
| expected trait T, found reference
|
||||
| help: you can probably remove the explicit borrow: `x`
|
||||
|
|
||||
= note: expected type `dyn T`
|
||||
found type `&_`
|
||||
= help: did you mean `x: &dyn T`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/destructure-trait-ref.rs:41:13
|
||||
|
@ -12,11 +12,13 @@ error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:18:9
|
||||
|
|
||||
LL | fn agh(&&bar: &u32) {
|
||||
| ^^^^ expected u32, found reference
|
||||
| ^^^^
|
||||
| |
|
||||
| expected u32, found reference
|
||||
| help: you can probably remove the explicit borrow: `bar`
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `&_`
|
||||
= help: did you mean `bar: &u32`?
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-38371.rs:21:8
|
||||
|
41
src/test/ui/suggestions/match-ergonomics.rs
Normal file
41
src/test/ui/suggestions/match-ergonomics.rs
Normal file
@ -0,0 +1,41 @@
|
||||
fn main() {
|
||||
let x = vec![1i32];
|
||||
match &x[..] {
|
||||
[&v] => {}, //~ ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
match x {
|
||||
[&v] => {}, //~ ERROR expected an array or slice
|
||||
_ => {},
|
||||
}
|
||||
match &x[..] {
|
||||
[v] => {},
|
||||
_ => {},
|
||||
}
|
||||
match &x[..] {
|
||||
&[v] => {},
|
||||
_ => {},
|
||||
}
|
||||
match x {
|
||||
[v] => {}, //~ ERROR expected an array or slice
|
||||
_ => {},
|
||||
}
|
||||
let y = 1i32;
|
||||
match &y {
|
||||
&v => {},
|
||||
_ => {},
|
||||
}
|
||||
match y {
|
||||
&v => {}, //~ ERROR mismatched types
|
||||
_ => {},
|
||||
}
|
||||
match &y {
|
||||
v => {},
|
||||
_ => {},
|
||||
}
|
||||
match y {
|
||||
v => {},
|
||||
_ => {},
|
||||
}
|
||||
if let [&v] = &x[..] {} //~ ERROR mismatched types
|
||||
}
|
52
src/test/ui/suggestions/match-ergonomics.stderr
Normal file
52
src/test/ui/suggestions/match-ergonomics.stderr
Normal file
@ -0,0 +1,52 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/match-ergonomics.rs:4:10
|
||||
|
|
||||
LL | [&v] => {},
|
||||
| ^^
|
||||
| |
|
||||
| expected i32, found reference
|
||||
| help: you can probably remove the explicit borrow: `v`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `&_`
|
||||
|
||||
error[E0529]: expected an array or slice, found `std::vec::Vec<i32>`
|
||||
--> $DIR/match-ergonomics.rs:8:9
|
||||
|
|
||||
LL | [&v] => {},
|
||||
| ^^^^ pattern cannot match with input type `std::vec::Vec<i32>`
|
||||
|
||||
error[E0529]: expected an array or slice, found `std::vec::Vec<i32>`
|
||||
--> $DIR/match-ergonomics.rs:20:9
|
||||
|
|
||||
LL | [v] => {},
|
||||
| ^^^ pattern cannot match with input type `std::vec::Vec<i32>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/match-ergonomics.rs:29:9
|
||||
|
|
||||
LL | &v => {},
|
||||
| ^^
|
||||
| |
|
||||
| expected i32, found reference
|
||||
| help: you can probably remove the explicit borrow: `v`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `&_`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/match-ergonomics.rs:40:13
|
||||
|
|
||||
LL | if let [&v] = &x[..] {}
|
||||
| ^^
|
||||
| |
|
||||
| expected i32, found reference
|
||||
| help: you can probably remove the explicit borrow: `v`
|
||||
|
|
||||
= note: expected type `i32`
|
||||
found type `&_`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0529.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
Loading…
x
Reference in New Issue
Block a user