1 //! Lexical region resolution.
2
3 use crate::infer::region_constraints::Constraint;
4 use crate::infer::region_constraints::GenericKind;
5 use crate::infer::region_constraints::RegionConstraintData;
6 use crate::infer::region_constraints::VarInfos;
7 use crate::infer::region_constraints::VerifyBound;
8 use crate::infer::RegionRelations;
9 use crate::infer::RegionVariableOrigin;
10 use crate::infer::SubregionOrigin;
11 use rustc_data_structures::fx::FxHashSet;
12 use rustc_data_structures::graph::implementation::{
13 Direction, Graph, NodeIndex, INCOMING, OUTGOING,
14 };
15 use rustc_data_structures::intern::Interned;
16 use rustc_index::{IndexSlice, IndexVec};
17 use rustc_middle::ty::fold::TypeFoldable;
18 use rustc_middle::ty::PlaceholderRegion;
19 use rustc_middle::ty::{self, Ty, TyCtxt};
20 use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic};
21 use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
22 use rustc_middle::ty::{Region, RegionVid};
23 use rustc_span::Span;
24 use std::fmt;
25
26 use super::outlives::test_type_match;
27
28 /// This function performs lexical region resolution given a complete
29 /// set of constraints and variable origins. It performs a fixed-point
30 /// iteration to find region values which satisfy all constraints,
31 /// assuming such values can be found. It returns the final values of
32 /// all the variables as well as a set of errors that must be reported.
33 #[instrument(level = "debug", skip(region_rels, var_infos, data))]
resolve<'tcx>( param_env: ty::ParamEnv<'tcx>, region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>)34 pub(crate) fn resolve<'tcx>(
35 param_env: ty::ParamEnv<'tcx>,
36 region_rels: &RegionRelations<'_, 'tcx>,
37 var_infos: VarInfos,
38 data: RegionConstraintData<'tcx>,
39 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
40 let mut errors = vec![];
41 let mut resolver = LexicalResolver { param_env, region_rels, var_infos, data };
42 let values = resolver.infer_variable_values(&mut errors);
43 (values, errors)
44 }
45
46 /// Contains the result of lexical region resolution. Offers methods
47 /// to lookup up the final value of a region variable.
48 #[derive(Clone)]
49 pub struct LexicalRegionResolutions<'tcx> {
50 pub(crate) values: IndexVec<RegionVid, VarValue<'tcx>>,
51 }
52
53 #[derive(Copy, Clone, Debug)]
54 pub(crate) enum VarValue<'tcx> {
55 /// Empty lifetime is for data that is never accessed. We tag the
56 /// empty lifetime with a universe -- the idea is that we don't
57 /// want `exists<'a> { forall<'b> { 'b: 'a } }` to be satisfiable.
58 /// Therefore, the `'empty` in a universe `U` is less than all
59 /// regions visible from `U`, but not less than regions not visible
60 /// from `U`.
61 Empty(ty::UniverseIndex),
62 Value(Region<'tcx>),
63 ErrorValue,
64 }
65
66 #[derive(Clone, Debug)]
67 pub enum RegionResolutionError<'tcx> {
68 /// `ConcreteFailure(o, a, b)`:
69 ///
70 /// `o` requires that `a <= b`, but this does not hold
71 ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
72
73 /// `GenericBoundFailure(p, s, a)`:
74 ///
75 /// The parameter/associated-type `p` must be known to outlive the lifetime
76 /// `a` (but none of the known bounds are sufficient).
77 GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>),
78
79 /// `SubSupConflict(v, v_origin, sub_origin, sub_r, sup_origin, sup_r)`:
80 ///
81 /// Could not infer a value for `v` (which has origin `v_origin`)
82 /// because `sub_r <= v` (due to `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and
83 /// `sub_r <= sup_r` does not hold.
84 SubSupConflict(
85 RegionVid,
86 RegionVariableOrigin,
87 SubregionOrigin<'tcx>,
88 Region<'tcx>,
89 SubregionOrigin<'tcx>,
90 Region<'tcx>,
91 Vec<Span>, // All the influences on a given value that didn't meet its constraints.
92 ),
93
94 /// Indicates a `'b: 'a` constraint where `'a` is in a universe that
95 /// cannot name the placeholder `'b`.
96 UpperBoundUniverseConflict(
97 RegionVid,
98 RegionVariableOrigin,
99 ty::UniverseIndex, // the universe index of the region variable
100 SubregionOrigin<'tcx>, // cause of the constraint
101 Region<'tcx>, // the placeholder `'b`
102 ),
103 }
104
105 impl<'tcx> RegionResolutionError<'tcx> {
origin(&self) -> &SubregionOrigin<'tcx>106 pub fn origin(&self) -> &SubregionOrigin<'tcx> {
107 match self {
108 RegionResolutionError::ConcreteFailure(origin, _, _)
109 | RegionResolutionError::GenericBoundFailure(origin, _, _)
110 | RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _)
111 | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin,
112 }
113 }
114 }
115
116 struct RegionAndOrigin<'tcx> {
117 region: Region<'tcx>,
118 origin: SubregionOrigin<'tcx>,
119 }
120
121 type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;
122
123 struct LexicalResolver<'cx, 'tcx> {
124 param_env: ty::ParamEnv<'tcx>,
125 region_rels: &'cx RegionRelations<'cx, 'tcx>,
126 var_infos: VarInfos,
127 data: RegionConstraintData<'tcx>,
128 }
129
130 impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
tcx(&self) -> TyCtxt<'tcx>131 fn tcx(&self) -> TyCtxt<'tcx> {
132 self.region_rels.tcx
133 }
134
infer_variable_values( &mut self, errors: &mut Vec<RegionResolutionError<'tcx>>, ) -> LexicalRegionResolutions<'tcx>135 fn infer_variable_values(
136 &mut self,
137 errors: &mut Vec<RegionResolutionError<'tcx>>,
138 ) -> LexicalRegionResolutions<'tcx> {
139 let mut var_data = self.construct_var_data();
140
141 if cfg!(debug_assertions) {
142 self.dump_constraints();
143 }
144
145 self.expansion(&mut var_data);
146 self.collect_errors(&mut var_data, errors);
147 self.collect_var_errors(&var_data, errors);
148 var_data
149 }
150
num_vars(&self) -> usize151 fn num_vars(&self) -> usize {
152 self.var_infos.len()
153 }
154
155 /// Initially, the value for all variables is set to `'empty`, the
156 /// empty region. The `expansion` phase will grow this larger.
construct_var_data(&self) -> LexicalRegionResolutions<'tcx>157 fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
158 LexicalRegionResolutions {
159 values: IndexVec::from_fn_n(
160 |vid| {
161 let vid_universe = self.var_infos[vid].universe;
162 VarValue::Empty(vid_universe)
163 },
164 self.num_vars(),
165 ),
166 }
167 }
168
169 #[instrument(level = "debug", skip(self))]
dump_constraints(&self)170 fn dump_constraints(&self) {
171 for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {
172 debug!("Constraint {} => {:?}", idx, constraint);
173 }
174 }
175
176 /// Gets the LUb of a given region and the empty region
lub_empty(&self, a_region: Region<'tcx>) -> Result<Region<'tcx>, PlaceholderRegion>177 fn lub_empty(&self, a_region: Region<'tcx>) -> Result<Region<'tcx>, PlaceholderRegion> {
178 match *a_region {
179 ReLateBound(..) | ReErased => {
180 bug!("cannot relate region: {:?}", a_region);
181 }
182
183 ReVar(v_id) => {
184 span_bug!(
185 self.var_infos[v_id].origin.span(),
186 "lub invoked with non-concrete regions: {:?}",
187 a_region,
188 );
189 }
190
191 ReStatic => {
192 // nothing lives longer than `'static`
193 Ok(self.tcx().lifetimes.re_static)
194 }
195
196 ReError(_) => Ok(a_region),
197
198 ReEarlyBound(_) | ReFree(_) => {
199 // All empty regions are less than early-bound, free,
200 // and scope regions.
201 Ok(a_region)
202 }
203
204 RePlaceholder(placeholder) => Err(placeholder),
205 }
206 }
207
expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>)208 fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
209 // In the first pass, we expand region vids according to constraints we
210 // have previously found. In the second pass, we loop through the region
211 // vids we expanded and expand *across* region vids (effectively
212 // "expanding" new `RegSubVar` constraints).
213
214 // Tracks the `VarSubVar` constraints generated for each region vid. We
215 // later use this to expand across vids.
216 let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values);
217 // Tracks the changed region vids.
218 let mut changes = Vec::new();
219 for constraint in self.data.constraints.keys() {
220 match *constraint {
221 Constraint::RegSubVar(a_region, b_vid) => {
222 let b_data = var_values.value_mut(b_vid);
223
224 if self.expand_node(a_region, b_vid, b_data) {
225 changes.push(b_vid);
226 }
227 }
228 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
229 VarValue::ErrorValue => continue,
230 VarValue::Empty(a_universe) => {
231 let b_data = var_values.value_mut(b_vid);
232
233 let changed = match *b_data {
234 VarValue::Empty(b_universe) => {
235 // Empty regions are ordered according to the universe
236 // they are associated with.
237 let ui = a_universe.min(b_universe);
238
239 debug!(
240 "Expanding value of {:?} \
241 from empty lifetime with universe {:?} \
242 to empty lifetime with universe {:?}",
243 b_vid, b_universe, ui
244 );
245
246 *b_data = VarValue::Empty(ui);
247 true
248 }
249 VarValue::Value(cur_region) => {
250 let lub = match self.lub_empty(cur_region) {
251 Ok(r) => r,
252 // If the empty and placeholder regions are in the same universe,
253 // then the LUB is the Placeholder region (which is the cur_region).
254 // If they are not in the same universe, the LUB is the Static lifetime.
255 Err(placeholder) if a_universe == placeholder.universe => {
256 cur_region
257 }
258 Err(_) => self.tcx().lifetimes.re_static,
259 };
260
261 if lub == cur_region {
262 false
263 } else {
264 debug!(
265 "Expanding value of {:?} from {:?} to {:?}",
266 b_vid, cur_region, lub
267 );
268
269 *b_data = VarValue::Value(lub);
270 true
271 }
272 }
273
274 VarValue::ErrorValue => false,
275 };
276
277 if changed {
278 changes.push(b_vid);
279 }
280 match b_data {
281 VarValue::Value(Region(Interned(ReStatic, _)))
282 | VarValue::ErrorValue => (),
283 _ => {
284 constraints[a_vid].push((a_vid, b_vid));
285 constraints[b_vid].push((a_vid, b_vid));
286 }
287 }
288 }
289 VarValue::Value(a_region) => {
290 let b_data = var_values.value_mut(b_vid);
291
292 if self.expand_node(a_region, b_vid, b_data) {
293 changes.push(b_vid);
294 }
295 match b_data {
296 VarValue::Value(Region(Interned(ReStatic, _)))
297 | VarValue::ErrorValue => (),
298 _ => {
299 constraints[a_vid].push((a_vid, b_vid));
300 constraints[b_vid].push((a_vid, b_vid));
301 }
302 }
303 }
304 },
305 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
306 // These constraints are checked after expansion
307 // is done, in `collect_errors`.
308 continue;
309 }
310 }
311 }
312
313 while let Some(vid) = changes.pop() {
314 constraints[vid].retain(|&(a_vid, b_vid)| {
315 let VarValue::Value(a_region) = *var_values.value(a_vid) else {
316 return false;
317 };
318 let b_data = var_values.value_mut(b_vid);
319 if self.expand_node(a_region, b_vid, b_data) {
320 changes.push(b_vid);
321 }
322 !matches!(
323 b_data,
324 VarValue::Value(Region(Interned(ReStatic, _))) | VarValue::ErrorValue
325 )
326 });
327 }
328 }
329
330 /// Expands the value of the region represented with `b_vid` with current
331 /// value `b_data` to the lub of `b_data` and `a_region`. The corresponds
332 /// with the constraint `'?b: 'a` (`'a <: '?b`), where `'a` is some known
333 /// region and `'?b` is some region variable.
expand_node( &self, a_region: Region<'tcx>, b_vid: RegionVid, b_data: &mut VarValue<'tcx>, ) -> bool334 fn expand_node(
335 &self,
336 a_region: Region<'tcx>,
337 b_vid: RegionVid,
338 b_data: &mut VarValue<'tcx>,
339 ) -> bool {
340 debug!("expand_node({:?}, {:?} == {:?})", a_region, b_vid, b_data);
341
342 match *b_data {
343 VarValue::Empty(empty_ui) => {
344 let lub = match self.lub_empty(a_region) {
345 Ok(r) => r,
346 // If this empty region is from a universe that can
347 // name the placeholder, then the placeholder is
348 // larger; otherwise, the only ancestor is `'static`.
349 Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
350 ty::Region::new_placeholder(self.tcx(), placeholder)
351 }
352 Err(_) => self.tcx().lifetimes.re_static,
353 };
354
355 debug!("Expanding value of {:?} from empty lifetime to {:?}", b_vid, lub);
356
357 *b_data = VarValue::Value(lub);
358 true
359 }
360 VarValue::Value(cur_region) => {
361 // This is a specialized version of the `lub_concrete_regions`
362 // check below for a common case, here purely as an
363 // optimization.
364 let b_universe = self.var_infos[b_vid].universe;
365
366 let mut lub = self.lub_concrete_regions(a_region, cur_region);
367 if lub == cur_region {
368 return false;
369 }
370
371 // Watch out for `'b: !1` relationships, where the
372 // universe of `'b` can't name the placeholder `!1`. In
373 // that case, we have to grow `'b` to be `'static` for the
374 // relationship to hold. This is obviously a kind of sub-optimal
375 // choice -- in the future, when we incorporate a knowledge
376 // of the parameter environment, we might be able to find a
377 // tighter bound than `'static`.
378 //
379 // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
380 if let ty::RePlaceholder(p) = *lub && b_universe.cannot_name(p.universe) {
381 lub = self.tcx().lifetimes.re_static;
382 }
383
384 debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
385
386 *b_data = VarValue::Value(lub);
387 true
388 }
389
390 VarValue::ErrorValue => false,
391 }
392 }
393
394 /// True if `a <= b`.
sub_region_values(&self, a: VarValue<'tcx>, b: VarValue<'tcx>) -> bool395 fn sub_region_values(&self, a: VarValue<'tcx>, b: VarValue<'tcx>) -> bool {
396 match (a, b) {
397 // Error region is `'static`
398 (VarValue::ErrorValue, _) | (_, VarValue::ErrorValue) => return true,
399 (VarValue::Empty(a_ui), VarValue::Empty(b_ui)) => {
400 // Empty regions are ordered according to the universe
401 // they are associated with.
402 a_ui.min(b_ui) == b_ui
403 }
404 (VarValue::Value(a), VarValue::Empty(_)) => {
405 match *a {
406 // this is always on an error path,
407 // so it doesn't really matter if it's shorter or longer than an empty region
408 ReError(_) => false,
409
410 ReLateBound(..) | ReErased => {
411 bug!("cannot relate region: {:?}", a);
412 }
413
414 ReVar(v_id) => {
415 span_bug!(
416 self.var_infos[v_id].origin.span(),
417 "lub_concrete_regions invoked with non-concrete region: {:?}",
418 a
419 );
420 }
421
422 ReStatic | ReEarlyBound(_) | ReFree(_) => {
423 // nothing lives longer than `'static`
424
425 // All empty regions are less than early-bound, free,
426 // and scope regions.
427
428 false
429 }
430
431 RePlaceholder(_) => {
432 // The LUB is either `a` or `'static`
433 false
434 }
435 }
436 }
437 (VarValue::Empty(a_ui), VarValue::Value(b)) => {
438 match *b {
439 // this is always on an error path,
440 // so it doesn't really matter if it's shorter or longer than an empty region
441 ReError(_) => false,
442
443 ReLateBound(..) | ReErased => {
444 bug!("cannot relate region: {:?}", b);
445 }
446
447 ReVar(v_id) => {
448 span_bug!(
449 self.var_infos[v_id].origin.span(),
450 "lub_concrete_regions invoked with non-concrete regions: {:?}",
451 b
452 );
453 }
454
455 ReStatic | ReEarlyBound(_) | ReFree(_) => {
456 // nothing lives longer than `'static`
457 // All empty regions are less than early-bound, free,
458 // and scope regions.
459 true
460 }
461
462 RePlaceholder(placeholder) => {
463 // If this empty region is from a universe that can
464 // name the placeholder, then the placeholder is
465 // larger; otherwise, the only ancestor is `'static`.
466 return a_ui.can_name(placeholder.universe);
467 }
468 }
469 }
470 (VarValue::Value(a), VarValue::Value(b)) => self.sub_concrete_regions(a, b),
471 }
472 }
473
474 /// True if `a <= b`, but not defined over inference variables.
475 #[instrument(level = "trace", skip(self))]
sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool476 fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
477 let tcx = self.tcx();
478 let sub_free_regions = |r1, r2| self.region_rels.free_regions.sub_free_regions(tcx, r1, r2);
479
480 // Check for the case where we know that `'b: 'static` -- in that case,
481 // `a <= b` for all `a`.
482 let b_free_or_static = b.is_free_or_static();
483 if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) {
484 return true;
485 }
486
487 // If both `a` and `b` are free, consult the declared
488 // relationships. Note that this can be more precise than the
489 // `lub` relationship defined below, since sometimes the "lub"
490 // is actually the `postdom_upper_bound` (see
491 // `TransitiveRelation` for more details).
492 let a_free_or_static = a.is_free_or_static();
493 if a_free_or_static && b_free_or_static {
494 return sub_free_regions(a, b);
495 }
496
497 // For other cases, leverage the LUB code to find the LUB and
498 // check if it is equal to `b`.
499 self.lub_concrete_regions(a, b) == b
500 }
501
502 /// Returns the least-upper-bound of `a` and `b`; i.e., the
503 /// smallest region `c` such that `a <= c` and `b <= c`.
504 ///
505 /// Neither `a` nor `b` may be an inference variable (hence the
506 /// term "concrete regions").
507 #[instrument(level = "trace", skip(self), ret)]
lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx>508 fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
509 match (*a, *b) {
510 (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReErased, _) | (_, ReErased) => {
511 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
512 }
513
514 (ReVar(v_id), _) | (_, ReVar(v_id)) => {
515 span_bug!(
516 self.var_infos[v_id].origin.span(),
517 "lub_concrete_regions invoked with non-concrete \
518 regions: {:?}, {:?}",
519 a,
520 b
521 );
522 }
523
524 (ReError(_), _) => a,
525
526 (_, ReError(_)) => b,
527
528 (ReStatic, _) | (_, ReStatic) => {
529 // nothing lives longer than `'static`
530 self.tcx().lifetimes.re_static
531 }
532
533 (ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => {
534 self.region_rels.lub_free_regions(a, b)
535 }
536
537 // For these types, we cannot define any additional
538 // relationship:
539 (RePlaceholder(..), _) | (_, RePlaceholder(..)) => {
540 if a == b {
541 a
542 } else {
543 self.tcx().lifetimes.re_static
544 }
545 }
546 }
547 }
548
549 /// After expansion is complete, go and check upper bounds (i.e.,
550 /// cases where the region cannot grow larger than a fixed point)
551 /// and check that they are satisfied.
552 #[instrument(skip(self, var_data, errors))]
collect_errors( &self, var_data: &mut LexicalRegionResolutions<'tcx>, errors: &mut Vec<RegionResolutionError<'tcx>>, )553 fn collect_errors(
554 &self,
555 var_data: &mut LexicalRegionResolutions<'tcx>,
556 errors: &mut Vec<RegionResolutionError<'tcx>>,
557 ) {
558 for (constraint, origin) in &self.data.constraints {
559 debug!(?constraint, ?origin);
560 match *constraint {
561 Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
562 // Expansion will ensure that these constraints hold. Ignore.
563 }
564
565 Constraint::RegSubReg(sub, sup) => {
566 if self.sub_concrete_regions(sub, sup) {
567 continue;
568 }
569
570 debug!(
571 "region error at {:?}: \
572 cannot verify that {:?} <= {:?}",
573 origin, sub, sup
574 );
575
576 errors.push(RegionResolutionError::ConcreteFailure(
577 (*origin).clone(),
578 sub,
579 sup,
580 ));
581 }
582
583 Constraint::VarSubReg(a_vid, b_region) => {
584 let a_data = var_data.value_mut(a_vid);
585 debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data, b_region);
586
587 let VarValue::Value(a_region) = *a_data else {
588 continue;
589 };
590
591 // Do not report these errors immediately:
592 // instead, set the variable value to error and
593 // collect them later.
594 if !self.sub_concrete_regions(a_region, b_region) {
595 debug!(
596 "region error at {:?}: \
597 cannot verify that {:?}={:?} <= {:?}",
598 origin, a_vid, a_region, b_region
599 );
600 *a_data = VarValue::ErrorValue;
601 }
602 }
603 }
604 }
605
606 for verify in &self.data.verifys {
607 debug!("collect_errors: verify={:?}", verify);
608 let sub = var_data.normalize(self.tcx(), verify.region);
609
610 let verify_kind_ty = verify.kind.to_ty(self.tcx());
611 let verify_kind_ty = var_data.normalize(self.tcx(), verify_kind_ty);
612 if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
613 continue;
614 }
615
616 debug!(
617 "collect_errors: region error at {:?}: \
618 cannot verify that {:?} <= {:?}",
619 verify.origin, verify.region, verify.bound
620 );
621
622 errors.push(RegionResolutionError::GenericBoundFailure(
623 verify.origin.clone(),
624 verify.kind,
625 sub,
626 ));
627 }
628 }
629
630 /// Go over the variables that were declared to be error variables
631 /// and create a `RegionResolutionError` for each of them.
collect_var_errors( &self, var_data: &LexicalRegionResolutions<'tcx>, errors: &mut Vec<RegionResolutionError<'tcx>>, )632 fn collect_var_errors(
633 &self,
634 var_data: &LexicalRegionResolutions<'tcx>,
635 errors: &mut Vec<RegionResolutionError<'tcx>>,
636 ) {
637 debug!("collect_var_errors, var_data = {:#?}", var_data.values);
638
639 // This is the best way that I have found to suppress
640 // duplicate and related errors. Basically we keep a set of
641 // flags for every node. Whenever an error occurs, we will
642 // walk some portion of the graph looking to find pairs of
643 // conflicting regions to report to the user. As we walk, we
644 // trip the flags from false to true, and if we find that
645 // we've already reported an error involving any particular
646 // node we just stop and don't report the current error. The
647 // idea is to report errors that derive from independent
648 // regions of the graph, but not those that derive from
649 // overlapping locations.
650 let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
651
652 // Only construct the graph when necessary, because it's moderately
653 // expensive.
654 let mut graph = None;
655
656 for (node_vid, value) in var_data.values.iter_enumerated() {
657 match *value {
658 VarValue::Empty(_) | VarValue::Value(_) => { /* Inference successful */ }
659 VarValue::ErrorValue => {
660 // Inference impossible: this value contains
661 // inconsistent constraints.
662 //
663 // I think that in this case we should report an
664 // error now -- unlike the case above, we can't
665 // wait to see whether the user needs the result
666 // of this variable. The reason is that the mere
667 // existence of this variable implies that the
668 // region graph is inconsistent, whether or not it
669 // is used.
670 //
671 // For example, we may have created a region
672 // variable that is the GLB of two other regions
673 // which do not have a GLB. Even if that variable
674 // is not used, it implies that those two regions
675 // *should* have a GLB.
676 //
677 // At least I think this is true. It may be that
678 // the mere existence of a conflict in a region
679 // variable that is not used is not a problem, so
680 // if this rule starts to create problems we'll
681 // have to revisit this portion of the code and
682 // think hard about it. =) -- nikomatsakis
683
684 // Obtain the spans for all the places that can
685 // influence the constraints on this value for
686 // richer diagnostics in `static_impl_trait`.
687
688 let g = graph.get_or_insert_with(|| self.construct_graph());
689 self.collect_error_for_expanding_node(g, &mut dup_vec, node_vid, errors);
690 }
691 }
692 }
693 }
694
construct_graph(&self) -> RegionGraph<'tcx>695 fn construct_graph(&self) -> RegionGraph<'tcx> {
696 let num_vars = self.num_vars();
697
698 let mut graph = Graph::new();
699
700 for _ in 0..num_vars {
701 graph.add_node(());
702 }
703
704 // Issue #30438: two distinct dummy nodes, one for incoming
705 // edges (dummy_source) and another for outgoing edges
706 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
707 // dummy node leads one to think (erroneously) there exists a
708 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
709 let dummy_source = graph.add_node(());
710 let dummy_sink = graph.add_node(());
711
712 for constraint in self.data.constraints.keys() {
713 match *constraint {
714 Constraint::VarSubVar(a_id, b_id) => {
715 graph.add_edge(
716 NodeIndex(a_id.index() as usize),
717 NodeIndex(b_id.index() as usize),
718 *constraint,
719 );
720 }
721 Constraint::RegSubVar(_, b_id) => {
722 graph.add_edge(dummy_source, NodeIndex(b_id.index() as usize), *constraint);
723 }
724 Constraint::VarSubReg(a_id, _) => {
725 graph.add_edge(NodeIndex(a_id.index() as usize), dummy_sink, *constraint);
726 }
727 Constraint::RegSubReg(..) => {
728 // this would be an edge from `dummy_source` to
729 // `dummy_sink`; just ignore it.
730 }
731 }
732 }
733
734 graph
735 }
736
collect_error_for_expanding_node( &self, graph: &RegionGraph<'tcx>, dup_vec: &mut IndexSlice<RegionVid, Option<RegionVid>>, node_idx: RegionVid, errors: &mut Vec<RegionResolutionError<'tcx>>, )737 fn collect_error_for_expanding_node(
738 &self,
739 graph: &RegionGraph<'tcx>,
740 dup_vec: &mut IndexSlice<RegionVid, Option<RegionVid>>,
741 node_idx: RegionVid,
742 errors: &mut Vec<RegionResolutionError<'tcx>>,
743 ) {
744 // Errors in expanding nodes result from a lower-bound that is
745 // not contained by an upper-bound.
746 let (mut lower_bounds, lower_vid_bounds, lower_dup) =
747 self.collect_bounding_regions(graph, node_idx, INCOMING, Some(dup_vec));
748 let (mut upper_bounds, _, upper_dup) =
749 self.collect_bounding_regions(graph, node_idx, OUTGOING, Some(dup_vec));
750
751 if lower_dup || upper_dup {
752 return;
753 }
754
755 // We place free regions first because we are special casing
756 // SubSupConflict(ReFree, ReFree) when reporting error, and so
757 // the user will more likely get a specific suggestion.
758 fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
759 match *x.region {
760 ReEarlyBound(_) => 0,
761 ReFree(_) => 1,
762 _ => 2,
763 }
764 }
765 lower_bounds.sort_by_key(region_order_key);
766 upper_bounds.sort_by_key(region_order_key);
767
768 let node_universe = self.var_infos[node_idx].universe;
769
770 for lower_bound in &lower_bounds {
771 let effective_lower_bound = if let ty::RePlaceholder(p) = *lower_bound.region {
772 if node_universe.cannot_name(p.universe) {
773 self.tcx().lifetimes.re_static
774 } else {
775 lower_bound.region
776 }
777 } else {
778 lower_bound.region
779 };
780
781 for upper_bound in &upper_bounds {
782 if !self.sub_concrete_regions(effective_lower_bound, upper_bound.region) {
783 let origin = self.var_infos[node_idx].origin;
784 debug!(
785 "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
786 sup: {:?}",
787 origin, node_idx, lower_bound.region, upper_bound.region
788 );
789
790 errors.push(RegionResolutionError::SubSupConflict(
791 node_idx,
792 origin,
793 lower_bound.origin.clone(),
794 lower_bound.region,
795 upper_bound.origin.clone(),
796 upper_bound.region,
797 vec![],
798 ));
799 return;
800 }
801 }
802 }
803
804 // If we have a scenario like `exists<'a> { forall<'b> { 'b:
805 // 'a } }`, we wind up without any lower-bound -- all we have
806 // are placeholders as upper bounds, but the universe of the
807 // variable `'a`, or some variable that `'a` has to outlive, doesn't
808 // permit those placeholders.
809 //
810 // We only iterate to find the min, which means it doesn't cause reproducibility issues
811 #[allow(rustc::potential_query_instability)]
812 let min_universe = lower_vid_bounds
813 .into_iter()
814 .map(|vid| self.var_infos[vid].universe)
815 .min()
816 .expect("lower_vid_bounds should at least include `node_idx`");
817
818 for upper_bound in &upper_bounds {
819 if let ty::RePlaceholder(p) = *upper_bound.region {
820 if min_universe.cannot_name(p.universe) {
821 let origin = self.var_infos[node_idx].origin;
822 errors.push(RegionResolutionError::UpperBoundUniverseConflict(
823 node_idx,
824 origin,
825 min_universe,
826 upper_bound.origin.clone(),
827 upper_bound.region,
828 ));
829 return;
830 }
831 }
832 }
833
834 // Errors in earlier passes can yield error variables without
835 // resolution errors here; delay ICE in favor of those errors.
836 self.tcx().sess.delay_span_bug(
837 self.var_infos[node_idx].origin.span(),
838 format!(
839 "collect_error_for_expanding_node() could not find \
840 error for var {:?} in universe {:?}, lower_bounds={:#?}, \
841 upper_bounds={:#?}",
842 node_idx, node_universe, lower_bounds, upper_bounds
843 ),
844 );
845 }
846
847 /// Collects all regions that "bound" the variable `orig_node_idx` in the
848 /// given direction.
849 ///
850 /// If `dup_vec` is `Some` it's used to track duplicates between successive
851 /// calls of this function.
852 ///
853 /// The return tuple fields are:
854 /// - a list of all concrete regions bounding the given region.
855 /// - the set of all region variables bounding the given region.
856 /// - a `bool` that's true if the returned region variables overlap with
857 /// those returned by a previous call for another region.
collect_bounding_regions( &self, graph: &RegionGraph<'tcx>, orig_node_idx: RegionVid, dir: Direction, mut dup_vec: Option<&mut IndexSlice<RegionVid, Option<RegionVid>>>, ) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool)858 fn collect_bounding_regions(
859 &self,
860 graph: &RegionGraph<'tcx>,
861 orig_node_idx: RegionVid,
862 dir: Direction,
863 mut dup_vec: Option<&mut IndexSlice<RegionVid, Option<RegionVid>>>,
864 ) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool) {
865 struct WalkState<'tcx> {
866 set: FxHashSet<RegionVid>,
867 stack: Vec<RegionVid>,
868 result: Vec<RegionAndOrigin<'tcx>>,
869 dup_found: bool,
870 }
871 let mut state = WalkState {
872 set: Default::default(),
873 stack: vec![orig_node_idx],
874 result: Vec::new(),
875 dup_found: false,
876 };
877 state.set.insert(orig_node_idx);
878
879 // to start off the process, walk the source node in the
880 // direction specified
881 process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
882
883 while let Some(node_idx) = state.stack.pop() {
884 // check whether we've visited this node on some previous walk
885 if let Some(dup_vec) = &mut dup_vec {
886 if dup_vec[node_idx].is_none() {
887 dup_vec[node_idx] = Some(orig_node_idx);
888 } else if dup_vec[node_idx] != Some(orig_node_idx) {
889 state.dup_found = true;
890 }
891
892 debug!(
893 "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
894 orig_node_idx, node_idx
895 );
896 }
897
898 process_edges(&self.data, &mut state, graph, node_idx, dir);
899 }
900
901 let WalkState { result, dup_found, set, .. } = state;
902 return (result, set, dup_found);
903
904 fn process_edges<'tcx>(
905 this: &RegionConstraintData<'tcx>,
906 state: &mut WalkState<'tcx>,
907 graph: &RegionGraph<'tcx>,
908 source_vid: RegionVid,
909 dir: Direction,
910 ) {
911 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
912
913 let source_node_index = NodeIndex(source_vid.index() as usize);
914 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
915 match edge.data {
916 Constraint::VarSubVar(from_vid, to_vid) => {
917 let opp_vid = if from_vid == source_vid { to_vid } else { from_vid };
918 if state.set.insert(opp_vid) {
919 state.stack.push(opp_vid);
920 }
921 }
922
923 Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => {
924 state.result.push(RegionAndOrigin {
925 region,
926 origin: this.constraints.get(&edge.data).unwrap().clone(),
927 });
928 }
929
930 Constraint::RegSubReg(..) => panic!(
931 "cannot reach reg-sub-reg edge in region inference \
932 post-processing"
933 ),
934 }
935 }
936 }
937 }
938
bound_is_met( &self, bound: &VerifyBound<'tcx>, var_values: &LexicalRegionResolutions<'tcx>, generic_ty: Ty<'tcx>, min: ty::Region<'tcx>, ) -> bool939 fn bound_is_met(
940 &self,
941 bound: &VerifyBound<'tcx>,
942 var_values: &LexicalRegionResolutions<'tcx>,
943 generic_ty: Ty<'tcx>,
944 min: ty::Region<'tcx>,
945 ) -> bool {
946 match bound {
947 VerifyBound::IfEq(verify_if_eq_b) => {
948 let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
949 match test_type_match::extract_verify_if_eq(
950 self.tcx(),
951 self.param_env,
952 &verify_if_eq_b,
953 generic_ty,
954 ) {
955 Some(r) => {
956 self.bound_is_met(&VerifyBound::OutlivedBy(r), var_values, generic_ty, min)
957 }
958
959 None => false,
960 }
961 }
962
963 VerifyBound::OutlivedBy(r) => {
964 let a = match *min {
965 ty::ReVar(rid) => var_values.values[rid],
966 _ => VarValue::Value(min),
967 };
968 let b = match **r {
969 ty::ReVar(rid) => var_values.values[rid],
970 _ => VarValue::Value(*r),
971 };
972 self.sub_region_values(a, b)
973 }
974
975 VerifyBound::IsEmpty => match *min {
976 ty::ReVar(rid) => match var_values.values[rid] {
977 VarValue::ErrorValue => false,
978 VarValue::Empty(_) => true,
979 VarValue::Value(_) => false,
980 },
981 _ => false,
982 },
983
984 VerifyBound::AnyBound(bs) => {
985 bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
986 }
987
988 VerifyBound::AllBounds(bs) => {
989 bs.iter().all(|b| self.bound_is_met(b, var_values, generic_ty, min))
990 }
991 }
992 }
993 }
994
995 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result996 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
997 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
998 }
999 }
1000
1001 impl<'tcx> LexicalRegionResolutions<'tcx> {
normalize<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T where T: TypeFoldable<TyCtxt<'tcx>>,1002 fn normalize<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
1003 where
1004 T: TypeFoldable<TyCtxt<'tcx>>,
1005 {
1006 tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r))
1007 }
1008
value(&self, rid: RegionVid) -> &VarValue<'tcx>1009 fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
1010 &self.values[rid]
1011 }
1012
value_mut(&mut self, rid: RegionVid) -> &mut VarValue<'tcx>1013 fn value_mut(&mut self, rid: RegionVid) -> &mut VarValue<'tcx> {
1014 &mut self.values[rid]
1015 }
1016
resolve_region( &self, tcx: TyCtxt<'tcx>, r: ty::Region<'tcx>, ) -> ty::Region<'tcx>1017 pub(crate) fn resolve_region(
1018 &self,
1019 tcx: TyCtxt<'tcx>,
1020 r: ty::Region<'tcx>,
1021 ) -> ty::Region<'tcx> {
1022 let result = match *r {
1023 ty::ReVar(rid) => match self.values[rid] {
1024 VarValue::Empty(_) => r,
1025 VarValue::Value(r) => r,
1026 VarValue::ErrorValue => tcx.lifetimes.re_static,
1027 },
1028 _ => r,
1029 };
1030 debug!("resolve_region({:?}) = {:?}", r, result);
1031 result
1032 }
1033 }
1034