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::mir::{BasicBlock, Location};
9use rustc_middle::ty::{self, RegionVid};
10use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
11use tracing::debug;
12
13use crate::BorrowIndex;
14use crate::polonius::LiveLoans;
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
135    /// [`location`][rustc_middle::mir::Location].
136    pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
137        let point = self.location_map.point_from_location(location);
138        self.is_live_at_point(region, point)
139    }
140
141    /// Returns whether `region` is marked live at the given
142    /// [`point`][rustc_mir_dataflow::points::PointIndex].
143    #[inline]
144    pub(crate) fn is_live_at_point(&self, region: RegionVid, point: PointIndex) -> bool {
145        if let Some(points) = &self.points {
146            points.row(region).is_some_and(|r| r.contains(point))
147        } else {
148            {
    ::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!(
149                "Should be using LivenessValues::with_specific_points to ask whether live at a location"
150            )
151        }
152    }
153
154    /// Returns an iterator of all the points where `region` is live.
155    fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> {
156        let Some(points) = &self.points else {
157            {
    ::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!(
158                "Should be using LivenessValues::with_specific_points to ask whether live at a location"
159            )
160        };
161        points
162            .row(region)
163            .into_iter()
164            .flat_map(|set| set.iter())
165            .take_while(|&p| self.location_map.point_in_range(p))
166    }
167
168    /// For debugging purposes, returns a pretty-printed string of the points where the `region` is
169    /// live.
170    pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String {
171        pretty_print_region_elements(
172            self.live_points(region)
173                .map(|p| RegionElement::Location(self.location_map.to_location(p))),
174        )
175    }
176
177    #[inline]
178    pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
179        self.location_map.point_from_location(location)
180    }
181
182    #[inline]
183    pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
184        self.location_map.to_location(point)
185    }
186
187    /// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active
188    /// loans dataflow computations.
189    pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) {
190        self.live_loans = Some(live_loans);
191    }
192
193    /// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
194    pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
195        self.live_loans
196            .as_ref()
197            .expect("Accessing live loans requires `-Zpolonius=next`")
198            .contains(point, loan_idx)
199    }
200}
201
202/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
203/// rustc to the internal `PlaceholderIndex` values that are used in
204/// NLL.
205#[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)]
206#[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)
207pub(crate) struct PlaceholderIndices<'tcx> {
208    indices: FxIndexSet<ty::PlaceholderRegion<'tcx>>,
209}
210
211impl<'tcx> PlaceholderIndices<'tcx> {
212    /// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
213    pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion<'tcx>) -> PlaceholderIndex {
214        let (index, _) = self.indices.insert_full(placeholder);
215        index.into()
216    }
217
218    pub(crate) fn lookup_index(
219        &self,
220        placeholder: ty::PlaceholderRegion<'tcx>,
221    ) -> PlaceholderIndex {
222        self.indices.get_index_of(&placeholder).unwrap().into()
223    }
224
225    pub(crate) fn lookup_placeholder(
226        &self,
227        placeholder: PlaceholderIndex,
228    ) -> ty::PlaceholderRegion<'tcx> {
229        self.indices[placeholder.index()]
230    }
231
232    pub(crate) fn len(&self) -> usize {
233        self.indices.len()
234    }
235}
236
237/// Stores the full values for a set of regions (in contrast to
238/// `LivenessValues`, which only stores those points in the where a
239/// region is live). The full value for a region may contain points in
240/// the CFG, but also free regions as well as bound universe
241/// placeholders.
242///
243/// Example:
244///
245/// ```text
246/// fn foo(x: &'a u32) -> &'a u32 {
247///    let y: &'0 u32 = x; // let's call this `'0`
248///    y
249/// }
250/// ```
251///
252/// Here, the variable `'0` would contain the free region `'a`,
253/// because (since it is returned) it must live for at least `'a`. But
254/// it would also contain various points from within the function.
255pub(crate) struct RegionValues<'tcx, N: Idx> {
256    location_map: Rc<DenseLocationMap>,
257    placeholder_indices: PlaceholderIndices<'tcx>,
258    points: SparseIntervalMatrix<N, PointIndex>,
259    free_regions: SparseBitMatrix<N, RegionVid>,
260
261    /// Placeholders represent bound regions -- so something like `'a`
262    /// in `for<'a> fn(&'a u32)`.
263    placeholders: SparseBitMatrix<N, PlaceholderIndex>,
264}
265
266impl<'tcx, N: Idx> RegionValues<'tcx, N> {
267    /// Creates a new set of "region values" that tracks causal information.
268    /// Each of the regions in num_region_variables will be initialized with an
269    /// empty set of points and no causal information.
270    pub(crate) fn new(
271        location_map: Rc<DenseLocationMap>,
272        num_universal_regions: usize,
273        placeholder_indices: PlaceholderIndices<'tcx>,
274    ) -> Self {
275        let num_points = location_map.num_points();
276        let num_placeholders = placeholder_indices.len();
277        Self {
278            location_map,
279            points: SparseIntervalMatrix::new(num_points),
280            placeholder_indices,
281            free_regions: SparseBitMatrix::new(num_universal_regions),
282            placeholders: SparseBitMatrix::new(num_placeholders),
283        }
284    }
285
286    /// Adds the given element to the value for the given region. Returns whether
287    /// the element is newly added (i.e., was not already present).
288    pub(crate) fn add_element(&mut self, r: N, elem: impl ToElementIndex<'tcx>) -> bool {
289        {
    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:289",
                        "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(289u32),
                        ::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);
290        elem.add_to_row(self, r)
291    }
292
293    /// Adds all the control-flow points to the values for `r`.
294    pub(crate) fn add_all_points(&mut self, r: N) {
295        self.points.insert_all_into_row(r);
296    }
297
298    /// Adds all elements in `r_from` to `r_to` (because e.g., `r_to:
299    /// r_from`).
300    pub(crate) fn add_region(&mut self, r_to: N, r_from: N) -> bool {
301        self.points.union_rows(r_from, r_to)
302            | self.free_regions.union_rows(r_from, r_to)
303            | self.placeholders.union_rows(r_from, r_to)
304    }
305
306    /// Returns `true` if the region `r` contains the given element.
307    pub(crate) fn contains(&self, r: N, elem: impl ToElementIndex<'tcx>) -> bool {
308        elem.contained_in_row(self, r)
309    }
310
311    /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
312    pub(crate) fn first_non_contained_inclusive(
313        &self,
314        r: N,
315        block: BasicBlock,
316        start: usize,
317        end: usize,
318    ) -> Option<usize> {
319        let row = self.points.row(r)?;
320        let block = self.location_map.entry_point(block);
321        let start = block.plus(start);
322        let end = block.plus(end);
323        let first_unset = row.first_unset_in(start..=end)?;
324        Some(first_unset.index() - block.index())
325    }
326
327    /// `self[to] |= values[from]`, essentially: that is, take all the
328    /// elements for the region `from` from `values` and add them to
329    /// the region `to` in `self`.
330    pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
331        let Some(value_points) = &values.points else {
332            {
    ::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");
333        };
334        if let Some(set) = value_points.row(from) {
335            self.points.union_row(to, set);
336        }
337    }
338
339    /// Returns `true` if `sup_region` contains all the CFG points that
340    /// `sub_region` contains. Ignores universal regions.
341    pub(crate) fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
342        if let Some(sub_row) = self.points.row(sub_region) {
343            if let Some(sup_row) = self.points.row(sup_region) {
344                sup_row.superset(sub_row)
345            } else {
346                // sup row is empty, so sub row must be empty
347                sub_row.is_empty()
348            }
349        } else {
350            // sub row is empty, always true
351            true
352        }
353    }
354
355    /// Returns the locations contained within a given region `r`.
356    pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> {
357        self.points.row(r).into_iter().flat_map(move |set| {
358            set.iter()
359                .take_while(move |&p| self.location_map.point_in_range(p))
360                .map(move |p| self.location_map.to_location(p))
361        })
362    }
363
364    /// Returns just the universal regions that are contained in a given region's value.
365    pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator<Item = RegionVid> {
366        self.free_regions.row(r).into_iter().flat_map(|set| set.iter())
367    }
368
369    /// Returns all the elements contained in a given region's value.
370    pub(crate) fn placeholders_contained_in(
371        &self,
372        r: N,
373    ) -> impl Iterator<Item = ty::PlaceholderRegion<'tcx>> {
374        self.placeholders
375            .row(r)
376            .into_iter()
377            .flat_map(|set| set.iter())
378            .map(move |p| self.placeholder_indices.lookup_placeholder(p))
379    }
380
381    /// Returns all the elements contained in a given region's value.
382    pub(crate) fn elements_contained_in(&self, r: N) -> impl Iterator<Item = RegionElement<'tcx>> {
383        let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
384
385        let free_regions_iter =
386            self.universal_regions_outlived_by(r).map(RegionElement::RootUniversalRegion);
387
388        let placeholder_universes_iter =
389            self.placeholders_contained_in(r).map(RegionElement::PlaceholderRegion);
390
391        points_iter.chain(free_regions_iter).chain(placeholder_universes_iter)
392    }
393
394    /// Returns a "pretty" string value of the region. Meant for debugging.
395    pub(crate) fn region_value_str(&self, r: N) -> String {
396        pretty_print_region_elements(self.elements_contained_in(r))
397    }
398}
399
400pub(crate) trait ToElementIndex<'tcx>: Debug + Copy {
401    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool;
402
403    fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool;
404}
405
406impl ToElementIndex<'_> for Location {
407    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
408        let index = values.location_map.point_from_location(self);
409        values.points.insert(row, index)
410    }
411
412    fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
413        let index = values.location_map.point_from_location(self);
414        values.points.contains(row, index)
415    }
416}
417
418impl ToElementIndex<'_> for RegionVid {
419    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
420        values.free_regions.insert(row, self)
421    }
422
423    fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
424        values.free_regions.contains(row, self)
425    }
426}
427
428impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> {
429    fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool
430    where
431        Self: Into<ty::PlaceholderRegion<'tcx>>,
432    {
433        let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
434        let index = values.placeholder_indices.lookup_index(placeholder);
435        values.placeholders.insert(row, index)
436    }
437
438    fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool
439    where
440        Self: Into<ty::PlaceholderRegion<'tcx>>,
441    {
442        let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
443        let index = values.placeholder_indices.lookup_index(placeholder);
444        values.placeholders.contains(row, index)
445    }
446}
447
448/// For debugging purposes, returns a pretty-printed string of the given points.
449pub(crate) fn pretty_print_points(
450    location_map: &DenseLocationMap,
451    points: impl IntoIterator<Item = PointIndex>,
452) -> String {
453    pretty_print_region_elements(
454        points
455            .into_iter()
456            .take_while(|&p| location_map.point_in_range(p))
457            .map(|p| location_map.to_location(p))
458            .map(RegionElement::Location),
459    )
460}
461
462/// For debugging purposes, returns a pretty-printed string of the given region elements.
463fn pretty_print_region_elements<'tcx>(
464    elements: impl IntoIterator<Item = RegionElement<'tcx>>,
465) -> String {
466    let mut result = String::new();
467    result.push('{');
468
469    // Set to Some(l1, l2) when we have observed all the locations
470    // from l1..=l2 (inclusive) but not yet printed them. This
471    // gets extended if we then see l3 where l3 is the successor
472    // to l2.
473    let mut open_location: Option<(Location, Location)> = None;
474
475    let mut sep = "";
476    let mut push_sep = |s: &mut String| {
477        s.push_str(sep);
478        sep = ", ";
479    };
480
481    for element in elements {
482        match element {
483            RegionElement::Location(l) => {
484                if let Some((location1, location2)) = open_location {
485                    if location2.block == l.block
486                        && location2.statement_index == l.statement_index - 1
487                    {
488                        open_location = Some((location1, l));
489                        continue;
490                    }
491
492                    push_sep(&mut result);
493                    push_location_range(&mut result, location1, location2);
494                }
495
496                open_location = Some((l, l));
497            }
498
499            RegionElement::RootUniversalRegion(fr) => {
500                if let Some((location1, location2)) = open_location {
501                    push_sep(&mut result);
502                    push_location_range(&mut result, location1, location2);
503                    open_location = None;
504                }
505
506                push_sep(&mut result);
507                result.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", fr))
    })format!("{fr:?}"));
508            }
509
510            RegionElement::PlaceholderRegion(placeholder) => {
511                if let Some((location1, location2)) = open_location {
512                    push_sep(&mut result);
513                    push_location_range(&mut result, location1, location2);
514                    open_location = None;
515                }
516
517                push_sep(&mut result);
518                result.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", placeholder))
    })format!("{placeholder:?}"));
519            }
520        }
521    }
522
523    if let Some((location1, location2)) = open_location {
524        push_sep(&mut result);
525        push_location_range(&mut result, location1, location2);
526    }
527
528    result.push('}');
529
530    return result;
531
532    fn push_location_range(s: &mut String, location1: Location, location2: Location) {
533        if location1 == location2 {
534            s.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}", location1))
    })format!("{location1:?}"));
535        } else {
536            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);
537            s.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:?}[{1}..={2}]", location1.block,
                location1.statement_index, location2.statement_index))
    })format!(
538                "{:?}[{}..={}]",
539                location1.block, location1.statement_index, location2.statement_index
540            ));
541        }
542    }
543}