Auto merge of #124227 - compiler-errors:hack-check-method-res, r=estebank
Make sure that the method resolution matches in `note_source_of_type_mismatch_constraint` `note_source_of_type_mismatch_constraint` is a pile of hacks that I implemented to cover up another pile of hacks. It does a bunch of re-confirming methods, but it wasn't previously checking that the methods it was looking (back) up were equal to the methods we previously had. This PR adds those checks. Fixes #118185
This commit is contained in:
commit
f0038a7c8f
4 changed files with 46 additions and 35 deletions
|
@ -373,8 +373,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
|
let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else {
|
||||||
return false;
|
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)?;
|
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.
|
// Fudge the receiver, so we can do new inference on it.
|
||||||
let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
|
let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
|
||||||
let method = self
|
let method = self
|
||||||
|
@ -386,6 +389,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
binding,
|
binding,
|
||||||
)
|
)
|
||||||
.ok()?;
|
.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
|
// Unify the method signature with our incompatible arg, to
|
||||||
// do inference in the *opposite* direction and to find out
|
// do inference in the *opposite* direction and to find out
|
||||||
// what our ideal rcvr ty would look like.
|
// what our ideal rcvr ty would look like.
|
||||||
|
@ -456,6 +465,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
) else {
|
) else {
|
||||||
continue;
|
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_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
|
||||||
let ideal_method = self
|
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
|
// blame arg, if possible. Don't do this if we're coming from
|
||||||
// arg mismatch code, because we'll possibly suggest a mutually
|
// arg mismatch code, because we'll possibly suggest a mutually
|
||||||
// incompatible fix at the original mismatch site.
|
// 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(_))
|
if matches!(source, TypeMismatchSource::Ty(_))
|
||||||
&& let Some(ideal_method) = ideal_method
|
&& let Some(ideal_method) = ideal_method
|
||||||
&& let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1])
|
&& Some(ideal_method.def_id)
|
||||||
// HACK(compiler-errors): We don't actually consider the implications
|
== self
|
||||||
// of our inference guesses in `emit_type_mismatch_suggestions`, so
|
.typeck_results
|
||||||
// only suggest things when we know our type error is precisely due to
|
.borrow()
|
||||||
// a type mismatch, and not via some projection or something. See #116155.
|
.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()
|
&& !ideal_arg_ty.has_non_region_infer()
|
||||||
{
|
{
|
||||||
self.emit_type_mismatch_suggestions(
|
self.emit_type_mismatch_suggestions(
|
||||||
|
|
|
@ -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!()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,8 @@
|
||||||
//@ known-bug: #118185
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let target: Target = create_target();
|
let target: Target = create_target();
|
||||||
target.get(0); // correct arguments work
|
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
|
// must be generic
|
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue