diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 2cbc381a11a..3a0ddae1c63 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,3 +1,5 @@ +#![allow(rustc::usage_of_ty_tykind)] + /// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type @@ -88,7 +90,7 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_type_ir::WithCachedTypeInfo>, + [] tys: rustc_type_ir::WithCachedTypeInfo>, [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstS<'tcx>, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e1834f1f57a..f798c0a4e22 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,5 +1,7 @@ //! Type context book-keeping. +#![allow(rustc::usage_of_ty_tykind)] + use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::hir::place::Place as HirPlace; @@ -20,7 +22,7 @@ use crate::ty::{ ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, - Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; @@ -137,7 +139,7 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, WithCachedTypeInfo>>, + type_: InternedSet<'tcx, WithCachedTypeInfo>>, const_lists: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, @@ -194,15 +196,12 @@ impl<'tcx> CtxtInterners<'tcx> { let stable_hash = self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); - let ty_struct = TyS { - kind, + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet( - self.arena.alloc(WithCachedTypeInfo { internee: ty_struct, stable_hash }), - ) + })) }) .0, )) @@ -2058,7 +2057,7 @@ macro_rules! sty_debug_print { let shards = tcx.interners.type_.lock_shards(); let types = shards.iter().flat_map(|shard| shard.keys()); for &InternedInSet(t) in types { - let variant = match t.kind { + let variant = match t.internee { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Str | ty::Never => continue, ty::Error(_) => /* unimportant */ continue, @@ -2168,26 +2167,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { - &self.0.kind + &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. - self.0.kind == other.0.kind + self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) + self.0.internee.hash(s) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c56e1b6e5a0..667b55088cc 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,6 +9,8 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html +#![allow(rustc::usage_of_ty_tykind)] + pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub use self::AssocItemContainer::*; @@ -446,89 +448,24 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Represents a type. -/// -/// IMPORTANT: -/// - This is a very "dumb" struct (with no derives and no `impls`). -/// - Values of this type are always interned and thus unique, and are stored -/// as an `Interned`. -/// - `Ty` (which contains a reference to a `Interned`) or `Interned` -/// should be used everywhere instead of `TyS`. In particular, `Ty` has most -/// of the relevant methods. -#[derive(PartialEq, Eq, PartialOrd, Ord)] -#[allow(rustc::usage_of_ty_tykind)] -pub(crate) struct TyS<'tcx> { - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::kind()` instead. - kind: TyKind<'tcx>, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::flags()` instead. - flags: TypeFlags, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This is a kind of confusing thing: it stores the smallest - /// binder such that - /// - /// (a) the binder itself captures nothing but - /// (b) all the late-bound things within the type are captured - /// by some sub-binder. - /// - /// So, for a type without any late-bound things, like `u32`, this - /// will be *innermost*, because that is the innermost binder that - /// captures nothing. But for a type `&'D u32`, where `'D` is a - /// late-bound region with De Bruijn index `D`, this would be `D + 1` - /// -- the binder itself does not capture `D`, but `D` is captured - /// by an inner binder. - /// - /// We call this concept an "exclusive" binder `D` because all - /// De Bruijn indices within the type are contained within `0..D` - /// (exclusive). - outer_exclusive_binder: ty::DebruijnIndex, -} - /// Use this rather than `TyS`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); +pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> TyCtxt<'tcx> { /// A "bool" type used in rustc_mir_transform unit tests when we /// have not spun up a TyCtxt. pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithCachedTypeInfo { - internee: TyS { - kind: ty::Bool, - flags: TypeFlags::empty(), - outer_exclusive_binder: DebruijnIndex::from_usize(0), - }, + internee: ty::Bool, stable_hash: Fingerprint::ZERO, + flags: TypeFlags::empty(), + outer_exclusive_binder: DebruijnIndex::from_usize(0), })); } -impl<'a, 'tcx> HashStable> for TyS<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let TyS { - kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - - outer_exclusive_binder: _, - } = self; - - kind.hash_stable(hcx, hasher) - } -} - impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). @@ -1030,7 +967,7 @@ impl<'tcx> Term<'tcx> { unsafe { match ptr & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -1074,7 +1011,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -2695,7 +2632,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(PredicateS<'_>, 48); - static_assert_size!(TyS<'_>, 40); - static_assert_size!(WithCachedTypeInfo>, 56); + static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5984686044b..a90f4f91377 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1602,7 +1602,7 @@ impl<'tcx> Region<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0.kind + &self.0.0 } #[inline(always)] diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 13fab0068d6..89901d1575a 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -85,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -163,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index 815237a06c0..4e5d424886a 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -9,9 +9,11 @@ use rustc_data_structures::{ stable_hasher::{HashStable, StableHasher}, }; +use crate::{DebruijnIndex, TypeFlags}; + /// A helper type that you can wrap round your own type in order to automatically -/// cache the stable hash on creation and not recompute it whenever the stable hash -/// of the type is computed. +/// cache the stable hash, type flags and debruijn index on creation and +/// not recompute it whenever the information is needed. /// This is only done in incremental mode. You can also opt out of caching by using /// StableHash::ZERO for the hash, in which case the hash gets computed each time. /// This is useful if you have values that you intern but never (can?) use for stable @@ -20,6 +22,35 @@ use rustc_data_structures::{ pub struct WithCachedTypeInfo { pub internee: T, pub stable_hash: Fingerprint, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// + /// This field shouldn't be used directly and may be removed in the future. + /// Use `Ty::flags()` instead. + pub flags: TypeFlags, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// + /// This is a kind of confusing thing: it stores the smallest + /// binder such that + /// + /// (a) the binder itself captures nothing but + /// (b) all the late-bound things within the type are captured + /// by some sub-binder. + /// + /// So, for a type without any late-bound things, like `u32`, this + /// will be *innermost*, because that is the innermost binder that + /// captures nothing. But for a type `&'D u32`, where `'D` is a + /// late-bound region with De Bruijn index `D`, this would be `D + 1` + /// -- the binder itself does not capture `D`, but `D` is captured + /// by an inner binder. + /// + /// We call this concept an "exclusive" binder `D` because all + /// De Bruijn indices within the type are contained within `0..D` + /// (exclusive). + pub outer_exclusive_binder: DebruijnIndex, } impl PartialEq for WithCachedTypeInfo {