diff options
| author | bors <bors@rust-lang.org> | 2018-03-30 11:48:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-03-30 11:48:10 +0000 |
| commit | 4379c86fe752d0e2eb969646d5a18014ac969a26 (patch) | |
| tree | 6729641d89233b55bee1da33d127cc3c6ef8fe1d | |
| parent | 051050dab9b39d29c8a5978bc79c7895dfa1118b (diff) | |
| parent | 422efd793b0d65bd1d1725937a853244af8124c8 (diff) | |
| download | rust-4379c86fe752d0e2eb969646d5a18014ac969a26.tar.gz rust-4379c86fe752d0e2eb969646d5a18014ac969a26.zip | |
Auto merge of #49403 - oli-obk:try2, r=eddyb
Trim discriminants to their final type size r? @eddyb fixes #49181
| -rw-r--r-- | src/librustc_mir/hair/pattern/mod.rs | 37 | ||||
| -rw-r--r-- | src/test/run-pass/match-arm-statics.rs | 7 |
2 files changed, 38 insertions, 6 deletions
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index eb87d5b044b..798d6353181 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -851,13 +851,38 @@ 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::<Vec<_>>(), + ); + }) + } + ty::layout::Variants::NicheFilling { .. } => { + assert_eq!(discr_val as usize as u128, discr_val); + discr_val as usize + }, + }; let subpatterns = adt_subpatterns( adt_def.variants[variant_index].fields.len(), Some(variant_index), diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs index 78a37f51837..ca6ef2e4277 100644 --- a/src/test/run-pass/match-arm-statics.rs +++ b/src/test/run-pass/match-arm-statics.rs @@ -94,6 +94,13 @@ fn issue_14576() { const F : C = C::D; assert_eq!(match C::D { F => 1, _ => 2, }, 1); + + // test gaps + #[derive(PartialEq, Eq)] + enum G { H = 3, I = 5 } + const K : G = G::I; + + assert_eq!(match G::I { K => 1, _ => 2, }, 1); } fn issue_13731() { |
