@@ -15,7 +15,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
15
15
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
16
16
use rustc_middle:: ty:: { ProjectionPredicate , TypeSuperVisitable , TypeVisitor } ;
17
17
use rustc_middle:: ty:: { ToPredicate , TypeVisitable } ;
18
- use rustc_span:: DUMMY_SP ;
18
+ use rustc_span:: { sym , DUMMY_SP } ;
19
19
use std:: iter;
20
20
use std:: ops:: ControlFlow ;
21
21
@@ -391,6 +391,73 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
391
391
) -> QueryResult < ' tcx > {
392
392
bug ! ( "`Tuple` does not have an associated type: {:?}" , goal) ;
393
393
}
394
+
395
+ fn consider_builtin_future_candidate (
396
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
397
+ goal : Goal < ' tcx , Self > ,
398
+ ) -> QueryResult < ' tcx > {
399
+ let self_ty = goal. predicate . self_ty ( ) ;
400
+ let ty:: Generator ( def_id, substs, _) = * self_ty. kind ( ) else {
401
+ return Err ( NoSolution ) ;
402
+ } ;
403
+
404
+ // Generators are not futures unless they come from `async` desugaring
405
+ let tcx = ecx. tcx ( ) ;
406
+ if !tcx. generator_is_async ( def_id) {
407
+ return Err ( NoSolution ) ;
408
+ }
409
+
410
+ let term = substs. as_generator ( ) . return_ty ( ) . into ( ) ;
411
+
412
+ Self :: consider_assumption (
413
+ ecx,
414
+ goal,
415
+ ty:: Binder :: dummy ( ty:: ProjectionPredicate {
416
+ projection_ty : ecx. tcx ( ) . mk_alias_ty ( goal. predicate . def_id ( ) , [ self_ty] ) ,
417
+ term,
418
+ } )
419
+ . to_predicate ( tcx) ,
420
+ )
421
+ }
422
+
423
+ fn consider_builtin_generator_candidate (
424
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
425
+ goal : Goal < ' tcx , Self > ,
426
+ ) -> QueryResult < ' tcx > {
427
+ let self_ty = goal. predicate . self_ty ( ) ;
428
+ let ty:: Generator ( def_id, substs, _) = * self_ty. kind ( ) else {
429
+ return Err ( NoSolution ) ;
430
+ } ;
431
+
432
+ // `async`-desugared generators do not implement the generator trait
433
+ let tcx = ecx. tcx ( ) ;
434
+ if tcx. generator_is_async ( def_id) {
435
+ return Err ( NoSolution ) ;
436
+ }
437
+
438
+ let generator = substs. as_generator ( ) ;
439
+
440
+ let name = tcx. associated_item ( goal. predicate . def_id ( ) ) . name ;
441
+ let term = if name == sym:: Return {
442
+ generator. return_ty ( ) . into ( )
443
+ } else if name == sym:: Yield {
444
+ generator. yield_ty ( ) . into ( )
445
+ } else {
446
+ bug ! ( "unexpected associated item `<{self_ty} as Generator>::{name}`" )
447
+ } ;
448
+
449
+ Self :: consider_assumption (
450
+ ecx,
451
+ goal,
452
+ ty:: Binder :: dummy ( ty:: ProjectionPredicate {
453
+ projection_ty : ecx
454
+ . tcx ( )
455
+ . mk_alias_ty ( goal. predicate . def_id ( ) , [ self_ty, generator. resume_ty ( ) ] ) ,
456
+ term,
457
+ } )
458
+ . to_predicate ( tcx) ,
459
+ )
460
+ }
394
461
}
395
462
396
463
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
0 commit comments