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