1use std::fmt;
4
5use rustc_data_structures::fx::FxHashSet;
6use rustc_data_structures::graph::linked_graph::{
7    Direction, INCOMING, LinkedGraph, 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, ConstraintKind, GenericKind, RegionConstraintData, VarInfos, VerifyBound,
23};
24use crate::infer::{RegionRelations, RegionVariableOrigin, SubregionOrigin};
25
26#[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#[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(ty::UniverseIndex),
59    Value(Region<'tcx>),
60    ErrorValue,
61}
62
63#[derive(Clone, Debug)]
64pub enum RegionResolutionError<'tcx> {
65    ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
69
70    GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>),
75
76    SubSupConflict(
82        RegionVid,
83        RegionVariableOrigin,
84        SubregionOrigin<'tcx>,
85        Region<'tcx>,
86        SubregionOrigin<'tcx>,
87        Region<'tcx>,
88        Vec<Span>, ),
90
91    UpperBoundUniverseConflict(
94        RegionVid,
95        RegionVariableOrigin,
96        ty::UniverseIndex,     SubregionOrigin<'tcx>, Region<'tcx>,          ),
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> = LinkedGraph<(), 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        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    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        let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values);
188        let mut changes = Vec::new();
190        for (c, _) in &self.data.constraints {
191            match c.kind {
192                ConstraintKind::RegSubVar => {
193                    let sup_vid = c.sup.as_var();
194                    let sup_data = var_values.value_mut(sup_vid);
195
196                    if self.expand_node(c.sub, sup_vid, sup_data) {
197                        changes.push(sup_vid);
198                    }
199                }
200                ConstraintKind::VarSubVar => {
201                    let sub_vid = c.sub.as_var();
202                    let sup_vid = c.sup.as_var();
203                    match *var_values.value(sub_vid) {
204                        VarValue::ErrorValue => continue,
205                        VarValue::Empty(sub_universe) => {
206                            let sup_data = var_values.value_mut(sup_vid);
207
208                            let changed = match *sup_data {
209                                VarValue::Empty(sup_universe) => {
210                                    let ui = sub_universe.min(sup_universe);
213
214                                    debug!(
215                                        "Expanding value of {:?} \
216                                    from empty lifetime with universe {:?} \
217                                    to empty lifetime with universe {:?}",
218                                        sup_vid, sup_universe, ui
219                                    );
220
221                                    *sup_data = VarValue::Empty(ui);
222                                    true
223                                }
224                                VarValue::Value(cur_region) => {
225                                    match cur_region.kind() {
226                                        RePlaceholder(placeholder)
231                                            if !sub_universe.can_name(placeholder.universe) =>
232                                        {
233                                            let lub = self.tcx().lifetimes.re_static;
234                                            debug!(
235                                                "Expanding value of {:?} from {:?} to {:?}",
236                                                sup_vid, cur_region, lub
237                                            );
238
239                                            *sup_data = VarValue::Value(lub);
240                                            true
241                                        }
242
243                                        _ => false,
244                                    }
245                                }
246
247                                VarValue::ErrorValue => false,
248                            };
249
250                            if changed {
251                                changes.push(sup_vid);
252                            }
253                            match sup_data {
254                                VarValue::Value(Region(Interned(ReStatic, _)))
255                                | VarValue::ErrorValue => (),
256                                _ => {
257                                    constraints[sub_vid].push((sub_vid, sup_vid));
258                                    constraints[sup_vid].push((sub_vid, sup_vid));
259                                }
260                            }
261                        }
262                        VarValue::Value(sub_region) => {
263                            let sup_data = var_values.value_mut(sup_vid);
264
265                            if self.expand_node(sub_region, sup_vid, sup_data) {
266                                changes.push(sup_vid);
267                            }
268                            match sup_data {
269                                VarValue::Value(Region(Interned(ReStatic, _)))
270                                | VarValue::ErrorValue => (),
271                                _ => {
272                                    constraints[sub_vid].push((sub_vid, sup_vid));
273                                    constraints[sup_vid].push((sub_vid, sup_vid));
274                                }
275                            }
276                        }
277                    }
278                }
279                ConstraintKind::RegSubReg | ConstraintKind::VarSubReg => {
280                    continue;
283                }
284            }
285        }
286
287        while let Some(vid) = changes.pop() {
288            constraints[vid].retain(|&(a_vid, b_vid)| {
289                let VarValue::Value(a_region) = *var_values.value(a_vid) else {
290                    return false;
291                };
292                let b_data = var_values.value_mut(b_vid);
293                if self.expand_node(a_region, b_vid, b_data) {
294                    changes.push(b_vid);
295                }
296                !matches!(
297                    b_data,
298                    VarValue::Value(Region(Interned(ReStatic, _))) | VarValue::ErrorValue
299                )
300            });
301        }
302    }
303
304    fn expand_node(
309        &self,
310        a_region: Region<'tcx>,
311        b_vid: RegionVid,
312        b_data: &mut VarValue<'tcx>,
313    ) -> bool {
314        debug!("expand_node({:?}, {:?} == {:?})", a_region, b_vid, b_data);
315
316        match *b_data {
317            VarValue::Empty(empty_ui) => {
318                let lub = match a_region.kind() {
319                    RePlaceholder(placeholder) => {
320                        if empty_ui.can_name(placeholder.universe) {
324                            ty::Region::new_placeholder(self.tcx(), placeholder)
325                        } else {
326                            self.tcx().lifetimes.re_static
327                        }
328                    }
329
330                    _ => a_region,
331                };
332
333                debug!("Expanding value of {:?} from empty lifetime to {:?}", b_vid, lub);
334
335                *b_data = VarValue::Value(lub);
336                true
337            }
338            VarValue::Value(cur_region) => {
339                let b_universe = self.var_infos[b_vid].universe;
343
344                let mut lub = self.lub_concrete_regions(a_region, cur_region);
345                if lub == cur_region {
346                    return false;
347                }
348
349                if let ty::RePlaceholder(p) = lub.kind()
359                    && b_universe.cannot_name(p.universe)
360                {
361                    lub = self.tcx().lifetimes.re_static;
362                }
363
364                debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
365
366                *b_data = VarValue::Value(lub);
367                true
368            }
369
370            VarValue::ErrorValue => false,
371        }
372    }
373
374    fn sub_region_values(&self, a: VarValue<'tcx>, b: VarValue<'tcx>) -> bool {
376        match (a, b) {
377            (VarValue::ErrorValue, _) | (_, VarValue::ErrorValue) => return true,
379            (VarValue::Empty(a_ui), VarValue::Empty(b_ui)) => {
380                a_ui.min(b_ui) == b_ui
383            }
384            (VarValue::Value(a), VarValue::Empty(_)) => {
385                match a.kind() {
386                    ReError(_) => false,
389
390                    ReBound(..) | ReErased => {
391                        bug!("cannot relate region: {:?}", a);
392                    }
393
394                    ReVar(v_id) => {
395                        span_bug!(
396                            self.var_infos[v_id].origin.span(),
397                            "lub_concrete_regions invoked with non-concrete region: {:?}",
398                            a
399                        );
400                    }
401
402                    ReStatic | ReEarlyParam(_) | ReLateParam(_) => {
403                        false
409                    }
410
411                    RePlaceholder(_) => {
412                        false
414                    }
415                }
416            }
417            (VarValue::Empty(a_ui), VarValue::Value(b)) => {
418                match b.kind() {
419                    ReError(_) => false,
422
423                    ReBound(..) | ReErased => {
424                        bug!("cannot relate region: {:?}", b);
425                    }
426
427                    ReVar(v_id) => {
428                        span_bug!(
429                            self.var_infos[v_id].origin.span(),
430                            "lub_concrete_regions invoked with non-concrete regions: {:?}",
431                            b
432                        );
433                    }
434
435                    ReStatic | ReEarlyParam(_) | ReLateParam(_) => {
436                        true
440                    }
441
442                    RePlaceholder(placeholder) => {
443                        return a_ui.can_name(placeholder.universe);
447                    }
448                }
449            }
450            (VarValue::Value(a), VarValue::Value(b)) => self.sub_concrete_regions(a, b),
451        }
452    }
453
454    #[instrument(level = "trace", skip(self))]
456    fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
457        let tcx = self.tcx();
458        let sub_free_regions = |r1, r2| self.region_rels.free_regions.sub_free_regions(tcx, r1, r2);
459
460        if b.is_free() && sub_free_regions(tcx.lifetimes.re_static, b) {
463            return true;
464        }
465
466        if a.is_free() && b.is_free() {
472            return sub_free_regions(a, b);
473        }
474
475        self.lub_concrete_regions(a, b) == b
478    }
479
480    #[instrument(level = "trace", skip(self), ret)]
486    fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
487        match (a.kind(), b.kind()) {
488            (ReBound(..), _) | (_, ReBound(..)) | (ReErased, _) | (_, ReErased) => {
489                bug!("cannot relate region: LUB({:?}, {:?})", a, b);
490            }
491
492            (ReVar(v_id), _) | (_, ReVar(v_id)) => {
493                span_bug!(
494                    self.var_infos[v_id].origin.span(),
495                    "lub_concrete_regions invoked with non-concrete \
496                     regions: {:?}, {:?}",
497                    a,
498                    b
499                );
500            }
501
502            (ReError(_), _) => a,
503
504            (_, ReError(_)) => b,
505
506            (ReStatic, _) | (_, ReStatic) => {
507                self.tcx().lifetimes.re_static
509            }
510
511            (ReEarlyParam(_) | ReLateParam(_), ReEarlyParam(_) | ReLateParam(_)) => {
512                self.region_rels.lub_param_regions(a, b)
513            }
514
515            (RePlaceholder(..), _) | (_, RePlaceholder(..)) => {
518                if a == b {
519                    a
520                } else {
521                    self.tcx().lifetimes.re_static
522                }
523            }
524        }
525    }
526
527    #[instrument(skip(self, var_data, errors))]
531    fn collect_errors(
532        &self,
533        var_data: &mut LexicalRegionResolutions<'tcx>,
534        errors: &mut Vec<RegionResolutionError<'tcx>>,
535    ) {
536        for (c, origin) in &self.data.constraints {
537            debug!(?c, ?origin);
538            match c.kind {
539                ConstraintKind::RegSubVar | ConstraintKind::VarSubVar => {
540                    }
542
543                ConstraintKind::RegSubReg => {
544                    if self.sub_concrete_regions(c.sub, c.sup) {
545                        continue;
546                    }
547
548                    debug!(
549                        "region error at {:?}: cannot verify that {:?} <= {:?}",
550                        origin, c.sub, c.sup
551                    );
552
553                    errors.push(RegionResolutionError::ConcreteFailure(
554                        (*origin).clone(),
555                        c.sub,
556                        c.sup,
557                    ));
558                }
559
560                ConstraintKind::VarSubReg => {
561                    let sub_vid = c.sub.as_var();
562                    let sub_data = var_data.value_mut(sub_vid);
563                    debug!("contraction: {:?} == {:?}, {:?}", sub_vid, sub_data, c.sup);
564
565                    let VarValue::Value(sub_region) = *sub_data else {
566                        continue;
567                    };
568
569                    if !self.sub_concrete_regions(sub_region, c.sup) {
573                        debug!(
574                            "region error at {:?}: cannot verify that {:?}={:?} <= {:?}",
575                            origin, sub_vid, sub_region, c.sup
576                        );
577                        *sub_data = VarValue::ErrorValue;
578                    }
579                }
580            }
581        }
582
583        for verify in &self.data.verifys {
584            debug!("collect_errors: verify={:?}", verify);
585            let sub = var_data.normalize(self.tcx(), verify.region);
586
587            let verify_kind_ty = verify.kind.to_ty(self.tcx());
588            let verify_kind_ty = var_data.normalize(self.tcx(), verify_kind_ty);
589            if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
590                continue;
591            }
592
593            debug!(
594                "collect_errors: region error at {:?}: \
595                 cannot verify that {:?} <= {:?}",
596                verify.origin, verify.region, verify.bound
597            );
598
599            errors.push(RegionResolutionError::GenericBoundFailure(
600                verify.origin.clone(),
601                verify.kind,
602                sub,
603            ));
604        }
605    }
606
607    fn collect_var_errors(
610        &self,
611        var_data: &LexicalRegionResolutions<'tcx>,
612        errors: &mut Vec<RegionResolutionError<'tcx>>,
613    ) {
614        debug!("collect_var_errors, var_data = {:#?}", var_data.values);
615
616        let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
628
629        let mut graph = None;
632
633        for (node_vid, value) in var_data.values.iter_enumerated() {
634            match *value {
635                VarValue::Empty(_) | VarValue::Value(_) => { }
636                VarValue::ErrorValue => {
637                    let g = graph.get_or_insert_with(|| self.construct_graph());
666                    self.collect_error_for_expanding_node(g, &mut dup_vec, node_vid, errors);
667                }
668            }
669        }
670    }
671
672    fn construct_graph(&self) -> RegionGraph<'tcx> {
673        let num_vars = self.num_vars();
674
675        let mut graph = LinkedGraph::new();
676
677        for _ in 0..num_vars {
678            graph.add_node(());
679        }
680
681        let dummy_source = graph.add_node(());
687        let dummy_sink = graph.add_node(());
688
689        for (c, _) in &self.data.constraints {
690            match c.kind {
691                ConstraintKind::VarSubVar => {
692                    let sub_vid = c.sub.as_var();
693                    let sup_vid = c.sup.as_var();
694                    graph.add_edge(NodeIndex(sub_vid.index()), NodeIndex(sup_vid.index()), *c);
695                }
696                ConstraintKind::RegSubVar => {
697                    graph.add_edge(dummy_source, NodeIndex(c.sup.as_var().index()), *c);
698                }
699                ConstraintKind::VarSubReg => {
700                    graph.add_edge(NodeIndex(c.sub.as_var().index()), dummy_sink, *c);
701                }
702                ConstraintKind::RegSubReg => {
703                    }
706            }
707        }
708
709        graph
710    }
711
712    fn collect_error_for_expanding_node(
713        &self,
714        graph: &RegionGraph<'tcx>,
715        dup_vec: &mut IndexSlice<RegionVid, Option<RegionVid>>,
716        node_idx: RegionVid,
717        errors: &mut Vec<RegionResolutionError<'tcx>>,
718    ) {
719        let (mut lower_bounds, lower_vid_bounds, lower_dup) =
722            self.collect_bounding_regions(graph, node_idx, INCOMING, Some(dup_vec));
723        let (mut upper_bounds, _, upper_dup) =
724            self.collect_bounding_regions(graph, node_idx, OUTGOING, Some(dup_vec));
725
726        if lower_dup || upper_dup {
727            return;
728        }
729
730        fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
734            match x.region.kind() {
735                ReEarlyParam(_) => 0,
736                ReLateParam(_) => 1,
737                _ => 2,
738            }
739        }
740        lower_bounds.sort_by_key(region_order_key);
741        upper_bounds.sort_by_key(region_order_key);
742
743        let node_universe = self.var_infos[node_idx].universe;
744
745        for lower_bound in &lower_bounds {
746            let effective_lower_bound = if let ty::RePlaceholder(p) = lower_bound.region.kind() {
747                if node_universe.cannot_name(p.universe) {
748                    self.tcx().lifetimes.re_static
749                } else {
750                    lower_bound.region
751                }
752            } else {
753                lower_bound.region
754            };
755
756            for upper_bound in &upper_bounds {
757                if !self.sub_concrete_regions(effective_lower_bound, upper_bound.region) {
758                    let origin = self.var_infos[node_idx].origin;
759                    debug!(
760                        "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
761                         sup: {:?}",
762                        origin, node_idx, lower_bound.region, upper_bound.region
763                    );
764
765                    errors.push(RegionResolutionError::SubSupConflict(
766                        node_idx,
767                        origin,
768                        lower_bound.origin.clone(),
769                        lower_bound.region,
770                        upper_bound.origin.clone(),
771                        upper_bound.region,
772                        vec![],
773                    ));
774                    return;
775                }
776            }
777        }
778
779        #[allow(rustc::potential_query_instability)]
787        let min_universe = lower_vid_bounds
788            .into_iter()
789            .map(|vid| self.var_infos[vid].universe)
790            .min()
791            .expect("lower_vid_bounds should at least include `node_idx`");
792
793        for upper_bound in &upper_bounds {
794            if let ty::RePlaceholder(p) = upper_bound.region.kind() {
795                if min_universe.cannot_name(p.universe) {
796                    let origin = self.var_infos[node_idx].origin;
797                    errors.push(RegionResolutionError::UpperBoundUniverseConflict(
798                        node_idx,
799                        origin,
800                        min_universe,
801                        upper_bound.origin.clone(),
802                        upper_bound.region,
803                    ));
804                    return;
805                }
806            }
807        }
808
809        assert!(
812            self.tcx().dcx().has_errors().is_some(),
813            "collect_error_for_expanding_node() could not find error for var {node_idx:?} in \
814            universe {node_universe:?}, lower_bounds={lower_bounds:#?}, \
815            upper_bounds={upper_bounds:#?}",
816        );
817    }
818
819    fn collect_bounding_regions(
831        &self,
832        graph: &RegionGraph<'tcx>,
833        orig_node_idx: RegionVid,
834        dir: Direction,
835        mut dup_vec: Option<&mut IndexSlice<RegionVid, Option<RegionVid>>>,
836    ) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool) {
837        struct WalkState<'tcx> {
838            set: FxHashSet<RegionVid>,
839            stack: Vec<RegionVid>,
840            result: Vec<RegionAndOrigin<'tcx>>,
841            dup_found: bool,
842        }
843        let mut state = WalkState {
844            set: Default::default(),
845            stack: vec![orig_node_idx],
846            result: Vec::new(),
847            dup_found: false,
848        };
849        state.set.insert(orig_node_idx);
850
851        process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
854
855        while let Some(node_idx) = state.stack.pop() {
856            if let Some(dup_vec) = &mut dup_vec {
858                if dup_vec[node_idx].is_none() {
859                    dup_vec[node_idx] = Some(orig_node_idx);
860                } else if dup_vec[node_idx] != Some(orig_node_idx) {
861                    state.dup_found = true;
862                }
863
864                debug!(
865                    "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
866                    orig_node_idx, node_idx
867                );
868            }
869
870            process_edges(&self.data, &mut state, graph, node_idx, dir);
871        }
872
873        let WalkState { result, dup_found, set, .. } = state;
874        return (result, set, dup_found);
875
876        fn process_edges<'tcx>(
877            this: &RegionConstraintData<'tcx>,
878            state: &mut WalkState<'tcx>,
879            graph: &RegionGraph<'tcx>,
880            source_vid: RegionVid,
881            dir: Direction,
882        ) {
883            debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
884
885            let source_node_index = NodeIndex(source_vid.index());
886            for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
887                let get_origin =
888                    || this.constraints.iter().find(|(c, _)| *c == edge.data).unwrap().1.clone();
889
890                match edge.data.kind {
891                    ConstraintKind::VarSubVar => {
892                        let from_vid = edge.data.sub.as_var();
893                        let to_vid = edge.data.sup.as_var();
894                        let opp_vid = if from_vid == source_vid { to_vid } else { from_vid };
895                        if state.set.insert(opp_vid) {
896                            state.stack.push(opp_vid);
897                        }
898                    }
899
900                    ConstraintKind::RegSubVar => {
901                        let origin = get_origin();
902                        state.result.push(RegionAndOrigin { region: edge.data.sub, origin });
903                    }
904
905                    ConstraintKind::VarSubReg => {
906                        let origin = get_origin();
907                        state.result.push(RegionAndOrigin { region: edge.data.sup, origin });
908                    }
909
910                    ConstraintKind::RegSubReg => panic!(
911                        "cannot reach reg-sub-reg edge in region inference \
912                         post-processing"
913                    ),
914                }
915            }
916        }
917    }
918
919    fn bound_is_met(
920        &self,
921        bound: &VerifyBound<'tcx>,
922        var_values: &LexicalRegionResolutions<'tcx>,
923        generic_ty: Ty<'tcx>,
924        min: ty::Region<'tcx>,
925    ) -> bool {
926        if let ty::ReError(_) = min.kind() {
927            return true;
928        }
929
930        match bound {
931            VerifyBound::IfEq(verify_if_eq_b) => {
932                let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
933                match test_type_match::extract_verify_if_eq(self.tcx(), &verify_if_eq_b, generic_ty)
934                {
935                    Some(r) => {
936                        self.bound_is_met(&VerifyBound::OutlivedBy(r), var_values, generic_ty, min)
937                    }
938
939                    None => false,
940                }
941            }
942
943            VerifyBound::OutlivedBy(r) => {
944                let a = match min.kind() {
945                    ty::ReVar(rid) => var_values.values[rid],
946                    _ => VarValue::Value(min),
947                };
948                let b = match r.kind() {
949                    ty::ReVar(rid) => var_values.values[rid],
950                    _ => VarValue::Value(*r),
951                };
952                self.sub_region_values(a, b)
953            }
954
955            VerifyBound::IsEmpty => match min.kind() {
956                ty::ReVar(rid) => match var_values.values[rid] {
957                    VarValue::ErrorValue => false,
958                    VarValue::Empty(_) => true,
959                    VarValue::Value(_) => false,
960                },
961                _ => false,
962            },
963
964            VerifyBound::AnyBound(bs) => {
965                bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
966            }
967
968            VerifyBound::AllBounds(bs) => {
969                bs.iter().all(|b| self.bound_is_met(b, var_values, generic_ty, min))
970            }
971        }
972    }
973}
974
975impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
976    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
977        write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
978    }
979}
980
981impl<'tcx> LexicalRegionResolutions<'tcx> {
982    fn normalize<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
983    where
984        T: TypeFoldable<TyCtxt<'tcx>>,
985    {
986        fold_regions(tcx, value, |r, _db| self.resolve_region(tcx, r))
987    }
988
989    fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
990        &self.values[rid]
991    }
992
993    fn value_mut(&mut self, rid: RegionVid) -> &mut VarValue<'tcx> {
994        &mut self.values[rid]
995    }
996
997    pub(crate) fn resolve_region(
998        &self,
999        tcx: TyCtxt<'tcx>,
1000        r: ty::Region<'tcx>,
1001    ) -> ty::Region<'tcx> {
1002        let result = match r.kind() {
1003            ty::ReVar(rid) => match self.values[rid] {
1004                VarValue::Empty(_) => r,
1005                VarValue::Value(r) => r,
1006                VarValue::ErrorValue => tcx.lifetimes.re_static,
1007            },
1008            _ => r,
1009        };
1010        debug!("resolve_region({:?}) = {:?}", r, result);
1011        result
1012    }
1013}