rustc_mir: always downcast enums, even if univariant.

This commit is contained in:
Eduard-Mihai Burtescu 2017-11-18 20:24:54 +02:00
parent fab2532ef9
commit 9deea47c96
11 changed files with 35 additions and 34 deletions

View File

@ -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(),

View File

@ -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())

View File

@ -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))

View File

@ -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,

View File

@ -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)
}

View File

@ -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);

View File

@ -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)

View File

@ -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(),

View File

@ -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) => {

View File

@ -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,

View File

@ -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),
}
}
}