rustc_infer/infer/lexical_region_resolve/
mod.rs

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