|
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