mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 05:53:10 +00:00
rustc_mir: always downcast enums, even if univariant.
This commit is contained in:
parent
fab2532ef9
commit
9deea47c96
@ -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(),
|
||||
|
@ -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())
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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(),
|
||||
|
@ -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) => {
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user