Don't typecheck suggested method call

Only make the use-dot-operator-to-call-method suggestion, but do not
double down and use the recovered type to perform method call
typechecking as it will produce confusing diagnostics on the "fixed"
code.
This commit is contained in:
许杰友 Jieyou Xu (Joe) 2023-05-30 17:57:37 +08:00
parent 45eec0fe93
commit e11ffb62df
No known key found for this signature in database
GPG Key ID: C5FD5D32014FDB47
3 changed files with 42 additions and 32 deletions

View File

@ -420,20 +420,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod) .steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
{ {
// Try suggesting `foo(a)` -> `a.foo()` if possible. // Try suggesting `foo(a)` -> `a.foo()` if possible.
if let Some(ty) = self.suggest_call_as_method(
self.suggest_call_as_method( &mut diag,
&mut diag, segment,
segment, arg_exprs,
arg_exprs, call_expr,
call_expr, expected
expected );
) diag.emit();
{
diag.emit();
return ty;
} else {
diag.emit();
}
} }
let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs); let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
@ -496,9 +490,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>], arg_exprs: &'tcx [hir::Expr<'tcx>],
call_expr: &'tcx hir::Expr<'tcx>, call_expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
) -> Option<Ty<'tcx>> { ) {
if let [callee_expr, rest @ ..] = arg_exprs { if let [callee_expr, rest @ ..] = arg_exprs {
let callee_ty = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)?; let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr) else {
return;
};
// First, do a probe with `IsSuggestion(true)` to avoid emitting // First, do a probe with `IsSuggestion(true)` to avoid emitting
// any strange errors. If it's successful, then we'll do a true // any strange errors. If it's successful, then we'll do a true
@ -513,7 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ProbeScope::AllTraits, ProbeScope::AllTraits,
expected.only_has_type(self), expected.only_has_type(self),
) else { ) else {
return None; return;
}; };
let pick = self.confirm_method( let pick = self.confirm_method(
@ -525,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segment, segment,
); );
if pick.illegal_sized_bound.is_some() { if pick.illegal_sized_bound.is_some() {
return None; return;
} }
let up_to_rcvr_span = segment.ident.span.until(callee_expr.span); let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
@ -567,22 +563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg, sugg,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
// Let's check the method fully now
let return_ty = self.check_method_argument_types(
segment.ident.span,
call_expr,
Ok(pick.callee),
rest,
TupleArgumentsFlag::DontTupleArguments,
expected,
);
return Some(return_ty);
} }
} }
None
} }
fn report_invalid_callee( fn report_invalid_callee(

View File

@ -0,0 +1,13 @@
struct Client;
impl Client {
fn post<T: std::ops::Add>(&self, _: T, _: T) {}
}
fn f() {
let c = Client;
post(c, ());
//~^ ERROR cannot find function `post` in this scope
}
fn main() {}

View File

@ -0,0 +1,15 @@
error[E0425]: cannot find function `post` in this scope
--> $DIR/issue-106929.rs:9:5
|
LL | post(c, ());
| ^^^^ not found in this scope
|
help: use the `.` operator to call the method `post` on `&Client`
|
LL - post(c, ());
LL + c.post(());
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.