about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNilstrieb <48135649+Nilstrieb@users.noreply.github.com>2023-05-30 12:57:41 +0200
committerGitHub <noreply@github.com>2023-05-30 12:57:41 +0200
commitcc121828eed9636987493e77962b95cc187914de (patch)
tree0e32139706bb1874ba84e217de13cd0ee77cfa90
parentf4b20dac81ae2dfea100285dc6fc56928da4b700 (diff)
parente11ffb62dfda4850b971310b6f721141ba29f267 (diff)
downloadrust-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.rs46
-rw-r--r--tests/ui/typeck/issue-106929.rs13
-rw-r--r--tests/ui/typeck/issue-106929.stderr15
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`.