Move type of discriminant to AdtDef
Previously AdtDef variants contained ConstInt for each discriminant, which did not really reflect the actual type of the discriminants. Moving the type into AdtDef allows to easily put the type into metadata and also saves bytes from ConstVal overhead for each discriminant. Also arguably the code is cleaner now :)
This commit is contained in:
parent
98d1db7fe3
commit
24c93efbb5
@ -673,10 +673,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn alloc_adt_def(self,
|
||||
did: DefId,
|
||||
kind: AdtKind,
|
||||
discr_ty: Option<attr::IntType>,
|
||||
variants: Vec<ty::VariantDef>,
|
||||
repr: ReprOptions)
|
||||
-> &'gcx ty::AdtDef {
|
||||
let def = ty::AdtDef::new(self, did, kind, variants, repr);
|
||||
let discr_ty = discr_ty.unwrap_or(attr::UnsignedInt(ast::UintTy::U8));
|
||||
let def = ty::AdtDef::new(self, did, kind, discr_ty, variants, repr);
|
||||
self.global_arenas.adt_def.alloc(def)
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
|
||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use syntax::attr;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
@ -1183,10 +1182,12 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
i64::min_value(),
|
||||
true);
|
||||
for v in &def.variants {
|
||||
let x = match v.disr_val.erase_type() {
|
||||
ConstInt::InferSigned(i) => i as i64,
|
||||
ConstInt::Infer(i) => i as u64 as i64,
|
||||
_ => bug!()
|
||||
let x = match def.discr_ty {
|
||||
attr::IntType::SignedInt(IntTy::I128) |
|
||||
attr::IntType::UnsignedInt(UintTy::U128) =>
|
||||
bug!("128-bit discriminants not yet supported"),
|
||||
attr::IntType::SignedInt(_) => v.disr_val as i64,
|
||||
attr::IntType::UnsignedInt(_) => v.disr_val as u64 as i64,
|
||||
};
|
||||
if x == 0 { non_zero = false; }
|
||||
if x < min { min = x; }
|
||||
@ -1247,7 +1248,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
// non-empty body, explicit discriminants should have
|
||||
// been rejected by a checker before this point.
|
||||
for (i, v) in def.variants.iter().enumerate() {
|
||||
if i as u128 != v.disr_val.to_u128_unchecked() {
|
||||
if i as u128 != v.disr_val {
|
||||
bug!("non-C-like enum {} with specified discriminants",
|
||||
tcx.item_path_str(def.did));
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ use syntax::attr;
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
|
||||
|
||||
use hir;
|
||||
@ -72,6 +71,8 @@ pub use self::context::{Lift, TypeckTables};
|
||||
|
||||
pub use self::trait_def::{TraitDef, TraitFlags};
|
||||
|
||||
use rustc_i128::u128;
|
||||
|
||||
pub mod adjustment;
|
||||
pub mod cast;
|
||||
pub mod error;
|
||||
@ -96,7 +97,7 @@ mod flags;
|
||||
mod structural_impls;
|
||||
mod sty;
|
||||
|
||||
pub type Disr = ConstInt;
|
||||
pub type Disr = u128;
|
||||
|
||||
// Data types
|
||||
|
||||
@ -1325,6 +1326,7 @@ pub struct FieldDef {
|
||||
/// table.
|
||||
pub struct AdtDef {
|
||||
pub did: DefId,
|
||||
pub discr_ty: attr::IntType, // Type of the discriminant
|
||||
pub variants: Vec<VariantDef>,
|
||||
destructor: Cell<Option<DefId>>,
|
||||
flags: Cell<AdtFlags>,
|
||||
@ -1387,6 +1389,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
did: DefId,
|
||||
kind: AdtKind,
|
||||
discr_ty: attr::IntType,
|
||||
variants: Vec<VariantDef>,
|
||||
repr: ReprOptions) -> Self {
|
||||
let mut flags = AdtFlags::NO_ADT_FLAGS;
|
||||
@ -1410,6 +1413,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
}
|
||||
AdtDef {
|
||||
did: did,
|
||||
discr_ty: discr_ty,
|
||||
variants: variants,
|
||||
flags: Cell::new(flags),
|
||||
destructor: Cell::new(None),
|
||||
|
@ -23,7 +23,7 @@ use ty::TypeVariants::*;
|
||||
use util::nodemap::FxHashMap;
|
||||
use middle::lang_items;
|
||||
|
||||
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult};
|
||||
|
||||
use std::cell::RefCell;
|
||||
@ -34,14 +34,15 @@ use syntax::ast::{self, Name};
|
||||
use syntax::attr::{self, SignedInt, UnsignedInt};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc_i128::i128;
|
||||
|
||||
use hir;
|
||||
|
||||
pub trait IntTypeExt {
|
||||
fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx>;
|
||||
fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
|
||||
-> Option<Disr>;
|
||||
fn assert_ty_matches(&self, val: Disr);
|
||||
fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr;
|
||||
fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr;
|
||||
}
|
||||
|
||||
impl IntTypeExt for attr::IntType {
|
||||
@ -62,56 +63,18 @@ impl IntTypeExt for attr::IntType {
|
||||
}
|
||||
}
|
||||
|
||||
fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
|
||||
match *self {
|
||||
SignedInt(ast::IntTy::I8) => ConstInt::I8(0),
|
||||
SignedInt(ast::IntTy::I16) => ConstInt::I16(0),
|
||||
SignedInt(ast::IntTy::I32) => ConstInt::I32(0),
|
||||
SignedInt(ast::IntTy::I64) => ConstInt::I64(0),
|
||||
SignedInt(ast::IntTy::I128) => ConstInt::I128(0),
|
||||
SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
|
||||
ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)),
|
||||
ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
|
||||
ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)),
|
||||
_ => bug!(),
|
||||
},
|
||||
UnsignedInt(ast::UintTy::U8) => ConstInt::U8(0),
|
||||
UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
|
||||
UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
|
||||
UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
|
||||
UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0),
|
||||
UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
|
||||
ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)),
|
||||
ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
|
||||
ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)),
|
||||
_ => bug!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_ty_matches(&self, val: Disr) {
|
||||
match (*self, val) {
|
||||
(SignedInt(ast::IntTy::I8), ConstInt::I8(_)) => {},
|
||||
(SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {},
|
||||
(SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
|
||||
(SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
|
||||
(SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
|
||||
(SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
|
||||
(UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
|
||||
_ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
|
||||
}
|
||||
fn initial_discriminant<'a, 'tcx>(&self, _: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
|
||||
0
|
||||
}
|
||||
|
||||
/// None = overflow
|
||||
fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
|
||||
-> Option<Disr> {
|
||||
if let Some(val) = val {
|
||||
self.assert_ty_matches(val);
|
||||
(val + ConstInt::Infer(1)).ok()
|
||||
match *self {
|
||||
SignedInt(it) => ConstInt::new_signed(val as i128, it, tcx.sess.target.int_type),
|
||||
UnsignedInt(it) => ConstInt::new_unsigned(val, it, tcx.sess.target.uint_type),
|
||||
}.and_then(|l| (l + ConstInt::Infer(1)).ok()).map(|v| v.to_u128_unchecked())
|
||||
} else {
|
||||
Some(self.initial_discriminant(tcx))
|
||||
}
|
||||
|
@ -25,8 +25,6 @@ use rustc::session::Session;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use rustc::mir::Mir;
|
||||
|
||||
use std::borrow::Cow;
|
||||
@ -435,7 +433,7 @@ impl<'tcx> EntryKind<'tcx> {
|
||||
EntryKind::Mod(_) => Def::Mod(did),
|
||||
EntryKind::Variant(_) => Def::Variant(did),
|
||||
EntryKind::Trait(_) => Def::Trait(did),
|
||||
EntryKind::Enum(_) => Def::Enum(did),
|
||||
EntryKind::Enum(..) => Def::Enum(did),
|
||||
EntryKind::MacroDef(_) => Def::Macro(did),
|
||||
|
||||
EntryKind::ForeignMod |
|
||||
@ -535,7 +533,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
vis: f.visibility.decode(self)
|
||||
}
|
||||
}).collect(),
|
||||
disr_val: ConstInt::Infer(data.disr),
|
||||
disr_val: data.disr,
|
||||
ctor_kind: data.ctor_kind,
|
||||
}, data.struct_ctor)
|
||||
}
|
||||
@ -546,6 +544,12 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
-> &'tcx ty::AdtDef {
|
||||
let item = self.entry(item_id);
|
||||
let did = self.local_def_id(item_id);
|
||||
let (kind, ty) = match item.kind {
|
||||
EntryKind::Enum(dt, _) => (ty::AdtKind::Enum, Some(dt.decode(self))),
|
||||
EntryKind::Struct(_) => (ty::AdtKind::Struct, None),
|
||||
EntryKind::Union(_) => (ty::AdtKind::Union, None),
|
||||
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
|
||||
};
|
||||
let mut ctor_index = None;
|
||||
let variants = if let EntryKind::Enum(_) = item.kind {
|
||||
item.children
|
||||
@ -562,13 +566,13 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
vec![variant]
|
||||
};
|
||||
let (kind, repr) = match item.kind {
|
||||
EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
|
||||
EntryKind::Enum(_, repr) => (ty::AdtKind::Enum, repr),
|
||||
EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
|
||||
EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
|
||||
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
|
||||
};
|
||||
|
||||
let adt = tcx.alloc_adt_def(did, kind, variants, repr);
|
||||
let adt = tcx.alloc_adt_def(did, kind, ty, variants, repr);
|
||||
if let Some(ctor_index) = ctor_index {
|
||||
// Make adt definition available through constructor id as well.
|
||||
tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt);
|
||||
|
@ -261,7 +261,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
let data = VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
disr: variant.disr_val,
|
||||
struct_ctor: None,
|
||||
};
|
||||
|
||||
@ -388,7 +388,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
let data = VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
disr: variant.disr_val,
|
||||
struct_ctor: Some(def_id.index),
|
||||
};
|
||||
|
||||
@ -661,7 +661,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
}
|
||||
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
|
||||
hir::ItemTy(..) => EntryKind::Type,
|
||||
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
|
||||
hir::ItemEnum(..) => EntryKind::Enum(self.lazy(&tcx.lookup_adt_def(def_id).discr_ty), get_repr_options(&tcx, def_id)),
|
||||
hir::ItemStruct(ref struct_def, _) => {
|
||||
let variant = tcx.lookup_adt_def(def_id).struct_variant();
|
||||
|
||||
@ -678,7 +678,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
EntryKind::Struct(self.lazy(&VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
disr: variant.disr_val,
|
||||
struct_ctor: struct_ctor,
|
||||
}), repr_options)
|
||||
}
|
||||
@ -688,7 +688,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
EntryKind::Union(self.lazy(&VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
disr: variant.disr_val,
|
||||
struct_ctor: None,
|
||||
}), repr_options)
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ pub enum EntryKind<'tcx> {
|
||||
ForeignMutStatic,
|
||||
ForeignMod,
|
||||
Type,
|
||||
Enum(ReprOptions),
|
||||
Enum(Lazy<attr::IntType>, ReprOptions),
|
||||
Field,
|
||||
Variant(Lazy<VariantData>),
|
||||
Struct(Lazy<VariantData>, ReprOptions),
|
||||
|
@ -1473,7 +1473,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
DIB(cx),
|
||||
name.as_ptr(),
|
||||
// FIXME: what if enumeration has i128 discriminant?
|
||||
v.disr_val.to_u128_unchecked() as u64)
|
||||
v.disr_val as u64)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
@ -27,7 +27,7 @@ impl ::std::ops::BitAnd for Disr {
|
||||
impl From<::rustc::ty::Disr> for Disr {
|
||||
fn from(i: ::rustc::ty::Disr) -> Disr {
|
||||
// FIXME: what if discr has 128 bit discr?
|
||||
Disr(i.to_u128_unchecked() as u64)
|
||||
Disr(i as u64)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1004,9 +1004,8 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let did = ccx.tcx.hir.local_def_id(it.id);
|
||||
// Use separate constructor id for unit/tuple structs and reuse did for braced structs.
|
||||
let ctor_id = if !def.is_struct() { Some(ccx.tcx.hir.local_def_id(def.id())) } else { None };
|
||||
let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
|
||||
ConstInt::Infer(0), def)];
|
||||
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants,
|
||||
let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name, 0, def)];
|
||||
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, None, variants,
|
||||
ReprOptions::new(&ccx.tcx, did));
|
||||
if let Some(ctor_id) = ctor_id {
|
||||
// Make adt definition available through constructor id as well.
|
||||
@ -1023,9 +1022,14 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
-> &'tcx ty::AdtDef
|
||||
{
|
||||
let did = ccx.tcx.hir.local_def_id(it.id);
|
||||
<<<<<<< HEAD
|
||||
let variants = vec![convert_struct_variant(ccx, did, it.name, ConstInt::Infer(0), def)];
|
||||
|
||||
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did));
|
||||
=======
|
||||
let variants = vec![convert_struct_variant(ccx, did, it.name, 0, def)];
|
||||
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, None, variants);
|
||||
>>>>>>> b1934037e6... Move type of discriminant to AdtDef
|
||||
ccx.tcx.adt_defs.borrow_mut().insert(did, adt);
|
||||
adt
|
||||
}
|
||||
@ -1059,7 +1063,8 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
(attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) |
|
||||
(attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) |
|
||||
(attr::UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) |
|
||||
(attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Some(i),
|
||||
(attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) =>
|
||||
Some(i.to_u128_unchecked()),
|
||||
(_, i) => {
|
||||
print_err(ConstVal::Integral(i));
|
||||
None
|
||||
@ -1093,7 +1098,7 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let initial = repr_type.initial_discriminant(tcx);
|
||||
let mut prev_disr = None::<ty::Disr>;
|
||||
let variants = def.variants.iter().map(|v| {
|
||||
let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr());
|
||||
let wrapped_disr = prev_disr.map_or(initial, |d| d.wrapping_add(1));
|
||||
let disr = if let Some(e) = v.node.disr_expr {
|
||||
evaluate_disr_expr(ccx, repr_type, e)
|
||||
} else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) {
|
||||
@ -1113,7 +1118,11 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data)
|
||||
}).collect();
|
||||
|
||||
<<<<<<< HEAD
|
||||
let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did));
|
||||
=======
|
||||
let adt = tcx.alloc_adt_def(did, AdtKind::Enum, Some(repr_type), variants);
|
||||
>>>>>>> b1934037e6... Move type of discriminant to AdtDef
|
||||
tcx.adt_defs.borrow_mut().insert(did, adt);
|
||||
adt
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user