Skip to main content

rustc_borrowck/region_infer/
values.rs

1use std::fmt::Debug;
2use std::rc::Rc;
3
4use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
5use rustc_index::Idx;
6use rustc_index::bit_set::SparseBitMatrix;
7use rustc_index::interval::{IntervalSet, SparseIntervalMatrix};
8use rustc_middle::bug;
9use rustc_middle::mir::{BasicBlock, Location};
10use rustc_middle::ty::{self, RegionVid};
11use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
12use tracing::debug;
13
14use crate::BorrowIndex;
15use crate::polonius::LiveLoans;
16
17impl ::std::fmt::Debug for PlaceholderIndex {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_fmt(format_args!("PlaceholderIndex({0})", self.as_u32()))
    }
}rustc_index::newtype_index! {
18    /// A single integer representing a `ty::Placeholder`.
19    #[debug_format = "PlaceholderIndex({})"]
20    pub(crate) struct PlaceholderIndex {}
21}
22
23/// An individual element in a region value -- the value of a
24/// particular region variable consists of a set of these elements.
25#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for RegionElement<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            RegionElement::Location(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Location", &__self_0),
            RegionElement::RootUniversalRegion(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "RootUniversalRegion", &__self_0),
            RegionElement::PlaceholderRegion(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "PlaceholderRegion", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for RegionElement<'tcx> {
    #[inline]
    fn clone(&self) -> RegionElement<'tcx> {
        match self {
            RegionElement::Location(__self_0) =>
                RegionElement::Location(::core::clone::Clone::clone(__self_0)),
            RegionElement::RootUniversalRegion(__self_0) =>
                RegionElement::RootUniversalRegion(::core::clone::Clone::clone(__self_0)),
            RegionElement::PlaceholderRegion(__self_0) =>
                RegionElement::PlaceholderRegion(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for RegionElement<'tcx> {
    #[inline]
    fn eq(&self, other: &RegionElement<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (RegionElement::Location(__self_0),
                    RegionElement::Location(__arg1_0)) => __self_0 == __arg1_0,
                (RegionElement::RootUniversalRegion(__self_0),
                    RegionElement::RootUniversalRegion(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (RegionElement::PlaceholderRegion(__self_0),
                    RegionElement::PlaceholderRegion(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
26pub(crate) enum RegionElement<'tcx> {
27    /// A point in the control-flow graph.
28    Location(Location),
29
30    /// A universally quantified region from the root universe (e.g.,
31    /// a lifetime parameter).
32    RootUniversalRegion(RegionVid),
33
34    /// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)`
35    /// type).
36    PlaceholderRegion(ty::PlaceholderRegion<'tcx>),
37}
38
39/// Either a mapping of which points a region is live at (for regular bodies),
40/// or which regions are live in the body somewhere (for promoteds, which do
41/// not care about where they are live, only that they are).
42#[derive(#[automatically_derived]
impl ::core::clone::Clone for LiveRegions {
    #[inline]
    fn clone(&self) -> LiveRegions {
        match self {
            LiveRegions::AtPoints(__self_0) =>
                LiveRegions::AtPoints(::core::clone::Clone::clone(__self_0)),
            LiveRegions::InBody(__self_0) =>
                LiveRegions::InBody(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)] // FIXME(#146079)
43enum LiveRegions {
44    /// region `'r` is live at locations `L`.
45    AtPoints(SparseIntervalMatrix<RegionVid, PointIndex>),
46    /// Region `'r` is live in function body.
47    InBody(FxHashSet<RegionVid>),
48}
49
50/// Records the CFG locations where each region is live. When we initially compute liveness, we use
51/// an interval matrix storing liveness ranges for each region-vid.
52#[derive(#[automatically_derived]
impl ::core::clone::Clone for LivenessValues {
    #[inline]
    fn clone(&self) -> LivenessValues {
        LivenessValues {
            location_map: ::core::clone::Clone::clone(&self.location_map),
            live_regions: ::core::clone::Clone::clone(&self.live_regions),
            live_loans: ::core::clone::Clone::clone(&self.live_loans),
        }
    }
}Clone)] // FIXME(#146079)
53pub(crate) struct LivenessValues {
54    /// The map from locations to points.
55    location_map: Rc<DenseLocationMap>,
56
57    /// Where a region is live.
58    live_regions: LiveRegions,
59
60    /// When using `-Zpolonius=next`, the set of loans that are live at a given point in the CFG.
61    live_loans: Option<LiveLoans>,
62}
63
64impl LivenessValues {
65    /// Create an empty map of regions to locations where they're live.
66    pub(crate) fn with_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
67        LivenessValues {
68            live_regions: LiveRegions::AtPoints(SparseIntervalMatrix::new(
69                location_map.num_points(),
70            )),
71            location_map,
72            live_loans: None,
73        }
74    }
75
76    /// Create an empty map of regions to locations where they're live.
77    ///
78    /// Unlike `with_specific_points`, does not track exact locations where something is live, only
79    /// which regions are live.
80    pub(crate) fn without_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
81        LivenessValues {
82            live_regions: LiveRegions::InBody(Default::default()),
83            location_map,
84            live_loans: None,
85        }
86    }
87
88    /// Returns the liveness matrix of points where each region is live. Panics if the liveness
89    /// values have been created without any per-point data (that is, for promoteds).
90    pub(crate) fn points(&self) -> &SparseIntervalMatrix<RegionVid, PointIndex> {
91        if let LiveRegions::AtPoints(points) = &self.live_regions {
92            points
93        } else {
94            ::rustc_middle::util::bug::bug_fmt(format_args!("this `LivenessValues` wasn\'t created using `with_specific_points`"))bug!("this `LivenessValues` wasn't created using `with_specific_points`")
95        }
96    }
97
98    /// Iterate through each region that has a value in this set.
99    pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> {
100        self.points().rows()
101    }
102
103    /// Iterate through each region that has a value in this set.
104    // We are passing query instability implications to the caller.
105    #[rustc_lint_query_instability]
106    #[allow(rustc::potential_query_instability)]
107    pub(crate) fn live_regions_unordered(&self) -> impl Iterator<Item = RegionVid> {
108        if let LiveRegions::InBody(live_regions) = &self.live_regions {
109            live_regions.iter().copied()
110        } else {
111            ::rustc_middle::util::bug::bug_fmt(format_args!("this `LivenessValues` wasn\'t created using `without_specific_points`"))bug!("this `LivenessValues` wasn't created using `without_specific_points`")
112        }
113    }
114
115    /// Records `region` as being live at the given `location`.
116    pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
117        let point = self.location_map.point_from_location(location);
118        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/region_infer/values.rs:118",
                        "rustc_borrowck::region_infer::values",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/values.rs"),
                        ::tracing_core::__macro_support::Option::Some(118u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::values"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("LivenessValues::add_location(region={0:?}, location={1:?})",
                                                    region, location) as &dyn Value))])
            });
    } else { ; }
};debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
119        match &mut self.live_regions {
120            LiveRegions::AtPoints(points) => {
121                points.insert(region, point);
122            }
123
124            LiveRegions::InBody(live_regions) if self.location_map.point_in_range(point) => {
125                live_regions.insert(region);
126            }
127
128            LiveRegions::InBody(_) => (),
129        };
130    }
131
132    /// Records `region` as being live at all the given `points`.
133    pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
134        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/region_infer/values.rs:134",
                        "rustc_borrowck::region_infer::values",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/values.rs"),
                        ::tracing_core::__macro_support::Option::Some(134u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::values"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("LivenessValues::add_points(region={0:?}, points={1:?})",
                                                    region, points) as &dyn Value))])
            });
    } else { ; }
};debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
135        match &mut self.live_regions {
136            LiveRegions::AtPoints(these_points) => {
137                these_points.union_row(region, points);
138            }
139            LiveRegions::InBody(live_regions)
140                if points.iter().any(|point| self.location_map.point_in_range(point)) =>
141            {
142                live_regions.insert(region);
143            }
144            LiveRegions::InBody(_) => (),
145        };
146    }
147
148    /// Records `region` as being live at all the control-flow points.
149    pub(crate) fn add_all_points(&mut self, region: RegionVid) {
150        match &mut self.live_regions {
151            LiveRegions::AtPoints(points) => points.insert_all_into_row(region),
152            LiveRegions::InBody(live_regions) => {
153                live_regions.insert(region);
154            }
155        }
156    }
157
158    /// Returns whether `region` is marked live at the given
159    /// [`location`][rustc_middle::mir::Location].
160    pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
161        let point = self.location_map.point_from_location(location);
162        self.is_live_at_point(region, point)
163    }
164
165    /// Returns whether `region` is marked live at the given
166    /// [`point`][rustc_mir_dataflow::points::PointIndex].
167    #[inline]
168    pub(crate) fn is_live_at_point(&self, region: RegionVid, point: PointIndex) -> bool {
169        self.points().row(region).is_some_and(|r| r.contains(point))
170    }
171
172    /// Returns an iterator of all the points where `region` is live.
173    fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> {
174        self.points()
175            .row(region)
176            .into_iter()
177            .flat_map(|set| set.iter())
178            .take_while(|&p| self.location_map.point_in_range(p))
179    }
180
181    /// For debugging purposes, returns a pretty-printed string of the points where the `region` is
182    /// live.
183    pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String {
184        pretty_print_region_elements(
185            self.live_points(region)
186                .map(|p| RegionElement::Location(self.location_map.to_location(p))),
187        )
188    }
189
190    #[inline]
191    pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
192        self.location_map.point_from_location(location)
193    }
194
195    #[inline]
196    pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
197        self.location_map.to_location(point)
198    }
199
200    /// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active
201    /// loans dataflow computations.
202    pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) {
203        self.live_loans = Some(live_loans);
204    }
205
206    /// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
207    pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
208        self.live_loans
209            .as_ref()
210            .expect("Accessing live loans requires `-Zpolonius=next`")
211            .contains(point, loan_idx)
212    }
213}
214
215/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
216/// rustc to the internal `PlaceholderIndex` values that are used in
217/// NLL.
218#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for PlaceholderIndices<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "PlaceholderIndices", "indices", &&self.indices)
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::default::Default for PlaceholderIndices<'tcx> {
    #[inline]
    fn default() -> PlaceholderIndices<'tcx> {
        PlaceholderIndices { indices: ::core::default::Default::default() }
    }
}Default)]
219#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for PlaceholderIndices<'tcx> {
    #[inline]
    fn clone(&self) -> PlaceholderIndices<'tcx> {
        PlaceholderIndices {
            indices: ::core::clone::Clone::clone(&self.indices),
        }
    }
}Clone)] // FIXME(#146079)
220pub(crate) struct PlaceholderIndices<'tcx> {
221    indices: FxIndexSet<ty::PlaceholderRegion<'tcx>>,
222}
223
224impl<'tcx> PlaceholderIndices<'tcx> {
225    /// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
226    pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion<'tcx>) -> PlaceholderIndex {
227        let (index, _) = self.indices.insert_full(placeholder);
228        index.into()
229    }
230
231    pub(crate) fn lookup_index(
232        &self,
233        placeholder: ty::PlaceholderRegion<'tcx>,
234    ) -> PlaceholderIndex {
235        self.indices.get_index_of(&placeholder).unwrap().into()
236    }
237
238    pub(crate) fn lookup_placeholder(
239        &self,
240        placeholder: PlaceholderIndex,
241    ) -> ty::PlaceholderRegion<'tcx> {
242        self.indices[placeholder.index()]
243    }
244
245    pub(crate) fn len(&self) -> usize {
246        self.indices.len()
247    }
248}
249
250/// Stores the full values for a set of regions (in contrast to
251/// `LivenessValues`, which only stores those points in the where a
252/// region is live). The full value for a region may contain points in
253/// the CFG, but also free regions as well as bound universe
254/// placeholders.
255///
256/// Example:
257///
258/// ```text
259/// fn foo(x: &'a u32) -> &'a u32 {
260///    let y: &'0 u32 = x; // let's call this `'0`
261///    y
262/// }
263/// ```
264///
265/// Here, the variable `'0` would contain the free region `'a`,
266/// because (since it is returned) it must live for at least `'a`. But
267/// it would also contain various points from within the function.
268pub(crate) struct RegionValues<'tcx, N: Idx> {
269    location_map: Rc<DenseLocationMap>,
270    placeholder_indices: PlaceholderIndices<'tcx>,
271    points: SparseIntervalMatrix<N, PointIndex>,
272    free_regions: SparseBitMatrix<N, RegionVid>,
273
274    /// Placeholders represent bound regions -- so something like `'a`
275    /// in `for<'a> fn(&'a u32)`.
276    placeholders: SparseBitMatrix<N, PlaceholderIndex>,
277}
278
279impl<'tcx, N: Idx> RegionValues<'tcx, N> {
280    /// Creates a new set of "region values" that tracks causal information.
281    /// Each of the regions in num_region_variables will be initialized with an
282    /// empty set of points and no causal information.
283    pub(crate) fn new(
284        location_map: Rc<DenseLocationMap>,
285        num_universal_regions: usize,
286        placeholder_indices: PlaceholderIndices<'tcx>,
287    ) -> Self {
288        let num_points = location_map.num_points();
289        let num_placeholders = placeholder_indices.len();
290        Self {
291            location_map,
292            points: SparseIntervalMatrix::new(num_points),
293            placeholder_indices,
294            free_regions: SparseBitMatrix::new(num_universal_regions),
295            placeholders: SparseBitMatrix::new(num_placeholders),
296        }
297    }
298
299    /// Adds the given element to the value for the given region. Returns whether
300    /// the element is newly added (i.e., was not already present).
301    pub(crate) fn add_element(&mut self, r: N, elem: impl ToElementIndex<'tcx>) -> bool {
302        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/region_infer/values.rs:302",
                        "rustc_borrowck::region_infer::values",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/values.rs"),
                        ::tracing_core::__macro_support::Option::Some(302u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::values"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("add(r={0:?}, elem={1:?})",
                                                    r, elem) as &dyn Value))])
            });
    } else { ; }
};debug!("add(r={:?}, elem={:?})", r, elem);
303        elem.add_to_row(self, r)
304    }
305
306    /// Adds all the control-flow points to the values for `r`.
307    pub(crate) fn add_all_points(&mut self, r: N) {
308        self.points.insert_all_into_row(r);
309    }
310
311    /// Adds all elements in `r_from` to `r_to` (because e.g., `r_to:
312    /// r_from`).
313    pub(crate) fn add_region(&mut self, r_to: N, r_from: N) -> bool {
314        self.points.union_rows(r_from, r_to)
315            | self.free_regions.union_rows(r_from, r_to)
316            | self.placeholders.union_rows(r_from, r_to)
317    }
318
319    /// Returns `true` if the region `r` contains the given element.
320    pub(crate) fn contains(&self, r: N, elem: impl ToElementIndex<'tcx>) -> bool {
321        elem.contained_in_row(self, r)
322    }
323
324    /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
325    pub(crate) fn first_non_contained_inclusive(
326        &self,
327        r: N,
328        block: BasicBlock,
329        start: usize,
330        end: usize,
331    ) -> Option<usize> {
332        let row = self.points.row(r)?;
333        let block = self.location_map.entry_point(block);
334        let start = block.plus(start);
335        let end = block.plus(end);
336        let first_unset = row.first_unset_in(start..=end)?;
337        Some(first_unset.index() - block.index())
338    }
339
340    /// `self[to] |= values[from]`, essentially: that is, take all the
341    /// elements for the region `from` from `values` and add them to
342    /// the region `to` in `self`.
343    pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
344        if let Some(set) = values.points().row(from) {
345            self.points.union_row(to, set);
346        }
347    }
348
349    /// Returns `true` if `sup_region` contains all the CFG points that
350    /// `sub_region` contains. Ignores universal regions.
351    pub(crate) fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
352        if let Some(sub_row) = self.points.row(sub_region) {
353            if let Some(sup_row) = self.points.row(sup_region) {
354                sup_row.superset(sub_row)
355            } else {
356                // sup row is empty, so sub row must be empty
357                sub_row.is_empty()
358            }
359        } else {
360            // sub row is empty, always true
361            true
362        }
363    }
364
365    /// Returns the locations contained within a given region `r`.
366    pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> {
367        self.points.row(r).into_iter().flat_map(move |set| {
368            set.iter()
369                .take_while(move |&p| self.location_map.point_in_range(p))
370                .map(move |p| self.location_map.to_location(p))
371        })
372    }
373
374    /// Returns just the universal regions that are contained in a given region's value.
375    pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator<Item = RegionVid> {
376        self.free_regions.row(r).into_iter().flat_map(|set| set.iter())
377    }
378
379    /// Returns all the elements contained in a given region's value.
380    pub(crate) fn placeholders_contained_in(
381        &self,
382        r: N,
383    ) -> impl Iterator<Item = ty::PlaceholderRegion<'tcx>> {
384        self.placeholders
385            .row(r)
386            .into_iter()
387            .flat_map(|set| set.iter())
388            .map(move |p| self.placeholder_indices.lookup_placeholder(p))
389    }
390
391    /// Returns all the elements contained in a given region's value.
392    pub(crate) fn elements_contained_in(&self, r: N) -> impl Iterator<Item = RegionElement<'tcx>> {
393        let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
394
395        let free_regions_iter =
396            self.universal_regions_outlived_by(r).map(RegionElement::RootUniversalRegion);
397
398        let placeholder_universes_iter =
399            self.placeholders_contained_in(r).map(RegionElement::PlaceholderRegion);
400
401        points_iter.chain(free_regions_iter).chain(placeholder_universes_iter)
402    }
403
404    /// Returns a "pretty" string value of the region. Meant for debugging.
405    pub(crate) fn region_value_str(&self, r: N) -> String {
406        pretty_print_region_elements(self.elements_contained_in(r))
407    }
408}
409
410pub(crate) trait ToElementIndex<'tcx>: Debug + Copy {
411    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool;
412
413    fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool;
414}
415
416impl ToElementIndex<'_> for Location {
417    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
418        let index = values.location_map.point_from_location(self);
419        values.points.insert(row, index)
420    }
421
422    fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
423        let index = values.location_map.point_from_location(self);
424        values.points.contains(row, index)
425    }
426}
427
428impl ToElementIndex<'_> for RegionVid {
429    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
430        values.free_regions.insert(row, self)
431    }
432
433    fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
434        values.free_regions.contains(row, self)
435    }
436}
437
438impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> {
439    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool {
440        let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
441        let index = values.placeholder_indices.lookup_index(placeholder);
442        values.placeholders.insert(row, index)
443    }
444
445    fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool {
446        let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
447        let index = values.placeholder_indices.lookup_index(placeholder);
448        values.placeholders.contains(row, index)
449    }
450}
451
452/// For debugging purposes, returns a pretty-printed string of the given points.
453pub(crate) fn pretty_print_points(
454    location_map: &DenseLocationMap,
455    points: impl IntoIterator<Item = PointIndex>,
456) -> String {
457    pretty_print_region_elements(
458        points
459            .into_iter()
460            .take_while(|&p| location_map.point_in_range(p))
461            .map(|p| location_map.to_location(p))
462            .map(RegionElement::Location),
463    )
464}
465
466/// For debugging purposes, returns a pretty-printed string of the given region elements.
467fn pretty_print_region_elements<'tcx>(
468    elements: impl IntoIterator<Item = RegionElement<'tcx>>,
469) -> String {
470    let mut result = String::new();
471    result.push('{');
472
473    // Set to Some(l1, l2) when we have observed all the locations
474    // from l1..=l2 (inclusive) but not yet printed them. This
475    // gets extended if we then see l3 where l3 is the successor
476    // to l2.
477    let mut open_location: Option<(Location, Location)> = None;
478
479    let mut sep = "";
480    let mut push_sep = |s: &mut String| {
481        s.push_str(sep);
482        sep = ", ";
483    };
484
485    for element in elements {
486        match element {
487            RegionElement::Location(l) => {
488                if let Some((location1, location2)) = open_location {
489                    if location2.block == l.block
490                        && location2.statement_index == l.statement_index - 1
491                    {
492                        open_location = Some((location1, l));
493                        continue;
494                    }
495
496                    push_sep(&mut result);
497                    push_location_range(&mut result, location1, location2);
498                }
499
500                open_location = Some((l, l));
501            }
502
503            RegionElement::RootUniversalRegion(fr) => {
504                if let Some((location1, location2)) = open_location {
505                    push_sep(&mut result);
506                    push_location_range(&mut result, location1, location2);
507                    open_location = None;
508                }
509
510                push_sep(&mut result);
511                result.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", fr))
    })format!("{fr:?}"));
512            }
513
514            RegionElement::PlaceholderRegion(placeholder) => {
515                if let Some((location1, location2)) = open_location {
516                    push_sep(&mut result);
517                    push_location_range(&mut result, location1, location2);
518                    open_location = None;
519                }
520
521                push_sep(&mut result);
522                result.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", placeholder))
    })format!("{placeholder:?}"));
523            }
524        }
525    }
526
527    if let Some((location1, location2)) = open_location {
528        push_sep(&mut result);
529        push_location_range(&mut result, location1, location2);
530    }
531
532    result.push('}');
533
534    return result;
535
536    fn push_location_range(s: &mut String, location1: Location, location2: Location) {
537        if location1 == location2 {
538            s.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", location1))
    })format!("{location1:?}"));
539        } else {
540            match (&location1.block, &location2.block) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(location1.block, location2.block);
541            s.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}[{1}..={2}]", location1.block,
                location1.statement_index, location2.statement_index))
    })format!(
542                "{:?}[{}..={}]",
543                location1.block, location1.statement_index, location2.statement_index
544            ));
545        }
546    }
547}