Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f29c91b

Browse files
committed
Create VarValue::Empty
1 parent cc87d53 commit f29c91b

File tree

6 files changed

+191
-22
lines changed

6 files changed

+191
-22
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
109109
.iter()
110110
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
111111
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
112-
.unwrap_or(infcx.tcx.lifetimes.re_root_empty),
112+
.unwrap_or(infcx.tcx.lifetimes.re_erased),
113113
_ => region,
114114
});
115115

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

Lines changed: 181 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ pub struct LexicalRegionResolutions<'tcx> {
5151

5252
#[derive(Copy, Clone, Debug)]
5353
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),
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
},

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub fn trait_obligations<'a, 'tcx>(
101101
wf.normalize(infcx)
102102
}
103103

104+
#[instrument(skip(infcx), ret)]
104105
pub fn predicate_obligations<'a, 'tcx>(
105106
infcx: &InferCtxt<'a, 'tcx>,
106107
param_env: ty::ParamEnv<'tcx>,
@@ -440,6 +441,7 @@ impl<'tcx> WfPredicates<'tcx> {
440441
let param_env = self.param_env;
441442
let depth = self.recursion_depth;
442443
while let Some(arg) = walker.next() {
444+
debug!(?arg, ?self.out);
443445
let ty = match arg.unpack() {
444446
GenericArgKind::Type(ty) => ty,
445447

@@ -689,6 +691,8 @@ impl<'tcx> WfPredicates<'tcx> {
689691
));
690692
}
691693
}
694+
695+
debug!(?self.out);
692696
}
693697
}
694698

compiler/rustc_typeck/src/check/dropck.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
144144
let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
145145
let assumptions_in_impl_context = assumptions_in_impl_context.predicates;
146146

147+
debug!(?assumptions_in_impl_context, ?dtor_predicates.predicates);
148+
147149
let self_param_env = tcx.param_env(self_type_did);
148150

149151
// An earlier version of this code attempted to do this checking

compiler/rustc_typeck/src/check/wfcheck.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,6 +1816,7 @@ fn report_bivariance(
18161816
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
18171817
/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
18181818
/// aren't true.
1819+
#[instrument(level = "debug", skip(self))]
18191820
fn check_false_global_bounds(&mut self) {
18201821
let tcx = self.ocx.infcx.tcx;
18211822
let mut span = self.span;

compiler/rustc_typeck/src/collect.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,7 @@ pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir
18081808
None
18091809
}
18101810

1811+
#[instrument(level = "debug", skip(tcx))]
18111812
fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
18121813
use rustc_hir::Node::*;
18131814
use rustc_hir::*;
@@ -2038,8 +2039,8 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
20382039
/// Returns a list of type predicates for the definition with ID `def_id`, including inferred
20392040
/// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
20402041
/// inferred constraints concerning which regions outlive other regions.
2042+
#[instrument(level = "debug", skip(tcx))]
20412043
fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
2042-
debug!("predicates_defined_on({:?})", def_id);
20432044
let mut result = tcx.explicit_predicates_of(def_id);
20442045
debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,);
20452046
let inferred_outlives = tcx.inferred_outlives_of(def_id);

0 commit comments

Comments
 (0)