1use rustc_abi::VariantIdx;
2use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
3use smallvec::SmallVec;
4use tracing::debug;
5
6use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
7
8#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DropFlagState {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
DropFlagState::Present => "Present",
DropFlagState::Absent => "Absent",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for DropFlagState { }
#[automatically_derived]
impl ::core::cmp::PartialEq for DropFlagState {
#[inline]
fn eq(&self, other: &DropFlagState) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DropFlagState {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::marker::Copy for DropFlagState { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for DropFlagState { }
#[automatically_derived]
impl ::core::clone::Clone for DropFlagState {
#[inline]
fn clone(&self) -> DropFlagState { *self }
}Clone)]
10pub enum DropFlagState {
11 Present,
13
14 Absent,
17}
18
19impl DropFlagState {
20 pub fn value(self) -> bool {
21 match self {
22 DropFlagState::Present => true,
23 DropFlagState::Absent => false,
24 }
25 }
26}
27
28pub fn move_path_children_matching<'tcx, F>(
29 move_data: &MoveData<'tcx>,
30 path: MovePathIndex,
31 mut cond: F,
32) -> Option<MovePathIndex>
33where
34 F: FnMut(mir::PlaceElem<'tcx>) -> bool,
35{
36 let mut next_child = move_data.move_paths[path].first_child;
37 while let Some(child_index) = next_child {
38 let move_path_children = &move_data.move_paths[child_index];
39 if let Some(&elem) = move_path_children.place.projection.last() {
40 if cond(elem) {
41 return Some(child_index);
42 }
43 }
44 next_child = move_path_children.next_sibling;
45 }
46
47 None
48}
49
50pub fn on_lookup_result_bits<'tcx, F>(
51 move_data: &MoveData<'tcx>,
52 lookup_result: LookupResult,
53 each_child: F,
54) where
55 F: FnMut(MovePathIndex),
56{
57 match lookup_result {
58 LookupResult::Parent(..) => {
59 }
61 LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child),
62 }
63}
64
65pub fn on_all_children_bits<'tcx, F>(
66 move_data: &MoveData<'tcx>,
67 move_path_index: MovePathIndex,
68 mut each_child: F,
69) where
70 F: FnMut(MovePathIndex),
71{
72 fn on_all_children_bits<'tcx, F>(
73 move_data: &MoveData<'tcx>,
74 move_path_index: MovePathIndex,
75 each_child: &mut F,
76 ) where
77 F: FnMut(MovePathIndex),
78 {
79 each_child(move_path_index);
80
81 let mut next_child_index = move_data.move_paths[move_path_index].first_child;
82 while let Some(child_index) = next_child_index {
83 on_all_children_bits(move_data, child_index, each_child);
84 next_child_index = move_data.move_paths[child_index].next_sibling;
85 }
86 }
87 on_all_children_bits(move_data, move_path_index, &mut each_child);
88}
89
90pub fn drop_flag_effects_for_function_entry<'tcx, F>(
93 body: &Body<'tcx>,
94 move_data: &MoveData<'tcx>,
95 mut callback: F,
96) where
97 F: FnMut(MovePathIndex, DropFlagState),
98{
99 for arg in body.args_iter() {
100 let place = mir::Place::from(arg);
101 let lookup_result = move_data.rev_lookup.find(place.as_ref());
102 on_lookup_result_bits(move_data, lookup_result, |mpi| {
103 callback(mpi, DropFlagState::Present)
104 });
105 }
106}
107
108pub fn drop_flag_effects_for_location<'tcx, F>(
109 body: &Body<'tcx>,
110 move_data: &MoveData<'tcx>,
111 loc: Location,
112 mut callback: F,
113) where
114 F: FnMut(MovePathIndex, DropFlagState),
115{
116 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5a2be9f5f075d31e3ca5526b5b029881ce441253/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs:116",
"rustc_mir_dataflow::drop_flag_effects",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5a2be9f5f075d31e3ca5526b5b029881ce441253/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs"),
::tracing_core::__macro_support::Option::Some(116u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::drop_flag_effects"),
::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!("drop_flag_effects_for_location({0:?})",
loc) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("drop_flag_effects_for_location({:?})", loc);
117
118 for mi in &move_data.move_out_loc_map[loc] {
120 let path = mi.move_path_index(move_data);
121 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5a2be9f5f075d31e3ca5526b5b029881ce441253/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs:121",
"rustc_mir_dataflow::drop_flag_effects",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5a2be9f5f075d31e3ca5526b5b029881ce441253/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs"),
::tracing_core::__macro_support::Option::Some(121u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::drop_flag_effects"),
::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!("moving out of path {0:?}",
move_data.move_paths[path]) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("moving out of path {:?}", move_data.move_paths[path]);
122
123 on_all_children_bits(move_data, path, |mpi| callback(mpi, DropFlagState::Absent))
124 }
125
126 if let Some(Terminator { kind: TerminatorKind::Drop { place, .. }, .. }) =
128 body.stmt_at(loc).right()
129 && let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref())
130 {
131 on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent))
132 }
133
134 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5a2be9f5f075d31e3ca5526b5b029881ce441253/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs:134",
"rustc_mir_dataflow::drop_flag_effects",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5a2be9f5f075d31e3ca5526b5b029881ce441253/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs"),
::tracing_core::__macro_support::Option::Some(134u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_dataflow::drop_flag_effects"),
::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!("drop_flag_effects: assignment for location({0:?})",
loc) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("drop_flag_effects: assignment for location({:?})", loc);
135
136 for_location_inits(move_data, loc, |mpi| callback(mpi, DropFlagState::Present));
137}
138
139fn for_location_inits<'tcx, F>(move_data: &MoveData<'tcx>, loc: Location, mut callback: F)
140where
141 F: FnMut(MovePathIndex),
142{
143 for ii in &move_data.init_loc_map[loc] {
144 let init = move_data.inits[*ii];
145 match init.kind {
146 InitKind::Deep => {
147 let path = init.path;
148
149 on_all_children_bits(move_data, path, &mut callback)
150 }
151 InitKind::Shallow => {
152 let mpi = init.path;
153 callback(mpi);
154 }
155 InitKind::NonPanicPathOnly => (),
156 }
157 }
158}
159
160pub(crate) enum InactiveVariants {
163 Inactives(SmallVec<[VariantIdx; 4]>),
164 Active(VariantIdx),
165}
166
167impl InactiveVariants {
168 fn contains(&self, variant_idx: VariantIdx) -> bool {
169 match self {
170 InactiveVariants::Inactives(inactives) => inactives.contains(&variant_idx),
171 InactiveVariants::Active(active) => variant_idx != *active,
172 }
173 }
174}
175
176pub(crate) fn on_all_inactive_variants<'tcx>(
179 move_data: &MoveData<'tcx>,
180 enum_place: mir::Place<'tcx>,
181 inactive_variants: &InactiveVariants,
182 mut handle_inactive_variant: impl FnMut(MovePathIndex),
183) {
184 let LookupResult::Exact(enum_mpi) = move_data.rev_lookup.find(enum_place.as_ref()) else {
185 return;
186 };
187
188 let enum_path = &move_data.move_paths[enum_mpi];
189 for (variant_mpi, variant_path) in enum_path.children(&move_data.move_paths) {
190 let (downcast, base_proj) = variant_path.place.projection.split_last().unwrap();
194 {
match (&enum_place.projection.len(), &base_proj.len()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(enum_place.projection.len(), base_proj.len());
195
196 let mir::ProjectionElem::Downcast(_, variant_idx) = *downcast else {
197 ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
198 };
199
200 if inactive_variants.contains(variant_idx) {
201 on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi));
202 }
203 }
204}