@@ -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