about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2021-09-17 14:09:49 +0900
committerGitHub <noreply@github.com>2021-09-17 14:09:49 +0900
commitc97ff098f192901b81dc2ad7142195757853964d (patch)
tree16d5e079a59f18ddfe1bce4a0611c0e1c3d8832d /compiler
parent5d14396ed0b8efc06e3446bd3a6ed2c3e8eccd80 (diff)
parentcbd79836a5b7ef07e33213cb979294ad1b9faccc (diff)
downloadrust-c97ff098f192901b81dc2ad7142195757853964d.tar.gz
rust-c97ff098f192901b81dc2ad7142195757853964d.zip
Rollup merge of #88911 - FabianWolff:issue-88653, r=petrochenkov
Improve error message for type mismatch in generator arguments

Fixes #88653. The code example given there is invalid because the `Generator` trait (unlike the `Fn` traits) does not take the generator arguments in tupled-up form (because there can only be one argument, from my understanding). Hence, the type error in the example in #88653 is correct, because the given generator takes a `bool` argument, whereas the function's return type talks about a generator with a `(bool,)` argument.

The error message is both confusing and wrong, though: It is wrong because it displays the wrong "expected signature", and it is confusing because both the "expected" and "found" notes point at the same span. With my changes, I get the following, more helpful output:
```
error[E0631]: type mismatch in generator arguments
 --> test.rs:5:22
  |
5 | fn foo(bar: bool) -> impl Generator<(bool,)> {
  |                      ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _`
6 |     |bar| {
  |     ----- found signature of `fn(bool) -> _`
```
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs33
2 files changed, 24 insertions, 14 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 8c9acd3ba73..e435154d931 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -722,7 +722,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 };
 
                 let found_did = match *found_trait_ty.kind() {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Closure(did, _)
+                    | ty::Foreign(did)
+                    | ty::FnDef(did, _)
+                    | ty::Generator(did, ..) => Some(did),
                     ty::Adt(def, _) => Some(def.did),
                     _ => None,
                 };
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index f006bede409..ae61988928f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1256,33 +1256,40 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             trait_ref: ty::PolyTraitRef<'tcx>,
         ) -> String {
             let inputs = trait_ref.skip_binder().substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind() {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
-                    false,
-                    hir::Unsafety::Normal,
-                    abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
+            let sig = match inputs.kind() {
+                ty::Tuple(inputs)
+                    if tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() =>
+                {
+                    tcx.mk_fn_sig(
+                        inputs.iter().map(|k| k.expect_ty()),
+                        tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
+                        false,
+                        hir::Unsafety::Normal,
+                        abi::Abi::Rust,
+                    )
+                }
+                _ => tcx.mk_fn_sig(
                     std::iter::once(inputs),
                     tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
                     false,
                     hir::Unsafety::Normal,
                     abi::Abi::Rust,
-                )
+                ),
             };
             trait_ref.rebind(sig).to_string()
         }
 
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let argument_kind = match expected_ref.skip_binder().substs.type_at(0) {
+            t if t.is_closure() => "closure",
+            t if t.is_generator() => "generator",
+            _ => "function",
+        };
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
             E0631,
             "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
+            argument_kind
         );
 
         let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found));