@@ -12,6 +12,8 @@ use ut::UnifyKey;
12
12
13
13
use std:: ops:: Range ;
14
14
15
+ use super :: { NoSnapshotLeaks , VariableLengths } ;
16
+
15
17
fn vars_since_snapshot < ' tcx , T > (
16
18
table : & mut UnificationTable < ' _ , ' tcx , T > ,
17
19
snapshot_var_len : usize ,
@@ -88,82 +90,108 @@ impl<'tcx> InferCtxt<'tcx> {
88
90
where
89
91
F : FnOnce ( ) -> Result < T , E > ,
90
92
T : TypeFoldable < TyCtxt < ' tcx > > ,
93
+ E : NoSnapshotLeaks < ' tcx > ,
91
94
{
92
- let variable_lengths = self . variable_lengths ( ) ;
93
- let ( mut fudger, value) = self . probe_unchecked ( |_| {
94
- match f ( ) {
95
- Ok ( value) => {
96
- let value = self . resolve_vars_if_possible ( value) ;
97
-
98
- // At this point, `value` could in principle refer
99
- // to inference variables that have been created during
100
- // the snapshot. Once we exit `probe()`, those are
101
- // going to be popped, so we will have to
102
- // eliminate any references to them.
103
-
104
- let mut inner = self . inner . borrow_mut ( ) ;
105
- let type_vars =
106
- inner. type_variables ( ) . vars_since_snapshot ( variable_lengths. type_vars ) ;
107
- let int_vars = vars_since_snapshot (
108
- & mut inner. int_unification_table ( ) ,
109
- variable_lengths. int_vars ,
110
- ) ;
111
- let float_vars = vars_since_snapshot (
112
- & mut inner. float_unification_table ( ) ,
113
- variable_lengths. float_vars ,
114
- ) ;
115
- let region_vars = inner
116
- . unwrap_region_constraints ( )
117
- . vars_since_snapshot ( variable_lengths. region_vars ) ;
118
- let const_vars = const_vars_since_snapshot (
119
- & mut inner. const_unification_table ( ) ,
120
- variable_lengths. const_vars ,
121
- ) ;
122
-
123
- let fudger = InferenceFudger {
124
- infcx : self ,
125
- type_vars,
126
- int_vars,
127
- float_vars,
128
- region_vars,
129
- const_vars,
130
- } ;
95
+ self . probe ( |_| f ( ) . map ( |value| FudgeInference ( self . resolve_vars_if_possible ( value) ) ) )
96
+ . map ( |FudgeInference ( value) | value)
97
+ }
98
+ }
131
99
132
- Ok ( ( fudger, value) )
100
+ #[ macro_export]
101
+ macro_rules! fudge_vars_no_snapshot_leaks {
102
+ ( $tcx: lifetime, $t: ty) => {
103
+ const _: ( ) = {
104
+ use $crate:: infer:: snapshot:: fudge:: InferenceFudgeData ;
105
+ impl <$tcx> $crate:: infer:: snapshot:: NoSnapshotLeaks <$tcx> for $t {
106
+ type DataStart = $crate:: infer:: snapshot:: VariableLengths ;
107
+ type DataEnd = InferenceFudgeData ;
108
+ fn mk_data_snapshot_start( infcx: & InferCtxt <$tcx>) -> Self :: DataStart {
109
+ infcx. variable_lengths( )
110
+ }
111
+ fn mk_data_snapshot_end(
112
+ infcx: & InferCtxt <$tcx>,
113
+ variable_lengths: Self :: DataStart ,
114
+ ) -> Self :: DataEnd {
115
+ InferenceFudgeData :: new( infcx, variable_lengths)
116
+ }
117
+ fn avoid_leaks( self , infcx: & InferCtxt <' tcx>, fudge_data: Self :: DataEnd ) -> Self {
118
+ fudge_data. fudge_inference( infcx, self )
133
119
}
134
- Err ( e) => Err ( e) ,
135
120
}
136
- } ) ? ;
137
-
138
- // At this point, we need to replace any of the now-popped
139
- // type/region variables that appear in `value` with a fresh
140
- // variable of the appropriate kind. We can't do this during
141
- // the probe because they would just get popped then too. =)
142
-
143
- // Micro-optimization: if no variables have been created, then
144
- // `value` can't refer to any of them. =) So we can just return it.
145
- if fudger . type_vars . 0 . is_empty ( )
146
- && fudger . int_vars . is_empty ( )
147
- && fudger . float_vars . is_empty ( )
148
- && fudger . region_vars . 0 . is_empty ( )
149
- && fudger . const_vars . 0 . is_empty ( )
150
- {
151
- Ok ( value )
152
- } else {
153
- Ok ( value . fold_with ( & mut fudger ) )
154
- }
121
+ } ;
122
+ } ;
123
+ }
124
+
125
+ struct FudgeInference < T > ( T ) ;
126
+ impl < ' tcx , T : TypeFoldable < TyCtxt < ' tcx > > > NoSnapshotLeaks < ' tcx > for FudgeInference < T > {
127
+ type DataStart = VariableLengths ;
128
+ type DataEnd = InferenceFudgeData ;
129
+ fn mk_data_snapshot_start ( infcx : & InferCtxt < ' tcx > ) -> Self :: DataStart {
130
+ infcx . variable_lengths ( )
131
+ }
132
+ fn mk_data_snapshot_end (
133
+ infcx : & InferCtxt < ' tcx > ,
134
+ variable_lengths : Self :: DataStart ,
135
+ ) -> Self :: DataEnd {
136
+ InferenceFudgeData :: new ( infcx , variable_lengths )
137
+ }
138
+ fn avoid_leaks ( self , infcx : & InferCtxt < ' tcx > , fudge_data : Self :: DataEnd ) -> Self {
139
+ FudgeInference ( fudge_data . fudge_inference ( infcx , self . 0 ) )
155
140
}
156
141
}
157
142
158
- pub struct InferenceFudger < ' a , ' tcx > {
159
- infcx : & ' a InferCtxt < ' tcx > ,
143
+ pub struct InferenceFudgeData {
160
144
type_vars : ( Range < TyVid > , Vec < TypeVariableOrigin > ) ,
161
145
int_vars : Range < IntVid > ,
162
146
float_vars : Range < FloatVid > ,
163
147
region_vars : ( Range < RegionVid > , Vec < RegionVariableOrigin > ) ,
164
148
const_vars : ( Range < ConstVid > , Vec < ConstVariableOrigin > ) ,
165
149
}
166
150
151
+ impl InferenceFudgeData {
152
+ pub fn new < ' tcx > (
153
+ infcx : & InferCtxt < ' tcx > ,
154
+ variable_lengths : VariableLengths ,
155
+ ) -> InferenceFudgeData {
156
+ let mut inner = infcx. inner . borrow_mut ( ) ;
157
+ let type_vars = inner. type_variables ( ) . vars_since_snapshot ( variable_lengths. type_vars ) ;
158
+ let int_vars =
159
+ vars_since_snapshot ( & mut inner. int_unification_table ( ) , variable_lengths. int_vars ) ;
160
+ let float_vars =
161
+ vars_since_snapshot ( & mut inner. float_unification_table ( ) , variable_lengths. float_vars ) ;
162
+ let region_vars =
163
+ inner. unwrap_region_constraints ( ) . vars_since_snapshot ( variable_lengths. region_vars ) ;
164
+ let const_vars = const_vars_since_snapshot (
165
+ & mut inner. const_unification_table ( ) ,
166
+ variable_lengths. const_vars ,
167
+ ) ;
168
+
169
+ InferenceFudgeData { type_vars, int_vars, float_vars, region_vars, const_vars }
170
+ }
171
+
172
+ pub fn fudge_inference < ' tcx , T : TypeFoldable < TyCtxt < ' tcx > > > (
173
+ self ,
174
+ infcx : & InferCtxt < ' tcx > ,
175
+ value : T ,
176
+ ) -> T {
177
+ if self . type_vars . 0 . is_empty ( )
178
+ && self . int_vars . is_empty ( )
179
+ && self . float_vars . is_empty ( )
180
+ && self . region_vars . 0 . is_empty ( )
181
+ && self . const_vars . 0 . is_empty ( )
182
+ {
183
+ value
184
+ } else {
185
+ value. fold_with ( & mut InferenceFudger { infcx, data : self } )
186
+ }
187
+ }
188
+ }
189
+
190
+ struct InferenceFudger < ' a , ' tcx > {
191
+ infcx : & ' a InferCtxt < ' tcx > ,
192
+ data : InferenceFudgeData ,
193
+ }
194
+
167
195
impl < ' a , ' tcx > TypeFolder < TyCtxt < ' tcx > > for InferenceFudger < ' a , ' tcx > {
168
196
fn interner ( & self ) -> TyCtxt < ' tcx > {
169
197
self . infcx . tcx
@@ -172,11 +200,11 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
172
200
fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
173
201
match * ty. kind ( ) {
174
202
ty:: Infer ( ty:: InferTy :: TyVar ( vid) ) => {
175
- if self . type_vars . 0 . contains ( & vid) {
203
+ if self . data . type_vars . 0 . contains ( & vid) {
176
204
// This variable was created during the fudging.
177
205
// Recreate it with a fresh variable here.
178
- let idx = vid. as_usize ( ) - self . type_vars . 0 . start . as_usize ( ) ;
179
- let origin = self . type_vars . 1 [ idx] ;
206
+ let idx = vid. as_usize ( ) - self . data . type_vars . 0 . start . as_usize ( ) ;
207
+ let origin = self . data . type_vars . 1 [ idx] ;
180
208
self . infcx . next_ty_var ( origin)
181
209
} else {
182
210
// This variable was created before the
@@ -191,14 +219,14 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
191
219
}
192
220
}
193
221
ty:: Infer ( ty:: InferTy :: IntVar ( vid) ) => {
194
- if self . int_vars . contains ( & vid) {
222
+ if self . data . int_vars . contains ( & vid) {
195
223
self . infcx . next_int_var ( )
196
224
} else {
197
225
ty
198
226
}
199
227
}
200
228
ty:: Infer ( ty:: InferTy :: FloatVar ( vid) ) => {
201
- if self . float_vars . contains ( & vid) {
229
+ if self . data . float_vars . contains ( & vid) {
202
230
self . infcx . next_float_var ( )
203
231
} else {
204
232
ty
@@ -210,22 +238,22 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
210
238
211
239
fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
212
240
if let ty:: ReVar ( vid) = * r
213
- && self . region_vars . 0 . contains ( & vid)
241
+ && self . data . region_vars . 0 . contains ( & vid)
214
242
{
215
- let idx = vid. index ( ) - self . region_vars . 0 . start . index ( ) ;
216
- let origin = self . region_vars . 1 [ idx] ;
243
+ let idx = vid. index ( ) - self . data . region_vars . 0 . start . index ( ) ;
244
+ let origin = self . data . region_vars . 1 [ idx] ;
217
245
return self . infcx . next_region_var ( origin) ;
218
246
}
219
247
r
220
248
}
221
249
222
250
fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
223
251
if let ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( vid) ) = ct. kind ( ) {
224
- if self . const_vars . 0 . contains ( & vid) {
252
+ if self . data . const_vars . 0 . contains ( & vid) {
225
253
// This variable was created during the fudging.
226
254
// Recreate it with a fresh variable here.
227
- let idx = vid. index ( ) - self . const_vars . 0 . start . index ( ) ;
228
- let origin = self . const_vars . 1 [ idx] ;
255
+ let idx = vid. index ( ) - self . data . const_vars . 0 . start . index ( ) ;
256
+ let origin = self . data . const_vars . 1 [ idx] ;
229
257
self . infcx . next_const_var ( ct. ty ( ) , origin)
230
258
} else {
231
259
ct
0 commit comments