about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src/jump_threading.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/jump_threading.rs')
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs22
1 files changed, 20 insertions, 2 deletions
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index a41d8e21245..dcab124505e 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -43,6 +43,7 @@ use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem};
+use rustc_target::abi::{TagEncoding, Variants};
 
 use crate::cost_checker::CostChecker;
 
@@ -391,8 +392,25 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             StatementKind::SetDiscriminant { box place, variant_index } => {
                 let discr_target = self.map.find_discr(place.as_ref())?;
                 let enum_ty = place.ty(self.body, self.tcx).ty;
-                let discr = discriminant_for_variant(enum_ty, *variant_index)?;
-                self.process_operand(bb, discr_target, &discr, state)?;
+                // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant
+                // of a niche encoding. If we cannot ensure that we write to the discriminant, do
+                // nothing.
+                let enum_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?;
+                let writes_discriminant = match enum_layout.variants {
+                    Variants::Single { index } => {
+                        assert_eq!(index, *variant_index);
+                        true
+                    }
+                    Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => true,
+                    Variants::Multiple {
+                        tag_encoding: TagEncoding::Niche { untagged_variant, .. },
+                        ..
+                    } => *variant_index != untagged_variant,
+                };
+                if writes_discriminant {
+                    let discr = discriminant_for_variant(enum_ty, *variant_index)?;
+                    self.process_operand(bb, discr_target, &discr, state)?;
+                }
             }
             // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`.
             StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(