Trust signature over return expr for generators.
This commit extends the logic used to determine what the expected signature of a closure is so that it can also determine the expected signature of a generator. This improves a diagnostic where the fn signature was blamed instead of the generator body. It doesn't fix fix the diagnostic for `async fn`.
This commit is contained in:
parent
a416a19153
commit
f2919a31c8
5 changed files with 53 additions and 53 deletions
|
|
@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
|
||||
/// everything we need to know about a closure.
|
||||
/// everything we need to know about a closure or generator.
|
||||
///
|
||||
/// The `cause_span` should be the span that caused us to
|
||||
/// have this expected signature, or `None` if we can't readily
|
||||
|
|
@ -262,37 +262,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
let trait_ref = projection.to_poly_trait_ref(tcx);
|
||||
|
||||
if tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_none() {
|
||||
let is_fn = tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_some();
|
||||
let gen_trait = tcx.lang_items().gen_trait().unwrap();
|
||||
let is_gen = gen_trait == trait_ref.def_id();
|
||||
if !is_fn && !is_gen {
|
||||
debug!("deduce_sig_from_projection: not fn or generator");
|
||||
return None;
|
||||
}
|
||||
|
||||
let arg_param_ty = trait_ref.skip_binder().substs.type_at(1);
|
||||
let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
|
||||
debug!(
|
||||
"deduce_sig_from_projection: arg_param_ty {:?}",
|
||||
arg_param_ty
|
||||
);
|
||||
if is_gen {
|
||||
// Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
|
||||
// associated item and not yield.
|
||||
let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id;
|
||||
if return_assoc_item != projection.projection_def_id() {
|
||||
debug!("deduce_sig_from_projection: not return assoc item of generator");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let input_tys = match arg_param_ty.sty {
|
||||
ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()),
|
||||
_ => return None,
|
||||
let input_tys = if is_fn {
|
||||
let arg_param_ty = trait_ref.skip_binder().substs.type_at(1);
|
||||
let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
|
||||
debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty);
|
||||
|
||||
match arg_param_ty.sty {
|
||||
ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::<Vec<_>>(),
|
||||
_ => return None,
|
||||
}
|
||||
} else {
|
||||
// Generators cannot have explicit arguments.
|
||||
vec![]
|
||||
};
|
||||
|
||||
let ret_param_ty = projection.skip_binder().ty;
|
||||
let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
|
||||
debug!(
|
||||
"deduce_sig_from_projection: ret_param_ty {:?}",
|
||||
ret_param_ty
|
||||
);
|
||||
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
|
||||
|
||||
let sig = self.tcx.mk_fn_sig(
|
||||
input_tys,
|
||||
ret_param_ty,
|
||||
input_tys.iter(),
|
||||
&ret_param_ty,
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
Abi::Rust,
|
||||
);
|
||||
debug!("deduce_sig_from_projection: sig {:?}", sig);
|
||||
debug!("deduce_sig_from_projection: sig={:?}", sig);
|
||||
|
||||
Some(ExpectedSig { cause_span, sig })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub fn want_cyclic_generator_return<T>(_: T)
|
|||
|
||||
fn supply_cyclic_generator_return() {
|
||||
want_cyclic_generator_return(|| {
|
||||
//~^ ERROR type mismatch
|
||||
//~^ ERROR closure/generator type that references itself
|
||||
if false { yield None.unwrap(); }
|
||||
None.unwrap()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _] as std::ops::Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 19:6 _]`
|
||||
--> $DIR/generator-yielding-or-returning-itself.rs:15:5
|
||||
error[E0644]: closure/generator type that references itself
|
||||
--> $DIR/generator-yielding-or-returning-itself.rs:15:34
|
||||
|
|
||||
LL | want_cyclic_generator_return(|| {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
|
||||
LL | want_cyclic_generator_return(|| {
|
||||
| __________________________________^
|
||||
LL | |
|
||||
LL | | if false { yield None.unwrap(); }
|
||||
LL | | None.unwrap()
|
||||
LL | | })
|
||||
| |_____^ cyclic type of infinite size
|
||||
|
|
||||
= note: closures cannot capture themselves or take themselves as argument;
|
||||
this error may be the result of a recent compiler bug-fix,
|
||||
see https://github.com/rust-lang/rust/issues/46062 for more details
|
||||
note: required by `want_cyclic_generator_return`
|
||||
--> $DIR/generator-yielding-or-returning-itself.rs:9:1
|
||||
|
|
||||
LL | / pub fn want_cyclic_generator_return<T>(_: T)
|
||||
LL | | where T: Generator<Yield = (), Return = T>
|
||||
LL | | {
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _] as std::ops::Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 32:6 _]`
|
||||
--> $DIR/generator-yielding-or-returning-itself.rs:28:5
|
||||
|
|
@ -36,4 +33,5 @@ LL | | }
|
|||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
Some errors have detailed explanations: E0271, E0644.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
use std::ops::Generator;
|
||||
|
||||
fn foo() -> impl Generator<Return = i32> { //~ ERROR type mismatch
|
||||
fn foo() -> impl Generator<Return = i32> {
|
||||
|| {
|
||||
if false {
|
||||
return Ok(6);
|
||||
return Ok(6); //~ ERROR mismatched types [E0308]
|
||||
}
|
||||
|
||||
yield ();
|
||||
|
||||
5 //~ ERROR mismatched types [E0308]
|
||||
5
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,12 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/type-mismatch-signature-deduction.rs:13:9
|
||||
--> $DIR/type-mismatch-signature-deduction.rs:8:20
|
||||
|
|
||||
LL | 5
|
||||
| ^ expected enum `std::result::Result`, found integer
|
||||
LL | return Ok(6);
|
||||
| ^^^^^ expected i32, found enum `std::result::Result`
|
||||
|
|
||||
= note: expected type `std::result::Result<{integer}, _>`
|
||||
found type `{integer}`
|
||||
= note: expected type `i32`
|
||||
found type `std::result::Result<{integer}, _>`
|
||||
|
||||
error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:6:5: 14:6 _] as std::ops::Generator>::Return == i32`
|
||||
--> $DIR/type-mismatch-signature-deduction.rs:5:13
|
||||
|
|
||||
LL | fn foo() -> impl Generator<Return = i32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found i32
|
||||
|
|
||||
= note: expected type `std::result::Result<{integer}, _>`
|
||||
found type `i32`
|
||||
= note: the return type of a function must have a statically known size
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0308.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue