@@ -96,7 +96,7 @@ use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
96
96
use rustc:: ty:: { self , ToPolyTraitRef , Ty , TyCtxt , Visibility } ;
97
97
use rustc:: ty:: { MethodCall , MethodCallee } ;
98
98
use rustc:: ty:: adjustment;
99
- use rustc:: ty:: fold:: TypeFoldable ;
99
+ use rustc:: ty:: fold:: { BottomUpFolder , TypeFoldable } ;
100
100
use rustc:: ty:: util:: { Representability , IntTypeExt } ;
101
101
use require_c_abi_if_variadic;
102
102
use rscope:: { ElisionFailureInfo , RegionScope } ;
@@ -172,6 +172,12 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
172
172
deferred_call_resolutions : RefCell < DefIdMap < Vec < DeferredCallResolutionHandler < ' gcx , ' tcx > > > > ,
173
173
174
174
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 > > > ,
175
181
}
176
182
177
183
impl < ' a , ' gcx , ' tcx > Deref for Inherited < ' a , ' gcx , ' tcx > {
@@ -408,6 +414,7 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
408
414
locals : RefCell :: new ( NodeMap ( ) ) ,
409
415
deferred_call_resolutions : RefCell :: new ( DefIdMap ( ) ) ,
410
416
deferred_cast_checks : RefCell :: new ( Vec :: new ( ) ) ,
417
+ anon_types : RefCell :: new ( DefIdMap ( ) ) ,
411
418
} )
412
419
} )
413
420
}
@@ -631,32 +638,29 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
631
638
body : & ' gcx hir:: Block )
632
639
-> FnCtxt < ' a , ' gcx , ' tcx >
633
640
{
634
- let arg_tys = & fn_sig. inputs ;
635
- let ret_ty = fn_sig. output ;
641
+ let mut fn_sig = fn_sig. clone ( ) ;
636
642
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) ;
641
644
642
645
// Create the function context. This is either derived from scratch or,
643
646
// 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 ) ;
645
648
* fcx. ps . borrow_mut ( ) = UnsafetyState :: function ( unsafety, unsafety_id) ;
646
649
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 ;
654
658
655
659
{
656
660
let mut visit = GatherLocalsVisitor { fcx : & fcx, } ;
657
661
658
662
// 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 ) {
660
664
// The type of the argument must be well-formed.
661
665
//
662
666
// 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>,
672
676
} ) ;
673
677
674
678
// 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) ;
676
681
}
677
682
678
683
visit. visit_block ( body) ;
679
684
}
680
685
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 {
682
689
ty:: FnConverging ( result_type) => ExpectHasType ( result_type) ,
683
690
ty:: FnDiverging => NoExpectation
684
691
} ) ;
685
692
686
- for ( input, arg) in decl. inputs . iter ( ) . zip ( arg_tys) {
687
- fcx. write_ty ( input. id , arg) ;
688
- }
689
-
690
693
fcx
691
694
}
692
695
@@ -1623,6 +1626,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
1623
1626
}
1624
1627
}
1625
1628
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
+ }
1626
1664
1627
1665
fn normalize_associated_types_in < T > ( & self , span : Span , value : & T ) -> T
1628
1666
where T : TypeFoldable < ' tcx >
0 commit comments