@@ -51,6 +51,13 @@ pub struct LexicalRegionResolutions<'tcx> {
51
51
52
52
#[ derive( Copy , Clone , Debug ) ]
53
53
pub ( crate ) enum VarValue < ' tcx > {
54
+ /// Empty lifetime is for data that is never accessed. We tag the
55
+ /// empty lifetime with a universe -- the idea is that we don't
56
+ /// want `exists<'a> { forall<'b> { 'b: 'a } }` to be satisfiable.
57
+ /// Therefore, the `'empty` in a universe `U` is less than all
58
+ /// regions visible from `U`, but not less than regions not visible
59
+ /// from `U`.
60
+ Empty ( ty:: UniverseIndex ) ,
54
61
Value ( Region < ' tcx > ) ,
55
62
ErrorValue ,
56
63
}
@@ -117,7 +124,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
117
124
& mut self ,
118
125
errors : & mut Vec < RegionResolutionError < ' tcx > > ,
119
126
) -> LexicalRegionResolutions < ' tcx > {
120
- let mut var_data = self . construct_var_data ( self . tcx ( ) ) ;
127
+ let mut var_data = self . construct_var_data ( ) ;
121
128
122
129
if cfg ! ( debug_assertions) {
123
130
self . dump_constraints ( ) ;
@@ -137,13 +144,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
137
144
138
145
/// Initially, the value for all variables is set to `'empty`, the
139
146
/// empty region. The `expansion` phase will grow this larger.
140
- fn construct_var_data ( & self , tcx : TyCtxt < ' tcx > ) -> LexicalRegionResolutions < ' tcx > {
147
+ fn construct_var_data ( & self ) -> LexicalRegionResolutions < ' tcx > {
141
148
LexicalRegionResolutions {
142
149
values : IndexVec :: from_fn_n (
143
150
|vid| {
144
151
let vid_universe = self . var_infos [ vid] . universe ;
145
- let re_empty = tcx. mk_region ( ty:: ReEmpty ( vid_universe) ) ;
146
- VarValue :: Value ( re_empty)
152
+ VarValue :: Empty ( vid_universe)
147
153
} ,
148
154
self . num_vars ( ) ,
149
155
) ,
@@ -190,38 +196,139 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
190
196
}
191
197
192
198
fn expansion ( & self , var_values : & mut LexicalRegionResolutions < ' tcx > ) {
199
+ // In the first pass, we expand region vids according to constraints we
200
+ // have previously found. In the second pass, we loop through the region
201
+ // vids we expanded and expand *across* region vids (effectively
202
+ // "expanding" new `RegSubVar` constraints).
203
+
204
+ // Tracks the `VarSubVar` constraints generated for each region vid. We
205
+ // later use this to expand across vids.
193
206
let mut constraints = IndexVec :: from_elem_n ( Vec :: new ( ) , var_values. values . len ( ) ) ;
207
+ // Tracks the changed region vids.
194
208
let mut changes = Vec :: new ( ) ;
195
209
for constraint in self . data . constraints . keys ( ) {
196
- let ( a_vid , a_region , b_vid , b_data ) = match * constraint {
210
+ match * constraint {
197
211
Constraint :: RegSubVar ( a_region, b_vid) => {
198
212
let b_data = var_values. value_mut ( b_vid) ;
199
- ( None , a_region, b_vid, b_data)
213
+
214
+ if self . expand_node ( a_region, b_vid, b_data) {
215
+ changes. push ( b_vid) ;
216
+ }
200
217
}
201
218
Constraint :: VarSubVar ( a_vid, b_vid) => match * var_values. value ( a_vid) {
202
219
VarValue :: ErrorValue => continue ,
220
+ VarValue :: Empty ( a_universe) => {
221
+ let b_data = var_values. value_mut ( b_vid) ;
222
+
223
+ let changed = ( || match * b_data {
224
+ VarValue :: Empty ( b_universe) => {
225
+ // Empty regions are ordered according to the universe
226
+ // they are associated with.
227
+ let ui = a_universe. min ( b_universe) ;
228
+
229
+ debug ! (
230
+ "Expanding value of {:?} \
231
+ from empty lifetime with universe {:?} \
232
+ to empty lifetime with universe {:?}",
233
+ b_vid, b_universe, ui
234
+ ) ;
235
+
236
+ * b_data = VarValue :: Empty ( ui) ;
237
+ true
238
+ }
239
+ VarValue :: Value ( cur_region) => {
240
+ let lub = match * cur_region {
241
+ ReLateBound ( ..) | ReErased => {
242
+ bug ! ( "cannot relate region: {:?}" , cur_region) ;
243
+ }
244
+
245
+ ReVar ( v_id) => {
246
+ span_bug ! (
247
+ self . var_infos[ v_id] . origin. span( ) ,
248
+ "lub_concrete_regions invoked with non-concrete regions: {:?}" ,
249
+ cur_region,
250
+ ) ;
251
+ }
252
+
253
+ ReStatic => {
254
+ // nothing lives longer than `'static`
255
+ self . tcx ( ) . lifetimes . re_static
256
+ }
257
+
258
+ ReEarlyBound ( _) | ReFree ( _) => {
259
+ // All empty regions are less than early-bound, free,
260
+ // and scope regions.
261
+ cur_region
262
+ }
263
+
264
+ ReEmpty ( b_ui) => {
265
+ // Empty regions are ordered according to the universe
266
+ // they are associated with.
267
+ let ui = a_universe. min ( b_ui) ;
268
+ self . tcx ( ) . mk_region ( ReEmpty ( ui) )
269
+ }
270
+
271
+ RePlaceholder ( placeholder) => {
272
+ // If the empty and placeholder regions are in the same universe,
273
+ // then the LUB is the Placeholder region (which is the cur_region).
274
+ // If they are not in the same universe, the LUB is the Static lifetime.
275
+ if a_universe == placeholder. universe {
276
+ cur_region
277
+ } else {
278
+ self . tcx ( ) . lifetimes . re_static
279
+ }
280
+ }
281
+ } ;
282
+
283
+ if lub == cur_region {
284
+ return false ;
285
+ }
286
+
287
+ debug ! (
288
+ "Expanding value of {:?} from {:?} to {:?}" ,
289
+ b_vid, cur_region, lub
290
+ ) ;
291
+
292
+ * b_data = VarValue :: Value ( lub) ;
293
+ true
294
+ }
295
+
296
+ VarValue :: ErrorValue => false ,
297
+ } ) ( ) ;
298
+
299
+ if changed {
300
+ changes. push ( b_vid) ;
301
+ }
302
+ match b_data {
303
+ VarValue :: Value ( Region ( Interned ( ReStatic , _) ) )
304
+ | VarValue :: ErrorValue => ( ) ,
305
+ _ => {
306
+ constraints[ a_vid] . push ( ( a_vid, b_vid) ) ;
307
+ constraints[ b_vid] . push ( ( a_vid, b_vid) ) ;
308
+ }
309
+ }
310
+ }
203
311
VarValue :: Value ( a_region) => {
204
312
let b_data = var_values. value_mut ( b_vid) ;
205
- ( Some ( a_vid) , a_region, b_vid, b_data)
313
+
314
+ if self . expand_node ( a_region, b_vid, b_data) {
315
+ changes. push ( b_vid) ;
316
+ }
317
+ match b_data {
318
+ VarValue :: Value ( Region ( Interned ( ReStatic , _) ) )
319
+ | VarValue :: ErrorValue => ( ) ,
320
+ _ => {
321
+ constraints[ a_vid] . push ( ( a_vid, b_vid) ) ;
322
+ constraints[ b_vid] . push ( ( a_vid, b_vid) ) ;
323
+ }
324
+ }
206
325
}
207
326
} ,
208
327
Constraint :: RegSubReg ( ..) | Constraint :: VarSubReg ( ..) => {
209
328
// These constraints are checked after expansion
210
329
// is done, in `collect_errors`.
211
330
continue ;
212
331
}
213
- } ;
214
- if self . expand_node ( a_region, b_vid, b_data) {
215
- changes. push ( b_vid) ;
216
- }
217
- if let Some ( a_vid) = a_vid {
218
- match b_data {
219
- VarValue :: Value ( Region ( Interned ( ReStatic , _) ) ) | VarValue :: ErrorValue => ( ) ,
220
- _ => {
221
- constraints[ a_vid] . push ( ( a_vid, b_vid) ) ;
222
- constraints[ b_vid] . push ( ( a_vid, b_vid) ) ;
223
- }
224
- }
225
332
}
226
333
}
227
334
@@ -242,6 +349,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
242
349
}
243
350
}
244
351
352
+ /// Expands the value of the region represented with `b_vid` with current
353
+ /// value `b_data` to the lub of `b_data` and `a_region`. The corresponds
354
+ /// with the constraint `'?b: 'a` (`'a <: '?b`), where `'a` is some known
355
+ /// region and `'?b` is some region variable.
245
356
fn expand_node (
246
357
& self ,
247
358
a_region : Region < ' tcx > ,
@@ -263,6 +374,55 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
263
374
}
264
375
265
376
match * b_data {
377
+ VarValue :: Empty ( empty_ui) => {
378
+ let lub = match * a_region {
379
+ ReLateBound ( ..) | ReErased => {
380
+ bug ! ( "cannot relate region: {:?}" , a_region) ;
381
+ }
382
+
383
+ ReVar ( v_id) => {
384
+ span_bug ! (
385
+ self . var_infos[ v_id] . origin. span( ) ,
386
+ "expand_node invoked with non-concrete regions: {:?}" ,
387
+ a_region,
388
+ ) ;
389
+ }
390
+
391
+ ReStatic => {
392
+ // nothing lives longer than `'static`
393
+ self . tcx ( ) . lifetimes . re_static
394
+ }
395
+
396
+ ReEarlyBound ( _) | ReFree ( _) => {
397
+ // All empty regions are less than early-bound, free,
398
+ // and scope regions.
399
+ a_region
400
+ }
401
+
402
+ ReEmpty ( a_ui) => {
403
+ // Empty regions are ordered according to the universe
404
+ // they are associated with.
405
+ let ui = a_ui. min ( empty_ui) ;
406
+ self . tcx ( ) . mk_region ( ReEmpty ( ui) )
407
+ }
408
+
409
+ RePlaceholder ( placeholder) => {
410
+ // If this empty region is from a universe that can
411
+ // name the placeholder, then the placeholder is
412
+ // larger; otherwise, the only ancestor is `'static`.
413
+ if empty_ui. can_name ( placeholder. universe ) {
414
+ self . tcx ( ) . mk_region ( RePlaceholder ( placeholder) )
415
+ } else {
416
+ self . tcx ( ) . lifetimes . re_static
417
+ }
418
+ }
419
+ } ;
420
+
421
+ debug ! ( "Expanding value of {:?} from empty lifetime to {:?}" , b_vid, lub) ;
422
+
423
+ * b_data = VarValue :: Value ( lub) ;
424
+ true
425
+ }
266
426
VarValue :: Value ( cur_region) => {
267
427
// This is a specialized version of the `lub_concrete_regions`
268
428
// check below for a common case, here purely as an
@@ -508,7 +668,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
508
668
509
669
for ( node_vid, value) in var_data. values . iter_enumerated ( ) {
510
670
match * value {
511
- VarValue :: Value ( _) => { /* Inference successful */ }
671
+ VarValue :: Empty ( _ ) | VarValue :: Value ( _) => { /* Inference successful */ }
512
672
VarValue :: ErrorValue => {
513
673
// Inference impossible: this value contains
514
674
// inconsistent constraints.
@@ -876,6 +1036,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
876
1036
) -> ty:: Region < ' tcx > {
877
1037
let result = match * r {
878
1038
ty:: ReVar ( rid) => match self . values [ rid] {
1039
+ VarValue :: Empty ( vid_universe) => tcx. mk_region ( ty:: ReEmpty ( vid_universe) ) ,
879
1040
VarValue :: Value ( r) => r,
880
1041
VarValue :: ErrorValue => tcx. lifetimes . re_static ,
881
1042
} ,
0 commit comments