about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-18 20:24:54 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-18 20:52:38 +0200
commit9deea47c9605f77d3d595744753704bfd74c0dc9 (patch)
treea3c0e2afa11487fb8ae4fd0cf70c2ce1cfacd56b /src
parentfab2532ef949a08e16b621259a91d1ff37165665 (diff)
rustc_mir: always downcast enums, even if univariant.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/ty/mod.rs5
-rw-r--r--src/librustc_const_eval/_match.rs6
-rw-r--r--src/librustc_const_eval/pattern.rs4
-rw-r--r--src/librustc_mir/build/matches/simplify.rs21
-rw-r--r--src/librustc_mir/build/matches/test.rs4
-rw-r--r--src/librustc_mir/hair/cx/mod.rs4
-rw-r--r--src/librustc_mir/transform/deaggregator.rs4
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs2
-rw-r--r--src/test/run-pass/enum-univariant-repr.rs13
11 files changed, 35 insertions, 34 deletions
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 2c6bcc654a5..c89d67d4aab 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -210,7 +210,7 @@ impl<'tcx> cmt_<'tcx> {
                 adt_def.variant_with_id(variant_did)
             }
             _ => {
-                assert!(adt_def.is_univariant());
+                assert_eq!(adt_def.variants.len(), 1);
                 &adt_def.variants[0]
             }
         };
@@ -1096,7 +1096,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                                               -> cmt<'tcx> {
         // univariant enums do not need downcasts
         let base_did = self.tcx.parent_def_id(variant_did).unwrap();
-        if !self.tcx.adt_def(base_did).is_univariant() {
+        if self.tcx.adt_def(base_did).variants.len() != 1 {
             let base_ty = base_cmt.ty;
             let ret = Rc::new(cmt_ {
                 id: node.id(),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a584f2ce191..dac200efb39 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1674,11 +1674,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         self.variants.iter().flat_map(|v| v.fields.iter())
     }
 
-    #[inline]
-    pub fn is_univariant(&self) -> bool {
-        self.variants.len() == 1
-    }
-
     pub fn is_payloadfree(&self) -> bool {
         !self.variants.is_empty() &&
             self.variants.iter().all(|v| v.fields.is_empty())
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index 6ebe3c67966..33d9bfa6e6b 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -255,7 +255,7 @@ impl<'tcx> Constructor<'tcx> {
         match self {
             &Variant(vid) => adt.variant_index_with_id(vid),
             &Single => {
-                assert_eq!(adt.variants.len(), 1);
+                assert!(!adt.is_enum());
                 0
             }
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt)
@@ -356,7 +356,7 @@ impl<'tcx> Witness<'tcx> {
                     }).collect();
 
                     if let ty::TyAdt(adt, substs) = ty.sty {
-                        if adt.variants.len() > 1 {
+                        if adt.is_enum() {
                             PatternKind::Variant {
                                 adt_def: adt,
                                 substs,
@@ -444,7 +444,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                 (0..pcx.max_slice_length+1).map(|length| Slice(length)).collect()
             }
         }
-        ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
+        ty::TyAdt(def, substs) if def.is_enum() => {
             def.variants.iter()
                 .filter(|v| !cx.is_variant_uninhabited(v, substs))
                 .map(|v| Variant(v.did))
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index d7a16e9d2fc..cfbb9623f7d 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -150,7 +150,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
                         Some(&adt_def.variants[variant_index])
                     }
                     _ => if let ty::TyAdt(adt, _) = self.ty.sty {
-                        if adt.is_univariant() {
+                        if !adt.is_enum() {
                             Some(&adt.variants[0])
                         } else {
                             None
@@ -598,7 +598,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
                 let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
-                if adt_def.variants.len() > 1 {
+                if adt_def.is_enum() {
                     let substs = match ty.sty {
                         ty::TyAdt(_, substs) |
                         ty::TyFnDef(_, substs) => substs,
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index 9b3f16f1ab4..a7599f19244 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -98,19 +98,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             }
 
             PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
-                if self.hir.tcx().sess.features.borrow().never_type {
-                    let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
-                        i == variant_index || {
-                            self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
-                        }
-                    });
-                    if irrefutable {
-                        let lvalue = match_pair.lvalue.downcast(adt_def, variant_index);
-                        candidate.match_pairs.extend(self.field_match_pairs(lvalue, subpatterns));
-                        Ok(())
-                    } else {
-                        Err(match_pair)
+                let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
+                    i == variant_index || {
+                        self.hir.tcx().sess.features.borrow().never_type &&
+                        self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
                     }
+                });
+                if irrefutable {
+                    let lvalue = match_pair.lvalue.downcast(adt_def, variant_index);
+                    candidate.match_pairs.extend(self.field_match_pairs(lvalue, subpatterns));
+                    Ok(())
                 } else {
                     Err(match_pair)
                 }
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 1cf35af3a9e..02a7bc83f6e 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -39,7 +39,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     span: match_pair.pattern.span,
                     kind: TestKind::Switch {
                         adt_def: adt_def.clone(),
-                        variants: BitVector::new(self.hir.num_variants(adt_def)),
+                        variants: BitVector::new(adt_def.variants.len()),
                     },
                 }
             }
@@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         match test.kind {
             TestKind::Switch { adt_def, ref variants } => {
                 // Variants is a BitVec of indexes into adt_def.variants.
-                let num_enum_variants = self.hir.num_variants(adt_def);
+                let num_enum_variants = adt_def.variants.len();
                 let used_variants = variants.count();
                 let mut otherwise_block = None;
                 let mut target_blocks = Vec::with_capacity(num_enum_variants);
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 50264238aac..b1f4b849b89 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -213,10 +213,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
-    pub fn num_variants(&mut self, adt_def: &ty::AdtDef) -> usize {
-        adt_def.variants.len()
-    }
-
     pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: usize) -> Vec<Field> {
         (0..adt_def.variants[variant_index].fields.len())
             .map(Field::new)
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index 61b4716c564..e2ecd4839fb 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -67,7 +67,7 @@ impl MirPass for Deaggregator {
                     let ty = variant_def.fields[i].ty(tcx, substs);
                     let rhs = Rvalue::Use(op.clone());
 
-                    let lhs_cast = if adt_def.variants.len() > 1 {
+                    let lhs_cast = if adt_def.is_enum() {
                         Lvalue::Projection(Box::new(LvalueProjection {
                             base: lhs.clone(),
                             elem: ProjectionElem::Downcast(adt_def, variant),
@@ -89,7 +89,7 @@ impl MirPass for Deaggregator {
                 }
 
                 // if the aggregate was an enum, we need to set the discriminant
-                if adt_def.variants.len() > 1 {
+                if adt_def.is_enum() {
                     let set_discriminant = Statement {
                         kind: StatementKind::SetDiscriminant {
                             lvalue: lhs.clone(),
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 837c3d42fe8..30f3a0f3186 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -344,7 +344,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 variant_index,
             } => (&adt_def.variants[variant_index], substs),
             LvalueTy::Ty { ty } => match ty.sty {
-                ty::TyAdt(adt_def, substs) if adt_def.is_univariant() => {
+                ty::TyAdt(adt_def, substs) if !adt_def.is_enum() => {
                     (&adt_def.variants[0], substs)
                 }
                 ty::TyClosure(def_id, substs) => {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 3b9772079ad..1852712a083 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -384,7 +384,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                                   substs: &'tcx Substs<'tcx>)
                                   -> (BasicBlock, Unwind) {
         let (succ, unwind) = self.drop_ladder_bottom();
-        if adt.variants.len() == 1 {
+        if !adt.is_enum() {
             let fields = self.move_paths_for_fields(
                 self.lvalue,
                 self.path,
diff --git a/src/test/run-pass/enum-univariant-repr.rs b/src/test/run-pass/enum-univariant-repr.rs
index ef4cc60bf0d..17d614b5496 100644
--- a/src/test/run-pass/enum-univariant-repr.rs
+++ b/src/test/run-pass/enum-univariant-repr.rs
@@ -22,6 +22,11 @@ enum UnivariantWithoutDescr {
     Y
 }
 
+#[repr(u8)]
+enum UnivariantWithData {
+    Z(u8),
+}
+
 pub fn main() {
     {
         assert_eq!(4, mem::size_of::<Univariant>());
@@ -44,4 +49,12 @@ pub fn main() {
         // check it has the same memory layout as u16
         assert_eq!(&[descr, descr, descr], ints);
     }
+
+    {
+        assert_eq!(2, mem::size_of::<UnivariantWithData>());
+
+        match UnivariantWithData::Z(4) {
+            UnivariantWithData::Z(x) => assert_eq!(x, 4),
+        }
+    }
 }