1use std::fmt::Debug;
2use std::rc::Rc;
34use 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, instrument};
1314use crate::BorrowIndex;
15use crate::polonius::LiveLoans;
1617impl ::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({})"]
20pub(crate) struct PlaceholderIndex {}
21}2223/// 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.
28Location(Location),
2930/// A universally quantified region from the root universe (e.g.,
31 /// a lifetime parameter).
32RootUniversalRegion(RegionVid),
3334/// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)`
35 /// type).
36PlaceholderRegion(ty::PlaceholderRegion<'tcx>),
37}
3839/// 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`.
45AtPoints(SparseIntervalMatrix<RegionVid, PointIndex>),
46/// Region `'r` is live in function body.
47InBody(FxHashSet<RegionVid>),
48}
4950/// 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.
55location_map: Rc<DenseLocationMap>,
5657/// Where a region is live.
58live_regions: LiveRegions,
5960/// When using `-Zpolonius=next`, the set of loans that are live at a given point in the CFG.
61live_loans: Option<LiveLoans>,
62}
6364impl LivenessValues {
65/// Create an empty map of regions to locations where they're live.
66pub(crate) fn with_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
67LivenessValues {
68 live_regions: LiveRegions::AtPoints(SparseIntervalMatrix::new(
69location_map.num_points(),
70 )),
71location_map,
72 live_loans: None,
73 }
74 }
7576/// 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.
80pub(crate) fn without_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
81LivenessValues {
82 live_regions: LiveRegions::InBody(Default::default()),
83location_map,
84 live_loans: None,
85 }
86 }
8788/// 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).
90pub(crate) fn points(&self) -> &SparseIntervalMatrix<RegionVid, PointIndex> {
91if let LiveRegions::AtPoints(points) = &self.live_regions {
92points93 } 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 }
9798/// Get the liveness status of a region `r`, if any.
99 /// Panics if liveness data is not tracked for any region.
100pub(crate) fn point_liveness(&self, region: RegionVid) -> Option<&IntervalSet<PointIndex>> {
101self.points().row(region)
102 }
103104/// Iterate through each region that has a value in this set.
105// We are passing query instability implications to the caller.
106#[rustc_lint_query_instability]
107 #[allow(rustc::potential_query_instability)]
108pub(crate) fn live_regions_unordered(&self) -> impl Iterator<Item = RegionVid> {
109if let LiveRegions::InBody(live_regions) = &self.live_regions {
110live_regions.iter().copied()
111 } else {
112::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`")113 }
114 }
115116/// Records `region` as being live at the given `location`.
117pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
118let point = self.location_map.point_from_location(location);
119// This is a debug assert despite being cheap because it drops
120 // the current `point_in_range()` uses to 0 when debugging is off.
121if true {
if !self.location_map.point_in_range(point) {
{
::core::panicking::panic_fmt(format_args!("Tried inserting region {0:?} whose location {1:?} does not belong to this body!",
region, location));
}
};
};debug_assert!(
122self.location_map.point_in_range(point),
123"Tried inserting region {region:?} whose location {location:?} does not belong to this body!"
124);
125{
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:125",
"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(125u32),
::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);
126match &mut self.live_regions {
127 LiveRegions::AtPoints(points) => {
128points.insert(region, point);
129 }
130131 LiveRegions::InBody(live_regions) => {
132live_regions.insert(region);
133 }
134 };
135 }
136137/// Records `region` as being live at all the given `points`.
138pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
139if true {
if !points.iter().all(|point| self.location_map.point_in_range(point)) {
{
::core::panicking::panic_fmt(format_args!("Tried inserting region {0:?} with some points not belonging to this body!",
region));
}
};
};debug_assert!(
140 points.iter().all(|point| self.location_map.point_in_range(point)),
141"Tried inserting region {region:?} with some points not belonging to this body!"
142);
143{
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:143",
"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(143u32),
::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);
144match &mut self.live_regions {
145 LiveRegions::AtPoints(these_points) => {
146these_points.union_row(region, points);
147 }
148 LiveRegions::InBody(live_regions) => {
149live_regions.insert(region);
150 }
151 };
152 }
153154/// Records `region` as being live at all the control-flow points.
155#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("add_all_points",
"rustc_borrowck::region_infer::values",
::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/values.rs"),
::tracing_core::__macro_support::Option::Some(155u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::values"),
::tracing_core::field::FieldSet::new(&["region"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(®ion)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match &mut self.live_regions {
LiveRegions::AtPoints(points) =>
points.insert_all_into_row(region),
LiveRegions::InBody(live_regions) => {
live_regions.insert(region);
}
}
}
}
}#[instrument(skip(self))]156pub(crate) fn add_all_points(&mut self, region: RegionVid) {
157match &mut self.live_regions {
158 LiveRegions::AtPoints(points) => points.insert_all_into_row(region),
159 LiveRegions::InBody(live_regions) => {
160 live_regions.insert(region);
161 }
162 }
163 }
164165/// Returns whether `region` is marked live at the given
166 /// [`location`][rustc_middle::mir::Location].
167pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
168let point = self.location_map.point_from_location(location);
169self.is_live_at_point(region, point)
170 }
171172/// Returns whether `region` is marked live at the given
173 /// [`point`][rustc_mir_dataflow::points::PointIndex].
174#[inline]
175pub(crate) fn is_live_at_point(&self, region: RegionVid, point: PointIndex) -> bool {
176self.point_liveness(region).is_some_and(|r| r.contains(point))
177 }
178179/// Returns an iterator of all the points where `region` is live.
180fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> {
181self.point_liveness(region).into_iter().flat_map(|set| set.iter())
182 }
183184/// For debugging purposes, returns a pretty-printed string of the points where the `region` is
185 /// live.
186pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String {
187pretty_print_region_elements(
188self.live_points(region)
189 .map(|p| RegionElement::Location(self.location_map.to_location(p))),
190 )
191 }
192193#[inline]
194pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
195self.location_map.point_from_location(location)
196 }
197198#[inline]
199pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
200self.location_map.to_location(point)
201 }
202203/// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active
204 /// loans dataflow computations.
205pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) {
206self.live_loans = Some(live_loans);
207 }
208209/// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
210pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
211self.live_loans
212 .as_ref()
213 .expect("Accessing live loans requires `-Zpolonius=next`")
214 .contains(point, loan_idx)
215 }
216}
217218/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
219/// rustc to the internal `PlaceholderIndex` values that are used in
220/// NLL.
221#[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)]
222#[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)
223pub(crate) struct PlaceholderIndices<'tcx> {
224 indices: FxIndexSet<ty::PlaceholderRegion<'tcx>>,
225}
226227impl<'tcx> PlaceholderIndices<'tcx> {
228/// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
229pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion<'tcx>) -> PlaceholderIndex {
230let (index, _) = self.indices.insert_full(placeholder);
231index.into()
232 }
233234pub(crate) fn lookup_index(
235&self,
236 placeholder: ty::PlaceholderRegion<'tcx>,
237 ) -> PlaceholderIndex {
238self.indices.get_index_of(&placeholder).unwrap().into()
239 }
240241pub(crate) fn lookup_placeholder(
242&self,
243 placeholder: PlaceholderIndex,
244 ) -> ty::PlaceholderRegion<'tcx> {
245self.indices[placeholder.index()]
246 }
247248pub(crate) fn len(&self) -> usize {
249self.indices.len()
250 }
251}
252253/// Stores the full values for a set of regions (in contrast to
254/// `LivenessValues`, which only stores those points in the where a
255/// region is live). The full value for a region may contain points in
256/// the CFG, but also free regions as well as bound universe
257/// placeholders.
258///
259/// Example:
260///
261/// ```text
262/// fn foo(x: &'a u32) -> &'a u32 {
263/// let y: &'0 u32 = x; // let's call this `'0`
264/// y
265/// }
266/// ```
267///
268/// Here, the variable `'0` would contain the free region `'a`,
269/// because (since it is returned) it must live for at least `'a`. But
270/// it would also contain various points from within the function.
271pub(crate) struct RegionValues<'tcx, N: Idx> {
272 location_map: Rc<DenseLocationMap>,
273 placeholder_indices: PlaceholderIndices<'tcx>,
274 points: SparseIntervalMatrix<N, PointIndex>,
275 free_regions: SparseBitMatrix<N, RegionVid>,
276277/// Placeholders represent bound regions -- so something like `'a`
278 /// in `for<'a> fn(&'a u32)`.
279placeholders: SparseBitMatrix<N, PlaceholderIndex>,
280}
281282impl<'tcx, N: Idx> RegionValues<'tcx, N> {
283/// Creates a new set of "region values" that tracks causal information.
284 /// Each of the regions in num_region_variables will be initialized with an
285 /// empty set of points and no causal information.
286pub(crate) fn new(
287 location_map: Rc<DenseLocationMap>,
288 num_universal_regions: usize,
289 placeholder_indices: PlaceholderIndices<'tcx>,
290 ) -> Self {
291let num_points = location_map.num_points();
292let num_placeholders = placeholder_indices.len();
293Self {
294location_map,
295 points: SparseIntervalMatrix::new(num_points),
296placeholder_indices,
297 free_regions: SparseBitMatrix::new(num_universal_regions),
298 placeholders: SparseBitMatrix::new(num_placeholders),
299 }
300 }
301302/// Adds all elements in `r_from` to `r_to` (because e.g., `r_to:
303 /// r_from`).
304pub(crate) fn add_region(&mut self, r_to: N, r_from: N) -> bool {
305self.points.union_rows(r_from, r_to)
306 | self.free_regions.union_rows(r_from, r_to)
307 | self.placeholders.union_rows(r_from, r_to)
308 }
309310/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
311pub(crate) fn first_non_contained_inclusive(
312&self,
313 r: N,
314 block: BasicBlock,
315 start: usize,
316 end: usize,
317 ) -> Option<usize> {
318let row = self.points.row(r)?;
319let block = self.location_map.entry_point(block);
320let start = block.plus(start);
321let end = block.plus(end);
322let first_unset = row.first_unset_in(start..=end)?;
323Some(first_unset.index() - block.index())
324 }
325326/// Merge a row of liveness into our points.
327pub(crate) fn merge_liveness(&mut self, to: N, liveness: &IntervalSet<PointIndex>) {
328self.points.union_row(to, liveness);
329 }
330331/// Returns `true` if `sup_region` contains all the CFG points that
332 /// `sub_region` contains. Ignores universal regions.
333pub(crate) fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
334if let Some(sub_row) = self.points.row(sub_region) {
335if let Some(sup_row) = self.points.row(sup_region) {
336sup_row.superset(sub_row)
337 } else {
338// sup row is empty, so sub row must be empty
339sub_row.is_empty()
340 }
341 } else {
342// sub row is empty, always true
343true
344}
345 }
346347/// Returns the locations contained within a given region `r`.
348pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> {
349self.points
350 .row(r)
351 .into_iter()
352 .flat_map(move |set| set.iter().map(move |p| self.location_map.to_location(p)))
353 }
354355/// Returns just the universal regions that are contained in a given region's value.
356pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator<Item = RegionVid> {
357self.free_regions.row(r).into_iter().flat_map(|set| set.iter())
358 }
359360/// Returns all the elements contained in a given region's value.
361pub(crate) fn placeholders_contained_in(
362&self,
363 r: N,
364 ) -> impl Iterator<Item = ty::PlaceholderRegion<'tcx>> {
365self.placeholders
366 .row(r)
367 .into_iter()
368 .flat_map(|set| set.iter())
369 .map(move |p| self.placeholder_indices.lookup_placeholder(p))
370 }
371372/// Returns all the elements contained in a given region's value.
373pub(crate) fn elements_contained_in(&self, r: N) -> impl Iterator<Item = RegionElement<'tcx>> {
374let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
375376let free_regions_iter =
377self.universal_regions_outlived_by(r).map(RegionElement::RootUniversalRegion);
378379let placeholder_universes_iter =
380self.placeholders_contained_in(r).map(RegionElement::PlaceholderRegion);
381382points_iter.chain(free_regions_iter).chain(placeholder_universes_iter)
383 }
384385/// Returns a "pretty" string value of the region. Meant for debugging.
386pub(crate) fn region_value_str(&self, r: N) -> String {
387pretty_print_region_elements(self.elements_contained_in(r))
388 }
389390/// Add a the free region with rvid `region` to SCC `scc`
391pub(crate) fn add_free_region(&mut self, scc: N, region: RegionVid) {
392self.free_regions.insert(scc, region);
393 }
394395pub(crate) fn add_placeholder(&mut self, scc: N, placeholder: ty::PlaceholderRegion<'tcx>) {
396let index = self.placeholder_indices.lookup_index(placeholder);
397self.placeholders.insert(scc, index);
398 }
399400/// Determine if `scc` contains the CFG point `p`.
401pub(crate) fn contains_point(&self, scc: N, p: Location) -> bool {
402let index = self.location_map.point_from_location(p);
403self.points.contains(scc, index)
404 }
405406/// Determine if `scc` contains the free region `free_region`.
407pub(crate) fn contains_free_region(&self, scc: N, free_region: RegionVid) -> bool {
408self.free_regions.contains(scc, free_region)
409 }
410}
411412/// For debugging purposes, returns a pretty-printed string of the given points.
413pub(crate) fn pretty_print_points(
414 location_map: &DenseLocationMap,
415 points: impl IntoIterator<Item = PointIndex>,
416) -> String {
417pretty_print_region_elements(
418points.into_iter().map(|p| location_map.to_location(p)).map(RegionElement::Location),
419 )
420}
421422/// For debugging purposes, returns a pretty-printed string of the given region elements.
423fn pretty_print_region_elements<'tcx>(
424 elements: impl IntoIterator<Item = RegionElement<'tcx>>,
425) -> String {
426let mut result = String::new();
427result.push('{');
428429// Set to Some(l1, l2) when we have observed all the locations
430 // from l1..=l2 (inclusive) but not yet printed them. This
431 // gets extended if we then see l3 where l3 is the successor
432 // to l2.
433let mut open_location: Option<(Location, Location)> = None;
434435let mut sep = "";
436let mut push_sep = |s: &mut String| {
437s.push_str(sep);
438sep = ", ";
439 };
440441for element in elements {
442match element {
443 RegionElement::Location(l) => {
444if let Some((location1, location2)) = open_location {
445if location2.block == l.block
446 && location2.statement_index == l.statement_index - 1
447{
448 open_location = Some((location1, l));
449continue;
450 }
451452 push_sep(&mut result);
453 push_location_range(&mut result, location1, location2);
454 }
455456 open_location = Some((l, l));
457 }
458459 RegionElement::RootUniversalRegion(fr) => {
460if let Some((location1, location2)) = open_location {
461 push_sep(&mut result);
462 push_location_range(&mut result, location1, location2);
463 open_location = None;
464 }
465466 push_sep(&mut result);
467 result.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", fr))
})format!("{fr:?}"));
468 }
469470 RegionElement::PlaceholderRegion(placeholder) => {
471if let Some((location1, location2)) = open_location {
472 push_sep(&mut result);
473 push_location_range(&mut result, location1, location2);
474 open_location = None;
475 }
476477 push_sep(&mut result);
478 result.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", placeholder))
})format!("{placeholder:?}"));
479 }
480 }
481 }
482483if let Some((location1, location2)) = open_location {
484push_sep(&mut result);
485push_location_range(&mut result, location1, location2);
486 }
487488result.push('}');
489490return result;
491492fn push_location_range(s: &mut String, location1: Location, location2: Location) {
493if location1 == location2 {
494s.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", location1))
})format!("{location1:?}"));
495 } else {
496{
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);
497s.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}[{1}..={2}]", location1.block,
location1.statement_index, location2.statement_index))
})format!(
498"{:?}[{}..={}]",
499 location1.block, location1.statement_index, location2.statement_index
500 ));
501 }
502 }
503}