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 } ;
3
2
use crate :: ty:: fold:: { TypeFoldable , TypeFolder } ;
4
3
5
4
use super :: InferCtxt ;
6
5
use super :: RegionVariableOrigin ;
6
+ use super :: type_variable:: TypeVariableOrigin ;
7
+
8
+ use std:: ops:: Range ;
7
9
8
10
impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
9
11
/// This rather funky routine is used while processing expected
@@ -17,7 +19,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
17
19
/// from `&[u32; 3]` to `&[u32]` and make the users life more
18
20
/// pleasant.
19
21
///
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
21
23
/// routine actually does is to start a snapshot and execute the
22
24
/// closure `f`. In our example above, what this closure will do
23
25
/// is to unify the expectation (`Option<&[u32]>`) with the actual
@@ -26,7 +28,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
26
28
/// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The
27
29
/// input type (`?T`) is then returned by `f()`.
28
30
///
29
- /// At this point, `fudge_regions_if_ok ` will normalize all type
31
+ /// At this point, `fudge_inference_if_ok ` will normalize all type
30
32
/// variables, converting `?T` to `&?a [u32]` and end the
31
33
/// snapshot. The problem is that we can't just return this type
32
34
/// out, because it references the region variable `?a`, and that
@@ -42,36 +44,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
42
44
/// regions in question are not particularly important. We will
43
45
/// use the expected types to guide coercions, but we will still
44
46
/// 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
46
48
/// after the snapshot is popped, the variable `?T` is no longer
47
49
/// 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
51
54
F : FnOnce ( ) -> Result < T , E > ,
52
55
T : TypeFoldable < ' tcx > ,
53
56
{
54
- debug ! ( "fudge_regions_if_ok(origin={:?})" , origin ) ;
57
+ debug ! ( "fudge_inference_if_ok()" ) ;
55
58
56
- let ( type_variables , region_vars , value) = self . probe ( |snapshot| {
59
+ let ( mut fudger , value) = self . probe ( |snapshot| {
57
60
match f ( ) {
58
61
Ok ( value) => {
59
62
let value = self . resolve_type_vars_if_possible ( & value) ;
60
63
61
64
// 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
63
66
// the snapshot. Once we exit `probe()`, those are
64
67
// going to be popped, so we will have to
65
68
// eliminate any references to them.
66
69
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
+ } ;
73
90
74
- Ok ( ( type_variables , region_vars , value) )
91
+ Ok ( ( fudger , value) )
75
92
}
76
93
Err ( e) => Err ( e) ,
77
94
}
@@ -84,69 +101,77 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
84
101
85
102
// Micro-optimization: if no variables have been created, then
86
103
// `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) )
89
111
}
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) )
99
112
}
100
113
}
101
114
102
- pub struct RegionFudger < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
115
+ pub struct InferenceFudger < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
103
116
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 > ) ,
107
121
}
108
122
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 > {
110
124
fn tcx < ' b > ( & ' b self ) -> TyCtxt < ' b , ' gcx , ' tcx > {
111
125
self . infcx . tcx
112
126
}
113
127
114
128
fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
115
129
match ty. sty {
116
130
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
136
161
}
137
162
}
138
163
_ => ty. super_fold_with ( self ) ,
139
164
}
140
165
}
141
166
142
167
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) ;
149
173
}
150
174
}
175
+ r
151
176
}
152
177
}
0 commit comments