Skip to content

Commit e2213d7

Browse files
committed
only enable for MaybeInitializedPlaces
1 parent 10e1a9d commit e2213d7

File tree

7 files changed

+134
-67
lines changed

7 files changed

+134
-67
lines changed

compiler/rustc_mir_dataflow/src/drop_flag_effects.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,15 @@ where
155155
}
156156
}
157157

158-
/// Calls `handle_inactive_variant` for each descendant move path of `enum_place` that contains a
159-
/// `Downcast` to a variant besides the `active_variant`, otherwise calls `handle_active_variant`.
160-
///
161-
/// NOTE: If there are no move paths corresponding to an inactive variant, `handle_active_variant`
162-
/// or `handle_inactive_variant` will not be called for that variant.
163-
pub(crate) fn on_all_inactive_variants<'tcx>(
158+
/// Handles each variant that corresponds to one of the child move paths of `enum_place`. If the
159+
/// variant is `active_variant`, `handle_active_variant` will be called (if provided). Otherwise,
160+
/// `handle_inactive_variant` will be called.
161+
pub(crate) fn on_all_variants<'tcx>(
164162
move_data: &MoveData<'tcx>,
165163
enum_place: mir::Place<'tcx>,
166164
active_variant: VariantIdx,
167165
mut handle_inactive_variant: impl FnMut(MovePathIndex),
168-
mut handle_active_variant: impl FnMut(MovePathIndex),
166+
mut handle_active_variant: Option<impl FnMut(MovePathIndex)>,
169167
) {
170168
let LookupResult::Exact(enum_mpi) = move_data.rev_lookup.find(enum_place.as_ref()) else {
171169
return;
@@ -185,7 +183,7 @@ pub(crate) fn on_all_inactive_variants<'tcx>(
185183

186184
if variant_idx != active_variant {
187185
on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi));
188-
} else {
186+
} else if let Some(ref mut handle_active_variant) = handle_active_variant {
189187
on_all_children_bits(move_data, variant_mpi, |mpi| handle_active_variant(mpi));
190188
}
191189
}

compiler/rustc_mir_dataflow/src/framework/direction.rs

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use std::ops::RangeInclusive;
22

3-
use rustc_middle::mir::{
4-
self, BasicBlock, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges,
5-
};
3+
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
64

75
use super::visitor::ResultsVisitor;
86
use super::{Analysis, Effect, EffectIndex};
@@ -245,7 +243,7 @@ impl Direction for Forward {
245243

246244
fn apply_effects_in_block<'mir, 'tcx, A>(
247245
analysis: &mut A,
248-
body: &mir::Body<'tcx>,
246+
_body: &mir::Body<'tcx>,
249247
state: &mut A::Domain,
250248
block: BasicBlock,
251249
block_data: &'mir mir::BasicBlockData<'tcx>,
@@ -285,23 +283,10 @@ impl Direction for Forward {
285283
}
286284
}
287285
TerminatorEdges::SwitchInt { targets, discr } => {
288-
if let Some(mut data) = analysis.get_switch_int_data(block, discr) {
289-
let mut tmp = analysis.bottom_value(body);
290-
let mut otherwise_state = exit_state.clone();
291-
292-
for (value, target) in targets.iter() {
293-
tmp.clone_from(exit_state);
294-
let value = SwitchTargetValue::Normal(value);
295-
analysis.apply_switch_int_edge_effect(
296-
&mut data,
297-
&mut tmp,
298-
value,
299-
Some(&mut otherwise_state),
300-
);
301-
propagate(target, &tmp);
302-
}
303-
304-
propagate(targets.otherwise(), &otherwise_state);
286+
if let Some(data) = analysis.get_switch_int_data(block, discr) {
287+
analysis.apply_switch_int_edge_effect_for_targets(
288+
targets, data, exit_state, propagate,
289+
);
305290
} else {
306291
for target in targets.all_targets() {
307292
propagate(*target, exit_state);

compiler/rustc_mir_dataflow/src/framework/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,19 @@ pub trait Analysis<'tcx> {
229229
unreachable!();
230230
}
231231

232+
/// Calls `apply_switch_int_edge_effect` for each target in `targets` and calls `propagate` with
233+
/// the new state. This is used in forward analysis for `MaybeUninitializedPlaces` and
234+
/// `MaybeInitializedPlaces`.
235+
fn apply_switch_int_edge_effect_for_targets(
236+
&mut self,
237+
_targets: &mir::SwitchTargets,
238+
mut _data: Self::SwitchIntData,
239+
_state: &mut Self::Domain,
240+
mut _propagate: impl FnMut(mir::BasicBlock, &Self::Domain),
241+
) {
242+
unreachable!();
243+
}
244+
232245
/* Extension methods */
233246

234247
/// Finds the fixpoint for this dataflow problem.

compiler/rustc_mir_dataflow/src/impls/initialized.rs

Lines changed: 84 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,26 @@ pub struct MaybeInitializedPlaces<'a, 'tcx> {
131131
tcx: TyCtxt<'tcx>,
132132
body: &'a Body<'tcx>,
133133
move_data: &'a MoveData<'tcx>,
134+
exclude_inactive_in_otherwise: bool,
134135
skip_unreachable_unwind: bool,
135136
}
136137

137138
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
138139
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
139-
MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false }
140+
MaybeInitializedPlaces {
141+
tcx,
142+
body,
143+
move_data,
144+
exclude_inactive_in_otherwise: false,
145+
skip_unreachable_unwind: false,
146+
}
147+
}
148+
149+
/// Ensures definitely inactive variants are excluded from the set of initialized places for
150+
/// blocks reached through an `otherwise` edge.
151+
pub fn exclude_inactive_in_otherwise(mut self) -> Self {
152+
self.exclude_inactive_in_otherwise = true;
153+
self
140154
}
141155

142156
pub fn skipping_unreachable_unwind(mut self) -> Self {
@@ -208,6 +222,7 @@ pub struct MaybeUninitializedPlaces<'a, 'tcx> {
208222
move_data: &'a MoveData<'tcx>,
209223

210224
mark_inactive_variants_as_uninit: bool,
225+
include_inactive_in_otherwise: bool,
211226
skip_unreachable_unwind: DenseBitSet<mir::BasicBlock>,
212227
}
213228

@@ -218,6 +233,7 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
218233
body,
219234
move_data,
220235
mark_inactive_variants_as_uninit: false,
236+
include_inactive_in_otherwise: false,
221237
skip_unreachable_unwind: DenseBitSet::new_empty(body.basic_blocks.len()),
222238
}
223239
}
@@ -232,6 +248,13 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
232248
self
233249
}
234250

251+
/// Ensures definitely inactive variants are included in the set of uninitialized places for
252+
/// blocks reached through an `otherwise` edge.
253+
pub fn include_inactive_in_otherwise(mut self) -> Self {
254+
self.include_inactive_in_otherwise = true;
255+
self
256+
}
257+
235258
pub fn skipping_unreachable_unwind(
236259
mut self,
237260
unreachable_unwind: DenseBitSet<mir::BasicBlock>,
@@ -431,22 +454,47 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
431454
data: &mut Self::SwitchIntData,
432455
state: &mut Self::Domain,
433456
value: SwitchTargetValue,
434-
mut otherwise_state: Option<&mut Self::Domain>,
457+
otherwise_state: Option<&mut Self::Domain>,
435458
) {
436459
if let SwitchTargetValue::Normal(value) = value {
437460
// Kill all move paths that correspond to variants we know to be inactive along this
438461
// particular outgoing edge of a `SwitchInt`.
439-
drop_flag_effects::on_all_inactive_variants(
462+
drop_flag_effects::on_all_variants(
440463
self.move_data,
441464
data.enum_place,
442465
data.next_discr(value),
443466
|mpi| state.kill(mpi),
444-
move |mpi| {
445-
otherwise_state.as_mut().map(|state| state.kill(mpi));
446-
},
467+
otherwise_state.map(|state| |mpi| state.kill(mpi)),
447468
);
448469
}
449470
}
471+
472+
fn apply_switch_int_edge_effect_for_targets(
473+
&mut self,
474+
targets: &mir::SwitchTargets,
475+
mut data: Self::SwitchIntData,
476+
state: &mut Self::Domain,
477+
mut propagate: impl FnMut(mir::BasicBlock, &Self::Domain),
478+
) {
479+
let analyze_otherwise = self.exclude_inactive_in_otherwise
480+
&& (1..data.discriminants.len()).contains(&targets.all_values().len());
481+
482+
let mut otherwise_state = if analyze_otherwise { Some(state.clone()) } else { None };
483+
let mut target_state = MaybeReachable::Unreachable;
484+
485+
for (value, target) in targets.iter() {
486+
target_state.clone_from(&state);
487+
self.apply_switch_int_edge_effect(
488+
&mut data,
489+
&mut target_state,
490+
SwitchTargetValue::Normal(value),
491+
otherwise_state.as_mut(),
492+
);
493+
propagate(target, &target_state);
494+
}
495+
496+
propagate(targets.otherwise(), otherwise_state.as_ref().unwrap_or(state));
497+
}
450498
}
451499

452500
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
@@ -548,21 +596,46 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
548596
data: &mut Self::SwitchIntData,
549597
state: &mut Self::Domain,
550598
value: SwitchTargetValue,
551-
mut otherwise_state: Option<&mut Self::Domain>,
599+
otherwise_state: Option<&mut Self::Domain>,
552600
) {
553601
if let SwitchTargetValue::Normal(value) = value {
554602
// Mark all move paths that correspond to variants other than this one as maybe
555603
// uninitialized (in reality, they are *definitely* uninitialized).
556-
drop_flag_effects::on_all_inactive_variants(
604+
drop_flag_effects::on_all_variants(
557605
self.move_data,
558606
data.enum_place,
559607
data.next_discr(value),
560608
|mpi| state.gen_(mpi),
561-
|mpi| {
562-
otherwise_state.as_mut().map(|state| state.gen_(mpi));
563-
},
609+
otherwise_state.map(|state| |mpi| state.gen_(mpi)),
610+
);
611+
}
612+
}
613+
614+
fn apply_switch_int_edge_effect_for_targets(
615+
&mut self,
616+
targets: &mir::SwitchTargets,
617+
mut data: Self::SwitchIntData,
618+
state: &mut Self::Domain,
619+
mut propagate: impl FnMut(mir::BasicBlock, &Self::Domain),
620+
) {
621+
let analyze_otherwise = self.include_inactive_in_otherwise
622+
&& (1..data.discriminants.len()).contains(&targets.all_values().len());
623+
624+
let mut otherwise_state = if analyze_otherwise { Some(state.clone()) } else { None };
625+
let mut target_state = MixedBitSet::new_empty(self.move_data().move_paths.len());
626+
627+
for (value, target) in targets.iter() {
628+
target_state.clone_from(&state);
629+
self.apply_switch_int_edge_effect(
630+
&mut data,
631+
&mut target_state,
632+
SwitchTargetValue::Normal(value),
633+
otherwise_state.as_mut(),
564634
);
635+
propagate(target, &target_state);
565636
}
637+
638+
propagate(targets.otherwise(), otherwise_state.as_ref().unwrap_or(state));
566639
}
567640
}
568641

compiler/rustc_mir_transform/src/elaborate_drops.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
6262
let env = MoveDataTypingEnv { move_data, typing_env };
6363

6464
let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
65+
.exclude_inactive_in_otherwise()
6566
.skipping_unreachable_unwind()
6667
.iterate_to_fixpoint(tcx, body, Some("elaborate_drops"))
6768
.into_results_cursor(body);

compiler/rustc_mir_transform/src/remove_uninit_drops.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
2222
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
2323

2424
let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
25+
.exclude_inactive_in_otherwise()
2526
.iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops"))
2627
.into_results_cursor(body);
2728

0 commit comments

Comments
 (0)