@@ -10,12 +10,10 @@ use rustc_hir::lang_items::LangItem;
10
10
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
11
11
use rustc_infer:: infer:: LateBoundRegionConversionTime ;
12
12
use rustc_infer:: infer:: { InferOk , InferResult } ;
13
- use rustc_infer:: traits:: ObligationCauseCode ;
14
13
use rustc_middle:: ty:: fold:: TypeFoldable ;
15
14
use rustc_middle:: ty:: subst:: InternalSubsts ;
16
15
use rustc_middle:: ty:: { self , Ty } ;
17
16
use rustc_span:: source_map:: Span ;
18
- use rustc_span:: DUMMY_SP ;
19
17
use rustc_target:: spec:: abi:: Abi ;
20
18
use rustc_trait_selection:: traits:: error_reporting:: ArgKind ;
21
19
use rustc_trait_selection:: traits:: error_reporting:: InferCtxtExt as _;
@@ -429,14 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
429
427
// in this binder we are creating.
430
428
assert ! ( !expected_sig. sig. skip_binder( ) . has_vars_bound_above( ty:: INNERMOST ) ) ;
431
429
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
- ) ;
437
430
self . tcx . mk_fn_sig (
438
431
sig. inputs ( ) . iter ( ) . cloned ( ) ,
439
- output,
432
+ sig . output ( ) ,
440
433
sig. c_variadic ,
441
434
hir:: Unsafety :: Normal ,
442
435
Abi :: RustCall ,
@@ -608,23 +601,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
608
601
// function.
609
602
Some ( hir:: GeneratorKind :: Async ( hir:: AsyncGeneratorKind :: Fn ) ) => {
610
603
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
+ } )
621
615
}
622
616
623
617
_ => astconv. ty_infer ( None , decl. output . span ( ) ) ,
624
618
} ,
625
619
} ;
626
- let supplied_return =
627
- self . hide_parent_opaque_types ( supplied_return, decl. output . span ( ) , body. id ( ) . hir_id ) ;
628
620
629
621
let result = ty:: Binder :: bind_with_vars (
630
622
self . tcx . mk_fn_sig (
@@ -645,67 +637,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
645
637
result
646
638
}
647
639
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
-
660
640
/// Invoked when we are translating the generator that results
661
641
/// from desugaring an `async fn`. Returns the "sugared" return
662
642
/// type of the `async fn` -- that is, the return type that the
663
643
/// user specified. The "desugared" return type is an `impl
664
644
/// Future<Output = T>`, so we do this by searching through the
665
645
/// obligations to extract the `T`.
666
646
#[ 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 > > {
668
652
let ret_coercion = self . ret_coercion . as_ref ( ) . unwrap_or_else ( || {
669
653
span_bug ! ( self . tcx. def_span( expr_def_id) , "async fn generator outside of a fn" )
670
654
} ) ;
671
655
672
656
let ret_ty = ret_coercion. borrow ( ) . expected_ty ( ) ;
673
657
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 ) ) ?,
676
689
ty:: Error ( _) => return None ,
677
690
_ => span_bug ! (
678
691
self . tcx. def_span( expr_def_id) ,
679
692
"async fn generator return type not an inference variable"
680
693
) ,
681
694
} ;
682
695
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) ;
706
706
707
707
debug ! ( "deduce_future_output_from_obligations: output_ty={:?}" , output_ty) ;
708
- output_ty
708
+ Some ( output_ty)
709
709
}
710
710
711
711
/// Given a projection like
0 commit comments