Skip to main content

rustc_middle/ty/
context.rs

1//! Type context book-keeping.
2
3#![allow(rustc::usage_of_ty_tykind)]
4
5mod impl_interner;
6pub mod tls;
7
8use std::borrow::{Borrow, Cow};
9use std::cmp::Ordering;
10use std::env::VarError;
11use std::ffi::OsStr;
12use std::hash::{Hash, Hasher};
13use std::marker::PointeeSized;
14use std::ops::Deref;
15use std::sync::{Arc, OnceLock};
16use std::{fmt, iter, mem};
17
18use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
19use rustc_ast as ast;
20use rustc_data_structures::defer;
21use rustc_data_structures::fx::FxHashMap;
22use rustc_data_structures::intern::Interned;
23use rustc_data_structures::jobserver::Proxy;
24use rustc_data_structures::profiling::SelfProfilerRef;
25use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
26use rustc_data_structures::stable_hasher::StableHash;
27use rustc_data_structures::steal::Steal;
28use rustc_data_structures::sync::{
29    self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal,
30};
31use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, MultiSpan};
32use rustc_hir::def::DefKind;
33use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
34use rustc_hir::definitions::{DefPathData, Definitions, PerParentDisambiguatorState};
35use rustc_hir::intravisit::VisitorExt;
36use rustc_hir::lang_items::LangItem;
37use rustc_hir::limit::Limit;
38use rustc_hir::{self as hir, CRATE_HIR_ID, HirId, MaybeOwner, Node, TraitCandidate, find_attr};
39use rustc_index::IndexVec;
40use rustc_macros::Diagnostic;
41use rustc_session::Session;
42use rustc_session::config::CrateType;
43use rustc_session::cstore::{CrateStoreDyn, Untracked};
44use rustc_session::lint::Lint;
45use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
46use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
47use rustc_type_ir::TyKind::*;
48pub use rustc_type_ir::lift::Lift;
49use rustc_type_ir::{CollectAndApply, WithCachedTypeInfo, elaborate, search_graph};
50use tracing::{debug, instrument};
51
52use crate::arena::Arena;
53use crate::dep_graph::dep_node::make_metadata;
54use crate::dep_graph::{DepGraph, DepKindVTable, DepNodeIndex};
55use crate::ich::StableHashingContext;
56use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind};
57use crate::lint::emit_lint_base;
58use crate::metadata::ModChild;
59use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
60use crate::middle::resolve_bound_vars;
61use crate::mir::interpret::{self, Allocation, ConstAllocation};
62use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
63use crate::query::{IntoQueryKey, LocalCrate, Providers, QuerySystem, TyCtxtAt};
64use crate::thir::Thir;
65use crate::traits;
66use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData, PredefinedOpaques};
67use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
68use crate::ty::{
69    self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, FnSigKind, GenericArg,
70    GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst,
71    Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
72    PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
73    ValTree, ValTreeKind, Visibility,
74};
75
76impl<'tcx> rustc_type_ir::inherent::DefId<TyCtxt<'tcx>> for DefId {
77    fn is_local(self) -> bool {
78        self.is_local()
79    }
80
81    fn as_local(self) -> Option<LocalDefId> {
82        self.as_local()
83    }
84}
85
86impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
87    fn safe() -> Self {
88        hir::Safety::Safe
89    }
90
91    fn unsafe_mode() -> Self {
92        hir::Safety::Unsafe
93    }
94
95    fn is_safe(self) -> bool {
96        self.is_safe()
97    }
98
99    fn prefix_str(self) -> &'static str {
100        self.prefix_str()
101    }
102}
103
104impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_feature::Features {
105    fn generic_const_exprs(self) -> bool {
106        self.generic_const_exprs()
107    }
108
109    fn generic_const_args(self) -> bool {
110        self.generic_const_args()
111    }
112
113    fn coroutine_clone(self) -> bool {
114        self.coroutine_clone()
115    }
116
117    fn feature_bound_holds_in_crate(self, symbol: Symbol) -> bool {
118        // We don't consider feature bounds to hold in the crate when `staged_api` feature is
119        // enabled, even if it is enabled through `#[feature]`.
120        // This is to prevent accidentally leaking unstable APIs to stable.
121        !self.staged_api() && self.enabled(symbol)
122    }
123}
124
125impl<'tcx> rustc_type_ir::inherent::Span<TyCtxt<'tcx>> for Span {
126    fn dummy() -> Self {
127        DUMMY_SP
128    }
129}
130
131type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
132
133pub struct CtxtInterners<'tcx> {
134    /// The arena that types, regions, etc. are allocated from.
135    arena: &'tcx WorkerLocal<Arena<'tcx>>,
136
137    // Specifically use a speedy hash algorithm for these hash sets, since
138    // they're accessed quite often.
139    type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
140    const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
141    args: InternedSet<'tcx, GenericArgs<'tcx>>,
142    type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
143    canonical_var_kinds: InternedSet<'tcx, List<CanonicalVarKind<'tcx>>>,
144    region: InternedSet<'tcx, RegionKind<'tcx>>,
145    poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
146    predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
147    clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
148    projs: InternedSet<'tcx, List<ProjectionKind>>,
149    place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
150    const_: InternedSet<'tcx, WithCachedTypeInfo<ty::ConstKind<'tcx>>>,
151    pat: InternedSet<'tcx, PatternKind<'tcx>>,
152    const_allocation: InternedSet<'tcx, Allocation>,
153    bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind<'tcx>>>,
154    layout: InternedSet<'tcx, LayoutData<FieldIdx, VariantIdx>>,
155    adt_def: InternedSet<'tcx, AdtDefData>,
156    external_constraints: InternedSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
157    predefined_opaques_in_body: InternedSet<'tcx, List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>>,
158    fields: InternedSet<'tcx, List<FieldIdx>>,
159    local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
160    captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>,
161    valtree: InternedSet<'tcx, ty::ValTreeKind<TyCtxt<'tcx>>>,
162    patterns: InternedSet<'tcx, List<ty::Pattern<'tcx>>>,
163    outlives: InternedSet<'tcx, List<ty::ArgOutlivesPredicate<'tcx>>>,
164}
165
166impl<'tcx> CtxtInterners<'tcx> {
167    fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
168        // Default interner size - this value has been chosen empirically, and may need to be
169        // adjusted as the compiler evolves.
170        const N: usize = 2048;
171        CtxtInterners {
172            arena,
173            // The factors have been chosen by @FractalFir based on observed interner sizes, and
174            // local perf runs. To get the interner sizes, insert `eprintln` printing the size of
175            // the interner in functions like `intern_ty`. Bigger benchmarks tend to give more
176            // accurate ratios, so use something like `x perf eprintln --includes cargo`.
177            type_: InternedSet::with_capacity(N * 16),
178            const_lists: InternedSet::with_capacity(N * 4),
179            args: InternedSet::with_capacity(N * 4),
180            type_lists: InternedSet::with_capacity(N * 4),
181            region: InternedSet::with_capacity(N * 4),
182            poly_existential_predicates: InternedSet::with_capacity(N / 4),
183            canonical_var_kinds: InternedSet::with_capacity(N / 2),
184            predicate: InternedSet::with_capacity(N),
185            clauses: InternedSet::with_capacity(N),
186            projs: InternedSet::with_capacity(N * 4),
187            place_elems: InternedSet::with_capacity(N * 2),
188            const_: InternedSet::with_capacity(N * 2),
189            pat: InternedSet::with_capacity(N),
190            const_allocation: InternedSet::with_capacity(N),
191            bound_variable_kinds: InternedSet::with_capacity(N * 2),
192            layout: InternedSet::with_capacity(N),
193            adt_def: InternedSet::with_capacity(N),
194            external_constraints: InternedSet::with_capacity(N),
195            predefined_opaques_in_body: InternedSet::with_capacity(N),
196            fields: InternedSet::with_capacity(N * 4),
197            local_def_ids: InternedSet::with_capacity(N),
198            captures: InternedSet::with_capacity(N),
199            valtree: InternedSet::with_capacity(N),
200            patterns: InternedSet::with_capacity(N),
201            outlives: InternedSet::with_capacity(N),
202        }
203    }
204
205    /// Interns a type. (Use `mk_*` functions instead, where possible.)
206    #[allow(rustc::usage_of_ty_tykind)]
207    #[inline(never)]
208    fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> {
209        Ty(Interned::new_unchecked(
210            self.type_
211                .intern(kind, |kind| {
212                    let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_kind(&kind);
213                    InternedInSet(self.arena.alloc(WithCachedTypeInfo {
214                        internee: kind,
215                        flags: flags.flags,
216                        outer_exclusive_binder: flags.outer_exclusive_binder,
217                    }))
218                })
219                .0,
220        ))
221    }
222
223    /// Interns a const. (Use `mk_*` functions instead, where possible.)
224    #[allow(rustc::usage_of_ty_tykind)]
225    #[inline(never)]
226    fn intern_const(&self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
227        Const(Interned::new_unchecked(
228            self.const_
229                .intern(kind, |kind: ty::ConstKind<'_>| {
230                    let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_const_kind(&kind);
231                    InternedInSet(self.arena.alloc(WithCachedTypeInfo {
232                        internee: kind,
233                        flags: flags.flags,
234                        outer_exclusive_binder: flags.outer_exclusive_binder,
235                    }))
236                })
237                .0,
238        ))
239    }
240
241    /// Interns a predicate. (Use `mk_predicate` instead, where possible.)
242    #[inline(never)]
243    fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
244        Predicate(Interned::new_unchecked(
245            self.predicate
246                .intern(kind, |kind| {
247                    let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_predicate(kind);
248                    InternedInSet(self.arena.alloc(WithCachedTypeInfo {
249                        internee: kind,
250                        flags: flags.flags,
251                        outer_exclusive_binder: flags.outer_exclusive_binder,
252                    }))
253                })
254                .0,
255        ))
256    }
257
258    fn intern_clauses(&self, clauses: &[Clause<'tcx>]) -> Clauses<'tcx> {
259        if clauses.is_empty() {
260            ListWithCachedTypeInfo::empty()
261        } else {
262            self.clauses
263                .intern_ref(clauses, || {
264                    let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_clauses(clauses);
265
266                    InternedInSet(ListWithCachedTypeInfo::from_arena(
267                        &*self.arena,
268                        flags.into(),
269                        clauses,
270                    ))
271                })
272                .0
273        }
274    }
275}
276
277// For these preinterned values, an alternative would be to have
278// variable-length vectors that grow as needed. But that turned out to be
279// slightly more complex and no faster.
280
281const NUM_PREINTERNED_TY_VARS: u32 = 100;
282const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
283const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
284const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
285const NUM_PREINTERNED_ANON_BOUND_TYS_I: u32 = 3;
286
287// From general profiling of the *max vars during canonicalization* of a value:
288// - about 90% of the time, there are no canonical vars
289// - about 9% of the time, there is only one canonical var
290// - there are rarely more than 3-5 canonical vars (with exceptions in particularly pathological
291//   cases)
292// This may not match the number of bound vars found in `for`s.
293// Given that this is all heap interned, it seems likely that interning fewer
294// vars here won't make an appreciable difference. Though, if we were to inline the data (in an
295// array), we may want to consider reducing the number for canonicalized vars down to 4 or so.
296const NUM_PREINTERNED_ANON_BOUND_TYS_V: u32 = 20;
297
298// This number may seem high, but it is reached in all but the smallest crates.
299const NUM_PREINTERNED_RE_VARS: u32 = 500;
300const NUM_PREINTERNED_ANON_RE_BOUNDS_I: u32 = 3;
301const NUM_PREINTERNED_ANON_RE_BOUNDS_V: u32 = 20;
302
303pub struct CommonTypes<'tcx> {
304    pub unit: Ty<'tcx>,
305    pub bool: Ty<'tcx>,
306    pub char: Ty<'tcx>,
307    pub isize: Ty<'tcx>,
308    pub i8: Ty<'tcx>,
309    pub i16: Ty<'tcx>,
310    pub i32: Ty<'tcx>,
311    pub i64: Ty<'tcx>,
312    pub i128: Ty<'tcx>,
313    pub usize: Ty<'tcx>,
314    pub u8: Ty<'tcx>,
315    pub u16: Ty<'tcx>,
316    pub u32: Ty<'tcx>,
317    pub u64: Ty<'tcx>,
318    pub u128: Ty<'tcx>,
319    pub f16: Ty<'tcx>,
320    pub f32: Ty<'tcx>,
321    pub f64: Ty<'tcx>,
322    pub f128: Ty<'tcx>,
323    pub str_: Ty<'tcx>,
324    pub never: Ty<'tcx>,
325    pub self_param: Ty<'tcx>,
326
327    /// Dummy type used for the `Self` of a `TraitRef` created for converting
328    /// a trait object, and which gets removed in `ExistentialTraitRef`.
329    /// This type must not appear anywhere in other converted types.
330    /// `Infer(ty::FreshTy(0))` does the job.
331    pub trait_object_dummy_self: Ty<'tcx>,
332
333    /// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
334    pub ty_vars: Vec<Ty<'tcx>>,
335
336    /// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
337    pub fresh_tys: Vec<Ty<'tcx>>,
338
339    /// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
340    pub fresh_int_tys: Vec<Ty<'tcx>>,
341
342    /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
343    pub fresh_float_tys: Vec<Ty<'tcx>>,
344
345    /// Pre-interned values of the form:
346    /// `Bound(BoundVarIndexKind::Bound(DebruijnIndex(i)), BoundTy { var: v, kind:
347    /// BoundTyKind::Anon})` for small values of `i` and `v`.
348    pub anon_bound_tys: Vec<Vec<Ty<'tcx>>>,
349
350    // Pre-interned values of the form:
351    // `Bound(BoundVarIndexKind::Canonical, BoundTy { var: v, kind: BoundTyKind::Anon })`
352    // for small values of `v`.
353    pub anon_canonical_bound_tys: Vec<Ty<'tcx>>,
354}
355
356pub struct CommonLifetimes<'tcx> {
357    /// `ReStatic`
358    pub re_static: Region<'tcx>,
359
360    /// Erased region, used outside of type inference.
361    pub re_erased: Region<'tcx>,
362
363    /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
364    pub re_vars: Vec<Region<'tcx>>,
365
366    /// Pre-interned values of the form:
367    /// `ReBound(BoundVarIndexKind::Bound(DebruijnIndex(i)), BoundRegion { var: v, kind: BoundRegionKind::Anon })`
368    /// for small values of `i` and `v`.
369    pub anon_re_bounds: Vec<Vec<Region<'tcx>>>,
370
371    // Pre-interned values of the form:
372    // `ReBound(BoundVarIndexKind::Canonical, BoundRegion { var: v, kind: BoundRegionKind::Anon })`
373    // for small values of `v`.
374    pub anon_re_canonical_bounds: Vec<Region<'tcx>>,
375}
376
377pub struct CommonConsts<'tcx> {
378    pub unit: Const<'tcx>,
379    pub true_: Const<'tcx>,
380    pub false_: Const<'tcx>,
381    /// Use [`ty::ValTree::zst`] instead.
382    pub(crate) valtree_zst: ValTree<'tcx>,
383}
384
385impl<'tcx> CommonTypes<'tcx> {
386    fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
387        let mk = |ty| interners.intern_ty(ty);
388
389        let ty_vars =
390            (0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect();
391        let fresh_tys: Vec<_> =
392            (0..NUM_PREINTERNED_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect();
393        let fresh_int_tys: Vec<_> =
394            (0..NUM_PREINTERNED_FRESH_INT_TYS).map(|n| mk(Infer(ty::FreshIntTy(n)))).collect();
395        let fresh_float_tys: Vec<_> =
396            (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect();
397
398        let anon_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_I)
399            .map(|i| {
400                (0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
401                    .map(|v| {
402                        mk(ty::Bound(
403                            ty::BoundVarIndexKind::Bound(ty::DebruijnIndex::from(i)),
404                            ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon },
405                        ))
406                    })
407                    .collect()
408            })
409            .collect();
410
411        let anon_canonical_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
412            .map(|v| {
413                mk(ty::Bound(
414                    ty::BoundVarIndexKind::Canonical,
415                    ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon },
416                ))
417            })
418            .collect();
419
420        CommonTypes {
421            unit: mk(Tuple(List::empty())),
422            bool: mk(Bool),
423            char: mk(Char),
424            never: mk(Never),
425            isize: mk(Int(ty::IntTy::Isize)),
426            i8: mk(Int(ty::IntTy::I8)),
427            i16: mk(Int(ty::IntTy::I16)),
428            i32: mk(Int(ty::IntTy::I32)),
429            i64: mk(Int(ty::IntTy::I64)),
430            i128: mk(Int(ty::IntTy::I128)),
431            usize: mk(Uint(ty::UintTy::Usize)),
432            u8: mk(Uint(ty::UintTy::U8)),
433            u16: mk(Uint(ty::UintTy::U16)),
434            u32: mk(Uint(ty::UintTy::U32)),
435            u64: mk(Uint(ty::UintTy::U64)),
436            u128: mk(Uint(ty::UintTy::U128)),
437            f16: mk(Float(ty::FloatTy::F16)),
438            f32: mk(Float(ty::FloatTy::F32)),
439            f64: mk(Float(ty::FloatTy::F64)),
440            f128: mk(Float(ty::FloatTy::F128)),
441            str_: mk(Str),
442            self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
443
444            trait_object_dummy_self: fresh_tys[0],
445
446            ty_vars,
447            fresh_tys,
448            fresh_int_tys,
449            fresh_float_tys,
450            anon_bound_tys,
451            anon_canonical_bound_tys,
452        }
453    }
454}
455
456impl<'tcx> CommonLifetimes<'tcx> {
457    fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> {
458        let mk = |r| {
459            Region(Interned::new_unchecked(
460                interners.region.intern(r, |r| InternedInSet(interners.arena.alloc(r))).0,
461            ))
462        };
463
464        let re_vars =
465            (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
466
467        let anon_re_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_I)
468            .map(|i| {
469                (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
470                    .map(|v| {
471                        mk(ty::ReBound(
472                            ty::BoundVarIndexKind::Bound(ty::DebruijnIndex::from(i)),
473                            ty::BoundRegion {
474                                var: ty::BoundVar::from(v),
475                                kind: ty::BoundRegionKind::Anon,
476                            },
477                        ))
478                    })
479                    .collect()
480            })
481            .collect();
482
483        let anon_re_canonical_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
484            .map(|v| {
485                mk(ty::ReBound(
486                    ty::BoundVarIndexKind::Canonical,
487                    ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BoundRegionKind::Anon },
488                ))
489            })
490            .collect();
491
492        CommonLifetimes {
493            re_static: mk(ty::ReStatic),
494            re_erased: mk(ty::ReErased),
495            re_vars,
496            anon_re_bounds,
497            anon_re_canonical_bounds,
498        }
499    }
500}
501
502impl<'tcx> CommonConsts<'tcx> {
503    fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
504        let mk_const = |c| interners.intern_const(c);
505
506        let mk_valtree = |v| {
507            ty::ValTree(Interned::new_unchecked(
508                interners.valtree.intern(v, |v| InternedInSet(interners.arena.alloc(v))).0,
509            ))
510        };
511
512        let valtree_zst = mk_valtree(ty::ValTreeKind::Branch(List::empty()));
513        let valtree_true = mk_valtree(ty::ValTreeKind::Leaf(ty::ScalarInt::TRUE));
514        let valtree_false = mk_valtree(ty::ValTreeKind::Leaf(ty::ScalarInt::FALSE));
515
516        CommonConsts {
517            unit: mk_const(ty::ConstKind::Value(ty::Value {
518                ty: types.unit,
519                valtree: valtree_zst,
520            })),
521            true_: mk_const(ty::ConstKind::Value(ty::Value {
522                ty: types.bool,
523                valtree: valtree_true,
524            })),
525            false_: mk_const(ty::ConstKind::Value(ty::Value {
526                ty: types.bool,
527                valtree: valtree_false,
528            })),
529            valtree_zst,
530        }
531    }
532}
533
534/// This struct contains information regarding a free parameter region,
535/// either a `ReEarlyParam` or `ReLateParam`.
536#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FreeRegionInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "FreeRegionInfo", "scope", &self.scope, "region_def_id",
            &self.region_def_id, "is_impl_item", &&self.is_impl_item)
    }
}Debug)]
537pub struct FreeRegionInfo {
538    /// `LocalDefId` of the scope.
539    pub scope: LocalDefId,
540    /// the `DefId` of the free region.
541    pub region_def_id: DefId,
542    /// checks if bound region is in Impl Item
543    pub is_impl_item: bool,
544}
545
546/// This struct should only be created by `create_def`.
547#[derive(#[automatically_derived]
impl<'tcx, K: ::core::marker::Copy + Copy> ::core::marker::Copy for
    TyCtxtFeed<'tcx, K> {
}Copy, #[automatically_derived]
impl<'tcx, K: ::core::clone::Clone + Copy> ::core::clone::Clone for
    TyCtxtFeed<'tcx, K> {
    #[inline]
    fn clone(&self) -> TyCtxtFeed<'tcx, K> {
        TyCtxtFeed {
            tcx: ::core::clone::Clone::clone(&self.tcx),
            key: ::core::clone::Clone::clone(&self.key),
        }
    }
}Clone)]
548pub struct TyCtxtFeed<'tcx, K: Copy> {
549    pub tcx: TyCtxt<'tcx>,
550    // Do not allow direct access, as downstream code must not mutate this field.
551    key: K,
552}
553
554/// Only queries that create a `DefId` are allowed to feed queries for that `DefId`.
555impl<K: Copy> !StableHash for TyCtxtFeed<'_, K> {}
556
557/// Some workarounds to use cases that cannot use `create_def`.
558/// Do not add new ways to create `TyCtxtFeed` without consulting
559/// with T-compiler and making an analysis about why your addition
560/// does not cause incremental compilation issues.
561impl<'tcx> TyCtxt<'tcx> {
562    /// Can only be fed before queries are run, and is thus exempt from any
563    /// incremental issues. Do not use except for the initial query feeding.
564    pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
565        self.dep_graph.assert_ignored();
566        TyCtxtFeed { tcx: self, key: () }
567    }
568
569    /// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed
570    /// some queries for it. It will panic if used twice.
571    pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> {
572        let key = self.untracked().source_span.push(span);
573        match (&key, &CRATE_DEF_ID) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(key, CRATE_DEF_ID);
574        TyCtxtFeed { tcx: self, key }
575    }
576
577    /// In order to break cycles involving `AnonConst`, we need to set the expected type by side
578    /// effect. However, we do not want this as a general capability, so this interface restricts
579    /// to the only allowed case.
580    pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<'tcx, Ty<'tcx>>) {
581        if true {
    match (&self.def_kind(key), &DefKind::AnonConst) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    };
};debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
582        TyCtxtFeed { tcx: self, key }.type_of(value)
583    }
584
585    /// Feeds the HIR delayed owner during AST -> HIR delayed lowering.
586    pub fn feed_delayed_owner(self, key: LocalDefId, owner: MaybeOwner<'tcx>) {
587        self.dep_graph.assert_ignored();
588        TyCtxtFeed { tcx: self, key }.delayed_owner(owner);
589    }
590
591    // Trait impl item visibility is inherited from its trait when not specified
592    // explicitly. In that case we cannot determine it in early resolve,
593    // but instead are feeding it in late resolve, where we don't have access to the
594    // `TyCtxtFeed` anymore.
595    // To avoid having to hash the `LocalDefId` multiple times for inserting and removing the
596    // `TyCtxtFeed` from a hash table, we add this hack to feed the visibility.
597    // Do not use outside of the resolver query.
598    pub fn feed_visibility_for_trait_impl_item(self, key: LocalDefId, vis: ty::Visibility) {
599        if truecfg!(debug_assertions) {
600            match self.def_kind(self.local_parent(key)) {
601                DefKind::Impl { of_trait: true } => {}
602                other => crate::util::bug::bug_fmt(format_args!("{0:?} is not an assoc item of a trait impl: {1:?}",
        key, other))bug!("{key:?} is not an assoc item of a trait impl: {other:?}"),
603            }
604        }
605        TyCtxtFeed { tcx: self, key }.visibility(vis.to_def_id())
606    }
607}
608
609impl<'tcx, K: Copy> TyCtxtFeed<'tcx, K> {
610    #[inline(always)]
611    pub fn key(&self) -> K {
612        self.key
613    }
614}
615
616impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
617    #[inline(always)]
618    pub fn def_id(&self) -> LocalDefId {
619        self.key
620    }
621
622    // Caller must ensure that `self.key` ID is indeed an owner.
623    pub fn feed_owner_id(&self) -> TyCtxtFeed<'tcx, hir::OwnerId> {
624        TyCtxtFeed { tcx: self.tcx, key: hir::OwnerId { def_id: self.key } }
625    }
626
627    // Fills in all the important parts needed by HIR queries
628    pub fn feed_hir(&self) {
629        self.local_def_id_to_hir_id(HirId::make_owner(self.def_id()));
630        self.opt_hir_owner_nodes(Some(self.tcx.arena.alloc(hir::OwnerNodes::synthetic())));
631        self.feed_owner_id().hir_attr_map(hir::AttributeMap::EMPTY);
632    }
633}
634
635/// The central data structure of the compiler. It stores references
636/// to the various **arenas** and also houses the results of the
637/// various **compiler queries** that have been performed. See the
638/// [rustc dev guide] for more details.
639///
640/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
641///
642/// An implementation detail: `TyCtxt` is a wrapper type for [GlobalCtxt],
643/// which is the struct that actually holds all the data. `TyCtxt` derefs to
644/// `GlobalCtxt`, and in practice `TyCtxt` is passed around everywhere, and all
645/// operations are done via `TyCtxt`. A `TyCtxt` is obtained for a `GlobalCtxt`
646/// by calling `enter` with a closure `f`. That function creates both the
647/// `TyCtxt`, and an `ImplicitCtxt` around it that is put into TLS. Within `f`:
648/// - The `ImplicitCtxt` is available implicitly via TLS.
649/// - The `TyCtxt` is available explicitly via the `tcx` parameter, and also
650///   implicitly within the `ImplicitCtxt`. Explicit access is preferred when
651///   possible.
652#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for TyCtxt<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for TyCtxt<'tcx> {
    #[inline]
    fn clone(&self) -> TyCtxt<'tcx> {
        let _: ::core::clone::AssertParamIsClone<&'tcx GlobalCtxt<'tcx>>;
        *self
    }
}Clone)]
653#[rustc_diagnostic_item = "TyCtxt"]
654#[rustc_pass_by_value]
655pub struct TyCtxt<'tcx> {
656    gcx: &'tcx GlobalCtxt<'tcx>,
657}
658
659// Explicitly implement `DynSync` and `DynSend` for `TyCtxt` to short circuit trait resolution. Its
660// field are asserted to implement these traits below, so this is trivially safe, and it greatly
661// speeds-up compilation of this crate and its dependents.
662unsafe impl DynSend for TyCtxt<'_> {}
663unsafe impl DynSync for TyCtxt<'_> {}
664fn _assert_tcx_fields() {
665    sync::assert_dyn_sync::<&'_ GlobalCtxt<'_>>();
666    sync::assert_dyn_send::<&'_ GlobalCtxt<'_>>();
667}
668
669impl<'tcx> Deref for TyCtxt<'tcx> {
670    type Target = &'tcx GlobalCtxt<'tcx>;
671    #[inline(always)]
672    fn deref(&self) -> &Self::Target {
673        &self.gcx
674    }
675}
676
677/// See [TyCtxt] for details about this type.
678pub struct GlobalCtxt<'tcx> {
679    pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
680    pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
681
682    interners: CtxtInterners<'tcx>,
683
684    pub sess: &'tcx Session,
685    crate_types: Vec<CrateType>,
686    /// The `stable_crate_id` is constructed out of the crate name and all the
687    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
688    /// global identifier for the crate. It is used to allow multiple crates
689    /// with the same name to coexist. See the
690    /// `rustc_symbol_mangling` crate for more information.
691    stable_crate_id: StableCrateId,
692
693    pub dep_graph: DepGraph,
694
695    pub prof: SelfProfilerRef,
696
697    /// Common types, pre-interned for your convenience.
698    pub types: CommonTypes<'tcx>,
699
700    /// Common lifetimes, pre-interned for your convenience.
701    pub lifetimes: CommonLifetimes<'tcx>,
702
703    /// Common consts, pre-interned for your convenience.
704    pub consts: CommonConsts<'tcx>,
705
706    /// Hooks to be able to register functions in other crates that can then still
707    /// be called from rustc_middle.
708    pub(crate) hooks: crate::hooks::Providers,
709
710    untracked: Untracked,
711
712    pub query_system: QuerySystem<'tcx>,
713    pub(crate) dep_kind_vtables: &'tcx [DepKindVTable<'tcx>],
714
715    // Internal caches for metadata decoding. No need to track deps on this.
716    pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
717
718    /// Caches the results of trait selection. This cache is used
719    /// for things that do not have to do with the parameters in scope.
720    pub selection_cache: traits::SelectionCache<'tcx, ty::TypingEnv<'tcx>>,
721
722    /// Caches the results of trait evaluation. This cache is used
723    /// for things that do not have to do with the parameters in scope.
724    /// Merge this with `selection_cache`?
725    pub evaluation_cache: traits::EvaluationCache<'tcx, ty::TypingEnv<'tcx>>,
726
727    /// Caches the results of goal evaluation in the new solver.
728    pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
729    pub new_solver_canonical_param_env_cache:
730        Lock<FxHashMap<ty::ParamEnv<'tcx>, ty::CanonicalParamEnvCacheEntry<TyCtxt<'tcx>>>>,
731
732    pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
733
734    /// Caches the index of the highest bound var in clauses in a canonical binder.
735    pub highest_var_in_clauses_cache: Lock<FxHashMap<ty::Clauses<'tcx>, usize>>,
736    /// Caches the instantiation of a canonical binder given a set of args.
737    pub clauses_cache:
738        Lock<FxHashMap<(ty::Clauses<'tcx>, &'tcx [ty::GenericArg<'tcx>]), ty::Clauses<'tcx>>>,
739
740    /// Data layout specification for the current target.
741    pub data_layout: TargetDataLayout,
742
743    /// Stores memory for globals (statics/consts).
744    pub(crate) alloc_map: interpret::AllocMap<'tcx>,
745
746    current_gcx: CurrentGcx,
747
748    /// A jobserver reference used to release then acquire a token while waiting on a query.
749    pub jobserver_proxy: Arc<Proxy>,
750}
751
752impl<'tcx> GlobalCtxt<'tcx> {
753    /// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
754    /// `f`.
755    pub fn enter<F, R>(&'tcx self, f: F) -> R
756    where
757        F: FnOnce(TyCtxt<'tcx>) -> R,
758    {
759        let icx = tls::ImplicitCtxt::new(self);
760
761        // Reset `current_gcx` to `None` when we exit.
762        let _on_drop = defer(move || {
763            *self.current_gcx.value.write() = None;
764        });
765
766        // Set this `GlobalCtxt` as the current one.
767        {
768            let mut guard = self.current_gcx.value.write();
769            if !guard.is_none() {
    {
        ::core::panicking::panic_fmt(format_args!("no `GlobalCtxt` is currently set"));
    }
};assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
770            *guard = Some(self as *const _ as *const ());
771        }
772
773        tls::enter_context(&icx, || f(icx.tcx))
774    }
775}
776
777/// This is used to get a reference to a `GlobalCtxt` if one is available.
778///
779/// This is needed to allow the deadlock handler access to `GlobalCtxt` to look for query cycles.
780/// It cannot use the `TLV` global because that's only guaranteed to be defined on the thread
781/// creating the `GlobalCtxt`. Other threads have access to the `TLV` only inside Rayon jobs, but
782/// the deadlock handler is not called inside such a job.
783#[derive(#[automatically_derived]
impl ::core::clone::Clone for CurrentGcx {
    #[inline]
    fn clone(&self) -> CurrentGcx {
        CurrentGcx { value: ::core::clone::Clone::clone(&self.value) }
    }
}Clone)]
784pub struct CurrentGcx {
785    /// This stores a pointer to a `GlobalCtxt`. This is set to `Some` inside `GlobalCtxt::enter`
786    /// and reset to `None` when that function returns or unwinds.
787    value: Arc<RwLock<Option<*const ()>>>,
788}
789
790unsafe impl DynSend for CurrentGcx {}
791unsafe impl DynSync for CurrentGcx {}
792
793impl CurrentGcx {
794    pub fn new() -> Self {
795        Self { value: Arc::new(RwLock::new(None)) }
796    }
797
798    pub fn access<R>(&self, f: impl for<'tcx> FnOnce(&'tcx GlobalCtxt<'tcx>) -> R) -> R {
799        let read_guard = self.value.read();
800        let gcx: *const GlobalCtxt<'_> = read_guard.unwrap() as *const _;
801        // SAFETY: We hold the read lock for the `GlobalCtxt` pointer. That prevents
802        // `GlobalCtxt::enter` from returning as it would first acquire the write lock.
803        // This ensures the `GlobalCtxt` is live during `f`.
804        f(unsafe { &*gcx })
805    }
806}
807
808impl<'tcx> TyCtxt<'tcx> {
809    pub fn has_typeck_results(self, def_id: LocalDefId) -> bool {
810        // Closures' typeck results come from their outermost function,
811        // as they are part of the same "inference environment".
812        let root = self.typeck_root_def_id_local(def_id);
813        self.hir_node_by_def_id(root).body_id().is_some()
814    }
815
816    /// Expects a body and returns its codegen attributes.
817    ///
818    /// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
819    /// constants.
820    pub fn body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs {
821        let def_kind = self.def_kind(def_id);
822        if def_kind.has_codegen_attrs() {
823            self.codegen_fn_attrs(def_id)
824        } else if #[allow(non_exhaustive_omitted_patterns)] match def_kind {
    DefKind::AnonConst | DefKind::AssocConst { .. } | DefKind::Const { .. } |
        DefKind::InlineConst | DefKind::GlobalAsm => true,
    _ => false,
}matches!(
825            def_kind,
826            DefKind::AnonConst
827                | DefKind::AssocConst { .. }
828                | DefKind::Const { .. }
829                | DefKind::InlineConst
830                | DefKind::GlobalAsm
831        ) {
832            CodegenFnAttrs::EMPTY
833        } else {
834            crate::util::bug::bug_fmt(format_args!("body_codegen_fn_attrs called on unexpected definition: {0:?} {1:?}",
        def_id, def_kind))bug!(
835                "body_codegen_fn_attrs called on unexpected definition: {:?} {:?}",
836                def_id,
837                def_kind
838            )
839        }
840    }
841
842    pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
843        self.arena.alloc(Steal::new(thir))
844    }
845
846    pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
847        self.arena.alloc(Steal::new(mir))
848    }
849
850    pub fn alloc_steal_promoted(
851        self,
852        promoted: IndexVec<Promoted, Body<'tcx>>,
853    ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
854        self.arena.alloc(Steal::new(promoted))
855    }
856
857    pub fn mk_adt_def(
858        self,
859        did: DefId,
860        kind: AdtKind,
861        variants: IndexVec<VariantIdx, ty::VariantDef>,
862        repr: ReprOptions,
863    ) -> ty::AdtDef<'tcx> {
864        self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
865    }
866
867    /// Allocates a read-only byte or string literal for `mir::interpret` with alignment 1.
868    /// Returns the same `AllocId` if called again with the same bytes.
869    pub fn allocate_bytes_dedup<'a>(
870        self,
871        bytes: impl Into<Cow<'a, [u8]>>,
872        salt: usize,
873    ) -> interpret::AllocId {
874        // Create an allocation that just contains these bytes.
875        let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes, ());
876        let alloc = self.mk_const_alloc(alloc);
877        self.reserve_and_set_memory_dedup(alloc, salt)
878    }
879
880    /// Traits added on all bounds by default, excluding `Sized` which is treated separately.
881    pub fn default_traits(self) -> &'static [rustc_hir::LangItem] {
882        if self.sess.opts.unstable_opts.experimental_default_bounds {
883            &[
884                LangItem::DefaultTrait1,
885                LangItem::DefaultTrait2,
886                LangItem::DefaultTrait3,
887                LangItem::DefaultTrait4,
888            ]
889        } else {
890            &[]
891        }
892    }
893
894    pub fn is_default_trait(self, def_id: DefId) -> bool {
895        self.default_traits().iter().any(|&default_trait| self.is_lang_item(def_id, default_trait))
896    }
897
898    pub fn is_sizedness_trait(self, def_id: DefId) -> bool {
899        #[allow(non_exhaustive_omitted_patterns)] match self.as_lang_item(def_id) {
    Some(LangItem::Sized | LangItem::MetaSized) => true,
    _ => false,
}matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
900    }
901
902    pub fn lift<T: Lift<TyCtxt<'tcx>>>(self, value: T) -> T::Lifted {
903        value.lift_to_interner(self)
904    }
905
906    /// Creates a type context. To use the context call `fn enter` which
907    /// provides a `TyCtxt`.
908    ///
909    /// By only providing the `TyCtxt` inside of the closure we enforce that the type
910    /// context and any interned value (types, args, etc.) can only be used while `ty::tls`
911    /// has a valid reference to the context, to allow formatting values that need it.
912    pub fn create_global_ctxt<T>(
913        gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
914        sess: &'tcx Session,
915        crate_types: Vec<CrateType>,
916        stable_crate_id: StableCrateId,
917        arena: &'tcx WorkerLocal<Arena<'tcx>>,
918        hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
919        untracked: Untracked,
920        dep_graph: DepGraph,
921        dep_kind_vtables: &'tcx [DepKindVTable<'tcx>],
922        query_system: QuerySystem<'tcx>,
923        hooks: crate::hooks::Providers,
924        current_gcx: CurrentGcx,
925        jobserver_proxy: Arc<Proxy>,
926        f: impl FnOnce(TyCtxt<'tcx>) -> T,
927    ) -> T {
928        let data_layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
929            sess.dcx().emit_fatal(err);
930        });
931        let interners = CtxtInterners::new(arena);
932        let common_types = CommonTypes::new(&interners);
933        let common_lifetimes = CommonLifetimes::new(&interners);
934        let common_consts = CommonConsts::new(&interners, &common_types);
935
936        let gcx = gcx_cell.get_or_init(|| GlobalCtxt {
937            sess,
938            crate_types,
939            stable_crate_id,
940            arena,
941            hir_arena,
942            interners,
943            dep_graph,
944            hooks,
945            prof: sess.prof.clone(),
946            types: common_types,
947            lifetimes: common_lifetimes,
948            consts: common_consts,
949            untracked,
950            query_system,
951            dep_kind_vtables,
952            ty_rcache: Default::default(),
953            selection_cache: Default::default(),
954            evaluation_cache: Default::default(),
955            new_solver_evaluation_cache: Default::default(),
956            new_solver_canonical_param_env_cache: Default::default(),
957            canonical_param_env_cache: Default::default(),
958            highest_var_in_clauses_cache: Default::default(),
959            clauses_cache: Default::default(),
960            data_layout,
961            alloc_map: interpret::AllocMap::new(),
962            current_gcx,
963            jobserver_proxy,
964        });
965
966        // This is a separate function to work around a crash with parallel rustc (#135870)
967        gcx.enter(f)
968    }
969
970    /// Obtain all lang items of this crate and all dependencies (recursively)
971    pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
972        self.get_lang_items(())
973    }
974
975    /// Gets a `Ty` representing the [`LangItem::OrderingEnum`]
976    #[track_caller]
977    pub fn ty_ordering_enum(self, span: Span) -> Ty<'tcx> {
978        let ordering_enum = self.require_lang_item(hir::LangItem::OrderingEnum, span);
979        self.type_of(ordering_enum).no_bound_vars().unwrap()
980    }
981
982    /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
983    /// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
984    pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
985        self.all_diagnostic_items(()).name_to_id.get(&name).copied()
986    }
987
988    /// Obtain the diagnostic item's name
989    pub fn get_diagnostic_name(self, id: DefId) -> Option<Symbol> {
990        self.diagnostic_items(id.krate).id_to_name.get(&id).copied()
991    }
992
993    /// Check whether the diagnostic item with the given `name` has the given `DefId`.
994    pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool {
995        self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
996    }
997
998    pub fn is_coroutine(self, def_id: DefId) -> bool {
999        self.coroutine_kind(def_id).is_some()
1000    }
1001
1002    pub fn is_async_drop_in_place_coroutine(self, def_id: DefId) -> bool {
1003        self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace)
1004    }
1005
1006    pub fn type_const_span(self, def_id: DefId) -> Option<Span> {
1007        if !self.is_type_const(def_id) {
1008            return None;
1009        }
1010        Some(self.def_span(def_id))
1011    }
1012
1013    /// Check if the given `def_id` is a `type const` (mgca)
1014    pub fn is_type_const(self, def_id: impl IntoQueryKey<DefId>) -> bool {
1015        let def_id = def_id.into_query_key();
1016        match self.def_kind(def_id) {
1017            DefKind::Const { is_type_const } | DefKind::AssocConst { is_type_const } => {
1018                is_type_const
1019            }
1020            _ => false,
1021        }
1022    }
1023
1024    /// Returns the movability of the coroutine of `def_id`, or panics
1025    /// if given a `def_id` that is not a coroutine.
1026    pub fn coroutine_movability(self, def_id: DefId) -> hir::Movability {
1027        self.coroutine_kind(def_id).expect("expected a coroutine").movability()
1028    }
1029
1030    /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct.
1031    pub fn coroutine_is_async(self, def_id: DefId) -> bool {
1032        #[allow(non_exhaustive_omitted_patterns)] match self.coroutine_kind(def_id) {
    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) =>
        true,
    _ => false,
}matches!(
1033            self.coroutine_kind(def_id),
1034            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _))
1035        )
1036    }
1037
1038    // Whether the body owner is synthetic, which in this case means it does not correspond to
1039    // meaningful HIR. This is currently used to skip over MIR borrowck.
1040    pub fn is_synthetic_mir(self, def_id: impl Into<DefId>) -> bool {
1041        #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(def_id.into()) {
    DefKind::SyntheticCoroutineBody => true,
    _ => false,
}matches!(self.def_kind(def_id.into()), DefKind::SyntheticCoroutineBody)
1042    }
1043
1044    /// Returns `true` if the node pointed to by `def_id` is a general coroutine that implements `Coroutine`.
1045    /// This means it is neither an `async` or `gen` construct.
1046    pub fn is_general_coroutine(self, def_id: DefId) -> bool {
1047        #[allow(non_exhaustive_omitted_patterns)] match self.coroutine_kind(def_id) {
    Some(hir::CoroutineKind::Coroutine(_)) => true,
    _ => false,
}matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Coroutine(_)))
1048    }
1049
1050    /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `gen` construct.
1051    pub fn coroutine_is_gen(self, def_id: DefId) -> bool {
1052        #[allow(non_exhaustive_omitted_patterns)] match self.coroutine_kind(def_id) {
    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) =>
        true,
    _ => false,
}matches!(
1053            self.coroutine_kind(def_id),
1054            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
1055        )
1056    }
1057
1058    /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `async gen` construct.
1059    pub fn coroutine_is_async_gen(self, def_id: DefId) -> bool {
1060        #[allow(non_exhaustive_omitted_patterns)] match self.coroutine_kind(def_id) {
    Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _))
        => true,
    _ => false,
}matches!(
1061            self.coroutine_kind(def_id),
1062            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _))
1063        )
1064    }
1065
1066    pub fn features(self) -> &'tcx rustc_feature::Features {
1067        self.features_query(())
1068    }
1069
1070    pub fn def_key(self, id: impl IntoQueryKey<DefId>) -> rustc_hir::definitions::DefKey {
1071        let id = id.into_query_key();
1072        // Accessing the DefKey is ok, since it is part of DefPathHash.
1073        if let Some(id) = id.as_local() {
1074            self.definitions_untracked().def_key(id)
1075        } else {
1076            self.cstore_untracked().def_key(id)
1077        }
1078    }
1079
1080    /// Converts a `DefId` into its fully expanded `DefPath` (every
1081    /// `DefId` is really just an interned `DefPath`).
1082    ///
1083    /// Note that if `id` is not local to this crate, the result will
1084    ///  be a non-local `DefPath`.
1085    pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
1086        // Accessing the DefPath is ok, since it is part of DefPathHash.
1087        if let Some(id) = id.as_local() {
1088            self.definitions_untracked().def_path(id)
1089        } else {
1090            self.cstore_untracked().def_path(id)
1091        }
1092    }
1093
1094    #[inline]
1095    pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
1096        // Accessing the DefPathHash is ok, it is incr. comp. stable.
1097        if let Some(def_id) = def_id.as_local() {
1098            self.definitions_untracked().def_path_hash(def_id)
1099        } else {
1100            self.cstore_untracked().def_path_hash(def_id)
1101        }
1102    }
1103
1104    #[inline]
1105    pub fn crate_types(self) -> &'tcx [CrateType] {
1106        &self.crate_types
1107    }
1108
1109    pub fn needs_metadata(self) -> bool {
1110        self.crate_types().iter().any(|ty| match *ty {
1111            CrateType::Executable
1112            | CrateType::StaticLib
1113            | CrateType::Cdylib
1114            | CrateType::Sdylib => false,
1115            CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
1116        })
1117    }
1118
1119    pub fn needs_hir_hash(self) -> bool {
1120        // Why is the hir hash needed for these configurations?
1121        // - debug_assertions: for the "fingerprint the result" check in
1122        //   `rustc_query_impl::execution::execute_job`.
1123        // - incremental: for query lookups.
1124        // - needs_metadata: it is included in the crate metadata through the crate_hash query
1125        // - instrument_coverage: for putting into coverage data (see
1126        //   `hash_mir_source`).
1127        // - metrics_dir: metrics use the strict version hash in the filenames
1128        //   for dumped metrics files to prevent overwriting distinct metrics
1129        //   for similar source builds (may change in the future, this is part
1130        //   of the proof of concept impl for the metrics initiative project goal)
1131        truecfg!(debug_assertions)
1132            || self.sess.opts.incremental.is_some()
1133            || self.needs_metadata()
1134            || self.sess.instrument_coverage()
1135            || self.sess.opts.unstable_opts.metrics_dir.is_some()
1136    }
1137
1138    #[inline]
1139    pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
1140        if crate_num == LOCAL_CRATE {
1141            self.stable_crate_id
1142        } else {
1143            self.cstore_untracked().stable_crate_id(crate_num)
1144        }
1145    }
1146
1147    /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
1148    /// that the crate in question has already been loaded by the CrateStore.
1149    #[inline]
1150    pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
1151        if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
1152            LOCAL_CRATE
1153        } else {
1154            *self
1155                .untracked()
1156                .stable_crate_ids
1157                .read()
1158                .get(&stable_crate_id)
1159                .unwrap_or_else(|| crate::util::bug::bug_fmt(format_args!("uninterned StableCrateId: {0:?}",
        stable_crate_id))bug!("uninterned StableCrateId: {stable_crate_id:?}"))
1160        }
1161    }
1162
1163    /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
1164    /// session, if it still exists. This is used during incremental compilation to
1165    /// turn a deserialized `DefPathHash` into its current `DefId`.
1166    pub fn def_path_hash_to_def_id(self, hash: DefPathHash) -> Option<DefId> {
1167        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/context.rs:1167",
                        "rustc_middle::ty::context", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/context.rs"),
                        ::tracing_core::__macro_support::Option::Some(1167u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::context"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("def_path_hash_to_def_id({0:?})",
                                                    hash) as &dyn Value))])
            });
    } else { ; }
};debug!("def_path_hash_to_def_id({:?})", hash);
1168
1169        let stable_crate_id = hash.stable_crate_id();
1170
1171        // If this is a DefPathHash from the local crate, we can look up the
1172        // DefId in the tcx's `Definitions`.
1173        if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) {
1174            Some(self.untracked.definitions.read().local_def_path_hash_to_def_id(hash)?.to_def_id())
1175        } else {
1176            self.def_path_hash_to_def_id_extern(hash, stable_crate_id)
1177        }
1178    }
1179
1180    pub fn def_path_debug_str(self, def_id: DefId) -> String {
1181        // We are explicitly not going through queries here in order to get
1182        // crate name and stable crate id since this code is called from debug!()
1183        // statements within the query system and we'd run into endless
1184        // recursion otherwise.
1185        let (crate_name, stable_crate_id) = if def_id.is_local() {
1186            (self.crate_name(LOCAL_CRATE), self.stable_crate_id(LOCAL_CRATE))
1187        } else {
1188            let cstore = &*self.cstore_untracked();
1189            (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
1190        };
1191
1192        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}[{1:04x}]{2}", crate_name,
                stable_crate_id.as_u64() >> (8 * 6),
                self.def_path(def_id).to_string_no_crate_verbose()))
    })format!(
1193            "{}[{:04x}]{}",
1194            crate_name,
1195            // Don't print the whole stable crate id. That's just
1196            // annoying in debug output.
1197            stable_crate_id.as_u64() >> (8 * 6),
1198            self.def_path(def_id).to_string_no_crate_verbose()
1199        )
1200    }
1201
1202    pub fn dcx(self) -> DiagCtxtHandle<'tcx> {
1203        self.sess.dcx()
1204    }
1205
1206    /// Checks to see if the caller (`body_features`) has all the features required by the callee
1207    /// (`callee_features`).
1208    pub fn is_target_feature_call_safe(
1209        self,
1210        callee_features: &[TargetFeature],
1211        body_features: &[TargetFeature],
1212    ) -> bool {
1213        // If the called function has target features the calling function hasn't,
1214        // the call requires `unsafe`. Don't check this on wasm
1215        // targets, though. For more information on wasm see the
1216        // is_like_wasm check in hir_analysis/src/collect.rs
1217        self.sess.target.options.is_like_wasm
1218            || callee_features
1219                .iter()
1220                .all(|feature| body_features.iter().any(|f| f.name == feature.name))
1221    }
1222
1223    /// Returns the safe version of the signature of the given function, if calling it
1224    /// would be safe in the context of the given caller.
1225    pub fn adjust_target_feature_sig(
1226        self,
1227        fun_def: DefId,
1228        fun_sig: ty::Binder<'tcx, ty::FnSig<'tcx>>,
1229        caller: DefId,
1230    ) -> Option<ty::Binder<'tcx, ty::FnSig<'tcx>>> {
1231        let fun_features = &self.codegen_fn_attrs(fun_def).target_features;
1232        let caller_features = &self.body_codegen_attrs(caller).target_features;
1233        if self.is_target_feature_call_safe(&fun_features, &caller_features) {
1234            return Some(fun_sig.map_bound(|sig| ty::FnSig {
1235                fn_sig_kind: fun_sig.fn_sig_kind().set_safety(hir::Safety::Safe),
1236                ..sig
1237            }));
1238        }
1239        None
1240    }
1241
1242    /// Helper to get a tracked environment variable via. [`TyCtxt::env_var_os`] and converting to
1243    /// UTF-8 like [`std::env::var`].
1244    pub fn env_var<K: ?Sized + AsRef<OsStr>>(self, key: &'tcx K) -> Result<&'tcx str, VarError> {
1245        match self.env_var_os(key.as_ref()) {
1246            Some(value) => value.to_str().ok_or_else(|| VarError::NotUnicode(value.to_os_string())),
1247            None => Err(VarError::NotPresent),
1248        }
1249    }
1250}
1251
1252impl<'tcx> TyCtxtAt<'tcx> {
1253    /// Create a new definition within the incr. comp. engine.
1254    pub fn create_def(
1255        self,
1256        parent: LocalDefId,
1257        name: Option<Symbol>,
1258        def_kind: DefKind,
1259        override_def_path_data: Option<DefPathData>,
1260        disambiguator: &mut PerParentDisambiguatorState,
1261    ) -> TyCtxtFeed<'tcx, LocalDefId> {
1262        let feed =
1263            self.tcx.create_def(parent, name, def_kind, override_def_path_data, disambiguator);
1264
1265        feed.def_span(self.span);
1266        feed
1267    }
1268}
1269
1270impl<'tcx> TyCtxt<'tcx> {
1271    /// `tcx`-dependent operations performed for every created definition.
1272    pub fn create_def(
1273        self,
1274        parent: LocalDefId,
1275        name: Option<Symbol>,
1276        def_kind: DefKind,
1277        override_def_path_data: Option<DefPathData>,
1278        disambiguator: &mut PerParentDisambiguatorState,
1279    ) -> TyCtxtFeed<'tcx, LocalDefId> {
1280        let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
1281        // The following call has the side effect of modifying the tables inside `definitions`.
1282        // These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1283        // decode the on-disk cache.
1284        //
1285        // Any LocalDefId which is used within queries, either as key or result, either:
1286        // - has been created before the construction of the TyCtxt;
1287        // - has been created by this call to `create_def`.
1288        // As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1289        // comp. engine itself.
1290        let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
1291
1292        // This function modifies `self.definitions` using a side-effect.
1293        // We need to ensure that these side effects are re-run by the incr. comp. engine.
1294        // Depending on the forever-red node will tell the graph that the calling query
1295        // needs to be re-evaluated.
1296        self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
1297
1298        let feed = TyCtxtFeed { tcx: self, key: def_id };
1299        feed.def_kind(def_kind);
1300        // Unique types created for closures participate in type privacy checking.
1301        // They have visibilities inherited from the module they are defined in.
1302        // Visibilities for opaque types are meaningless, but still provided
1303        // so that all items have visibilities.
1304        if #[allow(non_exhaustive_omitted_patterns)] match def_kind {
    DefKind::Closure | DefKind::OpaqueTy => true,
    _ => false,
}matches!(def_kind, DefKind::Closure | DefKind::OpaqueTy) {
1305            let parent_mod = self.parent_module_from_def_id(def_id).to_def_id();
1306            feed.visibility(ty::Visibility::Restricted(parent_mod));
1307        }
1308
1309        feed
1310    }
1311
1312    pub fn create_crate_num(
1313        self,
1314        stable_crate_id: StableCrateId,
1315    ) -> Result<TyCtxtFeed<'tcx, CrateNum>, CrateNum> {
1316        let mut lock = self.untracked().stable_crate_ids.write();
1317        if let Some(&existing) = lock.get(&stable_crate_id) {
1318            return Err(existing);
1319        }
1320        let num = CrateNum::new(lock.len());
1321        lock.insert(stable_crate_id, num);
1322        Ok(TyCtxtFeed { key: num, tcx: self })
1323    }
1324
1325    pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> {
1326        // Depend on the `analysis` query to ensure compilation if finished.
1327        self.ensure_ok().analysis(());
1328
1329        let definitions = &self.untracked.definitions;
1330        gen {
1331            let mut i = 0;
1332
1333            // Recompute the number of definitions each time, because our caller may be creating
1334            // new ones.
1335            while i < { definitions.read().num_definitions() } {
1336                let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
1337                yield LocalDefId { local_def_index };
1338                i += 1;
1339            }
1340
1341            // Freeze definitions once we finish iterating on them, to prevent adding new ones.
1342            definitions.freeze();
1343        }
1344    }
1345
1346    pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
1347        // Depend on the `analysis` query to ensure compilation if finished.
1348        self.ensure_ok().analysis(());
1349
1350        // Freeze definitions once we start iterating on them, to prevent adding new ones
1351        // while iterating. If some query needs to add definitions, it should be `ensure`d above.
1352        self.untracked.definitions.freeze().def_path_table()
1353    }
1354
1355    pub fn def_path_hash_to_def_index_map(
1356        self,
1357    ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap {
1358        // Create a dependency to the crate to be sure we re-execute this when the amount of
1359        // definitions change.
1360        self.ensure_ok().hir_crate_items(());
1361        // Freeze definitions once we start iterating on them, to prevent adding new ones
1362        // while iterating. If some query needs to add definitions, it should be `ensure`d above.
1363        self.untracked.definitions.freeze().def_path_hash_to_def_index_map()
1364    }
1365
1366    /// Note that this is *untracked* and should only be used within the query
1367    /// system if the result is otherwise tracked through queries
1368    #[inline]
1369    pub fn cstore_untracked(self) -> FreezeReadGuard<'tcx, CrateStoreDyn> {
1370        FreezeReadGuard::map(self.untracked.cstore.read(), |c| &**c)
1371    }
1372
1373    /// Give out access to the untracked data without any sanity checks.
1374    pub fn untracked(self) -> &'tcx Untracked {
1375        &self.untracked
1376    }
1377    /// Note that this is *untracked* and should only be used within the query
1378    /// system if the result is otherwise tracked through queries
1379    #[inline]
1380    pub fn definitions_untracked(self) -> FreezeReadGuard<'tcx, Definitions> {
1381        self.untracked.definitions.read()
1382    }
1383
1384    /// Note that this is *untracked* and should only be used within the query
1385    /// system if the result is otherwise tracked through queries
1386    #[inline]
1387    pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
1388        self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
1389    }
1390
1391    #[inline(always)]
1392    pub fn with_stable_hashing_context<R>(
1393        self,
1394        f: impl FnOnce(StableHashingContext<'_>) -> R,
1395    ) -> R {
1396        f(StableHashingContext::new(self.sess, &self.untracked))
1397    }
1398
1399    #[inline]
1400    pub fn local_crate_exports_generics(self) -> bool {
1401        // compiler-builtins has some special treatment in codegen, which can result in confusing
1402        // behavior if another crate ends up calling into its monomorphizations.
1403        // https://github.com/rust-lang/rust/issues/150173
1404        if self.is_compiler_builtins(LOCAL_CRATE) {
1405            return false;
1406        }
1407        self.crate_types().iter().any(|crate_type| {
1408            match crate_type {
1409                CrateType::Executable
1410                | CrateType::StaticLib
1411                | CrateType::ProcMacro
1412                | CrateType::Cdylib
1413                | CrateType::Sdylib => false,
1414
1415                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
1416                // We want to block export of generics from dylibs,
1417                // but we must fix rust-lang/rust#65890 before we can
1418                // do that robustly.
1419                CrateType::Dylib => true,
1420
1421                CrateType::Rlib => true,
1422            }
1423        })
1424    }
1425
1426    /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
1427    pub fn is_suitable_region(
1428        self,
1429        generic_param_scope: LocalDefId,
1430        mut region: Region<'tcx>,
1431    ) -> Option<FreeRegionInfo> {
1432        let (suitable_region_binding_scope, region_def_id) = loop {
1433            let def_id =
1434                region.opt_param_def_id(self, generic_param_scope.to_def_id())?.as_local()?;
1435            let scope = self.local_parent(def_id);
1436            if self.def_kind(scope) == DefKind::OpaqueTy {
1437                // Lifetime params of opaque types are synthetic and thus irrelevant to
1438                // diagnostics. Map them back to their origin!
1439                region = self.map_opaque_lifetime_to_parent_lifetime(def_id);
1440                continue;
1441            }
1442            break (scope, def_id.into());
1443        };
1444
1445        let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) {
1446            Node::Item(..) | Node::TraitItem(..) => false,
1447            Node::ImplItem(impl_item) => match impl_item.impl_kind {
1448                // For now, we do not try to target impls of traits. This is
1449                // because this message is going to suggest that the user
1450                // change the fn signature, but they may not be free to do so,
1451                // since the signature must match the trait.
1452                //
1453                // FIXME(#42706) -- in some cases, we could do better here.
1454                hir::ImplItemImplKind::Trait { .. } => true,
1455                _ => false,
1456            },
1457            _ => false,
1458        };
1459
1460        Some(FreeRegionInfo { scope: suitable_region_binding_scope, region_def_id, is_impl_item })
1461    }
1462
1463    /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
1464    pub fn return_type_impl_or_dyn_traits(
1465        self,
1466        scope_def_id: LocalDefId,
1467    ) -> Vec<&'tcx hir::Ty<'tcx>> {
1468        let hir_id = self.local_def_id_to_hir_id(scope_def_id);
1469        let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) =
1470            self.hir_fn_decl_by_hir_id(hir_id)
1471        else {
1472            return ::alloc::vec::Vec::new()vec![];
1473        };
1474
1475        let mut v = TraitObjectVisitor(::alloc::vec::Vec::new()vec![]);
1476        v.visit_ty_unambig(hir_output);
1477        v.0
1478    }
1479
1480    /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
1481    /// its return type, and the associated alias span when type alias is used,
1482    /// along with a span for lifetime suggestion (if there are existing generics).
1483    pub fn return_type_impl_or_dyn_traits_with_type_alias(
1484        self,
1485        scope_def_id: LocalDefId,
1486    ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
1487        let hir_id = self.local_def_id_to_hir_id(scope_def_id);
1488        let mut v = TraitObjectVisitor(::alloc::vec::Vec::new()vec![]);
1489        // when the return type is a type alias
1490        if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id)
1491            && let hir::TyKind::Path(hir::QPath::Resolved(
1492                None,
1493                hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
1494            && let Some(local_id) = def_id.as_local()
1495            && let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias
1496            && let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics()
1497        {
1498            v.visit_ty_unambig(alias_ty);
1499            if !v.0.is_empty() {
1500                return Some((
1501                    v.0,
1502                    alias_generics.span,
1503                    alias_generics.span_for_lifetime_suggestion(),
1504                ));
1505            }
1506        }
1507        None
1508    }
1509
1510    /// Determines whether identifiers in the assembly have strict naming rules.
1511    /// Currently, only NVPTX* targets need it.
1512    pub fn has_strict_asm_symbol_naming(self) -> bool {
1513        self.sess.target.llvm_target.starts_with("nvptx")
1514    }
1515
1516    /// Returns `&'static core::panic::Location<'static>`.
1517    pub fn caller_location_ty(self) -> Ty<'tcx> {
1518        Ty::new_imm_ref(
1519            self,
1520            self.lifetimes.re_static,
1521            self.type_of(self.require_lang_item(LangItem::PanicLocation, DUMMY_SP))
1522                .instantiate(self, self.mk_args(&[self.lifetimes.re_static.into()]))
1523                .skip_norm_wip(),
1524        )
1525    }
1526
1527    /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
1528    pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
1529        let kind = self.def_kind(def_id);
1530        (self.def_kind_descr_article(kind, def_id), self.def_kind_descr(kind, def_id))
1531    }
1532
1533    pub fn type_length_limit(self) -> Limit {
1534        self.limits(()).type_length_limit
1535    }
1536
1537    pub fn recursion_limit(self) -> Limit {
1538        self.limits(()).recursion_limit
1539    }
1540
1541    pub fn move_size_limit(self) -> Limit {
1542        self.limits(()).move_size_limit
1543    }
1544
1545    pub fn pattern_complexity_limit(self) -> Limit {
1546        self.limits(()).pattern_complexity_limit
1547    }
1548
1549    /// All traits in the crate graph, including those not visible to the user.
1550    pub fn all_traits_including_private(self) -> impl Iterator<Item = DefId> {
1551        iter::once(LOCAL_CRATE)
1552            .chain(self.crates(()).iter().copied())
1553            .flat_map(move |cnum| self.traits(cnum).iter().copied())
1554    }
1555
1556    /// All traits that are visible within the crate graph (i.e. excluding private dependencies).
1557    pub fn visible_traits(self) -> impl Iterator<Item = DefId> {
1558        let visible_crates =
1559            self.crates(()).iter().copied().filter(move |cnum| self.is_user_visible_dep(*cnum));
1560
1561        iter::once(LOCAL_CRATE)
1562            .chain(visible_crates)
1563            .flat_map(move |cnum| self.traits(cnum).iter().copied())
1564    }
1565
1566    #[inline]
1567    pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
1568        self.visibility(def_id).expect_local()
1569    }
1570
1571    /// Returns the origin of the opaque type `def_id`.
1572    x;#[instrument(skip(self), level = "trace", ret)]
1573    pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
1574        self.hir_expect_opaque_ty(def_id).origin
1575    }
1576
1577    pub fn finish(self) {
1578        // We assume that no queries are run past here. If there are new queries
1579        // after this point, they'll show up as "<unknown>" in self-profiling data.
1580        self.alloc_self_profile_query_strings();
1581
1582        self.save_dep_graph();
1583        self.verify_query_key_hashes();
1584
1585        if let Err((path, error)) = self.dep_graph.finish_encoding() {
1586            self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error });
1587        }
1588    }
1589
1590    pub fn report_unused_features(self) {
1591        #[derive(const _: () =
    {
        impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for UnusedFeature
            where G: rustc_errors::EmissionGuarantee {
            #[track_caller]
            fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'_sess>,
                level: rustc_errors::Level) -> rustc_errors::Diag<'_sess, G> {
                match self {
                    UnusedFeature { feature: __binding_0 } => {
                        let mut diag =
                            rustc_errors::Diag::new(dcx, level,
                                rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("feature `{$feature}` is declared but not used")));
                        ;
                        diag.arg("feature", __binding_0);
                        diag
                    }
                }
            }
        }
    };Diagnostic)]
1592        #[diag("feature `{$feature}` is declared but not used")]
1593        struct UnusedFeature {
1594            feature: Symbol,
1595        }
1596
1597        // Collect first to avoid holding the lock while linting.
1598        let used_features = self.sess.used_features.lock();
1599        let unused_features = self
1600            .features()
1601            .enabled_features_iter_stable_order()
1602            .filter(|(f, _)| {
1603                !used_features.contains_key(f)
1604                // FIXME: `restricted_std` is used to tell a standard library built
1605                // for a platform that it doesn't know how to support. But it
1606                // could only gate a private mod (see `__restricted_std_workaround`)
1607                // with `cfg(not(restricted_std))`, so it cannot be recorded as used
1608                // in downstream crates. It should never be linted, but should we
1609                // hack this in the linter to ignore it?
1610                && f.as_str() != "restricted_std"
1611                // `doc_cfg` affects rustdoc behavior: rustdoc checks it via
1612                // `tcx.features().doc_cfg()`, but a normal rustc compilation may
1613                // never observe that use. Do not lint it as unused here.
1614                && *f != sym::doc_cfg
1615            })
1616            .collect::<Vec<_>>();
1617
1618        for (feature, span) in unused_features {
1619            self.emit_node_span_lint(
1620                rustc_session::lint::builtin::UNUSED_FEATURES,
1621                CRATE_HIR_ID,
1622                span,
1623                UnusedFeature { feature },
1624            );
1625        }
1626    }
1627}
1628
1629macro_rules! nop_lift {
1630    ($set:ident; $ty:ty => $lifted:ty) => {
1631        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for $ty {
1632            type Lifted = $lifted;
1633            #[track_caller]
1634            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
1635                // Assert that the set has the right type.
1636                // Given an argument that has an interned type, the return type has the type of
1637                // the corresponding interner set. This won't actually return anything, we're
1638                // just doing this to compute said type!
1639                fn _intern_set_ty_from_interned_ty<'tcx, Inner>(
1640                    _x: Interned<'tcx, Inner>,
1641                ) -> InternedSet<'tcx, Inner> {
1642                    unreachable!()
1643                }
1644                fn _type_eq<T>(_x: &T, _y: &T) {}
1645                fn _test<'tcx>(x: $lifted, tcx: TyCtxt<'tcx>) {
1646                    // If `x` is a newtype around an `Interned<T>`, then `interner` is an
1647                    // interner of appropriate type. (Ideally we'd also check that `x` is a
1648                    // newtype with just that one field. Not sure how to do that.)
1649                    let interner = _intern_set_ty_from_interned_ty(x.0);
1650                    // Now check that this is the same type as `interners.$set`.
1651                    _type_eq(&interner, &tcx.interners.$set);
1652                }
1653
1654                assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)));
1655                // SAFETY: we just checked that `self` is interned and therefore is valid for the
1656                // entire lifetime of the `TyCtxt`.
1657                unsafe { mem::transmute(self) }
1658            }
1659        }
1660    };
1661}
1662
1663macro_rules! nop_list_lift {
1664    ($set:ident; $ty:ty => $lifted:ty) => {
1665        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<$ty> {
1666            type Lifted = &'tcx List<$lifted>;
1667            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
1668                // Assert that the set has the right type.
1669                if false {
1670                    let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set;
1671                }
1672
1673                if self.is_empty() {
1674                    return List::empty();
1675                }
1676                assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(self)));
1677                // SAFETY: we just checked that `self` is interned and therefore is valid for the
1678                // entire lifetime of the `TyCtxt`.
1679                unsafe { mem::transmute(self) }
1680            }
1681        }
1682    };
1683}
1684
1685impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Ty<'a> {
    type Lifted = Ty<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Ty<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.type_);
        }
        if !tcx.interners.type_.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.type_.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { type_; Ty<'a> => Ty<'tcx> }
1686impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Region<'a> {
    type Lifted = Region<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Region<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.region);
        }
        if !tcx.interners.region.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.region.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { region; Region<'a> => Region<'tcx> }
1687impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Const<'a> {
    type Lifted = Const<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Const<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.const_);
        }
        if !tcx.interners.const_.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.const_.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { const_; Const<'a> => Const<'tcx> }
1688impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Pattern<'a> {
    type Lifted = Pattern<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Pattern<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.pat);
        }
        if !tcx.interners.pat.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.pat.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { pat; Pattern<'a> => Pattern<'tcx> }
1689impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for ConstAllocation<'a> {
    type Lifted = ConstAllocation<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: ConstAllocation<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.const_allocation);
        }
        if !tcx.interners.const_allocation.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.const_allocation.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx> }
1690impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Predicate<'a> {
    type Lifted = Predicate<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Predicate<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.predicate);
        }
        if !tcx.interners.predicate.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.predicate.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { predicate; Predicate<'a> => Predicate<'tcx> }
1691impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Clause<'a> {
    type Lifted = Clause<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Clause<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.predicate);
        }
        if !tcx.interners.predicate.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.predicate.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { predicate; Clause<'a> => Clause<'tcx> }
1692impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Layout<'a> {
    type Lifted = Layout<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: Layout<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.layout);
        }
        if !tcx.interners.layout.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.layout.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { layout; Layout<'a> => Layout<'tcx> }
1693impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for ValTree<'a> {
    type Lifted = ValTree<'tcx>;
    #[track_caller]
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        fn _intern_set_ty_from_interned_ty<'tcx,
            Inner>(_x: Interned<'tcx, Inner>) -> InternedSet<'tcx, Inner> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
        fn _type_eq<T>(_x: &T, _y: &T) {}
        fn _test<'tcx>(x: ValTree<'tcx>, tcx: TyCtxt<'tcx>) {
            let interner = _intern_set_ty_from_interned_ty(x.0);
            _type_eq(&interner, &tcx.interners.valtree);
        }
        if !tcx.interners.valtree.contains_pointer_to(&InternedInSet(&*self.0.0))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.valtree.contains_pointer_to(&InternedInSet(&*self.0.0))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_lift! { valtree; ValTree<'a> => ValTree<'tcx> }
1694
1695impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<Ty<'a>> {
    type Lifted = &'tcx List<Ty<'tcx>>;
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        if false {
            let _x: &InternedSet<'tcx, List<Ty<'tcx>>> =
                &tcx.interners.type_lists;
        }
        if self.is_empty() { return List::empty(); }
        if !tcx.interners.type_lists.contains_pointer_to(&InternedInSet(self))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.type_lists.contains_pointer_to(&InternedInSet(self))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> }
1696impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<PolyExistentialPredicate<'a>> {
    type Lifted = &'tcx List<PolyExistentialPredicate<'tcx>>;
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        if false {
            let _x: &InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>> =
                &tcx.interners.poly_existential_predicates;
        }
        if self.is_empty() { return List::empty(); }
        if !tcx.interners.poly_existential_predicates.contains_pointer_to(&InternedInSet(self))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.poly_existential_predicates.contains_pointer_to(&InternedInSet(self))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_list_lift! {
1697    poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>
1698}
1699impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<ty::BoundVariableKind<'a>> {
    type Lifted = &'tcx List<ty::BoundVariableKind<'tcx>>;
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        if false {
            let _x: &InternedSet<'tcx, List<ty::BoundVariableKind<'tcx>>> =
                &tcx.interners.bound_variable_kinds;
        }
        if self.is_empty() { return List::empty(); }
        if !tcx.interners.bound_variable_kinds.contains_pointer_to(&InternedInSet(self))
            {
            ::core::panicking::panic("assertion failed: tcx.interners.bound_variable_kinds.contains_pointer_to(&InternedInSet(self))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind<'a> => ty::BoundVariableKind<'tcx> }
1700
1701// This is the impl for `&'a GenericArgs<'a>`.
1702impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<GenericArg<'a>> {
    type Lifted = &'tcx List<GenericArg<'tcx>>;
    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
        if false {
            let _x: &InternedSet<'tcx, List<GenericArg<'tcx>>> =
                &tcx.interners.args;
        }
        if self.is_empty() { return List::empty(); }
        if !tcx.interners.args.contains_pointer_to(&InternedInSet(self)) {
            ::core::panicking::panic("assertion failed: tcx.interners.args.contains_pointer_to(&InternedInSet(self))")
        };
        unsafe { mem::transmute(self) }
    }
}nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> }
1703
1704macro_rules! sty_debug_print {
1705    ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
1706        // Curious inner module to allow variant names to be used as
1707        // variable names.
1708        #[allow(non_snake_case)]
1709        mod inner {
1710            use crate::ty::{self, TyCtxt};
1711            use crate::ty::context::InternedInSet;
1712
1713            #[derive(Copy, Clone)]
1714            struct DebugStat {
1715                total: usize,
1716                lt_infer: usize,
1717                ty_infer: usize,
1718                ct_infer: usize,
1719                all_infer: usize,
1720            }
1721
1722            pub(crate) fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
1723                let mut total = DebugStat {
1724                    total: 0,
1725                    lt_infer: 0,
1726                    ty_infer: 0,
1727                    ct_infer: 0,
1728                    all_infer: 0,
1729                };
1730                $(let mut $variant = total;)*
1731
1732                for shard in tcx.interners.type_.lock_shards() {
1733                    // It seems that ordering doesn't affect anything here.
1734                    #[allow(rustc::potential_query_instability)]
1735                    let types = shard.iter();
1736                    for &(InternedInSet(t), ()) in types {
1737                        let variant = match t.internee {
1738                            ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
1739                                ty::Float(..) | ty::Str | ty::Never => continue,
1740                            ty::Error(_) => /* unimportant */ continue,
1741                            $(ty::$variant(..) => &mut $variant,)*
1742                        };
1743                        let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
1744                        let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
1745                        let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
1746
1747                        variant.total += 1;
1748                        total.total += 1;
1749                        if lt { total.lt_infer += 1; variant.lt_infer += 1 }
1750                        if ty { total.ty_infer += 1; variant.ty_infer += 1 }
1751                        if ct { total.ct_infer += 1; variant.ct_infer += 1 }
1752                        if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
1753                    }
1754                }
1755                writeln!(fmt, "Ty interner             total           ty lt ct all")?;
1756                $(writeln!(fmt, "    {:18}: {uses:6} {usespc:4.1}%, \
1757                            {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1758                    stringify!($variant),
1759                    uses = $variant.total,
1760                    usespc = $variant.total as f64 * 100.0 / total.total as f64,
1761                    ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
1762                    lt = $variant.lt_infer as f64 * 100.0  / total.total as f64,
1763                    ct = $variant.ct_infer as f64 * 100.0  / total.total as f64,
1764                    all = $variant.all_infer as f64 * 100.0  / total.total as f64)?;
1765                )*
1766                writeln!(fmt, "                  total {uses:6}        \
1767                          {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1768                    uses = total.total,
1769                    ty = total.ty_infer as f64 * 100.0  / total.total as f64,
1770                    lt = total.lt_infer as f64 * 100.0  / total.total as f64,
1771                    ct = total.ct_infer as f64 * 100.0  / total.total as f64,
1772                    all = total.all_infer as f64 * 100.0  / total.total as f64)
1773            }
1774        }
1775
1776        inner::go($fmt, $ctxt)
1777    }}
1778}
1779
1780impl<'tcx> TyCtxt<'tcx> {
1781    pub fn debug_stats(self) -> impl fmt::Debug {
1782        fmt::from_fn(move |fmt| {
1783            {
    #[allow(non_snake_case)]
    mod inner {
        use crate::ty::{self, TyCtxt};
        use crate::ty::context::InternedInSet;
        struct DebugStat {
            total: usize,
            lt_infer: usize,
            ty_infer: usize,
            ct_infer: usize,
            all_infer: usize,
        }
        #[automatically_derived]
        impl ::core::marker::Copy for DebugStat { }
        #[automatically_derived]
        #[doc(hidden)]
        unsafe impl ::core::clone::TrivialClone for DebugStat { }
        #[automatically_derived]
        impl ::core::clone::Clone for DebugStat {
            #[inline]
            fn clone(&self) -> DebugStat {
                let _: ::core::clone::AssertParamIsClone<usize>;
                *self
            }
        }
        pub(crate) fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>)
            -> std::fmt::Result {
            let mut total =
                DebugStat {
                    total: 0,
                    lt_infer: 0,
                    ty_infer: 0,
                    ct_infer: 0,
                    all_infer: 0,
                };
            let mut Adt = total;
            let mut Array = total;
            let mut Slice = total;
            let mut RawPtr = total;
            let mut Ref = total;
            let mut FnDef = total;
            let mut FnPtr = total;
            let mut UnsafeBinder = total;
            let mut Placeholder = total;
            let mut Coroutine = total;
            let mut CoroutineWitness = total;
            let mut Dynamic = total;
            let mut Closure = total;
            let mut CoroutineClosure = total;
            let mut Tuple = total;
            let mut Bound = total;
            let mut Param = total;
            let mut Infer = total;
            let mut Alias = total;
            let mut Pat = total;
            let mut Foreign = total;
            for shard in tcx.interners.type_.lock_shards() {
                #[allow(rustc :: potential_query_instability)]
                let types = shard.iter();
                for &(InternedInSet(t), ()) in types {
                    let variant =
                        match t.internee {
                            ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                                ty::Float(..) | ty::Str | ty::Never => continue,
                            ty::Error(_) => continue,
                            ty::Adt(..) => &mut Adt,
                            ty::Array(..) => &mut Array,
                            ty::Slice(..) => &mut Slice,
                            ty::RawPtr(..) => &mut RawPtr,
                            ty::Ref(..) => &mut Ref,
                            ty::FnDef(..) => &mut FnDef,
                            ty::FnPtr(..) => &mut FnPtr,
                            ty::UnsafeBinder(..) => &mut UnsafeBinder,
                            ty::Placeholder(..) => &mut Placeholder,
                            ty::Coroutine(..) => &mut Coroutine,
                            ty::CoroutineWitness(..) => &mut CoroutineWitness,
                            ty::Dynamic(..) => &mut Dynamic,
                            ty::Closure(..) => &mut Closure,
                            ty::CoroutineClosure(..) => &mut CoroutineClosure,
                            ty::Tuple(..) => &mut Tuple,
                            ty::Bound(..) => &mut Bound,
                            ty::Param(..) => &mut Param,
                            ty::Infer(..) => &mut Infer,
                            ty::Alias(..) => &mut Alias,
                            ty::Pat(..) => &mut Pat,
                            ty::Foreign(..) => &mut Foreign,
                        };
                    let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
                    let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
                    let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
                    variant.total += 1;
                    total.total += 1;
                    if lt { total.lt_infer += 1; variant.lt_infer += 1 }
                    if ty { total.ty_infer += 1; variant.ty_infer += 1 }
                    if ct { total.ct_infer += 1; variant.ct_infer += 1 }
                    if lt && ty && ct {
                        total.all_infer += 1;
                        variant.all_infer += 1
                    }
                }
            }
            fmt.write_fmt(format_args!("Ty interner             total           ty lt ct all\n"))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Adt", Adt.total,
                        Adt.total as f64 * 100.0 / total.total as f64,
                        Adt.ty_infer as f64 * 100.0 / total.total as f64,
                        Adt.lt_infer as f64 * 100.0 / total.total as f64,
                        Adt.ct_infer as f64 * 100.0 / total.total as f64,
                        Adt.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Array", Array.total,
                        Array.total as f64 * 100.0 / total.total as f64,
                        Array.ty_infer as f64 * 100.0 / total.total as f64,
                        Array.lt_infer as f64 * 100.0 / total.total as f64,
                        Array.ct_infer as f64 * 100.0 / total.total as f64,
                        Array.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Slice", Slice.total,
                        Slice.total as f64 * 100.0 / total.total as f64,
                        Slice.ty_infer as f64 * 100.0 / total.total as f64,
                        Slice.lt_infer as f64 * 100.0 / total.total as f64,
                        Slice.ct_infer as f64 * 100.0 / total.total as f64,
                        Slice.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "RawPtr", RawPtr.total,
                        RawPtr.total as f64 * 100.0 / total.total as f64,
                        RawPtr.ty_infer as f64 * 100.0 / total.total as f64,
                        RawPtr.lt_infer as f64 * 100.0 / total.total as f64,
                        RawPtr.ct_infer as f64 * 100.0 / total.total as f64,
                        RawPtr.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Ref", Ref.total,
                        Ref.total as f64 * 100.0 / total.total as f64,
                        Ref.ty_infer as f64 * 100.0 / total.total as f64,
                        Ref.lt_infer as f64 * 100.0 / total.total as f64,
                        Ref.ct_infer as f64 * 100.0 / total.total as f64,
                        Ref.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "FnDef", FnDef.total,
                        FnDef.total as f64 * 100.0 / total.total as f64,
                        FnDef.ty_infer as f64 * 100.0 / total.total as f64,
                        FnDef.lt_infer as f64 * 100.0 / total.total as f64,
                        FnDef.ct_infer as f64 * 100.0 / total.total as f64,
                        FnDef.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "FnPtr", FnPtr.total,
                        FnPtr.total as f64 * 100.0 / total.total as f64,
                        FnPtr.ty_infer as f64 * 100.0 / total.total as f64,
                        FnPtr.lt_infer as f64 * 100.0 / total.total as f64,
                        FnPtr.ct_infer as f64 * 100.0 / total.total as f64,
                        FnPtr.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "UnsafeBinder", UnsafeBinder.total,
                        UnsafeBinder.total as f64 * 100.0 / total.total as f64,
                        UnsafeBinder.ty_infer as f64 * 100.0 / total.total as f64,
                        UnsafeBinder.lt_infer as f64 * 100.0 / total.total as f64,
                        UnsafeBinder.ct_infer as f64 * 100.0 / total.total as f64,
                        UnsafeBinder.all_infer as f64 * 100.0 /
                            total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Placeholder", Placeholder.total,
                        Placeholder.total as f64 * 100.0 / total.total as f64,
                        Placeholder.ty_infer as f64 * 100.0 / total.total as f64,
                        Placeholder.lt_infer as f64 * 100.0 / total.total as f64,
                        Placeholder.ct_infer as f64 * 100.0 / total.total as f64,
                        Placeholder.all_infer as f64 * 100.0 /
                            total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Coroutine", Coroutine.total,
                        Coroutine.total as f64 * 100.0 / total.total as f64,
                        Coroutine.ty_infer as f64 * 100.0 / total.total as f64,
                        Coroutine.lt_infer as f64 * 100.0 / total.total as f64,
                        Coroutine.ct_infer as f64 * 100.0 / total.total as f64,
                        Coroutine.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "CoroutineWitness", CoroutineWitness.total,
                        CoroutineWitness.total as f64 * 100.0 / total.total as f64,
                        CoroutineWitness.ty_infer as f64 * 100.0 /
                            total.total as f64,
                        CoroutineWitness.lt_infer as f64 * 100.0 /
                            total.total as f64,
                        CoroutineWitness.ct_infer as f64 * 100.0 /
                            total.total as f64,
                        CoroutineWitness.all_infer as f64 * 100.0 /
                            total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Dynamic", Dynamic.total,
                        Dynamic.total as f64 * 100.0 / total.total as f64,
                        Dynamic.ty_infer as f64 * 100.0 / total.total as f64,
                        Dynamic.lt_infer as f64 * 100.0 / total.total as f64,
                        Dynamic.ct_infer as f64 * 100.0 / total.total as f64,
                        Dynamic.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Closure", Closure.total,
                        Closure.total as f64 * 100.0 / total.total as f64,
                        Closure.ty_infer as f64 * 100.0 / total.total as f64,
                        Closure.lt_infer as f64 * 100.0 / total.total as f64,
                        Closure.ct_infer as f64 * 100.0 / total.total as f64,
                        Closure.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "CoroutineClosure", CoroutineClosure.total,
                        CoroutineClosure.total as f64 * 100.0 / total.total as f64,
                        CoroutineClosure.ty_infer as f64 * 100.0 /
                            total.total as f64,
                        CoroutineClosure.lt_infer as f64 * 100.0 /
                            total.total as f64,
                        CoroutineClosure.ct_infer as f64 * 100.0 /
                            total.total as f64,
                        CoroutineClosure.all_infer as f64 * 100.0 /
                            total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Tuple", Tuple.total,
                        Tuple.total as f64 * 100.0 / total.total as f64,
                        Tuple.ty_infer as f64 * 100.0 / total.total as f64,
                        Tuple.lt_infer as f64 * 100.0 / total.total as f64,
                        Tuple.ct_infer as f64 * 100.0 / total.total as f64,
                        Tuple.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Bound", Bound.total,
                        Bound.total as f64 * 100.0 / total.total as f64,
                        Bound.ty_infer as f64 * 100.0 / total.total as f64,
                        Bound.lt_infer as f64 * 100.0 / total.total as f64,
                        Bound.ct_infer as f64 * 100.0 / total.total as f64,
                        Bound.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Param", Param.total,
                        Param.total as f64 * 100.0 / total.total as f64,
                        Param.ty_infer as f64 * 100.0 / total.total as f64,
                        Param.lt_infer as f64 * 100.0 / total.total as f64,
                        Param.ct_infer as f64 * 100.0 / total.total as f64,
                        Param.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Infer", Infer.total,
                        Infer.total as f64 * 100.0 / total.total as f64,
                        Infer.ty_infer as f64 * 100.0 / total.total as f64,
                        Infer.lt_infer as f64 * 100.0 / total.total as f64,
                        Infer.ct_infer as f64 * 100.0 / total.total as f64,
                        Infer.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Alias", Alias.total,
                        Alias.total as f64 * 100.0 / total.total as f64,
                        Alias.ty_infer as f64 * 100.0 / total.total as f64,
                        Alias.lt_infer as f64 * 100.0 / total.total as f64,
                        Alias.ct_infer as f64 * 100.0 / total.total as f64,
                        Alias.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Pat", Pat.total,
                        Pat.total as f64 * 100.0 / total.total as f64,
                        Pat.ty_infer as f64 * 100.0 / total.total as f64,
                        Pat.lt_infer as f64 * 100.0 / total.total as f64,
                        Pat.ct_infer as f64 * 100.0 / total.total as f64,
                        Pat.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("    {0:18}: {1:6} {2:4.1}%, {3:4.1}% {4:5.1}% {5:4.1}% {6:4.1}%\n",
                        "Foreign", Foreign.total,
                        Foreign.total as f64 * 100.0 / total.total as f64,
                        Foreign.ty_infer as f64 * 100.0 / total.total as f64,
                        Foreign.lt_infer as f64 * 100.0 / total.total as f64,
                        Foreign.ct_infer as f64 * 100.0 / total.total as f64,
                        Foreign.all_infer as f64 * 100.0 / total.total as f64))?;
            fmt.write_fmt(format_args!("                  total {0:6}        {1:4.1}% {2:5.1}% {3:4.1}% {4:4.1}%\n",
                    total.total,
                    total.ty_infer as f64 * 100.0 / total.total as f64,
                    total.lt_infer as f64 * 100.0 / total.total as f64,
                    total.ct_infer as f64 * 100.0 / total.total as f64,
                    total.all_infer as f64 * 100.0 / total.total as f64))
        }
    }
    inner::go(fmt, self)
}sty_debug_print!(
1784                fmt,
1785                self,
1786                Adt,
1787                Array,
1788                Slice,
1789                RawPtr,
1790                Ref,
1791                FnDef,
1792                FnPtr,
1793                UnsafeBinder,
1794                Placeholder,
1795                Coroutine,
1796                CoroutineWitness,
1797                Dynamic,
1798                Closure,
1799                CoroutineClosure,
1800                Tuple,
1801                Bound,
1802                Param,
1803                Infer,
1804                Alias,
1805                Pat,
1806                Foreign
1807            )?;
1808
1809            fmt.write_fmt(format_args!("GenericArgs interner: #{0}\n",
        self.interners.args.len()))writeln!(fmt, "GenericArgs interner: #{}", self.interners.args.len())?;
1810            fmt.write_fmt(format_args!("Region interner: #{0}\n",
        self.interners.region.len()))writeln!(fmt, "Region interner: #{}", self.interners.region.len())?;
1811            fmt.write_fmt(format_args!("Const Allocation interner: #{0}\n",
        self.interners.const_allocation.len()))writeln!(fmt, "Const Allocation interner: #{}", self.interners.const_allocation.len())?;
1812            fmt.write_fmt(format_args!("Layout interner: #{0}\n",
        self.interners.layout.len()))writeln!(fmt, "Layout interner: #{}", self.interners.layout.len())?;
1813
1814            Ok(())
1815        })
1816    }
1817}
1818
1819// This type holds a `T` in the interner. The `T` is stored in the arena and
1820// this type just holds a pointer to it, but it still effectively owns it. It
1821// impls `Borrow` so that it can be looked up using the original
1822// (non-arena-memory-owning) types.
1823struct InternedInSet<'tcx, T: ?Sized + PointeeSized>(&'tcx T);
1824
1825impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Clone for InternedInSet<'tcx, T> {
1826    fn clone(&self) -> Self {
1827        *self
1828    }
1829}
1830
1831impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Copy for InternedInSet<'tcx, T> {}
1832
1833impl<'tcx, T: 'tcx + ?Sized + PointeeSized> IntoPointer for InternedInSet<'tcx, T> {
1834    fn into_pointer(&self) -> *const () {
1835        self.0 as *const _ as *const ()
1836    }
1837}
1838
1839#[allow(rustc::usage_of_ty_tykind)]
1840impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1841    fn borrow(&self) -> &T {
1842        &self.0.internee
1843    }
1844}
1845
1846impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1847    fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
1848        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1849        // `x == y`.
1850        self.0.internee == other.0.internee
1851    }
1852}
1853
1854impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
1855
1856impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1857    fn hash<H: Hasher>(&self, s: &mut H) {
1858        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1859        self.0.internee.hash(s)
1860    }
1861}
1862
1863impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
1864    fn borrow(&self) -> &[T] {
1865        &self.0[..]
1866    }
1867}
1868
1869impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> {
1870    fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool {
1871        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1872        // `x == y`.
1873        self.0[..] == other.0[..]
1874    }
1875}
1876
1877impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {}
1878
1879impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
1880    fn hash<H: Hasher>(&self, s: &mut H) {
1881        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1882        self.0[..].hash(s)
1883    }
1884}
1885
1886impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1887    fn borrow(&self) -> &[T] {
1888        &self.0[..]
1889    }
1890}
1891
1892impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1893    fn eq(&self, other: &InternedInSet<'tcx, ListWithCachedTypeInfo<T>>) -> bool {
1894        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1895        // `x == y`.
1896        self.0[..] == other.0[..]
1897    }
1898}
1899
1900impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {}
1901
1902impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1903    fn hash<H: Hasher>(&self, s: &mut H) {
1904        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1905        self.0[..].hash(s)
1906    }
1907}
1908
1909macro_rules! direct_interners {
1910    ($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
1911        $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
1912            fn borrow<'a>(&'a self) -> &'a $ty {
1913                &self.0
1914            }
1915        }
1916
1917        impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
1918            fn eq(&self, other: &Self) -> bool {
1919                // The `Borrow` trait requires that `x.borrow() == y.borrow()`
1920                // equals `x == y`.
1921                self.0 == other.0
1922            }
1923        }
1924
1925        impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
1926
1927        impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
1928            fn hash<H: Hasher>(&self, s: &mut H) {
1929                // The `Borrow` trait requires that `x.borrow().hash(s) ==
1930                // x.hash(s)`.
1931                self.0.hash(s)
1932            }
1933        }
1934
1935        impl<'tcx> TyCtxt<'tcx> {
1936            $vis fn $method(self, v: $ty) -> $ret_ty {
1937                $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
1938                    InternedInSet(self.interners.arena.alloc(v))
1939                }).0))
1940            }
1941        })+
1942    }
1943}
1944
1945// Functions with a `mk_` prefix are intended for use outside this file and
1946// crate. Functions with an `intern_` prefix are intended for use within this
1947// crate only, and have a corresponding `mk_` function.
1948impl<'tcx> Borrow<ExternalConstraintsData<TyCtxt<'tcx>>> for
    InternedInSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>> {
    fn borrow<'a>(&'a self) -> &'a ExternalConstraintsData<TyCtxt<'tcx>> {
        &self.0
    }
}
impl<'tcx> PartialEq for
    InternedInSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'tcx> Eq for InternedInSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>
    {}
impl<'tcx> Hash for InternedInSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>
    {
    fn hash<H: Hasher>(&self, s: &mut H) { self.0.hash(s) }
}
impl<'tcx> TyCtxt<'tcx> {
    pub fn mk_external_constraints(self,
        v: ExternalConstraintsData<TyCtxt<'tcx>>)
        -> ExternalConstraints<'tcx> {
        ExternalConstraints(Interned::new_unchecked(self.interners.external_constraints.intern(v,
                        |v| { InternedInSet(self.interners.arena.alloc(v)) }).0))
    }
}direct_interners! {
1949    region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
1950    valtree: pub(crate) intern_valtree(ValTreeKind<TyCtxt<'tcx>>): ValTree -> ValTree<'tcx>,
1951    pat: pub mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>,
1952    const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
1953    layout: pub mk_layout(LayoutData<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
1954    adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
1955    external_constraints: pub mk_external_constraints(ExternalConstraintsData<TyCtxt<'tcx>>):
1956        ExternalConstraints -> ExternalConstraints<'tcx>,
1957}
1958
1959macro_rules! slice_interners {
1960    ($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
1961        impl<'tcx> TyCtxt<'tcx> {
1962            $($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
1963                if v.is_empty() {
1964                    List::empty()
1965                } else {
1966                    self.interners.$field.intern_ref(v, || {
1967                        InternedInSet(List::from_arena(&*self.arena, (), v))
1968                    }).0
1969                }
1970            })+
1971        }
1972    );
1973}
1974
1975// These functions intern slices. They all have a corresponding
1976// `mk_foo_from_iter` function that interns an iterator. The slice version
1977// should be used when possible, because it's faster.
1978impl<'tcx> TyCtxt<'tcx> {
    pub fn mk_const_list(self, v: &[Const<'tcx>]) -> &'tcx List<Const<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.const_lists.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_args(self, v: &[GenericArg<'tcx>])
        -> &'tcx List<GenericArg<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.args.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.type_lists.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_canonical_var_kinds(self, v: &[CanonicalVarKind<'tcx>])
        -> &'tcx List<CanonicalVarKind<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.canonical_var_kinds.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    fn intern_poly_existential_predicates(self,
        v: &[PolyExistentialPredicate<'tcx>])
        -> &'tcx List<PolyExistentialPredicate<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.poly_existential_predicates.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_projs(self, v: &[ProjectionKind])
        -> &'tcx List<ProjectionKind> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.projs.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_place_elems(self, v: &[PlaceElem<'tcx>])
        -> &'tcx List<PlaceElem<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.place_elems.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_bound_variable_kinds(self, v: &[ty::BoundVariableKind<'tcx>])
        -> &'tcx List<ty::BoundVariableKind<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.bound_variable_kinds.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_fields(self, v: &[FieldIdx]) -> &'tcx List<FieldIdx> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.fields.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    fn intern_local_def_ids(self, v: &[LocalDefId])
        -> &'tcx List<LocalDefId> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.local_def_ids.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    fn intern_captures(self, v: &[&'tcx ty::CapturedPlace<'tcx>])
        -> &'tcx List<&'tcx ty::CapturedPlace<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.captures.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_patterns(self, v: &[Pattern<'tcx>])
        -> &'tcx List<Pattern<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.patterns.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_outlives(self, v: &[ty::ArgOutlivesPredicate<'tcx>])
        -> &'tcx List<ty::ArgOutlivesPredicate<'tcx>> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.outlives.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
    pub fn mk_predefined_opaques_in_body(self,
        v: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)])
        -> &'tcx List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
        if v.is_empty() {
            List::empty()
        } else {
            self.interners.predefined_opaques_in_body.intern_ref(v,
                    ||
                        { InternedInSet(List::from_arena(&*self.arena, (), v)) }).0
        }
    }
}slice_interners!(
1979    const_lists: pub mk_const_list(Const<'tcx>),
1980    args: pub mk_args(GenericArg<'tcx>),
1981    type_lists: pub mk_type_list(Ty<'tcx>),
1982    canonical_var_kinds: pub mk_canonical_var_kinds(CanonicalVarKind<'tcx>),
1983    poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
1984    projs: pub mk_projs(ProjectionKind),
1985    place_elems: pub mk_place_elems(PlaceElem<'tcx>),
1986    bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind<'tcx>),
1987    fields: pub mk_fields(FieldIdx),
1988    local_def_ids: intern_local_def_ids(LocalDefId),
1989    captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
1990    patterns: pub mk_patterns(Pattern<'tcx>),
1991    outlives: pub mk_outlives(ty::ArgOutlivesPredicate<'tcx>),
1992    predefined_opaques_in_body: pub mk_predefined_opaques_in_body((ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)),
1993);
1994
1995impl<'tcx> TyCtxt<'tcx> {
1996    /// Given a `fn` sig, returns an equivalent `unsafe fn` type;
1997    /// that is, a `fn` type that is equivalent in every way for being
1998    /// unsafe.
1999    pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
2000        if !sig.safety().is_safe() {
    ::core::panicking::panic("assertion failed: sig.safety().is_safe()")
};assert!(sig.safety().is_safe());
2001        Ty::new_fn_ptr(
2002            self,
2003            sig.map_bound(|sig| ty::FnSig {
2004                fn_sig_kind: sig.fn_sig_kind.set_safety(hir::Safety::Unsafe),
2005                ..sig
2006            }),
2007        )
2008    }
2009
2010    /// Given a `fn` sig, returns an equivalent `unsafe fn` sig;
2011    /// that is, a `fn` sig that is equivalent in every way for being
2012    /// unsafe.
2013    pub fn safe_to_unsafe_sig(self, sig: PolyFnSig<'tcx>) -> PolyFnSig<'tcx> {
2014        if !sig.safety().is_safe() {
    ::core::panicking::panic("assertion failed: sig.safety().is_safe()")
};assert!(sig.safety().is_safe());
2015        sig.map_bound(|sig| ty::FnSig {
2016            fn_sig_kind: sig.fn_sig_kind.set_safety(hir::Safety::Unsafe),
2017            ..sig
2018        })
2019    }
2020
2021    /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
2022    /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
2023    pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
2024        elaborate::supertrait_def_ids(self, trait_def_id).any(|trait_did| {
2025            self.associated_items(trait_did)
2026                .filter_by_name_unhygienic(assoc_name.name)
2027                .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did))
2028        })
2029    }
2030
2031    /// Given a `ty`, return whether it's an `impl Future<...>`.
2032    pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
2033        let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *ty.kind() else {
2034            return false;
2035        };
2036        let future_trait = self.require_lang_item(LangItem::Future, DUMMY_SP);
2037
2038        self.explicit_item_self_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
2039            let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
2040                return false;
2041            };
2042            trait_predicate.trait_ref.def_id == future_trait
2043                && trait_predicate.polarity == PredicatePolarity::Positive
2044        })
2045    }
2046
2047    /// Given a closure signature, returns an equivalent fn signature. Detuples
2048    /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
2049    /// you would get a `fn(u32, i32)`.
2050    /// `unsafety` determines the unsafety of the fn signature. If you pass
2051    /// `hir::Safety::Unsafe` in the previous example, then you would get
2052    /// an `unsafe fn (u32, i32)`.
2053    /// It cannot convert a closure that requires unsafe.
2054    pub fn signature_unclosure(self, sig: PolyFnSig<'tcx>, safety: hir::Safety) -> PolyFnSig<'tcx> {
2055        sig.map_bound(|s| {
2056            let params = match s.inputs()[0].kind() {
2057                ty::Tuple(params) => *params,
2058                _ => crate::util::bug::bug_fmt(format_args!("impossible case reached"))bug!(),
2059            };
2060            self.mk_fn_sig(
2061                params,
2062                s.output(),
2063                s.fn_sig_kind.set_safety(safety).set_abi(ExternAbi::Rust),
2064            )
2065        })
2066    }
2067
2068    #[inline]
2069    pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
2070        self.interners.intern_predicate(binder)
2071    }
2072
2073    #[inline]
2074    pub fn reuse_or_mk_predicate(
2075        self,
2076        pred: Predicate<'tcx>,
2077        binder: Binder<'tcx, PredicateKind<'tcx>>,
2078    ) -> Predicate<'tcx> {
2079        if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
2080    }
2081
2082    pub fn check_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) -> bool {
2083        self.check_args_compatible_inner(def_id, args, false)
2084    }
2085
2086    fn check_args_compatible_inner(
2087        self,
2088        def_id: DefId,
2089        args: &'tcx [ty::GenericArg<'tcx>],
2090        nested: bool,
2091    ) -> bool {
2092        let generics = self.generics_of(def_id);
2093
2094        // IATs and IACs (inherent associated types/consts with `type const`) themselves have a
2095        // weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e.
2096        // ATPITs) do not.
2097        let is_inherent_assoc_ty = #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(def_id) {
    DefKind::AssocTy => true,
    _ => false,
}matches!(self.def_kind(def_id), DefKind::AssocTy)
2098            && #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(self.parent(def_id))
    {
    DefKind::Impl { of_trait: false } => true,
    _ => false,
}matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false });
2099        let is_inherent_assoc_type_const =
2100            #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(def_id) {
    DefKind::AssocConst { is_type_const: true } => true,
    _ => false,
}matches!(self.def_kind(def_id), DefKind::AssocConst { is_type_const: true })
2101                && #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(self.parent(def_id))
    {
    DefKind::Impl { of_trait: false } => true,
    _ => false,
}matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false });
2102        let own_args = if !nested && (is_inherent_assoc_ty || is_inherent_assoc_type_const) {
2103            if generics.own_params.len() + 1 != args.len() {
2104                return false;
2105            }
2106
2107            if !#[allow(non_exhaustive_omitted_patterns)] match args[0].kind() {
    ty::GenericArgKind::Type(_) => true,
    _ => false,
}matches!(args[0].kind(), ty::GenericArgKind::Type(_)) {
2108                return false;
2109            }
2110
2111            &args[1..]
2112        } else {
2113            if generics.count() != args.len() {
2114                return false;
2115            }
2116
2117            let (parent_args, own_args) = args.split_at(generics.parent_count);
2118
2119            if let Some(parent) = generics.parent
2120                && !self.check_args_compatible_inner(parent, parent_args, true)
2121            {
2122                return false;
2123            }
2124
2125            own_args
2126        };
2127
2128        for (param, arg) in std::iter::zip(&generics.own_params, own_args) {
2129            match (&param.kind, arg.kind()) {
2130                (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
2131                | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
2132                | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
2133                _ => return false,
2134            }
2135        }
2136
2137        true
2138    }
2139
2140    /// With `cfg(debug_assertions)`, assert that args are compatible with their generics,
2141    /// and print out the args if not.
2142    pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
2143        if truecfg!(debug_assertions) && !self.check_args_compatible(def_id, args) {
2144            let is_inherent_assoc_ty = #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(def_id) {
    DefKind::AssocTy => true,
    _ => false,
}matches!(self.def_kind(def_id), DefKind::AssocTy)
2145                && #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(self.parent(def_id))
    {
    DefKind::Impl { of_trait: false } => true,
    _ => false,
}matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false });
2146            let is_inherent_assoc_type_const =
2147                #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(def_id) {
    DefKind::AssocConst { is_type_const: true } => true,
    _ => false,
}matches!(self.def_kind(def_id), DefKind::AssocConst { is_type_const: true })
2148                    && #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(self.parent(def_id))
    {
    DefKind::Impl { of_trait: false } => true,
    _ => false,
}matches!(
2149                        self.def_kind(self.parent(def_id)),
2150                        DefKind::Impl { of_trait: false }
2151                    );
2152            if is_inherent_assoc_ty || is_inherent_assoc_type_const {
2153                crate::util::bug::bug_fmt(format_args!("args not compatible with generics for {0}: args={1:#?}, generics={2:#?}",
        self.def_path_str(def_id), args,
        self.mk_args_from_iter([self.types.self_param.into()].into_iter().chain(self.generics_of(def_id).own_args(ty::GenericArgs::identity_for_item(self,
                                def_id)).iter().copied()))));bug!(
2154                    "args not compatible with generics for {}: args={:#?}, generics={:#?}",
2155                    self.def_path_str(def_id),
2156                    args,
2157                    // Make `[Self, GAT_ARGS...]` (this could be simplified)
2158                    self.mk_args_from_iter(
2159                        [self.types.self_param.into()].into_iter().chain(
2160                            self.generics_of(def_id)
2161                                .own_args(ty::GenericArgs::identity_for_item(self, def_id))
2162                                .iter()
2163                                .copied()
2164                        )
2165                    )
2166                );
2167            } else {
2168                crate::util::bug::bug_fmt(format_args!("args not compatible with generics for {0}: args={1:#?}, generics={2:#?}",
        self.def_path_str(def_id), args,
        ty::GenericArgs::identity_for_item(self, def_id)));bug!(
2169                    "args not compatible with generics for {}: args={:#?}, generics={:#?}",
2170                    self.def_path_str(def_id),
2171                    args,
2172                    ty::GenericArgs::identity_for_item(self, def_id)
2173                );
2174            }
2175        }
2176    }
2177
2178    #[inline(always)]
2179    pub(crate) fn check_and_mk_args(
2180        self,
2181        def_id: DefId,
2182        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
2183    ) -> GenericArgsRef<'tcx> {
2184        let args = self.mk_args_from_iter(args.into_iter().map(Into::into));
2185        self.debug_assert_args_compatible(def_id, args);
2186        args
2187    }
2188
2189    #[inline]
2190    pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
2191        self.interners.intern_const(kind)
2192    }
2193
2194    // Avoid this in favour of more specific `Ty::new_*` methods, where possible.
2195    #[allow(rustc::usage_of_ty_tykind)]
2196    #[inline]
2197    pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
2198        self.interners.intern_ty(st)
2199    }
2200
2201    pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
2202        match param.kind {
2203            GenericParamDefKind::Lifetime => {
2204                ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
2205            }
2206            GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
2207            GenericParamDefKind::Const { .. } => {
2208                ty::Const::new_param(self, ParamConst { index: param.index, name: param.name })
2209                    .into()
2210            }
2211        }
2212    }
2213
2214    pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> {
2215        self.mk_place_elem(place, PlaceElem::Field(f, ty))
2216    }
2217
2218    pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
2219        self.mk_place_elem(place, PlaceElem::Deref)
2220    }
2221
2222    pub fn mk_place_downcast(
2223        self,
2224        place: Place<'tcx>,
2225        adt_def: AdtDef<'tcx>,
2226        variant_index: VariantIdx,
2227    ) -> Place<'tcx> {
2228        self.mk_place_elem(
2229            place,
2230            PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
2231        )
2232    }
2233
2234    pub fn mk_place_downcast_unnamed(
2235        self,
2236        place: Place<'tcx>,
2237        variant_index: VariantIdx,
2238    ) -> Place<'tcx> {
2239        self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
2240    }
2241
2242    pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
2243        self.mk_place_elem(place, PlaceElem::Index(index))
2244    }
2245
2246    /// This method copies `Place`'s projection, add an element and reintern it. Should not be used
2247    /// to build a full `Place` it's just a convenient way to grab a projection and modify it in
2248    /// flight.
2249    pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
2250        Place {
2251            local: place.local,
2252            projection: self.mk_place_elems_from_iter(place.projection.iter().chain([elem])),
2253        }
2254    }
2255
2256    pub fn mk_poly_existential_predicates(
2257        self,
2258        eps: &[PolyExistentialPredicate<'tcx>],
2259    ) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
2260        if !!eps.is_empty() {
    ::core::panicking::panic("assertion failed: !eps.is_empty()")
};assert!(!eps.is_empty());
2261        if !eps.array_windows().all(|[a, b]|
                a.skip_binder().stable_cmp(self, &b.skip_binder()) !=
                    Ordering::Greater) {
    ::core::panicking::panic("assertion failed: eps.array_windows().all(|[a, b]|\n        a.skip_binder().stable_cmp(self, &b.skip_binder()) !=\n            Ordering::Greater)")
};assert!(
2262            eps.array_windows()
2263                .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
2264                    != Ordering::Greater)
2265        );
2266        self.intern_poly_existential_predicates(eps)
2267    }
2268
2269    pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> Clauses<'tcx> {
2270        // FIXME consider asking the input slice to be sorted to avoid
2271        // re-interning permutations, in which case that would be asserted
2272        // here.
2273        self.interners.intern_clauses(clauses)
2274    }
2275
2276    pub fn mk_local_def_ids(self, def_ids: &[LocalDefId]) -> &'tcx List<LocalDefId> {
2277        // FIXME consider asking the input slice to be sorted to avoid
2278        // re-interning permutations, in which case that would be asserted
2279        // here.
2280        self.intern_local_def_ids(def_ids)
2281    }
2282
2283    pub fn mk_patterns_from_iter<I, T>(self, iter: I) -> T::Output
2284    where
2285        I: Iterator<Item = T>,
2286        T: CollectAndApply<ty::Pattern<'tcx>, &'tcx List<ty::Pattern<'tcx>>>,
2287    {
2288        T::collect_and_apply(iter, |xs| self.mk_patterns(xs))
2289    }
2290
2291    pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output
2292    where
2293        I: Iterator<Item = T>,
2294        T: CollectAndApply<LocalDefId, &'tcx List<LocalDefId>>,
2295    {
2296        T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs))
2297    }
2298
2299    pub fn mk_captures_from_iter<I, T>(self, iter: I) -> T::Output
2300    where
2301        I: Iterator<Item = T>,
2302        T: CollectAndApply<
2303                &'tcx ty::CapturedPlace<'tcx>,
2304                &'tcx List<&'tcx ty::CapturedPlace<'tcx>>,
2305            >,
2306    {
2307        T::collect_and_apply(iter, |xs| self.intern_captures(xs))
2308    }
2309
2310    pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
2311    where
2312        I: Iterator<Item = T>,
2313        T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
2314    {
2315        T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
2316    }
2317
2318    // Unlike various other `mk_*_from_iter` functions, this one uses `I:
2319    // IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
2320    // variant, because of the need to combine `inputs` and `output`. This
2321    // explains the lack of `_from_iter` suffix.
2322    pub fn mk_fn_sig<I, T>(
2323        self,
2324        inputs: I,
2325        output: I::Item,
2326        fn_sig_kind: FnSigKind<'tcx>,
2327    ) -> T::Output
2328    where
2329        I: IntoIterator<Item = T>,
2330        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
2331    {
2332        T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
2333            inputs_and_output: self.mk_type_list(xs),
2334            fn_sig_kind,
2335        })
2336    }
2337
2338    /// `mk_fn_sig`, but with a Rust ABI, and no C-variadic argument.
2339    pub fn mk_fn_sig_rust_abi<I, T>(
2340        self,
2341        inputs: I,
2342        output: I::Item,
2343        safety: hir::Safety,
2344    ) -> T::Output
2345    where
2346        I: IntoIterator<Item = T>,
2347        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
2348    {
2349        self.mk_fn_sig(inputs, output, FnSigKind::default().set_safety(safety))
2350    }
2351
2352    /// `mk_fn_sig`, but with a safe Rust ABI, and no C-variadic argument.
2353    pub fn mk_fn_sig_safe_rust_abi<I, T>(self, inputs: I, output: I::Item) -> T::Output
2354    where
2355        I: IntoIterator<Item = T>,
2356        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
2357    {
2358        self.mk_fn_sig(inputs, output, FnSigKind::default().set_safety(hir::Safety::Safe))
2359    }
2360
2361    pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
2362    where
2363        I: Iterator<Item = T>,
2364        T: CollectAndApply<
2365                PolyExistentialPredicate<'tcx>,
2366                &'tcx List<PolyExistentialPredicate<'tcx>>,
2367            >,
2368    {
2369        T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
2370    }
2371
2372    pub fn mk_predefined_opaques_in_body_from_iter<I, T>(self, iter: I) -> T::Output
2373    where
2374        I: Iterator<Item = T>,
2375        T: CollectAndApply<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>), PredefinedOpaques<'tcx>>,
2376    {
2377        T::collect_and_apply(iter, |xs| self.mk_predefined_opaques_in_body(xs))
2378    }
2379
2380    pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
2381    where
2382        I: Iterator<Item = T>,
2383        T: CollectAndApply<Clause<'tcx>, Clauses<'tcx>>,
2384    {
2385        T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
2386    }
2387
2388    pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
2389    where
2390        I: Iterator<Item = T>,
2391        T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
2392    {
2393        T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
2394    }
2395
2396    pub fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
2397    where
2398        I: Iterator<Item = T>,
2399        T: CollectAndApply<GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>,
2400    {
2401        T::collect_and_apply(iter, |xs| self.mk_args(xs))
2402    }
2403
2404    pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
2405    where
2406        I: Iterator<Item = T>,
2407        T: CollectAndApply<CanonicalVarKind<'tcx>, &'tcx List<CanonicalVarKind<'tcx>>>,
2408    {
2409        T::collect_and_apply(iter, |xs| self.mk_canonical_var_kinds(xs))
2410    }
2411
2412    pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
2413    where
2414        I: Iterator<Item = T>,
2415        T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
2416    {
2417        T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
2418    }
2419
2420    pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
2421    where
2422        I: Iterator<Item = T>,
2423        T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,
2424    {
2425        T::collect_and_apply(iter, |xs| self.mk_fields(xs))
2426    }
2427
2428    pub fn mk_args_trait(
2429        self,
2430        self_ty: Ty<'tcx>,
2431        rest: impl IntoIterator<Item = GenericArg<'tcx>>,
2432    ) -> GenericArgsRef<'tcx> {
2433        self.mk_args_from_iter(iter::once(self_ty.into()).chain(rest))
2434    }
2435
2436    pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
2437    where
2438        I: Iterator<Item = T>,
2439        T: CollectAndApply<ty::BoundVariableKind<'tcx>, &'tcx List<ty::BoundVariableKind<'tcx>>>,
2440    {
2441        T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
2442    }
2443
2444    pub fn mk_outlives_from_iter<I, T>(self, iter: I) -> T::Output
2445    where
2446        I: Iterator<Item = T>,
2447        T: CollectAndApply<
2448                ty::ArgOutlivesPredicate<'tcx>,
2449                &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>>,
2450            >,
2451    {
2452        T::collect_and_apply(iter, |xs| self.mk_outlives(xs))
2453    }
2454
2455    /// Emit a lint at `span` from a lint struct (some type that implements `Diagnostic`,
2456    /// typically generated by `#[derive(Diagnostic)]`).
2457    #[track_caller]
2458    pub fn emit_node_span_lint(
2459        self,
2460        lint: &'static Lint,
2461        hir_id: HirId,
2462        span: impl Into<MultiSpan>,
2463        decorator: impl for<'a> Diagnostic<'a, ()>,
2464    ) {
2465        let level = self.lint_level_at_node(lint, hir_id);
2466        emit_lint_base(self.sess, lint, level, Some(span.into()), decorator)
2467    }
2468
2469    /// Find the appropriate span where `use` and outer attributes can be inserted at.
2470    pub fn crate_level_attribute_injection_span(self) -> Span {
2471        let node = self.hir_node(hir::CRATE_HIR_ID);
2472        let hir::Node::Crate(m) = node else { crate::util::bug::bug_fmt(format_args!("impossible case reached"))bug!() };
2473        m.spans.inject_use_span.shrink_to_lo()
2474    }
2475
2476    pub fn disabled_nightly_features<E: rustc_errors::EmissionGuarantee>(
2477        self,
2478        diag: &mut Diag<'_, E>,
2479        features: impl IntoIterator<Item = (String, Symbol)>,
2480    ) {
2481        if !self.sess.is_nightly_build() {
2482            return;
2483        }
2484
2485        let span = self.crate_level_attribute_injection_span();
2486        for (desc, feature) in features {
2487            // FIXME: make this string translatable
2488            let msg =
2489                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("add `#![feature({0})]` to the crate attributes to enable{1}",
                feature, desc))
    })format!("add `#![feature({feature})]` to the crate attributes to enable{desc}");
2490            diag.span_suggestion_verbose(
2491                span,
2492                msg,
2493                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#![feature({0})]\n", feature))
    })format!("#![feature({feature})]\n"),
2494                Applicability::MaybeIncorrect,
2495            );
2496        }
2497    }
2498
2499    /// Emit a lint from a lint struct (some type that implements `Diagnostic`, typically generated
2500    /// by `#[derive(Diagnostic)]`).
2501    #[track_caller]
2502    pub fn emit_node_lint(
2503        self,
2504        lint: &'static Lint,
2505        id: HirId,
2506        decorator: impl for<'a> Diagnostic<'a, ()>,
2507    ) {
2508        let level = self.lint_level_at_node(lint, id);
2509        emit_lint_base(self.sess, lint, level, None, decorator);
2510    }
2511
2512    pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate<'tcx>]> {
2513        let map = self.in_scope_traits_map(id.owner)?;
2514        let candidates = map.get(&id.local_id)?;
2515        Some(candidates)
2516    }
2517
2518    pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
2519        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/context.rs:2519",
                        "rustc_middle::ty::context", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/context.rs"),
                        ::tracing_core::__macro_support::Option::Some(2519u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::context"),
                        ::tracing_core::field::FieldSet::new(&["message", "id"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("named_region")
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&id) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(?id, "named_region");
2520        self.named_variable_map(id.owner).get(&id.local_id).cloned()
2521    }
2522
2523    pub fn is_late_bound(self, id: HirId) -> bool {
2524        self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
2525    }
2526
2527    pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind<'tcx>> {
2528        self.mk_bound_variable_kinds(
2529            &self
2530                .late_bound_vars_map(id.owner)
2531                .get(&id.local_id)
2532                .cloned()
2533                .unwrap_or_else(|| crate::util::bug::bug_fmt(format_args!("No bound vars found for {0}",
        self.hir_id_to_string(id)))bug!("No bound vars found for {}", self.hir_id_to_string(id))),
2534        )
2535    }
2536
2537    /// Given the def-id of an early-bound lifetime on an opaque corresponding to
2538    /// a duplicated captured lifetime, map it back to the early- or late-bound
2539    /// lifetime of the function from which it originally as captured. If it is
2540    /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
2541    /// of the signature.
2542    // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
2543    // re-use the generics of the opaque, this function will need to be tweaked slightly.
2544    pub fn map_opaque_lifetime_to_parent_lifetime(
2545        self,
2546        mut opaque_lifetime_param_def_id: LocalDefId,
2547    ) -> ty::Region<'tcx> {
2548        if true {
    if !#[allow(non_exhaustive_omitted_patterns)] match self.def_kind(opaque_lifetime_param_def_id)
                {
                DefKind::LifetimeParam => true,
                _ => false,
            } {
        {
            ::core::panicking::panic_fmt(format_args!("{1:?} is a {0}",
                    self.def_descr(opaque_lifetime_param_def_id.to_def_id()),
                    opaque_lifetime_param_def_id));
        }
    };
};debug_assert!(
2549            matches!(self.def_kind(opaque_lifetime_param_def_id), DefKind::LifetimeParam),
2550            "{opaque_lifetime_param_def_id:?} is a {}",
2551            self.def_descr(opaque_lifetime_param_def_id.to_def_id())
2552        );
2553
2554        loop {
2555            let parent = self.local_parent(opaque_lifetime_param_def_id);
2556            let lifetime_mapping = self.opaque_captured_lifetimes(parent);
2557
2558            let Some((lifetime, _)) = lifetime_mapping
2559                .iter()
2560                .find(|(_, duplicated_param)| *duplicated_param == opaque_lifetime_param_def_id)
2561            else {
2562                crate::util::bug::bug_fmt(format_args!("duplicated lifetime param should be present"));bug!("duplicated lifetime param should be present");
2563            };
2564
2565            match *lifetime {
2566                resolve_bound_vars::ResolvedArg::EarlyBound(ebv) => {
2567                    let new_parent = self.local_parent(ebv);
2568
2569                    // If we map to another opaque, then it should be a parent
2570                    // of the opaque we mapped from. Continue mapping.
2571                    if #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(new_parent) {
    DefKind::OpaqueTy => true,
    _ => false,
}matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
2572                        if true {
    match (&self.local_parent(parent), &new_parent) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    };
};debug_assert_eq!(self.local_parent(parent), new_parent);
2573                        opaque_lifetime_param_def_id = ebv;
2574                        continue;
2575                    }
2576
2577                    let generics = self.generics_of(new_parent);
2578                    return ty::Region::new_early_param(
2579                        self,
2580                        ty::EarlyParamRegion {
2581                            index: generics
2582                                .param_def_id_to_index(self, ebv.to_def_id())
2583                                .expect("early-bound var should be present in fn generics"),
2584                            name: self.item_name(ebv.to_def_id()),
2585                        },
2586                    );
2587                }
2588                resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv) => {
2589                    let new_parent = self.local_parent(lbv);
2590                    return ty::Region::new_late_param(
2591                        self,
2592                        new_parent.to_def_id(),
2593                        ty::LateParamRegionKind::Named(lbv.to_def_id()),
2594                    );
2595                }
2596                resolve_bound_vars::ResolvedArg::Error(guar) => {
2597                    return ty::Region::new_error(self, guar);
2598                }
2599                _ => {
2600                    return ty::Region::new_error_with_message(
2601                        self,
2602                        self.def_span(opaque_lifetime_param_def_id),
2603                        "cannot resolve lifetime",
2604                    );
2605                }
2606            }
2607        }
2608    }
2609
2610    /// Whether `def_id` is a stable const fn (i.e., doesn't need any feature gates to be called).
2611    ///
2612    /// When this is `false`, the function may still be callable as a `const fn` due to features
2613    /// being enabled!
2614    pub fn is_stable_const_fn(self, def_id: DefId) -> bool {
2615        self.is_const_fn(def_id)
2616            && match self.lookup_const_stability(def_id) {
2617                None => true, // a fn in a non-staged_api crate
2618                Some(stability) if stability.is_const_stable() => true,
2619                _ => false,
2620            }
2621    }
2622
2623    /// Whether the trait impl is marked const. This does not consider stability or feature gates.
2624    pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
2625        self.def_kind(def_id) == DefKind::Impl { of_trait: true }
2626            && self.impl_trait_header(def_id).constness == hir::Constness::Const
2627    }
2628
2629    pub fn is_sdylib_interface_build(self) -> bool {
2630        self.sess.opts.unstable_opts.build_sdylib_interface
2631    }
2632
2633    pub fn intrinsic(self, def_id: impl IntoQueryKey<DefId>) -> Option<ty::IntrinsicDef> {
2634        let def_id = def_id.into_query_key();
2635        match self.def_kind(def_id) {
2636            DefKind::Fn | DefKind::AssocFn => self.intrinsic_raw(def_id),
2637            _ => None,
2638        }
2639    }
2640
2641    pub fn next_trait_solver_globally(self) -> bool {
2642        self.sess.opts.unstable_opts.next_solver.globally
2643    }
2644
2645    pub fn next_trait_solver_in_coherence(self) -> bool {
2646        self.sess.opts.unstable_opts.next_solver.coherence
2647    }
2648
2649    pub fn disable_trait_solver_fast_paths(self) -> bool {
2650        self.sess.opts.unstable_opts.disable_fast_paths
2651    }
2652
2653    #[allow(rustc::bad_opt_access)]
2654    pub fn use_typing_mode_borrowck(self) -> bool {
2655        self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck
2656    }
2657
2658    pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
2659        self.opt_rpitit_info(def_id).is_some()
2660    }
2661
2662    /// Named module children from all kinds of items, including imports.
2663    /// In addition to regular items this list also includes struct and variant constructors, and
2664    /// items inside `extern {}` blocks because all of them introduce names into parent module.
2665    ///
2666    /// Module here is understood in name resolution sense - it can be a `mod` item,
2667    /// or a crate root, or an enum, or a trait.
2668    ///
2669    /// This is not a query, making it a query causes perf regressions
2670    /// (probably due to hashing spans in `ModChild`ren).
2671    pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
2672        self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
2673    }
2674
2675    /// Return the crate imported by given use item.
2676    pub fn extern_mod_stmt_cnum(self, def_id: LocalDefId) -> Option<CrateNum> {
2677        self.resolutions(()).extern_crate_map.get(&def_id).copied()
2678    }
2679
2680    pub fn resolver_for_lowering(
2681        self,
2682    ) -> &'tcx Steal<(ty::ResolverAstLowering<'tcx>, Arc<ast::Crate>)> {
2683        self.resolver_for_lowering_raw(()).0
2684    }
2685
2686    pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode {
2687        make_metadata(self)
2688    }
2689
2690    pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool {
2691        if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) =
2692            self.coroutine_kind(def_id)
2693            && let ty::Coroutine(_, args) =
2694                self.type_of(def_id).instantiate_identity().skip_norm_wip().kind()
2695            && args.as_coroutine().kind_ty().to_opt_closure_kind() != Some(ty::ClosureKind::FnOnce)
2696        {
2697            true
2698        } else {
2699            false
2700        }
2701    }
2702
2703    /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
2704    pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
2705        {
        {
            'done:
                {
                for i in
                    ::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self) {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(DoNotRecommend) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(self, def_id, DoNotRecommend)
2706    }
2707
2708    pub fn is_trivial_const(self, def_id: impl IntoQueryKey<DefId>) -> bool {
2709        let def_id = def_id.into_query_key();
2710        self.trivial_const(def_id).is_some()
2711    }
2712
2713    /// Whether this def is one of the special bin crate entrypoint functions that must have a
2714    /// monomorphization and also not be internalized in the bin crate.
2715    pub fn is_entrypoint(self, def_id: DefId) -> bool {
2716        if self.is_lang_item(def_id, LangItem::Start) {
2717            return true;
2718        }
2719        if let Some((entry_def_id, _)) = self.entry_fn(())
2720            && entry_def_id == def_id
2721        {
2722            return true;
2723        }
2724        false
2725    }
2726}
2727
2728pub fn provide(providers: &mut Providers) {
2729    providers.is_panic_runtime = |tcx, LocalCrate| {
        'done:
            {
            for i in tcx.hir_krate_attrs() {
                #[allow(unused_imports)]
                use rustc_hir::attrs::AttributeKind::*;
                let i: &rustc_hir::Attribute = i;
                match i {
                    rustc_hir::Attribute::Parsed(PanicRuntime) => {
                        break 'done Some(());
                    }
                    rustc_hir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }.is_some()find_attr!(tcx, crate, PanicRuntime);
2730    providers.is_compiler_builtins = |tcx, LocalCrate| {
        'done:
            {
            for i in tcx.hir_krate_attrs() {
                #[allow(unused_imports)]
                use rustc_hir::attrs::AttributeKind::*;
                let i: &rustc_hir::Attribute = i;
                match i {
                    rustc_hir::Attribute::Parsed(CompilerBuiltins) => {
                        break 'done Some(());
                    }
                    rustc_hir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }.is_some()find_attr!(tcx, crate, CompilerBuiltins);
2731    providers.has_panic_handler = |tcx, LocalCrate| {
2732        // We want to check if the panic handler was defined in this crate
2733        tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
2734    };
2735    providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
2736}