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_data_structures::stack::ensure_sufficient_stack;
8use rustc_index::IndexVec;
9use rustc_index::bit_set::DenseBitSet;
10use rustc_middle::mir::visit::{PlaceContext, Visitor};
11use rustc_middle::mir::*;
12use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized};
13use tracing::debug;
14
15use crate::JoinSemiLattice;
16use crate::lattice::{HasBottom, HasTop};
17
18impl ::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!(
19 pub struct PlaceIndex {}
24);
25
26impl ::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!(
27 pub struct ValueIndex {}
29);
30
31#[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)]
33pub struct StateData<V> {
34 bottom: V,
35 map: FxHashMap<ValueIndex, V>,
37}
38
39impl<V: HasBottom> StateData<V> {
40 fn new() -> StateData<V> {
41 StateData { bottom: V::BOTTOM, map: FxHashMap::default() }
42 }
43
44 fn get(&self, idx: ValueIndex) -> &V {
45 self.map.get(&idx).unwrap_or(&self.bottom)
46 }
47
48 fn insert(&mut self, idx: ValueIndex, elem: V) {
49 if elem.is_bottom() {
50 self.map.remove(&idx);
51 } else {
52 self.map.insert(idx, elem);
53 }
54 }
55}
56
57impl<V: Clone> Clone for StateData<V> {
58 fn clone(&self) -> Self {
59 StateData { bottom: self.bottom.clone(), map: self.map.clone() }
60 }
61
62 fn clone_from(&mut self, source: &Self) {
63 self.map.clone_from(&source.map)
64 }
65}
66
67impl<V: JoinSemiLattice + Clone> JoinSemiLattice for StateData<V> {
68 fn join(&mut self, other: &Self) -> bool {
69 let mut changed = false;
70 #[allow(rustc::potential_query_instability)]
71 for (i, v) in other.map.iter() {
72 match self.map.entry(*i) {
73 StdEntry::Vacant(e) => {
74 e.insert(v.clone());
75 changed = true
76 }
77 StdEntry::Occupied(e) => changed |= e.into_mut().join(v),
78 }
79 }
80 changed
81 }
82}
83
84#[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)]
95pub enum State<V> {
96 Unreachable,
97 Reachable(StateData<V>),
98}
99
100impl<V: Clone> Clone for State<V> {
101 fn clone(&self) -> Self {
102 match self {
103 Self::Reachable(x) => Self::Reachable(x.clone()),
104 Self::Unreachable => Self::Unreachable,
105 }
106 }
107
108 fn clone_from(&mut self, source: &Self) {
109 match (&mut *self, source) {
110 (Self::Reachable(x), Self::Reachable(y)) => {
111 x.clone_from(&y);
112 }
113 _ => *self = source.clone(),
114 }
115 }
116}
117
118impl<V: Clone + HasBottom> State<V> {
119 pub fn new_reachable() -> State<V> {
120 State::Reachable(StateData::new())
121 }
122
123 pub fn all_bottom(&self) -> bool {
124 match self {
125 State::Unreachable => false,
126 State::Reachable(values) =>
127 {
128 #[allow(rustc::potential_query_instability)]
129 values.map.values().all(V::is_bottom)
130 }
131 }
132 }
133
134 pub fn is_reachable(&self) -> bool {
135 #[allow(non_exhaustive_omitted_patterns)] match self {
State::Reachable(_) => true,
_ => false,
}matches!(self, State::Reachable(_))
136 }
137
138 pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map<'_>, value: V) {
140 self.flood_with_tail_elem(place, None, map, value)
141 }
142
143 pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
145 where
146 V: HasTop,
147 {
148 self.flood_with(place, map, V::TOP)
149 }
150
151 fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map<'_>, value: V) {
153 self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value)
154 }
155
156 pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map<'_>)
158 where
159 V: HasTop,
160 {
161 self.flood_discr_with(place, map, V::TOP)
162 }
163
164 pub fn flood_with_tail_elem(
172 &mut self,
173 place: PlaceRef<'_>,
174 tail_elem: Option<TrackElem>,
175 map: &Map<'_>,
176 value: V,
177 ) {
178 let State::Reachable(values) = self else { return };
179 map.for_each_aliasing_place(place, tail_elem, &mut |vi| values.insert(vi, value.clone()));
180 }
181
182 fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map<'_>) {
187 match result {
188 ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
189 ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
190 }
191 }
192
193 pub fn insert_value_idx(&mut self, target: PlaceIndex, value: V, map: &Map<'_>) {
198 let State::Reachable(values) = self else { return };
199 if let Some(value_index) = map.places[target].value_index {
200 values.insert(value_index, value)
201 }
202 }
203
204 pub fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map<'_>) {
212 let State::Reachable(values) = self else { return };
213 map.for_each_value_pair(target, source, &mut |target, source| {
214 values.insert(target, values.get(source).clone());
215 });
216 }
217
218 pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map<'_>)
220 where
221 V: HasTop,
222 {
223 self.flood(target, map);
224 if let Some(target) = map.find(target) {
225 self.insert_idx(target, result, map);
226 }
227 }
228
229 pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map<'_>)
231 where
232 V: HasTop,
233 {
234 self.flood_discr(target, map);
235 if let Some(target) = map.find_discr(target) {
236 self.insert_idx(target, result, map);
237 }
238 }
239
240 pub fn try_get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
242 let place = map.find(place)?;
243 self.try_get_idx(place, map)
244 }
245
246 pub fn try_get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
248 let place = map.find_discr(place)?;
249 self.try_get_idx(place, map)
250 }
251
252 pub fn try_get_len(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option<V> {
254 let place = map.find_len(place)?;
255 self.try_get_idx(place, map)
256 }
257
258 pub fn try_get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> Option<V> {
260 match self {
261 State::Reachable(values) => {
262 map.places[place].value_index.map(|v| values.get(v).clone())
263 }
264 State::Unreachable => None,
265 }
266 }
267
268 pub fn get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
272 where
273 V: HasBottom + HasTop,
274 {
275 match self {
276 State::Reachable(_) => self.try_get(place, map).unwrap_or(V::TOP),
277 State::Unreachable => V::BOTTOM,
279 }
280 }
281
282 pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
286 where
287 V: HasBottom + HasTop,
288 {
289 match self {
290 State::Reachable(_) => self.try_get_discr(place, map).unwrap_or(V::TOP),
291 State::Unreachable => V::BOTTOM,
293 }
294 }
295
296 pub fn get_len(&self, place: PlaceRef<'_>, map: &Map<'_>) -> V
300 where
301 V: HasBottom + HasTop,
302 {
303 match self {
304 State::Reachable(_) => self.try_get_len(place, map).unwrap_or(V::TOP),
305 State::Unreachable => V::BOTTOM,
307 }
308 }
309
310 pub fn get_idx(&self, place: PlaceIndex, map: &Map<'_>) -> V
314 where
315 V: HasBottom + HasTop,
316 {
317 match self {
318 State::Reachable(values) => {
319 map.places[place].value_index.map(|v| values.get(v).clone()).unwrap_or(V::TOP)
320 }
321 State::Unreachable => {
322 V::BOTTOM
324 }
325 }
326 }
327}
328
329impl<V: JoinSemiLattice + Clone> JoinSemiLattice for State<V> {
330 fn join(&mut self, other: &Self) -> bool {
331 match (&mut *self, other) {
332 (_, State::Unreachable) => false,
333 (State::Unreachable, _) => {
334 *self = other.clone();
335 true
336 }
337 (State::Reachable(this), State::Reachable(other)) => this.join(other),
338 }
339 }
340}
341
342#[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)]
349pub struct Map<'tcx> {
350 locals: IndexVec<Local, Option<PlaceIndex>>,
351 projections: FxHashMap<(PlaceIndex, TrackElem), PlaceIndex>,
352 places: IndexVec<PlaceIndex, PlaceInfo<'tcx>>,
353 value_count: usize,
354 mode: PlaceCollectionMode,
355 inner_values: IndexVec<PlaceIndex, Range<usize>>,
357 inner_values_buffer: Vec<ValueIndex>,
358}
359
360#[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)]
361pub enum PlaceCollectionMode {
362 Full { value_limit: Option<usize> },
363 OnDemand,
364}
365
366impl<'tcx> Map<'tcx> {
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("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(372u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["mode"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mode)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: 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:374",
"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(374u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["def_id"],
::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};
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(&debug(&body.source.def_id())
as &dyn 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:395",
"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(395u32),
::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};
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!("registered {0} places ({1} nodes in total)",
map.value_count, map.places.len()) as &dyn Value))])
});
} else { ; }
};
map
}
}
}#[tracing::instrument(level = "trace", skip(tcx, body))]
373 pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, mode: PlaceCollectionMode) -> Self {
374 tracing::trace!(def_id=?body.source.def_id());
375 let capacity = 4 * body.local_decls.len();
376 let mut map = Self {
377 locals: IndexVec::from_elem(None, &body.local_decls),
378 projections: FxHashMap::default(),
379 places: IndexVec::with_capacity(capacity),
380 value_count: 0,
381 mode,
382 inner_values: IndexVec::new(),
383 inner_values_buffer: Vec::new(),
384 };
385 map.register_locals(tcx, body);
386 match mode {
387 PlaceCollectionMode::Full { value_limit } => {
388 map.collect_places(tcx, body);
389 map.propagate_assignments(tcx, body);
390 map.create_values(tcx, body, value_limit);
391 map.trim_useless_places();
392 }
393 PlaceCollectionMode::OnDemand => {}
394 }
395 debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
396 map
397 }
398
399 #[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(400u32),
::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(&[]) })
} 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))]
401 fn register_locals(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
402 let exclude = excluded_locals(body);
403
404 for (local, decl) in body.local_decls.iter_enumerated() {
406 if exclude.contains(local) {
407 continue;
408 }
409 if decl.ty.is_async_drop_in_place_coroutine(tcx) {
410 continue;
411 }
412
413 debug_assert!(self.locals[local].is_none());
415 let place = self.places.push(PlaceInfo::new(decl.ty, None));
416 self.locals[local] = Some(place);
417 }
418 }
419
420 #[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(421u32),
::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(&[]) })
} 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))]
422 fn collect_places(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
423 let mut collector = PlaceCollector { tcx, body, map: self };
424 collector.visit_body(body);
425 }
426
427 #[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(435u32),
::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(&[]) })
} 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))]
436 fn propagate_assignments(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
437 let mut assignments = FxIndexSet::default();
439
440 for bbdata in body.basic_blocks.iter() {
441 for stmt in bbdata.statements.iter() {
442 let Some((lhs, rhs)) = stmt.kind.as_assign() else { continue };
443 match rhs {
444 Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs))
445 | Rvalue::CopyForDeref(rhs) => {
446 let Some(lhs) = self.register_place_and_discr(tcx, body, *lhs) else {
447 continue;
448 };
449 let Some(rhs) = self.register_place_and_discr(tcx, body, *rhs) else {
450 continue;
451 };
452 assignments.insert((lhs, rhs));
453 }
454 Rvalue::Aggregate(kind, fields) => {
455 let Some(mut lhs) = self.register_place_and_discr(tcx, body, *lhs) else {
456 continue;
457 };
458 match **kind {
459 AggregateKind::Adt(_, _, _, _, Some(_)) => continue,
461 AggregateKind::Adt(_, variant, _, _, None) => {
462 let ty = self.places[lhs].ty;
463 if ty.is_enum() {
464 lhs = self.register_place_index(
465 ty,
466 lhs,
467 TrackElem::Variant(variant),
468 );
469 }
470 }
471 AggregateKind::RawPtr(..)
472 | AggregateKind::Array(_)
473 | AggregateKind::Tuple
474 | AggregateKind::Closure(..)
475 | AggregateKind::Coroutine(..)
476 | AggregateKind::CoroutineClosure(..) => {}
477 }
478 for (index, field) in fields.iter_enumerated() {
479 if let Some(rhs) = field.place()
480 && let Some(rhs) = self.register_place_and_discr(tcx, body, rhs)
481 {
482 let lhs = self.register_place_index(
483 self.places[rhs].ty,
484 lhs,
485 TrackElem::Field(index),
486 );
487 assignments.insert((lhs, rhs));
488 }
489 }
490 }
491 _ => {}
492 }
493 }
494 }
495
496 let mut num_places = 0;
499 while num_places < self.places.len() {
500 num_places = self.places.len();
501
502 for assign in 0.. {
503 let Some(&(lhs, rhs)) = assignments.get_index(assign) else { break };
504
505 let mut child = self.places[lhs].first_child;
507 while let Some(lhs_child) = child {
508 let PlaceInfo { ty, proj_elem, next_sibling, .. } = self.places[lhs_child];
509 let rhs_child = self.register_place_index(
510 ty,
511 rhs,
512 proj_elem.expect("child is not a projection"),
513 );
514 assignments.insert((lhs_child, rhs_child));
515 child = next_sibling;
516 }
517
518 let mut child = self.places[rhs].first_child;
520 while let Some(rhs_child) = child {
521 let PlaceInfo { ty, proj_elem, next_sibling, .. } = self.places[rhs_child];
522 let lhs_child = self.register_place_index(
523 ty,
524 lhs,
525 proj_elem.expect("child is not a projection"),
526 );
527 assignments.insert((lhs_child, rhs_child));
528 child = next_sibling;
529 }
530 }
531 }
532 }
533
534 #[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(535u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["value_limit"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value_limit)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
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))]
536 fn create_values(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) {
537 debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
538 let typing_env = body.typing_env(tcx);
539 for place_info in self.places.iter_mut() {
540 if let Some(value_limit) = value_limit
542 && self.value_count >= value_limit
543 {
544 break;
545 }
546
547 if let Ok(ty) =
548 tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(place_info.ty))
549 {
550 place_info.ty = ty;
551 }
552
553 assert!(place_info.value_index.is_none());
555 if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
556 && layout.backend_repr.is_scalar()
557 {
558 place_info.value_index = Some(self.value_count.into());
559 self.value_count += 1;
560 }
561 }
562
563 self.inner_values_buffer = Vec::with_capacity(self.value_count);
567 self.inner_values = IndexVec::from_elem(0..0, &self.places);
568 for local in body.local_decls.indices() {
569 if let Some(place) = self.locals[local] {
570 self.cache_preorder_invoke(place);
571 }
572 }
573 }
574
575 #[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(576u32),
::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(&[]) })
} 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))]
577 fn trim_useless_places(&mut self) {
578 debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
579 for opt_place in self.locals.iter_mut() {
580 if let Some(place) = *opt_place
581 && self.inner_values[place].is_empty()
582 {
583 *opt_place = None;
584 }
585 }
586 #[allow(rustc::potential_query_instability)]
587 self.projections.retain(|_, child| !self.inner_values[*child].is_empty());
588 }
589
590 x;#[tracing::instrument(level = "trace", skip(self), ret)]
591 pub fn register_place_index(
592 &mut self,
593 ty: Ty<'tcx>,
594 base: PlaceIndex,
595 elem: TrackElem,
596 ) -> PlaceIndex {
597 *self.projections.entry((base, elem)).or_insert_with(|| {
598 let next = self.places.push(PlaceInfo::new(ty, Some(elem)));
599 self.places[next].next_sibling = self.places[base].first_child;
600 self.places[base].first_child = Some(next);
601 next
602 })
603 }
604
605 x;#[tracing::instrument(level = "trace", skip(self, tcx, body), ret)]
606 pub fn register_place(
607 &mut self,
608 tcx: TyCtxt<'tcx>,
609 body: &Body<'tcx>,
610 place: Place<'tcx>,
611 tail: Option<TrackElem>,
612 ) -> Option<PlaceIndex> {
613 let mut place_index = self.locals[place.local]?;
615 let mut ty = PlaceTy::from_ty(body.local_decls[place.local].ty);
616 tracing::trace!(?place_index, ?ty);
617
618 for proj in place.projection {
619 let track_elem = proj.try_into().ok()?;
620 ty = ty.projection_ty(tcx, proj);
621 place_index = self.register_place_index(ty.ty, place_index, track_elem);
622 tracing::trace!(?proj, ?place_index, ?ty);
623 }
624
625 if let Some(tail) = tail {
626 let ty = match tail {
627 TrackElem::Discriminant => ty.ty.discriminant_ty(tcx),
628 TrackElem::Variant(..) | TrackElem::Field(..) => todo!(),
629 TrackElem::DerefLen => tcx.types.usize,
630 };
631 place_index = self.register_place_index(ty, place_index, tail);
632 }
633
634 Some(place_index)
635 }
636
637 x;#[tracing::instrument(level = "trace", skip(self, tcx, body), ret)]
638 fn register_place_and_discr(
639 &mut self,
640 tcx: TyCtxt<'tcx>,
641 body: &Body<'tcx>,
642 place: Place<'tcx>,
643 ) -> Option<PlaceIndex> {
644 let place = self.register_place(tcx, body, place, None)?;
645 let ty = self.places[place].ty;
646
647 if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.kind()
648 && let ty::Slice(..) = ref_ty.kind()
649 {
650 self.register_place_index(tcx.types.usize, place, TrackElem::DerefLen);
651 } else if ty.is_enum() {
652 let discriminant_ty = ty.discriminant_ty(tcx);
653 self.register_place_index(discriminant_ty, place, TrackElem::Discriminant);
654 }
655
656 Some(place)
657 }
658
659 x;#[tracing::instrument(level = "trace", skip(self, tcx, typing_env), ret)]
660 pub fn register_value(
661 &mut self,
662 tcx: TyCtxt<'tcx>,
663 typing_env: ty::TypingEnv<'tcx>,
664 place: PlaceIndex,
665 ) -> Option<ValueIndex> {
666 let place_info = &mut self.places[place];
667 if let Some(value) = place_info.value_index {
668 return Some(value);
669 }
670
671 if let Ok(ty) =
672 tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(place_info.ty))
673 {
674 place_info.ty = ty;
675 }
676
677 if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
679 && layout.backend_repr.is_scalar()
680 {
681 place_info.value_index = Some(self.value_count.into());
682 self.value_count += 1;
683 }
684
685 place_info.value_index
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("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(688u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["source", "target"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
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))]
689 pub fn register_copy_tree(
690 &mut self,
691 source: PlaceIndex,
693 target: PlaceIndex,
695 f: &mut impl FnMut(ValueIndex, ValueIndex),
696 ) {
697 if let Some(source_value) = self.places[source].value_index {
698 let target_value = *self.places[target].value_index.get_or_insert_with(|| {
699 let value_index = self.value_count.into();
700 self.value_count += 1;
701 value_index
702 });
703 f(source_value, target_value)
704 }
705
706 let mut source_child_iter = self.places[source].first_child;
708 while let Some(source_child) = source_child_iter {
709 source_child_iter = self.places[source_child].next_sibling;
710
711 let source_info = &self.places[source_child];
713 let source_ty = source_info.ty;
714 let source_elem = source_info.proj_elem.unwrap();
715 let target_child = self.register_place_index(source_ty, target, source_elem);
716 self.register_copy_tree(source_child, target_child, f);
717 }
718 }
719
720 #[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(722u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["root"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&root)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
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 {
ensure_sufficient_stack(|| 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))]
723 fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
724 debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
725 let start = self.inner_values_buffer.len();
726 if let Some(vi) = self.places[root].value_index {
727 self.inner_values_buffer.push(vi);
728 }
729
730 let mut next_child = self.places[root].first_child;
732 while let Some(child) = next_child {
733 ensure_sufficient_stack(|| self.cache_preorder_invoke(child));
734 next_child = self.places[child].next_sibling;
735 }
736
737 let end = self.inner_values_buffer.len();
738 self.inner_values[root] = start..end;
739 }
740}
741
742struct PlaceCollector<'a, 'tcx> {
743 tcx: TyCtxt<'tcx>,
744 body: &'a Body<'tcx>,
745 map: &'a mut Map<'tcx>,
746}
747
748impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
749 #[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(749u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["place", "ctxt"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ctxt)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if !ctxt.is_use() { return; }
self.map.register_place_and_discr(self.tcx, self.body, *place);
}
}
}#[tracing::instrument(level = "trace", skip(self))]
750 fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) {
751 if !ctxt.is_use() {
752 return;
753 }
754
755 self.map.register_place_and_discr(self.tcx, self.body, *place);
756 }
757}
758
759impl<'tcx> Map<'tcx> {
760 pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
762 self.projections.get(&(place, elem)).copied()
763 }
764
765 fn find_extra(
767 &self,
768 place: PlaceRef<'_>,
769 extra: impl IntoIterator<Item = TrackElem>,
770 ) -> Option<PlaceIndex> {
771 let mut index = *self.locals[place.local].as_ref()?;
772
773 for &elem in place.projection {
774 index = self.apply(index, elem.try_into().ok()?)?;
775 }
776 for elem in extra {
777 index = self.apply(index, elem)?;
778 }
779
780 Some(index)
781 }
782
783 pub fn find(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
785 self.find_extra(place, [])
786 }
787
788 pub fn find_discr(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
790 self.find_extra(place, [TrackElem::Discriminant])
791 }
792
793 pub fn find_len(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
795 self.find_extra(place, [TrackElem::DerefLen])
796 }
797
798 pub fn value(&self, place: PlaceIndex) -> Option<ValueIndex> {
800 self.places[place].value_index
801 }
802
803 pub fn find_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
805 self.value(self.find(place)?)
806 }
807
808 pub fn find_discr_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
810 self.value(self.find_discr(place)?)
811 }
812
813 pub fn find_len_value(&self, place: PlaceRef<'_>) -> Option<ValueIndex> {
815 self.value(self.find_len(place)?)
816 }
817
818 fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> {
820 Children::new(self, parent)
821 }
822
823 #[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(830u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["place",
"tail_elem"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&tail_elem)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
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))]
831 pub fn for_each_aliasing_place(
832 &self,
833 place: PlaceRef<'_>,
834 tail_elem: Option<TrackElem>,
835 f: &mut impl FnMut(ValueIndex),
836 ) {
837 if place.is_indirect_first_projection() {
838 return;
840 }
841 let Some(mut index) = self.locals[place.local] else {
842 return;
844 };
845 let elems = place.projection.iter().map(|&elem| elem.try_into()).chain(tail_elem.map(Ok));
846 for elem in elems {
847 if let Some(vi) = self.places[index].value_index {
849 f(vi);
850 }
851
852 let Ok(elem) = elem else { return };
853 let sub = self.apply(index, elem);
854 if let TrackElem::Variant(..) | TrackElem::Discriminant = elem {
855 self.for_each_variant_sibling(index, sub, f);
857 }
858 let Some(sub) = sub else { return };
859 index = sub;
860 }
861 self.for_each_value_inside(index, f);
862 }
863
864 #[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(865u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["parent",
"preserved_child"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&parent)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&preserved_child)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
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))]
866 fn for_each_variant_sibling(
867 &self,
868 parent: PlaceIndex,
869 preserved_child: Option<PlaceIndex>,
870 f: &mut impl FnMut(ValueIndex),
871 ) {
872 for sibling in self.children(parent) {
873 let elem = self.places[sibling].proj_elem;
874 if let Some(TrackElem::Variant(..) | TrackElem::Discriminant) = elem
877 && Some(sibling) != preserved_child
879 {
880 self.for_each_value_inside(sibling, f);
881 }
882 }
883 }
884
885 pub fn values_inside(&self, root: PlaceIndex) -> &[ValueIndex] {
887 let range = self.inner_values[root].clone();
888 &self.inner_values_buffer[range]
889 }
890
891 #[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(892u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::value_analysis"),
::tracing_core::field::FieldSet::new(&["root"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&root)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
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))]
893 fn for_each_value_inside(&self, root: PlaceIndex, f: &mut impl FnMut(ValueIndex)) {
894 if let Some(range) = self.inner_values.get(root) {
895 let values = &self.inner_values_buffer[range.clone()];
897 for &v in values {
898 f(v)
899 }
900 } else {
901 if let Some(root) = self.places[root].value_index {
902 f(root)
903 }
904
905 for child in self.children(root) {
906 self.for_each_value_inside(child, f);
907 }
908 }
909 }
910
911 pub fn for_each_projection_value<O>(
913 &self,
914 root: PlaceIndex,
915 value: O,
916 project: &mut impl FnMut(TrackElem, &O) -> Option<O>,
917 f: &mut impl FnMut(PlaceIndex, &O),
918 ) {
919 if let Some(value_range) = self.inner_values.get(root)
921 && value_range.is_empty()
922 {
923 return;
924 }
925
926 if self.places[root].value_index.is_some() {
927 f(root, &value)
928 }
929
930 for child in self.children(root) {
931 let elem = self.places[child].proj_elem.unwrap();
932 if let Some(value) = project(elem, &value) {
933 self.for_each_projection_value(child, value, project, f);
934 }
935 }
936 }
937
938 pub fn for_each_value_pair(
941 &self,
942 target: PlaceIndex,
943 source: PlaceIndex,
944 f: &mut impl FnMut(ValueIndex, ValueIndex),
945 ) {
946 if let Some(target_value) = self.places[target].value_index
950 && let Some(source_value) = self.places[source].value_index
951 {
952 f(target_value, source_value)
953 }
954 for target_child in self.children(target) {
955 let projection = self.places[target_child].proj_elem.unwrap();
957 if let Some(source_child) = self.projections.get(&(source, projection)) {
958 self.for_each_value_pair(target_child, *source_child, f);
959 }
960 }
961 }
962}
963
964#[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)]
969struct PlaceInfo<'tcx> {
970 ty: Ty<'tcx>,
972
973 value_index: Option<ValueIndex>,
975
976 proj_elem: Option<TrackElem>,
978
979 first_child: Option<PlaceIndex>,
981
982 next_sibling: Option<PlaceIndex>,
984}
985
986impl<'tcx> PlaceInfo<'tcx> {
987 fn new(ty: Ty<'tcx>, proj_elem: Option<TrackElem>) -> Self {
988 Self { ty, next_sibling: None, first_child: None, proj_elem, value_index: None }
989 }
990}
991
992struct Children<'a, 'tcx> {
993 map: &'a Map<'tcx>,
994 next: Option<PlaceIndex>,
995}
996
997impl<'a, 'tcx> Children<'a, 'tcx> {
998 fn new(map: &'a Map<'tcx>, parent: PlaceIndex) -> Self {
999 Self { map, next: map.places[parent].first_child }
1000 }
1001}
1002
1003impl Iterator for Children<'_, '_> {
1004 type Item = PlaceIndex;
1005
1006 fn next(&mut self) -> Option<Self::Item> {
1007 match self.next {
1008 Some(child) => {
1009 self.next = self.map.places[child].next_sibling;
1010 Some(child)
1011 }
1012 None => None,
1013 }
1014 }
1015}
1016
1017#[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)]
1019pub enum ValueOrPlace<V> {
1020 Value(V),
1021 Place(PlaceIndex),
1022}
1023
1024impl<V: HasTop> ValueOrPlace<V> {
1025 pub const TOP: Self = ValueOrPlace::Value(V::TOP);
1026}
1027
1028#[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)]
1032pub enum TrackElem {
1033 Field(FieldIdx),
1034 Variant(VariantIdx),
1035 Discriminant,
1036 DerefLen,
1038}
1039
1040impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
1041 type Error = ();
1042
1043 fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
1044 match value {
1045 ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
1046 ProjectionElem::Downcast(_, idx) => Ok(TrackElem::Variant(idx)),
1047 _ => Err(()),
1048 }
1049 }
1050}
1051
1052pub fn iter_fields<'tcx>(
1054 ty: Ty<'tcx>,
1055 tcx: TyCtxt<'tcx>,
1056 typing_env: ty::TypingEnv<'tcx>,
1057 mut f: impl FnMut(Option<VariantIdx>, FieldIdx, Ty<'tcx>),
1058) {
1059 match ty.kind() {
1060 ty::Tuple(list) => {
1061 for (field, ty) in list.iter().enumerate() {
1062 f(None, field.into(), ty);
1063 }
1064 }
1065 ty::Adt(def, args) => {
1066 if def.is_union() {
1067 return;
1068 }
1069 for (v_index, v_def) in def.variants().iter_enumerated() {
1070 let variant = if def.is_struct() { None } else { Some(v_index) };
1071 for (f_index, f_def) in v_def.fields.iter().enumerate() {
1072 let field_ty = f_def.ty(tcx, args);
1073 let field_ty = tcx
1074 .try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(field_ty))
1075 .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(field_ty));
1076 f(variant, f_index.into(), field_ty);
1077 }
1078 }
1079 }
1080 ty::Closure(_, args) => {
1081 iter_fields(args.as_closure().tupled_upvars_ty(), tcx, typing_env, f);
1082 }
1083 ty::Coroutine(_, args) => {
1084 iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, typing_env, f);
1085 }
1086 ty::CoroutineClosure(_, args) => {
1087 iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, typing_env, f);
1088 }
1089 _ => (),
1090 }
1091}
1092
1093pub fn excluded_locals(body: &Body<'_>) -> DenseBitSet<Local> {
1095 struct Collector {
1096 result: DenseBitSet<Local>,
1097 }
1098
1099 impl<'tcx> Visitor<'tcx> for Collector {
1100 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
1101 if context.may_observe_address() && !place.is_indirect() {
1102 self.result.insert(place.local);
1105 }
1106 }
1107 }
1108
1109 let mut collector = Collector { result: DenseBitSet::new_empty(body.local_decls.len()) };
1110 collector.visit_body(body);
1111 collector.result
1112}
1113
1114fn debug_with_context_rec<V: Debug + Eq + HasBottom>(
1115 place: PlaceIndex,
1116 place_str: &str,
1117 new: &StateData<V>,
1118 old: Option<&StateData<V>>,
1119 map: &Map<'_>,
1120 f: &mut Formatter<'_>,
1121) -> std::fmt::Result {
1122 if let Some(value) = map.places[place].value_index {
1123 match old {
1124 None => f.write_fmt(format_args!("{0}: {1:?}\n", place_str, new.get(value)))writeln!(f, "{}: {:?}", place_str, new.get(value))?,
1125 Some(old) => {
1126 if new.get(value) != old.get(value) {
1127 f.write_fmt(format_args!("\u{1f}-{0}: {1:?}\n", place_str, old.get(value)))writeln!(f, "\u{001f}-{}: {:?}", place_str, old.get(value))?;
1128 f.write_fmt(format_args!("\u{1f}+{0}: {1:?}\n", place_str, new.get(value)))writeln!(f, "\u{001f}+{}: {:?}", place_str, new.get(value))?;
1129 }
1130 }
1131 }
1132 }
1133
1134 for child in map.children(place) {
1135 let info_elem = map.places[child].proj_elem.unwrap();
1136 let child_place_str = match info_elem {
1137 TrackElem::Discriminant => {
1138 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("discriminant({0})", place_str))
})format!("discriminant({place_str})")
1139 }
1140 TrackElem::Variant(idx) => {
1141 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0} as {1:?})", place_str, idx))
})format!("({place_str} as {idx:?})")
1142 }
1143 TrackElem::Field(field) => {
1144 if place_str.starts_with('*') {
1145 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("({0}).{1}", place_str,
field.index()))
})format!("({}).{}", place_str, field.index())
1146 } else {
1147 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}.{1}", place_str,
field.index()))
})format!("{}.{}", place_str, field.index())
1148 }
1149 }
1150 TrackElem::DerefLen => {
1151 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Len(*{0})", place_str))
})format!("Len(*{})", place_str)
1152 }
1153 };
1154 debug_with_context_rec(child, &child_place_str, new, old, map, f)?;
1155 }
1156
1157 Ok(())
1158}
1159
1160pub fn debug_with_context<V: Debug + Eq + HasBottom>(
1161 new: &StateData<V>,
1162 old: Option<&StateData<V>>,
1163 map: &Map<'_>,
1164 f: &mut Formatter<'_>,
1165) -> std::fmt::Result {
1166 for (local, place) in map.locals.iter_enumerated() {
1167 if let Some(place) = place {
1168 debug_with_context_rec(*place, &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", local))
})format!("{local:?}"), new, old, map, f)?;
1169 }
1170 }
1171 Ok(())
1172}