@@ -4,9 +4,12 @@ use rustc_data_structures::{snapshot_vec as sv, unify as ut};
4
4
use rustc_middle:: infer:: unify_key:: { ConstVariableValue , ConstVidKey } ;
5
5
use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
6
6
use rustc_middle:: ty:: { self , ConstVid , FloatVid , IntVid , RegionVid , Ty , TyCtxt , TyVid } ;
7
+ use rustc_type_ir:: EffectVid ;
8
+ use rustc_type_ir:: visit:: TypeVisitableExt ;
7
9
use tracing:: instrument;
8
10
use ut:: UnifyKey ;
9
11
12
+ use super :: VariableLengths ;
10
13
use crate :: infer:: type_variable:: TypeVariableOrigin ;
11
14
use crate :: infer:: { ConstVariableOrigin , InferCtxt , RegionVariableOrigin , UnificationTable } ;
12
15
@@ -40,26 +43,7 @@ fn const_vars_since_snapshot<'tcx>(
40
43
)
41
44
}
42
45
43
- struct VariableLengths {
44
- type_var_len : usize ,
45
- const_var_len : usize ,
46
- int_var_len : usize ,
47
- float_var_len : usize ,
48
- region_constraints_len : usize ,
49
- }
50
-
51
46
impl < ' tcx > InferCtxt < ' tcx > {
52
- fn variable_lengths ( & self ) -> VariableLengths {
53
- let mut inner = self . inner . borrow_mut ( ) ;
54
- VariableLengths {
55
- type_var_len : inner. type_variables ( ) . num_vars ( ) ,
56
- const_var_len : inner. const_unification_table ( ) . len ( ) ,
57
- int_var_len : inner. int_unification_table ( ) . len ( ) ,
58
- float_var_len : inner. float_unification_table ( ) . len ( ) ,
59
- region_constraints_len : inner. unwrap_region_constraints ( ) . num_region_vars ( ) ,
60
- }
61
- }
62
-
63
47
/// This rather funky routine is used while processing expected
64
48
/// types. What happens here is that we want to propagate a
65
49
/// coercion through the return type of a fn to its
@@ -106,78 +90,94 @@ impl<'tcx> InferCtxt<'tcx> {
106
90
T : TypeFoldable < TyCtxt < ' tcx > > ,
107
91
{
108
92
let variable_lengths = self . variable_lengths ( ) ;
109
- let ( mut fudger, value) = self . probe ( |_| {
110
- match f ( ) {
111
- Ok ( value) => {
112
- let value = self . resolve_vars_if_possible ( value) ;
113
-
114
- // At this point, `value` could in principle refer
115
- // to inference variables that have been created during
116
- // the snapshot. Once we exit `probe()`, those are
117
- // going to be popped, so we will have to
118
- // eliminate any references to them.
119
-
120
- let mut inner = self . inner . borrow_mut ( ) ;
121
- let type_vars =
122
- inner. type_variables ( ) . vars_since_snapshot ( variable_lengths. type_var_len ) ;
123
- let int_vars = vars_since_snapshot (
124
- & inner. int_unification_table ( ) ,
125
- variable_lengths. int_var_len ,
126
- ) ;
127
- let float_vars = vars_since_snapshot (
128
- & inner. float_unification_table ( ) ,
129
- variable_lengths. float_var_len ,
130
- ) ;
131
- let region_vars = inner
132
- . unwrap_region_constraints ( )
133
- . vars_since_snapshot ( variable_lengths. region_constraints_len ) ;
134
- let const_vars = const_vars_since_snapshot (
135
- & mut inner. const_unification_table ( ) ,
136
- variable_lengths. const_var_len ,
137
- ) ;
138
-
139
- let fudger = InferenceFudger {
140
- infcx : self ,
141
- type_vars,
142
- int_vars,
143
- float_vars,
144
- region_vars,
145
- const_vars,
146
- } ;
147
-
148
- Ok ( ( fudger, value) )
149
- }
150
- Err ( e) => Err ( e) ,
151
- }
93
+ let ( snapshot_vars, value) = self . probe ( |_| {
94
+ let value = f ( ) ?;
95
+ // At this point, `value` could in principle refer
96
+ // to inference variables that have been created during
97
+ // the snapshot. Once we exit `probe()`, those are
98
+ // going to be popped, so we will have to
99
+ // eliminate any references to them.
100
+ let snapshot_vars = SnapshotVarData :: new ( self , variable_lengths) ;
101
+ Ok ( ( snapshot_vars, self . resolve_vars_if_possible ( value) ) )
152
102
} ) ?;
153
103
154
104
// At this point, we need to replace any of the now-popped
155
105
// type/region variables that appear in `value` with a fresh
156
106
// variable of the appropriate kind. We can't do this during
157
107
// the probe because they would just get popped then too. =)
108
+ Ok ( self . fudge_inference ( snapshot_vars, value) )
109
+ }
158
110
111
+ fn fudge_inference < T : TypeFoldable < TyCtxt < ' tcx > > > (
112
+ & self ,
113
+ snapshot_vars : SnapshotVarData ,
114
+ value : T ,
115
+ ) -> T {
159
116
// Micro-optimization: if no variables have been created, then
160
117
// `value` can't refer to any of them. =) So we can just return it.
161
- if fudger. type_vars . 0 . is_empty ( )
162
- && fudger. int_vars . is_empty ( )
163
- && fudger. float_vars . is_empty ( )
164
- && fudger. region_vars . 0 . is_empty ( )
165
- && fudger. const_vars . 0 . is_empty ( )
166
- {
167
- Ok ( value)
118
+ if snapshot_vars. is_empty ( ) {
119
+ value
168
120
} else {
169
- Ok ( value. fold_with ( & mut fudger ) )
121
+ value. fold_with ( & mut InferenceFudger { infcx : self , snapshot_vars } )
170
122
}
171
123
}
172
124
}
173
125
174
- struct InferenceFudger < ' a , ' tcx > {
175
- infcx : & ' a InferCtxt < ' tcx > ,
126
+ struct SnapshotVarData {
127
+ region_vars : ( Range < RegionVid > , Vec < RegionVariableOrigin > ) ,
176
128
type_vars : ( Range < TyVid > , Vec < TypeVariableOrigin > ) ,
177
129
int_vars : Range < IntVid > ,
178
130
float_vars : Range < FloatVid > ,
179
- region_vars : ( Range < RegionVid > , Vec < RegionVariableOrigin > ) ,
180
131
const_vars : ( Range < ConstVid > , Vec < ConstVariableOrigin > ) ,
132
+ effect_vars : Range < EffectVid > ,
133
+ }
134
+
135
+ impl SnapshotVarData {
136
+ fn new ( infcx : & InferCtxt < ' _ > , vars_pre_snapshot : VariableLengths ) -> SnapshotVarData {
137
+ let mut inner = infcx. inner . borrow_mut ( ) ;
138
+ let region_vars = inner
139
+ . unwrap_region_constraints ( )
140
+ . vars_since_snapshot ( vars_pre_snapshot. region_constraints_len ) ;
141
+ let type_vars = inner. type_variables ( ) . vars_since_snapshot ( vars_pre_snapshot. type_var_len ) ;
142
+ let int_vars =
143
+ vars_since_snapshot ( & inner. int_unification_table ( ) , vars_pre_snapshot. int_var_len ) ;
144
+ let float_vars =
145
+ vars_since_snapshot ( & inner. float_unification_table ( ) , vars_pre_snapshot. float_var_len ) ;
146
+
147
+ let const_vars = const_vars_since_snapshot (
148
+ & mut inner. const_unification_table ( ) ,
149
+ vars_pre_snapshot. const_var_len ,
150
+ ) ;
151
+ let effect_vars = vars_since_snapshot (
152
+ & inner. effect_unification_table ( ) ,
153
+ vars_pre_snapshot. effect_var_len ,
154
+ ) ;
155
+ let effect_vars = effect_vars. start . vid ..effect_vars. end . vid ;
156
+
157
+ SnapshotVarData { region_vars, type_vars, int_vars, float_vars, const_vars, effect_vars }
158
+ }
159
+
160
+ fn is_empty ( & self ) -> bool {
161
+ let SnapshotVarData {
162
+ region_vars,
163
+ type_vars,
164
+ int_vars,
165
+ float_vars,
166
+ const_vars,
167
+ effect_vars,
168
+ } = self ;
169
+ region_vars. 0 . is_empty ( )
170
+ && type_vars. 0 . is_empty ( )
171
+ && int_vars. is_empty ( )
172
+ && float_vars. is_empty ( )
173
+ && const_vars. 0 . is_empty ( )
174
+ && effect_vars. is_empty ( )
175
+ }
176
+ }
177
+
178
+ struct InferenceFudger < ' a , ' tcx > {
179
+ infcx : & ' a InferCtxt < ' tcx > ,
180
+ snapshot_vars : SnapshotVarData ,
181
181
}
182
182
183
183
impl < ' a , ' tcx > TypeFolder < TyCtxt < ' tcx > > for InferenceFudger < ' a , ' tcx > {
@@ -186,68 +186,93 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
186
186
}
187
187
188
188
fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
189
- match * ty. kind ( ) {
190
- ty:: Infer ( ty:: InferTy :: TyVar ( vid) ) => {
191
- if self . type_vars . 0 . contains ( & vid) {
192
- // This variable was created during the fudging.
193
- // Recreate it with a fresh variable here.
194
- let idx = vid. as_usize ( ) - self . type_vars . 0 . start . as_usize ( ) ;
195
- let origin = self . type_vars . 1 [ idx] ;
196
- self . infcx . next_ty_var_with_origin ( origin)
197
- } else {
198
- // This variable was created before the
199
- // "fudging". Since we refresh all type
200
- // variables to their binding anyhow, we know
201
- // that it is unbound, so we can just return
202
- // it.
203
- debug_assert ! (
204
- self . infcx. inner. borrow_mut( ) . type_variables( ) . probe( vid) . is_unknown( )
205
- ) ;
206
- ty
189
+ if let & ty:: Infer ( infer_ty) = ty. kind ( ) {
190
+ match infer_ty {
191
+ ty:: TyVar ( vid) => {
192
+ if self . snapshot_vars . type_vars . 0 . contains ( & vid) {
193
+ // This variable was created during the fudging.
194
+ // Recreate it with a fresh variable here.
195
+ let idx = vid. as_usize ( ) - self . snapshot_vars . type_vars . 0 . start . as_usize ( ) ;
196
+ let origin = self . snapshot_vars . type_vars . 1 [ idx] ;
197
+ self . infcx . next_ty_var_with_origin ( origin)
198
+ } else {
199
+ // This variable was created before the
200
+ // "fudging". Since we refresh all type
201
+ // variables to their binding anyhow, we know
202
+ // that it is unbound, so we can just return
203
+ // it.
204
+ debug_assert ! (
205
+ self . infcx. inner. borrow_mut( ) . type_variables( ) . probe( vid) . is_unknown( )
206
+ ) ;
207
+ ty
208
+ }
207
209
}
208
- }
209
- ty :: Infer ( ty :: InferTy :: IntVar ( vid) ) => {
210
- if self . int_vars . contains ( & vid ) {
211
- self . infcx . next_int_var ( )
212
- } else {
213
- ty
210
+ ty :: IntVar ( vid ) => {
211
+ if self . snapshot_vars . int_vars . contains ( & vid) {
212
+ self . infcx . next_int_var ( )
213
+ } else {
214
+ ty
215
+ }
214
216
}
215
- }
216
- ty:: Infer ( ty:: InferTy :: FloatVar ( vid) ) => {
217
- if self . float_vars . contains ( & vid) {
218
- self . infcx . next_float_var ( )
219
- } else {
220
- ty
217
+ ty:: FloatVar ( vid) => {
218
+ if self . snapshot_vars . float_vars . contains ( & vid) {
219
+ self . infcx . next_float_var ( )
220
+ } else {
221
+ ty
222
+ }
223
+ }
224
+ ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) => {
225
+ unreachable ! ( "unexpected fresh infcx var" )
221
226
}
222
227
}
223
- _ => ty. super_fold_with ( self ) ,
228
+ } else if ty. has_infer ( ) {
229
+ ty. super_fold_with ( self )
230
+ } else {
231
+ ty
224
232
}
225
233
}
226
234
227
235
fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
228
- if let ty:: ReVar ( vid) = * r
229
- && self . region_vars . 0 . contains ( & vid)
230
- {
231
- let idx = vid. index ( ) - self . region_vars . 0 . start . index ( ) ;
232
- let origin = self . region_vars . 1 [ idx] ;
233
- return self . infcx . next_region_var ( origin) ;
236
+ if let ty:: ReVar ( vid) = r. kind ( ) {
237
+ if self . snapshot_vars . region_vars . 0 . contains ( & vid) {
238
+ let idx = vid. index ( ) - self . snapshot_vars . region_vars . 0 . start . index ( ) ;
239
+ let origin = self . snapshot_vars . region_vars . 1 [ idx] ;
240
+ self . infcx . next_region_var ( origin)
241
+ } else {
242
+ r
243
+ }
244
+ } else {
245
+ r
234
246
}
235
- r
236
247
}
237
248
238
249
fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
239
- if let ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( vid) ) = ct. kind ( ) {
240
- if self . const_vars . 0 . contains ( & vid) {
241
- // This variable was created during the fudging.
242
- // Recreate it with a fresh variable here.
243
- let idx = vid. index ( ) - self . const_vars . 0 . start . index ( ) ;
244
- let origin = self . const_vars . 1 [ idx] ;
245
- self . infcx . next_const_var_with_origin ( origin)
246
- } else {
247
- ct
250
+ if let ty:: ConstKind :: Infer ( infer_ct) = ct. kind ( ) {
251
+ match infer_ct {
252
+ ty:: InferConst :: Var ( vid) => {
253
+ if self . snapshot_vars . const_vars . 0 . contains ( & vid) {
254
+ let idx = vid. index ( ) - self . snapshot_vars . const_vars . 0 . start . index ( ) ;
255
+ let origin = self . snapshot_vars . const_vars . 1 [ idx] ;
256
+ self . infcx . next_const_var_with_origin ( origin)
257
+ } else {
258
+ ct
259
+ }
260
+ }
261
+ ty:: InferConst :: EffectVar ( vid) => {
262
+ if self . snapshot_vars . effect_vars . contains ( & vid) {
263
+ self . infcx . next_effect_var ( )
264
+ } else {
265
+ ct
266
+ }
267
+ }
268
+ ty:: InferConst :: Fresh ( _) => {
269
+ unreachable ! ( "unexpected fresh infcx var" )
270
+ }
248
271
}
249
- } else {
272
+ } else if ct . has_infer ( ) {
250
273
ct. super_fold_with ( self )
274
+ } else {
275
+ ct
251
276
}
252
277
}
253
278
}
0 commit comments