about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs33
-rw-r--r--tests/crashes/118185.rs26
-rw-r--r--tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs (renamed from tests/crashes/118185-2.rs)5
-rw-r--r--tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr17
4 files changed, 46 insertions, 35 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 6da5adc7a6e..7916366ef08 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -373,8 +373,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
                     return false;
                 };
-                let possible_rcvr_ty = expr_finder.uses.iter().find_map(|binding| {
+                let possible_rcvr_ty = expr_finder.uses.iter().rev().find_map(|binding| {
                     let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?;
+                    if possible_rcvr_ty.is_ty_var() {
+                        return None;
+                    }
                     // Fudge the receiver, so we can do new inference on it.
                     let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
                     let method = self
@@ -386,6 +389,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             binding,
                         )
                         .ok()?;
+                    // Make sure we select the same method that we started with...
+                    if Some(method.def_id)
+                        != self.typeck_results.borrow().type_dependent_def_id(call_expr.hir_id)
+                    {
+                        return None;
+                    }
                     // Unify the method signature with our incompatible arg, to
                     // do inference in the *opposite* direction and to find out
                     // what our ideal rcvr ty would look like.
@@ -456,6 +465,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ) else {
                     continue;
                 };
+                // Make sure we select the same method that we started with...
+                if Some(method.def_id)
+                    != self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id)
+                {
+                    continue;
+                }
 
                 let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
                 let ideal_method = self
@@ -505,13 +520,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // blame arg, if possible. Don't do this if we're coming from
                     // arg mismatch code, because we'll possibly suggest a mutually
                     // incompatible fix at the original mismatch site.
+                    // HACK(compiler-errors): We don't actually consider the implications
+                    // of our inference guesses in `emit_type_mismatch_suggestions`, so
+                    // only suggest things when we know our type error is precisely due to
+                    // a type mismatch, and not via some projection or something. See #116155.
                     if matches!(source, TypeMismatchSource::Ty(_))
                         && let Some(ideal_method) = ideal_method
-                        && let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1])
-                        // HACK(compiler-errors): We don't actually consider the implications
-                        // of our inference guesses in `emit_type_mismatch_suggestions`, so
-                        // only suggest things when we know our type error is precisely due to
-                        // a type mismatch, and not via some projection or something. See #116155.
+                        && Some(ideal_method.def_id)
+                            == self
+                                .typeck_results
+                                .borrow()
+                                .type_dependent_def_id(parent_expr.hir_id)
+                        && let ideal_arg_ty =
+                            self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1])
                         && !ideal_arg_ty.has_non_region_infer()
                     {
                         self.emit_type_mismatch_suggestions(
diff --git a/tests/crashes/118185.rs b/tests/crashes/118185.rs
deleted file mode 100644
index c3a29c3a3f5..00000000000
--- a/tests/crashes/118185.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-//@ known-bug: #118185
-
-fn main() {
-    let target: Target = create_target();
-    target.get(0); // correct arguments work
-    target.get(10.0); // CRASH HERE
-}
-
-// must be generic
-fn create_target<T>() -> T {
-    unimplemented!()
-}
-
-// unimplemented trait, but contains function with the same name
-pub trait RandomTrait {
-    fn get(&mut self); // but less arguments
-}
-
-struct Target;
-
-impl Target {
-    // correct function with arguments
-    pub fn get(&self, data: i32) {
-        unimplemented!()
-    }
-}
diff --git a/tests/crashes/118185-2.rs b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs
index c3a29c3a3f5..fd41beecb0a 100644
--- a/tests/crashes/118185-2.rs
+++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs
@@ -1,9 +1,8 @@
-//@ known-bug: #118185
-
 fn main() {
     let target: Target = create_target();
     target.get(0); // correct arguments work
-    target.get(10.0); // CRASH HERE
+    target.get(10.0); // (used to crash here)
+    //~^ ERROR mismatched types
 }
 
 // must be generic
diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr
new file mode 100644
index 00000000000..0f86916fcda
--- /dev/null
+++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:4:16
+   |
+LL |     target.get(10.0); // (used to crash here)
+   |            --- ^^^^ expected `i32`, found floating-point number
+   |            |
+   |            arguments to this method are incorrect
+   |
+note: method defined here
+  --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:22:12
+   |
+LL |     pub fn get(&self, data: i32) {
+   |            ^^^        ---------
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.