1 //! Type context book-keeping.
2
3 #![allow(rustc::usage_of_ty_tykind)]
4
5 pub mod tls;
6
7 use crate::arena::Arena;
8 use crate::dep_graph::{DepGraph, DepKindStruct};
9 use crate::infer::canonical::CanonicalVarInfo;
10 use crate::lint::struct_lint_level;
11 use crate::metadata::ModChild;
12 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
13 use crate::middle::resolve_bound_vars;
14 use crate::middle::stability;
15 use crate::mir::interpret::{self, Allocation, ConstAllocation};
16 use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
17 use crate::query::plumbing::QuerySystem;
18 use crate::query::LocalCrate;
19 use crate::query::Providers;
20 use crate::query::{IntoQueryParam, TyCtxtAt};
21 use crate::thir::Thir;
22 use crate::traits;
23 use crate::traits::solve;
24 use crate::traits::solve::{
25 ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
26 };
27 use crate::ty::{
28 self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
29 ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig,
30 Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind,
31 TyVid, TypeAndMut, Visibility,
32 };
33 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
34 use rustc_ast::{self as ast, attr};
35 use rustc_data_structures::fingerprint::Fingerprint;
36 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
37 use rustc_data_structures::intern::Interned;
38 use rustc_data_structures::profiling::SelfProfilerRef;
39 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
40 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
41 use rustc_data_structures::steal::Steal;
42 use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal};
43 use rustc_data_structures::unord::UnordSet;
44 use rustc_errors::{
45 DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
46 };
47 use rustc_hir as hir;
48 use rustc_hir::def::DefKind;
49 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
50 use rustc_hir::definitions::Definitions;
51 use rustc_hir::intravisit::Visitor;
52 use rustc_hir::lang_items::LangItem;
53 use rustc_hir::{
54 Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
55 };
56 use rustc_index::IndexVec;
57 use rustc_macros::HashStable;
58 use rustc_query_system::dep_graph::DepNodeIndex;
59 use rustc_query_system::ich::StableHashingContext;
60 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
61 use rustc_session::config::CrateType;
62 use rustc_session::cstore::{CrateStoreDyn, Untracked};
63 use rustc_session::lint::Lint;
64 use rustc_session::Limit;
65 use rustc_session::Session;
66 use rustc_span::def_id::{DefPathHash, StableCrateId};
67 use rustc_span::symbol::{kw, sym, Ident, Symbol};
68 use rustc_span::{Span, DUMMY_SP};
69 use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
70 use rustc_target::spec::abi;
71 use rustc_type_ir::sty::TyKind::*;
72 use rustc_type_ir::WithCachedTypeInfo;
73 use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
74
75 use std::any::Any;
76 use std::borrow::Borrow;
77 use std::cmp::Ordering;
78 use std::fmt;
79 use std::hash::{Hash, Hasher};
80 use std::iter;
81 use std::mem;
82 use std::ops::{Bound, Deref};
83
84 #[allow(rustc::usage_of_ty_tykind)]
85 impl<'tcx> Interner for TyCtxt<'tcx> {
86 type AdtDef = ty::AdtDef<'tcx>;
87 type SubstsRef = ty::SubstsRef<'tcx>;
88 type DefId = DefId;
89 type Binder<T> = Binder<'tcx, T>;
90 type Ty = Ty<'tcx>;
91 type Const = ty::Const<'tcx>;
92 type Region = Region<'tcx>;
93 type Predicate = Predicate<'tcx>;
94 type TypeAndMut = TypeAndMut<'tcx>;
95 type Mutability = hir::Mutability;
96 type Movability = hir::Movability;
97 type PolyFnSig = PolyFnSig<'tcx>;
98 type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
99 type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
100 type ListTy = &'tcx List<Ty<'tcx>>;
101 type AliasTy = ty::AliasTy<'tcx>;
102 type ParamTy = ParamTy;
103 type BoundTy = ty::BoundTy;
104 type PlaceholderType = ty::PlaceholderType;
105 type InferTy = InferTy;
106 type ErrorGuaranteed = ErrorGuaranteed;
107 type PredicateKind = ty::PredicateKind<'tcx>;
108 type AllocId = crate::mir::interpret::AllocId;
109
110 type InferConst = ty::InferConst<'tcx>;
111 type AliasConst = ty::UnevaluatedConst<'tcx>;
112 type ParamConst = ty::ParamConst;
113 type BoundConst = ty::BoundVar;
114 type PlaceholderConst = ty::PlaceholderConst<'tcx>;
115 type ValueConst = ty::ValTree<'tcx>;
116 type ExprConst = ty::Expr<'tcx>;
117
118 type EarlyBoundRegion = ty::EarlyBoundRegion;
119 type BoundRegion = ty::BoundRegion;
120 type FreeRegion = ty::FreeRegion;
121 type RegionVid = ty::RegionVid;
122 type PlaceholderRegion = ty::PlaceholderRegion;
123
124 fn ty_and_mut_to_parts(
125 TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
126 ) -> (Self::Ty, Self::Mutability) {
127 (ty, mutbl)
128 }
129
mutability_is_mut(mutbl: Self::Mutability) -> bool130 fn mutability_is_mut(mutbl: Self::Mutability) -> bool {
131 mutbl.is_mut()
132 }
133 }
134
135 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
136
137 pub struct CtxtInterners<'tcx> {
138 /// The arena that types, regions, etc. are allocated from.
139 arena: &'tcx WorkerLocal<Arena<'tcx>>,
140
141 // Specifically use a speedy hash algorithm for these hash sets, since
142 // they're accessed quite often.
143 type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
144 const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
145 substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
146 type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
147 canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
148 region: InternedSet<'tcx, RegionKind<'tcx>>,
149 poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
150 predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
151 clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
152 projs: InternedSet<'tcx, List<ProjectionKind>>,
153 place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
154 const_: InternedSet<'tcx, ConstData<'tcx>>,
155 const_allocation: InternedSet<'tcx, Allocation>,
156 bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
157 layout: InternedSet<'tcx, LayoutS>,
158 adt_def: InternedSet<'tcx, AdtDefData>,
159 external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
160 predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
161 fields: InternedSet<'tcx, List<FieldIdx>>,
162 }
163
164 impl<'tcx> CtxtInterners<'tcx> {
new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx>165 fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
166 CtxtInterners {
167 arena,
168 type_: Default::default(),
169 const_lists: Default::default(),
170 substs: Default::default(),
171 type_lists: Default::default(),
172 region: Default::default(),
173 poly_existential_predicates: Default::default(),
174 canonical_var_infos: Default::default(),
175 predicate: Default::default(),
176 clauses: Default::default(),
177 projs: Default::default(),
178 place_elems: Default::default(),
179 const_: Default::default(),
180 const_allocation: Default::default(),
181 bound_variable_kinds: Default::default(),
182 layout: Default::default(),
183 adt_def: Default::default(),
184 external_constraints: Default::default(),
185 predefined_opaques_in_body: Default::default(),
186 fields: Default::default(),
187 }
188 }
189
190 /// Interns a type. (Use `mk_*` functions instead, where possible.)
191 #[allow(rustc::usage_of_ty_tykind)]
192 #[inline(never)]
intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx>193 fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
194 Ty(Interned::new_unchecked(
195 self.type_
196 .intern(kind, |kind| {
197 let flags = super::flags::FlagComputation::for_kind(&kind);
198 let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
199
200 InternedInSet(self.arena.alloc(WithCachedTypeInfo {
201 internee: kind,
202 stable_hash,
203 flags: flags.flags,
204 outer_exclusive_binder: flags.outer_exclusive_binder,
205 }))
206 })
207 .0,
208 ))
209 }
210
stable_hash<'a, T: HashStable<StableHashingContext<'a>>>( &self, flags: &ty::flags::FlagComputation, sess: &'a Session, untracked: &'a Untracked, val: &T, ) -> Fingerprint211 fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
212 &self,
213 flags: &ty::flags::FlagComputation,
214 sess: &'a Session,
215 untracked: &'a Untracked,
216 val: &T,
217 ) -> Fingerprint {
218 // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
219 // Without incremental, we rarely stable-hash types, so let's not do it proactively.
220 if flags.flags.intersects(TypeFlags::HAS_INFER) || sess.opts.incremental.is_none() {
221 Fingerprint::ZERO
222 } else {
223 let mut hasher = StableHasher::new();
224 let mut hcx = StableHashingContext::new(sess, untracked);
225 val.hash_stable(&mut hcx, &mut hasher);
226 hasher.finish()
227 }
228 }
229
230 /// Interns a predicate. (Use `mk_predicate` instead, where possible.)
231 #[inline(never)]
intern_predicate( &self, kind: Binder<'tcx, PredicateKind<'tcx>>, sess: &Session, untracked: &Untracked, ) -> Predicate<'tcx>232 fn intern_predicate(
233 &self,
234 kind: Binder<'tcx, PredicateKind<'tcx>>,
235 sess: &Session,
236 untracked: &Untracked,
237 ) -> Predicate<'tcx> {
238 Predicate(Interned::new_unchecked(
239 self.predicate
240 .intern(kind, |kind| {
241 let flags = super::flags::FlagComputation::for_predicate(kind);
242
243 let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
244
245 InternedInSet(self.arena.alloc(WithCachedTypeInfo {
246 internee: kind,
247 stable_hash,
248 flags: flags.flags,
249 outer_exclusive_binder: flags.outer_exclusive_binder,
250 }))
251 })
252 .0,
253 ))
254 }
255 }
256
257 // For these preinterned values, an alternative would be to have
258 // variable-length vectors that grow as needed. But that turned out to be
259 // slightly more complex and no faster.
260
261 const NUM_PREINTERNED_TY_VARS: u32 = 100;
262 const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
263 const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
264 const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
265
266 // This number may seem high, but it is reached in all but the smallest crates.
267 const NUM_PREINTERNED_RE_VARS: u32 = 500;
268 const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
269 const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
270
271 pub struct CommonTypes<'tcx> {
272 pub unit: Ty<'tcx>,
273 pub bool: Ty<'tcx>,
274 pub char: Ty<'tcx>,
275 pub isize: Ty<'tcx>,
276 pub i8: Ty<'tcx>,
277 pub i16: Ty<'tcx>,
278 pub i32: Ty<'tcx>,
279 pub i64: Ty<'tcx>,
280 pub i128: Ty<'tcx>,
281 pub usize: Ty<'tcx>,
282 pub u8: Ty<'tcx>,
283 pub u16: Ty<'tcx>,
284 pub u32: Ty<'tcx>,
285 pub u64: Ty<'tcx>,
286 pub u128: Ty<'tcx>,
287 pub f32: Ty<'tcx>,
288 pub f64: Ty<'tcx>,
289 pub str_: Ty<'tcx>,
290 pub never: Ty<'tcx>,
291 pub self_param: Ty<'tcx>,
292
293 /// Dummy type used for the `Self` of a `TraitRef` created for converting
294 /// a trait object, and which gets removed in `ExistentialTraitRef`.
295 /// This type must not appear anywhere in other converted types.
296 /// `Infer(ty::FreshTy(0))` does the job.
297 pub trait_object_dummy_self: Ty<'tcx>,
298
299 /// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
300 pub ty_vars: Vec<Ty<'tcx>>,
301
302 /// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
303 pub fresh_tys: Vec<Ty<'tcx>>,
304
305 /// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
306 pub fresh_int_tys: Vec<Ty<'tcx>>,
307
308 /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
309 pub fresh_float_tys: Vec<Ty<'tcx>>,
310 }
311
312 pub struct CommonLifetimes<'tcx> {
313 /// `ReStatic`
314 pub re_static: Region<'tcx>,
315
316 /// Erased region, used outside of type inference.
317 pub re_erased: Region<'tcx>,
318
319 /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
320 pub re_vars: Vec<Region<'tcx>>,
321
322 /// Pre-interned values of the form:
323 /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })`
324 /// for small values of `i` and `v`.
325 pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
326 }
327
328 pub struct CommonConsts<'tcx> {
329 pub unit: Const<'tcx>,
330 pub true_: Const<'tcx>,
331 pub false_: Const<'tcx>,
332 }
333
334 impl<'tcx> CommonTypes<'tcx> {
new( interners: &CtxtInterners<'tcx>, sess: &Session, untracked: &Untracked, ) -> CommonTypes<'tcx>335 fn new(
336 interners: &CtxtInterners<'tcx>,
337 sess: &Session,
338 untracked: &Untracked,
339 ) -> CommonTypes<'tcx> {
340 let mk = |ty| interners.intern_ty(ty, sess, untracked);
341
342 let ty_vars =
343 (0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect();
344 let fresh_tys: Vec<_> =
345 (0..NUM_PREINTERNED_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect();
346 let fresh_int_tys: Vec<_> =
347 (0..NUM_PREINTERNED_FRESH_INT_TYS).map(|n| mk(Infer(ty::FreshIntTy(n)))).collect();
348 let fresh_float_tys: Vec<_> =
349 (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect();
350
351 CommonTypes {
352 unit: mk(Tuple(List::empty())),
353 bool: mk(Bool),
354 char: mk(Char),
355 never: mk(Never),
356 isize: mk(Int(ty::IntTy::Isize)),
357 i8: mk(Int(ty::IntTy::I8)),
358 i16: mk(Int(ty::IntTy::I16)),
359 i32: mk(Int(ty::IntTy::I32)),
360 i64: mk(Int(ty::IntTy::I64)),
361 i128: mk(Int(ty::IntTy::I128)),
362 usize: mk(Uint(ty::UintTy::Usize)),
363 u8: mk(Uint(ty::UintTy::U8)),
364 u16: mk(Uint(ty::UintTy::U16)),
365 u32: mk(Uint(ty::UintTy::U32)),
366 u64: mk(Uint(ty::UintTy::U64)),
367 u128: mk(Uint(ty::UintTy::U128)),
368 f32: mk(Float(ty::FloatTy::F32)),
369 f64: mk(Float(ty::FloatTy::F64)),
370 str_: mk(Str),
371 self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
372
373 trait_object_dummy_self: fresh_tys[0],
374
375 ty_vars,
376 fresh_tys,
377 fresh_int_tys,
378 fresh_float_tys,
379 }
380 }
381 }
382
383 impl<'tcx> CommonLifetimes<'tcx> {
new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx>384 fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> {
385 let mk = |r| {
386 Region(Interned::new_unchecked(
387 interners.region.intern(r, |r| InternedInSet(interners.arena.alloc(r))).0,
388 ))
389 };
390
391 let re_vars =
392 (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
393
394 let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
395 .map(|i| {
396 (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
397 .map(|v| {
398 mk(ty::ReLateBound(
399 ty::DebruijnIndex::from(i),
400 ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) },
401 ))
402 })
403 .collect()
404 })
405 .collect();
406
407 CommonLifetimes {
408 re_static: mk(ty::ReStatic),
409 re_erased: mk(ty::ReErased),
410 re_vars,
411 re_late_bounds,
412 }
413 }
414 }
415
416 impl<'tcx> CommonConsts<'tcx> {
new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx>417 fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
418 let mk_const = |c| {
419 Const(Interned::new_unchecked(
420 interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0,
421 ))
422 };
423
424 CommonConsts {
425 unit: mk_const(ty::ConstData {
426 kind: ty::ConstKind::Value(ty::ValTree::zst()),
427 ty: types.unit,
428 }),
429 true_: mk_const(ty::ConstData {
430 kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)),
431 ty: types.bool,
432 }),
433 false_: mk_const(ty::ConstData {
434 kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)),
435 ty: types.bool,
436 }),
437 }
438 }
439 }
440
441 /// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
442 /// conflict.
443 #[derive(Debug)]
444 pub struct FreeRegionInfo {
445 /// `LocalDefId` corresponding to FreeRegion
446 pub def_id: LocalDefId,
447 /// the bound region corresponding to FreeRegion
448 pub boundregion: ty::BoundRegionKind,
449 /// checks if bound region is in Impl Item
450 pub is_impl_item: bool,
451 }
452
453 /// This struct should only be created by `create_def`.
454 #[derive(Copy, Clone)]
455 pub struct TyCtxtFeed<'tcx, KEY: Copy> {
456 pub tcx: TyCtxt<'tcx>,
457 // Do not allow direct access, as downstream code must not mutate this field.
458 key: KEY,
459 }
460
461 impl<'tcx> TyCtxt<'tcx> {
feed_unit_query(self) -> TyCtxtFeed<'tcx, ()>462 pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
463 TyCtxtFeed { tcx: self, key: () }
464 }
feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum>465 pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
466 TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
467 }
468
469 /// In order to break cycles involving `AnonConst`, we need to set the expected type by side
470 /// effect. However, we do not want this as a general capability, so this interface restricts
471 /// to the only allowed case.
feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>)472 pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>) {
473 debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
474 TyCtxtFeed { tcx: self, key }.type_of(value)
475 }
476 }
477
478 impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
479 #[inline(always)]
key(&self) -> KEY480 pub fn key(&self) -> KEY {
481 self.key
482 }
483 }
484
485 impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
486 #[inline(always)]
def_id(&self) -> LocalDefId487 pub fn def_id(&self) -> LocalDefId {
488 self.key
489 }
490 }
491
492 /// The central data structure of the compiler. It stores references
493 /// to the various **arenas** and also houses the results of the
494 /// various **compiler queries** that have been performed. See the
495 /// [rustc dev guide] for more details.
496 ///
497 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
498 ///
499 /// An implementation detail: `TyCtxt` is a wrapper type for [GlobalCtxt],
500 /// which is the struct that actually holds all the data. `TyCtxt` derefs to
501 /// `GlobalCtxt`, and in practice `TyCtxt` is passed around everywhere, and all
502 /// operations are done via `TyCtxt`. A `TyCtxt` is obtained for a `GlobalCtxt`
503 /// by calling `enter` with a closure `f`. That function creates both the
504 /// `TyCtxt`, and an `ImplicitCtxt` around it that is put into TLS. Within `f`:
505 /// - The `ImplicitCtxt` is available implicitly via TLS.
506 /// - The `TyCtxt` is available explicitly via the `tcx` parameter, and also
507 /// implicitly within the `ImplicitCtxt`. Explicit access is preferred when
508 /// possible.
509 #[derive(Copy, Clone)]
510 #[rustc_diagnostic_item = "TyCtxt"]
511 #[rustc_pass_by_value]
512 pub struct TyCtxt<'tcx> {
513 gcx: &'tcx GlobalCtxt<'tcx>,
514 }
515
516 impl<'tcx> Deref for TyCtxt<'tcx> {
517 type Target = &'tcx GlobalCtxt<'tcx>;
518 #[inline(always)]
deref(&self) -> &Self::Target519 fn deref(&self) -> &Self::Target {
520 &self.gcx
521 }
522 }
523
524 /// See [TyCtxt] for details about this type.
525 pub struct GlobalCtxt<'tcx> {
526 pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
527 pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
528
529 interners: CtxtInterners<'tcx>,
530
531 pub sess: &'tcx Session,
532
533 /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
534 ///
535 /// FIXME(Centril): consider `dyn LintStoreMarker` once
536 /// we can upcast to `Any` for some additional type safety.
537 pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
538
539 pub dep_graph: DepGraph,
540
541 pub prof: SelfProfilerRef,
542
543 /// Common types, pre-interned for your convenience.
544 pub types: CommonTypes<'tcx>,
545
546 /// Common lifetimes, pre-interned for your convenience.
547 pub lifetimes: CommonLifetimes<'tcx>,
548
549 /// Common consts, pre-interned for your convenience.
550 pub consts: CommonConsts<'tcx>,
551
552 untracked: Untracked,
553
554 pub query_system: QuerySystem<'tcx>,
555 pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
556
557 // Internal caches for metadata decoding. No need to track deps on this.
558 pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
559 pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
560
561 /// Caches the results of trait selection. This cache is used
562 /// for things that do not have to do with the parameters in scope.
563 pub selection_cache: traits::SelectionCache<'tcx>,
564
565 /// Caches the results of trait evaluation. This cache is used
566 /// for things that do not have to do with the parameters in scope.
567 /// Merge this with `selection_cache`?
568 pub evaluation_cache: traits::EvaluationCache<'tcx>,
569
570 /// Caches the results of goal evaluation in the new solver.
571 pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>,
572
573 /// Data layout specification for the current target.
574 pub data_layout: TargetDataLayout,
575
576 /// Stores memory for globals (statics/consts).
577 pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
578 }
579
580 impl<'tcx> GlobalCtxt<'tcx> {
581 /// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
582 /// `f`.
enter<'a: 'tcx, F, R>(&'a self, f: F) -> R where F: FnOnce(TyCtxt<'tcx>) -> R,583 pub fn enter<'a: 'tcx, F, R>(&'a self, f: F) -> R
584 where
585 F: FnOnce(TyCtxt<'tcx>) -> R,
586 {
587 let icx = tls::ImplicitCtxt::new(self);
588 tls::enter_context(&icx, || f(icx.tcx))
589 }
590 }
591
592 impl<'tcx> TyCtxt<'tcx> {
593 /// Expects a body and returns its codegen attributes.
594 ///
595 /// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
596 /// constants.
body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs597 pub fn body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs {
598 let def_kind = self.def_kind(def_id);
599 if def_kind.has_codegen_attrs() {
600 self.codegen_fn_attrs(def_id)
601 } else if matches!(
602 def_kind,
603 DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
604 ) {
605 CodegenFnAttrs::EMPTY
606 } else {
607 bug!(
608 "body_codegen_fn_attrs called on unexpected definition: {:?} {:?}",
609 def_id,
610 def_kind
611 )
612 }
613 }
614
alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>>615 pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
616 self.arena.alloc(Steal::new(thir))
617 }
618
alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>>619 pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
620 self.arena.alloc(Steal::new(mir))
621 }
622
alloc_steal_promoted( self, promoted: IndexVec<Promoted, Body<'tcx>>, ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>623 pub fn alloc_steal_promoted(
624 self,
625 promoted: IndexVec<Promoted, Body<'tcx>>,
626 ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
627 self.arena.alloc(Steal::new(promoted))
628 }
629
mk_adt_def( self, did: DefId, kind: AdtKind, variants: IndexVec<VariantIdx, ty::VariantDef>, repr: ReprOptions, ) -> ty::AdtDef<'tcx>630 pub fn mk_adt_def(
631 self,
632 did: DefId,
633 kind: AdtKind,
634 variants: IndexVec<VariantIdx, ty::VariantDef>,
635 repr: ReprOptions,
636 ) -> ty::AdtDef<'tcx> {
637 self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
638 }
639
640 /// Allocates a read-only byte or string literal for `mir::interpret`.
allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId641 pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
642 // Create an allocation that just contains these bytes.
643 let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
644 let alloc = self.mk_const_alloc(alloc);
645 self.create_memory_alloc(alloc)
646 }
647
648 /// Returns a range of the start/end indices specified with the
649 /// `rustc_layout_scalar_valid_range` attribute.
650 // FIXME(eddyb) this is an awkward spot for this method, maybe move it?
layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>)651 pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
652 let get = |name| {
653 let Some(attr) = self.get_attr(def_id, name) else {
654 return Bound::Unbounded;
655 };
656 debug!("layout_scalar_valid_range: attr={:?}", attr);
657 if let Some(
658 &[
659 ast::NestedMetaItem::Lit(ast::MetaItemLit {
660 kind: ast::LitKind::Int(a, _),
661 ..
662 }),
663 ],
664 ) = attr.meta_item_list().as_deref()
665 {
666 Bound::Included(a)
667 } else {
668 self.sess
669 .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute");
670 Bound::Unbounded
671 }
672 };
673 (
674 get(sym::rustc_layout_scalar_valid_range_start),
675 get(sym::rustc_layout_scalar_valid_range_end),
676 )
677 }
678
lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted>679 pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
680 value.lift_to_tcx(self)
681 }
682
683 /// Creates a type context and call the closure with a `TyCtxt` reference
684 /// to the context. The closure enforces that the type context and any interned
685 /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
686 /// reference to the context, to allow formatting values that need it.
create_global_ctxt( s: &'tcx Session, lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, untracked: Untracked, dep_graph: DepGraph, query_kinds: &'tcx [DepKindStruct<'tcx>], query_system: QuerySystem<'tcx>, ) -> GlobalCtxt<'tcx>687 pub fn create_global_ctxt(
688 s: &'tcx Session,
689 lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
690 arena: &'tcx WorkerLocal<Arena<'tcx>>,
691 hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
692 untracked: Untracked,
693 dep_graph: DepGraph,
694 query_kinds: &'tcx [DepKindStruct<'tcx>],
695 query_system: QuerySystem<'tcx>,
696 ) -> GlobalCtxt<'tcx> {
697 let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
698 s.emit_fatal(err);
699 });
700 let interners = CtxtInterners::new(arena);
701 let common_types = CommonTypes::new(&interners, s, &untracked);
702 let common_lifetimes = CommonLifetimes::new(&interners);
703 let common_consts = CommonConsts::new(&interners, &common_types);
704
705 GlobalCtxt {
706 sess: s,
707 lint_store,
708 arena,
709 hir_arena,
710 interners,
711 dep_graph,
712 prof: s.prof.clone(),
713 types: common_types,
714 lifetimes: common_lifetimes,
715 consts: common_consts,
716 untracked,
717 query_system,
718 query_kinds,
719 ty_rcache: Default::default(),
720 pred_rcache: Default::default(),
721 selection_cache: Default::default(),
722 evaluation_cache: Default::default(),
723 new_solver_evaluation_cache: Default::default(),
724 data_layout,
725 alloc_map: Lock::new(interpret::AllocMap::new()),
726 }
727 }
728
consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool729 pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
730 self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
731 }
732
733 /// Obtain all lang items of this crate and all dependencies (recursively)
lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems734 pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
735 self.get_lang_items(())
736 }
737
738 /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
739 /// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
get_diagnostic_item(self, name: Symbol) -> Option<DefId>740 pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
741 self.all_diagnostic_items(()).name_to_id.get(&name).copied()
742 }
743
744 /// Obtain the diagnostic item's name
get_diagnostic_name(self, id: DefId) -> Option<Symbol>745 pub fn get_diagnostic_name(self, id: DefId) -> Option<Symbol> {
746 self.diagnostic_items(id.krate).id_to_name.get(&id).copied()
747 }
748
749 /// Check whether the diagnostic item with the given `name` has the given `DefId`.
is_diagnostic_item(self, name: Symbol, did: DefId) -> bool750 pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool {
751 self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
752 }
753
754 /// Returns `true` if the node pointed to by `def_id` is a generator for an async construct.
generator_is_async(self, def_id: DefId) -> bool755 pub fn generator_is_async(self, def_id: DefId) -> bool {
756 matches!(self.generator_kind(def_id), Some(hir::GeneratorKind::Async(_)))
757 }
758
stability(self) -> &'tcx stability::Index759 pub fn stability(self) -> &'tcx stability::Index {
760 self.stability_index(())
761 }
762
features(self) -> &'tcx rustc_feature::Features763 pub fn features(self) -> &'tcx rustc_feature::Features {
764 self.features_query(())
765 }
766
def_key(self, id: impl IntoQueryParam<DefId>) -> rustc_hir::definitions::DefKey767 pub fn def_key(self, id: impl IntoQueryParam<DefId>) -> rustc_hir::definitions::DefKey {
768 let id = id.into_query_param();
769 // Accessing the DefKey is ok, since it is part of DefPathHash.
770 if let Some(id) = id.as_local() {
771 self.definitions_untracked().def_key(id)
772 } else {
773 self.cstore_untracked().def_key(id)
774 }
775 }
776
777 /// Converts a `DefId` into its fully expanded `DefPath` (every
778 /// `DefId` is really just an interned `DefPath`).
779 ///
780 /// Note that if `id` is not local to this crate, the result will
781 /// be a non-local `DefPath`.
def_path(self, id: DefId) -> rustc_hir::definitions::DefPath782 pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
783 // Accessing the DefPath is ok, since it is part of DefPathHash.
784 if let Some(id) = id.as_local() {
785 self.definitions_untracked().def_path(id)
786 } else {
787 self.cstore_untracked().def_path(id)
788 }
789 }
790
791 #[inline]
def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash792 pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
793 // Accessing the DefPathHash is ok, it is incr. comp. stable.
794 if let Some(def_id) = def_id.as_local() {
795 self.definitions_untracked().def_path_hash(def_id)
796 } else {
797 self.cstore_untracked().def_path_hash(def_id)
798 }
799 }
800
801 #[inline]
stable_crate_id(self, crate_num: CrateNum) -> StableCrateId802 pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
803 if crate_num == LOCAL_CRATE {
804 self.sess.local_stable_crate_id()
805 } else {
806 self.cstore_untracked().stable_crate_id(crate_num)
807 }
808 }
809
810 /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
811 /// that the crate in question has already been loaded by the CrateStore.
812 #[inline]
stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum813 pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
814 if stable_crate_id == self.sess.local_stable_crate_id() {
815 LOCAL_CRATE
816 } else {
817 self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
818 }
819 }
820
821 /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
822 /// session, if it still exists. This is used during incremental compilation to
823 /// turn a deserialized `DefPathHash` into its current `DefId`.
def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() -> !) -> DefId824 pub fn def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() -> !) -> DefId {
825 debug!("def_path_hash_to_def_id({:?})", hash);
826
827 let stable_crate_id = hash.stable_crate_id();
828
829 // If this is a DefPathHash from the local crate, we can look up the
830 // DefId in the tcx's `Definitions`.
831 if stable_crate_id == self.sess.local_stable_crate_id() {
832 self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
833 } else {
834 // If this is a DefPathHash from an upstream crate, let the CrateStore map
835 // it to a DefId.
836 let cstore = &*self.cstore_untracked();
837 let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
838 cstore.def_path_hash_to_def_id(cnum, hash)
839 }
840 }
841
def_path_debug_str(self, def_id: DefId) -> String842 pub fn def_path_debug_str(self, def_id: DefId) -> String {
843 // We are explicitly not going through queries here in order to get
844 // crate name and stable crate id since this code is called from debug!()
845 // statements within the query system and we'd run into endless
846 // recursion otherwise.
847 let (crate_name, stable_crate_id) = if def_id.is_local() {
848 (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
849 } else {
850 let cstore = &*self.cstore_untracked();
851 (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
852 };
853
854 format!(
855 "{}[{:04x}]{}",
856 crate_name,
857 // Don't print the whole stable crate id. That's just
858 // annoying in debug output.
859 stable_crate_id.as_u64() >> (8 * 6),
860 self.def_path(def_id).to_string_no_crate_verbose()
861 )
862 }
863 }
864
865 impl<'tcx> TyCtxtAt<'tcx> {
866 /// Create a new definition within the incr. comp. engine.
create_def( self, parent: LocalDefId, data: hir::definitions::DefPathData, ) -> TyCtxtFeed<'tcx, LocalDefId>867 pub fn create_def(
868 self,
869 parent: LocalDefId,
870 data: hir::definitions::DefPathData,
871 ) -> TyCtxtFeed<'tcx, LocalDefId> {
872 // This function modifies `self.definitions` using a side-effect.
873 // We need to ensure that these side effects are re-run by the incr. comp. engine.
874 // Depending on the forever-red node will tell the graph that the calling query
875 // needs to be re-evaluated.
876 self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
877
878 // The following call has the side effect of modifying the tables inside `definitions`.
879 // These very tables are relied on by the incr. comp. engine to decode DepNodes and to
880 // decode the on-disk cache.
881 //
882 // Any LocalDefId which is used within queries, either as key or result, either:
883 // - has been created before the construction of the TyCtxt;
884 // - has been created by this call to `create_def`.
885 // As a consequence, this LocalDefId is always re-created before it is needed by the incr.
886 // comp. engine itself.
887 //
888 // This call also writes to the value of `source_span` and `expn_that_defined` queries.
889 // This is fine because:
890 // - those queries are `eval_always` so we won't miss their result changing;
891 // - this write will have happened before these queries are called.
892 let key = self.untracked.definitions.write().create_def(parent, data);
893
894 let feed = TyCtxtFeed { tcx: self.tcx, key };
895 feed.def_span(self.span);
896 feed
897 }
898 }
899
900 impl<'tcx> TyCtxt<'tcx> {
iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx901 pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
902 // Create a dependency to the red node to be sure we re-execute this when the amount of
903 // definitions change.
904 self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
905
906 let definitions = &self.untracked.definitions;
907 std::iter::from_generator(|| {
908 let mut i = 0;
909
910 // Recompute the number of definitions each time, because our caller may be creating
911 // new ones.
912 while i < { definitions.read().num_definitions() } {
913 let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
914 yield LocalDefId { local_def_index };
915 i += 1;
916 }
917
918 // Leak a read lock once we finish iterating on definitions, to prevent adding new ones.
919 definitions.leak();
920 })
921 }
922
def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable923 pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
924 // Create a dependency to the crate to be sure we re-execute this when the amount of
925 // definitions change.
926 self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
927
928 // Leak a read lock once we start iterating on definitions, to prevent adding new ones
929 // while iterating. If some query needs to add definitions, it should be `ensure`d above.
930 let definitions = self.untracked.definitions.leak();
931 definitions.def_path_table()
932 }
933
def_path_hash_to_def_index_map( self, ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap934 pub fn def_path_hash_to_def_index_map(
935 self,
936 ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap {
937 // Create a dependency to the crate to be sure we re-execute this when the amount of
938 // definitions change.
939 self.ensure().hir_crate(());
940 // Leak a read lock once we start iterating on definitions, to prevent adding new ones
941 // while iterating. If some query needs to add definitions, it should be `ensure`d above.
942 let definitions = self.untracked.definitions.leak();
943 definitions.def_path_hash_to_def_index_map()
944 }
945
946 /// Note that this is *untracked* and should only be used within the query
947 /// system if the result is otherwise tracked through queries
948 #[inline]
cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn>949 pub fn cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn> {
950 ReadGuard::map(self.untracked.cstore.read(), |c| &**c)
951 }
952
953 /// Give out access to the untracked data without any sanity checks.
untracked(self) -> &'tcx Untracked954 pub fn untracked(self) -> &'tcx Untracked {
955 &self.untracked
956 }
957 /// Note that this is *untracked* and should only be used within the query
958 /// system if the result is otherwise tracked through queries
959 #[inline]
definitions_untracked(self) -> ReadGuard<'tcx, Definitions>960 pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
961 self.untracked.definitions.read()
962 }
963
964 /// Note that this is *untracked* and should only be used within the query
965 /// system if the result is otherwise tracked through queries
966 #[inline]
source_span_untracked(self, def_id: LocalDefId) -> Span967 pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
968 self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
969 }
970
971 #[inline(always)]
with_stable_hashing_context<R>( self, f: impl FnOnce(StableHashingContext<'_>) -> R, ) -> R972 pub fn with_stable_hashing_context<R>(
973 self,
974 f: impl FnOnce(StableHashingContext<'_>) -> R,
975 ) -> R {
976 f(StableHashingContext::new(self.sess, &self.untracked))
977 }
978
serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult979 pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
980 self.query_system.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
981 }
982
983 #[inline]
local_crate_exports_generics(self) -> bool984 pub fn local_crate_exports_generics(self) -> bool {
985 debug_assert!(self.sess.opts.share_generics());
986
987 self.sess.crate_types().iter().any(|crate_type| {
988 match crate_type {
989 CrateType::Executable
990 | CrateType::Staticlib
991 | CrateType::ProcMacro
992 | CrateType::Cdylib => false,
993
994 // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
995 // We want to block export of generics from dylibs,
996 // but we must fix rust-lang/rust#65890 before we can
997 // do that robustly.
998 CrateType::Dylib => true,
999
1000 CrateType::Rlib => true,
1001 }
1002 })
1003 }
1004
1005 /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo>1006 pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
1007 let (suitable_region_binding_scope, bound_region) = match *region {
1008 ty::ReFree(ref free_region) => {
1009 (free_region.scope.expect_local(), free_region.bound_region)
1010 }
1011 ty::ReEarlyBound(ref ebr) => (
1012 self.local_parent(ebr.def_id.expect_local()),
1013 ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
1014 ),
1015 _ => return None, // not a free region
1016 };
1017
1018 let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
1019 Some(Node::Item(..) | Node::TraitItem(..)) => false,
1020 Some(Node::ImplItem(..)) => {
1021 self.is_bound_region_in_impl_item(suitable_region_binding_scope)
1022 }
1023 _ => return None,
1024 };
1025
1026 Some(FreeRegionInfo {
1027 def_id: suitable_region_binding_scope,
1028 boundregion: bound_region,
1029 is_impl_item,
1030 })
1031 }
1032
1033 /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
return_type_impl_or_dyn_traits( self, scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>>1034 pub fn return_type_impl_or_dyn_traits(
1035 self,
1036 scope_def_id: LocalDefId,
1037 ) -> Vec<&'tcx hir::Ty<'tcx>> {
1038 let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
1039 let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
1040 return vec![];
1041 };
1042
1043 let mut v = TraitObjectVisitor(vec![], self.hir());
1044 v.visit_ty(hir_output);
1045 v.0
1046 }
1047
1048 /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
1049 /// its return type, and the associated alias span when type alias is used,
1050 /// along with a span for lifetime suggestion (if there are existing generics).
return_type_impl_or_dyn_traits_with_type_alias( self, scope_def_id: LocalDefId, ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)>1051 pub fn return_type_impl_or_dyn_traits_with_type_alias(
1052 self,
1053 scope_def_id: LocalDefId,
1054 ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
1055 let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
1056 let mut v = TraitObjectVisitor(vec![], self.hir());
1057 // when the return type is a type alias
1058 if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
1059 && let hir::TyKind::Path(hir::QPath::Resolved(
1060 None,
1061 hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
1062 && let Some(local_id) = def_id.as_local()
1063 && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias
1064 && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics()
1065 {
1066 v.visit_ty(alias_ty);
1067 if !v.0.is_empty() {
1068 return Some((v.0, alias_generics.span, alias_generics.span_for_lifetime_suggestion()));
1069 }
1070 }
1071 return None;
1072 }
1073
return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)>1074 pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
1075 // `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
1076 match self.hir().get_by_def_id(scope_def_id) {
1077 Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
1078 Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
1079 Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
1080 Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
1081 _ => return None,
1082 }
1083
1084 let ret_ty = self.type_of(scope_def_id).subst_identity();
1085 match ret_ty.kind() {
1086 ty::FnDef(_, _) => {
1087 let sig = ret_ty.fn_sig(self);
1088 let output = self.erase_late_bound_regions(sig.output());
1089 output.is_impl_trait().then(|| {
1090 let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
1091 let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
1092 (output, fn_decl.output.span())
1093 })
1094 }
1095 _ => None,
1096 }
1097 }
1098
1099 /// Checks if the bound region is in Impl Item.
is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool1100 pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
1101 let container_id = self.parent(suitable_region_binding_scope.to_def_id());
1102 if self.impl_trait_ref(container_id).is_some() {
1103 // For now, we do not try to target impls of traits. This is
1104 // because this message is going to suggest that the user
1105 // change the fn signature, but they may not be free to do so,
1106 // since the signature must match the trait.
1107 //
1108 // FIXME(#42706) -- in some cases, we could do better here.
1109 return true;
1110 }
1111 false
1112 }
1113
1114 /// Determines whether identifiers in the assembly have strict naming rules.
1115 /// Currently, only NVPTX* targets need it.
has_strict_asm_symbol_naming(self) -> bool1116 pub fn has_strict_asm_symbol_naming(self) -> bool {
1117 self.sess.target.arch.contains("nvptx")
1118 }
1119
1120 /// Returns `&'static core::panic::Location<'static>`.
caller_location_ty(self) -> Ty<'tcx>1121 pub fn caller_location_ty(self) -> Ty<'tcx> {
1122 Ty::new_imm_ref(
1123 self,
1124 self.lifetimes.re_static,
1125 self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
1126 .subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
1127 )
1128 }
1129
1130 /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
article_and_description(self, def_id: DefId) -> (&'static str, &'static str)1131 pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
1132 let kind = self.def_kind(def_id);
1133 (self.def_kind_descr_article(kind, def_id), self.def_kind_descr(kind, def_id))
1134 }
1135
type_length_limit(self) -> Limit1136 pub fn type_length_limit(self) -> Limit {
1137 self.limits(()).type_length_limit
1138 }
1139
recursion_limit(self) -> Limit1140 pub fn recursion_limit(self) -> Limit {
1141 self.limits(()).recursion_limit
1142 }
1143
move_size_limit(self) -> Limit1144 pub fn move_size_limit(self) -> Limit {
1145 self.limits(()).move_size_limit
1146 }
1147
all_traits(self) -> impl Iterator<Item = DefId> + 'tcx1148 pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
1149 iter::once(LOCAL_CRATE)
1150 .chain(self.crates(()).iter().copied())
1151 .flat_map(move |cnum| self.traits(cnum).iter().copied())
1152 }
1153
1154 #[inline]
local_visibility(self, def_id: LocalDefId) -> Visibility1155 pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
1156 self.visibility(def_id).expect_local()
1157 }
1158
1159 /// Returns the origin of the opaque type `def_id`.
1160 #[instrument(skip(self), level = "trace", ret)]
opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin1161 pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
1162 self.hir().expect_item(def_id).expect_opaque_ty().origin
1163 }
1164 }
1165
1166 /// A trait implemented for all `X<'a>` types that can be safely and
1167 /// efficiently converted to `X<'tcx>` as long as they are part of the
1168 /// provided `TyCtxt<'tcx>`.
1169 /// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>`
1170 /// by looking them up in their respective interners.
1171 ///
1172 /// However, this is still not the best implementation as it does
1173 /// need to compare the components, even for interned values.
1174 /// It would be more efficient if `TypedArena` provided a way to
1175 /// determine whether the address is in the allocated range.
1176 ///
1177 /// `None` is returned if the value or one of the components is not part
1178 /// of the provided context.
1179 /// For `Ty`, `None` can be returned if either the type interner doesn't
1180 /// contain the `TyKind` key or if the address of the interned
1181 /// pointer differs. The latter case is possible if a primitive type,
1182 /// e.g., `()` or `u8`, was interned in a different context.
1183 pub trait Lift<'tcx>: fmt::Debug {
1184 type Lifted: fmt::Debug + 'tcx;
lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>1185 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
1186 }
1187
1188 macro_rules! nop_lift {
1189 ($set:ident; $ty:ty => $lifted:ty) => {
1190 impl<'a, 'tcx> Lift<'tcx> for $ty {
1191 type Lifted = $lifted;
1192 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
1193 tcx.interners
1194 .$set
1195 .contains_pointer_to(&InternedInSet(&*self.0.0))
1196 // SAFETY: `self` is interned and therefore valid
1197 // for the entire lifetime of the `TyCtxt`.
1198 .then(|| unsafe { mem::transmute(self) })
1199 }
1200 }
1201 };
1202 }
1203
1204 macro_rules! nop_list_lift {
1205 ($set:ident; $ty:ty => $lifted:ty) => {
1206 impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
1207 type Lifted = &'tcx List<$lifted>;
1208 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
1209 if self.is_empty() {
1210 return Some(List::empty());
1211 }
1212 tcx.interners
1213 .$set
1214 .contains_pointer_to(&InternedInSet(self))
1215 .then(|| unsafe { mem::transmute(self) })
1216 }
1217 }
1218 };
1219 }
1220
1221 nop_lift! {type_; Ty<'a> => Ty<'tcx>}
1222 nop_lift! {region; Region<'a> => Region<'tcx>}
1223 nop_lift! {const_; Const<'a> => Const<'tcx>}
1224 nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
1225 nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
1226 nop_lift! {predicate; Clause<'a> => Clause<'tcx>}
1227
1228 nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
1229 nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
1230 nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
1231 nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
1232 nop_list_lift! {projs; ProjectionKind => ProjectionKind}
1233 nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
1234
1235 // This is the impl for `&'a InternalSubsts<'a>`.
1236 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
1237
1238 CloneLiftImpls! {
1239 Constness,
1240 traits::WellFormedLoc,
1241 ImplPolarity,
1242 crate::mir::ReturnConstraint,
1243 }
1244
1245 macro_rules! sty_debug_print {
1246 ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
1247 // Curious inner module to allow variant names to be used as
1248 // variable names.
1249 #[allow(non_snake_case)]
1250 mod inner {
1251 use crate::ty::{self, TyCtxt};
1252 use crate::ty::context::InternedInSet;
1253
1254 #[derive(Copy, Clone)]
1255 struct DebugStat {
1256 total: usize,
1257 lt_infer: usize,
1258 ty_infer: usize,
1259 ct_infer: usize,
1260 all_infer: usize,
1261 }
1262
1263 pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
1264 let mut total = DebugStat {
1265 total: 0,
1266 lt_infer: 0,
1267 ty_infer: 0,
1268 ct_infer: 0,
1269 all_infer: 0,
1270 };
1271 $(let mut $variant = total;)*
1272
1273 let shards = tcx.interners.type_.lock_shards();
1274 let types = shards.iter().flat_map(|shard| shard.keys());
1275 for &InternedInSet(t) in types {
1276 let variant = match t.internee {
1277 ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
1278 ty::Float(..) | ty::Str | ty::Never => continue,
1279 ty::Error(_) => /* unimportant */ continue,
1280 $(ty::$variant(..) => &mut $variant,)*
1281 };
1282 let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
1283 let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
1284 let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
1285
1286 variant.total += 1;
1287 total.total += 1;
1288 if lt { total.lt_infer += 1; variant.lt_infer += 1 }
1289 if ty { total.ty_infer += 1; variant.ty_infer += 1 }
1290 if ct { total.ct_infer += 1; variant.ct_infer += 1 }
1291 if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
1292 }
1293 writeln!(fmt, "Ty interner total ty lt ct all")?;
1294 $(writeln!(fmt, " {:18}: {uses:6} {usespc:4.1}%, \
1295 {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1296 stringify!($variant),
1297 uses = $variant.total,
1298 usespc = $variant.total as f64 * 100.0 / total.total as f64,
1299 ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
1300 lt = $variant.lt_infer as f64 * 100.0 / total.total as f64,
1301 ct = $variant.ct_infer as f64 * 100.0 / total.total as f64,
1302 all = $variant.all_infer as f64 * 100.0 / total.total as f64)?;
1303 )*
1304 writeln!(fmt, " total {uses:6} \
1305 {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1306 uses = total.total,
1307 ty = total.ty_infer as f64 * 100.0 / total.total as f64,
1308 lt = total.lt_infer as f64 * 100.0 / total.total as f64,
1309 ct = total.ct_infer as f64 * 100.0 / total.total as f64,
1310 all = total.all_infer as f64 * 100.0 / total.total as f64)
1311 }
1312 }
1313
1314 inner::go($fmt, $ctxt)
1315 }}
1316 }
1317
1318 impl<'tcx> TyCtxt<'tcx> {
debug_stats(self) -> impl std::fmt::Debug + 'tcx1319 pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx {
1320 struct DebugStats<'tcx>(TyCtxt<'tcx>);
1321
1322 impl<'tcx> std::fmt::Debug for DebugStats<'tcx> {
1323 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1324 sty_debug_print!(
1325 fmt,
1326 self.0,
1327 Adt,
1328 Array,
1329 Slice,
1330 RawPtr,
1331 Ref,
1332 FnDef,
1333 FnPtr,
1334 Placeholder,
1335 Generator,
1336 GeneratorWitness,
1337 GeneratorWitnessMIR,
1338 Dynamic,
1339 Closure,
1340 Tuple,
1341 Bound,
1342 Param,
1343 Infer,
1344 Alias,
1345 Foreign
1346 )?;
1347
1348 writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
1349 writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
1350 writeln!(
1351 fmt,
1352 "Const Allocation interner: #{}",
1353 self.0.interners.const_allocation.len()
1354 )?;
1355 writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
1356
1357 Ok(())
1358 }
1359 }
1360
1361 DebugStats(self)
1362 }
1363 }
1364
1365 // This type holds a `T` in the interner. The `T` is stored in the arena and
1366 // this type just holds a pointer to it, but it still effectively owns it. It
1367 // impls `Borrow` so that it can be looked up using the original
1368 // (non-arena-memory-owning) types.
1369 struct InternedInSet<'tcx, T: ?Sized>(&'tcx T);
1370
1371 impl<'tcx, T: 'tcx + ?Sized> Clone for InternedInSet<'tcx, T> {
clone(&self) -> Self1372 fn clone(&self) -> Self {
1373 InternedInSet(self.0)
1374 }
1375 }
1376
1377 impl<'tcx, T: 'tcx + ?Sized> Copy for InternedInSet<'tcx, T> {}
1378
1379 impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
into_pointer(&self) -> *const ()1380 fn into_pointer(&self) -> *const () {
1381 self.0 as *const _ as *const ()
1382 }
1383 }
1384
1385 #[allow(rustc::usage_of_ty_tykind)]
1386 impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
borrow(&self) -> &T1387 fn borrow(&self) -> &T {
1388 &self.0.internee
1389 }
1390 }
1391
1392 impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool1393 fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
1394 // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1395 // `x == y`.
1396 self.0.internee == other.0.internee
1397 }
1398 }
1399
1400 impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
1401
1402 impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
hash<H: Hasher>(&self, s: &mut H)1403 fn hash<H: Hasher>(&self, s: &mut H) {
1404 // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1405 self.0.internee.hash(s)
1406 }
1407 }
1408
1409 impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
borrow(&self) -> &[T]1410 fn borrow(&self) -> &[T] {
1411 &self.0[..]
1412 }
1413 }
1414
1415 impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> {
eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool1416 fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool {
1417 // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1418 // `x == y`.
1419 self.0[..] == other.0[..]
1420 }
1421 }
1422
1423 impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {}
1424
1425 impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
hash<H: Hasher>(&self, s: &mut H)1426 fn hash<H: Hasher>(&self, s: &mut H) {
1427 // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1428 self.0[..].hash(s)
1429 }
1430 }
1431
1432 macro_rules! direct_interners {
1433 ($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
1434 $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
1435 fn borrow<'a>(&'a self) -> &'a $ty {
1436 &self.0
1437 }
1438 }
1439
1440 impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
1441 fn eq(&self, other: &Self) -> bool {
1442 // The `Borrow` trait requires that `x.borrow() == y.borrow()`
1443 // equals `x == y`.
1444 self.0 == other.0
1445 }
1446 }
1447
1448 impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
1449
1450 impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
1451 fn hash<H: Hasher>(&self, s: &mut H) {
1452 // The `Borrow` trait requires that `x.borrow().hash(s) ==
1453 // x.hash(s)`.
1454 self.0.hash(s)
1455 }
1456 }
1457
1458 impl<'tcx> TyCtxt<'tcx> {
1459 $vis fn $method(self, v: $ty) -> $ret_ty {
1460 $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
1461 InternedInSet(self.interners.arena.alloc(v))
1462 }).0))
1463 }
1464 })+
1465 }
1466 }
1467
1468 // Functions with a `mk_` prefix are intended for use outside this file and
1469 // crate. Functions with an `intern_` prefix are intended for use within this
1470 // crate only, and have a corresponding `mk_` function.
1471 direct_interners! {
1472 region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
1473 const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
1474 const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
1475 layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
1476 adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
1477 external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
1478 ExternalConstraints -> ExternalConstraints<'tcx>,
1479 predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>):
1480 PredefinedOpaques -> PredefinedOpaques<'tcx>,
1481 }
1482
1483 macro_rules! slice_interners {
1484 ($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
1485 impl<'tcx> TyCtxt<'tcx> {
1486 $($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
1487 if v.is_empty() {
1488 List::empty()
1489 } else {
1490 self.interners.$field.intern_ref(v, || {
1491 InternedInSet(List::from_arena(&*self.arena, v))
1492 }).0
1493 }
1494 })+
1495 }
1496 );
1497 }
1498
1499 // These functions intern slices. They all have a corresponding
1500 // `mk_foo_from_iter` function that interns an iterator. The slice version
1501 // should be used when possible, because it's faster.
1502 slice_interners!(
1503 const_lists: pub mk_const_list(Const<'tcx>),
1504 substs: pub mk_substs(GenericArg<'tcx>),
1505 type_lists: pub mk_type_list(Ty<'tcx>),
1506 canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
1507 poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
1508 clauses: intern_clauses(Clause<'tcx>),
1509 projs: pub mk_projs(ProjectionKind),
1510 place_elems: pub mk_place_elems(PlaceElem<'tcx>),
1511 bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
1512 fields: pub mk_fields(FieldIdx),
1513 );
1514
1515 impl<'tcx> TyCtxt<'tcx> {
1516 /// Given a `fn` type, returns an equivalent `unsafe fn` type;
1517 /// that is, a `fn` type that is equivalent in every way for being
1518 /// unsafe.
safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx>1519 pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
1520 assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
1521 Ty::new_fn_ptr(
1522 self,
1523 sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }),
1524 )
1525 }
1526
1527 /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
1528 /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool1529 pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
1530 self.super_traits_of(trait_def_id).any(|trait_did| {
1531 self.associated_items(trait_did)
1532 .filter_by_name_unhygienic(assoc_name.name)
1533 .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did))
1534 })
1535 }
1536
1537 /// Given a `ty`, return whether it's an `impl Future<...>`.
ty_is_opaque_future(self, ty: Ty<'_>) -> bool1538 pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
1539 let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
1540 let future_trait = self.require_lang_item(LangItem::Future, None);
1541
1542 self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
1543 let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
1544 return false;
1545 };
1546 trait_predicate.trait_ref.def_id == future_trait
1547 && trait_predicate.polarity == ImplPolarity::Positive
1548 })
1549 }
1550
1551 /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally)
1552 /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
1553 /// to identify which traits may define a given associated type to help avoid cycle errors.
1554 /// Returns a `DefId` iterator.
super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx1555 fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
1556 let mut set = FxHashSet::default();
1557 let mut stack = vec![trait_def_id];
1558
1559 set.insert(trait_def_id);
1560
1561 iter::from_fn(move || -> Option<DefId> {
1562 let trait_did = stack.pop()?;
1563 let generic_predicates = self.super_predicates_of(trait_did);
1564
1565 for (predicate, _) in generic_predicates.predicates {
1566 if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() {
1567 if set.insert(data.def_id()) {
1568 stack.push(data.def_id());
1569 }
1570 }
1571 }
1572
1573 Some(trait_did)
1574 })
1575 }
1576
1577 /// Given a closure signature, returns an equivalent fn signature. Detuples
1578 /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
1579 /// you would get a `fn(u32, i32)`.
1580 /// `unsafety` determines the unsafety of the fn signature. If you pass
1581 /// `hir::Unsafety::Unsafe` in the previous example, then you would get
1582 /// an `unsafe fn (u32, i32)`.
1583 /// It cannot convert a closure that requires unsafe.
signature_unclosure( self, sig: PolyFnSig<'tcx>, unsafety: hir::Unsafety, ) -> PolyFnSig<'tcx>1584 pub fn signature_unclosure(
1585 self,
1586 sig: PolyFnSig<'tcx>,
1587 unsafety: hir::Unsafety,
1588 ) -> PolyFnSig<'tcx> {
1589 sig.map_bound(|s| {
1590 let params = match s.inputs()[0].kind() {
1591 ty::Tuple(params) => *params,
1592 _ => bug!(),
1593 };
1594 self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
1595 })
1596 }
1597
1598 #[inline]
mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx>1599 pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
1600 self.interners.intern_predicate(
1601 binder,
1602 self.sess,
1603 // This is only used to create a stable hashing context.
1604 &self.untracked,
1605 )
1606 }
1607
1608 #[inline]
reuse_or_mk_predicate( self, pred: Predicate<'tcx>, binder: Binder<'tcx, PredicateKind<'tcx>>, ) -> Predicate<'tcx>1609 pub fn reuse_or_mk_predicate(
1610 self,
1611 pred: Predicate<'tcx>,
1612 binder: Binder<'tcx, PredicateKind<'tcx>>,
1613 ) -> Predicate<'tcx> {
1614 if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
1615 }
1616
1617 #[inline(always)]
check_and_mk_substs( self, _def_id: DefId, substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, ) -> SubstsRef<'tcx>1618 pub(crate) fn check_and_mk_substs(
1619 self,
1620 _def_id: DefId,
1621 substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
1622 ) -> SubstsRef<'tcx> {
1623 let substs = substs.into_iter().map(Into::into);
1624 #[cfg(debug_assertions)]
1625 {
1626 let generics = self.generics_of(_def_id);
1627
1628 let n = if let DefKind::AssocTy = self.def_kind(_def_id)
1629 && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id))
1630 {
1631 // If this is an inherent projection.
1632
1633 generics.params.len() + 1
1634 } else {
1635 generics.count()
1636 };
1637 assert_eq!(
1638 (n, Some(n)),
1639 substs.size_hint(),
1640 "wrong number of generic parameters for {_def_id:?}: {:?}",
1641 substs.collect::<Vec<_>>(),
1642 );
1643 }
1644 self.mk_substs_from_iter(substs)
1645 }
1646
1647 #[inline]
mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx>1648 pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
1649 self.intern_const(ty::ConstData { kind, ty })
1650 }
1651
1652 // Avoid this in favour of more specific `Ty::new_*` methods, where possible.
1653 #[allow(rustc::usage_of_ty_tykind)]
1654 #[inline]
mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx>1655 pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
1656 self.interners.intern_ty(
1657 st,
1658 self.sess,
1659 // This is only used to create a stable hashing context.
1660 &self.untracked,
1661 )
1662 }
1663
mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx>1664 pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
1665 match param.kind {
1666 GenericParamDefKind::Lifetime => {
1667 ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into()
1668 }
1669 GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
1670 GenericParamDefKind::Const { .. } => ty::Const::new_param(
1671 self,
1672 ParamConst { index: param.index, name: param.name },
1673 self.type_of(param.def_id)
1674 .no_bound_vars()
1675 .expect("const parameter types cannot be generic"),
1676 )
1677 .into(),
1678 }
1679 }
1680
mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx>1681 pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> {
1682 self.mk_place_elem(place, PlaceElem::Field(f, ty))
1683 }
1684
mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx>1685 pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
1686 self.mk_place_elem(place, PlaceElem::Deref)
1687 }
1688
mk_place_downcast( self, place: Place<'tcx>, adt_def: AdtDef<'tcx>, variant_index: VariantIdx, ) -> Place<'tcx>1689 pub fn mk_place_downcast(
1690 self,
1691 place: Place<'tcx>,
1692 adt_def: AdtDef<'tcx>,
1693 variant_index: VariantIdx,
1694 ) -> Place<'tcx> {
1695 self.mk_place_elem(
1696 place,
1697 PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
1698 )
1699 }
1700
mk_place_downcast_unnamed( self, place: Place<'tcx>, variant_index: VariantIdx, ) -> Place<'tcx>1701 pub fn mk_place_downcast_unnamed(
1702 self,
1703 place: Place<'tcx>,
1704 variant_index: VariantIdx,
1705 ) -> Place<'tcx> {
1706 self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
1707 }
1708
mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx>1709 pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
1710 self.mk_place_elem(place, PlaceElem::Index(index))
1711 }
1712
1713 /// This method copies `Place`'s projection, add an element and reintern it. Should not be used
1714 /// to build a full `Place` it's just a convenient way to grab a projection and modify it in
1715 /// flight.
mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx>1716 pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
1717 let mut projection = place.projection.to_vec();
1718 projection.push(elem);
1719
1720 Place { local: place.local, projection: self.mk_place_elems(&projection) }
1721 }
1722
mk_poly_existential_predicates( self, eps: &[PolyExistentialPredicate<'tcx>], ) -> &'tcx List<PolyExistentialPredicate<'tcx>>1723 pub fn mk_poly_existential_predicates(
1724 self,
1725 eps: &[PolyExistentialPredicate<'tcx>],
1726 ) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
1727 assert!(!eps.is_empty());
1728 assert!(
1729 eps.array_windows()
1730 .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
1731 != Ordering::Greater)
1732 );
1733 self.intern_poly_existential_predicates(eps)
1734 }
1735
mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>>1736 pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
1737 // FIXME consider asking the input slice to be sorted to avoid
1738 // re-interning permutations, in which case that would be asserted
1739 // here.
1740 self.intern_clauses(clauses)
1741 }
1742
mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,1743 pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
1744 where
1745 I: Iterator<Item = T>,
1746 T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
1747 {
1748 T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
1749 }
1750
1751 // Unlike various other `mk_*_from_iter` functions, this one uses `I:
1752 // IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
1753 // variant, because of the need to combine `inputs` and `output`. This
1754 // explains the lack of `_from_iter` suffix.
mk_fn_sig<I, T>( self, inputs: I, output: I::Item, c_variadic: bool, unsafety: hir::Unsafety, abi: abi::Abi, ) -> T::Output where I: IntoIterator<Item = T>, T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,1755 pub fn mk_fn_sig<I, T>(
1756 self,
1757 inputs: I,
1758 output: I::Item,
1759 c_variadic: bool,
1760 unsafety: hir::Unsafety,
1761 abi: abi::Abi,
1762 ) -> T::Output
1763 where
1764 I: IntoIterator<Item = T>,
1765 T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
1766 {
1767 T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
1768 inputs_and_output: self.mk_type_list(xs),
1769 c_variadic,
1770 unsafety,
1771 abi,
1772 })
1773 }
1774
mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply< PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>, >,1775 pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
1776 where
1777 I: Iterator<Item = T>,
1778 T: CollectAndApply<
1779 PolyExistentialPredicate<'tcx>,
1780 &'tcx List<PolyExistentialPredicate<'tcx>>,
1781 >,
1782 {
1783 T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
1784 }
1785
mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,1786 pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
1787 where
1788 I: Iterator<Item = T>,
1789 T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,
1790 {
1791 T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
1792 }
1793
mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,1794 pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
1795 where
1796 I: Iterator<Item = T>,
1797 T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
1798 {
1799 T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
1800 }
1801
mk_substs_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,1802 pub fn mk_substs_from_iter<I, T>(self, iter: I) -> T::Output
1803 where
1804 I: Iterator<Item = T>,
1805 T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,
1806 {
1807 T::collect_and_apply(iter, |xs| self.mk_substs(xs))
1808 }
1809
mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<CanonicalVarInfo<'tcx>, &'tcx List<CanonicalVarInfo<'tcx>>>,1810 pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
1811 where
1812 I: Iterator<Item = T>,
1813 T: CollectAndApply<CanonicalVarInfo<'tcx>, &'tcx List<CanonicalVarInfo<'tcx>>>,
1814 {
1815 T::collect_and_apply(iter, |xs| self.mk_canonical_var_infos(xs))
1816 }
1817
mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,1818 pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
1819 where
1820 I: Iterator<Item = T>,
1821 T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
1822 {
1823 T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
1824 }
1825
mk_fields_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,1826 pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
1827 where
1828 I: Iterator<Item = T>,
1829 T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,
1830 {
1831 T::collect_and_apply(iter, |xs| self.mk_fields(xs))
1832 }
1833
mk_substs_trait( self, self_ty: Ty<'tcx>, rest: impl IntoIterator<Item = GenericArg<'tcx>>, ) -> SubstsRef<'tcx>1834 pub fn mk_substs_trait(
1835 self,
1836 self_ty: Ty<'tcx>,
1837 rest: impl IntoIterator<Item = GenericArg<'tcx>>,
1838 ) -> SubstsRef<'tcx> {
1839 self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest))
1840 }
1841
mk_alias_ty( self, def_id: DefId, substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, ) -> ty::AliasTy<'tcx>1842 pub fn mk_alias_ty(
1843 self,
1844 def_id: DefId,
1845 substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
1846 ) -> ty::AliasTy<'tcx> {
1847 let substs = self.check_and_mk_substs(def_id, substs);
1848 ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
1849 }
1850
mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output where I: Iterator<Item = T>, T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,1851 pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
1852 where
1853 I: Iterator<Item = T>,
1854 T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
1855 {
1856 T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
1857 }
1858
1859 /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
1860 /// typically generated by `#[derive(LintDiagnostic)]`).
emit_spanned_lint( self, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, decorator: impl for<'a> DecorateLint<'a, ()>, )1861 pub fn emit_spanned_lint(
1862 self,
1863 lint: &'static Lint,
1864 hir_id: HirId,
1865 span: impl Into<MultiSpan>,
1866 decorator: impl for<'a> DecorateLint<'a, ()>,
1867 ) {
1868 let msg = decorator.msg();
1869 let (level, src) = self.lint_level_at_node(lint, hir_id);
1870 struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
1871 decorator.decorate_lint(diag)
1872 })
1873 }
1874
1875 /// Emit a lint at the appropriate level for a hir node, with an associated span.
1876 ///
1877 /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
1878 ///
1879 /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
1880 #[rustc_lint_diagnostics]
struct_span_lint_hir( self, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, decorate: impl for<'a, 'b> FnOnce( &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()>, )1881 pub fn struct_span_lint_hir(
1882 self,
1883 lint: &'static Lint,
1884 hir_id: HirId,
1885 span: impl Into<MultiSpan>,
1886 msg: impl Into<DiagnosticMessage>,
1887 decorate: impl for<'a, 'b> FnOnce(
1888 &'b mut DiagnosticBuilder<'a, ()>,
1889 ) -> &'b mut DiagnosticBuilder<'a, ()>,
1890 ) {
1891 let (level, src) = self.lint_level_at_node(lint, hir_id);
1892 struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
1893 }
1894
1895 /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
1896 /// generated by `#[derive(LintDiagnostic)]`).
emit_lint( self, lint: &'static Lint, id: HirId, decorator: impl for<'a> DecorateLint<'a, ()>, )1897 pub fn emit_lint(
1898 self,
1899 lint: &'static Lint,
1900 id: HirId,
1901 decorator: impl for<'a> DecorateLint<'a, ()>,
1902 ) {
1903 self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
1904 }
1905
1906 /// Emit a lint at the appropriate level for a hir node.
1907 ///
1908 /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
1909 ///
1910 /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
1911 #[rustc_lint_diagnostics]
struct_lint_node( self, lint: &'static Lint, id: HirId, msg: impl Into<DiagnosticMessage>, decorate: impl for<'a, 'b> FnOnce( &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()>, )1912 pub fn struct_lint_node(
1913 self,
1914 lint: &'static Lint,
1915 id: HirId,
1916 msg: impl Into<DiagnosticMessage>,
1917 decorate: impl for<'a, 'b> FnOnce(
1918 &'b mut DiagnosticBuilder<'a, ()>,
1919 ) -> &'b mut DiagnosticBuilder<'a, ()>,
1920 ) {
1921 let (level, src) = self.lint_level_at_node(lint, id);
1922 struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
1923 }
1924
in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]>1925 pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
1926 let map = self.in_scope_traits_map(id.owner)?;
1927 let candidates = map.get(&id.local_id)?;
1928 Some(candidates)
1929 }
1930
named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg>1931 pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
1932 debug!(?id, "named_region");
1933 self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
1934 }
1935
is_late_bound(self, id: HirId) -> bool1936 pub fn is_late_bound(self, id: HirId) -> bool {
1937 self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
1938 }
1939
late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind>1940 pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
1941 self.mk_bound_variable_kinds(
1942 &self
1943 .late_bound_vars_map(id.owner)
1944 .and_then(|map| map.get(&id.local_id).cloned())
1945 .unwrap_or_else(|| {
1946 bug!("No bound vars found for {}", self.hir().node_to_string(id))
1947 }),
1948 )
1949 }
1950
1951 /// Whether the `def_id` counts as const fn in the current crate, considering all active
1952 /// feature gates
is_const_fn(self, def_id: DefId) -> bool1953 pub fn is_const_fn(self, def_id: DefId) -> bool {
1954 if self.is_const_fn_raw(def_id) {
1955 match self.lookup_const_stability(def_id) {
1956 Some(stability) if stability.is_const_unstable() => {
1957 // has a `rustc_const_unstable` attribute, check whether the user enabled the
1958 // corresponding feature gate.
1959 self.features()
1960 .declared_lib_features
1961 .iter()
1962 .any(|&(sym, _)| sym == stability.feature)
1963 }
1964 // functions without const stability are either stable user written
1965 // const fn or the user is using feature gates and we thus don't
1966 // care what they do
1967 _ => true,
1968 }
1969 } else {
1970 false
1971 }
1972 }
1973
1974 /// Whether the trait impl is marked const. This does not consider stability or feature gates.
is_const_trait_impl_raw(self, def_id: DefId) -> bool1975 pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool {
1976 let Some(local_def_id) = def_id.as_local() else { return false };
1977 let hir_id = self.local_def_id_to_hir_id(local_def_id);
1978 let node = self.hir().get(hir_id);
1979
1980 matches!(
1981 node,
1982 hir::Node::Item(hir::Item {
1983 kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
1984 ..
1985 })
1986 )
1987 }
1988
local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId1989 pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId {
1990 self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
1991 }
1992
next_trait_solver_globally(self) -> bool1993 pub fn next_trait_solver_globally(self) -> bool {
1994 self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
1995 }
1996
next_trait_solver_in_coherence(self) -> bool1997 pub fn next_trait_solver_in_coherence(self) -> bool {
1998 matches!(
1999 self.sess.opts.unstable_opts.trait_solver,
2000 rustc_session::config::TraitSolver::Next
2001 | rustc_session::config::TraitSolver::NextCoherence
2002 )
2003 }
2004
lower_impl_trait_in_trait_to_assoc_ty(self) -> bool2005 pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
2006 self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
2007 }
2008
is_impl_trait_in_trait(self, def_id: DefId) -> bool2009 pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
2010 if self.lower_impl_trait_in_trait_to_assoc_ty() {
2011 self.opt_rpitit_info(def_id).is_some()
2012 } else {
2013 self.def_kind(def_id) == DefKind::ImplTraitPlaceholder
2014 }
2015 }
2016
2017 /// Named module children from all kinds of items, including imports.
2018 /// In addition to regular items this list also includes struct and variant constructors, and
2019 /// items inside `extern {}` blocks because all of them introduce names into parent module.
2020 ///
2021 /// Module here is understood in name resolution sense - it can be a `mod` item,
2022 /// or a crate root, or an enum, or a trait.
2023 ///
2024 /// This is not a query, making it a query causes perf regressions
2025 /// (probably due to hashing spans in `ModChild`ren).
module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild]2026 pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
2027 self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
2028 }
2029 }
2030
2031 /// Parameter attributes that can only be determined by examining the body of a function instead
2032 /// of just its signature.
2033 ///
2034 /// These can be useful for optimization purposes when a function is directly called. We compute
2035 /// them and store them into the crate metadata so that downstream crates can make use of them.
2036 ///
2037 /// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
2038 /// future.
2039 #[derive(Clone, Copy, PartialEq, Debug, Default, TyDecodable, TyEncodable, HashStable)]
2040 pub struct DeducedParamAttrs {
2041 /// The parameter is marked immutable in the function and contains no `UnsafeCell` (i.e. its
2042 /// type is freeze).
2043 pub read_only: bool,
2044 }
2045
provide(providers: &mut Providers)2046 pub fn provide(providers: &mut Providers) {
2047 providers.maybe_unused_trait_imports =
2048 |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
2049 providers.names_imported_by_glob_use = |tcx, id| {
2050 tcx.arena.alloc(UnordSet::from(
2051 tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default(),
2052 ))
2053 };
2054
2055 providers.extern_mod_stmt_cnum =
2056 |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
2057 providers.is_panic_runtime =
2058 |tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::panic_runtime);
2059 providers.is_compiler_builtins =
2060 |tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
2061 providers.has_panic_handler = |tcx, LocalCrate| {
2062 // We want to check if the panic handler was defined in this crate
2063 tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
2064 };
2065 providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
2066 }
2067