1 //! Lexical region resolution.
3 use crate::infer::region_constraints::Constraint;
4 use crate::infer::region_constraints::GenericKind;
5 use crate::infer::region_constraints::RegionConstraintData;
6 use crate::infer::region_constraints::VarInfos;
7 use crate::infer::region_constraints::VerifyBound;
8 use crate::infer::RegionRelations;
9 use crate::infer::RegionVariableOrigin;
10 use crate::infer::RegionckMode;
11 use crate::infer::SubregionOrigin;
12 use rustc_data_structures::fx::FxHashSet;
13 use rustc_data_structures::graph::implementation::{
14 Direction, Graph, NodeIndex, INCOMING, OUTGOING,
16 use rustc_data_structures::intern::Interned;
17 use rustc_index::vec::{Idx, IndexVec};
18 use rustc_middle::ty::fold::TypeFoldable;
19 use rustc_middle::ty::{self, Ty, TyCtxt};
20 use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
21 use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
22 use rustc_middle::ty::{Region, RegionVid};
26 /// This function performs lexical region resolution given a complete
27 /// set of constraints and variable origins. It performs a fixed-point
28 /// iteration to find region values which satisfy all constraints,
29 /// assuming such values can be found. It returns the final values of
30 /// all the variables as well as a set of errors that must be reported.
31 #[instrument(level = "debug", skip(region_rels, var_infos, data))]
32 pub(crate) fn resolve<'tcx>(
33 region_rels: &RegionRelations<'_, 'tcx>,
35 data: RegionConstraintData<'tcx>,
37 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
38 let mut errors = vec![];
39 let mut resolver = LexicalResolver { region_rels, var_infos, data };
41 RegionckMode::Solve => {
42 let values = resolver.infer_variable_values(&mut errors);
45 RegionckMode::Erase { suppress_errors: false } => {
46 // Do real inference to get errors, then erase the results.
47 let mut values = resolver.infer_variable_values(&mut errors);
48 let re_erased = region_rels.tcx.lifetimes.re_erased;
50 values.values.iter_mut().for_each(|v| match *v {
51 VarValue::Value(ref mut r) => *r = re_erased,
52 VarValue::ErrorValue => {}
56 RegionckMode::Erase { suppress_errors: true } => {
57 // Skip region inference entirely.
58 (resolver.erased_data(region_rels.tcx), Vec::new())
63 /// Contains the result of lexical region resolution. Offers methods
64 /// to lookup up the final value of a region variable.
66 pub struct LexicalRegionResolutions<'tcx> {
67 values: IndexVec<RegionVid, VarValue<'tcx>>,
68 error_region: ty::Region<'tcx>,
71 #[derive(Copy, Clone, Debug)]
77 #[derive(Clone, Debug)]
78 pub enum RegionResolutionError<'tcx> {
79 /// `ConcreteFailure(o, a, b)`:
81 /// `o` requires that `a <= b`, but this does not hold
82 ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
84 /// `GenericBoundFailure(p, s, a)
86 /// The parameter/associated-type `p` must be known to outlive the lifetime
87 /// `a` (but none of the known bounds are sufficient).
88 GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>),
90 /// `SubSupConflict(v, v_origin, sub_origin, sub_r, sup_origin, sup_r)`:
92 /// Could not infer a value for `v` (which has origin `v_origin`)
93 /// because `sub_r <= v` (due to `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and
94 /// `sub_r <= sup_r` does not hold.
98 SubregionOrigin<'tcx>,
100 SubregionOrigin<'tcx>,
102 Vec<Span>, // All the influences on a given value that didn't meet its constraints.
105 /// Indicates a `'b: 'a` constraint where `'a` is in a universe that
106 /// cannot name the placeholder `'b`.
107 UpperBoundUniverseConflict(
109 RegionVariableOrigin,
110 ty::UniverseIndex, // the universe index of the region variable
111 SubregionOrigin<'tcx>, // cause of the constraint
112 Region<'tcx>, // the placeholder `'b`
116 struct RegionAndOrigin<'tcx> {
117 region: Region<'tcx>,
118 origin: SubregionOrigin<'tcx>,
121 type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;
123 struct LexicalResolver<'cx, 'tcx> {
124 region_rels: &'cx RegionRelations<'cx, 'tcx>,
126 data: RegionConstraintData<'tcx>,
129 impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
130 fn tcx(&self) -> TyCtxt<'tcx> {
134 fn infer_variable_values(
136 errors: &mut Vec<RegionResolutionError<'tcx>>,
137 ) -> LexicalRegionResolutions<'tcx> {
138 let mut var_data = self.construct_var_data(self.tcx());
140 // Dorky hack to cause `dump_constraints` to only get called
141 // if debug mode is enabled:
143 "----() End constraint listing (context={:?}) {:?}---",
144 self.region_rels.context,
145 self.dump_constraints(self.region_rels)
148 let graph = self.construct_graph();
149 self.expand_givens(&graph);
150 self.expansion(&mut var_data);
151 self.collect_errors(&mut var_data, errors);
152 self.collect_var_errors(&var_data, &graph, errors);
156 fn num_vars(&self) -> usize {
160 /// Initially, the value for all variables is set to `'empty`, the
161 /// empty region. The `expansion` phase will grow this larger.
162 fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
163 LexicalRegionResolutions {
164 error_region: tcx.lifetimes.re_static,
165 values: IndexVec::from_fn_n(
167 let vid_universe = self.var_infos[vid].universe;
168 let re_empty = tcx.mk_region(ty::ReEmpty(vid_universe));
169 VarValue::Value(re_empty)
176 /// An erased version of the lexical region resolutions. Used when we're
177 /// erasing regions and suppressing errors: in item bodies with
178 /// `-Zborrowck=mir`.
179 fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
180 LexicalRegionResolutions {
181 error_region: tcx.lifetimes.re_static,
182 values: IndexVec::from_elem_n(
183 VarValue::Value(tcx.lifetimes.re_erased),
189 fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) {
190 debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context);
191 for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {
192 debug!("Constraint {} => {:?}", idx, constraint);
196 fn expand_givens(&mut self, graph: &RegionGraph<'_>) {
197 // Givens are a kind of horrible hack to account for
198 // constraints like 'c <= '0 that are known to hold due to
199 // closure signatures (see the comment above on the `givens`
200 // field). They should go away. But until they do, the role
201 // of this fn is to account for the transitive nature:
207 let seeds: Vec<_> = self.data.givens.iter().cloned().collect();
208 for (r, vid) in seeds {
209 // While all things transitively reachable in the graph
210 // from the variable (`'0` in the example above).
211 let seed_index = NodeIndex(vid.index() as usize);
212 for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
213 let succ_index = succ_index.0;
215 // The first N nodes correspond to the region
216 // variables. Other nodes correspond to constant
218 if succ_index < self.num_vars() {
219 let succ_vid = RegionVid::new(succ_index);
222 self.data.givens.insert((r, succ_vid));
228 fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
229 let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
230 let mut changes = Vec::new();
231 for constraint in self.data.constraints.keys() {
232 let (a_vid, a_region, b_vid, b_data) = match *constraint {
233 Constraint::RegSubVar(a_region, b_vid) => {
234 let b_data = var_values.value_mut(b_vid);
235 (None, a_region, b_vid, b_data)
237 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
238 VarValue::ErrorValue => continue,
239 VarValue::Value(a_region) => {
240 let b_data = var_values.value_mut(b_vid);
241 (Some(a_vid), a_region, b_vid, b_data)
244 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
245 // These constraints are checked after expansion
246 // is done, in `collect_errors`.
250 if self.expand_node(a_region, b_vid, b_data) {
253 if let Some(a_vid) = a_vid {
255 VarValue::Value(Region(Interned(ReStatic, _))) | VarValue::ErrorValue => (),
257 constraints[a_vid].push((a_vid, b_vid));
258 constraints[b_vid].push((a_vid, b_vid));
264 while let Some(vid) = changes.pop() {
265 constraints[vid].retain(|&(a_vid, b_vid)| {
266 let a_region = match *var_values.value(a_vid) {
267 VarValue::ErrorValue => return false,
268 VarValue::Value(a_region) => a_region,
270 let b_data = var_values.value_mut(b_vid);
271 if self.expand_node(a_region, b_vid, b_data) {
276 VarValue::Value(Region(Interned(ReStatic, _))) | VarValue::ErrorValue
284 a_region: Region<'tcx>,
286 b_data: &mut VarValue<'tcx>,
288 debug!("expand_node({:?}, {:?} == {:?})", a_region, b_vid, b_data);
291 // Check if this relationship is implied by a given.
292 ty::ReEarlyBound(_) | ty::ReFree(_) => {
293 if self.data.givens.contains(&(a_region, b_vid)) {
303 VarValue::Value(cur_region) => {
304 // This is a specialized version of the `lub_concrete_regions`
305 // check below for a common case, here purely as an
307 let b_universe = self.var_infos[b_vid].universe;
308 if let ReEmpty(a_universe) = *a_region {
309 if a_universe == b_universe {
314 let mut lub = self.lub_concrete_regions(a_region, cur_region);
315 if lub == cur_region {
319 // Watch out for `'b: !1` relationships, where the
320 // universe of `'b` can't name the placeholder `!1`. In
321 // that case, we have to grow `'b` to be `'static` for the
322 // relationship to hold. This is obviously a kind of sub-optimal
323 // choice -- in the future, when we incorporate a knowledge
324 // of the parameter environment, we might be able to find a
325 // tighter bound than `'static`.
327 // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
328 if let ty::RePlaceholder(p) = *lub {
329 if b_universe.cannot_name(p.universe) {
330 lub = self.tcx().lifetimes.re_static;
334 debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
336 *b_data = VarValue::Value(lub);
340 VarValue::ErrorValue => false,
344 /// True if `a <= b`, but not defined over inference variables.
345 #[instrument(level = "trace", skip(self))]
346 fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
347 let tcx = self.tcx();
348 let sub_free_regions = |r1, r2| self.region_rels.free_regions.sub_free_regions(tcx, r1, r2);
350 // Check for the case where we know that `'b: 'static` -- in that case,
351 // `a <= b` for all `a`.
352 let b_free_or_static = self.region_rels.free_regions.is_free_or_static(b);
353 if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) {
357 // If both `a` and `b` are free, consult the declared
358 // relationships. Note that this can be more precise than the
359 // `lub` relationship defined below, since sometimes the "lub"
360 // is actually the `postdom_upper_bound` (see
361 // `TransitiveRelation` for more details).
362 let a_free_or_static = self.region_rels.free_regions.is_free_or_static(a);
363 if a_free_or_static && b_free_or_static {
364 return sub_free_regions(a, b);
367 // For other cases, leverage the LUB code to find the LUB and
368 // check if it is equal to `b`.
369 self.lub_concrete_regions(a, b) == b
372 /// Returns the least-upper-bound of `a` and `b`; i.e., the
373 /// smallest region `c` such that `a <= c` and `b <= c`.
375 /// Neither `a` nor `b` may be an inference variable (hence the
376 /// term "concrete regions").
377 #[instrument(level = "trace", skip(self))]
378 fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
379 let r = match (*a, *b) {
380 (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReErased, _) | (_, ReErased) => {
381 bug!("cannot relate region: LUB({:?}, {:?})", a, b);
384 (ReVar(v_id), _) | (_, ReVar(v_id)) => {
386 self.var_infos[v_id].origin.span(),
387 "lub_concrete_regions invoked with non-concrete \
388 regions: {:?}, {:?}",
394 (ReStatic, _) | (_, ReStatic) => {
395 // nothing lives longer than `'static`
396 self.tcx().lifetimes.re_static
399 (ReEmpty(_), ReEarlyBound(_) | ReFree(_)) => {
400 // All empty regions are less than early-bound, free,
401 // and scope regions.
405 (ReEarlyBound(_) | ReFree(_), ReEmpty(_)) => {
406 // All empty regions are less than early-bound, free,
407 // and scope regions.
411 (ReEmpty(a_ui), ReEmpty(b_ui)) => {
412 // Empty regions are ordered according to the universe
413 // they are associated with.
414 let ui = a_ui.min(b_ui);
415 self.tcx().mk_region(ReEmpty(ui))
418 (ReEmpty(empty_ui), RePlaceholder(placeholder))
419 | (RePlaceholder(placeholder), ReEmpty(empty_ui)) => {
420 // If this empty region is from a universe that can
421 // name the placeholder, then the placeholder is
422 // larger; otherwise, the only ancestor is `'static`.
423 if empty_ui.can_name(placeholder.universe) {
424 self.tcx().mk_region(RePlaceholder(placeholder))
426 self.tcx().lifetimes.re_static
430 (ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => {
431 self.region_rels.lub_free_regions(a, b)
434 // For these types, we cannot define any additional
436 (RePlaceholder(..), _) | (_, RePlaceholder(..)) => {
440 self.tcx().lifetimes.re_static
445 debug!("lub_concrete_regions({:?}, {:?}) = {:?}", a, b, r);
450 /// After expansion is complete, go and check upper bounds (i.e.,
451 /// cases where the region cannot grow larger than a fixed point)
452 /// and check that they are satisfied.
453 #[instrument(skip(self, var_data, errors))]
456 var_data: &mut LexicalRegionResolutions<'tcx>,
457 errors: &mut Vec<RegionResolutionError<'tcx>>,
459 for (constraint, origin) in &self.data.constraints {
460 debug!(?constraint, ?origin);
462 Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
463 // Expansion will ensure that these constraints hold. Ignore.
466 Constraint::RegSubReg(sub, sup) => {
467 if self.sub_concrete_regions(sub, sup) {
472 "region error at {:?}: \
473 cannot verify that {:?} <= {:?}",
477 errors.push(RegionResolutionError::ConcreteFailure(
484 Constraint::VarSubReg(a_vid, b_region) => {
485 let a_data = var_data.value_mut(a_vid);
486 debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data, b_region);
488 let a_region = match *a_data {
489 VarValue::ErrorValue => continue,
490 VarValue::Value(a_region) => a_region,
493 // Do not report these errors immediately:
494 // instead, set the variable value to error and
495 // collect them later.
496 if !self.sub_concrete_regions(a_region, b_region) {
498 "region error at {:?}: \
499 cannot verify that {:?}={:?} <= {:?}",
500 origin, a_vid, a_region, b_region
502 *a_data = VarValue::ErrorValue;
508 for verify in &self.data.verifys {
509 debug!("collect_errors: verify={:?}", verify);
510 let sub = var_data.normalize(self.tcx(), verify.region);
512 let verify_kind_ty = verify.kind.to_ty(self.tcx());
513 let verify_kind_ty = var_data.normalize(self.tcx(), verify_kind_ty);
514 if self.bound_is_met(&verify.bound, var_data, verify_kind_ty, sub) {
519 "collect_errors: region error at {:?}: \
520 cannot verify that {:?} <= {:?}",
521 verify.origin, verify.region, verify.bound
524 errors.push(RegionResolutionError::GenericBoundFailure(
525 verify.origin.clone(),
532 /// Go over the variables that were declared to be error variables
533 /// and create a `RegionResolutionError` for each of them.
534 fn collect_var_errors(
536 var_data: &LexicalRegionResolutions<'tcx>,
537 graph: &RegionGraph<'tcx>,
538 errors: &mut Vec<RegionResolutionError<'tcx>>,
540 debug!("collect_var_errors, var_data = {:#?}", var_data.values);
542 // This is the best way that I have found to suppress
543 // duplicate and related errors. Basically we keep a set of
544 // flags for every node. Whenever an error occurs, we will
545 // walk some portion of the graph looking to find pairs of
546 // conflicting regions to report to the user. As we walk, we
547 // trip the flags from false to true, and if we find that
548 // we've already reported an error involving any particular
549 // node we just stop and don't report the current error. The
550 // idea is to report errors that derive from independent
551 // regions of the graph, but not those that derive from
552 // overlapping locations.
553 let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
555 for (node_vid, value) in var_data.values.iter_enumerated() {
557 VarValue::Value(_) => { /* Inference successful */ }
558 VarValue::ErrorValue => {
559 // Inference impossible: this value contains
560 // inconsistent constraints.
562 // I think that in this case we should report an
563 // error now -- unlike the case above, we can't
564 // wait to see whether the user needs the result
565 // of this variable. The reason is that the mere
566 // existence of this variable implies that the
567 // region graph is inconsistent, whether or not it
570 // For example, we may have created a region
571 // variable that is the GLB of two other regions
572 // which do not have a GLB. Even if that variable
573 // is not used, it implies that those two regions
574 // *should* have a GLB.
576 // At least I think this is true. It may be that
577 // the mere existence of a conflict in a region
578 // variable that is not used is not a problem, so
579 // if this rule starts to create problems we'll
580 // have to revisit this portion of the code and
581 // think hard about it. =) -- nikomatsakis
583 // Obtain the spans for all the places that can
584 // influence the constraints on this value for
585 // richer diagnostics in `static_impl_trait`.
586 let influences: Vec<Span> = self
590 .filter_map(|(constraint, origin)| match (constraint, origin) {
592 Constraint::VarSubVar(_, sup),
593 SubregionOrigin::DataBorrowed(_, sp),
594 ) if sup == &node_vid => Some(*sp),
599 self.collect_error_for_expanding_node(
611 fn construct_graph(&self) -> RegionGraph<'tcx> {
612 let num_vars = self.num_vars();
614 let mut graph = Graph::new();
616 for _ in 0..num_vars {
620 // Issue #30438: two distinct dummy nodes, one for incoming
621 // edges (dummy_source) and another for outgoing edges
622 // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
623 // dummy node leads one to think (erroneously) there exists a
624 // path from `b` to `a`. Two dummy nodes sidesteps the issue.
625 let dummy_source = graph.add_node(());
626 let dummy_sink = graph.add_node(());
628 for constraint in self.data.constraints.keys() {
630 Constraint::VarSubVar(a_id, b_id) => {
632 NodeIndex(a_id.index() as usize),
633 NodeIndex(b_id.index() as usize),
637 Constraint::RegSubVar(_, b_id) => {
638 graph.add_edge(dummy_source, NodeIndex(b_id.index() as usize), *constraint);
640 Constraint::VarSubReg(a_id, _) => {
641 graph.add_edge(NodeIndex(a_id.index() as usize), dummy_sink, *constraint);
643 Constraint::RegSubReg(..) => {
644 // this would be an edge from `dummy_source` to
645 // `dummy_sink`; just ignore it.
653 fn collect_error_for_expanding_node(
655 graph: &RegionGraph<'tcx>,
656 dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
658 errors: &mut Vec<RegionResolutionError<'tcx>>,
659 influences: Vec<Span>,
661 // Errors in expanding nodes result from a lower-bound that is
662 // not contained by an upper-bound.
663 let (mut lower_bounds, lower_vid_bounds, lower_dup) =
664 self.collect_bounding_regions(graph, node_idx, INCOMING, Some(dup_vec));
665 let (mut upper_bounds, _, upper_dup) =
666 self.collect_bounding_regions(graph, node_idx, OUTGOING, Some(dup_vec));
668 if lower_dup || upper_dup {
672 // We place free regions first because we are special casing
673 // SubSupConflict(ReFree, ReFree) when reporting error, and so
674 // the user will more likely get a specific suggestion.
675 fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
677 ReEarlyBound(_) => 0,
682 lower_bounds.sort_by_key(region_order_key);
683 upper_bounds.sort_by_key(region_order_key);
685 let node_universe = self.var_infos[node_idx].universe;
687 for lower_bound in &lower_bounds {
688 let effective_lower_bound = if let ty::RePlaceholder(p) = *lower_bound.region {
689 if node_universe.cannot_name(p.universe) {
690 self.tcx().lifetimes.re_static
698 for upper_bound in &upper_bounds {
699 if !self.sub_concrete_regions(effective_lower_bound, upper_bound.region) {
700 let origin = self.var_infos[node_idx].origin;
702 "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
704 origin, node_idx, lower_bound.region, upper_bound.region
707 errors.push(RegionResolutionError::SubSupConflict(
710 lower_bound.origin.clone(),
712 upper_bound.origin.clone(),
721 // If we have a scenario like `exists<'a> { forall<'b> { 'b:
722 // 'a } }`, we wind up without any lower-bound -- all we have
723 // are placeholders as upper bounds, but the universe of the
724 // variable `'a`, or some variable that `'a` has to outlive, doesn't
725 // permit those placeholders.
726 let min_universe = lower_vid_bounds
728 .map(|vid| self.var_infos[vid].universe)
730 .expect("lower_vid_bounds should at least include `node_idx`");
732 for upper_bound in &upper_bounds {
733 if let ty::RePlaceholder(p) = *upper_bound.region {
734 if min_universe.cannot_name(p.universe) {
735 let origin = self.var_infos[node_idx].origin;
736 errors.push(RegionResolutionError::UpperBoundUniverseConflict(
740 upper_bound.origin.clone(),
748 // Errors in earlier passes can yield error variables without
749 // resolution errors here; delay ICE in favor of those errors.
750 self.tcx().sess.delay_span_bug(
751 self.var_infos[node_idx].origin.span(),
753 "collect_error_for_expanding_node() could not find \
754 error for var {:?} in universe {:?}, lower_bounds={:#?}, \
756 node_idx, node_universe, lower_bounds, upper_bounds
761 /// Collects all regions that "bound" the variable `orig_node_idx` in the
764 /// If `dup_vec` is `Some` it's used to track duplicates between successive
765 /// calls of this function.
767 /// The return tuple fields are:
768 /// - a list of all concrete regions bounding the given region.
769 /// - the set of all region variables bounding the given region.
770 /// - a `bool` that's true if the returned region variables overlap with
771 /// those returned by a previous call for another region.
772 fn collect_bounding_regions(
774 graph: &RegionGraph<'tcx>,
775 orig_node_idx: RegionVid,
777 mut dup_vec: Option<&mut IndexVec<RegionVid, Option<RegionVid>>>,
778 ) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool) {
779 struct WalkState<'tcx> {
780 set: FxHashSet<RegionVid>,
781 stack: Vec<RegionVid>,
782 result: Vec<RegionAndOrigin<'tcx>>,
785 let mut state = WalkState {
786 set: Default::default(),
787 stack: vec![orig_node_idx],
791 state.set.insert(orig_node_idx);
793 // to start off the process, walk the source node in the
794 // direction specified
795 process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
797 while let Some(node_idx) = state.stack.pop() {
798 // check whether we've visited this node on some previous walk
799 if let Some(dup_vec) = &mut dup_vec {
800 if dup_vec[node_idx].is_none() {
801 dup_vec[node_idx] = Some(orig_node_idx);
802 } else if dup_vec[node_idx] != Some(orig_node_idx) {
803 state.dup_found = true;
807 "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
808 orig_node_idx, node_idx
812 process_edges(&self.data, &mut state, graph, node_idx, dir);
815 let WalkState { result, dup_found, set, .. } = state;
816 return (result, set, dup_found);
818 fn process_edges<'tcx>(
819 this: &RegionConstraintData<'tcx>,
820 state: &mut WalkState<'tcx>,
821 graph: &RegionGraph<'tcx>,
822 source_vid: RegionVid,
825 debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
827 let source_node_index = NodeIndex(source_vid.index() as usize);
828 for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
830 Constraint::VarSubVar(from_vid, to_vid) => {
831 let opp_vid = if from_vid == source_vid { to_vid } else { from_vid };
832 if state.set.insert(opp_vid) {
833 state.stack.push(opp_vid);
837 Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => {
838 state.result.push(RegionAndOrigin {
840 origin: this.constraints.get(&edge.data).unwrap().clone(),
844 Constraint::RegSubReg(..) => panic!(
845 "cannot reach reg-sub-reg edge in region inference \
855 bound: &VerifyBound<'tcx>,
856 var_values: &LexicalRegionResolutions<'tcx>,
857 generic_ty: Ty<'tcx>,
858 min: ty::Region<'tcx>,
861 VerifyBound::IfEq(k, b) => {
862 (var_values.normalize(self.region_rels.tcx, *k) == generic_ty)
863 && self.bound_is_met(b, var_values, generic_ty, min)
866 VerifyBound::OutlivedBy(r) => {
867 self.sub_concrete_regions(min, var_values.normalize(self.tcx(), *r))
870 VerifyBound::IsEmpty => {
871 matches!(*min, ty::ReEmpty(_))
874 VerifyBound::AnyBound(bs) => {
875 bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
878 VerifyBound::AllBounds(bs) => {
879 bs.iter().all(|b| self.bound_is_met(b, var_values, generic_ty, min))
885 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
886 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
887 write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
891 impl<'tcx> LexicalRegionResolutions<'tcx> {
892 fn normalize<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
894 T: TypeFoldable<'tcx>,
896 tcx.fold_regions(value, &mut false, |r, _db| match *r {
897 ty::ReVar(rid) => self.resolve_var(rid),
902 fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
906 fn value_mut(&mut self, rid: RegionVid) -> &mut VarValue<'tcx> {
907 &mut self.values[rid]
910 pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
911 let result = match self.values[rid] {
912 VarValue::Value(r) => r,
913 VarValue::ErrorValue => self.error_region,
915 debug!("resolve_var({:?}) = {:?}", rid, result);