about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs52
1 files changed, 40 insertions, 12 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 6afbde86739..4ab7e2ee177 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3494,7 +3494,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if pick.autoderefs == 0 && !skip {
                             suggest = self.detect_and_explain_multiple_crate_versions(
                                 err,
-                                &pick.item,
+                                pick.item.def_id,
+                                pick.item.ident(self.tcx).span,
                                 rcvr.hir_id.owner,
                                 *rcvr_ty,
                             );
@@ -3684,6 +3685,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         }
+
+        if let SelfSource::QPath(ty) = source
+            && !valid_out_of_scope_traits.is_empty()
+            && let hir::TyKind::Path(path) = ty.kind
+            && let hir::QPath::Resolved(_, path) = path
+            && let Some(def_id) = path.res.opt_def_id()
+            && let Some(assoc) = self
+                .tcx
+                .associated_items(valid_out_of_scope_traits[0])
+                .filter_by_name_unhygienic(item_name.name)
+                .next()
+        {
+            // See if the `Type::function(val)` where `function` wasn't found corresponds to a
+            // `Trait` that is imported directly, but `Type` came from a different version of the
+            // same crate.
+            let rcvr_ty = self.tcx.type_of(def_id).instantiate_identity();
+            suggest = self.detect_and_explain_multiple_crate_versions(
+                err,
+                assoc.def_id,
+                self.tcx.def_span(assoc.def_id),
+                ty.hir_id.owner,
+                rcvr_ty,
+            );
+        }
         if suggest && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) {
             return;
         }
@@ -4052,21 +4077,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn detect_and_explain_multiple_crate_versions(
         &self,
         err: &mut Diag<'_>,
-        item: &ty::AssocItem,
+        item_def_id: DefId,
+        item_span: Span,
         owner: hir::OwnerId,
         rcvr_ty: Ty<'_>,
     ) -> bool {
-        let pick_name = self.tcx.crate_name(item.def_id.krate);
+        let pick_name = self.tcx.crate_name(item_def_id.krate);
+        let trait_did = self.tcx.parent(item_def_id);
+        let trait_name = self.tcx.item_name(trait_did);
         if let Some(map) = self.tcx.in_scope_traits_map(owner) {
             for trait_candidate in map.to_sorted_stable_ord().into_iter().flat_map(|v| v.1.iter()) {
-                let name = self.tcx.crate_name(trait_candidate.def_id.krate);
-                if trait_candidate.def_id.krate != item.def_id.krate && name == pick_name {
+                let crate_name = self.tcx.crate_name(trait_candidate.def_id.krate);
+                if trait_candidate.def_id.krate != item_def_id.krate && crate_name == pick_name {
                     let msg = format!(
-                        "there are multiple different versions of crate `{name}` in the \
+                        "there are multiple different versions of crate `{crate_name}` in the \
                          dependency graph",
                     );
-                    let tdid = self.tcx.parent(item.def_id);
-                    if self.tcx.item_name(trait_candidate.def_id) == self.tcx.item_name(tdid)
+                    let candidate_name = self.tcx.item_name(trait_candidate.def_id);
+                    if candidate_name == trait_name
                         && let Some(def_id) = trait_candidate.import_ids.get(0)
                     {
                         let span = self.tcx.def_span(*def_id);
@@ -4074,8 +4102,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         multi_span.push_span_label(
                             span,
                             format!(
-                                "`{name}` imported here doesn't correspond to the right crate \
-                                 version",
+                                "`{crate_name}` imported here doesn't correspond to the right \
+                                 crate version",
                             ),
                         );
                         multi_span.push_span_label(
@@ -4083,11 +4111,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             format!("this is the trait that was imported"),
                         );
                         multi_span.push_span_label(
-                            self.tcx.def_span(tdid),
+                            self.tcx.def_span(trait_did),
                             format!("this is the trait that is needed"),
                         );
                         multi_span.push_span_label(
-                            item.ident(self.tcx).span,
+                            item_span,
                             format!("the method is available for `{rcvr_ty}` here"),
                         );
                         err.span_note(multi_span, msg);