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 { (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::()); @@ -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::()); + + match UnivariantWithData::Z(4) { + UnivariantWithData::Z(x) => assert_eq!(x, 4), + } + } }