1- use crate :: infer:: type_variable:: TypeVariableMap ;
2- use crate :: ty:: { self , Ty , TyCtxt } ;
1+ use crate :: ty:: { self , Ty , TyCtxt , TyVid , IntVid , FloatVid , RegionVid } ;
32use crate :: ty:: fold:: { TypeFoldable , TypeFolder } ;
43
54use super :: InferCtxt ;
65use super :: RegionVariableOrigin ;
6+ use super :: type_variable:: TypeVariableOrigin ;
7+
8+ use std:: ops:: Range ;
79
810impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
911 /// This rather funky routine is used while processing expected
@@ -17,7 +19,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1719 /// from `&[u32; 3]` to `&[u32]` and make the users life more
1820 /// pleasant.
1921 ///
20- /// The way we do this is using `fudge_regions_if_ok `. What the
22+ /// The way we do this is using `fudge_inference_if_ok `. What the
2123 /// routine actually does is to start a snapshot and execute the
2224 /// closure `f`. In our example above, what this closure will do
2325 /// is to unify the expectation (`Option<&[u32]>`) with the actual
@@ -26,7 +28,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
2628 /// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The
2729 /// input type (`?T`) is then returned by `f()`.
2830 ///
29- /// At this point, `fudge_regions_if_ok ` will normalize all type
31+ /// At this point, `fudge_inference_if_ok ` will normalize all type
3032 /// variables, converting `?T` to `&?a [u32]` and end the
3133 /// snapshot. The problem is that we can't just return this type
3234 /// out, because it references the region variable `?a`, and that
@@ -42,36 +44,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
4244 /// regions in question are not particularly important. We will
4345 /// use the expected types to guide coercions, but we will still
4446 /// type-check the resulting types from those coercions against
45- /// the actual types (`?T`, `Option<?T`) -- and remember that
47+ /// the actual types (`?T`, `Option<?T> `) -- and remember that
4648 /// after the snapshot is popped, the variable `?T` is no longer
4749 /// unified.
48- pub fn fudge_regions_if_ok < T , E , F > ( & self ,
49- origin : & RegionVariableOrigin ,
50- f : F ) -> Result < T , E > where
50+ pub fn fudge_inference_if_ok < T , E , F > (
51+ & self ,
52+ f : F ,
53+ ) -> Result < T , E > where
5154 F : FnOnce ( ) -> Result < T , E > ,
5255 T : TypeFoldable < ' tcx > ,
5356 {
54- debug ! ( "fudge_regions_if_ok(origin={:?})" , origin ) ;
57+ debug ! ( "fudge_inference_if_ok()" ) ;
5558
56- let ( type_variables , region_vars , value) = self . probe ( |snapshot| {
59+ let ( mut fudger , value) = self . probe ( |snapshot| {
5760 match f ( ) {
5861 Ok ( value) => {
5962 let value = self . resolve_type_vars_if_possible ( & value) ;
6063
6164 // At this point, `value` could in principle refer
62- // to types/regions that have been created during
65+ // to inference variables that have been created during
6366 // the snapshot. Once we exit `probe()`, those are
6467 // going to be popped, so we will have to
6568 // eliminate any references to them.
6669
67- let type_variables =
68- self . type_variables . borrow_mut ( ) . types_created_since_snapshot (
69- & snapshot. type_snapshot ) ;
70- let region_vars =
71- self . borrow_region_constraints ( ) . vars_created_since_snapshot (
72- & snapshot. region_constraints_snapshot ) ;
70+ let type_vars = self . type_variables . borrow_mut ( ) . vars_since_snapshot (
71+ & snapshot. type_snapshot ,
72+ ) ;
73+ let int_vars = self . int_unification_table . borrow_mut ( ) . vars_since_snapshot (
74+ & snapshot. int_snapshot ,
75+ ) ;
76+ let float_vars = self . float_unification_table . borrow_mut ( ) . vars_since_snapshot (
77+ & snapshot. float_snapshot ,
78+ ) ;
79+ let region_vars = self . borrow_region_constraints ( ) . vars_since_snapshot (
80+ & snapshot. region_constraints_snapshot ,
81+ ) ;
82+
83+ let fudger = InferenceFudger {
84+ infcx : self ,
85+ type_vars,
86+ int_vars,
87+ float_vars,
88+ region_vars,
89+ } ;
7390
74- Ok ( ( type_variables , region_vars , value) )
91+ Ok ( ( fudger , value) )
7592 }
7693 Err ( e) => Err ( e) ,
7794 }
@@ -84,69 +101,77 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
84101
85102 // Micro-optimization: if no variables have been created, then
86103 // `value` can't refer to any of them. =) So we can just return it.
87- if type_variables. is_empty ( ) && region_vars. is_empty ( ) {
88- return Ok ( value) ;
104+ if fudger. type_vars . 0 . is_empty ( ) &&
105+ fudger. int_vars . is_empty ( ) &&
106+ fudger. float_vars . is_empty ( ) &&
107+ fudger. region_vars . 0 . is_empty ( ) {
108+ Ok ( value)
109+ } else {
110+ Ok ( value. fold_with ( & mut fudger) )
89111 }
90-
91- let mut fudger = RegionFudger {
92- infcx : self ,
93- type_variables : & type_variables,
94- region_vars : & region_vars,
95- origin,
96- } ;
97-
98- Ok ( value. fold_with ( & mut fudger) )
99112 }
100113}
101114
102- pub struct RegionFudger < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
115+ pub struct InferenceFudger < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
103116 infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
104- type_variables : & ' a TypeVariableMap ,
105- region_vars : & ' a Vec < ty:: RegionVid > ,
106- origin : & ' a RegionVariableOrigin ,
117+ type_vars : ( Range < TyVid > , Vec < TypeVariableOrigin > ) ,
118+ int_vars : Range < IntVid > ,
119+ float_vars : Range < FloatVid > ,
120+ region_vars : ( Range < RegionVid > , Vec < RegionVariableOrigin > ) ,
107121}
108122
109- impl < ' a , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for RegionFudger < ' a , ' gcx , ' tcx > {
123+ impl < ' a , ' gcx , ' tcx > TypeFolder < ' gcx , ' tcx > for InferenceFudger < ' a , ' gcx , ' tcx > {
110124 fn tcx < ' b > ( & ' b self ) -> TyCtxt < ' b , ' gcx , ' tcx > {
111125 self . infcx . tcx
112126 }
113127
114128 fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
115129 match ty. sty {
116130 ty:: Infer ( ty:: InferTy :: TyVar ( vid) ) => {
117- match self . type_variables . get ( & vid) {
118- None => {
119- // This variable was created before the
120- // "fudging". Since we refresh all type
121- // variables to their binding anyhow, we know
122- // that it is unbound, so we can just return
123- // it.
124- debug_assert ! ( self . infcx. type_variables. borrow_mut( )
125- . probe( vid)
126- . is_unknown( ) ) ;
127- ty
128- }
129-
130- Some ( & origin) => {
131- // This variable was created during the
132- // fudging. Recreate it with a fresh variable
133- // here.
134- self . infcx . next_ty_var ( origin)
135- }
131+ if self . type_vars . 0 . contains ( & vid) {
132+ // This variable was created during the fudging.
133+ // Recreate it with a fresh variable here.
134+ let idx = ( vid. index - self . type_vars . 0 . start . index ) as usize ;
135+ let origin = self . type_vars . 1 [ idx] ;
136+ self . infcx . next_ty_var ( origin)
137+ } else {
138+ // This variable was created before the
139+ // "fudging". Since we refresh all type
140+ // variables to their binding anyhow, we know
141+ // that it is unbound, so we can just return
142+ // it.
143+ debug_assert ! ( self . infcx. type_variables. borrow_mut( )
144+ . probe( vid)
145+ . is_unknown( ) ) ;
146+ ty
147+ }
148+ }
149+ ty:: Infer ( ty:: InferTy :: IntVar ( vid) ) => {
150+ if self . int_vars . contains ( & vid) {
151+ self . infcx . next_int_var ( )
152+ } else {
153+ ty
154+ }
155+ }
156+ ty:: Infer ( ty:: InferTy :: FloatVar ( vid) ) => {
157+ if self . float_vars . contains ( & vid) {
158+ self . infcx . next_float_var ( )
159+ } else {
160+ ty
136161 }
137162 }
138163 _ => ty. super_fold_with ( self ) ,
139164 }
140165 }
141166
142167 fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
143- match * r {
144- ty:: ReVar ( v) if self . region_vars . contains ( & v) => {
145- self . infcx . next_region_var ( self . origin . clone ( ) )
146- }
147- _ => {
148- r
168+ if let ty:: ReVar ( vid) = r {
169+ if self . region_vars . 0 . contains ( & vid) {
170+ let idx = ( vid. index ( ) - self . region_vars . 0 . start . index ( ) ) as usize ;
171+ let origin = self . region_vars . 1 [ idx] ;
172+ return self . infcx . next_region_var ( origin) ;
149173 }
150174 }
175+ r
151176 }
152177}
0 commit comments