Skip to main content

rustc_middle/query/
keys.rs

1//! Defines the set of legal keys that can be used in queries.
2
3use std::ffi::OsStr;
4use std::fmt::Debug;
5use std::hash::Hash;
6
7use rustc_ast::tokenstream::TokenStream;
8use rustc_data_structures::sso::SsoHashSet;
9use rustc_data_structures::stable_hash::StableHash;
10use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModId};
11use rustc_hir::hir_id::OwnerId;
12use rustc_span::def_id::ModId;
13use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol};
14
15use crate::dep_graph::DepNodeIndex;
16use crate::infer::canonical::CanonicalQueryInput;
17use crate::mono::CollectionMode;
18use crate::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
19use crate::ty::fast_reject::SimplifiedType;
20use crate::ty::layout::ValidityRequirement;
21use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
22use crate::{mir, traits};
23
24/// Placeholder for `CrateNum`'s "local" counterpart
25#[derive(#[automatically_derived]
impl ::core::marker::Copy for LocalCrate { }Copy, #[automatically_derived]
impl ::core::clone::Clone for LocalCrate {
    #[inline]
    fn clone(&self) -> LocalCrate { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for LocalCrate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "LocalCrate")
    }
}Debug)]
26pub struct LocalCrate;
27
28pub trait QueryKeyBounds = Copy + Debug + Eq + Hash + StableHash;
29
30/// Controls what types can legally be used as the key for a query.
31pub trait QueryKey: Sized + QueryKeyBounds {
32    /// The type of in-memory cache to use for queries with this key type.
33    ///
34    /// In practice the cache type must implement [`QueryCache`], though that
35    /// constraint is not enforced here.
36    ///
37    /// [`QueryCache`]: rustc_middle::query::QueryCache
38    type Cache<V> = DefaultCache<Self, V>;
39
40    type LocalQueryKey = !;
41
42    /// In the event that a cycle occurs, if no explicit span has been
43    /// given for a query with key `self`, what span should we use?
44    fn default_span(&self, tcx: TyCtxt<'_>) -> Span;
45
46    /// If the key is a [`DefId`] or `DefId`--equivalent, return that `DefId`.
47    /// Otherwise, return `None`.
48    fn key_as_def_id(&self) -> Option<DefId> {
49        None
50    }
51
52    /// Given an instance of this key, what crate is it referring to?
53    /// This is used to find the provider.
54    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
55        None
56    }
57}
58
59impl QueryKey for () {
60    type Cache<V> = SingleCache<V>;
61
62    fn default_span(&self, _: TyCtxt<'_>) -> Span {
63        DUMMY_SP
64    }
65}
66
67impl<'tcx> QueryKey for ty::ShimKind<'tcx> {
68    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
69        tcx.def_span(self.def_id())
70    }
71}
72
73impl<'tcx> QueryKey for ty::InstanceKind<'tcx> {
74    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
75        tcx.def_span(self.def_id())
76    }
77}
78
79impl<'tcx> QueryKey for ty::Instance<'tcx> {
80    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
81        tcx.def_span(self.def_id())
82    }
83}
84
85impl<'tcx> QueryKey for mir::interpret::GlobalId<'tcx> {
86    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
87        self.instance.default_span(tcx)
88    }
89}
90
91impl<'tcx> QueryKey for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
92    fn default_span(&self, _: TyCtxt<'_>) -> Span {
93        DUMMY_SP
94    }
95}
96
97impl<'tcx> QueryKey for ty::LitToConstInput<'tcx> {
98    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
99        DUMMY_SP
100    }
101}
102
103impl QueryKey for CrateNum {
104    type Cache<V> = VecCache<Self, V, DepNodeIndex>;
105
106    type LocalQueryKey = LocalCrate;
107
108    fn default_span(&self, _: TyCtxt<'_>) -> Span {
109        DUMMY_SP
110    }
111
112    #[inline(always)]
113    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
114        (*self == LOCAL_CRATE).then_some(LocalCrate)
115    }
116}
117
118impl QueryKey for OwnerId {
119    type Cache<V> = VecCache<Self, V, DepNodeIndex>;
120
121    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
122        self.to_def_id().default_span(tcx)
123    }
124
125    fn key_as_def_id(&self) -> Option<DefId> {
126        Some(self.to_def_id())
127    }
128}
129
130impl QueryKey for LocalDefId {
131    type Cache<V> = VecCache<Self, V, DepNodeIndex>;
132
133    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
134        self.to_def_id().default_span(tcx)
135    }
136
137    fn key_as_def_id(&self) -> Option<DefId> {
138        Some(self.to_def_id())
139    }
140}
141
142impl QueryKey for DefId {
143    type Cache<V> = DefIdCache<V>;
144    type LocalQueryKey = LocalDefId;
145
146    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
147        tcx.def_span(*self)
148    }
149
150    #[inline(always)]
151    fn key_as_def_id(&self) -> Option<DefId> {
152        Some(*self)
153    }
154
155    #[inline(always)]
156    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
157        self.as_local()
158    }
159}
160
161impl QueryKey for ModId {
162    type LocalQueryKey = LocalModId;
163
164    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
165        tcx.def_span(self.to_def_id())
166    }
167
168    #[inline(always)]
169    fn key_as_def_id(&self) -> Option<DefId> {
170        Some(self.to_def_id())
171    }
172
173    #[inline(always)]
174    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
175        self.as_local()
176    }
177}
178
179impl QueryKey for LocalModId {
180    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
181        tcx.def_span(*self)
182    }
183
184    #[inline(always)]
185    fn key_as_def_id(&self) -> Option<DefId> {
186        Some(self.to_def_id())
187    }
188}
189
190impl QueryKey for SimplifiedType {
191    fn default_span(&self, _: TyCtxt<'_>) -> Span {
192        DUMMY_SP
193    }
194}
195
196impl QueryKey for (DefId, DefId) {
197    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
198        self.1.default_span(tcx)
199    }
200}
201
202impl QueryKey for (DefId, Ident) {
203    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
204        tcx.def_span(self.0)
205    }
206
207    #[inline(always)]
208    fn key_as_def_id(&self) -> Option<DefId> {
209        Some(self.0)
210    }
211}
212
213impl QueryKey for (LocalDefId, LocalDefId, Ident) {
214    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
215        self.1.default_span(tcx)
216    }
217}
218
219impl QueryKey for (CrateNum, DefId) {
220    type LocalQueryKey = DefId;
221
222    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
223        self.1.default_span(tcx)
224    }
225
226    #[inline(always)]
227    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
228        (self.0 == LOCAL_CRATE).then(|| self.1)
229    }
230}
231
232impl QueryKey for (CrateNum, SimplifiedType) {
233    type LocalQueryKey = SimplifiedType;
234
235    fn default_span(&self, _: TyCtxt<'_>) -> Span {
236        DUMMY_SP
237    }
238
239    #[inline(always)]
240    fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
241        (self.0 == LOCAL_CRATE).then(|| self.1)
242    }
243}
244
245impl QueryKey for (DefId, ty::SizedTraitKind) {
246    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
247        self.0.default_span(tcx)
248    }
249}
250
251impl<'tcx> QueryKey for GenericArgsRef<'tcx> {
252    fn default_span(&self, _: TyCtxt<'_>) -> Span {
253        DUMMY_SP
254    }
255}
256
257impl<'tcx> QueryKey for (DefId, GenericArgsRef<'tcx>) {
258    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
259        self.0.default_span(tcx)
260    }
261}
262
263impl<'tcx> QueryKey for ty::TraitRef<'tcx> {
264    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
265        tcx.def_span(self.def_id)
266    }
267}
268
269impl<'tcx> QueryKey for GenericArg<'tcx> {
270    fn default_span(&self, _: TyCtxt<'_>) -> Span {
271        DUMMY_SP
272    }
273}
274
275impl<'tcx> QueryKey for Ty<'tcx> {
276    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
277        def_id_of_type(*self).map(|def_id| tcx.def_span(def_id)).unwrap_or(DUMMY_SP)
278    }
279}
280
281impl<'tcx> QueryKey for (Ty<'tcx>, Ty<'tcx>) {
282    fn default_span(&self, _: TyCtxt<'_>) -> Span {
283        DUMMY_SP
284    }
285}
286
287impl<'tcx> QueryKey for ty::Clauses<'tcx> {
288    fn default_span(&self, _: TyCtxt<'_>) -> Span {
289        DUMMY_SP
290    }
291}
292
293impl<'tcx> QueryKey for ty::AliasTyKind<'tcx> {
294    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
295        let def_id = match self {
296            ty::AliasTyKind::Projection { def_id }
297            | ty::AliasTyKind::Inherent { def_id }
298            | ty::AliasTyKind::Opaque { def_id }
299            | ty::AliasTyKind::Free { def_id } => def_id,
300        };
301        tcx.def_span(*def_id)
302    }
303}
304
305impl<'tcx, T: QueryKey> QueryKey for ty::PseudoCanonicalInput<'tcx, T> {
306    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
307        self.value.default_span(tcx)
308    }
309}
310
311impl QueryKey for Symbol {
312    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
313        DUMMY_SP
314    }
315}
316
317impl QueryKey for Option<Symbol> {
318    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
319        DUMMY_SP
320    }
321}
322
323impl<'tcx> QueryKey for &'tcx OsStr {
324    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
325        DUMMY_SP
326    }
327}
328
329/// Canonical query goals correspond to abstract trait operations that
330/// are not tied to any crate in particular.
331impl<'tcx, T: QueryKeyBounds> QueryKey for CanonicalQueryInput<'tcx, T> {
332    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
333        DUMMY_SP
334    }
335}
336
337impl<'tcx, T: QueryKeyBounds> QueryKey for (CanonicalQueryInput<'tcx, T>, bool) {
338    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
339        DUMMY_SP
340    }
341}
342
343impl<'tcx, T: QueryKeyBounds> QueryKey for (CanonicalQueryInput<'tcx, T>, usize) {
344    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
345        DUMMY_SP
346    }
347}
348
349impl<'tcx> QueryKey for (Ty<'tcx>, rustc_abi::VariantIdx) {
350    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
351        DUMMY_SP
352    }
353}
354
355impl<'tcx> QueryKey for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
356    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
357        DUMMY_SP
358    }
359}
360
361impl<'tcx> QueryKey for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
362    fn default_span(&self, _: TyCtxt<'_>) -> Span {
363        DUMMY_SP
364    }
365}
366
367impl<'tcx> QueryKey for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
368    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
369        self.0.default_span(tcx)
370    }
371}
372
373impl<'tcx> QueryKey for ty::Value<'tcx> {
374    fn default_span(&self, _: TyCtxt<'_>) -> Span {
375        DUMMY_SP
376    }
377}
378
379impl<'tcx> QueryKey for (LocalExpnId, &'tcx TokenStream) {
380    fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
381        self.0.expn_data().call_site
382    }
383}
384
385impl<'tcx> QueryKey for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) {
386    // Just forward to `Ty<'tcx>`
387
388    fn default_span(&self, _: TyCtxt<'_>) -> Span {
389        DUMMY_SP
390    }
391}
392
393impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) {
394    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
395        self.0.default_span(tcx)
396    }
397}
398
399/// Gets a `DefId` associated with a type
400///
401/// Visited set is needed to avoid full iteration over
402/// deeply nested tuples that have no DefId.
403fn def_id_of_type_cached<'a>(ty: Ty<'a>, visited: &mut SsoHashSet<Ty<'a>>) -> Option<DefId> {
404    match *ty.kind() {
405        ty::Adt(adt_def, _) => Some(adt_def.did()),
406
407        ty::Dynamic(data, ..) => data.principal_def_id(),
408
409        ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => {
410            def_id_of_type_cached(subty, visited)
411        }
412
413        ty::RawPtr(ty, _) => def_id_of_type_cached(ty, visited),
414
415        ty::Ref(_, ty, _) => def_id_of_type_cached(ty, visited),
416
417        ty::Tuple(tys) => tys.iter().find_map(|ty| {
418            if visited.insert(ty) {
419                return def_id_of_type_cached(ty, visited);
420            }
421            return None;
422        }),
423
424        ty::FnDef(def_id, _)
425        | ty::Closure(def_id, _)
426        | ty::CoroutineClosure(def_id, _)
427        | ty::Coroutine(def_id, _)
428        | ty::CoroutineWitness(def_id, _)
429        | ty::Foreign(def_id) => Some(def_id),
430
431        ty::Alias(_, alias) => match alias.kind {
432            ty::AliasTyKind::Projection { def_id }
433            | ty::AliasTyKind::Inherent { def_id }
434            | ty::AliasTyKind::Opaque { def_id }
435            | ty::AliasTyKind::Free { def_id } => Some(def_id),
436        },
437
438        ty::Bool
439        | ty::Char
440        | ty::Int(_)
441        | ty::Uint(_)
442        | ty::Str
443        | ty::FnPtr(..)
444        | ty::UnsafeBinder(_)
445        | ty::Placeholder(..)
446        | ty::Param(_)
447        | ty::Infer(_)
448        | ty::Bound(..)
449        | ty::Error(_)
450        | ty::Never
451        | ty::Float(_) => None,
452    }
453}
454
455fn def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
456    def_id_of_type_cached(ty, &mut SsoHashSet::new())
457}