about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs72
2 files changed, 27 insertions, 47 deletions
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 2a1c6b895ce..a324bd03eca 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -887,7 +887,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
         coerce
             .autoderef(rustc_span::DUMMY_SP, expr_ty)
-            .find_map(|(ty, steps)| coerce.unify(ty, target).ok().map(|_| steps))
+            .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
     }
 
     /// Given some expressions, their known unified type and another expression,
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index fc7a9c1d59b..700b9359d06 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -1,16 +1,15 @@
 use crate::check::FnCtxt;
 use rustc_infer::infer::InferOk;
 use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause};
+use rustc_trait_selection::traits::ObligationCause;
 
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem};
+use rustc_hir::lang_items::CloneTraitLangItem;
 use rustc_hir::{is_range_literal, Node};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
-use rustc_middle::ty::{self, AssocItem, ToPredicate, Ty, TypeAndMut};
+use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -633,48 +632,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             _ if sp == expr.span && !is_macro => {
-                // Check for `Deref` implementations by constructing a predicate to
-                // prove: `<T as Deref>::Output == U`
-                let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp));
-                let item_def_id = self
-                    .tcx
-                    .associated_items(deref_trait)
-                    .in_definition_order()
-                    .find(|item| item.kind == ty::AssocKind::Type)
-                    .unwrap()
-                    .def_id;
-                let predicate =
-                    ty::PredicateKind::Projection(ty::Binder::bind(ty::ProjectionPredicate {
-                        // `<T as Deref>::Output`
-                        projection_ty: ty::ProjectionTy {
-                            // `T`
-                            substs: self.tcx.intern_substs(&[checked_ty.into()]),
-                            // `Deref::Output`
-                            item_def_id,
-                        },
-                        // `U`
-                        ty: expected,
-                    }))
-                    .to_predicate(self.tcx);
-                let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
-                let impls_deref = self.infcx.predicate_may_hold(&obligation);
-
-                // For a suggestion to make sense, the type would need to be `Copy`.
-                let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp);
-
-                if is_copy && impls_deref {
-                    if let Ok(code) = sm.span_to_snippet(sp) {
-                        let message = if checked_ty.is_region_ptr() {
-                            "consider dereferencing the borrow"
-                        } else {
-                            "consider dereferencing the type"
-                        };
-                        let suggestion = if is_struct_pat_shorthand_field {
-                            format!("{}: *{}", code, code)
-                        } else {
-                            format!("*{}", code)
-                        };
-                        return Some((sp, message, suggestion, Applicability::MachineApplicable));
+                if let Some(steps) = self.deref_steps(checked_ty, expected) {
+                    if steps == 1 {
+                        // For a suggestion to make sense, the type would need to be `Copy`.
+                        if self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp) {
+                            if let Ok(code) = sm.span_to_snippet(sp) {
+                                let message = if checked_ty.is_region_ptr() {
+                                    "consider dereferencing the borrow"
+                                } else {
+                                    "consider dereferencing the type"
+                                };
+                                let suggestion = if is_struct_pat_shorthand_field {
+                                    format!("{}: *{}", code, code)
+                                } else {
+                                    format!("*{}", code)
+                                };
+                                return Some((
+                                    sp,
+                                    message,
+                                    suggestion,
+                                    Applicability::MachineApplicable,
+                                ));
+                            }
+                        }
                     }
                 }
             }