1use std::debug_assert_matches;
2use std::fmt::{Debug, Formatter};
3use std::ops::Range;
4
5use rustc_abi::{FieldIdx, VariantIdx};
6use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
7use rustc_index::IndexVec;
8use rustc_index::bit_set::DenseBitSet;
9use rustc_middle::mir::visit::{PlaceContext, Visitor};
10use rustc_middle::mir::*;
11use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized};
12use tracing::debug;
13
14use crate::JoinSemiLattice;
15use crate::lattice::{HasBottom, HasTop};
16
17impl ::std::fmt::Debug for PlaceIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("{0}", self.as_u32()))
}
}rustc_index::newtype_index!(
18 pub struct PlaceIndex {}
23);
24
25impl ::std::fmt::Debug for ValueIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("{0}", self.as_u32()))
}
}rustc_index::newtype_index!(
26 pub struct ValueIndex {}
28);
29
30#[derive(#[automatically_derived]
impl<V: ::core::cmp::PartialEq> ::core::cmp::PartialEq for StateData<V> {
#[inline]
fn eq(&self, other: &StateData<V>) -> bool {
self.bottom == other.bottom && self.map == other.map
}
}PartialEq, #[automatically_derived]
impl<V: ::core::cmp::Eq> ::core::cmp::Eq for StateData<V> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<V>;
let _: ::core::cmp::AssertParamIsEq<FxHashMap<ValueIndex, V>>;
}
}Eq, #[automatically_derived]
impl<V: ::core::fmt::Debug> ::core::fmt::Debug for StateData<V> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "StateData",
"bottom", &self.bottom, "map", &&self.map)
}
}Debug)]
32pub struct StateData<V> {
33 bottom: V,
34 map: FxHashMap<ValueIndex, V>,
36}
37
38impl<V: HasBottom> StateData<V> {
39 fn new() -> StateData<V> {
40 StateData { bottom: V::BOTTOM, map: FxHashMap::default() }
41 }
42
43 fn get(&self, idx: ValueIndex) -> &V {
44 self.map.get(&idx).unwrap_or(&self.bottom)
45 }
46
47 fn insert(&mut self, idx: ValueIndex, elem: V) {
48 if elem.is_bottom() {
49 self.map.remove(&idx);
50 } else {
51 self.map.insert(idx, elem);
52 }
53 }
54}
55
56impl<V: Clone> Clone for StateData<V> {
57 fn clone(&self) -> Self {
58 StateData { bottom: self.bottom.clone(), map: self.map.clone() }
59 }
60
61 fn clone_from(&mut self, source: &Self) {
62 self.map.clone_from(&source.map)
63 }
64}
65
66impl<V: JoinSemiLattice + Clone> JoinSemiLattice for StateData<V> {
67 fn join(&mut self, other: &Self) -> bool {
68 let mut changed = false;
69 #[allow(rustc::potential_query_instability)]
70 for (i, v) in other.map.iter() {
71 match self.map.entry(*i) {
72 StdEntry::Vacant(e) => {
73 e.insert(v.clone());
74 changed = true
75 }
76 StdEntry::Occupied(e) => changed |= e.into_mut().join(v),
77 }
78 }
79 changed
80 }
81}
82
83#[derive(#[automatically_derived]
impl<V: ::core::cmp::PartialEq> ::core::cmp::PartialEq for State<V> {
#[inline]
fn eq(&self, other: &State<V>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(State::Reachable(__self_0), State::Reachable(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl<V: ::core::cmp::Eq> ::core::cmp::Eq for State<V> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<StateData<V>>;
}
}Eq, #[automatically_derived]
impl<V: ::core::fmt::Debug> ::core::fmt::Debug for State<V> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
State::Unreachable =>
::core::fmt::Formatter::write_str(f, "Unreachable"),
State::Reachable(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Reachable", &__self_0),
}
}
}Debug)]
94pub enum State<V> {
95 Unreachable,
96 Reachable(StateData<V>),
97}
98
99impl<V: Clone> Clone for State<V> {
100 fn clone(&self) -> Self {
101 match self {
102 Self::Reachable(x) => Self::Reachable(x.clone()),
103 Self::Unreachable => Self::Unreachable,
104 }
105 }
106
107 fn clone_from(&mut self, source: &Self) {
108 match (&mut *self, source) {
109 (Self::Reachable(x), Self::Reachable(y)) => {
110 x.clone_from(&y);
111 }
112 _ => *self = source.clone(),
113 }
114 }
115}
116
117impl<V: Clone + HasBottom> State<V> {
118 pub fn new_reachable() -> State<V> {
119 State::Reachable(StateData::new())
120 }
121
122 pub fn is_reachable(&self) -> bool {
123 #[allow(non_exhaustive_omitted_patterns)] match self {
State::Reachable(_) => true,
_ => false,
}matches!(self, State::Reachable(_))
124 }
125
126 pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map<'_>, value: V) {
128 self.flood_with_tail_elem(place, None, map, value)
129 }
130
131 pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
133 where
134 V: HasTop,
135 {
136 self.flood_with(place, map, V::TOP)
137 }
138
139 fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map<'_>, value: V) {
141 self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value)
142 }
143
144 pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
146 where
147 V: HasTop,
148 {
149 self.flood_discr_with(place, map, V::TOP)
150 }
151
152 fn flood_with_tail_elem(
160 &mut self,
161 place: PlaceRef<'_>,
162 tail_elem: Option<TrackElem>,
163 map: &Map<'_>,
164 value: V,
165 ) {
166 let State::Reachable(values) = self else { return };
167 map.for_each_aliasing_place(place, tail_elem, &mut |vi| values.insert(vi, value.clone()));
168 }
169
170 fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map<'_>) {
175 match result {
176 ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
177 ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
178 }
179 }
180
181 pub fn insert_value_idx(&mut self, target: PlaceIndex, value: V, map: &Map<'_>) {
186 let State::Reachable(values) = self else { return };
187 if let Some(value_index) = map.places[target].value_index {
188 values.insert(value_index, value)
189 }
190 }
191
192 pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map<'_>) {
200 let State::Reachable(values) = self else { return };
201 map.for_each_value_pair(target, source, &mut |target, source| {
202 values.insert(target, values.get(source).clone());
203 });
204 }
205
206 pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map<'_>)
208 where
209 V: HasTop,
210 {
211 self.flood(target, map);
212 if let Some(target) = map.find(target) {
213 self.insert_idx(target, result, map);
214 }
215 }
216
217 pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map<'_>)
219 where
220 V: HasTop,
221 {
222 self.flood_discr(target, map);
223 if let Some(target) = map.find_discr(target) {
224 self.insert_idx(target, result, map);
225 }
226 }
227
228 fn try_get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
230 let place = map.find(place)?;
231 self.try_get_idx(place, map)
232 }
233
234 fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
236 let place = map.find_discr(place)?;
237 self.try_get_idx(place, map)
238 }
239
240 fn try_get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> Option<V> {
242 match self {
243 State::Reachable(values) => {
244 map.places[place].value_index.map(|v| values.get(v).clone())
245 }
246 State::Unreachable => None,
247 }
248 }
249
250 pub fn get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
254 where
255 V: HasBottom + HasTop,
256 {
257 match self {
258 State::Reachable(_) => self.try_get(place, map).unwrap_or(V::TOP),
259 State::Unreachable => V::BOTTOM,
261 }
262 }
263
264 pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
268 where
269 V: HasBottom + HasTop,
270 {
271 match self {
272 State::Reachable(_) => self.try_get_discr(place, map).unwrap_or(V::TOP),
273 State::Unreachable => V::BOTTOM,
275 }
276 }
277
278 pub fn get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> V
282 where
283 V: HasBottom + HasTop,
284 {
285 match self {
286 State::Reachable(values) => {
287 map.places[place].value_index.map(|v| values.get(v).clone()).unwrap_or(V::TOP)
288 }
289 State::Unreachable => {
290 V::BOTTOM
292 }
293 }
294 }
295}
296
297impl<V: JoinSemiLattice + Clone> JoinSemiLattice for State<V> {
298 fn join(&mut self, other: &Self) -> bool {
299 match (&mut *self, other) {
300 (_, State::Unreachable) => false,
301 (State::Unreachable, _) => {
302 *self = other.clone();
303 true
304 }
305 (State::Reachable(this), State::Reachable(other)) => this.join(other),
306 }
307 }
308}
309
310#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for Map<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["locals", "projections", "places", "value_count", "mode",
"inner_values", "inner_values_buffer"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.locals, &self.projections, &self.places,
&self.value_count, &self.mode, &self.inner_values,
&&self.inner_values_buffer];
::core::fmt::Formatter::debug_struct_fields_finish(f, "Map", names,
values)
}
}Debug)]
317pub struct Map<'tcx> {
318 locals: IndexVec<Local, Option<PlaceIndex>>,
319 projections: FxHashMap<(PlaceIndex, TrackElem), PlaceIndex>,
320 places: IndexVec<PlaceIndex, PlaceInfo<'tcx>>,
321 value_count: usize,
322 mode: PlaceCollectionMode,
323 inner_values: IndexVec<PlaceIndex, Range<usize>>,
325 inner_values_buffer: Vec<ValueIndex>,
326}
327
328#[derive(#[automatically_derived]
impl ::core::marker::Copy for PlaceCollectionMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PlaceCollectionMode {
#[inline]
fn clone(&self) -> PlaceCollectionMode {
let _: ::core::clone::AssertParamIsClone<Option<usize>>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for PlaceCollectionMode {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
PlaceCollectionMode::Full { value_limit: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Full",
"value_limit", &__self_0),
PlaceCollectionMode::OnDemand =>
::core::fmt::Formatter::write_str(f, "OnDemand"),
}
}
}Debug)]
329pub enum PlaceCollectionMode {
330 Full { value_limit: Option<usize> },
331 OnDemand,
332}
333
334impl<'tcx> Map<'tcx> {
335 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("new",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(340u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("mode")
}> =
::tracing::__macro_support::FieldName::new("mode");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mode)
as &dyn ::tracing::field::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: Self = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_dataflow/src/value_analysis.rs:342",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(342u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let capacity = 4 * body.local_decls.len();
let mut map =
Self {
locals: IndexVec::from_elem(None, &body.local_decls),
projections: FxHashMap::default(),
places: IndexVec::with_capacity(capacity),
value_count: 0,
mode,
inner_values: IndexVec::new(),
inner_values_buffer: Vec::new(),
};
map.register_locals(tcx, body);
match mode {
PlaceCollectionMode::Full { value_limit } => {
map.collect_places(tcx, body);
map.propagate_assignments(tcx, body);
map.create_values(tcx, body, value_limit);
map.trim_useless_places();
}
PlaceCollectionMode::OnDemand => {}
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_dataflow/src/value_analysis.rs:363",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(363u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::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!("registered {0} places ({1} nodes in total)",
map.value_count, map.places.len()) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
map
}
}
}#[tracing::instrument(level = "trace", skip(tcx, body))]
341 pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, mode: PlaceCollectionMode) -> Self {
342 tracing::trace!(def_id=?body.source.def_id());
343 let capacity = 4 * body.local_decls.len();
344 let mut map = Self {
345 locals: IndexVec::from_elem(None, &body.local_decls),
346 projections: FxHashMap::default(),
347 places: IndexVec::with_capacity(capacity),
348 value_count: 0,
349 mode,
350 inner_values: IndexVec::new(),
351 inner_values_buffer: Vec::new(),
352 };
353 map.register_locals(tcx, body);
354 match mode {
355 PlaceCollectionMode::Full { value_limit } => {
356 map.collect_places(tcx, body);
357 map.propagate_assignments(tcx, body);
358 map.create_values(tcx, body, value_limit);
359 map.trim_useless_places();
360 }
361 PlaceCollectionMode::OnDemand => {}
362 }
363 debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
364 map
365 }
366
367 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("register_locals",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(368u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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,
&{ meta.fields().value_set_all(&[]) })
} 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;
}
{
let exclude = excluded_locals(body);
for (local, decl) in body.local_decls.iter_enumerated() {
if exclude.contains(local) { continue; }
if decl.ty.is_async_drop_in_place_coroutine(tcx) { continue; }
if true {
if !self.locals[local].is_none() {
::core::panicking::panic("assertion failed: self.locals[local].is_none()")
};
};
let place = self.places.push(PlaceInfo::new(decl.ty, None));
self.locals[local] = Some(place);
}
}
}
}#[tracing::instrument(level = "trace", skip(self, tcx, body))]
369 fn register_locals(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
370 let exclude = excluded_locals(body);
371
372 for (local, decl) in body.local_decls.iter_enumerated() {
374 if exclude.contains(local) {
375 continue;
376 }
377 if decl.ty.is_async_drop_in_place_coroutine(tcx) {
378 continue;
379 }
380
381 debug_assert!(self.locals[local].is_none());
383 let place = self.places.push(PlaceInfo::new(decl.ty, None));
384 self.locals[local] = Some(place);
385 }
386 }
387
388 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("collect_places",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(389u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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,
&{ meta.fields().value_set_all(&[]) })
} 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;
}
{
let mut collector = PlaceCollector { tcx, body, map: self };
collector.visit_body(body);
}
}
}#[tracing::instrument(level = "trace", skip(self, tcx, body))]
390 fn collect_places(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
391 let mut collector = PlaceCollector { tcx, body, map: self };
392 collector.visit_body(body);
393 }
394
395 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("propagate_assignments",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(403u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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,
&{ meta.fields().value_set_all(&[]) })
} 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;
}
{
let mut assignments = FxIndexSet::default();
for bbdata in body.basic_blocks.iter() {
for stmt in bbdata.statements.iter() {
let Some((lhs, rhs)) =
stmt.kind.as_assign() else { continue };
match rhs {
Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs), _) |
Rvalue::CopyForDeref(rhs) => {
let Some(lhs) =
self.register_place_and_discr(tcx, body,
*lhs) else { continue; };
let Some(rhs) =
self.register_place_and_discr(tcx, body,
*rhs) else { continue; };
assignments.insert((lhs, rhs));
}
Rvalue::Aggregate(kind, fields) => {
let Some(mut lhs) =
self.register_place_and_discr(tcx, body,
*lhs) else { continue; };
match **kind {
AggregateKind::Adt(_, _, _, _, Some(_)) => continue,
AggregateKind::Adt(_, variant, _, _, None) => {
let ty = self.places[lhs].ty;
if ty.is_enum() {
lhs =
self.register_place_index(ty, lhs,
TrackElem::Variant(variant));
}
}
AggregateKind::RawPtr(..) | AggregateKind::Array(_) |
AggregateKind::Tuple | AggregateKind::Closure(..) |
AggregateKind::Coroutine(..) |
AggregateKind::CoroutineClosure(..) => {}
}
for (index, field) in fields.iter_enumerated() {
if let Some(rhs) = field.place() &&
let Some(rhs) =
self.register_place_and_discr(tcx, body, rhs) {
let lhs =
self.register_place_index(self.places[rhs].ty, lhs,
TrackElem::Field(index));
assignments.insert((lhs, rhs));
}
}
}
_ => {}
}
}
}
let mut num_places = 0;
while num_places < self.places.len() {
num_places = self.places.len();
for assign in 0.. {
let Some(&(lhs, rhs)) =
assignments.get_index(assign) else { break };
let mut child = self.places[lhs].first_child;
while let Some(lhs_child) = child {
let PlaceInfo { ty, proj_elem, next_sibling, .. } =
self.places[lhs_child];
let rhs_child =
self.register_place_index(ty, rhs,
proj_elem.expect("child is not a projection"));
assignments.insert((lhs_child, rhs_child));
child = next_sibling;
}
let mut child = self.places[rhs].first_child;
while let Some(rhs_child) = child {
let PlaceInfo { ty, proj_elem, next_sibling, .. } =
self.places[rhs_child];
let lhs_child =
self.register_place_index(ty, lhs,
proj_elem.expect("child is not a projection"));
assignments.insert((lhs_child, rhs_child));
child = next_sibling;
}
}
}
}
}
}#[tracing::instrument(level = "trace", skip(self, tcx, body))]
404 fn propagate_assignments(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
405 let mut assignments = FxIndexSet::default();
407
408 for bbdata in body.basic_blocks.iter() {
409 for stmt in bbdata.statements.iter() {
410 let Some((lhs, rhs)) = stmt.kind.as_assign() else { continue };
411 match rhs {
412 Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs), _)
413 | Rvalue::CopyForDeref(rhs) => {
414 let Some(lhs) = self.register_place_and_discr(tcx, body, *lhs) else {
415 continue;
416 };
417 let Some(rhs) = self.register_place_and_discr(tcx, body, *rhs) else {
418 continue;
419 };
420 assignments.insert((lhs, rhs));
421 }
422 Rvalue::Aggregate(kind, fields) => {
423 let Some(mut lhs) = self.register_place_and_discr(tcx, body, *lhs) else {
424 continue;
425 };
426 match **kind {
427 AggregateKind::Adt(_, _, _, _, Some(_)) => continue,
429 AggregateKind::Adt(_, variant, _, _, None) => {
430 let ty = self.places[lhs].ty;
431 if ty.is_enum() {
432 lhs = self.register_place_index(
433 ty,
434 lhs,
435 TrackElem::Variant(variant),
436 );
437 }
438 }
439 AggregateKind::RawPtr(..)
440 | AggregateKind::Array(_)
441 | AggregateKind::Tuple
442 | AggregateKind::Closure(..)
443 | AggregateKind::Coroutine(..)
444 | AggregateKind::CoroutineClosure(..) => {}
445 }
446 for (index, field) in fields.iter_enumerated() {
447 if let Some(rhs) = field.place()
448 && let Some(rhs) = self.register_place_and_discr(tcx, body, rhs)
449 {
450 let lhs = self.register_place_index(
451 self.places[rhs].ty,
452 lhs,
453 TrackElem::Field(index),
454 );
455 assignments.insert((lhs, rhs));
456 }
457 }
458 }
459 _ => {}
460 }
461 }
462 }
463
464 let mut num_places = 0;
467 while num_places < self.places.len() {
468 num_places = self.places.len();
469
470 for assign in 0.. {
471 let Some(&(lhs, rhs)) = assignments.get_index(assign) else { break };
472
473 let mut child = self.places[lhs].first_child;
475 while let Some(lhs_child) = child {
476 let PlaceInfo { ty, proj_elem, next_sibling, .. } = self.places[lhs_child];
477 let rhs_child = self.register_place_index(
478 ty,
479 rhs,
480 proj_elem.expect("child is not a projection"),
481 );
482 assignments.insert((lhs_child, rhs_child));
483 child = next_sibling;
484 }
485
486 let mut child = self.places[rhs].first_child;
488 while let Some(rhs_child) = child {
489 let PlaceInfo { ty, proj_elem, next_sibling, .. } = self.places[rhs_child];
490 let lhs_child = self.register_place_index(
491 ty,
492 lhs,
493 proj_elem.expect("child is not a projection"),
494 );
495 assignments.insert((lhs_child, rhs_child));
496 child = next_sibling;
497 }
498 }
499 }
500 }
501
502 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("create_values",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(503u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value_limit")
}> =
::tracing::__macro_support::FieldName::new("value_limit");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value_limit)
as &dyn ::tracing::field::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;
}
{
if true {
{
match self.mode {
PlaceCollectionMode::Full { .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"PlaceCollectionMode::Full { .. }",
::core::option::Option::None);
}
}
};
};
let typing_env = body.typing_env(tcx);
for place_info in self.places.iter_mut() {
if let Some(value_limit) = value_limit &&
self.value_count >= value_limit {
break;
}
if let Ok(ty) =
tcx.try_normalize_erasing_regions(typing_env,
Unnormalized::new_wip(place_info.ty)) {
place_info.ty = ty;
}
if !place_info.value_index.is_none() {
::core::panicking::panic("assertion failed: place_info.value_index.is_none()")
};
if let Ok(layout) =
tcx.layout_of(typing_env.as_query_input(place_info.ty)) &&
layout.backend_repr.is_scalar() {
place_info.value_index = Some(self.value_count.into());
self.value_count += 1;
}
}
self.inner_values_buffer = Vec::with_capacity(self.value_count);
self.inner_values = IndexVec::from_elem(0..0, &self.places);
for local in body.local_decls.indices() {
if let Some(place) = self.locals[local] {
self.cache_preorder_invoke(place);
}
}
}
}
}#[tracing::instrument(level = "trace", skip(self, tcx, body))]
504 fn create_values(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) {
505 debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
506 let typing_env = body.typing_env(tcx);
507 for place_info in self.places.iter_mut() {
508 if let Some(value_limit) = value_limit
510 && self.value_count >= value_limit
511 {
512 break;
513 }
514
515 if let Ok(ty) =
516 tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(place_info.ty))
517 {
518 place_info.ty = ty;
519 }
520
521 assert!(place_info.value_index.is_none());
523 if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
524 && layout.backend_repr.is_scalar()
525 {
526 place_info.value_index = Some(self.value_count.into());
527 self.value_count += 1;
528 }
529 }
530
531 self.inner_values_buffer = Vec::with_capacity(self.value_count);
535 self.inner_values = IndexVec::from_elem(0..0, &self.places);
536 for local in body.local_decls.indices() {
537 if let Some(place) = self.locals[local] {
538 self.cache_preorder_invoke(place);
539 }
540 }
541 }
542
543 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("trim_useless_places",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(544u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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,
&{ meta.fields().value_set_all(&[]) })
} 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;
}
{
if true {
{
match self.mode {
PlaceCollectionMode::Full { .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"PlaceCollectionMode::Full { .. }",
::core::option::Option::None);
}
}
};
};
for opt_place in self.locals.iter_mut() {
if let Some(place) = *opt_place &&
self.inner_values[place].is_empty() {
*opt_place = None;
}
}
#[allow(rustc::potential_query_instability)]
self.projections.retain(|_, child|
!self.inner_values[*child].is_empty());
}
}
}#[tracing::instrument(level = "trace", skip(self))]
545 fn trim_useless_places(&mut self) {
546 debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
547 for opt_place in self.locals.iter_mut() {
548 if let Some(place) = *opt_place
549 && self.inner_values[place].is_empty()
550 {
551 *opt_place = None;
552 }
553 }
554 #[allow(rustc::potential_query_instability)]
555 self.projections.retain(|_, child| !self.inner_values[*child].is_empty());
556 }
557
558 x;#[tracing::instrument(level = "trace", skip(self), ret)]
559 pub fn register_place_index(
560 &mut self,
561 ty: Ty<'tcx>,
562 base: PlaceIndex,
563 elem: TrackElem,
564 ) -> PlaceIndex {
565 *self.projections.entry((base, elem)).or_insert_with(|| {
566 let next = self.places.push(PlaceInfo::new(ty, Some(elem)));
567 self.places[next].next_sibling = self.places[base].first_child;
568 self.places[base].first_child = Some(next);
569 next
570 })
571 }
572
573 x;#[tracing::instrument(level = "trace", skip(self, tcx, body), ret)]
574 pub fn register_place(
575 &mut self,
576 tcx: TyCtxt<'tcx>,
577 body: &Body<'tcx>,
578 place: Place<'tcx>,
579 tail: Option<TrackElem>,
580 ) -> Option<PlaceIndex> {
581 let mut place_index = self.locals[place.local]?;
583 let mut ty = PlaceTy::from_ty(body.local_decls[place.local].ty);
584 tracing::trace!(?place_index, ?ty);
585
586 for proj in place.projection {
587 let track_elem = proj.try_into().ok()?;
588 ty = ty.projection_ty(tcx, proj);
589 place_index = self.register_place_index(ty.ty, place_index, track_elem);
590 tracing::trace!(?proj, ?place_index, ?ty);
591 }
592
593 if let Some(tail) = tail {
594 let ty = match tail {
595 TrackElem::Discriminant => ty.ty.discriminant_ty(tcx),
596 TrackElem::Variant(..) | TrackElem::Field(..) => unimplemented!(),
597 TrackElem::DerefLen => tcx.types.usize,
598 };
599 place_index = self.register_place_index(ty, place_index, tail);
600 }
601
602 Some(place_index)
603 }
604
605 x;#[tracing::instrument(level = "trace", skip(self, tcx, body), ret)]
606 fn register_place_and_discr(
607 &mut self,
608 tcx: TyCtxt<'tcx>,
609 body: &Body<'tcx>,
610 place: Place<'tcx>,
611 ) -> Option<PlaceIndex> {
612 let place = self.register_place(tcx, body, place, None)?;
613 let ty = self.places[place].ty;
614
615 if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.kind()
616 && let ty::Slice(..) = ref_ty.kind()
617 {
618 self.register_place_index(tcx.types.usize, place, TrackElem::DerefLen);
619 } else if ty.is_enum() {
620 let discriminant_ty = ty.discriminant_ty(tcx);
621 self.register_place_index(discriminant_ty, place, TrackElem::Discriminant);
622 }
623
624 Some(place)
625 }
626
627 x;#[tracing::instrument(level = "trace", skip(self, tcx, typing_env), ret)]
628 pub fn register_value(
629 &mut self,
630 tcx: TyCtxt<'tcx>,
631 typing_env: ty::TypingEnv<'tcx>,
632 place: PlaceIndex,
633 ) -> Option<ValueIndex> {
634 let place_info = &mut self.places[place];
635 if let Some(value) = place_info.value_index {
636 return Some(value);
637 }
638
639 if let Ok(ty) =
640 tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(place_info.ty))
641 {
642 place_info.ty = ty;
643 }
644
645 if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
647 && layout.backend_repr.is_scalar()
648 {
649 place_info.value_index = Some(self.value_count.into());
650 self.value_count += 1;
651 }
652
653 place_info.value_index
654 }
655
656 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("register_copy_tree",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(656u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("source")
}> =
::tracing::__macro_support::FieldName::new("source");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::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;
}
{
if let Some(source_value) = self.places[source].value_index {
let target_value =
*self.places[target].value_index.get_or_insert_with(||
{
let value_index = self.value_count.into();
self.value_count += 1;
value_index
});
f(source_value, target_value)
}
let mut source_child_iter = self.places[source].first_child;
while let Some(source_child) = source_child_iter {
source_child_iter = self.places[source_child].next_sibling;
let source_info = &self.places[source_child];
let source_ty = source_info.ty;
let source_elem = source_info.proj_elem.unwrap();
let target_child =
self.register_place_index(source_ty, target, source_elem);
self.register_copy_tree(source_child, target_child, f);
}
}
}
}#[tracing::instrument(level = "trace", skip(self, f))]
657 pub fn register_copy_tree(
658 &mut self,
659 source: PlaceIndex,
661 target: PlaceIndex,
663 f: &mut impl FnMut(ValueIndex, ValueIndex),
664 ) {
665 if let Some(source_value) = self.places[source].value_index {
666 let target_value = *self.places[target].value_index.get_or_insert_with(|| {
667 let value_index = self.value_count.into();
668 self.value_count += 1;
669 value_index
670 });
671 f(source_value, target_value)
672 }
673
674 let mut source_child_iter = self.places[source].first_child;
676 while let Some(source_child) = source_child_iter {
677 source_child_iter = self.places[source_child].next_sibling;
678
679 let source_info = &self.places[source_child];
681 let source_ty = source_info.ty;
682 let source_elem = source_info.proj_elem.unwrap();
683 let target_child = self.register_place_index(source_ty, target, source_elem);
684 self.register_copy_tree(source_child, target_child, f);
685 }
686 }
687
688 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("cache_preorder_invoke",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(690u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("root")
}> =
::tracing::__macro_support::FieldName::new("root");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&root)
as &dyn ::tracing::field::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;
}
{
if true {
{
match self.mode {
PlaceCollectionMode::Full { .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"PlaceCollectionMode::Full { .. }",
::core::option::Option::None);
}
}
};
};
let start = self.inner_values_buffer.len();
if let Some(vi) = self.places[root].value_index {
self.inner_values_buffer.push(vi);
}
let mut next_child = self.places[root].first_child;
while let Some(child) = next_child {
self.cache_preorder_invoke(child);
next_child = self.places[child].next_sibling;
}
let end = self.inner_values_buffer.len();
self.inner_values[root] = start..end;
}
}
}#[tracing::instrument(level = "trace", skip(self))]
691 fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
692 debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
693 let start = self.inner_values_buffer.len();
694 if let Some(vi) = self.places[root].value_index {
695 self.inner_values_buffer.push(vi);
696 }
697
698 let mut next_child = self.places[root].first_child;
700 while let Some(child) = next_child {
701 self.cache_preorder_invoke(child);
702 next_child = self.places[child].next_sibling;
703 }
704
705 let end = self.inner_values_buffer.len();
706 self.inner_values[root] = start..end;
707 }
708}
709
710struct PlaceCollector<'a, 'tcx> {
711 tcx: TyCtxt<'tcx>,
712 body: &'a Body<'tcx>,
713 map: &'a mut Map<'tcx>,
714}
715
716impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
717 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("visit_place",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(717u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ctxt")
}> =
::tracing::__macro_support::FieldName::new("ctxt");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ctxt)
as &dyn ::tracing::field::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;
}
{
if !ctxt.is_use() { return; }
self.map.register_place_and_discr(self.tcx, self.body, *place);
}
}
}#[tracing::instrument(level = "trace", skip(self))]
718 fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) {
719 if !ctxt.is_use() {
720 return;
721 }
722
723 self.map.register_place_and_discr(self.tcx, self.body, *place);
724 }
725}
726
727impl<'tcx> Map<'tcx> {
728 pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
730 self.projections.get(&(place, elem)).copied()
731 }
732
733 fn find_extra(
735 &self,
736 place: PlaceRef<'_>,
737 extra: impl IntoIterator<Item = TrackElem>,
738 ) -> Option<PlaceIndex> {
739 let mut index = *self.locals[place.local].as_ref()?;
740
741 for &elem in place.projection {
742 index = self.apply(index, elem.try_into().ok()?)?;
743 }
744 for elem in extra {
745 index = self.apply(index, elem)?;
746 }
747
748 Some(index)
749 }
750
751 pub fn find(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
753 self.find_extra(place, [])
754 }
755
756 pub fn find_discr(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
758 self.find_extra(place, [TrackElem::Discriminant])
759 }
760
761 pub fn find_len(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
763 self.find_extra(place, [TrackElem::DerefLen])
764 }
765
766 pub fn value(&self, place: PlaceIndex) -> Option<ValueIndex> {
768 self.places[place].value_index
769 }
770
771 fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
773 Children::new(self, parent)
774 }
775
776 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("for_each_aliasing_place",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(783u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("tail_elem")
}> =
::tracing::__macro_support::FieldName::new("tail_elem");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&tail_elem)
as &dyn ::tracing::field::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;
}
{
if place.is_indirect_first_projection() { return; }
let Some(mut index) = self.locals[place.local] else { return; };
let elems =
place.projection.iter().map(|&elem|
elem.try_into()).chain(tail_elem.map(Ok));
for elem in elems {
if let Some(vi) = self.places[index].value_index { f(vi); }
let Ok(elem) = elem else { return };
let sub = self.apply(index, elem);
if let TrackElem::Variant(..) | TrackElem::Discriminant = elem
{
self.for_each_variant_sibling(index, sub, f);
}
let Some(sub) = sub else { return };
index = sub;
}
self.for_each_value_inside(index, f);
}
}
}#[tracing::instrument(level = "trace", skip(self, f))]
784 pub fn for_each_aliasing_place(
785 &self,
786 place: PlaceRef<'_>,
787 tail_elem: Option<TrackElem>,
788 f: &mut impl FnMut(ValueIndex),
789 ) {
790 if place.is_indirect_first_projection() {
791 return;
793 }
794 let Some(mut index) = self.locals[place.local] else {
795 return;
797 };
798 let elems = place.projection.iter().map(|&elem| elem.try_into()).chain(tail_elem.map(Ok));
799 for elem in elems {
800 if let Some(vi) = self.places[index].value_index {
802 f(vi);
803 }
804
805 let Ok(elem) = elem else { return };
806 let sub = self.apply(index, elem);
807 if let TrackElem::Variant(..) | TrackElem::Discriminant = elem {
808 self.for_each_variant_sibling(index, sub, f);
810 }
811 let Some(sub) = sub else { return };
812 index = sub;
813 }
814 self.for_each_value_inside(index, f);
815 }
816
817 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("for_each_variant_sibling",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(818u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("parent")
}> =
::tracing::__macro_support::FieldName::new("parent");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("preserved_child")
}> =
::tracing::__macro_support::FieldName::new("preserved_child");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&parent)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&preserved_child)
as &dyn ::tracing::field::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;
}
{
for sibling in self.children(parent) {
let elem = self.places[sibling].proj_elem;
if let Some(TrackElem::Variant(..) | TrackElem::Discriminant)
= elem && Some(sibling) != preserved_child {
self.for_each_value_inside(sibling, f);
}
}
}
}
}#[tracing::instrument(level = "trace", skip(self, f))]
819 fn for_each_variant_sibling(
820 &self,
821 parent: PlaceIndex,
822 preserved_child: Option<PlaceIndex>,
823 f: &mut impl FnMut(ValueIndex),
824 ) {
825 for sibling in self.children(parent) {
826 let elem = self.places[sibling].proj_elem;
827 if let Some(TrackElem::Variant(..) | TrackElem::Discriminant) = elem
830 && Some(sibling) != preserved_child
832 {
833 self.for_each_value_inside(sibling, f);
834 }
835 }
836 }
837
838 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("for_each_value_inside",
"rustc_mir_dataflow::value_analysis",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_dataflow/src/value_analysis.rs"),
::tracing_core::__macro_support::Option::Some(839u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("root")
}> =
::tracing::__macro_support::FieldName::new("root");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&root)
as &dyn ::tracing::field::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;
}
{
if let Some(range) = self.inner_values.get(root) {
let values = &self.inner_values_buffer[range.clone()];
for &v in values { f(v) }
} else {
if let Some(root) = self.places[root].value_index { f(root) }
for child in self.children(root) {
self.for_each_value_inside(child, f);
}
}
}
}
}#[tracing::instrument(level = "trace", skip(self, f))]
840 fn for_each_value_inside(&self, root: PlaceIndex, f: &mut impl FnMut(ValueIndex)) {
841 if let Some(range) = self.inner_values.get(root) {
842 let values = &self.inner_values_buffer[range.clone()];
844 for &v in values {
845 f(v)
846 }
847 } else {
848 if let Some(root) = self.places[root].value_index {
849 f(root)
850 }
851
852 for child in self.children(root) {
853 self.for_each_value_inside(child, f);
854 }
855 }
856 }
857
858 pub fn for_each_projection_value<O>(
860 &self,
861 root: PlaceIndex,
862 value: O,
863 project: &mut impl FnMut(TrackElem, &O) -> Option<O>,
864 f: &mut impl FnMut(PlaceIndex, &O),
865 ) {
866 if let Some(value_range) = self.inner_values.get(root)
868 && value_range.is_empty()
869 {
870 return;
871 }
872
873 if self.places[root].value_index.is_some() {
874 f(root, &value)
875 }
876
877 for child in self.children(root) {
878 let elem = self.places[child].proj_elem.unwrap();
879 if let Some(value) = project(elem, &value) {
880 self.for_each_projection_value(child, value, project, f);
881 }
882 }
883 }
884
885 fn for_each_value_pair(
888 &self,
889 target: PlaceIndex,
890 source: PlaceIndex,
891 f: &mut impl FnMut(ValueIndex, ValueIndex),
892 ) {
893 if let Some(target_value) = self.places[target].value_index
897 && let Some(source_value) = self.places[source].value_index
898 {
899 f(target_value, source_value)
900 }
901 for target_child in self.children(target) {
902 let projection = self.places[target_child].proj_elem.unwrap();
904 if let Some(source_child) = self.projections.get(&(source, projection)) {
905 self.for_each_value_pair(target_child, *source_child, f);
906 }
907 }
908 }
909}
910
911#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for PlaceInfo<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f, "PlaceInfo",
"ty", &self.ty, "value_index", &self.value_index, "proj_elem",
&self.proj_elem, "first_child", &self.first_child, "next_sibling",
&&self.next_sibling)
}
}Debug)]
916struct PlaceInfo<'tcx> {
917 ty: Ty<'tcx>,
919
920 value_index: Option<ValueIndex>,
922
923 proj_elem: Option<TrackElem>,
925
926 first_child: Option<PlaceIndex>,
928
929 next_sibling: Option<PlaceIndex>,
931}
932
933impl<'tcx> PlaceInfo<'tcx> {
934 fn new(ty: Ty<'tcx>, proj_elem: Option<TrackElem>) -> Self {
935 Self { ty, next_sibling: None, first_child: None, proj_elem, value_index: None }
936 }
937}
938
939struct Children<'a, 'tcx> {
940 map: &'a Map<'tcx>,
941 next: Option<PlaceIndex>,
942}
943
944impl<'a, 'tcx> Children<'a, 'tcx> {
945 fn new(map: &'a Map<'tcx>, parent: PlaceIndex) -> Self {
946 Self { map, next: map.places[parent].first_child }
947 }
948}
949
950impl Iterator for Children<'_, '_> {
951 type Item = PlaceIndex;
952
953 fn next(&mut self) -> Option<Self::Item> {
954 match self.next {
955 Some(child) => {
956 self.next = self.map.places[child].next_sibling;
957 Some(child)
958 }
959 None => None,
960 }
961 }
962}
963
964#[derive(#[automatically_derived]
impl<V: ::core::fmt::Debug> ::core::fmt::Debug for ValueOrPlace<V> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ValueOrPlace::Value(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Value",
&__self_0),
ValueOrPlace::Place(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Place",
&__self_0),
}
}
}Debug)]
966pub enum ValueOrPlace<V> {
967 Value(V),
968 Place(PlaceIndex),
969}
970
971impl<V: HasTop> ValueOrPlace<V> {
972 pub const TOP: Self = ValueOrPlace::Value(V::TOP);
973}
974
975#[derive(#[automatically_derived]
impl ::core::marker::Copy for TrackElem { }Copy, #[automatically_derived]
impl ::core::clone::Clone for TrackElem {
#[inline]
fn clone(&self) -> TrackElem {
let _: ::core::clone::AssertParamIsClone<FieldIdx>;
let _: ::core::clone::AssertParamIsClone<VariantIdx>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TrackElem {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
TrackElem::Field(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Field",
&__self_0),
TrackElem::Variant(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Variant", &__self_0),
TrackElem::Discriminant =>
::core::fmt::Formatter::write_str(f, "Discriminant"),
TrackElem::DerefLen =>
::core::fmt::Formatter::write_str(f, "DerefLen"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for TrackElem {
#[inline]
fn eq(&self, other: &TrackElem) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(TrackElem::Field(__self_0), TrackElem::Field(__arg1_0)) =>
__self_0 == __arg1_0,
(TrackElem::Variant(__self_0), TrackElem::Variant(__arg1_0))
=> __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TrackElem {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<FieldIdx>;
let _: ::core::cmp::AssertParamIsEq<VariantIdx>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for TrackElem {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
TrackElem::Field(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
TrackElem::Variant(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash)]
979pub enum TrackElem {
980 Field(FieldIdx),
981 Variant(VariantIdx),
982 Discriminant,
983 DerefLen,
985}
986
987impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
988 type Error = ();
989
990 fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
991 match value {
992 ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
993 ProjectionElem::Downcast(_, idx) => Ok(TrackElem::Variant(idx)),
994 _ => Err(()),
995 }
996 }
997}
998
999pub fn iter_fields<'tcx>(
1001 ty: Ty<'tcx>,
1002 tcx: TyCtxt<'tcx>,
1003 typing_env: ty::TypingEnv<'tcx>,
1004 mut f: impl FnMut(Option<VariantIdx>, FieldIdx, Ty<'tcx>),
1005) {
1006 match ty.kind() {
1007 ty::Tuple(list) => {
1008 for (field, ty) in list.iter().enumerate() {
1009 f(None, field.into(), ty);
1010 }
1011 }
1012 ty::Adt(def, args) => {
1013 if def.is_union() {
1014 return;
1015 }
1016 for (v_index, v_def) in def.variants().iter_enumerated() {
1017 let variant = if def.is_struct() { None } else { Some(v_index) };
1018 for (f_index, f_def) in v_def.fields.iter().enumerate() {
1019 let field_ty = f_def.ty(tcx, args);
1020 let field_ty =
1021 tcx.try_normalize_erasing_regions(typing_env, field_ty).unwrap_or_else(
1022 |_| tcx.erase_and_anonymize_regions(field_ty.skip_norm_wip()),
1023 );
1024 f(variant, f_index.into(), field_ty);
1025 }
1026 }
1027 }
1028 ty::Closure(_, args) => {
1029 iter_fields(args.as_closure().tupled_upvars_ty(), tcx, typing_env, f);
1030 }
1031 ty::Coroutine(_, args) => {
1032 iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, typing_env, f);
1033 }
1034 ty::CoroutineClosure(_, args) => {
1035 iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, typing_env, f);
1036 }
1037 _ => (),
1038 }
1039}
1040
1041pub fn excluded_locals(body: &Body<'_>) -> DenseBitSet<Local> {
1043 struct Collector {
1044 result: DenseBitSet<Local>,
1045 }
1046
1047 impl<'tcx> Visitor<'tcx> for Collector {
1048 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
1049 if context.may_observe_address() && !place.is_indirect() {
1050 self.result.insert(place.local);
1053 }
1054 }
1055 }
1056
1057 let mut collector = Collector { result: DenseBitSet::new_empty(body.local_decls.len()) };
1058 collector.visit_body(body);
1059 collector.result
1060}
1061
1062fn debug_with_context_rec<V: Debug + Eq + HasBottom>(
1063 place: PlaceIndex,
1064 place_str: &str,
1065 new: &StateData<V>,
1066 old: Option<&StateData<V>>,
1067 map: &Map<'_>,
1068 f: &mut Formatter<'_>,
1069) -> std::fmt::Result {
1070 if let Some(value) = map.places[place].value_index {
1071 match old {
1072 None => f.write_fmt(format_args!("{0}: {1:?}\n", place_str, new.get(value)))writeln!(f, "{}: {:?}", place_str, new.get(value))?,
1073 Some(old) => {
1074 if new.get(value) != old.get(value) {
1075 f.write_fmt(format_args!("\u{1f}-{0}: {1:?}\n", place_str, old.get(value)))writeln!(f, "\u{001f}-{}: {:?}", place_str, old.get(value))?;
1076 f.write_fmt(format_args!("\u{1f}+{0}: {1:?}\n", place_str, new.get(value)))writeln!(f, "\u{001f}+{}: {:?}", place_str, new.get(value))?;
1077 }
1078 }
1079 }
1080 }
1081
1082 for child in map.children(place) {
1083 let info_elem = map.places[child].proj_elem.unwrap();
1084 let child_place_str = match info_elem {
1085 TrackElem::Discriminant => {
1086 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("discriminant({0})", place_str))
})format!("discriminant({place_str})")
1087 }
1088 TrackElem::Variant(idx) => {
1089 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0} as {1:?})", place_str, idx))
})format!("({place_str} as {idx:?})")
1090 }
1091 TrackElem::Field(field) => {
1092 if place_str.starts_with('*') {
1093 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}).{1}", place_str,
field.index()))
})format!("({}).{}", place_str, field.index())
1094 } else {
1095 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}.{1}", place_str,
field.index()))
})format!("{}.{}", place_str, field.index())
1096 }
1097 }
1098 TrackElem::DerefLen => {
1099 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Len(*{0})", place_str))
})format!("Len(*{})", place_str)
1100 }
1101 };
1102 debug_with_context_rec(child, &child_place_str, new, old, map, f)?;
1103 }
1104
1105 Ok(())
1106}
1107
1108pub fn debug_with_context<V: Debug + Eq + HasBottom>(
1109 new: &StateData<V>,
1110 old: Option<&StateData<V>>,
1111 map: &Map<'_>,
1112 f: &mut Formatter<'_>,
1113) -> std::fmt::Result {
1114 for (local, place) in map.locals.iter_enumerated() {
1115 if let Some(place) = place {
1116 debug_with_context_rec(*place, &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", local))
})format!("{local:?}"), new, old, map, f)?;
1117 }
1118 }
1119 Ok(())
1120}