Skip to content

Commit

Permalink
Rollup merge of #88911 - FabianWolff:issue-88653, r=petrochenkov
Browse files Browse the repository at this point in the history
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) -> _`
```
  • Loading branch information
JohnTitor authored Sep 17, 2021
2 parents 5d14396 + cbd7983 commit c97ff09
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
19 changes: 19 additions & 0 deletions src/test/ui/generator/issue-88653.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Regression test for #88653, where a confusing warning about a
// type mismatch in generator arguments was issued.

#![feature(generators, generator_trait)]

use std::ops::Generator;

fn foo(bar: bool) -> impl Generator<(bool,)> {
//~^ ERROR: type mismatch in generator arguments [E0631]
//~| NOTE: expected signature of `fn((bool,)) -> _`
|bar| {
//~^ NOTE: found signature of `fn(bool) -> _`
if bar {
yield bar;
}
}
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/generator/issue-88653.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0631]: type mismatch in generator arguments
--> $DIR/issue-88653.rs:8:22
|
LL | fn foo(bar: bool) -> impl Generator<(bool,)> {
| ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _`
...
LL | |bar| {
| ----- found signature of `fn(bool) -> _`

error: aborting due to previous error

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

0 comments on commit c97ff09

Please sign in to comment.