@@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
246246 }
247247
248248 /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
249- /// everything we need to know about a closure.
249+ /// everything we need to know about a closure or generator .
250250 ///
251251 /// The `cause_span` should be the span that caused us to
252252 /// have this expected signature, or `None` if we can't readily
@@ -262,37 +262,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
262262
263263 let trait_ref = projection. to_poly_trait_ref ( tcx) ;
264264
265- if tcx. lang_items ( ) . fn_trait_kind ( trait_ref. def_id ( ) ) . is_none ( ) {
265+ let is_fn = tcx. lang_items ( ) . fn_trait_kind ( trait_ref. def_id ( ) ) . is_some ( ) ;
266+ let gen_trait = tcx. lang_items ( ) . gen_trait ( ) . unwrap ( ) ;
267+ let is_gen = gen_trait == trait_ref. def_id ( ) ;
268+ if !is_fn && !is_gen {
269+ debug ! ( "deduce_sig_from_projection: not fn or generator" ) ;
266270 return None ;
267271 }
268272
269- let arg_param_ty = trait_ref. skip_binder ( ) . substs . type_at ( 1 ) ;
270- let arg_param_ty = self . resolve_type_vars_if_possible ( & arg_param_ty) ;
271- debug ! (
272- "deduce_sig_from_projection: arg_param_ty {:?}" ,
273- arg_param_ty
274- ) ;
273+ if is_gen {
274+ // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
275+ // associated item and not yield.
276+ let return_assoc_item = self . tcx . associated_items ( gen_trait) . nth ( 1 ) . unwrap ( ) . def_id ;
277+ if return_assoc_item != projection. projection_def_id ( ) {
278+ debug ! ( "deduce_sig_from_projection: not return assoc item of generator" ) ;
279+ return None ;
280+ }
281+ }
282+
283+ let input_tys = if is_fn {
284+ let arg_param_ty = trait_ref. skip_binder ( ) . substs . type_at ( 1 ) ;
285+ let arg_param_ty = self . resolve_type_vars_if_possible ( & arg_param_ty) ;
286+ debug ! ( "deduce_sig_from_projection: arg_param_ty={:?}" , arg_param_ty) ;
275287
276- let input_tys = match arg_param_ty. sty {
277- ty:: Tuple ( tys) => tys. into_iter ( ) . map ( |k| k. expect_ty ( ) ) ,
278- _ => return None ,
288+ match arg_param_ty. sty {
289+ ty:: Tuple ( tys) => tys. into_iter ( ) . map ( |k| k. expect_ty ( ) ) . collect :: < Vec < _ > > ( ) ,
290+ _ => return None ,
291+ }
292+ } else {
293+ // Generators cannot have explicit arguments.
294+ vec ! [ ]
279295 } ;
280296
281297 let ret_param_ty = projection. skip_binder ( ) . ty ;
282298 let ret_param_ty = self . resolve_type_vars_if_possible ( & ret_param_ty) ;
283- debug ! (
284- "deduce_sig_from_projection: ret_param_ty {:?}" ,
285- ret_param_ty
286- ) ;
299+ debug ! ( "deduce_sig_from_projection: ret_param_ty={:?}" , ret_param_ty) ;
287300
288301 let sig = self . tcx . mk_fn_sig (
289- input_tys,
290- ret_param_ty,
302+ input_tys. iter ( ) ,
303+ & ret_param_ty,
291304 false ,
292305 hir:: Unsafety :: Normal ,
293306 Abi :: Rust ,
294307 ) ;
295- debug ! ( "deduce_sig_from_projection: sig {:?}" , sig) ;
308+ debug ! ( "deduce_sig_from_projection: sig= {:?}" , sig) ;
296309
297310 Some ( ExpectedSig { cause_span, sig } )
298311 }
0 commit comments