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