1
Fork 0

Auto merge of #94733 - nnethercote:fix-AdtDef-interning, r=fee1-dead

Improve `AdtDef` interning.

This commit makes `AdtDef` use `Interned`. Much of the commit is tedious
changes to introduce getter functions. The interesting changes are in
`compiler/rustc_middle/src/ty/adt.rs`.

r? `@fee1-dead`
This commit is contained in:
bors 2022-03-12 07:02:05 +00:00
commit 012720ffb0
169 changed files with 702 additions and 687 deletions

View file

@ -9,7 +9,7 @@ macro_rules! arena_types {
[] layout: rustc_target::abi::LayoutS<'tcx>,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
[decode] adt_def: rustc_middle::ty::AdtDef,
[decode] adt_def: rustc_middle::ty::AdtDefData,
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>,
[] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>,
[decode] mir: rustc_middle::mir::Body<'tcx>,

View file

@ -2455,7 +2455,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => {
ty::tls::with(|tcx| {
let variant_def = &tcx.adt_def(adt_did).variants[variant];
let variant_def = &tcx.adt_def(adt_did).variant(variant);
let substs = tcx.lift(substs).expect("could not lift for printing");
let name = FmtPrinter::new(tcx, Namespace::ValueNS)
.print_def_path(variant_def.def_id, substs)?
@ -2783,7 +2783,7 @@ impl<'tcx> UserTypeProjections {
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
}
pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Field) -> Self {
pub fn variant(self, adt_def: AdtDef<'tcx>, variant_index: VariantIdx, field: Field) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
}
}
@ -2834,12 +2834,12 @@ impl UserTypeProjection {
pub(crate) fn variant(
mut self,
adt_def: &AdtDef,
adt_def: AdtDef<'_>,
variant_index: VariantIdx,
field: Field,
) -> Self {
self.projs.push(ProjectionElem::Downcast(
Some(adt_def.variants[variant_index].name),
Some(adt_def.variant(variant_index).name),
variant_index,
));
self.projs.push(ProjectionElem::Field(field, ()));

View file

@ -40,7 +40,7 @@ impl<'tcx> PlaceTy<'tcx> {
None => adt_def.non_enum_variant(),
Some(variant_index) => {
assert!(adt_def.is_enum());
&adt_def.variants[variant_index]
&adt_def.variant(variant_index)
}
};
let field_def = &variant_def.fields[f.index()];

View file

@ -523,7 +523,7 @@ rustc_queries! {
storage(ArenaCacheSelector<'tcx>)
separate_provide_extern
}
query adt_def(key: DefId) -> &'tcx ty::AdtDef {
query adt_def(key: DefId) -> ty::AdtDef<'tcx> {
desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern

View file

@ -128,7 +128,7 @@ pub struct Block {
#[derive(Debug, HashStable)]
pub struct Adt<'tcx> {
/// The ADT we're constructing.
pub adt_def: &'tcx AdtDef,
pub adt_def: AdtDef<'tcx>,
/// The variant of the ADT.
pub variant_index: VariantIdx,
pub substs: SubstsRef<'tcx>,
@ -617,7 +617,7 @@ pub enum PatKind<'tcx> {
/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
/// multiple variants.
Variant {
adt_def: &'tcx AdtDef,
adt_def: AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
variant_index: VariantIdx,
subpatterns: Vec<FieldPat<'tcx>>,
@ -714,7 +714,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
let variant = match *self.kind {
PatKind::Variant { adt_def, variant_index, .. } => {
Some(&adt_def.variants[variant_index])
Some(adt_def.variant(variant_index))
}
_ => self.ty.ty_adt_def().and_then(|adt| {
if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }

View file

@ -75,7 +75,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
type InternedVariances = Vec<chalk_ir::Variance>;
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
type DefId = DefId;
type InternedAdtId = &'tcx AdtDef;
type InternedAdtId = AdtDef<'tcx>;
type Identifier = ();
type FnAbi = Abi;

View file

@ -4,6 +4,7 @@ use crate::ty::util::{Discr, IntTypeExt};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::HashingControls;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
@ -89,62 +90,62 @@ bitflags! {
/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId`
/// can be used with [`TyCtxt::type_of()`] to get the type of the field.
#[derive(TyEncodable, TyDecodable)]
pub struct AdtDef {
pub struct AdtDefData {
/// The `DefId` of the struct, enum or union item.
pub did: DefId,
/// Variants of the ADT. If this is a struct or union, then there will be a single variant.
pub variants: IndexVec<VariantIdx, VariantDef>,
variants: IndexVec<VariantIdx, VariantDef>,
/// Flags of the ADT (e.g., is this a struct? is this non-exhaustive?).
flags: AdtFlags,
/// Repr options provided by the user.
pub repr: ReprOptions,
repr: ReprOptions,
}
impl PartialOrd for AdtDef {
fn partial_cmp(&self, other: &AdtDef) -> Option<Ordering> {
impl PartialOrd for AdtDefData {
fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `Ord` only based on `did`.
impl Ord for AdtDef {
fn cmp(&self, other: &AdtDef) -> Ordering {
impl Ord for AdtDefData {
fn cmp(&self, other: &AdtDefData) -> Ordering {
self.did.cmp(&other.did)
}
}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `PartialEq` only based on `did`.
impl PartialEq for AdtDef {
impl PartialEq for AdtDefData {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.did == other.did
}
}
impl Eq for AdtDef {}
impl Eq for AdtDefData {}
/// There should be only one AdtDef for each `did`, therefore
/// it is fine to implement `Hash` only based on `did`.
impl Hash for AdtDef {
impl Hash for AdtDefData {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
self.did.hash(s)
}
}
impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
thread_local! {
static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default();
}
let hash: Fingerprint = CACHE.with(|cache| {
let addr = self as *const AdtDef as usize;
let addr = self as *const AdtDefData as usize;
let hashing_controls = hcx.hashing_controls();
*cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| {
let ty::AdtDef { did, ref variants, ref flags, ref repr } = *self;
let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self;
let mut hasher = StableHasher::new();
did.hash_stable(hcx, &mut hasher);
@ -160,6 +161,32 @@ impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
#[cfg_attr(not(bootstrap), rustc_pass_by_value)]
pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>);
impl<'tcx> AdtDef<'tcx> {
pub fn did(self) -> DefId {
self.0.0.did
}
pub fn variants(self) -> &'tcx IndexVec<VariantIdx, VariantDef> {
&self.0.0.variants
}
pub fn variant(self, idx: VariantIdx) -> &'tcx VariantDef {
&self.0.0.variants[idx]
}
pub fn flags(self) -> AdtFlags {
self.0.0.flags
}
pub fn repr(self) -> ReprOptions {
self.0.0.repr
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,
@ -177,8 +204,8 @@ impl Into<DataTypeKind> for AdtKind {
}
}
impl<'tcx> AdtDef {
/// Creates a new `AdtDef`.
impl AdtDefData {
/// Creates a new `AdtDefData`.
pub(super) fn new(
tcx: TyCtxt<'_>,
did: DefId,
@ -218,36 +245,38 @@ impl<'tcx> AdtDef {
flags |= AdtFlags::IS_MANUALLY_DROP;
}
AdtDef { did, variants, flags, repr }
AdtDefData { did, variants, flags, repr }
}
}
impl<'tcx> AdtDef<'tcx> {
/// Returns `true` if this is a struct.
#[inline]
pub fn is_struct(&self) -> bool {
self.flags.contains(AdtFlags::IS_STRUCT)
pub fn is_struct(self) -> bool {
self.flags().contains(AdtFlags::IS_STRUCT)
}
/// Returns `true` if this is a union.
#[inline]
pub fn is_union(&self) -> bool {
self.flags.contains(AdtFlags::IS_UNION)
pub fn is_union(self) -> bool {
self.flags().contains(AdtFlags::IS_UNION)
}
/// Returns `true` if this is an enum.
#[inline]
pub fn is_enum(&self) -> bool {
self.flags.contains(AdtFlags::IS_ENUM)
pub fn is_enum(self) -> bool {
self.flags().contains(AdtFlags::IS_ENUM)
}
/// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`.
#[inline]
pub fn is_variant_list_non_exhaustive(&self) -> bool {
self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
pub fn is_variant_list_non_exhaustive(self) -> bool {
self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}
/// Returns the kind of the ADT.
#[inline]
pub fn adt_kind(&self) -> AdtKind {
pub fn adt_kind(self) -> AdtKind {
if self.is_enum() {
AdtKind::Enum
} else if self.is_union() {
@ -258,7 +287,7 @@ impl<'tcx> AdtDef {
}
/// Returns a description of this abstract data type.
pub fn descr(&self) -> &'static str {
pub fn descr(self) -> &'static str {
match self.adt_kind() {
AdtKind::Struct => "struct",
AdtKind::Union => "union",
@ -268,7 +297,7 @@ impl<'tcx> AdtDef {
/// Returns a description of a variant of this abstract data type.
#[inline]
pub fn variant_descr(&self) -> &'static str {
pub fn variant_descr(self) -> &'static str {
match self.adt_kind() {
AdtKind::Struct => "struct",
AdtKind::Union => "union",
@ -278,65 +307,65 @@ impl<'tcx> AdtDef {
/// If this function returns `true`, it implies that `is_struct` must return `true`.
#[inline]
pub fn has_ctor(&self) -> bool {
self.flags.contains(AdtFlags::HAS_CTOR)
pub fn has_ctor(self) -> bool {
self.flags().contains(AdtFlags::HAS_CTOR)
}
/// Returns `true` if this type is `#[fundamental]` for the purposes
/// of coherence checking.
#[inline]
pub fn is_fundamental(&self) -> bool {
self.flags.contains(AdtFlags::IS_FUNDAMENTAL)
pub fn is_fundamental(self) -> bool {
self.flags().contains(AdtFlags::IS_FUNDAMENTAL)
}
/// Returns `true` if this is `PhantomData<T>`.
#[inline]
pub fn is_phantom_data(&self) -> bool {
self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
pub fn is_phantom_data(self) -> bool {
self.flags().contains(AdtFlags::IS_PHANTOM_DATA)
}
/// Returns `true` if this is Box<T>.
#[inline]
pub fn is_box(&self) -> bool {
self.flags.contains(AdtFlags::IS_BOX)
pub fn is_box(self) -> bool {
self.flags().contains(AdtFlags::IS_BOX)
}
/// Returns `true` if this is `ManuallyDrop<T>`.
#[inline]
pub fn is_manually_drop(&self) -> bool {
self.flags.contains(AdtFlags::IS_MANUALLY_DROP)
pub fn is_manually_drop(self) -> bool {
self.flags().contains(AdtFlags::IS_MANUALLY_DROP)
}
/// Returns `true` if this type has a destructor.
pub fn has_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
self.destructor(tcx).is_some()
}
pub fn has_non_const_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
pub fn has_non_const_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. }))
}
/// Asserts this is a struct or union and returns its unique variant.
pub fn non_enum_variant(&self) -> &VariantDef {
pub fn non_enum_variant(self) -> &'tcx VariantDef {
assert!(self.is_struct() || self.is_union());
&self.variants[VariantIdx::new(0)]
&self.variant(VariantIdx::new(0))
}
#[inline]
pub fn predicates(&self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> {
tcx.predicates_of(self.did)
pub fn predicates(self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> {
tcx.predicates_of(self.did())
}
/// Returns an iterator over all fields contained
/// by this ADT.
#[inline]
pub fn all_fields(&self) -> impl Iterator<Item = &FieldDef> + Clone {
self.variants.iter().flat_map(|v| v.fields.iter())
pub fn all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone {
self.variants().iter().flat_map(|v| v.fields.iter())
}
/// Whether the ADT lacks fields. Note that this includes uninhabited enums,
/// e.g., `enum Void {}` is considered payload free as well.
pub fn is_payloadfree(&self) -> bool {
pub fn is_payloadfree(self) -> bool {
// Treat the ADT as not payload-free if arbitrary_enum_discriminant is used (#88621).
// This would disallow the following kind of enum from being casted into integer.
// ```
@ -347,31 +376,31 @@ impl<'tcx> AdtDef {
// }
// ```
if self
.variants
.variants()
.iter()
.any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const)
{
return false;
}
self.variants.iter().all(|v| v.fields.is_empty())
self.variants().iter().all(|v| v.fields.is_empty())
}
/// Return a `VariantDef` given a variant id.
pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
self.variants.iter().find(|v| v.def_id == vid).expect("variant_with_id: unknown variant")
pub fn variant_with_id(self, vid: DefId) -> &'tcx VariantDef {
self.variants().iter().find(|v| v.def_id == vid).expect("variant_with_id: unknown variant")
}
/// Return a `VariantDef` given a constructor id.
pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef {
self.variants
pub fn variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef {
self.variants()
.iter()
.find(|v| v.ctor_def_id == Some(cid))
.expect("variant_with_ctor_id: unknown variant")
}
/// Return the index of `VariantDef` given a variant id.
pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
self.variants
pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx {
self.variants()
.iter_enumerated()
.find(|(_, v)| v.def_id == vid)
.expect("variant_index_with_id: unknown variant")
@ -379,15 +408,15 @@ impl<'tcx> AdtDef {
}
/// Return the index of `VariantDef` given a constructor id.
pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx {
self.variants
pub fn variant_index_with_ctor_id(self, cid: DefId) -> VariantIdx {
self.variants()
.iter_enumerated()
.find(|(_, v)| v.ctor_def_id == Some(cid))
.expect("variant_index_with_ctor_id: unknown variant")
.0
}
pub fn variant_of_res(&self, res: Res) -> &VariantDef {
pub fn variant_of_res(self, res: Res) -> &'tcx VariantDef {
match res {
Res::Def(DefKind::Variant, vid) => self.variant_with_id(vid),
Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid),
@ -402,10 +431,10 @@ impl<'tcx> AdtDef {
}
#[inline]
pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
pub fn eval_explicit_discr(self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
assert!(self.is_enum());
let param_env = tcx.param_env(expr_did);
let repr_type = self.repr.discr_type();
let repr_type = self.repr().discr_type();
match tcx.const_eval_poly(expr_did) {
Ok(val) => {
let ty = repr_type.to_ty(tcx);
@ -437,14 +466,14 @@ impl<'tcx> AdtDef {
#[inline]
pub fn discriminants(
&'tcx self,
self,
tcx: TyCtxt<'tcx>,
) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
assert!(self.is_enum());
let repr_type = self.repr.discr_type();
let repr_type = self.repr().discr_type();
let initial = repr_type.initial_discriminant(tcx);
let mut prev_discr = None::<Discr<'tcx>>;
self.variants.iter_enumerated().map(move |(i, v)| {
self.variants().iter_enumerated().map(move |(i, v)| {
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
if let VariantDiscr::Explicit(expr_did) = v.discr {
if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
@ -458,8 +487,8 @@ impl<'tcx> AdtDef {
}
#[inline]
pub fn variant_range(&self) -> Range<VariantIdx> {
VariantIdx::new(0)..VariantIdx::new(self.variants.len())
pub fn variant_range(self) -> Range<VariantIdx> {
VariantIdx::new(0)..VariantIdx::new(self.variants().len())
}
/// Computes the discriminant value used by a specific variant.
@ -469,7 +498,7 @@ impl<'tcx> AdtDef {
/// assuming there are no constant-evaluation errors there.
#[inline]
pub fn discriminant_for_variant(
&self,
self,
tcx: TyCtxt<'tcx>,
variant_index: VariantIdx,
) -> Discr<'tcx> {
@ -477,19 +506,19 @@ impl<'tcx> AdtDef {
let (val, offset) = self.discriminant_def_for_variant(variant_index);
let explicit_value = val
.and_then(|expr_did| self.eval_explicit_discr(tcx, expr_did))
.unwrap_or_else(|| self.repr.discr_type().initial_discriminant(tcx));
.unwrap_or_else(|| self.repr().discr_type().initial_discriminant(tcx));
explicit_value.checked_add(tcx, offset as u128).0
}
/// Yields a `DefId` for the discriminant and an offset to add to it
/// Alternatively, if there is no explicit discriminant, returns the
/// inferred discriminant directly.
pub fn discriminant_def_for_variant(&self, variant_index: VariantIdx) -> (Option<DefId>, u32) {
assert!(!self.variants.is_empty());
pub fn discriminant_def_for_variant(self, variant_index: VariantIdx) -> (Option<DefId>, u32) {
assert!(!self.variants().is_empty());
let mut explicit_index = variant_index.as_u32();
let expr_did;
loop {
match self.variants[VariantIdx::from_u32(explicit_index)].discr {
match self.variant(VariantIdx::from_u32(explicit_index)).discr {
ty::VariantDiscr::Relative(0) => {
expr_did = None;
break;
@ -506,8 +535,8 @@ impl<'tcx> AdtDef {
(expr_did, variant_index.as_u32() - explicit_index)
}
pub fn destructor(&self, tcx: TyCtxt<'tcx>) -> Option<Destructor> {
tcx.adt_destructor(self.did)
pub fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<Destructor> {
tcx.adt_destructor(self.did())
}
/// Returns a list of types such that `Self: Sized` if and only
@ -520,7 +549,7 @@ impl<'tcx> AdtDef {
///
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
tcx.adt_sized_constraint(self.did).0
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
tcx.adt_sized_constraint(self.did()).0
}
}

View file

@ -164,7 +164,7 @@ impl<'tcx> CapturedPlace<'tcx> {
write!(
&mut symbol,
"__{}",
def.variants[variant].fields[idx as usize].name.as_str(),
def.variant(variant).fields[idx as usize].name.as_str(),
)
.unwrap();
}
@ -330,7 +330,7 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
curr_string = format!(
"{}.{}",
curr_string,
def.variants[variant].fields[idx as usize].name.as_str()
def.variant(variant).fields[idx as usize].name.as_str()
);
}
ty::Tuple(_) => {

View file

@ -15,7 +15,7 @@ use crate::mir::{
use crate::thir;
use crate::traits;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::Span;
@ -156,6 +156,12 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> {
}
}
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> {
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
self.0.0.encode(e)
}
}
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
e.encode_alloc_id(self)
@ -178,8 +184,7 @@ encodable_via_deref! {
&'tcx mir::Body<'tcx>,
&'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
&'tcx ty::AdtDef
&'tcx mir::coverage::CodeRegion
}
pub trait TyDecoder<'tcx>: Decoder {
@ -367,6 +372,12 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
}
}
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
fn decode(decoder: &mut D) -> Self {
decoder.tcx().intern_adt_def(Decodable::decode(decoder))
}
}
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, Span)] {
fn decode(decoder: &mut D) -> &'tcx Self {
decoder.tcx().arena.alloc_from_iter(
@ -409,8 +420,7 @@ impl_decodable_via_ref! {
&'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
&'tcx ty::List<ty::BoundVariableKind>,
&'tcx ty::AdtDef
&'tcx ty::List<ty::BoundVariableKind>
}
#[macro_export]

View file

@ -17,7 +17,7 @@ use crate::ty::query::{self, TyCtxtAt};
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
use crate::ty::TyKind::*;
use crate::ty::{
self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy,
FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List,
ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region,
@ -115,7 +115,7 @@ pub struct CtxtInterners<'tcx> {
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<'tcx>>,
adt_def: InternedSet<'tcx, AdtDef>,
adt_def: InternedSet<'tcx, AdtDefData>,
}
impl<'tcx> CtxtInterners<'tcx> {
@ -1123,8 +1123,8 @@ impl<'tcx> TyCtxt<'tcx> {
kind: AdtKind,
variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions,
) -> &'tcx ty::AdtDef {
self.intern_adt_def(ty::AdtDef::new(self, did, kind, variants, repr))
) -> ty::AdtDef<'tcx> {
self.intern_adt_def(ty::AdtDefData::new(self, did, kind, variants, repr))
}
/// Allocates a read-only byte or string literal for `mir::interpret`.
@ -2147,47 +2147,7 @@ direct_interners! {
const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>,
}
macro_rules! direct_interners_old {
($($name:ident: $method:ident($ty:ty),)+) => {
$(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
fn borrow<'a>(&'a self) -> &'a $ty {
&self.0
}
}
impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
fn eq(&self, other: &Self) -> bool {
// The `Borrow` trait requires that `x.borrow() == y.borrow()`
// equals `x == y`.
self.0 == other.0
}
}
impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
fn hash<H: Hasher>(&self, s: &mut H) {
// The `Borrow` trait requires that `x.borrow().hash(s) ==
// x.hash(s)`.
self.0.hash(s)
}
}
impl<'tcx> TyCtxt<'tcx> {
pub fn $method(self, v: $ty) -> &'tcx $ty {
self.interners.$name.intern(v, |v| {
InternedInSet(self.interners.arena.alloc(v))
}).0
}
})+
}
}
// FIXME: eventually these should all be converted to `direct_interners`.
direct_interners_old! {
adt_def: intern_adt_def(AdtDef),
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
}
macro_rules! slice_interners {
@ -2341,7 +2301,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline]
pub fn mk_adt(self, def: &'tcx AdtDef, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
// Take a copy of substs so that we own the vectors inside.
self.mk_ty(Adt(def, substs))
}
@ -2563,12 +2523,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn mk_place_downcast(
self,
place: Place<'tcx>,
adt_def: &'tcx AdtDef,
adt_def: AdtDef<'tcx>,
variant_index: VariantIdx,
) -> Place<'tcx> {
self.mk_place_elem(
place,
PlaceElem::Downcast(Some(adt_def.variants[variant_index].name), variant_index),
PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
)
}

View file

@ -247,7 +247,7 @@ impl<'tcx> Ty<'tcx> {
}
ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
ty::Array(t, n) => {
if t.is_simple_ty() {

View file

@ -86,7 +86,7 @@ pub fn simplify_type<'tcx>(
ty::Int(int_type) => Some(IntSimplifiedType(int_type)),
ty::Uint(uint_type) => Some(UintSimplifiedType(uint_type)),
ty::Float(float_type) => Some(FloatSimplifiedType(float_type)),
ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)),
ty::Adt(def, _) => Some(AdtSimplifiedType(def.did())),
ty::Str => Some(StrSimplifiedType),
ty::Array(..) => Some(ArraySimplifiedType),
ty::Slice(..) => Some(SliceSimplifiedType),

View file

@ -105,21 +105,21 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
impl<'tcx> AdtDef {
impl<'tcx> AdtDef<'tcx> {
/// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
fn uninhabited_from(
&self,
self,
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest<'tcx> {
// Non-exhaustive ADTs from other crates are always considered inhabited.
if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
if self.is_variant_list_non_exhaustive() && !self.did().is_local() {
DefIdForest::empty()
} else {
DefIdForest::intersection(
tcx,
self.variants
self.variants()
.iter()
.map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
)

View file

@ -733,7 +733,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
// SIMD vector types.
ty::Adt(def, substs) if def.repr.simd() => {
ty::Adt(def, substs) if def.repr().simd() => {
if !def.is_struct() {
// Should have yielded E0517 by now.
tcx.sess.delay_span_bug(
@ -853,7 +853,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
ty::Adt(def, substs) => {
// Cache the field layouts.
let variants = def
.variants
.variants()
.iter()
.map(|v| {
v.fields
@ -864,22 +864,22 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
if def.is_union() {
if def.repr.pack.is_some() && def.repr.align.is_some() {
if def.repr().pack.is_some() && def.repr().align.is_some() {
self.tcx.sess.delay_span_bug(
tcx.def_span(def.did),
tcx.def_span(def.did()),
"union cannot be packed and aligned",
);
return Err(LayoutError::Unknown(ty));
}
let mut align =
if def.repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
if def.repr().pack.is_some() { dl.i8_align } else { dl.aggregate_align };
if let Some(repr_align) = def.repr.align {
if let Some(repr_align) = def.repr().align {
align = align.max(AbiAndPrefAlign::new(repr_align));
}
let optimize = !def.repr.inhibit_union_abi_opt();
let optimize = !def.repr().inhibit_union_abi_opt();
let mut size = Size::ZERO;
let mut abi = Abi::Aggregate { sized: true };
let index = VariantIdx::new(0);
@ -915,7 +915,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
size = cmp::max(size, field.size);
}
if let Some(pack) = def.repr.pack {
if let Some(pack) = def.repr().pack {
align = align.min(AbiAndPrefAlign::new(pack));
}
@ -963,7 +963,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// Only one variant is present.
(present_second.is_none() &&
// Representation optimizations are allowed.
!def.repr.inhibit_enum_layout_opt());
!def.repr().inhibit_enum_layout_opt());
if is_struct {
// Struct, or univariant enum equivalent to a struct.
// (Typechecking will reject discriminant-sizing attrs.)
@ -972,8 +972,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let kind = if def.is_enum() || variants[v].is_empty() {
StructKind::AlwaysSized
} else {
let param_env = tcx.param_env(def.did);
let last_field = def.variants[v].fields.last().unwrap();
let param_env = tcx.param_env(def.did());
let last_field = def.variant(v).fields.last().unwrap();
let always_sized =
tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env);
if !always_sized {
@ -983,9 +983,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
};
let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr, kind)?;
let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr(), kind)?;
st.variants = Variants::Single { index: v };
let (start, end) = self.tcx.layout_scalar_valid_range(def.did);
let (start, end) = self.tcx.layout_scalar_valid_range(def.did());
match st.abi {
Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
// the asserts ensure that we are not using the
@ -1011,7 +1011,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
// Update `largest_niche` if we have introduced a larger niche.
let niche = if def.repr.hide_niche() {
let niche = if def.repr().hide_niche() {
None
} else {
Niche::from_scalar(dl, Size::ZERO, *scalar)
@ -1049,14 +1049,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// instead of actual discriminants, so dataful enums with
// explicit discriminants (RFC #2363) would misbehave.
let no_explicit_discriminants = def
.variants
.variants()
.iter_enumerated()
.all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32()));
let mut niche_filling_layout = None;
// Niche-filling enum optimization.
if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
if !def.repr().inhibit_enum_layout_opt() && no_explicit_discriminants {
let mut dataful_variant = None;
let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
@ -1107,7 +1107,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let mut st = self.univariant_uninterned(
ty,
v,
&def.repr,
&def.repr(),
StructKind::AlwaysSized,
)?;
st.variants = Variants::Single { index: j };
@ -1169,7 +1169,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
let (mut min, mut max) = (i128::MAX, i128::MIN);
let discr_type = def.repr.discr_type();
let discr_type = def.repr().discr_type();
let bits = Integer::from_attr(self, discr_type).size().bits();
for (i, discr) in def.discriminants(tcx) {
if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
@ -1193,7 +1193,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
max = 0;
}
assert!(min <= max, "discriminant range is {}...{}", min, max);
let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr(), min, max);
let mut align = dl.aggregate_align;
let mut size = Size::ZERO;
@ -1208,7 +1208,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// determining the alignment of the overall enum, and the
// determining the alignment of the payload after the tag.)
let mut prefix_align = min_ity.align(dl).abi;
if def.repr.c() {
if def.repr().c() {
for fields in &variants {
for field in fields {
prefix_align = prefix_align.max(field.align.abi);
@ -1223,7 +1223,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let mut st = self.univariant_uninterned(
ty,
&field_layouts,
&def.repr,
&def.repr(),
StructKind::Prefixed(min_ity.size(), prefix_align),
)?;
st.variants = Variants::Single { index: i };
@ -1250,7 +1250,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
return Err(LayoutError::SizeOverflow(ty));
}
let typeck_ity = Integer::from_attr(dl, def.repr.discr_type());
let typeck_ity = Integer::from_attr(dl, def.repr().discr_type());
if typeck_ity < min_ity {
// It is a bug if Layout decided on a greater discriminant size than typeck for
// some reason at this point (based on values discriminant can take on). Mostly
@ -1280,7 +1280,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// won't be so conservative.
// Use the initial field alignment
let mut ity = if def.repr.c() || def.repr.int.is_some() {
let mut ity = if def.repr().c() || def.repr().int.is_some() {
min_ity
} else {
Integer::for_align(dl, start_align).unwrap_or(min_ity)
@ -1821,7 +1821,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
};
let adt_kind = adt_def.adt_kind();
let adt_packed = adt_def.repr.pack.is_some();
let adt_packed = adt_def.repr().pack.is_some();
let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
let mut min_size = Size::ZERO;
@ -1855,12 +1855,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
match layout.variants {
Variants::Single { index } => {
if !adt_def.variants.is_empty() && layout.fields != FieldsShape::Primitive {
if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
debug!(
"print-type-size `{:#?}` variant {}",
layout, adt_def.variants[index].name
layout,
adt_def.variant(index).name
);
let variant_def = &adt_def.variants[index];
let variant_def = &adt_def.variant(index);
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
record(
adt_kind.into(),
@ -1879,10 +1880,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
debug!(
"print-type-size `{:#?}` adt general variants def {}",
layout.ty,
adt_def.variants.len()
adt_def.variants().len()
);
let variant_infos: Vec<_> = adt_def
.variants
.variants()
.iter_enumerated()
.map(|(i, variant_def)| {
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
@ -1964,17 +1965,17 @@ impl<'tcx> SizeSkeleton<'tcx> {
ty::Adt(def, substs) => {
// Only newtypes and enums w/ nullable pointer optimization.
if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
if def.is_union() || def.variants().is_empty() || def.variants().len() > 2 {
return Err(err);
}
// Get a zero-sized variant or a pointer newtype.
let zero_or_ptr_variant = |i| {
let i = VariantIdx::new(i);
let fields = def.variants[i]
.fields
.iter()
.map(|field| SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env));
let fields =
def.variant(i).fields.iter().map(|field| {
SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
});
let mut ptr = None;
for field in fields {
let field = field?;
@ -1997,11 +1998,11 @@ impl<'tcx> SizeSkeleton<'tcx> {
let v0 = zero_or_ptr_variant(0)?;
// Newtype.
if def.variants.len() == 1 {
if def.variants().len() == 1 {
if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
return Ok(SizeSkeleton::Pointer {
non_zero: non_zero
|| match tcx.layout_scalar_valid_range(def.did) {
|| match tcx.layout_scalar_valid_range(def.did()) {
(Bound::Included(start), Bound::Unbounded) => start > 0,
(Bound::Included(start), Bound::Included(end)) => {
0 < start && start < end
@ -2262,9 +2263,9 @@ where
}
let fields = match this.ty.kind() {
ty::Adt(def, _) if def.variants.is_empty() =>
ty::Adt(def, _) if def.variants().is_empty() =>
bug!("for_variant called on zero-variant enum"),
ty::Adt(def, _) => def.variants[variant_index].fields.len(),
ty::Adt(def, _) => def.variant(variant_index).fields.len(),
_ => bug!(),
};
tcx.intern_layout(LayoutS {
@ -2405,7 +2406,7 @@ where
ty::Adt(def, substs) => {
match this.variants {
Variants::Single { index } => {
TyMaybeWithLayout::Ty(def.variants[index].fields[i].ty(tcx, substs))
TyMaybeWithLayout::Ty(def.variant(index).fields[i].ty(tcx, substs))
}
// Discriminant field for enums (where applicable).

View file

@ -274,7 +274,7 @@ fn characteristic_def_id_of_type_cached<'a>(
visited: &mut SsoHashSet<Ty<'a>>,
) -> Option<DefId> {
match *ty.kind() {
ty::Adt(adt_def, _) => Some(adt_def.did),
ty::Adt(adt_def, _) => Some(adt_def.did()),
ty::Dynamic(data, ..) => data.principal_def_id(),

View file

@ -618,7 +618,7 @@ pub trait PrettyPrinter<'tcx>:
ty::BoundTyKind::Param(p) => p!(write("{}", p)),
},
ty::Adt(def, substs) => {
p!(print_def_path(def.did, substs));
p!(print_def_path(def.did(), substs));
}
ty::Dynamic(data, r) => {
let print_r = self.should_print_region(r);
@ -1487,7 +1487,7 @@ pub trait PrettyPrinter<'tcx>:
}
p!(")");
}
ty::Adt(def, _) if def.variants.is_empty() => {
ty::Adt(def, _) if def.variants().is_empty() => {
self = self.typed_value(
|mut this| {
write!(this, "unreachable()")?;
@ -1500,7 +1500,7 @@ pub trait PrettyPrinter<'tcx>:
ty::Adt(def, substs) => {
let variant_idx =
contents.variant.expect("destructed const of adt without variant idx");
let variant_def = &def.variants[variant_idx];
let variant_def = &def.variant(variant_idx);
p!(print_value_path(variant_def.def_id, substs));
match variant_def.ctor_kind {

View file

@ -406,7 +406,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => {
let substs = relation.relate_item_substs(a_def.did, a_substs, b_substs)?;
let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?;
Ok(tcx.mk_adt(a_def, substs))
}

View file

@ -33,13 +33,13 @@ impl fmt::Debug for ty::TraitDef {
}
}
impl fmt::Debug for ty::AdtDef {
impl<'tcx> fmt::Debug for ty::AdtDef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ty::tls::with(|tcx| {
with_no_trimmed_paths!({
f.write_str(
&FmtPrinter::new(tcx, Namespace::TypeNS)
.print_def_path(self.did, &[])?
.print_def_path(self.did(), &[])?
.into_buffer(),
)
})
@ -672,7 +672,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
// TypeFoldable implementations.
/// AdtDefs are basically the same as a DefId.
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> {
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
self,
_folder: &mut F,

View file

@ -109,7 +109,7 @@ pub enum TyKind<'tcx> {
///
/// Note that generic parameters in fields only get lazily substituted
/// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`.
Adt(&'tcx AdtDef, SubstsRef<'tcx>),
Adt(AdtDef<'tcx>, SubstsRef<'tcx>),
/// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
Foreign(DefId),
@ -1903,7 +1903,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn is_simd(self) -> bool {
match self.kind() {
Adt(def, _) => def.repr.simd(),
Adt(def, _) => def.repr().simd(),
_ => false,
}
}
@ -1919,7 +1919,7 @@ impl<'tcx> Ty<'tcx> {
pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
match self.kind() {
Adt(def, substs) => {
assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type");
assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
let variant = def.non_enum_variant();
let f0_ty = variant.fields[0].ty(tcx, substs);
@ -2153,9 +2153,9 @@ impl<'tcx> Ty<'tcx> {
}
#[inline]
pub fn ty_adt_def(self) -> Option<&'tcx AdtDef> {
pub fn ty_adt_def(self) -> Option<AdtDef<'tcx>> {
match self.kind() {
Adt(adt, _) => Some(adt),
Adt(adt, _) => Some(*adt),
_ => None,
}
}
@ -2194,7 +2194,7 @@ impl<'tcx> Ty<'tcx> {
variant_index: VariantIdx,
) -> Option<Discr<'tcx>> {
match self.kind() {
TyKind::Adt(adt, _) if adt.variants.is_empty() => {
TyKind::Adt(adt, _) if adt.variants().is_empty() => {
// This can actually happen during CTFE, see
// https://github.com/rust-lang/rust/issues/89765.
None
@ -2212,7 +2212,7 @@ impl<'tcx> Ty<'tcx> {
/// Returns the type of the discriminant of this type.
pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind() {
ty::Adt(adt, _) if adt.is_enum() => adt.repr.discr_type().to_ty(tcx),
ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {

View file

@ -377,10 +377,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// Note that this returns only the constraints for the
/// destructor of `def` itself. For the destructors of the
/// contents, you need `adt_dtorck_constraint`.
pub fn destructor_constraints(self, def: &'tcx ty::AdtDef) -> Vec<ty::subst::GenericArg<'tcx>> {
pub fn destructor_constraints(self, def: ty::AdtDef<'tcx>) -> Vec<ty::subst::GenericArg<'tcx>> {
let dtor = match def.destructor(self) {
None => {
debug!("destructor_constraints({:?}) - no dtor", def.did);
debug!("destructor_constraints({:?}) - no dtor", def.did());
return vec![];
}
Some(dtor) => dtor.did,
@ -415,7 +415,7 @@ impl<'tcx> TyCtxt<'tcx> {
_ => bug!(),
};
let item_substs = match *self.type_of(def.did).kind() {
let item_substs = match *self.type_of(def.did()).kind() {
ty::Adt(def_, substs) if def_ == def => substs,
_ => bug!(),
};
@ -445,7 +445,7 @@ impl<'tcx> TyCtxt<'tcx> {
})
.map(|(item_param, _)| item_param)
.collect();
debug!("destructor_constraint({:?}) = {:?}", def.did, result);
debug!("destructor_constraint({:?}) = {:?}", def.did(), result);
result
}