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, 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 (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                                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.kind() {
222                                    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                    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    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.kind() {
314                    RePlaceholder(placeholder) => {
315                        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                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                if let ty::RePlaceholder(p) = lub.kind()
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    fn sub_region_values(&self, a: VarValue<'tcx>, b: VarValue<'tcx>) -> bool {
371        match (a, b) {
372            (VarValue::ErrorValue, _) | (_, VarValue::ErrorValue) => return true,
374            (VarValue::Empty(a_ui), VarValue::Empty(b_ui)) => {
375                a_ui.min(b_ui) == b_ui
378            }
379            (VarValue::Value(a), VarValue::Empty(_)) => {
380                match a.kind() {
381                    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                        false
404                    }
405
406                    RePlaceholder(_) => {
407                        false
409                    }
410                }
411            }
412            (VarValue::Empty(a_ui), VarValue::Value(b)) => {
413                match b.kind() {
414                    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                        true
435                    }
436
437                    RePlaceholder(placeholder) => {
438                        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    #[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        if b.is_free() && sub_free_regions(tcx.lifetimes.re_static, b) {
458            return true;
459        }
460
461        if a.is_free() && b.is_free() {
467            return sub_free_regions(a, b);
468        }
469
470        self.lub_concrete_regions(a, b) == b
473    }
474
475    #[instrument(level = "trace", skip(self), ret)]
481    fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
482        match (a.kind(), b.kind()) {
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                self.tcx().lifetimes.re_static
504            }
505
506            (ReEarlyParam(_) | ReLateParam(_), ReEarlyParam(_) | ReLateParam(_)) => {
507                self.region_rels.lub_param_regions(a, b)
508            }
509
510            (RePlaceholder(..), _) | (_, RePlaceholder(..)) => {
513                if a == b {
514                    a
515                } else {
516                    self.tcx().lifetimes.re_static
517                }
518            }
519        }
520    }
521
522    #[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                    }
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                    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    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        let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
624
625        let mut graph = None;
628
629        for (node_vid, value) in var_data.values.iter_enumerated() {
630            match *value {
631                VarValue::Empty(_) | VarValue::Value(_) => { }
632                VarValue::ErrorValue => {
633                    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 = LinkedGraph::new();
672
673        for _ in 0..num_vars {
674            graph.add_node(());
675        }
676
677        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                    }
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        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        fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
728            match x.region.kind() {
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.kind() {
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        #[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.kind() {
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        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    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        process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
848
849        while let Some(node_idx) = state.stack.pop() {
850            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.kind() {
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.kind() {
935                    ty::ReVar(rid) => var_values.values[rid],
936                    _ => VarValue::Value(min),
937                };
938                let b = match r.kind() {
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.kind() {
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.kind() {
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}