about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-08-18 18:59:26 +0000
committerMichael Goulet <michael@errs.io>2024-08-26 13:02:21 -0400
commit00c435d9b37540d16489862446d934e98e58dfb1 (patch)
treee7def30caf987042885eca66c0f75b42801f0d06
parent22572d0994593197593e2a1b7b18d720a9a349a7 (diff)
downloadrust-00c435d9b37540d16489862446d934e98e58dfb1.tar.gz
rust-00c435d9b37540d16489862446d934e98e58dfb1.zip
Do not ICE on non-ADT rcvr type when looking for crate version collision
When looking for multiple versions of the same crate, do not blindly construct the receiver type.

Follow up to #128786. Fix #129205.
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs14
-rw-r--r--tests/ui/methods/missing-method-on-type-parameter.rs6
-rw-r--r--tests/ui/methods/missing-method-on-type-parameter.stderr19
3 files changed, 33 insertions, 6 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index ffd46ea13b9..8b8bb29dacd 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3498,7 +3498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 err,
                                 pick.item.def_id,
                                 rcvr.hir_id,
-                                *rcvr_ty,
+                                Some(*rcvr_ty),
                             );
                         if pick.autoderefs == 0 && !trait_in_other_version_found {
                             err.span_label(
@@ -3689,8 +3689,7 @@ 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 hir::QPath::Resolved(..) = path
             && let Some(assoc) = self
                 .tcx
                 .associated_items(valid_out_of_scope_traits[0])
@@ -3700,7 +3699,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // 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();
+
+            let rcvr_ty = self.node_ty_opt(ty.hir_id);
             trait_in_other_version_found = self.detect_and_explain_multiple_crate_versions(
                 err,
                 assoc.def_id,
@@ -4080,7 +4080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err: &mut Diag<'_>,
         item_def_id: DefId,
         hir_id: hir::HirId,
-        rcvr_ty: Ty<'_>,
+        rcvr_ty: Option<Ty<'_>>,
     ) -> bool {
         let hir_id = self.tcx.parent_hir_id(hir_id);
         let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false };
@@ -4110,8 +4110,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut multi_span: MultiSpan = trait_span.into();
         multi_span.push_span_label(trait_span, format!("this is the trait that is needed"));
         let descr = self.tcx.associated_item(item_def_id).descr();
+        let rcvr_ty =
+            rcvr_ty.map(|t| format!("`{t}`")).unwrap_or_else(|| "the receiver".to_string());
         multi_span
-            .push_span_label(item_span, format!("the {descr} is available for `{rcvr_ty}` here"));
+            .push_span_label(item_span, format!("the {descr} is available for {rcvr_ty} here"));
         for (def_id, import_def_id) in candidates {
             if let Some(import_def_id) = import_def_id {
                 multi_span.push_span_label(
diff --git a/tests/ui/methods/missing-method-on-type-parameter.rs b/tests/ui/methods/missing-method-on-type-parameter.rs
new file mode 100644
index 00000000000..cbcbeea4d4c
--- /dev/null
+++ b/tests/ui/methods/missing-method-on-type-parameter.rs
@@ -0,0 +1,6 @@
+// Regression test for https://github.com/rust-lang/rust/issues/129205
+fn x<T: Copy>() {
+    T::try_from(); //~ ERROR E0599
+}
+
+fn main() {}
diff --git a/tests/ui/methods/missing-method-on-type-parameter.stderr b/tests/ui/methods/missing-method-on-type-parameter.stderr
new file mode 100644
index 00000000000..c53d7afe4e2
--- /dev/null
+++ b/tests/ui/methods/missing-method-on-type-parameter.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no function or associated item named `try_from` found for type parameter `T` in the current scope
+  --> $DIR/missing-method-on-type-parameter.rs:3:8
+   |
+LL | fn x<T: Copy>() {
+   |      - function or associated item `try_from` not found for this type parameter
+LL |     T::try_from();
+   |        ^^^^^^^^ function or associated item not found in `T`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: there is an associated function `from` with a similar name
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+help: trait `TryFrom` which provides `try_from` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use std::convert::TryFrom;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.