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) -> _` ```
This commit is contained in:
commit
c97ff098f1
4 changed files with 55 additions and 14 deletions
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue