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::mir::{BasicBlock, Location};
9use rustc_middle::ty::{self, RegionVid};
10use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
11use tracing::debug;
1213use crate::BorrowIndex;
14use crate::polonius::LiveLoans;
1516impl ::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({})"]
19pub(crate) struct PlaceholderIndex {}
20}2122/// 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.
27Location(Location),
2829/// A universally quantified region from the root universe (e.g.,
30 /// a lifetime parameter).
31RootUniversalRegion(RegionVid),
3233/// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)`
34 /// type).
35PlaceholderRegion(ty::PlaceholderRegion<'tcx>),
36}
3738/// 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.
43location_map: Rc<DenseLocationMap>,
4445/// 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).
47live_regions: Option<FxHashSet<RegionVid>>,
4849/// 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.
53points: Option<SparseIntervalMatrix<RegionVid, PointIndex>>,
5455/// When using `-Zpolonius=next`, the set of loans that are live at a given point in the CFG.
56live_loans: Option<LiveLoans>,
57}
5859impl LivenessValues {
60/// Create an empty map of regions to locations where they're live.
61pub(crate) fn with_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
62LivenessValues {
63 live_regions: None,
64 points: Some(SparseIntervalMatrix::new(location_map.num_points())),
65location_map,
66 live_loans: None,
67 }
68 }
6970/// 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.
74pub(crate) fn without_specific_points(location_map: Rc<DenseLocationMap>) -> Self {
75LivenessValues {
76 live_regions: Some(Default::default()),
77 points: None,
78location_map,
79 live_loans: None,
80 }
81 }
8283/// 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).
85pub(crate) fn points(&self) -> &SparseIntervalMatrix<RegionVid, PointIndex> {
86self.points
87 .as_ref()
88 .expect("this `LivenessValues` wasn't created using `with_specific_points`")
89 }
9091/// Iterate through each region that has a value in this set.
92pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> {
93self.points.as_ref().expect("use with_specific_points").rows()
94 }
9596/// 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)]
100pub(crate) fn live_regions_unordered(&self) -> impl Iterator<Item = RegionVid> {
101self.live_regions.as_ref().unwrap().iter().copied()
102 }
103104/// Records `region` as being live at the given `location`.
105pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
106let 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);
108if let Some(points) = &mut self.points {
109points.insert(region, point);
110 } else if self.location_map.point_in_range(point) {
111self.live_regions.as_mut().unwrap().insert(region);
112 }
113 }
114115/// Records `region` as being live at all the given `points`.
116pub(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);
118if let Some(this) = &mut self.points {
119this.union_row(region, points);
120 } else if points.iter().any(|point| self.location_map.point_in_range(point)) {
121self.live_regions.as_mut().unwrap().insert(region);
122 }
123 }
124125/// Records `region` as being live at all the control-flow points.
126pub(crate) fn add_all_points(&mut self, region: RegionVid) {
127if let Some(points) = &mut self.points {
128points.insert_all_into_row(region);
129 } else {
130self.live_regions.as_mut().unwrap().insert(region);
131 }
132 }
133134/// Returns whether `region` is marked live at the given
135 /// [`location`][rustc_middle::mir::Location].
136pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
137let point = self.location_map.point_from_location(location);
138self.is_live_at_point(region, point)
139 }
140141/// Returns whether `region` is marked live at the given
142 /// [`point`][rustc_mir_dataflow::points::PointIndex].
143#[inline]
144pub(crate) fn is_live_at_point(&self, region: RegionVid, point: PointIndex) -> bool {
145if let Some(points) = &self.points {
146points.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 }
153154/// Returns an iterator of all the points where `region` is live.
155fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> {
156let 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 };
161points162 .row(region)
163 .into_iter()
164 .flat_map(|set| set.iter())
165 .take_while(|&p| self.location_map.point_in_range(p))
166 }
167168/// For debugging purposes, returns a pretty-printed string of the points where the `region` is
169 /// live.
170pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String {
171pretty_print_region_elements(
172self.live_points(region)
173 .map(|p| RegionElement::Location(self.location_map.to_location(p))),
174 )
175 }
176177#[inline]
178pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
179self.location_map.point_from_location(location)
180 }
181182#[inline]
183pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
184self.location_map.to_location(point)
185 }
186187/// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active
188 /// loans dataflow computations.
189pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) {
190self.live_loans = Some(live_loans);
191 }
192193/// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
194pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
195self.live_loans
196 .as_ref()
197 .expect("Accessing live loans requires `-Zpolonius=next`")
198 .contains(point, loan_idx)
199 }
200}
201202/// 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}
210211impl<'tcx> PlaceholderIndices<'tcx> {
212/// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
213pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion<'tcx>) -> PlaceholderIndex {
214let (index, _) = self.indices.insert_full(placeholder);
215index.into()
216 }
217218pub(crate) fn lookup_index(
219&self,
220 placeholder: ty::PlaceholderRegion<'tcx>,
221 ) -> PlaceholderIndex {
222self.indices.get_index_of(&placeholder).unwrap().into()
223 }
224225pub(crate) fn lookup_placeholder(
226&self,
227 placeholder: PlaceholderIndex,
228 ) -> ty::PlaceholderRegion<'tcx> {
229self.indices[placeholder.index()]
230 }
231232pub(crate) fn len(&self) -> usize {
233self.indices.len()
234 }
235}
236237/// 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>,
260261/// Placeholders represent bound regions -- so something like `'a`
262 /// in `for<'a> fn(&'a u32)`.
263placeholders: SparseBitMatrix<N, PlaceholderIndex>,
264}
265266impl<'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.
270pub(crate) fn new(
271 location_map: Rc<DenseLocationMap>,
272 num_universal_regions: usize,
273 placeholder_indices: PlaceholderIndices<'tcx>,
274 ) -> Self {
275let num_points = location_map.num_points();
276let num_placeholders = placeholder_indices.len();
277Self {
278location_map,
279 points: SparseIntervalMatrix::new(num_points),
280placeholder_indices,
281 free_regions: SparseBitMatrix::new(num_universal_regions),
282 placeholders: SparseBitMatrix::new(num_placeholders),
283 }
284 }
285286/// 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).
288pub(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);
290elem.add_to_row(self, r)
291 }
292293/// Adds all the control-flow points to the values for `r`.
294pub(crate) fn add_all_points(&mut self, r: N) {
295self.points.insert_all_into_row(r);
296 }
297298/// Adds all elements in `r_from` to `r_to` (because e.g., `r_to:
299 /// r_from`).
300pub(crate) fn add_region(&mut self, r_to: N, r_from: N) -> bool {
301self.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 }
305306/// Returns `true` if the region `r` contains the given element.
307pub(crate) fn contains(&self, r: N, elem: impl ToElementIndex<'tcx>) -> bool {
308elem.contained_in_row(self, r)
309 }
310311/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
312pub(crate) fn first_non_contained_inclusive(
313&self,
314 r: N,
315 block: BasicBlock,
316 start: usize,
317 end: usize,
318 ) -> Option<usize> {
319let row = self.points.row(r)?;
320let block = self.location_map.entry_point(block);
321let start = block.plus(start);
322let end = block.plus(end);
323let first_unset = row.first_unset_in(start..=end)?;
324Some(first_unset.index() - block.index())
325 }
326327/// `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`.
330pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
331let 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 };
334if let Some(set) = value_points.row(from) {
335self.points.union_row(to, set);
336 }
337 }
338339/// Returns `true` if `sup_region` contains all the CFG points that
340 /// `sub_region` contains. Ignores universal regions.
341pub(crate) fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
342if let Some(sub_row) = self.points.row(sub_region) {
343if let Some(sup_row) = self.points.row(sup_region) {
344sup_row.superset(sub_row)
345 } else {
346// sup row is empty, so sub row must be empty
347sub_row.is_empty()
348 }
349 } else {
350// sub row is empty, always true
351true
352}
353 }
354355/// Returns the locations contained within a given region `r`.
356pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> {
357self.points.row(r).into_iter().flat_map(move |set| {
358set.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 }
363364/// Returns just the universal regions that are contained in a given region's value.
365pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator<Item = RegionVid> {
366self.free_regions.row(r).into_iter().flat_map(|set| set.iter())
367 }
368369/// Returns all the elements contained in a given region's value.
370pub(crate) fn placeholders_contained_in(
371&self,
372 r: N,
373 ) -> impl Iterator<Item = ty::PlaceholderRegion<'tcx>> {
374self.placeholders
375 .row(r)
376 .into_iter()
377 .flat_map(|set| set.iter())
378 .map(move |p| self.placeholder_indices.lookup_placeholder(p))
379 }
380381/// Returns all the elements contained in a given region's value.
382pub(crate) fn elements_contained_in(&self, r: N) -> impl Iterator<Item = RegionElement<'tcx>> {
383let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
384385let free_regions_iter =
386self.universal_regions_outlived_by(r).map(RegionElement::RootUniversalRegion);
387388let placeholder_universes_iter =
389self.placeholders_contained_in(r).map(RegionElement::PlaceholderRegion);
390391points_iter.chain(free_regions_iter).chain(placeholder_universes_iter)
392 }
393394/// Returns a "pretty" string value of the region. Meant for debugging.
395pub(crate) fn region_value_str(&self, r: N) -> String {
396pretty_print_region_elements(self.elements_contained_in(r))
397 }
398}
399400pub(crate) trait ToElementIndex<'tcx>: Debug + Copy {
401fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool;
402403fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool;
404}
405406impl ToElementIndex<'_> for Location {
407fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
408let index = values.location_map.point_from_location(self);
409values.points.insert(row, index)
410 }
411412fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
413let index = values.location_map.point_from_location(self);
414values.points.contains(row, index)
415 }
416}
417418impl ToElementIndex<'_> for RegionVid {
419fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
420values.free_regions.insert(row, self)
421 }
422423fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
424values.free_regions.contains(row, self)
425 }
426}
427428impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> {
429fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool430where
431Self: Into<ty::PlaceholderRegion<'tcx>>,
432 {
433let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
434let index = values.placeholder_indices.lookup_index(placeholder);
435values.placeholders.insert(row, index)
436 }
437438fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool439where
440Self: Into<ty::PlaceholderRegion<'tcx>>,
441 {
442let placeholder: ty::PlaceholderRegion<'tcx> = self.into();
443let index = values.placeholder_indices.lookup_index(placeholder);
444values.placeholders.contains(row, index)
445 }
446}
447448/// 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 {
453pretty_print_region_elements(
454points455 .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}
461462/// 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 {
466let mut result = String::new();
467result.push('{');
468469// 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.
473let mut open_location: Option<(Location, Location)> = None;
474475let mut sep = "";
476let mut push_sep = |s: &mut String| {
477s.push_str(sep);
478sep = ", ";
479 };
480481for element in elements {
482match element {
483 RegionElement::Location(l) => {
484if let Some((location1, location2)) = open_location {
485if location2.block == l.block
486 && location2.statement_index == l.statement_index - 1
487{
488 open_location = Some((location1, l));
489continue;
490 }
491492 push_sep(&mut result);
493 push_location_range(&mut result, location1, location2);
494 }
495496 open_location = Some((l, l));
497 }
498499 RegionElement::RootUniversalRegion(fr) => {
500if let Some((location1, location2)) = open_location {
501 push_sep(&mut result);
502 push_location_range(&mut result, location1, location2);
503 open_location = None;
504 }
505506 push_sep(&mut result);
507 result.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", fr))
})format!("{fr:?}"));
508 }
509510 RegionElement::PlaceholderRegion(placeholder) => {
511if let Some((location1, location2)) = open_location {
512 push_sep(&mut result);
513 push_location_range(&mut result, location1, location2);
514 open_location = None;
515 }
516517 push_sep(&mut result);
518 result.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", placeholder))
})format!("{placeholder:?}"));
519 }
520 }
521 }
522523if let Some((location1, location2)) = open_location {
524push_sep(&mut result);
525push_location_range(&mut result, location1, location2);
526 }
527528result.push('}');
529530return result;
531532fn push_location_range(s: &mut String, location1: Location, location2: Location) {
533if location1 == location2 {
534s.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", location1))
})format!("{location1:?}"));
535 } else {
536match (&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);
537s.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}