RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
};
use rustc_ast as ast;
-use rustc_attr as attr;
+use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::memmap::Mmap;
use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
+use rustc_type_ir::TypeFlags;
use smallvec::SmallVec;
use std::any::Any;
use std::borrow::Borrow;
// Specifically use a speedy hash algorithm for these hash sets, since
// they're accessed quite often.
type_: InternedSet<'tcx, TyS<'tcx>>,
- type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
region: InternedSet<'tcx, RegionKind>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, Layout>,
adt_def: InternedSet<'tcx, AdtDef>,
-
- /// `#[stable]` and `#[unstable]` attributes
- stability: InternedSet<'tcx, attr::Stability>,
-
- /// `#[rustc_const_stable]` and `#[rustc_const_unstable]` attributes
- const_stability: InternedSet<'tcx, attr::ConstStability>,
}
impl<'tcx> CtxtInterners<'tcx> {
CtxtInterners {
arena,
type_: Default::default(),
- type_list: Default::default(),
substs: Default::default(),
region: Default::default(),
poly_existential_predicates: Default::default(),
bound_variable_kinds: Default::default(),
layout: Default::default(),
adt_def: Default::default(),
- stability: Default::default(),
- const_stability: Default::default(),
}
}
/// Interns a type.
#[allow(rustc::usage_of_ty_tykind)]
#[inline(never)]
- fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> {
+ fn intern_ty(
+ &self,
+ kind: TyKind<'tcx>,
+ sess: &Session,
+ resolutions: &ty::ResolverOutputs,
+ ) -> Ty<'tcx> {
Ty(Interned::new_unchecked(
self.type_
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_kind(&kind);
+ let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER) {
+ Fingerprint::ZERO
+ } else {
+ let mut hasher = StableHasher::new();
+ let mut hcx = StableHashingContext::ignore_spans(
+ sess,
+ &resolutions.definitions,
+ &*resolutions.cstore,
+ );
+ kind.hash_stable(&mut hcx, &mut hasher);
+ hasher.finish()
+ };
+
let ty_struct = TyS {
kind,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
+ stable_hash,
};
InternedInSet(self.arena.alloc(ty_struct))
}
impl<'tcx> CommonTypes<'tcx> {
- fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
- let mk = |ty| interners.intern_ty(ty);
+ fn new(
+ interners: &CtxtInterners<'tcx>,
+ sess: &Session,
+ resolutions: &ty::ResolverOutputs,
+ ) -> CommonTypes<'tcx> {
+ let mk = |ty| interners.intern_ty(ty, sess, resolutions);
CommonTypes {
unit: mk(Tuple(List::empty())),
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
let attrs = self.get_attrs(def_id);
let get = |name| {
- let attr = match attrs.iter().find(|a| a.has_name(name)) {
- Some(attr) => attr,
- None => return Bound::Unbounded,
+ let Some(attr) = attrs.iter().find(|a| a.has_name(name)) else {
+ return Bound::Unbounded;
};
debug!("layout_scalar_valid_range: attr={:?}", attr);
if let Some(
s.fatal(&err);
});
let interners = CtxtInterners::new(arena);
- let common_types = CommonTypes::new(&interners);
+ let common_types = CommonTypes::new(&interners, s, &resolutions);
let common_lifetimes = CommonLifetimes::new(&interners);
let common_consts = CommonConsts::new(&interners, &common_types);
self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
}
- pub fn stability(self) -> &'tcx stability::Index<'tcx> {
+ pub fn stability(self) -> &'tcx stability::Index {
self.stability_index(())
}
scope_def_id: LocalDefId,
) -> Vec<&'tcx hir::Ty<'tcx>> {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
- let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) {
- Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty,
- _ => return vec![],
+ let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
+ return vec![];
};
let mut v = TraitObjectVisitor(vec![], self.hir());
type Lifted = $lifted;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if tcx.interners.$set.contains_pointer_to(&InternedInSet(self.0.0)) {
+ // SAFETY: `self` is interned and therefore valid
+ // for the entire lifetime of the `TyCtxt`.
Some(unsafe { mem::transmute(self) })
} else {
None
};
}
+// Can't use the macros as we have reuse the `substs` here.
+//
+// See `intern_type_list` for more info.
+impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
+ type Lifted = &'tcx List<Ty<'tcx>>;
+ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+ if self.is_empty() {
+ return Some(List::empty());
+ }
+ if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
+ // SAFETY: `self` is interned and therefore valid
+ // for the entire lifetime of the `TyCtxt`.
+ Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
+ } else {
+ None
+ }
+ }
+}
+
macro_rules! nop_list_lift {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
nop_lift_old! {const_allocation; &'a Allocation => &'tcx Allocation}
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
-nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>}
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
- writeln!(fmt, "Stability interner: #{}", self.0.interners.stability.len())?;
- writeln!(
- fmt,
- "Const Stability interner: #{}",
- self.0.interners.const_stability.len()
- )?;
writeln!(
fmt,
"Const Allocation interner: #{}",
const_allocation: intern_const_alloc(Allocation),
layout: intern_layout(Layout),
adt_def: intern_adt_def(AdtDef),
- stability: intern_stability(attr::Stability),
- const_stability: intern_const_stability(attr::ConstStability),
}
macro_rules! slice_interners {
}
slice_interners!(
- type_list: _intern_type_list(Ty<'tcx>),
substs: _intern_substs(GenericArg<'tcx>),
canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
poly_existential_predicates:
) -> PolyFnSig<'tcx> {
sig.map_bound(|s| {
let params_iter = match s.inputs()[0].kind() {
- ty::Tuple(params) => params.into_iter().map(|k| k.expect_ty()),
+ ty::Tuple(params) => params.into_iter(),
_ => bug!(),
};
self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
#[allow(rustc::usage_of_ty_tykind)]
#[inline]
pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
- self.interners.intern_ty(st)
+ self.interners.intern_ty(st, self.sess, &self.gcx.untracked_resolutions)
}
#[inline]
#[inline]
pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
- let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect();
- self.mk_ty(Tuple(self.intern_substs(&kinds)))
+ self.mk_ty(Tuple(self.intern_type_list(&ts)))
}
pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
- iter.intern_with(|ts| {
- let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect();
- self.mk_ty(Tuple(self.intern_substs(&kinds)))
- })
+ iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts))))
}
#[inline]
}
pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
- if ts.is_empty() { List::empty() } else { self._intern_type_list(ts) }
+ if ts.is_empty() {
+ List::empty()
+ } else {
+ // Actually intern type lists as lists of `GenericArg`s.
+ //
+ // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
+ // as explained in ty_slice_as_generic_arg`. With this,
+ // we guarantee that even when transmuting between `List<Ty<'tcx>>`
+ // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
+ // lists is upheld.
+ let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts));
+ substs.try_as_type_list().unwrap()
+ }
}
pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {