diff options
| author | Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> | 2023-05-30 12:57:41 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-30 12:57:41 +0200 |
| commit | cc121828eed9636987493e77962b95cc187914de (patch) | |
| tree | 0e32139706bb1874ba84e217de13cd0ee77cfa90 | |
| parent | f4b20dac81ae2dfea100285dc6fc56928da4b700 (diff) | |
| parent | e11ffb62dfda4850b971310b6f721141ba29f267 (diff) | |
| download | rust-cc121828eed9636987493e77962b95cc187914de.tar.gz rust-cc121828eed9636987493e77962b95cc187914de.zip | |
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.
| -rw-r--r-- | compiler/rustc_hir_typeck/src/callee.rs | 46 | ||||
| -rw-r--r-- | tests/ui/typeck/issue-106929.rs | 13 | ||||
| -rw-r--r-- | tests/ui/typeck/issue-106929.stderr | 15 |
3 files changed, 42 insertions, 32 deletions
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 655ab94eb48..4389ad6ef26 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -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); @@ -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 @@ -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( @@ -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); @@ -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( diff --git a/tests/ui/typeck/issue-106929.rs b/tests/ui/typeck/issue-106929.rs new file mode 100644 index 00000000000..91342229ae1 --- /dev/null +++ b/tests/ui/typeck/issue-106929.rs @@ -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() {} diff --git a/tests/ui/typeck/issue-106929.stderr b/tests/ui/typeck/issue-106929.stderr new file mode 100644 index 00000000000..f744e5a41f0 --- /dev/null +++ b/tests/ui/typeck/issue-106929.stderr @@ -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`. |
