@@ -15,7 +15,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1515use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1616use rustc_middle:: ty:: { ProjectionPredicate , TypeSuperVisitable , TypeVisitor } ;
1717use rustc_middle:: ty:: { ToPredicate , TypeVisitable } ;
18- use rustc_span:: DUMMY_SP ;
18+ use rustc_span:: { sym , DUMMY_SP } ;
1919use std:: iter;
2020use std:: ops:: ControlFlow ;
2121
@@ -391,6 +391,73 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
391391 ) -> QueryResult < ' tcx > {
392392 bug ! ( "`Tuple` does not have an associated type: {:?}" , goal) ;
393393 }
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+ }
394461}
395462
396463/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
0 commit comments