@@ -16,7 +16,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
16
16
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
17
17
use rustc_middle:: ty:: { ProjectionPredicate , TypeSuperVisitable , TypeVisitor } ;
18
18
use rustc_middle:: ty:: { ToPredicate , TypeVisitable } ;
19
- use rustc_span:: DUMMY_SP ;
19
+ use rustc_span:: { sym , DUMMY_SP } ;
20
20
use std:: iter;
21
21
use std:: ops:: ControlFlow ;
22
22
@@ -482,6 +482,73 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
482
482
ecx. evaluate_all_and_make_canonical_response ( nested_goals)
483
483
} )
484
484
}
485
+
486
+ fn consider_builtin_future_candidate (
487
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
488
+ goal : Goal < ' tcx , Self > ,
489
+ ) -> QueryResult < ' tcx > {
490
+ let self_ty = goal. predicate . self_ty ( ) ;
491
+ let ty:: Generator ( def_id, substs, _) = * self_ty. kind ( ) else {
492
+ return Err ( NoSolution ) ;
493
+ } ;
494
+
495
+ // Generators are not futures unless they come from `async` desugaring
496
+ let tcx = ecx. tcx ( ) ;
497
+ if !tcx. generator_is_async ( def_id) {
498
+ return Err ( NoSolution ) ;
499
+ }
500
+
501
+ let term = substs. as_generator ( ) . return_ty ( ) . into ( ) ;
502
+
503
+ Self :: consider_assumption (
504
+ ecx,
505
+ goal,
506
+ ty:: Binder :: dummy ( ty:: ProjectionPredicate {
507
+ projection_ty : ecx. tcx ( ) . mk_alias_ty ( goal. predicate . def_id ( ) , [ self_ty] ) ,
508
+ term,
509
+ } )
510
+ . to_predicate ( tcx) ,
511
+ )
512
+ }
513
+
514
+ fn consider_builtin_generator_candidate (
515
+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
516
+ goal : Goal < ' tcx , Self > ,
517
+ ) -> QueryResult < ' tcx > {
518
+ let self_ty = goal. predicate . self_ty ( ) ;
519
+ let ty:: Generator ( def_id, substs, _) = * self_ty. kind ( ) else {
520
+ return Err ( NoSolution ) ;
521
+ } ;
522
+
523
+ // `async`-desugared generators do not implement the generator trait
524
+ let tcx = ecx. tcx ( ) ;
525
+ if tcx. generator_is_async ( def_id) {
526
+ return Err ( NoSolution ) ;
527
+ }
528
+
529
+ let generator = substs. as_generator ( ) ;
530
+
531
+ let name = tcx. associated_item ( goal. predicate . def_id ( ) ) . name ;
532
+ let term = if name == sym:: Return {
533
+ generator. return_ty ( ) . into ( )
534
+ } else if name == sym:: Yield {
535
+ generator. yield_ty ( ) . into ( )
536
+ } else {
537
+ bug ! ( "unexpected associated item `<{self_ty} as Generator>::{name}`" )
538
+ } ;
539
+
540
+ Self :: consider_assumption (
541
+ ecx,
542
+ goal,
543
+ ty:: Binder :: dummy ( ty:: ProjectionPredicate {
544
+ projection_ty : ecx
545
+ . tcx ( )
546
+ . mk_alias_ty ( goal. predicate . def_id ( ) , [ self_ty, generator. resume_ty ( ) ] ) ,
547
+ term,
548
+ } )
549
+ . to_predicate ( tcx) ,
550
+ )
551
+ }
485
552
}
486
553
487
554
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
0 commit comments