@@ -10,12 +10,10 @@ use rustc_hir::lang_items::LangItem;
1010use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1111use rustc_infer:: infer:: LateBoundRegionConversionTime ;
1212use rustc_infer:: infer:: { InferOk , InferResult } ;
13- use rustc_infer:: traits:: ObligationCauseCode ;
1413use rustc_middle:: ty:: fold:: TypeFoldable ;
1514use rustc_middle:: ty:: subst:: InternalSubsts ;
1615use rustc_middle:: ty:: { self , Ty } ;
1716use rustc_span:: source_map:: Span ;
18- use rustc_span:: DUMMY_SP ;
1917use rustc_target:: spec:: abi:: Abi ;
2018use rustc_trait_selection:: traits:: error_reporting:: ArgKind ;
2119use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt as _;
@@ -429,14 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
429427 // in this binder we are creating.
430428 assert ! ( !expected_sig. sig. skip_binder( ) . has_vars_bound_above( ty:: INNERMOST ) ) ;
431429 let bound_sig = expected_sig. sig . map_bound ( |sig| {
432- let output = self . hide_parent_opaque_types (
433- sig. output ( ) ,
434- expected_sig. cause_span . unwrap_or ( DUMMY_SP ) ,
435- body. id ( ) . hir_id ,
436- ) ;
437430 self . tcx . mk_fn_sig (
438431 sig. inputs ( ) . iter ( ) . cloned ( ) ,
439- output,
432+ sig . output ( ) ,
440433 sig. c_variadic ,
441434 hir:: Unsafety :: Normal ,
442435 Abi :: RustCall ,
@@ -608,23 +601,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
608601 // function.
609602 Some ( hir:: GeneratorKind :: Async ( hir:: AsyncGeneratorKind :: Fn ) ) => {
610603 debug ! ( "closure is async fn body" ) ;
611- self . deduce_future_output_from_obligations ( expr_def_id) . unwrap_or_else ( || {
612- // AFAIK, deducing the future output
613- // always succeeds *except* in error cases
614- // like #65159. I'd like to return Error
615- // here, but I can't because I can't
616- // easily (and locally) prove that we
617- // *have* reported an
618- // error. --nikomatsakis
619- astconv. ty_infer ( None , decl. output . span ( ) )
620- } )
604+ self . deduce_future_output_from_obligations ( expr_def_id, body. id ( ) . hir_id )
605+ . unwrap_or_else ( || {
606+ // AFAIK, deducing the future output
607+ // always succeeds *except* in error cases
608+ // like #65159. I'd like to return Error
609+ // here, but I can't because I can't
610+ // easily (and locally) prove that we
611+ // *have* reported an
612+ // error. --nikomatsakis
613+ astconv. ty_infer ( None , decl. output . span ( ) )
614+ } )
621615 }
622616
623617 _ => astconv. ty_infer ( None , decl. output . span ( ) ) ,
624618 } ,
625619 } ;
626- let supplied_return =
627- self . hide_parent_opaque_types ( supplied_return, decl. output . span ( ) , body. id ( ) . hir_id ) ;
628620
629621 let result = ty:: Binder :: bind_with_vars (
630622 self . tcx . mk_fn_sig (
@@ -645,67 +637,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
645637 result
646638 }
647639
648- fn hide_parent_opaque_types ( & self , ty : Ty < ' tcx > , span : Span , body_id : hir:: HirId ) -> Ty < ' tcx > {
649- let InferOk { value, obligations } = self . replace_opaque_types_with_inference_vars (
650- ty,
651- body_id,
652- span,
653- ObligationCauseCode :: MiscObligation ,
654- self . param_env ,
655- ) ;
656- self . register_predicates ( obligations) ;
657- value
658- }
659-
660640 /// Invoked when we are translating the generator that results
661641 /// from desugaring an `async fn`. Returns the "sugared" return
662642 /// type of the `async fn` -- that is, the return type that the
663643 /// user specified. The "desugared" return type is an `impl
664644 /// Future<Output = T>`, so we do this by searching through the
665645 /// obligations to extract the `T`.
666646 #[ instrument( skip( self ) , level = "debug" ) ]
667- fn deduce_future_output_from_obligations ( & self , expr_def_id : DefId ) -> Option < Ty < ' tcx > > {
647+ fn deduce_future_output_from_obligations (
648+ & self ,
649+ expr_def_id : DefId ,
650+ body_id : hir:: HirId ,
651+ ) -> Option < Ty < ' tcx > > {
668652 let ret_coercion = self . ret_coercion . as_ref ( ) . unwrap_or_else ( || {
669653 span_bug ! ( self . tcx. def_span( expr_def_id) , "async fn generator outside of a fn" )
670654 } ) ;
671655
672656 let ret_ty = ret_coercion. borrow ( ) . expected_ty ( ) ;
673657 let ret_ty = self . inh . infcx . shallow_resolve ( ret_ty) ;
674- let ( def_id, substs) = match * ret_ty. kind ( ) {
675- ty:: Opaque ( def_id, substs) => ( def_id, substs) ,
658+
659+ let get_future_output = |predicate : ty:: Predicate < ' tcx > , span| {
660+ // Search for a pending obligation like
661+ //
662+ // `<R as Future>::Output = T`
663+ //
664+ // where R is the return type we are expecting. This type `T`
665+ // will be our output.
666+ let bound_predicate = predicate. kind ( ) ;
667+ if let ty:: PredicateKind :: Projection ( proj_predicate) = bound_predicate. skip_binder ( ) {
668+ self . deduce_future_output_from_projection (
669+ span,
670+ bound_predicate. rebind ( proj_predicate) ,
671+ )
672+ } else {
673+ None
674+ }
675+ } ;
676+
677+ let output_ty = match * ret_ty. kind ( ) {
678+ ty:: Infer ( ty:: TyVar ( ret_vid) ) => {
679+ self . obligations_for_self_ty ( ret_vid) . find_map ( |( _, obligation) | {
680+ get_future_output ( obligation. predicate , obligation. cause . span )
681+ } ) ?
682+ }
683+ ty:: Opaque ( def_id, substs) => self
684+ . tcx
685+ . bound_explicit_item_bounds ( def_id)
686+ . transpose_iter ( )
687+ . map ( |e| e. map_bound ( |e| * e) . transpose_tuple2 ( ) )
688+ . find_map ( |( p, s) | get_future_output ( p. subst ( self . tcx , substs) , s. 0 ) ) ?,
676689 ty:: Error ( _) => return None ,
677690 _ => span_bug ! (
678691 self . tcx. def_span( expr_def_id) ,
679692 "async fn generator return type not an inference variable"
680693 ) ,
681694 } ;
682695
683- let item_bounds = self . tcx . bound_explicit_item_bounds ( def_id) ;
684-
685- // Search for a pending obligation like
686- //
687- // `<R as Future>::Output = T`
688- //
689- // where R is the return type we are expecting. This type `T`
690- // will be our output.
691- let output_ty = item_bounds
692- . transpose_iter ( )
693- . map ( |e| e. map_bound ( |e| * e) . transpose_tuple2 ( ) )
694- . find_map ( |( predicate, span) | {
695- let bound_predicate = predicate. subst ( self . tcx , substs) . kind ( ) ;
696- if let ty:: PredicateKind :: Projection ( proj_predicate) = bound_predicate. skip_binder ( )
697- {
698- self . deduce_future_output_from_projection (
699- span. 0 ,
700- bound_predicate. rebind ( proj_predicate) ,
701- )
702- } else {
703- None
704- }
705- } ) ;
696+ // async fn that have opaque types in their return type need to redo the conversion to inference variables
697+ // as they fetch the still opaque version from the signature.
698+ let InferOk { value : output_ty, obligations } = self
699+ . replace_opaque_types_with_inference_vars (
700+ output_ty,
701+ body_id,
702+ self . tcx . def_span ( expr_def_id) ,
703+ self . param_env ,
704+ ) ;
705+ self . register_predicates ( obligations) ;
706706
707707 debug ! ( "deduce_future_output_from_obligations: output_ty={:?}" , output_ty) ;
708- output_ty
708+ Some ( output_ty)
709709 }
710710
711711 /// Given a projection like
0 commit comments