Rollup merge of #112100 - jieyouxu:issue-106929, r=oli-obk

Don't typecheck recovered method call from suggestion

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 relevant for the *fixed* code.

### Code Sample

```rust
struct Client;

impl Client {
    fn post<T: std::ops::Add>(&self, _: T, _: T) {}
}

fn f() {
    let c = Client;
    post(c, ());
}
```

### Before This PR

```
error[[E0277]](https://doc.rust-lang.org/stable/error_codes/E0277.html): cannot add `()` to `()`
 --> src/lib.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^^^^^^^^ no implementation for `() + ()`
  |
  = help: the trait `Add` is not implemented for `()`
note: required by a bound in `Client::post`
 --> src/lib.rs:4:16
  |
4 |     fn post<T: std::ops::Add>(&self, _: T, _: T) {}
  |                ^^^^^^^^^^^^^ required by this bound in `Client::post`

error[[E0061]](https://doc.rust-lang.org/stable/error_codes/E0061.html): this function takes 2 arguments but 1 argument was supplied
 --> src/lib.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^ an argument of type `()` is missing
  |
note: method defined here
 --> src/lib.rs:4:8
  |
4 |     fn post<T: std::ops::Add>(&self, _: T, _: T) {}
  |        ^^^^                   -----  ----  ----
help: provide the argument
  |
9 |     post((), ())(c, ());
  |         ++++++++

error[[E0425]](https://doc.rust-lang.org/stable/error_codes/E0425.html): cannot find function `post` in this scope
 --> src/lib.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^ not found in this scope
  |
help: use the `.` operator to call the method `post` on `&Client`
  |
9 -     post(c, ());
9 +     c.post(());
  |

Some errors have detailed explanations: E0061, E0277, E0425.
For more information about an error, try `rustc --explain E0061`.
```

### After This PR

```
error[E0425]: cannot find function `post` in this scope
 --> tests/ui/typeck/issue-106929.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^ not found in this scope
  |
help: use the `.` operator to call the method `post` on `&Client`
  |
9 -     post(c, ());
9 +     c.post(());
  |

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
```

Fixes #106929.
This commit is contained in:
Nilstrieb 2023-05-30 12:57:41 +02:00 committed by GitHub
commit cc121828ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 32 deletions

View file

@ -420,20 +420,14 @@ fn confirm_builtin_call(
.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 @@ fn suggest_call_as_method(
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 @@ fn suggest_call_as_method(
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 @@ fn suggest_call_as_method(
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 @@ fn suggest_call_as_method(
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`.