rustc_borrowck/polonius/legacy/
location.rs1use rustc_index::IndexVec;
2use rustc_middle::mir::{BasicBlock, Body, Location};
3use tracing::debug;
4
5pub struct PoloniusLocationTable {
17 num_points: usize,
18 statements_before_block: IndexVec<BasicBlock, usize>,
19}
20
21#[automatically_derived]
impl ::core::marker::Copy for LocationIndex { }
impl LocationIndex {
#[doc = r" Maximum value the index can take, as a `u32`."]
pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
pub const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
pub const fn as_u32(self) -> u32 {
unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for LocationIndex {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for LocationIndex {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for LocationIndex {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for LocationIndex {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for LocationIndex {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for LocationIndex {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<LocationIndex> for u32 {
#[inline]
fn from(v: LocationIndex) -> u32 { v.as_u32() }
}
impl From<LocationIndex> for usize {
#[inline]
fn from(v: LocationIndex) -> usize { v.as_usize() }
}
impl From<usize> for LocationIndex {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for LocationIndex {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for LocationIndex {}
impl ::std::cmp::PartialEq for LocationIndex {
fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for LocationIndex {}
impl ::std::hash::Hash for LocationIndex {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for LocationIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("LocationIndex({0})", self.as_u32()))
}
}rustc_index::newtype_index! {
22 #[orderable]
23 #[debug_format = "LocationIndex({})"]
24 pub struct LocationIndex {}
25}
26
27#[derive(#[automatically_derived]
impl ::core::marker::Copy for RichLocation { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for RichLocation { }
#[automatically_derived]
impl ::core::clone::Clone for RichLocation {
#[inline]
fn clone(&self) -> RichLocation {
let _: ::core::clone::AssertParamIsClone<Location>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for RichLocation {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
RichLocation::Start(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Start",
&__self_0),
RichLocation::Mid(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Mid",
&__self_0),
}
}
}Debug)]
28pub enum RichLocation {
29 Start(Location),
30 Mid(Location),
31}
32
33impl PoloniusLocationTable {
34 pub(crate) fn new(body: &Body<'_>) -> Self {
35 let mut num_points = 0;
36 let statements_before_block = body
37 .basic_blocks
38 .iter()
39 .map(|block_data| {
40 let v = num_points;
41 num_points += (block_data.statements.len() + 1) * 2;
42 v
43 })
44 .collect();
45
46 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_borrowck/src/polonius/legacy/location.rs:46",
"rustc_borrowck::polonius::legacy::location",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_borrowck/src/polonius/legacy/location.rs"),
::tracing_core::__macro_support::Option::Some(46u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::location"),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("PoloniusLocationTable(statements_before_block={0:#?})",
statements_before_block) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("PoloniusLocationTable(statements_before_block={:#?})", statements_before_block);
47 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_borrowck/src/polonius/legacy/location.rs:47",
"rustc_borrowck::polonius::legacy::location",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/a69a63265cfd9e006d43137f98301b8d274ad4c9/compiler/rustc_borrowck/src/polonius/legacy/location.rs"),
::tracing_core::__macro_support::Option::Some(47u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::location"),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("PoloniusLocationTable: num_points={0:#?}",
num_points) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("PoloniusLocationTable: num_points={:#?}", num_points);
48
49 Self { num_points, statements_before_block }
50 }
51
52 pub fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
53 (0..self.num_points).map(LocationIndex::from_usize)
54 }
55
56 pub fn start_index(&self, location: Location) -> LocationIndex {
57 let Location { block, statement_index } = location;
58 let start_index = self.statements_before_block[block];
59 LocationIndex::from_usize(start_index + statement_index * 2)
60 }
61
62 pub fn mid_index(&self, location: Location) -> LocationIndex {
63 let Location { block, statement_index } = location;
64 let start_index = self.statements_before_block[block];
65 LocationIndex::from_usize(start_index + statement_index * 2 + 1)
66 }
67
68 pub fn to_rich_location(&self, index: LocationIndex) -> RichLocation {
69 let point_index = index.index();
70
71 let (block, &first_index) = self
88 .statements_before_block
89 .iter_enumerated()
90 .rfind(|&(_, &first_index)| first_index <= point_index)
91 .unwrap();
92
93 let statement_index = (point_index - first_index) / 2;
94 if index.is_start() {
95 RichLocation::Start(Location { block, statement_index })
96 } else {
97 RichLocation::Mid(Location { block, statement_index })
98 }
99 }
100
101 pub fn to_location(&self, index: LocationIndex) -> Location {
102 match self.to_rich_location(index) {
103 RichLocation::Start(location) => location,
104 RichLocation::Mid(location) => location,
105 }
106 }
107}
108
109impl LocationIndex {
110 fn is_start(self) -> bool {
111 self.index().is_multiple_of(2)
113 }
114}