@@ -16,7 +16,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1616use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1717use rustc_middle:: ty:: { ProjectionPredicate , TypeSuperVisitable , TypeVisitor } ;
1818use rustc_middle:: ty:: { ToPredicate , TypeVisitable } ;
19- use rustc_span:: DUMMY_SP ;
19+ use rustc_span:: { sym , DUMMY_SP } ;
2020use std:: iter;
2121use std:: ops:: ControlFlow ;
2222
@@ -482,6 +482,73 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
482482 ecx. evaluate_all_and_make_canonical_response ( nested_goals)
483483 } )
484484 }
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+ }
485552}
486553
487554/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
0 commit comments