Skip to content

Commit 529c353

Browse files
committed
Fix unsound optimization with explicit variant discriminants
1 parent edebf77 commit 529c353

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

compiler/rustc_mir_transform/src/simplify_try.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -706,12 +706,22 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
706706
let helper = |rhs: &Rvalue<'tcx>,
707707
place: &Place<'tcx>,
708708
variant_index: &VariantIdx,
709+
switch_value: u128,
709710
side_to_choose| {
710711
let place_type = place.ty(self.body, self.tcx).ty;
711712
let adt = match *place_type.kind() {
712713
ty::Adt(adt, _) if adt.is_enum() => adt,
713714
_ => return StatementEquality::NotEqual,
714715
};
716+
let variant_discr = adt.discriminant_for_variant(self.tcx, *variant_index).val;
717+
if variant_discr != switch_value {
718+
trace!(
719+
"NO: variant discriminant {} does not equal switch value {}",
720+
variant_discr,
721+
switch_value
722+
);
723+
return StatementEquality::NotEqual;
724+
}
715725
let variant_is_fieldless = adt.variants[*variant_index].fields.is_empty();
716726
if !variant_is_fieldless {
717727
trace!("NO: variant {:?} was not fieldless", variant_index);
@@ -742,18 +752,18 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
742752
StatementKind::SetDiscriminant { place, variant_index },
743753
)
744754
// we need to make sure that the switch value that targets the bb with SetDiscriminant (y), is the same as the variant index
745-
if Some(variant_index.index() as u128) == y_target_and_value.value => {
755+
if y_target_and_value.value.is_some() => {
746756
// choose basic block of x, as that has the assign
747-
helper(rhs, place, variant_index, x_target_and_value.target)
757+
helper(rhs, place, variant_index, y_target_and_value.value.unwrap(), x_target_and_value.target)
748758
}
749759
(
750760
StatementKind::SetDiscriminant { place, variant_index },
751761
StatementKind::Assign(box (_, rhs)),
752762
)
753763
// we need to make sure that the switch value that targets the bb with SetDiscriminant (x), is the same as the variant index
754-
if Some(variant_index.index() as u128) == x_target_and_value.value => {
764+
if x_target_and_value.value.is_some() => {
755765
// choose basic block of y, as that has the assign
756-
helper(rhs, place, variant_index, y_target_and_value.target)
766+
helper(rhs, place, variant_index, x_target_and_value.value.unwrap(), y_target_and_value.target)
757767
}
758768
_ => {
759769
trace!("NO: statements `{:?}` and `{:?}` not considered equal", x, y);

src/test/ui/mir/issue-89485.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Regression test for issue #89485.
2+
3+
// run-pass
4+
5+
#[derive(Debug, Eq, PartialEq)]
6+
pub enum Type {
7+
A = 1,
8+
B = 2,
9+
}
10+
pub fn encode(v: Type) -> Type {
11+
match v {
12+
Type::A => Type::B,
13+
_ => v,
14+
}
15+
}
16+
fn main() {
17+
assert_eq!(Type::B, encode(Type::A));
18+
}

0 commit comments

Comments
 (0)