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::polonius::LiveLoans;
14use crate::{BorrowIndex, TyCtxt};
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 `location`.
135pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool {
136let point = self.location_map.point_from_location(location);
137if let Some(points) = &self.points {
138points.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 }
145146/// Returns an iterator of all the points where `region` is live.
147fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> {
148let 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 };
153points154 .row(region)
155 .into_iter()
156 .flat_map(|set| set.iter())
157 .take_while(|&p| self.location_map.point_in_range(p))
158 }
159160/// For debugging purposes, returns a pretty-printed string of the points where the `region` is
161 /// live.
162pub(crate) fn pretty_print_live_points(&self, region: RegionVid) -> String {
163pretty_print_region_elements(
164self.live_points(region)
165 .map(|p| RegionElement::Location(self.location_map.to_location(p))),
166 )
167 }
168169#[inline]
170pub(crate) fn point_from_location(&self, location: Location) -> PointIndex {
171self.location_map.point_from_location(location)
172 }
173174#[inline]
175pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
176self.location_map.to_location(point)
177 }
178179/// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active
180 /// loans dataflow computations.
181pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) {
182self.live_loans = Some(live_loans);
183 }
184185/// When using `-Zpolonius=next`, returns whether the `loan_idx` is live at the given `point`.
186pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, point: PointIndex) -> bool {
187self.live_loans
188 .as_ref()
189 .expect("Accessing live loans requires `-Zpolonius=next`")
190 .contains(point, loan_idx)
191 }
192}
193194/// 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}
202203impl<'tcx> PlaceholderIndices<'tcx> {
204/// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
205pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion<'tcx>) -> PlaceholderIndex {
206let (index, _) = self.indices.insert_full(placeholder);
207index.into()
208 }
209210pub(crate) fn lookup_index(
211&self,
212 placeholder: ty::PlaceholderRegion<'tcx>,
213 ) -> PlaceholderIndex {
214self.indices.get_index_of(&placeholder).unwrap().into()
215 }
216217pub(crate) fn lookup_placeholder(
218&self,
219 placeholder: PlaceholderIndex,
220 ) -> ty::PlaceholderRegion<'tcx> {
221self.indices[placeholder.index()]
222 }
223224pub(crate) fn len(&self) -> usize {
225self.indices.len()
226 }
227}
228229/// 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>,
252253/// Placeholders represent bound regions -- so something like `'a`
254 /// in `for<'a> fn(&'a u32)`.
255placeholders: SparseBitMatrix<N, PlaceholderIndex>,
256}
257258impl<'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.
262pub(crate) fn new(
263 location_map: Rc<DenseLocationMap>,
264 num_universal_regions: usize,
265 placeholder_indices: PlaceholderIndices<'tcx>,
266 ) -> Self {
267let num_points = location_map.num_points();
268let num_placeholders = placeholder_indices.len();
269Self {
270location_map,
271 points: SparseIntervalMatrix::new(num_points),
272placeholder_indices,
273 free_regions: SparseBitMatrix::new(num_universal_regions),
274 placeholders: SparseBitMatrix::new(num_placeholders),
275 }
276 }
277278/// 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).
280pub(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);
282elem.add_to_row(self, r)
283 }
284285/// Adds all the control-flow points to the values for `r`.
286pub(crate) fn add_all_points(&mut self, r: N) {
287self.points.insert_all_into_row(r);
288 }
289290/// Adds all elements in `r_from` to `r_to` (because e.g., `r_to:
291 /// r_from`).
292pub(crate) fn add_region(&mut self, r_to: N, r_from: N) -> bool {
293self.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 }
297298/// Returns `true` if the region `r` contains the given element.
299pub(crate) fn contains(&self, r: N, elem: impl ToElementIndex<'tcx>) -> bool {
300elem.contained_in_row(self, r)
301 }
302303/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
304pub(crate) fn first_non_contained_inclusive(
305&self,
306 r: N,
307 block: BasicBlock,
308 start: usize,
309 end: usize,
310 ) -> Option<usize> {
311let row = self.points.row(r)?;
312let block = self.location_map.entry_point(block);
313let start = block.plus(start);
314let end = block.plus(end);
315let first_unset = row.first_unset_in(start..=end)?;
316Some(first_unset.index() - block.index())
317 }
318319/// `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`.
322pub(crate) fn merge_liveness(&mut self, to: N, from: RegionVid, values: &LivenessValues) {
323let 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 };
326if let Some(set) = value_points.row(from) {
327self.points.union_row(to, set);
328 }
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.row(r).into_iter().flat_map(move |set| {
350set.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 }
355356/// Returns just the universal regions that are contained in a given region's value.
357pub(crate) fn universal_regions_outlived_by(&self, r: N) -> impl Iterator<Item = RegionVid> {
358self.free_regions.row(r).into_iter().flat_map(|set| set.iter())
359 }
360361/// Returns all the elements contained in a given region's value.
362pub(crate) fn placeholders_contained_in(
363&self,
364 r: N,
365 ) -> impl Iterator<Item = ty::PlaceholderRegion<'tcx>> {
366self.placeholders
367 .row(r)
368 .into_iter()
369 .flat_map(|set| set.iter())
370 .map(move |p| self.placeholder_indices.lookup_placeholder(p))
371 }
372373/// Returns all the elements contained in a given region's value.
374pub(crate) fn elements_contained_in(&self, r: N) -> impl Iterator<Item = RegionElement<'tcx>> {
375let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
376377let free_regions_iter =
378self.universal_regions_outlived_by(r).map(RegionElement::RootUniversalRegion);
379380let placeholder_universes_iter =
381self.placeholders_contained_in(r).map(RegionElement::PlaceholderRegion);
382383points_iter.chain(free_regions_iter).chain(placeholder_universes_iter)
384 }
385386/// Returns a "pretty" string value of the region. Meant for debugging.
387pub(crate) fn region_value_str(&self, r: N) -> String {
388pretty_print_region_elements(self.elements_contained_in(r))
389 }
390}
391392pub(crate) trait ToElementIndex<'tcx>: Debug + Copy {
393fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool;
394395fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool;
396}
397398impl ToElementIndex<'_> for Location {
399fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
400let index = values.location_map.point_from_location(self);
401values.points.insert(row, index)
402 }
403404fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
405let index = values.location_map.point_from_location(self);
406values.points.contains(row, index)
407 }
408}
409410impl ToElementIndex<'_> for RegionVid {
411fn add_to_row<N: Idx>(self, values: &mut RegionValues<'_, N>, row: N) -> bool {
412values.free_regions.insert(row, self)
413 }
414415fn contained_in_row<N: Idx>(self, values: &RegionValues<'_, N>, row: N) -> bool {
416values.free_regions.contains(row, self)
417 }
418}
419420impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> {
421fn add_to_row<N: Idx>(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool422where
423Self: Into<ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion>>,
424 {
425let placeholder: ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion> = self.into();
426let index = values.placeholder_indices.lookup_index(placeholder);
427values.placeholders.insert(row, index)
428 }
429430fn contained_in_row<N: Idx>(self, values: &RegionValues<'tcx, N>, row: N) -> bool431where
432Self: Into<ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion>>,
433 {
434let placeholder: ty::Placeholder<TyCtxt<'tcx>, ty::BoundRegion> = self.into();
435let index = values.placeholder_indices.lookup_index(placeholder);
436values.placeholders.contains(row, index)
437 }
438}
439440/// 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 {
445pretty_print_region_elements(
446points447 .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}
453454/// 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 {
458let mut result = String::new();
459result.push('{');
460461// 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.
465let mut open_location: Option<(Location, Location)> = None;
466467let mut sep = "";
468let mut push_sep = |s: &mut String| {
469s.push_str(sep);
470sep = ", ";
471 };
472473for element in elements {
474match element {
475 RegionElement::Location(l) => {
476if let Some((location1, location2)) = open_location {
477if location2.block == l.block
478 && location2.statement_index == l.statement_index - 1
479{
480 open_location = Some((location1, l));
481continue;
482 }
483484 push_sep(&mut result);
485 push_location_range(&mut result, location1, location2);
486 }
487488 open_location = Some((l, l));
489 }
490491 RegionElement::RootUniversalRegion(fr) => {
492if let Some((location1, location2)) = open_location {
493 push_sep(&mut result);
494 push_location_range(&mut result, location1, location2);
495 open_location = None;
496 }
497498 push_sep(&mut result);
499 result.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", fr))
})format!("{fr:?}"));
500 }
501502 RegionElement::PlaceholderRegion(placeholder) => {
503if let Some((location1, location2)) = open_location {
504 push_sep(&mut result);
505 push_location_range(&mut result, location1, location2);
506 open_location = None;
507 }
508509 push_sep(&mut result);
510 result.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", placeholder))
})format!("{placeholder:?}"));
511 }
512 }
513 }
514515if let Some((location1, location2)) = open_location {
516push_sep(&mut result);
517push_location_range(&mut result, location1, location2);
518 }
519520result.push('}');
521522return result;
523524fn push_location_range(s: &mut String, location1: Location, location2: Location) {
525if location1 == location2 {
526s.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", location1))
})format!("{location1:?}"));
527 } else {
528match (&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);
529s.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}