@@ -51,6 +51,13 @@ pub struct LexicalRegionResolutions<'tcx> {
5151
5252#[ derive( Copy , Clone , Debug ) ]
5353pub ( 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 ) ,
5461 Value ( Region < ' tcx > ) ,
5562 ErrorValue ,
5663}
@@ -117,7 +124,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
117124 & mut self ,
118125 errors : & mut Vec < RegionResolutionError < ' tcx > > ,
119126 ) -> LexicalRegionResolutions < ' tcx > {
120- let mut var_data = self . construct_var_data ( self . tcx ( ) ) ;
127+ let mut var_data = self . construct_var_data ( ) ;
121128
122129 if cfg ! ( debug_assertions) {
123130 self . dump_constraints ( ) ;
@@ -137,13 +144,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
137144
138145 /// Initially, the value for all variables is set to `'empty`, the
139146 /// 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 > {
141148 LexicalRegionResolutions {
142149 values : IndexVec :: from_fn_n (
143150 |vid| {
144151 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)
147153 } ,
148154 self . num_vars ( ) ,
149155 ) ,
@@ -190,38 +196,139 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
190196 }
191197
192198 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.
193206 let mut constraints = IndexVec :: from_elem_n ( Vec :: new ( ) , var_values. values . len ( ) ) ;
207+ // Tracks the changed region vids.
194208 let mut changes = Vec :: new ( ) ;
195209 for constraint in self . data . constraints . keys ( ) {
196- let ( a_vid , a_region , b_vid , b_data ) = match * constraint {
210+ match * constraint {
197211 Constraint :: RegSubVar ( a_region, b_vid) => {
198212 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+ }
200217 }
201218 Constraint :: VarSubVar ( a_vid, b_vid) => match * var_values. value ( a_vid) {
202219 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+ }
203311 VarValue :: Value ( a_region) => {
204312 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+ }
206325 }
207326 } ,
208327 Constraint :: RegSubReg ( ..) | Constraint :: VarSubReg ( ..) => {
209328 // These constraints are checked after expansion
210329 // is done, in `collect_errors`.
211330 continue ;
212331 }
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- }
225332 }
226333 }
227334
@@ -242,6 +349,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
242349 }
243350 }
244351
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.
245356 fn expand_node (
246357 & self ,
247358 a_region : Region < ' tcx > ,
@@ -263,6 +374,55 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
263374 }
264375
265376 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+ }
266426 VarValue :: Value ( cur_region) => {
267427 // This is a specialized version of the `lub_concrete_regions`
268428 // check below for a common case, here purely as an
@@ -508,7 +668,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
508668
509669 for ( node_vid, value) in var_data. values . iter_enumerated ( ) {
510670 match * value {
511- VarValue :: Value ( _) => { /* Inference successful */ }
671+ VarValue :: Empty ( _ ) | VarValue :: Value ( _) => { /* Inference successful */ }
512672 VarValue :: ErrorValue => {
513673 // Inference impossible: this value contains
514674 // inconsistent constraints.
@@ -876,6 +1036,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
8761036 ) -> ty:: Region < ' tcx > {
8771037 let result = match * r {
8781038 ty:: ReVar ( rid) => match self . values [ rid] {
1039+ VarValue :: Empty ( vid_universe) => tcx. mk_region ( ty:: ReEmpty ( vid_universe) ) ,
8791040 VarValue :: Value ( r) => r,
8801041 VarValue :: ErrorValue => tcx. lifetimes . re_static ,
8811042 } ,
0 commit comments