From 483f13ce913b7ceaeae9173d21cd3dc343f6dbc1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 21 Apr 2024 10:41:04 -0400 Subject: [PATCH] Make sure that the method resolution matches in note_source_of_type_mismatch_constraint --- compiler/rustc_hir_typeck/src/demand.rs | 33 +++++++++++++++---- tests/crashes/118185.rs | 26 --------------- ...hod-lookup-returns-sig-with-fewer-args.rs} | 5 ++- ...-lookup-returns-sig-with-fewer-args.stderr | 17 ++++++++++ 4 files changed, 46 insertions(+), 35 deletions(-) delete mode 100644 tests/crashes/118185.rs rename tests/{crashes/118185-2.rs => ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs} (85%) create mode 100644 tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d6d22a43fe0..ed81ed64036 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -377,8 +377,11 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'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 @@ -390,6 +393,12 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'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. @@ -460,6 +469,12 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'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 @@ -509,13 +524,19 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'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 { - 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 similarity index 85% rename from tests/crashes/118185-2.rs rename to 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`.