Rollup merge of #39595 - camlorn:structured_repr, r=eddyb
Make reprs use a structured representation instead of a slice This is needed for `-z reorder-fields`. The old design uses a slice taken from HIR, plus a cache that lazily parses. The new design stores it directly in the `AdtDef` as a `ReprOptions`. We're doing this now because we need to be able to add reprs that don't necessarily exist in HIR for `-z reorder-fields`, but it needs to happen anyway. `lookup_repr_hints` should be mostly deprecated. I want to remove it from `layout` before closing this, unless people think that should be a separate PR. The `[WIP]` is because of this. The problem with closing this as-is is that the code here isn't actually testable until some parts of the compiler start using it. r? @eddyb
This commit is contained in:
commit
15decb86b2
7 changed files with 116 additions and 94 deletions
|
@ -26,6 +26,7 @@ use middle::resolve_lifetime;
|
||||||
use middle::stability;
|
use middle::stability;
|
||||||
use mir::Mir;
|
use mir::Mir;
|
||||||
use ty::subst::{Kind, Substs};
|
use ty::subst::{Kind, Substs};
|
||||||
|
use ty::ReprOptions;
|
||||||
use traits;
|
use traits;
|
||||||
use ty::{self, TraitRef, Ty, TypeAndMut};
|
use ty::{self, TraitRef, Ty, TypeAndMut};
|
||||||
use ty::{TyS, TypeVariants, Slice};
|
use ty::{TyS, TypeVariants, Slice};
|
||||||
|
@ -672,9 +673,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn alloc_adt_def(self,
|
pub fn alloc_adt_def(self,
|
||||||
did: DefId,
|
did: DefId,
|
||||||
kind: AdtKind,
|
kind: AdtKind,
|
||||||
variants: Vec<ty::VariantDef>)
|
variants: Vec<ty::VariantDef>,
|
||||||
|
repr: ReprOptions)
|
||||||
-> &'gcx ty::AdtDef {
|
-> &'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)
|
self.global_arenas.adt_def.alloc(def)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub use self::Primitive::*;
|
||||||
use infer::InferCtxt;
|
use infer::InferCtxt;
|
||||||
use session::Session;
|
use session::Session;
|
||||||
use traits;
|
use traits;
|
||||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
|
||||||
|
|
||||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
@ -437,7 +437,7 @@ impl Integer {
|
||||||
/// signed discriminant range and #[repr] attribute.
|
/// signed discriminant range and #[repr] attribute.
|
||||||
/// N.B.: u64 values above i64::MAX will be treated as signed, but
|
/// N.B.: u64 values above i64::MAX will be treated as signed, but
|
||||||
/// that shouldn't affect anything, other than maybe debuginfo.
|
/// that shouldn't affect anything, other than maybe debuginfo.
|
||||||
fn repr_discr(tcx: TyCtxt, ty: Ty, hints: &[attr::ReprAttr], min: i64, max: i64)
|
fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
|
||||||
-> (Integer, bool) {
|
-> (Integer, bool) {
|
||||||
// Theoretically, negative values could be larger in unsigned representation
|
// Theoretically, negative values could be larger in unsigned representation
|
||||||
// than the unsigned representation of the signed minimum. However, if there
|
// than the unsigned representation of the signed minimum. However, if there
|
||||||
|
@ -449,34 +449,24 @@ impl Integer {
|
||||||
let mut min_from_extern = None;
|
let mut min_from_extern = None;
|
||||||
let min_default = I8;
|
let min_default = I8;
|
||||||
|
|
||||||
for &r in hints.iter() {
|
if let Some(ity) = repr.int {
|
||||||
match r {
|
let discr = Integer::from_attr(&tcx.data_layout, ity);
|
||||||
attr::ReprInt(ity) => {
|
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
|
||||||
let discr = Integer::from_attr(&tcx.data_layout, ity);
|
if discr < fit {
|
||||||
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
|
bug!("Integer::repr_discr: `#[repr]` hint too small for \
|
||||||
if discr < fit {
|
discriminant range of enum `{}", ty)
|
||||||
bug!("Integer::repr_discr: `#[repr]` hint too small for \
|
}
|
||||||
discriminant range of enum `{}", ty)
|
return (discr, ity.is_signed());
|
||||||
}
|
}
|
||||||
return (discr, ity.is_signed());
|
|
||||||
}
|
if repr.c {
|
||||||
attr::ReprExtern => {
|
match &tcx.sess.target.target.arch[..] {
|
||||||
match &tcx.sess.target.target.arch[..] {
|
// WARNING: the ARM EABI has two variants; the one corresponding
|
||||||
// WARNING: the ARM EABI has two variants; the one corresponding
|
// to `at_least == I32` appears to be used on Linux and NetBSD,
|
||||||
// to `at_least == I32` appears to be used on Linux and NetBSD,
|
// but some systems may use the variant corresponding to no
|
||||||
// but some systems may use the variant corresponding to no
|
// lower bound. However, we don't run on those yet...?
|
||||||
// lower bound. However, we don't run on those yet...?
|
"arm" => min_from_extern = Some(I32),
|
||||||
"arm" => min_from_extern = Some(I32),
|
_ => min_from_extern = Some(I32),
|
||||||
_ => min_from_extern = Some(I32),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attr::ReprAny => {},
|
|
||||||
attr::ReprPacked => {
|
|
||||||
bug!("Integer::repr_discr: found #[repr(packed)] on enum `{}", ty);
|
|
||||||
}
|
|
||||||
attr::ReprSimd => {
|
|
||||||
bug!("Integer::repr_discr: found #[repr(simd)] on enum `{}", ty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,9 +558,9 @@ enum StructKind {
|
||||||
impl<'a, 'gcx, 'tcx> Struct {
|
impl<'a, 'gcx, 'tcx> Struct {
|
||||||
// FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
|
// FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
|
||||||
fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
|
fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
|
||||||
reprs: &[attr::ReprAttr], kind: StructKind,
|
repr: &ReprOptions, kind: StructKind,
|
||||||
scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
|
scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
|
||||||
let packed = reprs.contains(&attr::ReprPacked);
|
let packed = repr.packed;
|
||||||
let mut ret = Struct {
|
let mut ret = Struct {
|
||||||
align: if packed { dl.i8_align } else { dl.aggregate_align },
|
align: if packed { dl.i8_align } else { dl.aggregate_align },
|
||||||
packed: packed,
|
packed: packed,
|
||||||
|
@ -580,27 +570,16 @@ impl<'a, 'gcx, 'tcx> Struct {
|
||||||
min_size: Size::from_bytes(0),
|
min_size: Size::from_bytes(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Anything with ReprExtern or ReprPacked doesn't optimize.
|
// Anything with repr(C) or repr(packed) doesn't optimize.
|
||||||
// Neither do 1-member and 2-member structs.
|
// Neither do 1-member and 2-member structs.
|
||||||
// In addition, code in trans assume that 2-element structs can become pairs.
|
// In addition, code in trans assume that 2-element structs can become pairs.
|
||||||
// It's easier to just short-circuit here.
|
// It's easier to just short-circuit here.
|
||||||
let mut can_optimize = fields.len() > 2 || StructKind::EnumVariant == kind;
|
let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
|
||||||
if can_optimize {
|
&& ! (repr.c || repr.packed);
|
||||||
// This exhaustive match makes new reprs force the adder to modify this function.
|
|
||||||
// Otherwise, things can silently break.
|
|
||||||
// Note the inversion, return true to stop optimizing.
|
|
||||||
can_optimize = !reprs.iter().any(|r| {
|
|
||||||
match *r {
|
|
||||||
attr::ReprAny | attr::ReprInt(_) => false,
|
|
||||||
attr::ReprExtern | attr::ReprPacked => true,
|
|
||||||
attr::ReprSimd => bug!("Simd vectors should be represented as layout::Vector")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable field reordering until we can decide what to do.
|
// Disable field reordering until we can decide what to do.
|
||||||
// The odd pattern here avoids a warning about the value never being read.
|
// The odd pattern here avoids a warning about the value never being read.
|
||||||
if can_optimize { can_optimize = false }
|
if can_optimize { can_optimize = false; }
|
||||||
|
|
||||||
let (optimize, sort_ascending) = match kind {
|
let (optimize, sort_ascending) = match kind {
|
||||||
StructKind::AlwaysSizedUnivariant => (can_optimize, false),
|
StructKind::AlwaysSizedUnivariant => (can_optimize, false),
|
||||||
|
@ -1092,7 +1071,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
|
|
||||||
// The never type.
|
// The never type.
|
||||||
ty::TyNever => Univariant {
|
ty::TyNever => Univariant {
|
||||||
variant: Struct::new(dl, &vec![], &[],
|
variant: Struct::new(dl, &vec![], &ReprOptions::default(),
|
||||||
StructKind::AlwaysSizedUnivariant, ty)?,
|
StructKind::AlwaysSizedUnivariant, ty)?,
|
||||||
non_zero: false
|
non_zero: false
|
||||||
},
|
},
|
||||||
|
@ -1135,12 +1114,12 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
ty::TyFnDef(..) => {
|
ty::TyFnDef(..) => {
|
||||||
Univariant {
|
Univariant {
|
||||||
variant: Struct::new(dl, &vec![],
|
variant: Struct::new(dl, &vec![],
|
||||||
&[], StructKind::AlwaysSizedUnivariant, ty)?,
|
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
|
||||||
non_zero: false
|
non_zero: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::TyDynamic(..) => {
|
ty::TyDynamic(..) => {
|
||||||
let mut unit = Struct::new(dl, &vec![], &[],
|
let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
|
||||||
StructKind::AlwaysSizedUnivariant, ty)?;
|
StructKind::AlwaysSizedUnivariant, ty)?;
|
||||||
unit.sized = false;
|
unit.sized = false;
|
||||||
Univariant { variant: unit, non_zero: false }
|
Univariant { variant: unit, non_zero: false }
|
||||||
|
@ -1152,7 +1131,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
let st = Struct::new(dl,
|
let st = Struct::new(dl,
|
||||||
&tys.map(|ty| ty.layout(infcx))
|
&tys.map(|ty| ty.layout(infcx))
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
&[],
|
&ReprOptions::default(),
|
||||||
StructKind::AlwaysSizedUnivariant, ty)?;
|
StructKind::AlwaysSizedUnivariant, ty)?;
|
||||||
Univariant { variant: st, non_zero: false }
|
Univariant { variant: st, non_zero: false }
|
||||||
}
|
}
|
||||||
|
@ -1163,7 +1142,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
let st = Struct::new(dl,
|
let st = Struct::new(dl,
|
||||||
&tys.iter().map(|ty| ty.layout(infcx))
|
&tys.iter().map(|ty| ty.layout(infcx))
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
&[], StructKind::AlwaysSizedUnivariant, ty)?;
|
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
|
||||||
Univariant { variant: st, non_zero: false }
|
Univariant { variant: st, non_zero: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,16 +1166,13 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
|
|
||||||
// ADTs.
|
// ADTs.
|
||||||
ty::TyAdt(def, substs) => {
|
ty::TyAdt(def, substs) => {
|
||||||
let hints = &tcx.lookup_repr_hints(def.did)[..];
|
|
||||||
|
|
||||||
if def.variants.is_empty() {
|
if def.variants.is_empty() {
|
||||||
// Uninhabitable; represent as unit
|
// Uninhabitable; represent as unit
|
||||||
// (Typechecking will reject discriminant-sizing attrs.)
|
// (Typechecking will reject discriminant-sizing attrs.)
|
||||||
assert_eq!(hints.len(), 0);
|
|
||||||
|
|
||||||
return success(Univariant {
|
return success(Univariant {
|
||||||
variant: Struct::new(dl, &vec![],
|
variant: Struct::new(dl, &vec![],
|
||||||
&hints[..], StructKind::AlwaysSizedUnivariant, ty)?,
|
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
|
||||||
non_zero: false
|
non_zero: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1219,7 +1195,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
|
|
||||||
// FIXME: should handle i128? signed-value based impl is weird and hard to
|
// FIXME: should handle i128? signed-value based impl is weird and hard to
|
||||||
// grok.
|
// grok.
|
||||||
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
|
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr,
|
||||||
min,
|
min,
|
||||||
max);
|
max);
|
||||||
return success(CEnum {
|
return success(CEnum {
|
||||||
|
@ -1232,7 +1208,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !def.is_enum() || def.variants.len() == 1 && hints.is_empty() {
|
if !def.is_enum() || def.variants.len() == 1 {
|
||||||
// Struct, or union, or univariant enum equivalent to a struct.
|
// Struct, or union, or univariant enum equivalent to a struct.
|
||||||
// (Typechecking will reject discriminant-sizing attrs.)
|
// (Typechecking will reject discriminant-sizing attrs.)
|
||||||
|
|
||||||
|
@ -1259,7 +1235,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
|
un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
|
||||||
UntaggedUnion { variants: un }
|
UntaggedUnion { variants: un }
|
||||||
} else {
|
} else {
|
||||||
let st = Struct::new(dl, &fields, &hints[..],
|
let st = Struct::new(dl, &fields, &def.repr,
|
||||||
kind, ty)?;
|
kind, ty)?;
|
||||||
let non_zero = Some(def.did) == tcx.lang_items.non_zero();
|
let non_zero = Some(def.did) == tcx.lang_items.non_zero();
|
||||||
Univariant { variant: st, non_zero: non_zero }
|
Univariant { variant: st, non_zero: non_zero }
|
||||||
|
@ -1282,7 +1258,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
|
v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
if variants.len() == 2 && hints.is_empty() {
|
if variants.len() == 2 && !def.repr.c {
|
||||||
// Nullable pointer optimization
|
// Nullable pointer optimization
|
||||||
for discr in 0..2 {
|
for discr in 0..2 {
|
||||||
let other_fields = variants[1 - discr].iter().map(|ty| {
|
let other_fields = variants[1 - discr].iter().map(|ty| {
|
||||||
|
@ -1315,7 +1291,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
let st = Struct::new(dl,
|
let st = Struct::new(dl,
|
||||||
&variants[discr].iter().map(|ty| ty.layout(infcx))
|
&variants[discr].iter().map(|ty| ty.layout(infcx))
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
&hints[..], StructKind::AlwaysSizedUnivariant, ty)?;
|
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
|
||||||
|
|
||||||
// We have to fix the last element of path here.
|
// We have to fix the last element of path here.
|
||||||
let mut i = *path.last().unwrap();
|
let mut i = *path.last().unwrap();
|
||||||
|
@ -1338,7 +1314,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
// The general case.
|
// The general case.
|
||||||
let discr_max = (variants.len() - 1) as i64;
|
let discr_max = (variants.len() - 1) as i64;
|
||||||
assert!(discr_max >= 0);
|
assert!(discr_max >= 0);
|
||||||
let (min_ity, _) = Integer::repr_discr(tcx, ty, &hints[..], 0, discr_max);
|
let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
|
||||||
|
|
||||||
let mut align = dl.aggregate_align;
|
let mut align = dl.aggregate_align;
|
||||||
let mut size = Size::from_bytes(0);
|
let mut size = Size::from_bytes(0);
|
||||||
|
@ -1356,7 +1332,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
fields.insert(0, &discr);
|
fields.insert(0, &discr);
|
||||||
let st = Struct::new(dl,
|
let st = Struct::new(dl,
|
||||||
&fields,
|
&fields,
|
||||||
&hints[..], StructKind::EnumVariant, ty)?;
|
&def.repr, StructKind::EnumVariant, ty)?;
|
||||||
// Find the first field we can't move later
|
// Find the first field we can't move later
|
||||||
// to make room for a larger discriminant.
|
// to make room for a larger discriminant.
|
||||||
// It is important to skip the first field.
|
// It is important to skip the first field.
|
||||||
|
|
|
@ -1327,7 +1327,8 @@ pub struct AdtDef {
|
||||||
pub did: DefId,
|
pub did: DefId,
|
||||||
pub variants: Vec<VariantDef>,
|
pub variants: Vec<VariantDef>,
|
||||||
destructor: Cell<Option<DefId>>,
|
destructor: Cell<Option<DefId>>,
|
||||||
flags: Cell<AdtFlags>
|
flags: Cell<AdtFlags>,
|
||||||
|
pub repr: ReprOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for AdtDef {
|
impl PartialEq for AdtDef {
|
||||||
|
@ -1356,11 +1357,38 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum AdtKind { Struct, Union, Enum }
|
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<attr::IntType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
impl<'a, 'gcx, 'tcx> AdtDef {
|
||||||
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
did: DefId,
|
did: DefId,
|
||||||
kind: AdtKind,
|
kind: AdtKind,
|
||||||
variants: Vec<VariantDef>) -> Self {
|
variants: Vec<VariantDef>,
|
||||||
|
repr: ReprOptions) -> Self {
|
||||||
let mut flags = AdtFlags::NO_ADT_FLAGS;
|
let mut flags = AdtFlags::NO_ADT_FLAGS;
|
||||||
let attrs = tcx.get_attrs(did);
|
let attrs = tcx.get_attrs(did);
|
||||||
if attr::contains_name(&attrs, "fundamental") {
|
if attr::contains_name(&attrs, "fundamental") {
|
||||||
|
@ -1385,6 +1413,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||||
variants: variants,
|
variants: variants,
|
||||||
flags: Cell::new(flags),
|
flags: Cell::new(flags),
|
||||||
destructor: Cell::new(None),
|
destructor: Cell::new(None),
|
||||||
|
repr: repr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -425,8 +425,8 @@ impl<'tcx> EntryKind<'tcx> {
|
||||||
EntryKind::ForeignImmStatic => Def::Static(did, false),
|
EntryKind::ForeignImmStatic => Def::Static(did, false),
|
||||||
EntryKind::MutStatic |
|
EntryKind::MutStatic |
|
||||||
EntryKind::ForeignMutStatic => Def::Static(did, true),
|
EntryKind::ForeignMutStatic => Def::Static(did, true),
|
||||||
EntryKind::Struct(_) => Def::Struct(did),
|
EntryKind::Struct(_, _) => Def::Struct(did),
|
||||||
EntryKind::Union(_) => Def::Union(did),
|
EntryKind::Union(_, _) => Def::Union(did),
|
||||||
EntryKind::Fn(_) |
|
EntryKind::Fn(_) |
|
||||||
EntryKind::ForeignFn(_) => Def::Fn(did),
|
EntryKind::ForeignFn(_) => Def::Fn(did),
|
||||||
EntryKind::Method(_) => Def::Method(did),
|
EntryKind::Method(_) => Def::Method(did),
|
||||||
|
@ -435,7 +435,7 @@ impl<'tcx> EntryKind<'tcx> {
|
||||||
EntryKind::Mod(_) => Def::Mod(did),
|
EntryKind::Mod(_) => Def::Mod(did),
|
||||||
EntryKind::Variant(_) => Def::Variant(did),
|
EntryKind::Variant(_) => Def::Variant(did),
|
||||||
EntryKind::Trait(_) => Def::Trait(did),
|
EntryKind::Trait(_) => Def::Trait(did),
|
||||||
EntryKind::Enum => Def::Enum(did),
|
EntryKind::Enum(_) => Def::Enum(did),
|
||||||
EntryKind::MacroDef(_) => Def::Macro(did),
|
EntryKind::MacroDef(_) => Def::Macro(did),
|
||||||
|
|
||||||
EntryKind::ForeignMod |
|
EntryKind::ForeignMod |
|
||||||
|
@ -519,8 +519,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
-> (ty::VariantDef, Option<DefIndex>) {
|
-> (ty::VariantDef, Option<DefIndex>) {
|
||||||
let data = match item.kind {
|
let data = match item.kind {
|
||||||
EntryKind::Variant(data) |
|
EntryKind::Variant(data) |
|
||||||
EntryKind::Struct(data) |
|
EntryKind::Struct(data, _) |
|
||||||
EntryKind::Union(data) => data.decode(self),
|
EntryKind::Union(data, _) => data.decode(self),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
let item = self.entry(item_id);
|
let item = self.entry(item_id);
|
||||||
let did = self.local_def_id(item_id);
|
let did = self.local_def_id(item_id);
|
||||||
let mut ctor_index = None;
|
let mut ctor_index = None;
|
||||||
let variants = if let EntryKind::Enum = item.kind {
|
let variants = if let EntryKind::Enum(_) = item.kind {
|
||||||
item.children
|
item.children
|
||||||
.decode(self)
|
.decode(self)
|
||||||
.map(|index| {
|
.map(|index| {
|
||||||
|
@ -561,14 +561,14 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
ctor_index = struct_ctor;
|
ctor_index = struct_ctor;
|
||||||
vec![variant]
|
vec![variant]
|
||||||
};
|
};
|
||||||
let kind = match item.kind {
|
let (kind, repr) = match item.kind {
|
||||||
EntryKind::Enum => ty::AdtKind::Enum,
|
EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
|
||||||
EntryKind::Struct(_) => ty::AdtKind::Struct,
|
EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
|
||||||
EntryKind::Union(_) => ty::AdtKind::Union,
|
EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
|
||||||
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
|
_ => 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 {
|
if let Some(ctor_index) = ctor_index {
|
||||||
// Make adt definition available through constructor id as well.
|
// Make adt definition available through constructor id as well.
|
||||||
tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt);
|
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 {
|
pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
|
||||||
match self.entry(node_id).kind {
|
match self.entry(node_id).kind {
|
||||||
EntryKind::Struct(data) |
|
EntryKind::Struct(data, _) |
|
||||||
EntryKind::Union(data) |
|
EntryKind::Union(data, _) |
|
||||||
EntryKind::Variant(data) => data.decode(self).ctor_kind,
|
EntryKind::Variant(data) => data.decode(self).ctor_kind,
|
||||||
_ => CtorKind::Fictive,
|
_ => CtorKind::Fictive,
|
||||||
}
|
}
|
||||||
|
@ -890,7 +890,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
|
|
||||||
pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
|
pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
|
||||||
match self.entry(node_id).kind {
|
match self.entry(node_id).kind {
|
||||||
EntryKind::Struct(data) => {
|
EntryKind::Struct(data, _) => {
|
||||||
data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
|
data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -20,7 +20,7 @@ use rustc::middle::dependency_format::Linkage;
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::traits::specialization_graph;
|
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::session::config::{self, CrateTypeProcMacro};
|
||||||
use rustc::util::nodemap::{FxHashMap, NodeSet};
|
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 {
|
Entry {
|
||||||
kind: EntryKind::Struct(self.lazy(&data)),
|
kind: EntryKind::Struct(self.lazy(&data), repr_options),
|
||||||
visibility: self.lazy(&ctor_vis),
|
visibility: self.lazy(&ctor_vis),
|
||||||
span: self.lazy(&tcx.def_span(def_id)),
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
attributes: LazySeq::empty(),
|
attributes: LazySeq::empty(),
|
||||||
|
@ -659,7 +661,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
|
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
|
||||||
hir::ItemTy(..) => EntryKind::Type,
|
hir::ItemTy(..) => EntryKind::Type,
|
||||||
hir::ItemEnum(..) => EntryKind::Enum,
|
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
|
||||||
hir::ItemStruct(ref struct_def, _) => {
|
hir::ItemStruct(ref struct_def, _) => {
|
||||||
let variant = tcx.lookup_adt_def(def_id).struct_variant();
|
let variant = tcx.lookup_adt_def(def_id).struct_variant();
|
||||||
|
|
||||||
|
@ -671,20 +673,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let repr_options = get_repr_options(&tcx, def_id);
|
||||||
|
|
||||||
EntryKind::Struct(self.lazy(&VariantData {
|
EntryKind::Struct(self.lazy(&VariantData {
|
||||||
ctor_kind: variant.ctor_kind,
|
ctor_kind: variant.ctor_kind,
|
||||||
disr: variant.disr_val.to_u128_unchecked(),
|
disr: variant.disr_val.to_u128_unchecked(),
|
||||||
struct_ctor: struct_ctor,
|
struct_ctor: struct_ctor,
|
||||||
}))
|
}), repr_options)
|
||||||
}
|
}
|
||||||
hir::ItemUnion(..) => {
|
hir::ItemUnion(..) => {
|
||||||
let variant = tcx.lookup_adt_def(def_id).struct_variant();
|
let variant = tcx.lookup_adt_def(def_id).struct_variant();
|
||||||
|
let repr_options = get_repr_options(&tcx, def_id);
|
||||||
|
|
||||||
EntryKind::Union(self.lazy(&VariantData {
|
EntryKind::Union(self.lazy(&VariantData {
|
||||||
ctor_kind: variant.ctor_kind,
|
ctor_kind: variant.ctor_kind,
|
||||||
disr: variant.disr_val.to_u128_unchecked(),
|
disr: variant.disr_val.to_u128_unchecked(),
|
||||||
struct_ctor: None,
|
struct_ctor: None,
|
||||||
}))
|
}), repr_options)
|
||||||
}
|
}
|
||||||
hir::ItemDefaultImpl(..) => {
|
hir::ItemDefaultImpl(..) => {
|
||||||
let data = ImplData {
|
let data = ImplData {
|
||||||
|
@ -1419,3 +1425,11 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
result
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
|
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty, ReprOptions};
|
||||||
use rustc_back::PanicStrategy;
|
use rustc_back::PanicStrategy;
|
||||||
|
|
||||||
use rustc_serialize as serialize;
|
use rustc_serialize as serialize;
|
||||||
|
@ -228,11 +228,11 @@ pub enum EntryKind<'tcx> {
|
||||||
ForeignMutStatic,
|
ForeignMutStatic,
|
||||||
ForeignMod,
|
ForeignMod,
|
||||||
Type,
|
Type,
|
||||||
Enum,
|
Enum(ReprOptions),
|
||||||
Field,
|
Field,
|
||||||
Variant(Lazy<VariantData>),
|
Variant(Lazy<VariantData>),
|
||||||
Struct(Lazy<VariantData>),
|
Struct(Lazy<VariantData>, ReprOptions),
|
||||||
Union(Lazy<VariantData>),
|
Union(Lazy<VariantData>, ReprOptions),
|
||||||
Fn(Lazy<FnData>),
|
Fn(Lazy<FnData>),
|
||||||
ForeignFn(Lazy<FnData>),
|
ForeignFn(Lazy<FnData>),
|
||||||
Mod(Lazy<ModData>),
|
Mod(Lazy<ModData>),
|
||||||
|
|
|
@ -65,7 +65,7 @@ use middle::const_val::ConstVal;
|
||||||
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||||
use rustc_const_eval::{ConstContext, report_const_eval_err};
|
use rustc_const_eval::{ConstContext, report_const_eval_err};
|
||||||
use rustc::ty::subst::Substs;
|
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::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
|
||||||
use rustc::ty::util::IntTypeExt;
|
use rustc::ty::util::IntTypeExt;
|
||||||
use rustc::dep_graph::DepNode;
|
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 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,
|
let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
|
||||||
ConstInt::Infer(0), def)];
|
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 {
|
if let Some(ctor_id) = ctor_id {
|
||||||
// Make adt definition available through constructor id as well.
|
// Make adt definition available through constructor id as well.
|
||||||
ccx.tcx.adt_defs.borrow_mut().insert(ctor_id, adt);
|
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 did = ccx.tcx.hir.local_def_id(it.id);
|
||||||
let variants = vec![convert_struct_variant(ccx, did, it.name, ConstInt::Infer(0), def)];
|
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);
|
ccx.tcx.adt_defs.borrow_mut().insert(did, adt);
|
||||||
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)
|
convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data)
|
||||||
}).collect();
|
}).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);
|
tcx.adt_defs.borrow_mut().insert(did, adt);
|
||||||
adt
|
adt
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue