diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a0eae33c4402..6203679a5105 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -26,6 +26,7 @@ use middle::resolve_lifetime; use middle::stability; use mir::Mir; use ty::subst::{Kind, Substs}; +use ty::ReprOptions; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; @@ -672,9 +673,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn alloc_adt_def(self, did: DefId, kind: AdtKind, - variants: Vec) + variants: Vec, + repr: ReprOptions) -> &'gcx ty::AdtDef { - let def = ty::AdtDef::new(self, did, kind, variants); + let def = ty::AdtDef::new(self, did, kind, variants, repr); self.global_arenas.adt_def.alloc(def) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4d9514b1473c..beb286108a03 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1327,7 +1327,8 @@ pub struct AdtDef { pub did: DefId, pub variants: Vec, destructor: Cell>, - flags: Cell + flags: Cell, + pub repr: ReprOptions, } impl PartialEq for AdtDef { @@ -1356,11 +1357,38 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {} #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum AdtKind { Struct, Union, Enum } +/// Represents the repr options provided by the user, +#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] +pub struct ReprOptions { + pub c: bool, + pub packed: bool, + pub simd: bool, + pub int: Option, +} + +impl ReprOptions { + pub fn new<'a, 'gcx, 'tcx>(tcx: &TyCtxt<'a, 'gcx, 'tcx>, did: DefId) -> ReprOptions { + let mut ret = ReprOptions::default(); + let attrs = tcx.lookup_repr_hints(did); + for r in attrs.iter() { + match *r { + attr::ReprExtern => ret.c = true, + attr::ReprPacked => ret.packed = true, + attr::ReprSimd => ret.simd = true, + attr::ReprInt(i) => ret.int = Some(i), + attr::ReprAny => (), + } + } + ret + } +} + impl<'a, 'gcx, 'tcx> AdtDef { fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, did: DefId, kind: AdtKind, - variants: Vec) -> Self { + variants: Vec, + repr: ReprOptions) -> Self { let mut flags = AdtFlags::NO_ADT_FLAGS; let attrs = tcx.get_attrs(did); if attr::contains_name(&attrs, "fundamental") { @@ -1385,6 +1413,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { variants: variants, flags: Cell::new(flags), destructor: Cell::new(None), + repr: repr, } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f4a35ea5fd0c..bb99be20f64d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -425,8 +425,8 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::ForeignImmStatic => Def::Static(did, false), EntryKind::MutStatic | EntryKind::ForeignMutStatic => Def::Static(did, true), - EntryKind::Struct(_) => Def::Struct(did), - EntryKind::Union(_) => Def::Union(did), + EntryKind::Struct(_, _) => Def::Struct(did), + EntryKind::Union(_, _) => Def::Union(did), EntryKind::Fn(_) | EntryKind::ForeignFn(_) => Def::Fn(did), EntryKind::Method(_) => Def::Method(did), @@ -435,7 +435,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 | @@ -519,8 +519,8 @@ impl<'a, 'tcx> CrateMetadata { -> (ty::VariantDef, Option) { let data = match item.kind { EntryKind::Variant(data) | - EntryKind::Struct(data) | - EntryKind::Union(data) => data.decode(self), + EntryKind::Struct(data, _) | + EntryKind::Union(data, _) => data.decode(self), _ => bug!(), }; @@ -547,7 +547,7 @@ impl<'a, 'tcx> CrateMetadata { let item = self.entry(item_id); let did = self.local_def_id(item_id); let mut ctor_index = None; - let variants = if let EntryKind::Enum = item.kind { + let variants = if let EntryKind::Enum(_) = item.kind { item.children .decode(self) .map(|index| { @@ -561,14 +561,14 @@ impl<'a, 'tcx> CrateMetadata { ctor_index = struct_ctor; vec![variant] }; - let kind = match item.kind { - EntryKind::Enum => ty::AdtKind::Enum, - EntryKind::Struct(_) => ty::AdtKind::Struct, - EntryKind::Union(_) => ty::AdtKind::Union, + let (kind, repr) = match item.kind { + 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); + let adt = tcx.alloc_adt_def(did, kind, 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); @@ -881,8 +881,8 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { match self.entry(node_id).kind { - EntryKind::Struct(data) | - EntryKind::Union(data) | + EntryKind::Struct(data, _) | + EntryKind::Union(data, _) | EntryKind::Variant(data) => data.decode(self).ctor_kind, _ => CtorKind::Fictive, } @@ -890,7 +890,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option { match self.entry(node_id).kind { - EntryKind::Struct(data) => { + EntryKind::Struct(data, _) => { data.decode(self).struct_ctor.map(|index| self.local_def_id(index)) } _ => None, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 69e1bbd77662..f4ff5f4626f3 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -20,7 +20,7 @@ use rustc::middle::dependency_format::Linkage; use rustc::middle::lang_items; use rustc::mir; use rustc::traits::specialization_graph; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, ReprOptions}; use rustc::session::config::{self, CrateTypeProcMacro}; use rustc::util::nodemap::{FxHashMap, NodeSet}; @@ -401,8 +401,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } + let repr_options = get_repr_options(&tcx, adt_def_id); + Entry { - kind: EntryKind::Struct(self.lazy(&data)), + kind: EntryKind::Struct(self.lazy(&data), repr_options), visibility: self.lazy(&ctor_vis), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), @@ -659,7 +661,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemForeignMod(_) => EntryKind::ForeignMod, hir::ItemTy(..) => EntryKind::Type, - hir::ItemEnum(..) => EntryKind::Enum, + hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)), hir::ItemStruct(ref struct_def, _) => { let variant = tcx.lookup_adt_def(def_id).struct_variant(); @@ -671,20 +673,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { None }; + + let repr_options = get_repr_options(&tcx, def_id); + EntryKind::Struct(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, disr: variant.disr_val.to_u128_unchecked(), struct_ctor: struct_ctor, - })) + }), repr_options) } hir::ItemUnion(..) => { let variant = tcx.lookup_adt_def(def_id).struct_variant(); + let repr_options = get_repr_options(&tcx, def_id); EntryKind::Union(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, disr: variant.disr_val.to_u128_unchecked(), struct_ctor: None, - })) + }), repr_options) } hir::ItemDefaultImpl(..) => { let data = ImplData { @@ -1419,3 +1425,11 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result } + +pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions { + let ty = tcx.item_type(did); + match ty.sty { + ty::TyAdt(ref def, _) => return def.repr, + _ => bug!("{} is not an ADT", ty), + } +} diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d13628e9ce7a..10aa4784aa2e 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -18,7 +18,7 @@ use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; use rustc::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc::mir; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Ty, ReprOptions}; use rustc_back::PanicStrategy; use rustc_serialize as serialize; @@ -228,11 +228,11 @@ pub enum EntryKind<'tcx> { ForeignMutStatic, ForeignMod, Type, - Enum, + Enum(ReprOptions), Field, Variant(Lazy), - Struct(Lazy), - Union(Lazy), + Struct(Lazy, ReprOptions), + Union(Lazy, ReprOptions), Fn(Lazy), ForeignFn(Lazy), Mod(Lazy), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1981e7c3a3d1..7936db65c44a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; -use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer}; +use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer, ReprOptions}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; use rustc::dep_graph::DepNode; @@ -1006,7 +1006,8 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, 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 adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants, + ReprOptions::new(&ccx.tcx, did)); if let Some(ctor_id) = ctor_id { // Make adt definition available through constructor id as well. ccx.tcx.adt_defs.borrow_mut().insert(ctor_id, adt); @@ -1024,7 +1025,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let did = ccx.tcx.hir.local_def_id(it.id); 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); + let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did)); ccx.tcx.adt_defs.borrow_mut().insert(did, adt); adt } @@ -1112,7 +1113,7 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data) }).collect(); - let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants); + let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did)); tcx.adt_defs.borrow_mut().insert(did, adt); adt }