@@ -239,23 +239,26 @@ where
239
239
}
240
240
241
241
SwitchInt { ref targets, ref values, ref discr, .. } => {
242
- // If this is a switch on an enum discriminant, a custom effect may be applied
243
- // along each outgoing edge.
244
- if let Some ( place) = discr. place ( ) {
245
- let enum_def = switch_on_enum_discriminant ( self . tcx , self . body , bb_data, place) ;
246
- if let Some ( enum_def) = enum_def {
242
+ let Engine { tcx, body, .. } = * self ;
243
+ let enum_ = discr
244
+ . place ( )
245
+ . and_then ( |discr| switch_on_enum_discriminant ( tcx, body, bb_data, discr) ) ;
246
+ match enum_ {
247
+ // If this is a switch on an enum discriminant, a custom effect may be applied
248
+ // along each outgoing edge.
249
+ Some ( ( enum_place, enum_def) ) => {
247
250
self . propagate_bits_into_enum_discriminant_switch_successors (
248
- in_out, bb, enum_def, place , dirty_list, & * values, & * targets,
251
+ in_out, bb, enum_def, enum_place , dirty_list, & * values, & * targets,
249
252
) ;
250
-
251
- return ;
252
253
}
253
- }
254
254
255
- // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same
256
- // exit state.
257
- for target in targets. iter ( ) . copied ( ) {
258
- self . propagate_bits_into_entry_set_for ( & in_out, target, dirty_list) ;
255
+ // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same
256
+ // exit state.
257
+ None => {
258
+ for target in targets. iter ( ) . copied ( ) {
259
+ self . propagate_bits_into_entry_set_for ( & in_out, target, dirty_list) ;
260
+ }
261
+ }
259
262
}
260
263
}
261
264
@@ -342,22 +345,27 @@ where
342
345
}
343
346
}
344
347
345
- /// Look at the last statement of a block that ends with to see if it is an assignment of an enum
346
- /// discriminant to the local that determines the target of a `SwitchInt` like so:
347
- /// _42 = discriminant(..)
348
+ /// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is
349
+ /// an enum discriminant.
350
+ ///
351
+ /// We expect such blocks to have a call to `discriminant` as their last statement like so:
352
+ /// _42 = discriminant(_1)
348
353
/// SwitchInt(_42, ..)
354
+ ///
355
+ /// If the basic block matches this pattern, this function returns the place corresponding to the
356
+ /// enum (`_1` in the example above) as well as the `AdtDef` of that enum.
349
357
fn switch_on_enum_discriminant (
350
358
tcx : TyCtxt < ' tcx > ,
351
- body : & mir:: Body < ' tcx > ,
352
- block : & mir:: BasicBlockData < ' tcx > ,
359
+ body : & ' mir mir:: Body < ' tcx > ,
360
+ block : & ' mir mir:: BasicBlockData < ' tcx > ,
353
361
switch_on : & mir:: Place < ' tcx > ,
354
- ) -> Option < & ' tcx ty:: AdtDef > {
362
+ ) -> Option < ( & ' mir mir :: Place < ' tcx > , & ' tcx ty:: AdtDef ) > {
355
363
match block. statements . last ( ) . map ( |stmt| & stmt. kind ) {
356
364
Some ( mir:: StatementKind :: Assign ( box ( lhs, mir:: Rvalue :: Discriminant ( discriminated) ) ) )
357
365
if lhs == switch_on =>
358
366
{
359
367
match & discriminated. ty ( body, tcx) . ty . kind {
360
- ty:: Adt ( def, _) => Some ( def) ,
368
+ ty:: Adt ( def, _) => Some ( ( discriminated , def) ) ,
361
369
362
370
// `Rvalue::Discriminant` is also used to get the active yield point for a
363
371
// generator, but we do not need edge-specific effects in that case. This may
0 commit comments