Skip to content

Commit 4c5f9f7

Browse files
Replace discriminant_switch_effect with more general version
...that allows arbitrary effects on each edge of a `SwitchInt` terminator.
1 parent e37c99f commit 4c5f9f7

File tree

1 file changed

+44
-21
lines changed
  • compiler/rustc_mir/src/dataflow/framework

1 file changed

+44
-21
lines changed

compiler/rustc_mir/src/dataflow/framework/mod.rs

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ use rustc_hir::def_id::DefId;
3737
use rustc_index::bit_set::{BitSet, HybridBitSet};
3838
use rustc_index::vec::Idx;
3939
use rustc_middle::mir::{self, BasicBlock, Location};
40-
use rustc_middle::ty::{self, TyCtxt};
41-
use rustc_target::abi::VariantIdx;
40+
use rustc_middle::ty::TyCtxt;
4241

4342
mod cursor;
4443
mod direction;
@@ -152,6 +151,8 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
152151
) {
153152
}
154153

154+
/* Edge-specific effects */
155+
155156
/// Updates the current dataflow state with the effect of a successful return from a `Call`
156157
/// terminator.
157158
///
@@ -183,20 +184,28 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
183184
/// Updates the current dataflow state with the effect of taking a particular branch in a
184185
/// `SwitchInt` terminator.
185186
///
186-
/// Much like `apply_call_return_effect`, this effect is only propagated along a single
187-
/// outgoing edge from this basic block.
187+
/// Unlike the other edge-specific effects, which are allowed to mutate `Self::Domain`
188+
/// directly, overriders of this method must pass a callback to
189+
/// [`SwitchIntEdgeEffects::apply`]. The callback will be run once for each outgoing edge and
190+
/// will have access to the dataflow state that will be propagated along that edge.
191+
///
192+
/// This interface is somewhat more complex than the other visitor-like "effect" methods.
193+
/// However, it is both more ergonomic—callers don't need to recompute or cache information
194+
/// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the
195+
/// engine doesn't need to clone the exit state for a block unless
196+
/// `SwitchIntEdgeEffects::apply` is actually called.
188197
///
189198
/// FIXME: This class of effects is not supported for backward dataflow analyses.
190-
fn apply_discriminant_switch_effect(
199+
fn apply_switch_int_edge_effects(
191200
&self,
192-
_state: &mut Self::Domain,
193201
_block: BasicBlock,
194-
_enum_place: mir::Place<'tcx>,
195-
_adt: &ty::AdtDef,
196-
_variant: VariantIdx,
202+
_discr: &mir::Operand<'tcx>,
203+
_apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
197204
) {
198205
}
199206

207+
/* Extension methods */
208+
200209
/// Creates an `Engine` to find the fixpoint for this dataflow problem.
201210
///
202211
/// You shouldn't need to override this outside this module, since the combination of the
@@ -267,6 +276,8 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
267276
) {
268277
}
269278

279+
/* Edge-specific effects */
280+
270281
/// See `Analysis::apply_call_return_effect`.
271282
fn call_return_effect(
272283
&self,
@@ -286,14 +297,12 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
286297
) {
287298
}
288299

289-
/// See `Analysis::apply_discriminant_switch_effect`.
290-
fn discriminant_switch_effect(
300+
/// See `Analysis::apply_switch_int_edge_effects`.
301+
fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
291302
&self,
292-
_state: &mut impl GenKill<Self::Idx>,
293303
_block: BasicBlock,
294-
_enum_place: mir::Place<'tcx>,
295-
_adt: &ty::AdtDef,
296-
_variant: VariantIdx,
304+
_discr: &mir::Operand<'tcx>,
305+
_edge_effects: &mut impl SwitchIntEdgeEffects<G>,
297306
) {
298307
}
299308
}
@@ -339,6 +348,8 @@ where
339348
self.before_terminator_effect(state, terminator, location);
340349
}
341350

351+
/* Edge-specific effects */
352+
342353
fn apply_call_return_effect(
343354
&self,
344355
state: &mut A::Domain,
@@ -359,17 +370,17 @@ where
359370
self.yield_resume_effect(state, resume_block, resume_place);
360371
}
361372

362-
fn apply_discriminant_switch_effect(
373+
fn apply_switch_int_edge_effects(
363374
&self,
364-
state: &mut A::Domain,
365375
block: BasicBlock,
366-
enum_place: mir::Place<'tcx>,
367-
adt: &ty::AdtDef,
368-
variant: VariantIdx,
376+
discr: &mir::Operand<'tcx>,
377+
edge_effects: &mut impl SwitchIntEdgeEffects<A::Domain>,
369378
) {
370-
self.discriminant_switch_effect(state, block, enum_place, adt, variant);
379+
self.switch_int_edge_effects(block, discr, edge_effects);
371380
}
372381

382+
/* Extension methods */
383+
373384
fn into_engine(
374385
self,
375386
tcx: TyCtxt<'tcx>,
@@ -531,5 +542,17 @@ impl EffectIndex {
531542
}
532543
}
533544

545+
pub struct SwitchIntTarget {
546+
pub value: Option<u128>,
547+
pub target: BasicBlock,
548+
}
549+
550+
/// A type that records the edge-specific effects for a `SwitchInt` terminator.
551+
pub trait SwitchIntEdgeEffects<D> {
552+
/// Calls `apply_edge_effect` for each outgoing edge from a `SwitchInt` terminator and
553+
/// records the results.
554+
fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget));
555+
}
556+
534557
#[cfg(test)]
535558
mod tests;

0 commit comments

Comments
 (0)