Skip to content

Commit

Permalink
Don't typecheck suggested method call
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jieyouxu committed May 30, 2023
1 parent 45eec0f commit e11ffb6
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 32 deletions.
46 changes: 14 additions & 32 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,20 +420,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
{
// Try suggesting `foo(a)` -> `a.foo()` if possible.
if let Some(ty) =
self.suggest_call_as_method(
&mut diag,
segment,
arg_exprs,
call_expr,
expected
)
{
diag.emit();
return ty;
} else {
diag.emit();
}
self.suggest_call_as_method(
&mut diag,
segment,
arg_exprs,
call_expr,
expected
);
diag.emit();
}

let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
Expand Down Expand Up @@ -496,9 +490,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
call_expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>,
) -> Option<Ty<'tcx>> {
) {
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
// any strange errors. If it's successful, then we'll do a true
Expand All @@ -513,7 +509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ProbeScope::AllTraits,
expected.only_has_type(self),
) else {
return None;
return;
};

let pick = self.confirm_method(
Expand All @@ -525,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segment,
);
if pick.illegal_sized_bound.is_some() {
return None;
return;
}

let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
Expand Down Expand Up @@ -567,22 +563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg,
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(
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/typeck/issue-106929.rs
Original file line number Diff line number Diff line change
@@ -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() {}
15 changes: 15 additions & 0 deletions tests/ui/typeck/issue-106929.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit e11ffb6

Please sign in to comment.