@@ -19,6 +19,7 @@ pub use self::TypeOrigin::*;
19
19
pub use self :: ValuePairs :: * ;
20
20
pub use self :: fixup_err:: * ;
21
21
pub use middle:: ty:: IntVarValue ;
22
+ use middle:: ty:: ClosureTyper ;
22
23
pub use self :: freshen:: TypeFreshener ;
23
24
pub use self :: region_inference:: GenericKind ;
24
25
@@ -29,7 +30,8 @@ use middle::region::CodeExtent;
29
30
use middle:: subst;
30
31
use middle:: subst:: Substs ;
31
32
use middle:: subst:: Subst ;
32
- use middle:: traits;
33
+ use middle:: traits:: { self , FulfillmentContext , Normalized , MiscObligation ,
34
+ SelectionContext , ObligationCause } ;
33
35
use middle:: ty:: { TyVid , IntVid , FloatVid , RegionVid , UnconstrainedNumeric } ;
34
36
use middle:: ty:: { self , Ty , HasTypeFlags } ;
35
37
use middle:: ty_fold:: { self , TypeFolder , TypeFoldable } ;
@@ -39,7 +41,7 @@ use std::cell::{RefCell, Ref};
39
41
use std:: fmt;
40
42
use syntax:: ast;
41
43
use syntax:: codemap;
42
- use syntax:: codemap:: Span ;
44
+ use syntax:: codemap:: { Span , DUMMY_SP } ;
43
45
use util:: nodemap:: { FnvHashMap , NodeMap } ;
44
46
45
47
use self :: combine:: CombineFields ;
@@ -354,6 +356,14 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
354
356
}
355
357
}
356
358
359
+ pub fn normalizing_infer_ctxt < ' a , ' tcx > ( tcx : & ' a ty:: ctxt < ' tcx > ,
360
+ tables : & ' a RefCell < ty:: Tables < ' tcx > > )
361
+ -> InferCtxt < ' a , ' tcx > {
362
+ let mut infcx = new_infer_ctxt ( tcx, tables, None , false ) ;
363
+ infcx. normalize = true ;
364
+ infcx
365
+ }
366
+
357
367
/// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and
358
368
/// returns ty::err.
359
369
pub fn common_supertype < ' a , ' tcx > ( cx : & InferCtxt < ' a , ' tcx > ,
@@ -557,7 +567,8 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
557
567
// the substitutions in `substs` are already monomorphized,
558
568
// but we still must normalize associated types
559
569
// normalize_associated_type(self.param_env.tcx, &closure_ty)
560
- panic ! ( "see issue 26597: fufillment context refactor must occur" )
570
+ normalize_associated_type ( & self . tcx , & closure_ty)
571
+ // panic!("see issue 26597: fufillment context refactor must occur")
561
572
} else {
562
573
closure_ty
563
574
}
@@ -579,13 +590,158 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for InferCtxt<'a, 'tcx> {
579
590
// the substitutions in `substs` are already monomorphized,
580
591
// but we still must normalize associated types
581
592
// monomorphize::normalize_associated_type(self.param_env.tcx, &result)
582
- panic ! ( "see issue 26597: fufillment context refactor must occur" )
593
+ // panic!("see issue 26597: fufillment context refactor must occur")
594
+ normalize_associated_type ( & self . tcx , & result)
583
595
} else {
584
596
result
585
597
}
586
598
}
587
599
}
588
600
601
+ pub fn normalize_associated_type < ' tcx , T > ( tcx : & ty:: ctxt < ' tcx > , value : & T ) -> T
602
+ where T : TypeFoldable < ' tcx > + HasTypeFlags
603
+ {
604
+ debug ! ( "normalize_associated_type(t={:?})" , value) ;
605
+
606
+ let value = erase_regions ( tcx, value) ;
607
+
608
+ if !value. has_projection_types ( ) {
609
+ return value;
610
+ }
611
+
612
+ let infcx = new_infer_ctxt ( tcx, & tcx. tables , None , true ) ;
613
+ let mut selcx = traits:: SelectionContext :: new ( & infcx, & infcx) ;
614
+ let cause = traits:: ObligationCause :: dummy ( ) ;
615
+ let traits:: Normalized { value : result, obligations } =
616
+ traits:: normalize ( & mut selcx, cause, & value) ;
617
+
618
+ debug ! ( "normalize_associated_type: result={:?} obligations={:?}" ,
619
+ result,
620
+ obligations) ;
621
+
622
+ let mut fulfill_cx = infcx. fulfillment_cx . borrow_mut ( ) ;
623
+
624
+ for obligation in obligations {
625
+ fulfill_cx. register_predicate_obligation ( & infcx, obligation) ;
626
+ }
627
+
628
+ let result = drain_fulfillment_cx_or_panic ( DUMMY_SP , & infcx, & mut fulfill_cx, & result) ;
629
+
630
+ result
631
+ }
632
+
633
+ pub fn drain_fulfillment_cx_or_panic < ' a , ' tcx , T > ( span : Span ,
634
+ infcx : & InferCtxt < ' a , ' tcx > ,
635
+ fulfill_cx : & mut traits:: FulfillmentContext < ' tcx > ,
636
+ result : & T )
637
+ -> T
638
+ where T : TypeFoldable < ' tcx >
639
+ {
640
+ match drain_fulfillment_cx ( infcx, fulfill_cx, result) {
641
+ Ok ( v) => v,
642
+ Err ( errors) => {
643
+ infcx. tcx . sess . span_bug (
644
+ span,
645
+ & format ! ( "Encountered errors `{:?}` fulfilling during trans" ,
646
+ errors) ) ;
647
+ }
648
+ }
649
+ }
650
+
651
+ /// Finishes processes any obligations that remain in the fulfillment
652
+ /// context, and then "freshens" and returns `result`. This is
653
+ /// primarily used during normalization and other cases where
654
+ /// processing the obligations in `fulfill_cx` may cause type
655
+ /// inference variables that appear in `result` to be unified, and
656
+ /// hence we need to process those obligations to get the complete
657
+ /// picture of the type.
658
+ pub fn drain_fulfillment_cx < ' a , ' tcx , T > ( infcx : & InferCtxt < ' a , ' tcx > ,
659
+ fulfill_cx : & mut traits:: FulfillmentContext < ' tcx > ,
660
+ result : & T )
661
+ -> Result < T , Vec < traits:: FulfillmentError < ' tcx > > >
662
+ where T : TypeFoldable < ' tcx >
663
+ {
664
+ debug ! ( "drain_fulfillment_cx(result={:?})" ,
665
+ result) ;
666
+ // this is stupid but temporary
667
+ let typer: & ClosureTyper < ' tcx > = infcx;
668
+ // In principle, we only need to do this so long as `result`
669
+ // contains unbound type parameters. It could be a slight
670
+ // optimization to stop iterating early.
671
+ match fulfill_cx. select_all_or_error ( infcx, typer) {
672
+ Ok ( ( ) ) => { }
673
+ Err ( errors) => {
674
+ return Err ( errors) ;
675
+ }
676
+ }
677
+
678
+ // Use freshen to simultaneously replace all type variables with
679
+ // their bindings and replace all regions with 'static. This is
680
+ // sort of overkill because we do not expect there to be any
681
+ // unbound type variables, hence no `TyFresh` types should ever be
682
+ // inserted.
683
+ Ok ( result. fold_with ( & mut infcx. freshener ( ) ) )
684
+ }
685
+
686
+ /// Returns an equivalent value with all free regions removed (note
687
+ /// that late-bound regions remain, because they are important for
688
+ /// subtyping, but they are anonymized and normalized as well). This
689
+ /// is a stronger, caching version of `ty_fold::erase_regions`.
690
+ pub fn erase_regions < ' tcx , T > ( cx : & ty:: ctxt < ' tcx > , value : & T ) -> T
691
+ where T : TypeFoldable < ' tcx >
692
+ {
693
+ let value1 = value. fold_with ( & mut RegionEraser ( cx) ) ;
694
+ debug ! ( "erase_regions({:?}) = {:?}" ,
695
+ value, value1) ;
696
+ return value1;
697
+
698
+ struct RegionEraser < ' a , ' tcx : ' a > ( & ' a ty:: ctxt < ' tcx > ) ;
699
+
700
+ impl < ' a , ' tcx > TypeFolder < ' tcx > for RegionEraser < ' a , ' tcx > {
701
+ fn tcx ( & self ) -> & ty:: ctxt < ' tcx > { self . 0 }
702
+
703
+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
704
+ match self . tcx ( ) . normalized_cache . borrow ( ) . get ( & ty) . cloned ( ) {
705
+ None => { }
706
+ Some ( u) => return u
707
+ }
708
+
709
+ let t_norm = ty_fold:: super_fold_ty ( self , ty) ;
710
+ self . tcx ( ) . normalized_cache . borrow_mut ( ) . insert ( ty, t_norm) ;
711
+ return t_norm;
712
+ }
713
+
714
+ fn fold_binder < T > ( & mut self , t : & ty:: Binder < T > ) -> ty:: Binder < T >
715
+ where T : TypeFoldable < ' tcx >
716
+ {
717
+ let u = self . tcx ( ) . anonymize_late_bound_regions ( t) ;
718
+ ty_fold:: super_fold_binder ( self , & u)
719
+ }
720
+
721
+ fn fold_region ( & mut self , r : ty:: Region ) -> ty:: Region {
722
+ // because late-bound regions affect subtyping, we can't
723
+ // erase the bound/free distinction, but we can replace
724
+ // all free regions with 'static.
725
+ //
726
+ // Note that we *CAN* replace early-bound regions -- the
727
+ // type system never "sees" those, they get substituted
728
+ // away. In trans, they will always be erased to 'static
729
+ // whenever a substitution occurs.
730
+ match r {
731
+ ty:: ReLateBound ( ..) => r,
732
+ _ => ty:: ReStatic
733
+ }
734
+ }
735
+
736
+ fn fold_substs ( & mut self ,
737
+ substs : & subst:: Substs < ' tcx > )
738
+ -> subst:: Substs < ' tcx > {
739
+ subst:: Substs { regions : subst:: ErasedRegions ,
740
+ types : substs. types . fold_with ( self ) }
741
+ }
742
+ }
743
+ }
744
+
589
745
impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
590
746
pub fn freshen < T : TypeFoldable < ' tcx > > ( & self , t : T ) -> T {
591
747
t. fold_with ( & mut self . freshener ( ) )
0 commit comments