@@ -11,7 +11,7 @@ use std::ops::ControlFlow;
11
11
use hir:: LangItem ;
12
12
use hir:: def_id:: DefId ;
13
13
use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
14
- use rustc_hir as hir;
14
+ use rustc_hir:: { self as hir, CoroutineDesugaring , CoroutineKind } ;
15
15
use rustc_infer:: traits:: { Obligation , PolyTraitObligation , SelectionError } ;
16
16
use rustc_middle:: ty:: fast_reject:: DeepRejectCtxt ;
17
17
use rustc_middle:: ty:: { self , Ty , TypeVisitableExt , TypingMode } ;
@@ -125,11 +125,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
125
125
self . assemble_async_iterator_candidates ( obligation, & mut candidates) ;
126
126
} else if tcx. is_lang_item ( def_id, LangItem :: AsyncFnKindHelper ) {
127
127
self . assemble_async_fn_kind_helper_candidates ( obligation, & mut candidates) ;
128
+ } else if tcx. is_lang_item ( def_id, LangItem :: AsyncFn )
129
+ || tcx. is_lang_item ( def_id, LangItem :: AsyncFnOnce )
130
+ || tcx. is_lang_item ( def_id, LangItem :: AsyncFnMut )
131
+ {
132
+ self . assemble_async_closure_candidates ( obligation, & mut candidates) ;
128
133
}
129
134
130
135
// FIXME: Put these into `else if` blocks above, since they're built-in.
131
136
self . assemble_closure_candidates ( obligation, & mut candidates) ;
132
- self . assemble_async_closure_candidates ( obligation, & mut candidates) ;
133
137
self . assemble_fn_pointer_candidates ( obligation, & mut candidates) ;
134
138
135
139
self . assemble_candidates_from_impls ( obligation, & mut candidates) ;
@@ -425,6 +429,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
425
429
}
426
430
}
427
431
432
+ #[ instrument( level = "debug" , skip( self , candidates) ) ]
428
433
fn assemble_async_closure_candidates (
429
434
& mut self ,
430
435
obligation : & PolyTraitObligation < ' tcx > ,
@@ -436,15 +441,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
436
441
return ;
437
442
} ;
438
443
444
+ debug ! ( "self_ty = {:?}" , obligation. self_ty( ) . skip_binder( ) . kind( ) ) ;
439
445
match * obligation. self_ty ( ) . skip_binder ( ) . kind ( ) {
440
- ty:: CoroutineClosure ( _ , args) => {
446
+ ty:: CoroutineClosure ( def_id , args) => {
441
447
if let Some ( closure_kind) =
442
448
args. as_coroutine_closure ( ) . kind_ty ( ) . to_opt_closure_kind ( )
443
449
&& !closure_kind. extends ( goal_kind)
444
450
{
445
451
return ;
446
452
}
447
- candidates. vec . push ( AsyncClosureCandidate ) ;
453
+
454
+ // Make sure this is actually an async closure.
455
+ let Some ( coroutine_kind) =
456
+ self . tcx ( ) . coroutine_kind ( self . tcx ( ) . coroutine_for_closure ( def_id) )
457
+ else {
458
+ bug ! ( "coroutine with no kind" ) ;
459
+ } ;
460
+
461
+ debug ! ( ?coroutine_kind) ;
462
+ match coroutine_kind {
463
+ CoroutineKind :: Desugared ( CoroutineDesugaring :: Async , _) => {
464
+ candidates. vec . push ( AsyncClosureCandidate ) ;
465
+ }
466
+ _ => ( ) ,
467
+ }
448
468
}
449
469
// Closures and fn pointers implement `AsyncFn*` if their return types
450
470
// implement `Future`, which is checked later.
0 commit comments