|
1 | 1 | use crate::check::FnCtxt;
|
2 | 2 | use rustc_infer::infer::InferOk;
|
3 | 3 | use rustc_trait_selection::infer::InferCtxtExt as _;
|
4 |
| -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; |
5 |
| -use rustc_trait_selection::traits::{self, ObligationCause}; |
| 4 | +use rustc_trait_selection::traits::ObligationCause; |
6 | 5 |
|
7 | 6 | use rustc_ast::util::parser::PREC_POSTFIX;
|
8 | 7 | use rustc_errors::{Applicability, DiagnosticBuilder};
|
9 | 8 | use rustc_hir as hir;
|
10 |
| -use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem}; |
| 9 | +use rustc_hir::lang_items::CloneTraitLangItem; |
11 | 10 | use rustc_hir::{is_range_literal, Node};
|
12 | 11 | use rustc_middle::ty::adjustment::AllowTwoPhase;
|
13 |
| -use rustc_middle::ty::{self, AssocItem, ToPredicate, Ty, TypeAndMut}; |
| 12 | +use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; |
14 | 13 | use rustc_span::symbol::sym;
|
15 | 14 | use rustc_span::Span;
|
16 | 15 |
|
@@ -633,48 +632,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
633 | 632 | }
|
634 | 633 | }
|
635 | 634 | _ if sp == expr.span && !is_macro => {
|
636 |
| - // Check for `Deref` implementations by constructing a predicate to |
637 |
| - // prove: `<T as Deref>::Output == U` |
638 |
| - let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp)); |
639 |
| - let item_def_id = self |
640 |
| - .tcx |
641 |
| - .associated_items(deref_trait) |
642 |
| - .in_definition_order() |
643 |
| - .find(|item| item.kind == ty::AssocKind::Type) |
644 |
| - .unwrap() |
645 |
| - .def_id; |
646 |
| - let predicate = |
647 |
| - ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate { |
648 |
| - // `<T as Deref>::Output` |
649 |
| - projection_ty: ty::ProjectionTy { |
650 |
| - // `T` |
651 |
| - substs: self.tcx.intern_substs(&[checked_ty.into()]), |
652 |
| - // `Deref::Output` |
653 |
| - item_def_id, |
654 |
| - }, |
655 |
| - // `U` |
656 |
| - ty: expected, |
657 |
| - })) |
658 |
| - .to_predicate(self.tcx); |
659 |
| - let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate); |
660 |
| - let impls_deref = self.infcx.predicate_may_hold(&obligation); |
661 |
| - |
662 |
| - // For a suggestion to make sense, the type would need to be `Copy`. |
663 |
| - let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp); |
664 |
| - |
665 |
| - if is_copy && impls_deref { |
666 |
| - if let Ok(code) = sm.span_to_snippet(sp) { |
667 |
| - let message = if checked_ty.is_region_ptr() { |
668 |
| - "consider dereferencing the borrow" |
669 |
| - } else { |
670 |
| - "consider dereferencing the type" |
671 |
| - }; |
672 |
| - let suggestion = if is_struct_pat_shorthand_field { |
673 |
| - format!("{}: *{}", code, code) |
674 |
| - } else { |
675 |
| - format!("*{}", code) |
676 |
| - }; |
677 |
| - return Some((sp, message, suggestion, Applicability::MachineApplicable)); |
| 635 | + if let Some(steps) = self.deref_steps(checked_ty, expected) { |
| 636 | + if steps == 1 { |
| 637 | + // For a suggestion to make sense, the type would need to be `Copy`. |
| 638 | + if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) { |
| 639 | + if let Ok(code) = sm.span_to_snippet(sp) { |
| 640 | + let message = if checked_ty.is_region_ptr() { |
| 641 | + "consider dereferencing the borrow" |
| 642 | + } else { |
| 643 | + "consider dereferencing the type" |
| 644 | + }; |
| 645 | + let suggestion = if is_struct_pat_shorthand_field { |
| 646 | + format!("{}: *{}", code, code) |
| 647 | + } else { |
| 648 | + format!("*{}", code) |
| 649 | + }; |
| 650 | + return Some(( |
| 651 | + sp, |
| 652 | + message, |
| 653 | + suggestion, |
| 654 | + Applicability::MachineApplicable, |
| 655 | + )); |
| 656 | + } |
| 657 | + } |
678 | 658 | }
|
679 | 659 | }
|
680 | 660 | }
|
|
0 commit comments