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_hash::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::StableHashState;
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>(self, f: impl FnOnce(StableHashState<'_>) -> R) -> R {
1393        f(StableHashState::new(self.sess, &self.untracked))
1394    }
1395
1396    #[inline]
1397    pub fn local_crate_exports_generics(self) -> bool {
1398        // compiler-builtins has some special treatment in codegen, which can result in confusing
1399        // behavior if another crate ends up calling into its monomorphizations.
1400        // https://github.com/rust-lang/rust/issues/150173
1401        if self.is_compiler_builtins(LOCAL_CRATE) {
1402            return false;
1403        }
1404        self.crate_types().iter().any(|crate_type| {
1405            match crate_type {
1406                CrateType::Executable
1407                | CrateType::StaticLib
1408                | CrateType::ProcMacro
1409                | CrateType::Cdylib
1410                | CrateType::Sdylib => false,
1411
1412                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
1413                // We want to block export of generics from dylibs,
1414                // but we must fix rust-lang/rust#65890 before we can
1415                // do that robustly.
1416                CrateType::Dylib => true,
1417
1418                CrateType::Rlib => true,
1419            }
1420        })
1421    }
1422
1423    /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
1424    pub fn is_suitable_region(
1425        self,
1426        generic_param_scope: LocalDefId,
1427        mut region: Region<'tcx>,
1428    ) -> Option<FreeRegionInfo> {
1429        let (suitable_region_binding_scope, region_def_id) = loop {
1430            let def_id =
1431                region.opt_param_def_id(self, generic_param_scope.to_def_id())?.as_local()?;
1432            let scope = self.local_parent(def_id);
1433            if self.def_kind(scope) == DefKind::OpaqueTy {
1434                // Lifetime params of opaque types are synthetic and thus irrelevant to
1435                // diagnostics. Map them back to their origin!
1436                region = self.map_opaque_lifetime_to_parent_lifetime(def_id);
1437                continue;
1438            }
1439            break (scope, def_id.into());
1440        };
1441
1442        let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) {
1443            Node::Item(..) | Node::TraitItem(..) => false,
1444            Node::ImplItem(impl_item) => match impl_item.impl_kind {
1445                // For now, we do not try to target impls of traits. This is
1446                // because this message is going to suggest that the user
1447                // change the fn signature, but they may not be free to do so,
1448                // since the signature must match the trait.
1449                //
1450                // FIXME(#42706) -- in some cases, we could do better here.
1451                hir::ImplItemImplKind::Trait { .. } => true,
1452                _ => false,
1453            },
1454            _ => false,
1455        };
1456
1457        Some(FreeRegionInfo { scope: suitable_region_binding_scope, region_def_id, is_impl_item })
1458    }
1459
1460    /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
1461    pub fn return_type_impl_or_dyn_traits(
1462        self,
1463        scope_def_id: LocalDefId,
1464    ) -> Vec<&'tcx hir::Ty<'tcx>> {
1465        let hir_id = self.local_def_id_to_hir_id(scope_def_id);
1466        let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) =
1467            self.hir_fn_decl_by_hir_id(hir_id)
1468        else {
1469            return ::alloc::vec::Vec::new()vec![];
1470        };
1471
1472        let mut v = TraitObjectVisitor(::alloc::vec::Vec::new()vec![]);
1473        v.visit_ty_unambig(hir_output);
1474        v.0
1475    }
1476
1477    /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
1478    /// its return type, and the associated alias span when type alias is used,
1479    /// along with a span for lifetime suggestion (if there are existing generics).
1480    pub fn return_type_impl_or_dyn_traits_with_type_alias(
1481        self,
1482        scope_def_id: LocalDefId,
1483    ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
1484        let hir_id = self.local_def_id_to_hir_id(scope_def_id);
1485        let mut v = TraitObjectVisitor(::alloc::vec::Vec::new()vec![]);
1486        // when the return type is a type alias
1487        if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id)
1488            && let hir::TyKind::Path(hir::QPath::Resolved(
1489                None,
1490                hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
1491            && let Some(local_id) = def_id.as_local()
1492            && let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias
1493            && let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics()
1494        {
1495            v.visit_ty_unambig(alias_ty);
1496            if !v.0.is_empty() {
1497                return Some((
1498                    v.0,
1499                    alias_generics.span,
1500                    alias_generics.span_for_lifetime_suggestion(),
1501                ));
1502            }
1503        }
1504        None
1505    }
1506
1507    /// Determines whether identifiers in the assembly have strict naming rules.
1508    /// Currently, only NVPTX* targets need it.
1509    pub fn has_strict_asm_symbol_naming(self) -> bool {
1510        self.sess.target.llvm_target.starts_with("nvptx")
1511    }
1512
1513    /// Returns `&'static core::panic::Location<'static>`.
1514    pub fn caller_location_ty(self) -> Ty<'tcx> {
1515        Ty::new_imm_ref(
1516            self,
1517            self.lifetimes.re_static,
1518            self.type_of(self.require_lang_item(LangItem::PanicLocation, DUMMY_SP))
1519                .instantiate(self, self.mk_args(&[self.lifetimes.re_static.into()]))
1520                .skip_norm_wip(),
1521        )
1522    }
1523
1524    /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
1525    pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
1526        let kind = self.def_kind(def_id);
1527        (self.def_kind_descr_article(kind, def_id), self.def_kind_descr(kind, def_id))
1528    }
1529
1530    pub fn type_length_limit(self) -> Limit {
1531        self.limits(()).type_length_limit
1532    }
1533
1534    pub fn recursion_limit(self) -> Limit {
1535        self.limits(()).recursion_limit
1536    }
1537
1538    pub fn move_size_limit(self) -> Limit {
1539        self.limits(()).move_size_limit
1540    }
1541
1542    pub fn pattern_complexity_limit(self) -> Limit {
1543        self.limits(()).pattern_complexity_limit
1544    }
1545
1546    /// All traits in the crate graph, including those not visible to the user.
1547    pub fn all_traits_including_private(self) -> impl Iterator<Item = DefId> {
1548        iter::once(LOCAL_CRATE)
1549            .chain(self.crates(()).iter().copied())
1550            .flat_map(move |cnum| self.traits(cnum).iter().copied())
1551    }
1552
1553    /// All traits that are visible within the crate graph (i.e. excluding private dependencies).
1554    pub fn visible_traits(self) -> impl Iterator<Item = DefId> {
1555        let visible_crates =
1556            self.crates(()).iter().copied().filter(move |cnum| self.is_user_visible_dep(*cnum));
1557
1558        iter::once(LOCAL_CRATE)
1559            .chain(visible_crates)
1560            .flat_map(move |cnum| self.traits(cnum).iter().copied())
1561    }
1562
1563    #[inline]
1564    pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
1565        self.visibility(def_id).expect_local()
1566    }
1567
1568    /// Returns the origin of the opaque type `def_id`.
1569    x;#[instrument(skip(self), level = "trace", ret)]
1570    pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
1571        self.hir_expect_opaque_ty(def_id).origin
1572    }
1573
1574    pub fn finish(self) {
1575        // We assume that no queries are run past here. If there are new queries
1576        // after this point, they'll show up as "<unknown>" in self-profiling data.
1577        self.alloc_self_profile_query_strings();
1578
1579        self.save_dep_graph();
1580        self.verify_query_key_hashes();
1581
1582        if let Err((path, error)) = self.dep_graph.finish_encoding() {
1583            self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error });
1584        }
1585    }
1586
1587    pub fn report_unused_features(self) {
1588        #[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)]
1589        #[diag("feature `{$feature}` is declared but not used")]
1590        struct UnusedFeature {
1591            feature: Symbol,
1592        }
1593
1594        // Collect first to avoid holding the lock while linting.
1595        let used_features = self.sess.used_features.lock();
1596        let unused_features = self
1597            .features()
1598            .enabled_features_iter_stable_order()
1599            .filter(|(f, _)| {
1600                !used_features.contains_key(f)
1601                // FIXME: `restricted_std` is used to tell a standard library built
1602                // for a platform that it doesn't know how to support. But it
1603                // could only gate a private mod (see `__restricted_std_workaround`)
1604                // with `cfg(not(restricted_std))`, so it cannot be recorded as used
1605                // in downstream crates. It should never be linted, but should we
1606                // hack this in the linter to ignore it?
1607                && f.as_str() != "restricted_std"
1608                // `doc_cfg` affects rustdoc behavior: rustdoc checks it via
1609                // `tcx.features().doc_cfg()`, but a normal rustc compilation may
1610                // never observe that use. Do not lint it as unused here.
1611                && *f != sym::doc_cfg
1612            })
1613            .collect::<Vec<_>>();
1614
1615        for (feature, span) in unused_features {
1616            self.emit_node_span_lint(
1617                rustc_session::lint::builtin::UNUSED_FEATURES,
1618                CRATE_HIR_ID,
1619                span,
1620                UnusedFeature { feature },
1621            );
1622        }
1623    }
1624}
1625
1626macro_rules! nop_lift {
1627    ($set:ident; $ty:ty => $lifted:ty) => {
1628        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for $ty {
1629            type Lifted = $lifted;
1630            #[track_caller]
1631            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
1632                // Assert that the set has the right type.
1633                // Given an argument that has an interned type, the return type has the type of
1634                // the corresponding interner set. This won't actually return anything, we're
1635                // just doing this to compute said type!
1636                fn _intern_set_ty_from_interned_ty<'tcx, Inner>(
1637                    _x: Interned<'tcx, Inner>,
1638                ) -> InternedSet<'tcx, Inner> {
1639                    unreachable!()
1640                }
1641                fn _type_eq<T>(_x: &T, _y: &T) {}
1642                fn _test<'tcx>(x: $lifted, tcx: TyCtxt<'tcx>) {
1643                    // If `x` is a newtype around an `Interned<T>`, then `interner` is an
1644                    // interner of appropriate type. (Ideally we'd also check that `x` is a
1645                    // newtype with just that one field. Not sure how to do that.)
1646                    let interner = _intern_set_ty_from_interned_ty(x.0);
1647                    // Now check that this is the same type as `interners.$set`.
1648                    _type_eq(&interner, &tcx.interners.$set);
1649                }
1650
1651                assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)));
1652                // SAFETY: we just checked that `self` is interned and therefore is valid for the
1653                // entire lifetime of the `TyCtxt`.
1654                unsafe { mem::transmute(self) }
1655            }
1656        }
1657    };
1658}
1659
1660macro_rules! nop_list_lift {
1661    ($set:ident; $ty:ty => $lifted:ty) => {
1662        impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<$ty> {
1663            type Lifted = &'tcx List<$lifted>;
1664            fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
1665                // Assert that the set has the right type.
1666                if false {
1667                    let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set;
1668                }
1669
1670                if self.is_empty() {
1671                    return List::empty();
1672                }
1673                assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(self)));
1674                // SAFETY: we just checked that `self` is interned and therefore is valid for the
1675                // entire lifetime of the `TyCtxt`.
1676                unsafe { mem::transmute(self) }
1677            }
1678        }
1679    };
1680}
1681
1682impl<'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> }
1683impl<'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> }
1684impl<'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> }
1685impl<'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> }
1686impl<'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> }
1687impl<'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> }
1688impl<'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> }
1689impl<'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> }
1690impl<'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> }
1691
1692impl<'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> }
1693impl<'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! {
1694    poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>
1695}
1696impl<'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> }
1697
1698// This is the impl for `&'a GenericArgs<'a>`.
1699impl<'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> }
1700
1701macro_rules! sty_debug_print {
1702    ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
1703        // Curious inner module to allow variant names to be used as
1704        // variable names.
1705        #[allow(non_snake_case)]
1706        mod inner {
1707            use crate::ty::{self, TyCtxt};
1708            use crate::ty::context::InternedInSet;
1709
1710            #[derive(Copy, Clone)]
1711            struct DebugStat {
1712                total: usize,
1713                lt_infer: usize,
1714                ty_infer: usize,
1715                ct_infer: usize,
1716                all_infer: usize,
1717            }
1718
1719            pub(crate) fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
1720                let mut total = DebugStat {
1721                    total: 0,
1722                    lt_infer: 0,
1723                    ty_infer: 0,
1724                    ct_infer: 0,
1725                    all_infer: 0,
1726                };
1727                $(let mut $variant = total;)*
1728
1729                for shard in tcx.interners.type_.lock_shards() {
1730                    // It seems that ordering doesn't affect anything here.
1731                    #[allow(rustc::potential_query_instability)]
1732                    let types = shard.iter();
1733                    for &(InternedInSet(t), ()) in types {
1734                        let variant = match t.internee {
1735                            ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
1736                                ty::Float(..) | ty::Str | ty::Never => continue,
1737                            ty::Error(_) => /* unimportant */ continue,
1738                            $(ty::$variant(..) => &mut $variant,)*
1739                        };
1740                        let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
1741                        let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
1742                        let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
1743
1744                        variant.total += 1;
1745                        total.total += 1;
1746                        if lt { total.lt_infer += 1; variant.lt_infer += 1 }
1747                        if ty { total.ty_infer += 1; variant.ty_infer += 1 }
1748                        if ct { total.ct_infer += 1; variant.ct_infer += 1 }
1749                        if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
1750                    }
1751                }
1752                writeln!(fmt, "Ty interner             total           ty lt ct all")?;
1753                $(writeln!(fmt, "    {:18}: {uses:6} {usespc:4.1}%, \
1754                            {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1755                    stringify!($variant),
1756                    uses = $variant.total,
1757                    usespc = $variant.total as f64 * 100.0 / total.total as f64,
1758                    ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
1759                    lt = $variant.lt_infer as f64 * 100.0  / total.total as f64,
1760                    ct = $variant.ct_infer as f64 * 100.0  / total.total as f64,
1761                    all = $variant.all_infer as f64 * 100.0  / total.total as f64)?;
1762                )*
1763                writeln!(fmt, "                  total {uses:6}        \
1764                          {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1765                    uses = total.total,
1766                    ty = total.ty_infer as f64 * 100.0  / total.total as f64,
1767                    lt = total.lt_infer as f64 * 100.0  / total.total as f64,
1768                    ct = total.ct_infer as f64 * 100.0  / total.total as f64,
1769                    all = total.all_infer as f64 * 100.0  / total.total as f64)
1770            }
1771        }
1772
1773        inner::go($fmt, $ctxt)
1774    }}
1775}
1776
1777impl<'tcx> TyCtxt<'tcx> {
1778    pub fn debug_stats(self) -> impl fmt::Debug {
1779        fmt::from_fn(move |fmt| {
1780            {
    #[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!(
1781                fmt,
1782                self,
1783                Adt,
1784                Array,
1785                Slice,
1786                RawPtr,
1787                Ref,
1788                FnDef,
1789                FnPtr,
1790                UnsafeBinder,
1791                Placeholder,
1792                Coroutine,
1793                CoroutineWitness,
1794                Dynamic,
1795                Closure,
1796                CoroutineClosure,
1797                Tuple,
1798                Bound,
1799                Param,
1800                Infer,
1801                Alias,
1802                Pat,
1803                Foreign
1804            )?;
1805
1806            fmt.write_fmt(format_args!("GenericArgs interner: #{0}\n",
        self.interners.args.len()))writeln!(fmt, "GenericArgs interner: #{}", self.interners.args.len())?;
1807            fmt.write_fmt(format_args!("Region interner: #{0}\n",
        self.interners.region.len()))writeln!(fmt, "Region interner: #{}", self.interners.region.len())?;
1808            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())?;
1809            fmt.write_fmt(format_args!("Layout interner: #{0}\n",
        self.interners.layout.len()))writeln!(fmt, "Layout interner: #{}", self.interners.layout.len())?;
1810
1811            Ok(())
1812        })
1813    }
1814}
1815
1816// This type holds a `T` in the interner. The `T` is stored in the arena and
1817// this type just holds a pointer to it, but it still effectively owns it. It
1818// impls `Borrow` so that it can be looked up using the original
1819// (non-arena-memory-owning) types.
1820struct InternedInSet<'tcx, T: ?Sized + PointeeSized>(&'tcx T);
1821
1822impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Clone for InternedInSet<'tcx, T> {
1823    fn clone(&self) -> Self {
1824        *self
1825    }
1826}
1827
1828impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Copy for InternedInSet<'tcx, T> {}
1829
1830impl<'tcx, T: 'tcx + ?Sized + PointeeSized> IntoPointer for InternedInSet<'tcx, T> {
1831    fn into_pointer(&self) -> *const () {
1832        self.0 as *const _ as *const ()
1833    }
1834}
1835
1836#[allow(rustc::usage_of_ty_tykind)]
1837impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1838    fn borrow(&self) -> &T {
1839        &self.0.internee
1840    }
1841}
1842
1843impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1844    fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
1845        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1846        // `x == y`.
1847        self.0.internee == other.0.internee
1848    }
1849}
1850
1851impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
1852
1853impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1854    fn hash<H: Hasher>(&self, s: &mut H) {
1855        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1856        self.0.internee.hash(s)
1857    }
1858}
1859
1860impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
1861    fn borrow(&self) -> &[T] {
1862        &self.0[..]
1863    }
1864}
1865
1866impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> {
1867    fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool {
1868        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1869        // `x == y`.
1870        self.0[..] == other.0[..]
1871    }
1872}
1873
1874impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {}
1875
1876impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
1877    fn hash<H: Hasher>(&self, s: &mut H) {
1878        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1879        self.0[..].hash(s)
1880    }
1881}
1882
1883impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1884    fn borrow(&self) -> &[T] {
1885        &self.0[..]
1886    }
1887}
1888
1889impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1890    fn eq(&self, other: &InternedInSet<'tcx, ListWithCachedTypeInfo<T>>) -> bool {
1891        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1892        // `x == y`.
1893        self.0[..] == other.0[..]
1894    }
1895}
1896
1897impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {}
1898
1899impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, ListWithCachedTypeInfo<T>> {
1900    fn hash<H: Hasher>(&self, s: &mut H) {
1901        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1902        self.0[..].hash(s)
1903    }
1904}
1905
1906macro_rules! direct_interners {
1907    ($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
1908        $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
1909            fn borrow<'a>(&'a self) -> &'a $ty {
1910                &self.0
1911            }
1912        }
1913
1914        impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
1915            fn eq(&self, other: &Self) -> bool {
1916                // The `Borrow` trait requires that `x.borrow() == y.borrow()`
1917                // equals `x == y`.
1918                self.0 == other.0
1919            }
1920        }
1921
1922        impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
1923
1924        impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
1925            fn hash<H: Hasher>(&self, s: &mut H) {
1926                // The `Borrow` trait requires that `x.borrow().hash(s) ==
1927                // x.hash(s)`.
1928                self.0.hash(s)
1929            }
1930        }
1931
1932        impl<'tcx> TyCtxt<'tcx> {
1933            $vis fn $method(self, v: $ty) -> $ret_ty {
1934                $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
1935                    InternedInSet(self.interners.arena.alloc(v))
1936                }).0))
1937            }
1938        })+
1939    }
1940}
1941
1942// Functions with a `mk_` prefix are intended for use outside this file and
1943// crate. Functions with an `intern_` prefix are intended for use within this
1944// crate only, and have a corresponding `mk_` function.
1945impl<'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! {
1946    region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
1947    valtree: pub(crate) intern_valtree(ValTreeKind<TyCtxt<'tcx>>): ValTree -> ValTree<'tcx>,
1948    pat: pub mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>,
1949    const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
1950    layout: pub mk_layout(LayoutData<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
1951    adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
1952    external_constraints: pub mk_external_constraints(ExternalConstraintsData<TyCtxt<'tcx>>):
1953        ExternalConstraints -> ExternalConstraints<'tcx>,
1954}
1955
1956macro_rules! slice_interners {
1957    ($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
1958        impl<'tcx> TyCtxt<'tcx> {
1959            $($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
1960                if v.is_empty() {
1961                    List::empty()
1962                } else {
1963                    self.interners.$field.intern_ref(v, || {
1964                        InternedInSet(List::from_arena(&*self.arena, (), v))
1965                    }).0
1966                }
1967            })+
1968        }
1969    );
1970}
1971
1972// These functions intern slices. They all have a corresponding
1973// `mk_foo_from_iter` function that interns an iterator. The slice version
1974// should be used when possible, because it's faster.
1975impl<'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!(
1976    const_lists: pub mk_const_list(Const<'tcx>),
1977    args: pub mk_args(GenericArg<'tcx>),
1978    type_lists: pub mk_type_list(Ty<'tcx>),
1979    canonical_var_kinds: pub mk_canonical_var_kinds(CanonicalVarKind<'tcx>),
1980    poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
1981    projs: pub mk_projs(ProjectionKind),
1982    place_elems: pub mk_place_elems(PlaceElem<'tcx>),
1983    bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind<'tcx>),
1984    fields: pub mk_fields(FieldIdx),
1985    local_def_ids: intern_local_def_ids(LocalDefId),
1986    captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
1987    patterns: pub mk_patterns(Pattern<'tcx>),
1988    outlives: pub mk_outlives(ty::ArgOutlivesPredicate<'tcx>),
1989    predefined_opaques_in_body: pub mk_predefined_opaques_in_body((ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)),
1990);
1991
1992impl<'tcx> TyCtxt<'tcx> {
1993    /// Given a `fn` sig, returns an equivalent `unsafe fn` type;
1994    /// that is, a `fn` type that is equivalent in every way for being
1995    /// unsafe.
1996    pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
1997        if !sig.safety().is_safe() {
    ::core::panicking::panic("assertion failed: sig.safety().is_safe()")
};assert!(sig.safety().is_safe());
1998        Ty::new_fn_ptr(
1999            self,
2000            sig.map_bound(|sig| ty::FnSig {
2001                fn_sig_kind: sig.fn_sig_kind.set_safety(hir::Safety::Unsafe),
2002                ..sig
2003            }),
2004        )
2005    }
2006
2007    /// Given a `fn` sig, returns an equivalent `unsafe fn` sig;
2008    /// that is, a `fn` sig that is equivalent in every way for being
2009    /// unsafe.
2010    pub fn safe_to_unsafe_sig(self, sig: PolyFnSig<'tcx>) -> PolyFnSig<'tcx> {
2011        if !sig.safety().is_safe() {
    ::core::panicking::panic("assertion failed: sig.safety().is_safe()")
};assert!(sig.safety().is_safe());
2012        sig.map_bound(|sig| ty::FnSig {
2013            fn_sig_kind: sig.fn_sig_kind.set_safety(hir::Safety::Unsafe),
2014            ..sig
2015        })
2016    }
2017
2018    /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
2019    /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
2020    pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
2021        elaborate::supertrait_def_ids(self, trait_def_id).any(|trait_did| {
2022            self.associated_items(trait_did)
2023                .filter_by_name_unhygienic(assoc_name.name)
2024                .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did))
2025        })
2026    }
2027
2028    /// Given a `ty`, return whether it's an `impl Future<...>`.
2029    pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
2030        let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *ty.kind() else {
2031            return false;
2032        };
2033        let future_trait = self.require_lang_item(LangItem::Future, DUMMY_SP);
2034
2035        self.explicit_item_self_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
2036            let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
2037                return false;
2038            };
2039            trait_predicate.trait_ref.def_id == future_trait
2040                && trait_predicate.polarity == PredicatePolarity::Positive
2041        })
2042    }
2043
2044    /// Given a closure signature, returns an equivalent fn signature. Detuples
2045    /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
2046    /// you would get a `fn(u32, i32)`.
2047    /// `unsafety` determines the unsafety of the fn signature. If you pass
2048    /// `hir::Safety::Unsafe` in the previous example, then you would get
2049    /// an `unsafe fn (u32, i32)`.
2050    /// It cannot convert a closure that requires unsafe.
2051    pub fn signature_unclosure(self, sig: PolyFnSig<'tcx>, safety: hir::Safety) -> PolyFnSig<'tcx> {
2052        sig.map_bound(|s| {
2053            let params = match s.inputs()[0].kind() {
2054                ty::Tuple(params) => *params,
2055                _ => crate::util::bug::bug_fmt(format_args!("impossible case reached"))bug!(),
2056            };
2057            self.mk_fn_sig(
2058                params,
2059                s.output(),
2060                s.fn_sig_kind.set_safety(safety).set_abi(ExternAbi::Rust),
2061            )
2062        })
2063    }
2064
2065    #[inline]
2066    pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
2067        self.interners.intern_predicate(binder)
2068    }
2069
2070    #[inline]
2071    pub fn reuse_or_mk_predicate(
2072        self,
2073        pred: Predicate<'tcx>,
2074        binder: Binder<'tcx, PredicateKind<'tcx>>,
2075    ) -> Predicate<'tcx> {
2076        if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
2077    }
2078
2079    pub fn check_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) -> bool {
2080        self.check_args_compatible_inner(def_id, args, false)
2081    }
2082
2083    fn check_args_compatible_inner(
2084        self,
2085        def_id: DefId,
2086        args: &'tcx [ty::GenericArg<'tcx>],
2087        nested: bool,
2088    ) -> bool {
2089        let generics = self.generics_of(def_id);
2090
2091        // IATs and IACs (inherent associated types/consts with `type const`) themselves have a
2092        // weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e.
2093        // ATPITs) do not.
2094        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)
2095            && #[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 });
2096        let is_inherent_assoc_type_const =
2097            #[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 })
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 own_args = if !nested && (is_inherent_assoc_ty || is_inherent_assoc_type_const) {
2100            if generics.own_params.len() + 1 != args.len() {
2101                return false;
2102            }
2103
2104            if !#[allow(non_exhaustive_omitted_patterns)] match args[0].kind() {
    ty::GenericArgKind::Type(_) => true,
    _ => false,
}matches!(args[0].kind(), ty::GenericArgKind::Type(_)) {
2105                return false;
2106            }
2107
2108            &args[1..]
2109        } else {
2110            if generics.count() != args.len() {
2111                return false;
2112            }
2113
2114            let (parent_args, own_args) = args.split_at(generics.parent_count);
2115
2116            if let Some(parent) = generics.parent
2117                && !self.check_args_compatible_inner(parent, parent_args, true)
2118            {
2119                return false;
2120            }
2121
2122            own_args
2123        };
2124
2125        for (param, arg) in std::iter::zip(&generics.own_params, own_args) {
2126            match (&param.kind, arg.kind()) {
2127                (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
2128                | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
2129                | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
2130                _ => return false,
2131            }
2132        }
2133
2134        true
2135    }
2136
2137    /// With `cfg(debug_assertions)`, assert that args are compatible with their generics,
2138    /// and print out the args if not.
2139    pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
2140        if truecfg!(debug_assertions) && !self.check_args_compatible(def_id, args) {
2141            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)
2142                && #[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 });
2143            let is_inherent_assoc_type_const =
2144                #[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 })
2145                    && #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(self.parent(def_id))
    {
    DefKind::Impl { of_trait: false } => true,
    _ => false,
}matches!(
2146                        self.def_kind(self.parent(def_id)),
2147                        DefKind::Impl { of_trait: false }
2148                    );
2149            if is_inherent_assoc_ty || is_inherent_assoc_type_const {
2150                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!(
2151                    "args not compatible with generics for {}: args={:#?}, generics={:#?}",
2152                    self.def_path_str(def_id),
2153                    args,
2154                    // Make `[Self, GAT_ARGS...]` (this could be simplified)
2155                    self.mk_args_from_iter(
2156                        [self.types.self_param.into()].into_iter().chain(
2157                            self.generics_of(def_id)
2158                                .own_args(ty::GenericArgs::identity_for_item(self, def_id))
2159                                .iter()
2160                                .copied()
2161                        )
2162                    )
2163                );
2164            } else {
2165                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!(
2166                    "args not compatible with generics for {}: args={:#?}, generics={:#?}",
2167                    self.def_path_str(def_id),
2168                    args,
2169                    ty::GenericArgs::identity_for_item(self, def_id)
2170                );
2171            }
2172        }
2173    }
2174
2175    #[inline(always)]
2176    pub(crate) fn check_and_mk_args(
2177        self,
2178        def_id: DefId,
2179        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
2180    ) -> GenericArgsRef<'tcx> {
2181        let args = self.mk_args_from_iter(args.into_iter().map(Into::into));
2182        self.debug_assert_args_compatible(def_id, args);
2183        args
2184    }
2185
2186    #[inline]
2187    pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
2188        self.interners.intern_const(kind)
2189    }
2190
2191    // Avoid this in favour of more specific `Ty::new_*` methods, where possible.
2192    #[allow(rustc::usage_of_ty_tykind)]
2193    #[inline]
2194    pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
2195        self.interners.intern_ty(st)
2196    }
2197
2198    pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
2199        match param.kind {
2200            GenericParamDefKind::Lifetime => {
2201                ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
2202            }
2203            GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
2204            GenericParamDefKind::Const { .. } => {
2205                ty::Const::new_param(self, ParamConst { index: param.index, name: param.name })
2206                    .into()
2207            }
2208        }
2209    }
2210
2211    pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> {
2212        self.mk_place_elem(place, PlaceElem::Field(f, ty))
2213    }
2214
2215    pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
2216        self.mk_place_elem(place, PlaceElem::Deref)
2217    }
2218
2219    pub fn mk_place_downcast(
2220        self,
2221        place: Place<'tcx>,
2222        adt_def: AdtDef<'tcx>,
2223        variant_index: VariantIdx,
2224    ) -> Place<'tcx> {
2225        self.mk_place_elem(
2226            place,
2227            PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
2228        )
2229    }
2230
2231    pub fn mk_place_downcast_unnamed(
2232        self,
2233        place: Place<'tcx>,
2234        variant_index: VariantIdx,
2235    ) -> Place<'tcx> {
2236        self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
2237    }
2238
2239    pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
2240        self.mk_place_elem(place, PlaceElem::Index(index))
2241    }
2242
2243    /// This method copies `Place`'s projection, add an element and reintern it. Should not be used
2244    /// to build a full `Place` it's just a convenient way to grab a projection and modify it in
2245    /// flight.
2246    pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
2247        Place {
2248            local: place.local,
2249            projection: self.mk_place_elems_from_iter(place.projection.iter().chain([elem])),
2250        }
2251    }
2252
2253    pub fn mk_poly_existential_predicates(
2254        self,
2255        eps: &[PolyExistentialPredicate<'tcx>],
2256    ) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
2257        if !!eps.is_empty() {
    ::core::panicking::panic("assertion failed: !eps.is_empty()")
};assert!(!eps.is_empty());
2258        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!(
2259            eps.array_windows()
2260                .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
2261                    != Ordering::Greater)
2262        );
2263        self.intern_poly_existential_predicates(eps)
2264    }
2265
2266    pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> Clauses<'tcx> {
2267        // FIXME consider asking the input slice to be sorted to avoid
2268        // re-interning permutations, in which case that would be asserted
2269        // here.
2270        self.interners.intern_clauses(clauses)
2271    }
2272
2273    pub fn mk_local_def_ids(self, def_ids: &[LocalDefId]) -> &'tcx List<LocalDefId> {
2274        // FIXME consider asking the input slice to be sorted to avoid
2275        // re-interning permutations, in which case that would be asserted
2276        // here.
2277        self.intern_local_def_ids(def_ids)
2278    }
2279
2280    pub fn mk_patterns_from_iter<I, T>(self, iter: I) -> T::Output
2281    where
2282        I: Iterator<Item = T>,
2283        T: CollectAndApply<ty::Pattern<'tcx>, &'tcx List<ty::Pattern<'tcx>>>,
2284    {
2285        T::collect_and_apply(iter, |xs| self.mk_patterns(xs))
2286    }
2287
2288    pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output
2289    where
2290        I: Iterator<Item = T>,
2291        T: CollectAndApply<LocalDefId, &'tcx List<LocalDefId>>,
2292    {
2293        T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs))
2294    }
2295
2296    pub fn mk_captures_from_iter<I, T>(self, iter: I) -> T::Output
2297    where
2298        I: Iterator<Item = T>,
2299        T: CollectAndApply<
2300                &'tcx ty::CapturedPlace<'tcx>,
2301                &'tcx List<&'tcx ty::CapturedPlace<'tcx>>,
2302            >,
2303    {
2304        T::collect_and_apply(iter, |xs| self.intern_captures(xs))
2305    }
2306
2307    pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
2308    where
2309        I: Iterator<Item = T>,
2310        T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
2311    {
2312        T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
2313    }
2314
2315    // Unlike various other `mk_*_from_iter` functions, this one uses `I:
2316    // IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
2317    // variant, because of the need to combine `inputs` and `output`. This
2318    // explains the lack of `_from_iter` suffix.
2319    pub fn mk_fn_sig<I, T>(
2320        self,
2321        inputs: I,
2322        output: I::Item,
2323        fn_sig_kind: FnSigKind<'tcx>,
2324    ) -> T::Output
2325    where
2326        I: IntoIterator<Item = T>,
2327        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
2328    {
2329        T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
2330            inputs_and_output: self.mk_type_list(xs),
2331            fn_sig_kind,
2332        })
2333    }
2334
2335    /// `mk_fn_sig`, but with a Rust ABI, and no C-variadic argument.
2336    pub fn mk_fn_sig_rust_abi<I, T>(
2337        self,
2338        inputs: I,
2339        output: I::Item,
2340        safety: hir::Safety,
2341    ) -> T::Output
2342    where
2343        I: IntoIterator<Item = T>,
2344        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
2345    {
2346        self.mk_fn_sig(inputs, output, FnSigKind::default().set_safety(safety))
2347    }
2348
2349    /// `mk_fn_sig`, but with a safe Rust ABI, and no C-variadic argument.
2350    pub fn mk_fn_sig_safe_rust_abi<I, T>(self, inputs: I, output: I::Item) -> T::Output
2351    where
2352        I: IntoIterator<Item = T>,
2353        T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
2354    {
2355        self.mk_fn_sig(inputs, output, FnSigKind::default().set_safety(hir::Safety::Safe))
2356    }
2357
2358    pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
2359    where
2360        I: Iterator<Item = T>,
2361        T: CollectAndApply<
2362                PolyExistentialPredicate<'tcx>,
2363                &'tcx List<PolyExistentialPredicate<'tcx>>,
2364            >,
2365    {
2366        T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
2367    }
2368
2369    pub fn mk_predefined_opaques_in_body_from_iter<I, T>(self, iter: I) -> T::Output
2370    where
2371        I: Iterator<Item = T>,
2372        T: CollectAndApply<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>), PredefinedOpaques<'tcx>>,
2373    {
2374        T::collect_and_apply(iter, |xs| self.mk_predefined_opaques_in_body(xs))
2375    }
2376
2377    pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
2378    where
2379        I: Iterator<Item = T>,
2380        T: CollectAndApply<Clause<'tcx>, Clauses<'tcx>>,
2381    {
2382        T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
2383    }
2384
2385    pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
2386    where
2387        I: Iterator<Item = T>,
2388        T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
2389    {
2390        T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
2391    }
2392
2393    pub fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
2394    where
2395        I: Iterator<Item = T>,
2396        T: CollectAndApply<GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>,
2397    {
2398        T::collect_and_apply(iter, |xs| self.mk_args(xs))
2399    }
2400
2401    pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
2402    where
2403        I: Iterator<Item = T>,
2404        T: CollectAndApply<CanonicalVarKind<'tcx>, &'tcx List<CanonicalVarKind<'tcx>>>,
2405    {
2406        T::collect_and_apply(iter, |xs| self.mk_canonical_var_kinds(xs))
2407    }
2408
2409    pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
2410    where
2411        I: Iterator<Item = T>,
2412        T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
2413    {
2414        T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
2415    }
2416
2417    pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
2418    where
2419        I: Iterator<Item = T>,
2420        T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,
2421    {
2422        T::collect_and_apply(iter, |xs| self.mk_fields(xs))
2423    }
2424
2425    pub fn mk_args_trait(
2426        self,
2427        self_ty: Ty<'tcx>,
2428        rest: impl IntoIterator<Item = GenericArg<'tcx>>,
2429    ) -> GenericArgsRef<'tcx> {
2430        self.mk_args_from_iter(iter::once(self_ty.into()).chain(rest))
2431    }
2432
2433    pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
2434    where
2435        I: Iterator<Item = T>,
2436        T: CollectAndApply<ty::BoundVariableKind<'tcx>, &'tcx List<ty::BoundVariableKind<'tcx>>>,
2437    {
2438        T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
2439    }
2440
2441    pub fn mk_outlives_from_iter<I, T>(self, iter: I) -> T::Output
2442    where
2443        I: Iterator<Item = T>,
2444        T: CollectAndApply<
2445                ty::ArgOutlivesPredicate<'tcx>,
2446                &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>>,
2447            >,
2448    {
2449        T::collect_and_apply(iter, |xs| self.mk_outlives(xs))
2450    }
2451
2452    /// Emit a lint at `span` from a lint struct (some type that implements `Diagnostic`,
2453    /// typically generated by `#[derive(Diagnostic)]`).
2454    #[track_caller]
2455    pub fn emit_node_span_lint(
2456        self,
2457        lint: &'static Lint,
2458        hir_id: HirId,
2459        span: impl Into<MultiSpan>,
2460        decorator: impl for<'a> Diagnostic<'a, ()>,
2461    ) {
2462        let level_spec = self.lint_level_spec_at_node(lint, hir_id);
2463        emit_lint_base(self.sess, lint, level_spec, Some(span.into()), decorator)
2464    }
2465
2466    /// Find the appropriate span where `use` and outer attributes can be inserted at.
2467    pub fn crate_level_attribute_injection_span(self) -> Span {
2468        let node = self.hir_node(hir::CRATE_HIR_ID);
2469        let hir::Node::Crate(m) = node else { crate::util::bug::bug_fmt(format_args!("impossible case reached"))bug!() };
2470        m.spans.inject_use_span.shrink_to_lo()
2471    }
2472
2473    pub fn disabled_nightly_features<E: rustc_errors::EmissionGuarantee>(
2474        self,
2475        diag: &mut Diag<'_, E>,
2476        features: impl IntoIterator<Item = (String, Symbol)>,
2477    ) {
2478        if !self.sess.is_nightly_build() {
2479            return;
2480        }
2481
2482        let span = self.crate_level_attribute_injection_span();
2483        for (desc, feature) in features {
2484            // FIXME: make this string translatable
2485            let msg =
2486                ::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}");
2487            diag.span_suggestion_verbose(
2488                span,
2489                msg,
2490                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#![feature({0})]\n", feature))
    })format!("#![feature({feature})]\n"),
2491                Applicability::MaybeIncorrect,
2492            );
2493        }
2494    }
2495
2496    /// Emit a lint from a lint struct (some type that implements `Diagnostic`, typically generated
2497    /// by `#[derive(Diagnostic)]`).
2498    #[track_caller]
2499    pub fn emit_node_lint(
2500        self,
2501        lint: &'static Lint,
2502        id: HirId,
2503        decorator: impl for<'a> Diagnostic<'a, ()>,
2504    ) {
2505        let level_spec = self.lint_level_spec_at_node(lint, id);
2506        emit_lint_base(self.sess, lint, level_spec, None, decorator);
2507    }
2508
2509    pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate<'tcx>]> {
2510        let map = self.in_scope_traits_map(id.owner)?;
2511        let candidates = map.get(&id.local_id)?;
2512        Some(candidates)
2513    }
2514
2515    pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
2516        {
    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:2516",
                        "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(2516u32),
                        ::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");
2517        self.named_variable_map(id.owner).get(&id.local_id).cloned()
2518    }
2519
2520    pub fn is_late_bound(self, id: HirId) -> bool {
2521        self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
2522    }
2523
2524    pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind<'tcx>> {
2525        self.mk_bound_variable_kinds(
2526            &self
2527                .late_bound_vars_map(id.owner)
2528                .get(&id.local_id)
2529                .cloned()
2530                .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))),
2531        )
2532    }
2533
2534    /// Given the def-id of an early-bound lifetime on an opaque corresponding to
2535    /// a duplicated captured lifetime, map it back to the early- or late-bound
2536    /// lifetime of the function from which it originally as captured. If it is
2537    /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
2538    /// of the signature.
2539    // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
2540    // re-use the generics of the opaque, this function will need to be tweaked slightly.
2541    pub fn map_opaque_lifetime_to_parent_lifetime(
2542        self,
2543        mut opaque_lifetime_param_def_id: LocalDefId,
2544    ) -> ty::Region<'tcx> {
2545        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!(
2546            matches!(self.def_kind(opaque_lifetime_param_def_id), DefKind::LifetimeParam),
2547            "{opaque_lifetime_param_def_id:?} is a {}",
2548            self.def_descr(opaque_lifetime_param_def_id.to_def_id())
2549        );
2550
2551        loop {
2552            let parent = self.local_parent(opaque_lifetime_param_def_id);
2553            let lifetime_mapping = self.opaque_captured_lifetimes(parent);
2554
2555            let Some((lifetime, _)) = lifetime_mapping
2556                .iter()
2557                .find(|(_, duplicated_param)| *duplicated_param == opaque_lifetime_param_def_id)
2558            else {
2559                crate::util::bug::bug_fmt(format_args!("duplicated lifetime param should be present"));bug!("duplicated lifetime param should be present");
2560            };
2561
2562            match *lifetime {
2563                resolve_bound_vars::ResolvedArg::EarlyBound(ebv) => {
2564                    let new_parent = self.local_parent(ebv);
2565
2566                    // If we map to another opaque, then it should be a parent
2567                    // of the opaque we mapped from. Continue mapping.
2568                    if #[allow(non_exhaustive_omitted_patterns)] match self.def_kind(new_parent) {
    DefKind::OpaqueTy => true,
    _ => false,
}matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
2569                        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);
2570                        opaque_lifetime_param_def_id = ebv;
2571                        continue;
2572                    }
2573
2574                    let generics = self.generics_of(new_parent);
2575                    return ty::Region::new_early_param(
2576                        self,
2577                        ty::EarlyParamRegion {
2578                            index: generics
2579                                .param_def_id_to_index(self, ebv.to_def_id())
2580                                .expect("early-bound var should be present in fn generics"),
2581                            name: self.item_name(ebv.to_def_id()),
2582                        },
2583                    );
2584                }
2585                resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv) => {
2586                    let new_parent = self.local_parent(lbv);
2587                    return ty::Region::new_late_param(
2588                        self,
2589                        new_parent.to_def_id(),
2590                        ty::LateParamRegionKind::Named(lbv.to_def_id()),
2591                    );
2592                }
2593                resolve_bound_vars::ResolvedArg::Error(guar) => {
2594                    return ty::Region::new_error(self, guar);
2595                }
2596                _ => {
2597                    return ty::Region::new_error_with_message(
2598                        self,
2599                        self.def_span(opaque_lifetime_param_def_id),
2600                        "cannot resolve lifetime",
2601                    );
2602                }
2603            }
2604        }
2605    }
2606
2607    /// Whether `def_id` is a stable const fn (i.e., doesn't need any feature gates to be called).
2608    ///
2609    /// When this is `false`, the function may still be callable as a `const fn` due to features
2610    /// being enabled!
2611    pub fn is_stable_const_fn(self, def_id: DefId) -> bool {
2612        self.is_const_fn(def_id)
2613            && match self.lookup_const_stability(def_id) {
2614                None => true, // a fn in a non-staged_api crate
2615                Some(stability) if stability.is_const_stable() => true,
2616                _ => false,
2617            }
2618    }
2619
2620    /// Whether the trait impl is marked const. This does not consider stability or feature gates.
2621    pub fn is_const_trait_impl(self, def_id: DefId) -> bool {
2622        self.def_kind(def_id) == DefKind::Impl { of_trait: true }
2623            && self.impl_trait_header(def_id).constness == hir::Constness::Const
2624    }
2625
2626    pub fn is_sdylib_interface_build(self) -> bool {
2627        self.sess.opts.unstable_opts.build_sdylib_interface
2628    }
2629
2630    pub fn intrinsic(self, def_id: impl IntoQueryKey<DefId>) -> Option<ty::IntrinsicDef> {
2631        let def_id = def_id.into_query_key();
2632        match self.def_kind(def_id) {
2633            DefKind::Fn | DefKind::AssocFn => self.intrinsic_raw(def_id),
2634            _ => None,
2635        }
2636    }
2637
2638    pub fn next_trait_solver_globally(self) -> bool {
2639        self.sess.opts.unstable_opts.next_solver.globally
2640    }
2641
2642    pub fn next_trait_solver_in_coherence(self) -> bool {
2643        self.sess.opts.unstable_opts.next_solver.coherence
2644    }
2645
2646    pub fn disable_trait_solver_fast_paths(self) -> bool {
2647        self.sess.opts.unstable_opts.disable_fast_paths
2648    }
2649
2650    #[allow(rustc::bad_opt_access)]
2651    pub fn use_typing_mode_borrowck(self) -> bool {
2652        self.next_trait_solver_globally() || self.sess.opts.unstable_opts.typing_mode_borrowck
2653    }
2654
2655    pub fn assumptions_on_binders(self) -> bool {
2656        self.sess.opts.unstable_opts.assumptions_on_binders
2657    }
2658
2659    pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
2660        self.opt_rpitit_info(def_id).is_some()
2661    }
2662
2663    /// Named module children from all kinds of items, including imports.
2664    /// In addition to regular items this list also includes struct and variant constructors, and
2665    /// items inside `extern {}` blocks because all of them introduce names into parent module.
2666    ///
2667    /// Module here is understood in name resolution sense - it can be a `mod` item,
2668    /// or a crate root, or an enum, or a trait.
2669    ///
2670    /// This is not a query, making it a query causes perf regressions
2671    /// (probably due to hashing spans in `ModChild`ren).
2672    pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
2673        self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
2674    }
2675
2676    /// Return the crate imported by given use item.
2677    pub fn extern_mod_stmt_cnum(self, def_id: LocalDefId) -> Option<CrateNum> {
2678        self.resolutions(()).extern_crate_map.get(&def_id).copied()
2679    }
2680
2681    pub fn resolver_for_lowering(
2682        self,
2683    ) -> &'tcx Steal<(ty::ResolverAstLowering<'tcx>, Arc<ast::Crate>)> {
2684        self.resolver_for_lowering_raw(()).0
2685    }
2686
2687    pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode {
2688        make_metadata(self)
2689    }
2690
2691    pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool {
2692        if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) =
2693            self.coroutine_kind(def_id)
2694            && let ty::Coroutine(_, args) =
2695                self.type_of(def_id).instantiate_identity().skip_norm_wip().kind()
2696            && args.as_coroutine().kind_ty().to_opt_closure_kind() != Some(ty::ClosureKind::FnOnce)
2697        {
2698            true
2699        } else {
2700            false
2701        }
2702    }
2703
2704    /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
2705    pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
2706        {
        {
            '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)
2707    }
2708
2709    pub fn is_trivial_const(self, def_id: impl IntoQueryKey<DefId>) -> bool {
2710        let def_id = def_id.into_query_key();
2711        self.trivial_const(def_id).is_some()
2712    }
2713
2714    /// Whether this def is one of the special bin crate entrypoint functions that must have a
2715    /// monomorphization and also not be internalized in the bin crate.
2716    pub fn is_entrypoint(self, def_id: DefId) -> bool {
2717        if self.is_lang_item(def_id, LangItem::Start) {
2718            return true;
2719        }
2720        if let Some((entry_def_id, _)) = self.entry_fn(())
2721            && entry_def_id == def_id
2722        {
2723            return true;
2724        }
2725        false
2726    }
2727}
2728
2729pub fn provide(providers: &mut Providers) {
2730    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);
2731    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);
2732    providers.has_panic_handler = |tcx, LocalCrate| {
2733        // We want to check if the panic handler was defined in this crate
2734        tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
2735    };
2736    providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
2737}