Trim discriminants to their final type size

This commit is contained in:
Oliver Schneider 2018-03-27 08:31:05 +02:00
parent a0b0f5fba5
commit 6b3202a2bf
No known key found for this signature in database
GPG Key ID: 1D5CB4FC597C3004

View File

@ -851,13 +851,36 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
ty::TyAdt(adt_def, substs) if adt_def.is_enum() => { ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
match cv.val { match cv.val {
ConstVal::Value(val) => { ConstVal::Value(val) => {
let discr = const_discr( let discr_val = const_discr(
self.tcx, self.param_env, instance, val, cv.ty self.tcx, self.param_env, instance, val, cv.ty
).unwrap(); ).expect("const_discr failed");
let variant_index = adt_def let layout = self
.discriminants(self.tcx) .tcx
.position(|var| var.val == discr) .layout_of(self.param_env.and(cv.ty))
.unwrap(); .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::<Vec<_>>(),
);
})
}
ty::layout::Variants::NicheFilling { dataful_variant, .. } =>
dataful_variant,
};
let subpatterns = adt_subpatterns( let subpatterns = adt_subpatterns(
adt_def.variants[variant_index].fields.len(), adt_def.variants[variant_index].fields.len(),
Some(variant_index), Some(variant_index),