@@ -37,8 +37,7 @@ use rustc_hir::def_id::DefId;
37
37
use rustc_index:: bit_set:: { BitSet , HybridBitSet } ;
38
38
use rustc_index:: vec:: Idx ;
39
39
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 ;
42
41
43
42
mod cursor;
44
43
mod direction;
@@ -152,6 +151,8 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
152
151
) {
153
152
}
154
153
154
+ /* Edge-specific effects */
155
+
155
156
/// Updates the current dataflow state with the effect of a successful return from a `Call`
156
157
/// terminator.
157
158
///
@@ -183,20 +184,28 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
183
184
/// Updates the current dataflow state with the effect of taking a particular branch in a
184
185
/// `SwitchInt` terminator.
185
186
///
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.
188
197
///
189
198
/// 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 (
191
200
& self ,
192
- _state : & mut Self :: Domain ,
193
201
_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 > ,
197
204
) {
198
205
}
199
206
207
+ /* Extension methods */
208
+
200
209
/// Creates an `Engine` to find the fixpoint for this dataflow problem.
201
210
///
202
211
/// 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> {
267
276
) {
268
277
}
269
278
279
+ /* Edge-specific effects */
280
+
270
281
/// See `Analysis::apply_call_return_effect`.
271
282
fn call_return_effect (
272
283
& self ,
@@ -286,14 +297,12 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
286
297
) {
287
298
}
288
299
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 > > (
291
302
& self ,
292
- _state : & mut impl GenKill < Self :: Idx > ,
293
303
_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 > ,
297
306
) {
298
307
}
299
308
}
@@ -339,6 +348,8 @@ where
339
348
self . before_terminator_effect ( state, terminator, location) ;
340
349
}
341
350
351
+ /* Edge-specific effects */
352
+
342
353
fn apply_call_return_effect (
343
354
& self ,
344
355
state : & mut A :: Domain ,
@@ -359,17 +370,17 @@ where
359
370
self . yield_resume_effect ( state, resume_block, resume_place) ;
360
371
}
361
372
362
- fn apply_discriminant_switch_effect (
373
+ fn apply_switch_int_edge_effects (
363
374
& self ,
364
- state : & mut A :: Domain ,
365
375
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 > ,
369
378
) {
370
- self . discriminant_switch_effect ( state , block, enum_place , adt , variant ) ;
379
+ self . switch_int_edge_effects ( block, discr , edge_effects ) ;
371
380
}
372
381
382
+ /* Extension methods */
383
+
373
384
fn into_engine (
374
385
self ,
375
386
tcx : TyCtxt < ' tcx > ,
@@ -531,5 +542,17 @@ impl EffectIndex {
531
542
}
532
543
}
533
544
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
+
534
557
#[ cfg( test) ]
535
558
mod tests;
0 commit comments