@@ -246,7 +246,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
246
246
}
247
247
248
248
/// 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 .
250
250
///
251
251
/// The `cause_span` should be the span that caused us to
252
252
/// have this expected signature, or `None` if we can't readily
@@ -262,37 +262,50 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
262
262
263
263
let trait_ref = projection. to_poly_trait_ref ( tcx) ;
264
264
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" ) ;
266
270
return None ;
267
271
}
268
272
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) ;
275
287
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 ! [ ]
279
295
} ;
280
296
281
297
let ret_param_ty = projection. skip_binder ( ) . ty ;
282
298
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) ;
287
300
288
301
let sig = self . tcx . mk_fn_sig (
289
- input_tys,
290
- ret_param_ty,
302
+ input_tys. iter ( ) ,
303
+ & ret_param_ty,
291
304
false ,
292
305
hir:: Unsafety :: Normal ,
293
306
Abi :: Rust ,
294
307
) ;
295
- debug ! ( "deduce_sig_from_projection: sig {:?}" , sig) ;
308
+ debug ! ( "deduce_sig_from_projection: sig= {:?}" , sig) ;
296
309
297
310
Some ( ExpectedSig { cause_span, sig } )
298
311
}
0 commit comments