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