@@ -56,18 +56,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
56
56
// It's always helpful for inference if we know the kind of
57
57
// closure sooner rather than later, so first examine the expected
58
58
// type, and see if can glean a closure kind from there.
59
- let ( expected_sig, expected_kind) = match closure. kind {
60
- hir:: ClosureKind :: Closure => match expected. to_option ( self ) {
61
- Some ( ty) => {
62
- self . deduce_closure_signature ( self . try_structurally_resolve_type ( expr_span, ty) )
63
- }
64
- None => ( None , None ) ,
65
- } ,
66
- // We don't want to deduce a signature from `Fn` bounds for coroutines
67
- // or coroutine-closures, because the former does not implement `Fn`
68
- // ever, and the latter's signature doesn't correspond to the coroutine
69
- // type that it returns.
70
- hir:: ClosureKind :: Coroutine ( _) | hir:: ClosureKind :: CoroutineClosure ( _) => ( None , None ) ,
59
+ let ( expected_sig, expected_kind) = match expected. to_option ( self ) {
60
+ Some ( ty) => self . deduce_closure_signature (
61
+ self . try_structurally_resolve_type ( expr_span, ty) ,
62
+ closure. kind ,
63
+ ) ,
64
+ None => ( None , None ) ,
71
65
} ;
72
66
73
67
let ClosureSignatures { bound_sig, mut liberated_sig } =
@@ -323,11 +317,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
323
317
fn deduce_closure_signature (
324
318
& self ,
325
319
expected_ty : Ty < ' tcx > ,
320
+ closure_kind : hir:: ClosureKind ,
326
321
) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
327
322
match * expected_ty. kind ( ) {
328
323
ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, args, .. } ) => self
329
324
. deduce_closure_signature_from_predicates (
330
325
expected_ty,
326
+ closure_kind,
331
327
self . tcx
332
328
. explicit_item_bounds ( def_id)
333
329
. iter_instantiated_copied ( self . tcx , args)
@@ -336,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
336
332
ty:: Dynamic ( object_type, ..) => {
337
333
let sig = object_type. projection_bounds ( ) . find_map ( |pb| {
338
334
let pb = pb. with_self_ty ( self . tcx , self . tcx . types . trait_object_dummy_self ) ;
339
- self . deduce_sig_from_projection ( None , pb)
335
+ self . deduce_sig_from_projection ( None , closure_kind , pb)
340
336
} ) ;
341
337
let kind = object_type
342
338
. principal_def_id ( )
@@ -345,19 +341,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
345
341
}
346
342
ty:: Infer ( ty:: TyVar ( vid) ) => self . deduce_closure_signature_from_predicates (
347
343
Ty :: new_var ( self . tcx , self . root_var ( vid) ) ,
344
+ closure_kind,
348
345
self . obligations_for_self_ty ( vid) . map ( |obl| ( obl. predicate , obl. cause . span ) ) ,
349
346
) ,
350
- ty:: FnPtr ( sig) => {
351
- let expected_sig = ExpectedSig { cause_span : None , sig } ;
352
- ( Some ( expected_sig) , Some ( ty:: ClosureKind :: Fn ) )
353
- }
347
+ ty:: FnPtr ( sig) => match closure_kind {
348
+ hir:: ClosureKind :: Closure => {
349
+ let expected_sig = ExpectedSig { cause_span : None , sig } ;
350
+ ( Some ( expected_sig) , Some ( ty:: ClosureKind :: Fn ) )
351
+ }
352
+ hir:: ClosureKind :: Coroutine ( _) | hir:: ClosureKind :: CoroutineClosure ( _) => {
353
+ ( None , None )
354
+ }
355
+ } ,
354
356
_ => ( None , None ) ,
355
357
}
356
358
}
357
359
358
360
fn deduce_closure_signature_from_predicates (
359
361
& self ,
360
362
expected_ty : Ty < ' tcx > ,
363
+ closure_kind : hir:: ClosureKind ,
361
364
predicates : impl DoubleEndedIterator < Item = ( ty:: Predicate < ' tcx > , Span ) > ,
362
365
) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
363
366
let mut expected_sig = None ;
@@ -386,6 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
386
389
span,
387
390
self . deduce_sig_from_projection (
388
391
Some ( span) ,
392
+ closure_kind,
389
393
bound_predicate. rebind ( proj_predicate) ,
390
394
) ,
391
395
) ;
@@ -422,13 +426,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
422
426
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( data) ) => Some ( data. def_id ( ) ) ,
423
427
_ => None ,
424
428
} ;
425
- if let Some ( closure_kind) =
426
- trait_def_id. and_then ( |def_id| self . tcx . fn_trait_kind_from_def_id ( def_id) )
427
- {
428
- expected_kind = Some (
429
- expected_kind
430
- . map_or_else ( || closure_kind, |current| cmp:: min ( current, closure_kind) ) ,
431
- ) ;
429
+
430
+ if let Some ( trait_def_id) = trait_def_id {
431
+ let found_kind = match closure_kind {
432
+ hir:: ClosureKind :: Closure => self . tcx . fn_trait_kind_from_def_id ( trait_def_id) ,
433
+ hir:: ClosureKind :: CoroutineClosure ( hir:: CoroutineDesugaring :: Async ) => {
434
+ self . tcx . async_fn_trait_kind_from_def_id ( trait_def_id)
435
+ }
436
+ _ => None ,
437
+ } ;
438
+
439
+ if let Some ( found_kind) = found_kind {
440
+ expected_kind = Some (
441
+ expected_kind
442
+ . map_or_else ( || found_kind, |current| cmp:: min ( current, found_kind) ) ,
443
+ ) ;
444
+ }
432
445
}
433
446
}
434
447
@@ -445,14 +458,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
445
458
fn deduce_sig_from_projection (
446
459
& self ,
447
460
cause_span : Option < Span > ,
461
+ closure_kind : hir:: ClosureKind ,
448
462
projection : ty:: PolyProjectionPredicate < ' tcx > ,
449
463
) -> Option < ExpectedSig < ' tcx > > {
450
464
let tcx = self . tcx ;
451
465
452
466
let trait_def_id = projection. trait_def_id ( tcx) ;
453
- // For now, we only do signature deduction based off of the `Fn` traits.
454
- if !tcx. is_fn_trait ( trait_def_id) {
455
- return None ;
467
+
468
+ // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
469
+ // for closures and async closures, respectively.
470
+ match closure_kind {
471
+ hir:: ClosureKind :: Closure
472
+ if self . tcx . fn_trait_kind_from_def_id ( trait_def_id) . is_some ( ) => { }
473
+ hir:: ClosureKind :: CoroutineClosure ( hir:: CoroutineDesugaring :: Async )
474
+ if self . tcx . async_fn_trait_kind_from_def_id ( trait_def_id) . is_some ( ) => { }
475
+ _ => return None ,
456
476
}
457
477
458
478
let arg_param_ty = projection. skip_binder ( ) . projection_ty . args . type_at ( 1 ) ;
0 commit comments