|
1 | 1 | use crate::check::{FnCtxt, Expectation, Diverges, Needs};
|
2 | 2 | use crate::check::coercion::CoerceMany;
|
3 | 3 | use crate::util::nodemap::FxHashMap;
|
4 |
| -use errors::Applicability; |
5 |
| -use rustc::hir::{self, PatKind}; |
| 4 | +use errors::{Applicability, DiagnosticBuilder}; |
| 5 | +use rustc::hir::{self, PatKind, Pat}; |
6 | 6 | use rustc::hir::def::{Def, CtorKind};
|
7 | 7 | use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
8 | 8 | use rustc::infer;
|
@@ -377,15 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
377 | 377 | // Look for a case like `fn foo(&foo: u32)` and suggest
|
378 | 378 | // `fn foo(foo: &u32)`
|
379 | 379 | if let Some(mut err) = err {
|
380 |
| - if let PatKind::Binding(..) = inner.node { |
381 |
| - if let Ok(snippet) = tcx.sess.source_map() |
382 |
| - .span_to_snippet(pat.span) |
383 |
| - { |
384 |
| - err.help(&format!("did you mean `{}: &{}`?", |
385 |
| - &snippet[1..], |
386 |
| - expected)); |
387 |
| - } |
388 |
| - } |
| 380 | + self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); |
389 | 381 | err.emit();
|
390 | 382 | }
|
391 | 383 | (rptr_ty, inner_ty)
|
@@ -517,6 +509,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
517 | 509 | // subtyping.
|
518 | 510 | }
|
519 | 511 |
|
| 512 | + fn borrow_pat_suggestion( |
| 513 | + &self, |
| 514 | + err: &mut DiagnosticBuilder<'_>, |
| 515 | + pat: &Pat, |
| 516 | + inner: &Pat, |
| 517 | + expected: Ty<'tcx>, |
| 518 | + ) { |
| 519 | + let tcx = self.tcx; |
| 520 | + if let PatKind::Binding(..) = inner.node { |
| 521 | + let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id); |
| 522 | + let parent = tcx.hir().get_by_hir_id(parent_id); |
| 523 | + debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent); |
| 524 | + match parent { |
| 525 | + hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) | |
| 526 | + hir::Node::ForeignItem(hir::ForeignItem { |
| 527 | + node: hir::ForeignItemKind::Fn(..), .. |
| 528 | + }) | |
| 529 | + hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) | |
| 530 | + hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => { |
| 531 | + // this pat is likely an argument |
| 532 | + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { |
| 533 | + // FIXME: turn into structured suggestion, will need a span that also |
| 534 | + // includes the the arg's type. |
| 535 | + err.help(&format!("did you mean `{}: &{}`?", snippet, expected)); |
| 536 | + } |
| 537 | + } |
| 538 | + hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) | |
| 539 | + hir::Node::Pat(_) => { |
| 540 | + // rely on match ergonomics or it might be nested `&&pat` |
| 541 | + if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { |
| 542 | + err.span_suggestion( |
| 543 | + pat.span, |
| 544 | + "you can probably remove the explicit borrow", |
| 545 | + snippet, |
| 546 | + Applicability::MaybeIncorrect, |
| 547 | + ); |
| 548 | + } |
| 549 | + } |
| 550 | + _ => {} // don't provide suggestions in other cases #55175 |
| 551 | + } |
| 552 | + } |
| 553 | + } |
| 554 | + |
520 | 555 | pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
|
521 | 556 | if let PatKind::Binding(..) = inner.node {
|
522 | 557 | if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
|
|
0 commit comments