use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span};
-use rustc_target::abi::{Align, VariantIdx};
+use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
+pub use rustc_target::abi::{ReprFlags, ReprOptions};
pub use subst::*;
pub use vtable::*;
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
- Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+ Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
/// A small map keeping true kinds of built-in macros that appear to be fn-like on
/// the surface (`macro` items in libcore), but are actually attributes or derives.
pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
+ /// List functions and methods for which lifetime elision was successful.
+ pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
}
#[derive(Clone, Copy, Debug)]
self.map_id(|id| id.expect_local())
}
- // Returns `true` if this item is visible anywhere in the local crate.
+ /// Returns `true` if this item is visible anywhere in the local crate.
pub fn is_visible_locally(self) -> bool {
match self {
Visibility::Public => true,
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
pub fn has_name(&self) -> bool {
- self.name != kw::UnderscoreLifetime
+ self.name != kw::UnderscoreLifetime && self.name != kw::Empty
}
}
let kind = self
.kind()
.map_bound(|kind| match kind {
- PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => {
- Some(PredicateKind::Trait(TraitPredicate {
- trait_ref,
- constness,
- polarity: polarity.flip()?,
- }))
- }
+ PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ trait_ref,
+ constness,
+ polarity,
+ })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ trait_ref,
+ constness,
+ polarity: polarity.flip()?,
+ }))),
_ => None,
})
}
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
- if let PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) = self.kind().skip_binder()
+ if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
&& constness != BoundConstness::NotConst
{
- self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Trait(TraitPredicate {
+ self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate {
trait_ref,
constness: BoundConstness::NotConst,
polarity,
- })));
+ }))));
}
self
}
pub fn allow_normalization(self) -> bool {
match self.kind().skip_binder() {
PredicateKind::WellFormed(_) => false,
- PredicateKind::Trait(_)
- | PredicateKind::RegionOutlives(_)
- | PredicateKind::TypeOutlives(_)
- | PredicateKind::Projection(_)
+ PredicateKind::Clause(Clause::Trait(_))
+ | PredicateKind::Clause(Clause::RegionOutlives(_))
+ | PredicateKind::Clause(Clause::TypeOutlives(_))
+ | PredicateKind::Clause(Clause::Projection(_))
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
| PredicateKind::Coerce(_)
| PredicateKind::ConstEvaluatable(_)
| PredicateKind::ConstEquate(_, _)
+ | PredicateKind::Ambiguous
| PredicateKind::TypeWellFormedFromEnv(_) => true,
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum PredicateKind<'tcx> {
+/// A clause is something that can appear in where bounds or be inferred
+/// by implied bounds.
+pub enum Clause<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
/// `where <T as TraitRef>::Name == X`, approximately.
/// See the `ProjectionPredicate` struct for details.
Projection(ProjectionPredicate<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum PredicateKind<'tcx> {
+ /// Prove a clause
+ Clause(Clause<'tcx>),
/// No syntax: `T` well-formed.
WellFormed(GenericArg<'tcx>),
///
/// Only used for Chalk.
TypeWellFormedFromEnv(Ty<'tcx>),
+
+ /// A marker predicate that is always ambiguous.
+ /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
+ Ambiguous,
}
/// The crate outlives map is computed during typeck and contains the
}
}
+/// `A: B`
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B`
+pub struct OutlivesPredicate<A, B>(pub A, pub B);
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
}
}
+impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
+ pred.to_predicate(tcx)
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
+ self.map_bound(|trait_ref| TraitPredicate {
+ trait_ref,
+ constness: ty::BoundConstness::NotConst,
+ polarity: ty::ImplPolarity::Positive,
+ })
+ }
+}
+
impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateKind::Trait).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(PredicateKind::Projection).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
}
}
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Trait(t) => Some(predicate.rebind(t)),
- PredicateKind::Projection(..)
+ PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
+ PredicateKind::Clause(Clause::Projection(..))
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::RegionOutlives(..)
+ | PredicateKind::Clause(Clause::RegionOutlives(..))
| PredicateKind::WellFormed(..)
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::TypeOutlives(..)
+ | PredicateKind::Clause(Clause::TypeOutlives(..))
| PredicateKind::ConstEvaluatable(..)
| PredicateKind::ConstEquate(..)
+ | PredicateKind::Ambiguous
| PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Projection(t) => Some(predicate.rebind(t)),
- PredicateKind::Trait(..)
+ PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
+ PredicateKind::Clause(Clause::Trait(..))
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::RegionOutlives(..)
+ | PredicateKind::Clause(Clause::RegionOutlives(..))
| PredicateKind::WellFormed(..)
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::TypeOutlives(..)
+ | PredicateKind::Clause(Clause::TypeOutlives(..))
| PredicateKind::ConstEvaluatable(..)
| PredicateKind::ConstEquate(..)
+ | PredicateKind::Ambiguous
| PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::TypeOutlives(data) => Some(predicate.rebind(data)),
- PredicateKind::Trait(..)
- | PredicateKind::Projection(..)
+ PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
+ PredicateKind::Clause(Clause::Trait(..))
+ | PredicateKind::Clause(Clause::Projection(..))
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::RegionOutlives(..)
+ | PredicateKind::Clause(Clause::RegionOutlives(..))
| PredicateKind::WellFormed(..)
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::ConstEvaluatable(..)
| PredicateKind::ConstEquate(..)
+ | PredicateKind::Ambiguous
| PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
}
ParamEnv::new(
- tcx.normalize_opaque_types(self.caller_bounds()),
+ tcx.reveal_opaque_types_in_bounds(self.caller_bounds()),
Reveal::All,
self.constness(),
)
pub def_id: DefId,
/// `DefId` that identifies the variant's constructor.
/// If this variant is a struct variant, then this is `None`.
- pub ctor_def_id: Option<DefId>,
+ pub ctor: Option<(CtorKind, DefId)>,
/// Variant or struct name.
pub name: Symbol,
/// Discriminant of this variant.
pub discr: VariantDiscr,
/// Fields of this variant.
pub fields: Vec<FieldDef>,
- /// Type of constructor of variant.
- pub ctor_kind: CtorKind,
/// Flags of the variant (e.g. is field list non-exhaustive)?
flags: VariantFlags,
}
pub fn new(
name: Symbol,
variant_did: Option<DefId>,
- ctor_def_id: Option<DefId>,
+ ctor: Option<(CtorKind, DefId)>,
discr: VariantDiscr,
fields: Vec<FieldDef>,
- ctor_kind: CtorKind,
adt_kind: AdtKind,
parent_did: DefId,
recovered: bool,
is_field_list_non_exhaustive: bool,
) -> Self {
debug!(
- "VariantDef::new(name = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?},
- fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})",
- name, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did,
+ "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
+ fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
+ name, variant_did, ctor, discr, fields, adt_kind, parent_did,
);
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
flags |= VariantFlags::IS_RECOVERED;
}
- VariantDef {
- def_id: variant_did.unwrap_or(parent_did),
- ctor_def_id,
- name,
- discr,
- fields,
- ctor_kind,
- flags,
- }
+ VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
}
/// Is this field list non-exhaustive?
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
}
+
+ #[inline]
+ pub fn ctor_kind(&self) -> Option<CtorKind> {
+ self.ctor.map(|(kind, _)| kind)
+ }
+
+ #[inline]
+ pub fn ctor_def_id(&self) -> Option<DefId> {
+ self.ctor.map(|(_, def_id)| def_id)
+ }
}
impl PartialEq for VariantDef {
// definition of `VariantDef` changes, a compile-error will be produced,
// reminding us to revisit this assumption.
- let Self {
- def_id: lhs_def_id,
- ctor_def_id: _,
- name: _,
- discr: _,
- fields: _,
- ctor_kind: _,
- flags: _,
- } = &self;
-
- let Self {
- def_id: rhs_def_id,
- ctor_def_id: _,
- name: _,
- discr: _,
- fields: _,
- ctor_kind: _,
- flags: _,
- } = other;
-
+ let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
+ let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
lhs_def_id == rhs_def_id
}
}
// of `VariantDef` changes, a compile-error will be produced, reminding
// us to revisit this assumption.
- let Self { def_id, ctor_def_id: _, name: _, discr: _, fields: _, ctor_kind: _, flags: _ } =
- &self;
-
+ let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
def_id.hash(s)
}
}
}
}
-bitflags! {
- #[derive(TyEncodable, TyDecodable, Default, HashStable)]
- pub struct ReprFlags: u8 {
- const IS_C = 1 << 0;
- const IS_SIMD = 1 << 1;
- const IS_TRANSPARENT = 1 << 2;
- // Internal only for now. If true, don't reorder fields.
- const IS_LINEAR = 1 << 3;
- // If true, the type's layout can be randomized using
- // the seed stored in `ReprOptions.layout_seed`
- const RANDOMIZE_LAYOUT = 1 << 4;
- // Any of these flags being set prevent field reordering optimisation.
- const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits
- | ReprFlags::IS_SIMD.bits
- | ReprFlags::IS_LINEAR.bits;
- }
-}
-
-/// Represents the repr options provided by the user,
-#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)]
-pub struct ReprOptions {
- pub int: Option<attr::IntType>,
- pub align: Option<Align>,
- pub pack: Option<Align>,
- pub flags: ReprFlags,
- /// The seed to be used for randomizing a type's layout
- ///
- /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
- /// be the "most accurate" hash as it'd encompass the item and crate
- /// hash without loss, but it does pay the price of being larger.
- /// Everything's a tradeoff, a `u64` seed should be sufficient for our
- /// purposes (primarily `-Z randomize-layout`)
- pub field_shuffle_seed: u64,
-}
-
-impl ReprOptions {
- pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
- let mut flags = ReprFlags::empty();
- let mut size = None;
- let mut max_align: Option<Align> = None;
- let mut min_pack: Option<Align> = None;
-
- // Generate a deterministically-derived seed from the item's path hash
- // to allow for cross-crate compilation to actually work
- let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
-
- // If the user defined a custom seed for layout randomization, xor the item's
- // path hash with the user defined seed, this will allowing determinism while
- // still allowing users to further randomize layout generation for e.g. fuzzing
- if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed {
- field_shuffle_seed ^= user_seed;
- }
-
- for attr in tcx.get_attrs(did, sym::repr) {
- for r in attr::parse_repr_attr(&tcx.sess, attr) {
- flags.insert(match r {
- attr::ReprC => ReprFlags::IS_C,
- attr::ReprPacked(pack) => {
- let pack = Align::from_bytes(pack as u64).unwrap();
- min_pack = Some(if let Some(min_pack) = min_pack {
- min_pack.min(pack)
- } else {
- pack
- });
- ReprFlags::empty()
- }
- attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
- attr::ReprSimd => ReprFlags::IS_SIMD,
- attr::ReprInt(i) => {
- size = Some(i);
- ReprFlags::empty()
- }
- attr::ReprAlign(align) => {
- max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
- ReprFlags::empty()
- }
- });
- }
- }
-
- // If `-Z randomize-layout` was enabled for the type definition then we can
- // consider performing layout randomization
- if tcx.sess.opts.unstable_opts.randomize_layout {
- flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
- }
-
- // This is here instead of layout because the choice must make it into metadata.
- if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
- flags.insert(ReprFlags::IS_LINEAR);
- }
-
- Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
- }
-
- #[inline]
- pub fn simd(&self) -> bool {
- self.flags.contains(ReprFlags::IS_SIMD)
- }
-
- #[inline]
- pub fn c(&self) -> bool {
- self.flags.contains(ReprFlags::IS_C)
- }
-
- #[inline]
- pub fn packed(&self) -> bool {
- self.pack.is_some()
- }
-
- #[inline]
- pub fn transparent(&self) -> bool {
- self.flags.contains(ReprFlags::IS_TRANSPARENT)
- }
-
- #[inline]
- pub fn linear(&self) -> bool {
- self.flags.contains(ReprFlags::IS_LINEAR)
- }
-
- /// Returns the discriminant type, given these `repr` options.
- /// This must only be called on enums!
- pub fn discr_type(&self) -> attr::IntType {
- self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
- }
-
- /// Returns `true` if this `#[repr()]` should inhabit "smart enum
- /// layout" optimizations, such as representing `Foo<&T>` as a
- /// single pointer.
- pub fn inhibit_enum_layout_opt(&self) -> bool {
- self.c() || self.int.is_some()
- }
-
- /// Returns `true` if this `#[repr()]` should inhibit struct field reordering
- /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`.
- pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
- if let Some(pack) = self.pack {
- if pack.bytes() == 1 {
- return true;
- }
- }
-
- self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
- }
-
- /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
- /// was enabled for its declaration crate
- pub fn can_randomize_type_layout(&self) -> bool {
- !self.inhibit_struct_field_reordering_opt()
- && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
- }
-
- /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
- pub fn inhibit_union_abi_opt(&self) -> bool {
- self.c()
- }
-}
-
impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
/// typically obtained via the second field of [`TyKind::Adt`].
.filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
}
+ pub fn repr_options_of_def(self, did: DefId) -> ReprOptions {
+ let mut flags = ReprFlags::empty();
+ let mut size = None;
+ let mut max_align: Option<Align> = None;
+ let mut min_pack: Option<Align> = None;
+
+ // Generate a deterministically-derived seed from the item's path hash
+ // to allow for cross-crate compilation to actually work
+ let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash();
+
+ // If the user defined a custom seed for layout randomization, xor the item's
+ // path hash with the user defined seed, this will allowing determinism while
+ // still allowing users to further randomize layout generation for e.g. fuzzing
+ if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed {
+ field_shuffle_seed ^= user_seed;
+ }
+
+ for attr in self.get_attrs(did, sym::repr) {
+ for r in attr::parse_repr_attr(&self.sess, attr) {
+ flags.insert(match r {
+ attr::ReprC => ReprFlags::IS_C,
+ attr::ReprPacked(pack) => {
+ let pack = Align::from_bytes(pack as u64).unwrap();
+ min_pack = Some(if let Some(min_pack) = min_pack {
+ min_pack.min(pack)
+ } else {
+ pack
+ });
+ ReprFlags::empty()
+ }
+ attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
+ attr::ReprSimd => ReprFlags::IS_SIMD,
+ attr::ReprInt(i) => {
+ size = Some(match i {
+ attr::IntType::SignedInt(x) => match x {
+ ast::IntTy::Isize => IntegerType::Pointer(true),
+ ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true),
+ ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true),
+ ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true),
+ ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true),
+ ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true),
+ },
+ attr::IntType::UnsignedInt(x) => match x {
+ ast::UintTy::Usize => IntegerType::Pointer(false),
+ ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false),
+ ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false),
+ ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false),
+ ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false),
+ ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false),
+ },
+ });
+ ReprFlags::empty()
+ }
+ attr::ReprAlign(align) => {
+ max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
+ ReprFlags::empty()
+ }
+ });
+ }
+ }
+
+ // If `-Z randomize-layout` was enabled for the type definition then we can
+ // consider performing layout randomization
+ if self.sess.opts.unstable_opts.randomize_layout {
+ flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
+ }
+
+ // This is here instead of layout because the choice must make it into metadata.
+ if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) {
+ flags.insert(ReprFlags::IS_LINEAR);
+ }
+
+ ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
+ }
+
/// Look up the name of a definition across crates. This does not look at HIR.
pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
if let Some(cnum) = def_id.as_crate_root() {