@@ -52,7 +52,7 @@ pub trait GeneralizerDelegate<'tcx> {
52
52
53
53
fn forbid_inference_vars ( ) -> bool ;
54
54
55
- fn generalize_existential ( & mut self , universe : ty:: UniverseIndex ) -> ty:: Region < ' tcx > ;
55
+ fn generalize_region ( & mut self , universe : ty:: UniverseIndex ) -> ty:: Region < ' tcx > ;
56
56
}
57
57
58
58
pub struct CombineDelegate < ' cx , ' tcx > {
@@ -70,7 +70,9 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
70
70
false
71
71
}
72
72
73
- fn generalize_existential ( & mut self , universe : ty:: UniverseIndex ) -> ty:: Region < ' tcx > {
73
+ fn generalize_region ( & mut self , universe : ty:: UniverseIndex ) -> ty:: Region < ' tcx > {
74
+ // FIXME: This is non-ideal because we don't give a
75
+ // very descriptive origin for this region variable.
74
76
self . infcx
75
77
. next_region_var_in_universe ( RegionVariableOrigin :: MiscVariable ( self . span ) , universe)
76
78
}
@@ -88,18 +90,17 @@ where
88
90
<Self as TypeRelatingDelegate < ' tcx > >:: forbid_inference_vars ( )
89
91
}
90
92
91
- fn generalize_existential ( & mut self , universe : ty:: UniverseIndex ) -> ty:: Region < ' tcx > {
93
+ fn generalize_region ( & mut self , universe : ty:: UniverseIndex ) -> ty:: Region < ' tcx > {
92
94
<Self as TypeRelatingDelegate < ' tcx > >:: generalize_existential ( self , universe)
93
95
}
94
96
}
95
97
96
- /// The "type generalizer" is used when handling inference variables.
98
+ /// The "generalizer" is used when handling inference variables.
97
99
///
98
100
/// The basic strategy for handling a constraint like `?A <: B` is to
99
- /// apply a "generalization strategy" to the type `B` -- this replaces
100
- /// all the lifetimes in the type `B` with fresh inference
101
- /// variables. (You can read more about the strategy in this [blog
102
- /// post].)
101
+ /// apply a "generalization strategy" to the term `B` -- this replaces
102
+ /// all the lifetimes in the term `B` with fresh inference variables.
103
+ /// (You can read more about the strategy in this [blog post].)
103
104
///
104
105
/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
105
106
/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
@@ -110,9 +111,11 @@ where
110
111
struct Generalizer < ' me , ' tcx , D > {
111
112
infcx : & ' me InferCtxt < ' tcx > ,
112
113
113
- // An delegate used to abstract the behaviors of the three previous
114
- // generalizer-like implementations.
115
- pub delegate : & ' me mut D ,
114
+ /// This is used to abstract the behaviors of the three previous
115
+ /// generalizer-like implementations (`Generalizer`, `TypeGeneralizer`,
116
+ /// and `ConstInferUnifier`). See [`GeneralizerDelegate`] for more
117
+ /// information.
118
+ delegate : & ' me mut D ,
116
119
117
120
/// After we generalize this type, we are going to relate it to
118
121
/// some other type. What will be the variance at this point?
@@ -138,6 +141,7 @@ struct Generalizer<'me, 'tcx, D> {
138
141
}
139
142
140
143
impl < ' tcx , D > Generalizer < ' _ , ' tcx , D > {
144
+ /// Create an error that corresponds to the term kind in `root_term`
141
145
fn cyclic_term_error ( & self ) -> TypeError < ' tcx > {
142
146
match self . root_term . unpack ( ) {
143
147
ty:: TermKind :: Ty ( ty) => TypeError :: CyclicTy ( ty) ,
@@ -183,44 +187,37 @@ where
183
187
relate:: relate_substs_with_variances (
184
188
self ,
185
189
item_def_id,
186
- & opt_variances,
190
+ opt_variances,
187
191
a_subst,
188
192
b_subst,
189
193
true ,
190
194
)
191
195
}
192
196
}
193
197
198
+ #[ instrument( level = "debug" , skip( self , variance, b) , ret) ]
194
199
fn relate_with_variance < T : Relate < ' tcx > > (
195
200
& mut self ,
196
201
variance : ty:: Variance ,
197
202
_info : ty:: VarianceDiagInfo < ' tcx > ,
198
203
a : T ,
199
204
b : T ,
200
205
) -> RelateResult < ' tcx , T > {
201
- debug ! ( "Generalizer::relate_with_variance(variance={:?}, a={:?}, b={:?})" , variance, a, b) ;
202
-
203
206
let old_ambient_variance = self . ambient_variance ;
204
207
self . ambient_variance = self . ambient_variance . xform ( variance) ;
205
-
206
- debug ! ( "Generalizer::relate_with_variance: ambient_variance = {:?}" , self . ambient_variance) ;
207
-
208
+ debug ! ( ?self . ambient_variance, "new ambient variance" ) ;
208
209
let r = self . relate ( a, b) ?;
209
-
210
210
self . ambient_variance = old_ambient_variance;
211
-
212
- debug ! ( "Generalizer::relate_with_variance: r={:?}" , r) ;
213
-
214
211
Ok ( r)
215
212
}
216
213
214
+ #[ instrument( level = "debug" , skip( self , t2) , ret) ]
217
215
fn tys ( & mut self , t : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
218
216
assert_eq ! ( t, t2) ; // we are misusing TypeRelation here; both LHS and RHS ought to be ==
219
217
220
218
if let Some ( & result) = self . cache . get ( & t) {
221
219
return Ok ( result) ;
222
220
}
223
- debug ! ( "generalize: t={:?}" , t) ;
224
221
225
222
// Check to see whether the type we are generalizing references
226
223
// any other type variable related to `vid` via
@@ -241,21 +238,22 @@ where
241
238
let mut inner = self . infcx . inner . borrow_mut ( ) ;
242
239
let vid = inner. type_variables ( ) . root_var ( vid) ;
243
240
let sub_vid = inner. type_variables ( ) . sub_root_var ( vid) ;
244
- if TermVid :: Ty ( sub_vid) == self . root_vid {
245
- // If sub-roots are equal, then `for_vid` and
241
+
242
+ if ty:: TermVid :: Ty ( sub_vid) == self . root_vid {
243
+ // If sub-roots are equal, then `root_vid` and
246
244
// `vid` are related via subtyping.
247
245
Err ( self . cyclic_term_error ( ) )
248
246
} else {
249
247
let probe = inner. type_variables ( ) . probe ( vid) ;
250
248
match probe {
251
249
TypeVariableValue :: Known { value : u } => {
252
- debug ! ( "generalize: known value {:?}" , u) ;
253
250
drop ( inner) ;
254
251
self . relate ( u, u)
255
252
}
256
253
TypeVariableValue :: Unknown { universe } => {
257
254
match self . ambient_variance {
258
- // Invariant: no need to make a fresh type variable.
255
+ // Invariant: no need to make a fresh type variable
256
+ // if we can name the universe.
259
257
ty:: Invariant => {
260
258
if self . for_universe . can_name ( universe) {
261
259
return Ok ( t) ;
@@ -282,7 +280,7 @@ where
282
280
// operation. This is needed to detect cyclic types. To see why, see the
283
281
// docs in the `type_variables` module.
284
282
inner. type_variables ( ) . sub ( vid, new_var_id) ;
285
- debug ! ( "generalize: replacing original vid={:?} with new={:?}" , vid, u) ;
283
+ debug ! ( "replacing original vid={:?} with new={:?}" , vid, u) ;
286
284
Ok ( u)
287
285
}
288
286
}
@@ -297,45 +295,41 @@ where
297
295
}
298
296
299
297
ty:: Placeholder ( placeholder) => {
300
- if self . for_universe . cannot_name ( placeholder. universe ) {
298
+ if self . for_universe . can_name ( placeholder. universe ) {
299
+ Ok ( t)
300
+ } else {
301
301
debug ! (
302
- "Generalizer::tys: root universe {:?} cannot name\
303
- placeholder in universe {:?}",
302
+ "root universe {:?} cannot name placeholder in universe {:?}" ,
304
303
self . for_universe, placeholder. universe
305
304
) ;
306
305
Err ( TypeError :: Mismatch )
307
- } else {
308
- Ok ( t)
309
306
}
310
307
}
311
308
312
- ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
313
- let s = self . relate ( substs, substs) ?;
314
- Ok ( if s == substs { t } else { self . tcx ( ) . mk_opaque ( def_id, s) } )
315
- }
316
309
_ => relate:: super_relate_tys ( self , t, t) ,
317
310
} ?;
318
311
319
312
self . cache . insert ( t, g) ;
320
313
Ok ( g)
321
314
}
322
315
316
+ #[ instrument( level = "debug" , skip( self , r2) , ret) ]
323
317
fn regions (
324
318
& mut self ,
325
319
r : ty:: Region < ' tcx > ,
326
320
r2 : ty:: Region < ' tcx > ,
327
321
) -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
328
322
assert_eq ! ( r, r2) ; // we are misusing TypeRelation here; both LHS and RHS ought to be ==
329
323
330
- debug ! ( "generalize: regions r={:?}" , r) ;
331
-
332
324
match * r {
333
325
// Never make variables for regions bound within the type itself,
334
326
// nor for erased regions.
335
327
ty:: ReLateBound ( ..) | ty:: ReErased => {
336
328
return Ok ( r) ;
337
329
}
338
330
331
+ // It doesn't really matter for correctness if we generalize ReError,
332
+ // since we're already on a doomed compilation path.
339
333
ty:: ReError ( _) => {
340
334
return Ok ( r) ;
341
335
}
@@ -359,13 +353,10 @@ where
359
353
}
360
354
}
361
355
362
- // FIXME: This is non-ideal because we don't give a
363
- // very descriptive origin for this region variable.
364
- let replacement_region_vid = self . delegate . generalize_existential ( self . for_universe ) ;
365
-
366
- Ok ( replacement_region_vid)
356
+ Ok ( self . delegate . generalize_region ( self . for_universe ) )
367
357
}
368
358
359
+ #[ instrument( level = "debug" , skip( self , c2) , ret) ]
369
360
fn consts (
370
361
& mut self ,
371
362
c : ty:: Const < ' tcx > ,
@@ -378,13 +369,12 @@ where
378
369
bug ! ( "unexpected inference variable encountered in NLL generalization: {:?}" , c) ;
379
370
}
380
371
ty:: ConstKind :: Infer ( InferConst :: Var ( vid) ) => {
381
- // Check if the current unification would end up
382
- // unifying `target_vid` with a const which contains
383
- // an inference variable which is unioned with `target_vid`.
384
- //
385
- // Not doing so can easily result in stack overflows.
386
- if TermVid :: Const ( self . infcx . inner . borrow_mut ( ) . const_unification_table ( ) . find ( vid) )
387
- == self . root_vid
372
+ // If root const vids are equal, then `root_vid` and
373
+ // `vid` are related and we'd be inferring an infinitely
374
+ // deep const.
375
+ if ty:: TermVid :: Const (
376
+ self . infcx . inner . borrow_mut ( ) . const_unification_table ( ) . find ( vid) ,
377
+ ) == self . root_vid
388
378
{
389
379
return Err ( self . cyclic_term_error ( ) ) ;
390
380
}
@@ -421,10 +411,22 @@ where
421
411
) ?;
422
412
Ok ( self . tcx ( ) . mk_const ( ty:: UnevaluatedConst { def, substs } , c. ty ( ) ) )
423
413
}
414
+ ty:: ConstKind :: Placeholder ( placeholder) => {
415
+ if self . for_universe . can_name ( placeholder. universe ) {
416
+ Ok ( c)
417
+ } else {
418
+ debug ! (
419
+ "root universe {:?} cannot name placeholder in universe {:?}" ,
420
+ self . for_universe, placeholder. universe
421
+ ) ;
422
+ Err ( TypeError :: Mismatch )
423
+ }
424
+ }
424
425
_ => relate:: super_relate_consts ( self , c, c) ,
425
426
}
426
427
}
427
428
429
+ #[ instrument( level = "debug" , skip( self ) , ret) ]
428
430
fn binders < T > (
429
431
& mut self ,
430
432
a : ty:: Binder < ' tcx , T > ,
@@ -433,7 +435,6 @@ where
433
435
where
434
436
T : Relate < ' tcx > ,
435
437
{
436
- debug ! ( "Generalizer::binders(a={:?})" , a) ;
437
438
let result = self . relate ( a. skip_binder ( ) , a. skip_binder ( ) ) ?;
438
439
Ok ( a. rebind ( result) )
439
440
}
0 commit comments