| //! Defines the set of legal keys that can be used in queries. |
| |
| use std::ffi::OsStr; |
| use std::fmt::Debug; |
| use std::hash::Hash; |
| |
| use rustc_ast::tokenstream::TokenStream; |
| use rustc_data_structures::sso::SsoHashSet; |
| use rustc_data_structures::stable_hash::StableHash; |
| use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; |
| use rustc_hir::hir_id::OwnerId; |
| use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; |
| |
| use crate::dep_graph::DepNodeIndex; |
| use crate::infer::canonical::CanonicalQueryInput; |
| use crate::mono::CollectionMode; |
| use crate::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; |
| use crate::ty::fast_reject::SimplifiedType; |
| use crate::ty::layout::ValidityRequirement; |
| use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt}; |
| use crate::{mir, traits}; |
| |
| /// Placeholder for `CrateNum`'s "local" counterpart |
| #[derive(Copy, Clone, Debug)] |
| pub struct LocalCrate; |
| |
| pub trait QueryKeyBounds = Copy + Debug + Eq + Hash + StableHash; |
| |
| /// Controls what types can legally be used as the key for a query. |
| pub trait QueryKey: Sized + QueryKeyBounds { |
| /// The type of in-memory cache to use for queries with this key type. |
| /// |
| /// In practice the cache type must implement [`QueryCache`], though that |
| /// constraint is not enforced here. |
| /// |
| /// [`QueryCache`]: rustc_middle::query::QueryCache |
| type Cache<V> = DefaultCache<Self, V>; |
| |
| /// In the event that a cycle occurs, if no explicit span has been |
| /// given for a query with key `self`, what span should we use? |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span; |
| |
| /// If the key is a [`DefId`] or `DefId`--equivalent, return that `DefId`. |
| /// Otherwise, return `None`. |
| fn key_as_def_id(&self) -> Option<DefId> { |
| None |
| } |
| } |
| |
| pub trait AsLocalQueryKey: QueryKey { |
| type LocalQueryKey; |
| |
| /// Given an instance of this key, what crate is it referring to? |
| /// This is used to find the provider. |
| fn as_local_key(&self) -> Option<Self::LocalQueryKey>; |
| } |
| |
| impl QueryKey for () { |
| type Cache<V> = SingleCache<V>; |
| |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for ty::InstanceKind<'tcx> { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| tcx.def_span(self.def_id()) |
| } |
| } |
| |
| impl<'tcx> QueryKey for ty::Instance<'tcx> { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| tcx.def_span(self.def_id()) |
| } |
| } |
| |
| impl<'tcx> QueryKey for mir::interpret::GlobalId<'tcx> { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.instance.default_span(tcx) |
| } |
| } |
| |
| impl<'tcx> QueryKey for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for ty::LitToConstInput<'tcx> { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl QueryKey for CrateNum { |
| type Cache<V> = VecCache<Self, V, DepNodeIndex>; |
| |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl AsLocalQueryKey for CrateNum { |
| type LocalQueryKey = LocalCrate; |
| |
| #[inline(always)] |
| fn as_local_key(&self) -> Option<Self::LocalQueryKey> { |
| (*self == LOCAL_CRATE).then_some(LocalCrate) |
| } |
| } |
| |
| impl QueryKey for OwnerId { |
| type Cache<V> = VecCache<Self, V, DepNodeIndex>; |
| |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.to_def_id().default_span(tcx) |
| } |
| |
| fn key_as_def_id(&self) -> Option<DefId> { |
| Some(self.to_def_id()) |
| } |
| } |
| |
| impl QueryKey for LocalDefId { |
| type Cache<V> = VecCache<Self, V, DepNodeIndex>; |
| |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.to_def_id().default_span(tcx) |
| } |
| |
| fn key_as_def_id(&self) -> Option<DefId> { |
| Some(self.to_def_id()) |
| } |
| } |
| |
| impl QueryKey for DefId { |
| type Cache<V> = DefIdCache<V>; |
| |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| tcx.def_span(*self) |
| } |
| |
| #[inline(always)] |
| fn key_as_def_id(&self) -> Option<DefId> { |
| Some(*self) |
| } |
| } |
| |
| impl AsLocalQueryKey for DefId { |
| type LocalQueryKey = LocalDefId; |
| |
| #[inline(always)] |
| fn as_local_key(&self) -> Option<Self::LocalQueryKey> { |
| self.as_local() |
| } |
| } |
| |
| impl QueryKey for LocalModDefId { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| tcx.def_span(*self) |
| } |
| |
| #[inline(always)] |
| fn key_as_def_id(&self) -> Option<DefId> { |
| Some(self.to_def_id()) |
| } |
| } |
| |
| impl QueryKey for SimplifiedType { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl QueryKey for (DefId, DefId) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.1.default_span(tcx) |
| } |
| } |
| |
| impl QueryKey for (DefId, Ident) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| tcx.def_span(self.0) |
| } |
| |
| #[inline(always)] |
| fn key_as_def_id(&self) -> Option<DefId> { |
| Some(self.0) |
| } |
| } |
| |
| impl QueryKey for (LocalDefId, LocalDefId, Ident) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.1.default_span(tcx) |
| } |
| } |
| |
| impl QueryKey for (CrateNum, DefId) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.1.default_span(tcx) |
| } |
| } |
| |
| impl AsLocalQueryKey for (CrateNum, DefId) { |
| type LocalQueryKey = DefId; |
| |
| #[inline(always)] |
| fn as_local_key(&self) -> Option<Self::LocalQueryKey> { |
| (self.0 == LOCAL_CRATE).then(|| self.1) |
| } |
| } |
| |
| impl QueryKey for (CrateNum, SimplifiedType) { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl AsLocalQueryKey for (CrateNum, SimplifiedType) { |
| type LocalQueryKey = SimplifiedType; |
| |
| #[inline(always)] |
| fn as_local_key(&self) -> Option<Self::LocalQueryKey> { |
| (self.0 == LOCAL_CRATE).then(|| self.1) |
| } |
| } |
| |
| impl QueryKey for (DefId, ty::SizedTraitKind) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.0.default_span(tcx) |
| } |
| } |
| |
| impl<'tcx> QueryKey for GenericArgsRef<'tcx> { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (DefId, GenericArgsRef<'tcx>) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.0.default_span(tcx) |
| } |
| } |
| |
| impl<'tcx> QueryKey for ty::TraitRef<'tcx> { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| tcx.def_span(self.def_id) |
| } |
| } |
| |
| impl<'tcx> QueryKey for GenericArg<'tcx> { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for Ty<'tcx> { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| def_id_of_type(*self).map(|def_id| tcx.def_span(def_id)).unwrap_or(DUMMY_SP) |
| } |
| } |
| |
| impl<'tcx> QueryKey for (Ty<'tcx>, Ty<'tcx>) { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for ty::Clauses<'tcx> { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx, T: QueryKey> QueryKey for ty::PseudoCanonicalInput<'tcx, T> { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.value.default_span(tcx) |
| } |
| } |
| |
| impl QueryKey for Symbol { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl QueryKey for Option<Symbol> { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for &'tcx OsStr { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| /// Canonical query goals correspond to abstract trait operations that |
| /// are not tied to any crate in particular. |
| impl<'tcx, T: QueryKeyBounds> QueryKey for CanonicalQueryInput<'tcx, T> { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx, T: QueryKeyBounds> QueryKey for (CanonicalQueryInput<'tcx, T>, bool) { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (Ty<'tcx>, rustc_abi::VariantIdx) { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (ty::Predicate<'tcx>, traits::WellFormedLoc) { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.0.default_span(tcx) |
| } |
| } |
| |
| impl<'tcx> QueryKey for ty::Value<'tcx> { |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (LocalExpnId, &'tcx TokenStream) { |
| fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { |
| self.0.expn_data().call_site |
| } |
| } |
| |
| impl<'tcx> QueryKey for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { |
| // Just forward to `Ty<'tcx>` |
| |
| fn default_span(&self, _: TyCtxt<'_>) -> Span { |
| DUMMY_SP |
| } |
| } |
| |
| impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) { |
| fn default_span(&self, tcx: TyCtxt<'_>) -> Span { |
| self.0.default_span(tcx) |
| } |
| } |
| |
| /// Gets a `DefId` associated with a type |
| /// |
| /// Visited set is needed to avoid full iteration over |
| /// deeply nested tuples that have no DefId. |
| fn def_id_of_type_cached<'a>(ty: Ty<'a>, visited: &mut SsoHashSet<Ty<'a>>) -> Option<DefId> { |
| match *ty.kind() { |
| ty::Adt(adt_def, _) => Some(adt_def.did()), |
| |
| ty::Dynamic(data, ..) => data.principal_def_id(), |
| |
| ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => { |
| def_id_of_type_cached(subty, visited) |
| } |
| |
| ty::RawPtr(ty, _) => def_id_of_type_cached(ty, visited), |
| |
| ty::Ref(_, ty, _) => def_id_of_type_cached(ty, visited), |
| |
| ty::Tuple(tys) => tys.iter().find_map(|ty| { |
| if visited.insert(ty) { |
| return def_id_of_type_cached(ty, visited); |
| } |
| return None; |
| }), |
| |
| ty::FnDef(def_id, _) |
| | ty::Closure(def_id, _) |
| | ty::CoroutineClosure(def_id, _) |
| | ty::Coroutine(def_id, _) |
| | ty::CoroutineWitness(def_id, _) |
| | ty::Foreign(def_id) => Some(def_id), |
| |
| ty::Alias(alias) => Some(alias.kind.def_id()), |
| |
| ty::Bool |
| | ty::Char |
| | ty::Int(_) |
| | ty::Uint(_) |
| | ty::Str |
| | ty::FnPtr(..) |
| | ty::UnsafeBinder(_) |
| | ty::Placeholder(..) |
| | ty::Param(_) |
| | ty::Infer(_) |
| | ty::Bound(..) |
| | ty::Error(_) |
| | ty::Never |
| | ty::Float(_) => None, |
| } |
| } |
| |
| fn def_id_of_type(ty: Ty<'_>) -> Option<DefId> { |
| def_id_of_type_cached(ty, &mut SsoHashSet::new()) |
| } |