diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index eb87d5b044b45..7359b1ed1021c 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -851,13 +851,36 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::TyAdt(adt_def, substs) if adt_def.is_enum() => { match cv.val { ConstVal::Value(val) => { - let discr = const_discr( + let discr_val = const_discr( self.tcx, self.param_env, instance, val, cv.ty - ).unwrap(); - let variant_index = adt_def - .discriminants(self.tcx) - .position(|var| var.val == discr) - .unwrap(); + ).expect("const_discr failed"); + let layout = self + .tcx + .layout_of(self.param_env.and(cv.ty)) + .expect("layout of enum not available"); + let variant_index = match layout.variants { + ty::layout::Variants::Single { index } => index, + ty::layout::Variants::Tagged { ref discr, .. } => { + // raw discriminants for enums are isize or bigger during + // their computation, but later shrunk to the smallest possible + // representation + let size = discr.value.size(self.tcx).bits(); + let amt = 128 - size; + adt_def + .discriminants(self.tcx) + .position(|var| ((var.val << amt) >> amt) == discr_val) + .unwrap_or_else(|| { + bug!("discriminant {} not found in {:#?}", + discr_val, + adt_def + .discriminants(self.tcx) + .collect::>(), + ); + }) + } + ty::layout::Variants::NicheFilling { dataful_variant, .. } => + dataful_variant, + }; let subpatterns = adt_subpatterns( adt_def.variants[variant_index].fields.len(), Some(variant_index),