@@ -96,7 +96,7 @@ use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
9696use rustc:: ty:: { self , ToPolyTraitRef , Ty , TyCtxt , Visibility } ;
9797use rustc:: ty:: { MethodCall , MethodCallee } ;
9898use rustc:: ty:: adjustment;
99- use rustc:: ty:: fold:: TypeFoldable ;
99+ use rustc:: ty:: fold:: { BottomUpFolder , TypeFoldable } ;
100100use rustc:: ty:: util:: { Representability , IntTypeExt } ;
101101use require_c_abi_if_variadic;
102102use rscope:: { ElisionFailureInfo , RegionScope } ;
@@ -172,6 +172,12 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
172172 deferred_call_resolutions : RefCell < DefIdMap < Vec < DeferredCallResolutionHandler < ' gcx , ' tcx > > > > ,
173173
174174 deferred_cast_checks : RefCell < Vec < cast:: CastCheck < ' tcx > > > ,
175+
176+ // Anonymized types found in explicit return types and their
177+ // associated fresh inference variable. Writeback resolves these
178+ // variables to get the concrete type, which can be used to
179+ // deanonymize TyAnon, after typeck is done with all functions.
180+ anon_types : RefCell < DefIdMap < Ty < ' tcx > > > ,
175181}
176182
177183impl < ' a , ' gcx , ' tcx > Deref for Inherited < ' a , ' gcx , ' tcx > {
@@ -408,6 +414,7 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
408414 locals : RefCell :: new ( NodeMap ( ) ) ,
409415 deferred_call_resolutions : RefCell :: new ( DefIdMap ( ) ) ,
410416 deferred_cast_checks : RefCell :: new ( Vec :: new ( ) ) ,
417+ anon_types : RefCell :: new ( DefIdMap ( ) ) ,
411418 } )
412419 } )
413420 }
@@ -631,32 +638,29 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
631638 body : & ' gcx hir:: Block )
632639 -> FnCtxt < ' a , ' gcx , ' tcx >
633640{
634- let arg_tys = & fn_sig. inputs ;
635- let ret_ty = fn_sig. output ;
641+ let mut fn_sig = fn_sig. clone ( ) ;
636642
637- debug ! ( "check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})" ,
638- arg_tys,
639- ret_ty,
640- fn_id) ;
643+ debug ! ( "check_fn(sig={:?}, fn_id={})" , fn_sig, fn_id) ;
641644
642645 // Create the function context. This is either derived from scratch or,
643646 // in the case of function expressions, based on the outer context.
644- let fcx = FnCtxt :: new ( inherited, ret_ty , body. id ) ;
647+ let mut fcx = FnCtxt :: new ( inherited, fn_sig . output , body. id ) ;
645648 * fcx. ps . borrow_mut ( ) = UnsafetyState :: function ( unsafety, unsafety_id) ;
646649
647- if let ty:: FnConverging ( ret_ty) = ret_ty {
648- fcx. require_type_is_sized ( ret_ty, decl. output . span ( ) , traits:: ReturnType ) ;
649- }
650-
651- debug ! ( "fn-sig-map: fn_id={} fn_sig={:?}" , fn_id, fn_sig) ;
652-
653- inherited. tables . borrow_mut ( ) . liberated_fn_sigs . insert ( fn_id, fn_sig. clone ( ) ) ;
650+ fn_sig. output = match fcx. ret_ty {
651+ ty:: FnConverging ( orig_ret_ty) => {
652+ fcx. require_type_is_sized ( orig_ret_ty, decl. output . span ( ) , traits:: ReturnType ) ;
653+ ty:: FnConverging ( fcx. instantiate_anon_types ( & orig_ret_ty) )
654+ }
655+ ty:: FnDiverging => ty:: FnDiverging
656+ } ;
657+ fcx. ret_ty = fn_sig. output ;
654658
655659 {
656660 let mut visit = GatherLocalsVisitor { fcx : & fcx, } ;
657661
658662 // Add formal parameters.
659- for ( arg_ty, input) in arg_tys . iter ( ) . zip ( & decl. inputs ) {
663+ for ( arg_ty, input) in fn_sig . inputs . iter ( ) . zip ( & decl. inputs ) {
660664 // The type of the argument must be well-formed.
661665 //
662666 // NB -- this is now checked in wfcheck, but that
@@ -672,21 +676,20 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
672676 } ) ;
673677
674678 // Check the pattern.
675- fcx. check_pat ( & input. pat , * arg_ty) ;
679+ fcx. check_pat ( & input. pat , arg_ty) ;
680+ fcx. write_ty ( input. id , arg_ty) ;
676681 }
677682
678683 visit. visit_block ( body) ;
679684 }
680685
681- fcx. check_block_with_expected ( body, match ret_ty {
686+ inherited. tables . borrow_mut ( ) . liberated_fn_sigs . insert ( fn_id, fn_sig) ;
687+
688+ fcx. check_block_with_expected ( body, match fcx. ret_ty {
682689 ty:: FnConverging ( result_type) => ExpectHasType ( result_type) ,
683690 ty:: FnDiverging => NoExpectation
684691 } ) ;
685692
686- for ( input, arg) in decl. inputs . iter ( ) . zip ( arg_tys) {
687- fcx. write_ty ( input. id , arg) ;
688- }
689-
690693 fcx
691694}
692695
@@ -1623,6 +1626,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
16231626 }
16241627 }
16251628
1629+ /// Replace all anonymized types with fresh inference variables
1630+ /// and record them for writeback.
1631+ fn instantiate_anon_types < T : TypeFoldable < ' tcx > > ( & self , value : & T ) -> T {
1632+ value. fold_with ( & mut BottomUpFolder { tcx : self . tcx , fldop : |ty| {
1633+ if let ty:: TyAnon ( def_id, substs) = ty. sty {
1634+ // Use the same type variable if the exact same TyAnon appears more
1635+ // than once in the return type (e.g. if it's pased to a type alias).
1636+ if let Some ( ty_var) = self . anon_types . borrow ( ) . get ( & def_id) {
1637+ return ty_var;
1638+ }
1639+ let ty_var = self . next_ty_var ( ) ;
1640+ self . anon_types . borrow_mut ( ) . insert ( def_id, ty_var) ;
1641+
1642+ let item_predicates = self . tcx . lookup_predicates ( def_id) ;
1643+ let bounds = item_predicates. instantiate ( self . tcx , substs) ;
1644+
1645+ let span = self . tcx . map . def_id_span ( def_id, codemap:: DUMMY_SP ) ;
1646+ for predicate in bounds. predicates {
1647+ // Change the predicate to refer to the type variable,
1648+ // which will be the concrete type, instead of the TyAnon.
1649+ // This also instantiates nested `impl Trait`.
1650+ let predicate = self . instantiate_anon_types ( & predicate) ;
1651+
1652+ // Require that the predicate holds for the concrete type.
1653+ let cause = traits:: ObligationCause :: new ( span, self . body_id ,
1654+ traits:: ReturnType ) ;
1655+ self . register_predicate ( traits:: Obligation :: new ( cause, predicate) ) ;
1656+ }
1657+
1658+ ty_var
1659+ } else {
1660+ ty
1661+ }
1662+ } } )
1663+ }
16261664
16271665 fn normalize_associated_types_in < T > ( & self , span : Span , value : & T ) -> T
16281666 where T : TypeFoldable < ' tcx >
0 commit comments