]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/ty/context.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / context.rs
1 //! Type context book-keeping.
2
3 #![allow(rustc::usage_of_ty_tykind)]
4
5 use crate::arena::Arena;
6 use crate::dep_graph::{DepGraph, DepKindStruct};
7 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
8 use crate::lint::struct_lint_level;
9 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
10 use crate::middle::resolve_lifetime;
11 use crate::middle::stability;
12 use crate::mir::interpret::{self, Allocation, ConstAllocation};
13 use crate::mir::{
14 Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
15 };
16 use crate::thir::Thir;
17 use crate::traits;
18 use crate::ty::query::{self, TyCtxtAt};
19 use crate::ty::{
20 self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
21 FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
22 ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
23 ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
24 Visibility,
25 };
26 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
27 use rustc_ast as ast;
28 use rustc_data_structures::fingerprint::Fingerprint;
29 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
30 use rustc_data_structures::intern::Interned;
31 use rustc_data_structures::memmap::Mmap;
32 use rustc_data_structures::profiling::SelfProfilerRef;
33 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
34 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
35 use rustc_data_structures::steal::Steal;
36 use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
37 use rustc_errors::{
38 DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
39 };
40 use rustc_hir as hir;
41 use rustc_hir::def::DefKind;
42 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
43 use rustc_hir::definitions::Definitions;
44 use rustc_hir::intravisit::Visitor;
45 use rustc_hir::lang_items::LangItem;
46 use rustc_hir::{
47 Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
48 };
49 use rustc_index::vec::IndexVec;
50 use rustc_macros::HashStable;
51 use rustc_query_system::dep_graph::DepNodeIndex;
52 use rustc_query_system::ich::StableHashingContext;
53 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
54 use rustc_session::config::CrateType;
55 use rustc_session::cstore::{CrateStoreDyn, Untracked};
56 use rustc_session::lint::Lint;
57 use rustc_session::Limit;
58 use rustc_session::Session;
59 use rustc_span::def_id::{DefPathHash, StableCrateId};
60 use rustc_span::source_map::SourceMap;
61 use rustc_span::symbol::{kw, sym, Ident, Symbol};
62 use rustc_span::{Span, DUMMY_SP};
63 use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
64 use rustc_target::spec::abi;
65 use rustc_type_ir::sty::TyKind::*;
66 use rustc_type_ir::WithCachedTypeInfo;
67 use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
68
69 use std::any::Any;
70 use std::borrow::Borrow;
71 use std::cmp::Ordering;
72 use std::fmt;
73 use std::hash::{Hash, Hasher};
74 use std::iter;
75 use std::mem;
76 use std::ops::{Bound, Deref};
77
78 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
79 /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
80 fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
81 where
82 Self: Sized;
83
84 fn new_empty(source_map: &'tcx SourceMap) -> Self
85 where
86 Self: Sized;
87
88 fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
89
90 fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult;
91 }
92
93 #[allow(rustc::usage_of_ty_tykind)]
94 impl<'tcx> Interner for TyCtxt<'tcx> {
95 type AdtDef = ty::AdtDef<'tcx>;
96 type SubstsRef = ty::SubstsRef<'tcx>;
97 type DefId = DefId;
98 type Ty = Ty<'tcx>;
99 type Const = ty::Const<'tcx>;
100 type Region = Region<'tcx>;
101 type TypeAndMut = TypeAndMut<'tcx>;
102 type Mutability = hir::Mutability;
103 type Movability = hir::Movability;
104 type PolyFnSig = PolyFnSig<'tcx>;
105 type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
106 type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
107 type ListTy = &'tcx List<Ty<'tcx>>;
108 type AliasTy = ty::AliasTy<'tcx>;
109 type ParamTy = ParamTy;
110 type BoundTy = ty::BoundTy;
111 type PlaceholderType = ty::PlaceholderType;
112 type InferTy = InferTy;
113 type ErrorGuaranteed = ErrorGuaranteed;
114 type PredicateKind = ty::PredicateKind<'tcx>;
115 type AllocId = crate::mir::interpret::AllocId;
116
117 type EarlyBoundRegion = ty::EarlyBoundRegion;
118 type BoundRegion = ty::BoundRegion;
119 type FreeRegion = ty::FreeRegion;
120 type RegionVid = ty::RegionVid;
121 type PlaceholderRegion = ty::PlaceholderRegion;
122 }
123
124 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
125
126 pub struct CtxtInterners<'tcx> {
127 /// The arena that types, regions, etc. are allocated from.
128 arena: &'tcx WorkerLocal<Arena<'tcx>>,
129
130 // Specifically use a speedy hash algorithm for these hash sets, since
131 // they're accessed quite often.
132 type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
133 const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
134 substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
135 canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
136 region: InternedSet<'tcx, RegionKind<'tcx>>,
137 poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
138 predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
139 predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
140 projs: InternedSet<'tcx, List<ProjectionKind>>,
141 place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
142 const_: InternedSet<'tcx, ConstData<'tcx>>,
143 const_allocation: InternedSet<'tcx, Allocation>,
144 bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
145 layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
146 adt_def: InternedSet<'tcx, AdtDefData>,
147 }
148
149 impl<'tcx> CtxtInterners<'tcx> {
150 fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
151 CtxtInterners {
152 arena,
153 type_: Default::default(),
154 const_lists: Default::default(),
155 substs: Default::default(),
156 region: Default::default(),
157 poly_existential_predicates: Default::default(),
158 canonical_var_infos: Default::default(),
159 predicate: Default::default(),
160 predicates: Default::default(),
161 projs: Default::default(),
162 place_elems: Default::default(),
163 const_: Default::default(),
164 const_allocation: Default::default(),
165 bound_variable_kinds: Default::default(),
166 layout: Default::default(),
167 adt_def: Default::default(),
168 }
169 }
170
171 /// Interns a type.
172 #[allow(rustc::usage_of_ty_tykind)]
173 #[inline(never)]
174 fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
175 Ty(Interned::new_unchecked(
176 self.type_
177 .intern(kind, |kind| {
178 let flags = super::flags::FlagComputation::for_kind(&kind);
179 let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
180
181 InternedInSet(self.arena.alloc(WithCachedTypeInfo {
182 internee: kind,
183 stable_hash,
184 flags: flags.flags,
185 outer_exclusive_binder: flags.outer_exclusive_binder,
186 }))
187 })
188 .0,
189 ))
190 }
191
192 fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
193 &self,
194 flags: &ty::flags::FlagComputation,
195 sess: &'a Session,
196 untracked: &'a Untracked,
197 val: &T,
198 ) -> Fingerprint {
199 // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
200 // Without incremental, we rarely stable-hash types, so let's not do it proactively.
201 if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() {
202 Fingerprint::ZERO
203 } else {
204 let mut hasher = StableHasher::new();
205 let mut hcx = StableHashingContext::new(sess, untracked);
206 val.hash_stable(&mut hcx, &mut hasher);
207 hasher.finish()
208 }
209 }
210
211 #[inline(never)]
212 fn intern_predicate(
213 &self,
214 kind: Binder<'tcx, PredicateKind<'tcx>>,
215 sess: &Session,
216 untracked: &Untracked,
217 ) -> Predicate<'tcx> {
218 Predicate(Interned::new_unchecked(
219 self.predicate
220 .intern(kind, |kind| {
221 let flags = super::flags::FlagComputation::for_predicate(kind);
222
223 let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
224
225 InternedInSet(self.arena.alloc(WithCachedTypeInfo {
226 internee: kind,
227 stable_hash,
228 flags: flags.flags,
229 outer_exclusive_binder: flags.outer_exclusive_binder,
230 }))
231 })
232 .0,
233 ))
234 }
235 }
236
237 pub struct CommonTypes<'tcx> {
238 pub unit: Ty<'tcx>,
239 pub bool: Ty<'tcx>,
240 pub char: Ty<'tcx>,
241 pub isize: Ty<'tcx>,
242 pub i8: Ty<'tcx>,
243 pub i16: Ty<'tcx>,
244 pub i32: Ty<'tcx>,
245 pub i64: Ty<'tcx>,
246 pub i128: Ty<'tcx>,
247 pub usize: Ty<'tcx>,
248 pub u8: Ty<'tcx>,
249 pub u16: Ty<'tcx>,
250 pub u32: Ty<'tcx>,
251 pub u64: Ty<'tcx>,
252 pub u128: Ty<'tcx>,
253 pub f32: Ty<'tcx>,
254 pub f64: Ty<'tcx>,
255 pub str_: Ty<'tcx>,
256 pub never: Ty<'tcx>,
257 pub self_param: Ty<'tcx>,
258
259 /// Dummy type used for the `Self` of a `TraitRef` created for converting
260 /// a trait object, and which gets removed in `ExistentialTraitRef`.
261 /// This type must not appear anywhere in other converted types.
262 pub trait_object_dummy_self: Ty<'tcx>,
263 }
264
265 pub struct CommonLifetimes<'tcx> {
266 /// `ReStatic`
267 pub re_static: Region<'tcx>,
268
269 /// Erased region, used outside of type inference.
270 pub re_erased: Region<'tcx>,
271 }
272
273 pub struct CommonConsts<'tcx> {
274 pub unit: Const<'tcx>,
275 }
276
277 impl<'tcx> CommonTypes<'tcx> {
278 fn new(
279 interners: &CtxtInterners<'tcx>,
280 sess: &Session,
281 untracked: &Untracked,
282 ) -> CommonTypes<'tcx> {
283 let mk = |ty| interners.intern_ty(ty, sess, untracked);
284
285 CommonTypes {
286 unit: mk(Tuple(List::empty())),
287 bool: mk(Bool),
288 char: mk(Char),
289 never: mk(Never),
290 isize: mk(Int(ty::IntTy::Isize)),
291 i8: mk(Int(ty::IntTy::I8)),
292 i16: mk(Int(ty::IntTy::I16)),
293 i32: mk(Int(ty::IntTy::I32)),
294 i64: mk(Int(ty::IntTy::I64)),
295 i128: mk(Int(ty::IntTy::I128)),
296 usize: mk(Uint(ty::UintTy::Usize)),
297 u8: mk(Uint(ty::UintTy::U8)),
298 u16: mk(Uint(ty::UintTy::U16)),
299 u32: mk(Uint(ty::UintTy::U32)),
300 u64: mk(Uint(ty::UintTy::U64)),
301 u128: mk(Uint(ty::UintTy::U128)),
302 f32: mk(Float(ty::FloatTy::F32)),
303 f64: mk(Float(ty::FloatTy::F64)),
304 str_: mk(Str),
305 self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
306
307 trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
308 }
309 }
310 }
311
312 impl<'tcx> CommonLifetimes<'tcx> {
313 fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> {
314 let mk = |r| {
315 Region(Interned::new_unchecked(
316 interners.region.intern(r, |r| InternedInSet(interners.arena.alloc(r))).0,
317 ))
318 };
319
320 CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
321 }
322 }
323
324 impl<'tcx> CommonConsts<'tcx> {
325 fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
326 let mk_const = |c| {
327 Const(Interned::new_unchecked(
328 interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0,
329 ))
330 };
331
332 CommonConsts {
333 unit: mk_const(ty::ConstData {
334 kind: ty::ConstKind::Value(ty::ValTree::zst()),
335 ty: types.unit,
336 }),
337 }
338 }
339 }
340
341 /// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
342 /// conflict.
343 #[derive(Debug)]
344 pub struct FreeRegionInfo {
345 /// `LocalDefId` corresponding to FreeRegion
346 pub def_id: LocalDefId,
347 /// the bound region corresponding to FreeRegion
348 pub boundregion: ty::BoundRegionKind,
349 /// checks if bound region is in Impl Item
350 pub is_impl_item: bool,
351 }
352
353 /// This struct should only be created by `create_def`.
354 #[derive(Copy, Clone)]
355 pub struct TyCtxtFeed<'tcx, KEY: Copy> {
356 pub tcx: TyCtxt<'tcx>,
357 // Do not allow direct access, as downstream code must not mutate this field.
358 key: KEY,
359 }
360
361 impl<'tcx> TyCtxt<'tcx> {
362 pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
363 TyCtxtFeed { tcx: self, key: () }
364 }
365 pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
366 TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
367 }
368 }
369
370 impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
371 #[inline(always)]
372 pub fn key(&self) -> KEY {
373 self.key
374 }
375 }
376
377 impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
378 #[inline(always)]
379 pub fn def_id(&self) -> LocalDefId {
380 self.key
381 }
382 }
383
384 /// The central data structure of the compiler. It stores references
385 /// to the various **arenas** and also houses the results of the
386 /// various **compiler queries** that have been performed. See the
387 /// [rustc dev guide] for more details.
388 ///
389 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
390 #[derive(Copy, Clone)]
391 #[rustc_diagnostic_item = "TyCtxt"]
392 #[rustc_pass_by_value]
393 pub struct TyCtxt<'tcx> {
394 gcx: &'tcx GlobalCtxt<'tcx>,
395 }
396
397 impl<'tcx> Deref for TyCtxt<'tcx> {
398 type Target = &'tcx GlobalCtxt<'tcx>;
399 #[inline(always)]
400 fn deref(&self) -> &Self::Target {
401 &self.gcx
402 }
403 }
404
405 pub struct GlobalCtxt<'tcx> {
406 pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
407 pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
408
409 interners: CtxtInterners<'tcx>,
410
411 pub sess: &'tcx Session,
412
413 /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
414 ///
415 /// FIXME(Centril): consider `dyn LintStoreMarker` once
416 /// we can upcast to `Any` for some additional type safety.
417 pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
418
419 pub dep_graph: DepGraph,
420
421 pub prof: SelfProfilerRef,
422
423 /// Common types, pre-interned for your convenience.
424 pub types: CommonTypes<'tcx>,
425
426 /// Common lifetimes, pre-interned for your convenience.
427 pub lifetimes: CommonLifetimes<'tcx>,
428
429 /// Common consts, pre-interned for your convenience.
430 pub consts: CommonConsts<'tcx>,
431
432 untracked: Untracked,
433
434 /// This provides access to the incremental compilation on-disk cache for query results.
435 /// Do not access this directly. It is only meant to be used by
436 /// `DepGraph::try_mark_green()` and the query infrastructure.
437 /// This is `None` if we are not incremental compilation mode
438 pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
439
440 pub queries: &'tcx dyn query::QueryEngine<'tcx>,
441 pub query_caches: query::QueryCaches<'tcx>,
442 pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
443
444 // Internal caches for metadata decoding. No need to track deps on this.
445 pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
446 pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
447
448 /// Caches the results of trait selection. This cache is used
449 /// for things that do not have to do with the parameters in scope.
450 pub selection_cache: traits::SelectionCache<'tcx>,
451
452 /// Caches the results of trait evaluation. This cache is used
453 /// for things that do not have to do with the parameters in scope.
454 /// Merge this with `selection_cache`?
455 pub evaluation_cache: traits::EvaluationCache<'tcx>,
456
457 /// Data layout specification for the current target.
458 pub data_layout: TargetDataLayout,
459
460 /// Stores memory for globals (statics/consts).
461 pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
462 }
463
464 impl<'tcx> TyCtxt<'tcx> {
465 /// Expects a body and returns its codegen attributes.
466 ///
467 /// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
468 /// constants.
469 pub fn body_codegen_attrs(self, def_id: DefId) -> &'tcx CodegenFnAttrs {
470 let def_kind = self.def_kind(def_id);
471 if def_kind.has_codegen_attrs() {
472 self.codegen_fn_attrs(def_id)
473 } else if matches!(
474 def_kind,
475 DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
476 ) {
477 CodegenFnAttrs::EMPTY
478 } else {
479 bug!(
480 "body_codegen_fn_attrs called on unexpected definition: {:?} {:?}",
481 def_id,
482 def_kind
483 )
484 }
485 }
486
487 pub fn typeck_opt_const_arg(
488 self,
489 def: ty::WithOptConstParam<LocalDefId>,
490 ) -> &'tcx TypeckResults<'tcx> {
491 if let Some(param_did) = def.const_param_did {
492 self.typeck_const_arg((def.did, param_did))
493 } else {
494 self.typeck(def.did)
495 }
496 }
497
498 pub fn mir_borrowck_opt_const_arg(
499 self,
500 def: ty::WithOptConstParam<LocalDefId>,
501 ) -> &'tcx BorrowCheckResult<'tcx> {
502 if let Some(param_did) = def.const_param_did {
503 self.mir_borrowck_const_arg((def.did, param_did))
504 } else {
505 self.mir_borrowck(def.did)
506 }
507 }
508
509 pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
510 self.arena.alloc(Steal::new(thir))
511 }
512
513 pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
514 self.arena.alloc(Steal::new(mir))
515 }
516
517 pub fn alloc_steal_promoted(
518 self,
519 promoted: IndexVec<Promoted, Body<'tcx>>,
520 ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
521 self.arena.alloc(Steal::new(promoted))
522 }
523
524 pub fn alloc_adt_def(
525 self,
526 did: DefId,
527 kind: AdtKind,
528 variants: IndexVec<VariantIdx, ty::VariantDef>,
529 repr: ReprOptions,
530 ) -> ty::AdtDef<'tcx> {
531 self.intern_adt_def(ty::AdtDefData::new(self, did, kind, variants, repr))
532 }
533
534 /// Allocates a read-only byte or string literal for `mir::interpret`.
535 pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
536 // Create an allocation that just contains these bytes.
537 let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
538 let alloc = self.intern_const_alloc(alloc);
539 self.create_memory_alloc(alloc)
540 }
541
542 /// Returns a range of the start/end indices specified with the
543 /// `rustc_layout_scalar_valid_range` attribute.
544 // FIXME(eddyb) this is an awkward spot for this method, maybe move it?
545 pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
546 let get = |name| {
547 let Some(attr) = self.get_attr(def_id, name) else {
548 return Bound::Unbounded;
549 };
550 debug!("layout_scalar_valid_range: attr={:?}", attr);
551 if let Some(
552 &[
553 ast::NestedMetaItem::Lit(ast::MetaItemLit {
554 kind: ast::LitKind::Int(a, _),
555 ..
556 }),
557 ],
558 ) = attr.meta_item_list().as_deref()
559 {
560 Bound::Included(a)
561 } else {
562 self.sess
563 .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute");
564 Bound::Unbounded
565 }
566 };
567 (
568 get(sym::rustc_layout_scalar_valid_range_start),
569 get(sym::rustc_layout_scalar_valid_range_end),
570 )
571 }
572
573 pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
574 value.lift_to_tcx(self)
575 }
576
577 /// Creates a type context and call the closure with a `TyCtxt` reference
578 /// to the context. The closure enforces that the type context and any interned
579 /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
580 /// reference to the context, to allow formatting values that need it.
581 pub fn create_global_ctxt(
582 s: &'tcx Session,
583 lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
584 arena: &'tcx WorkerLocal<Arena<'tcx>>,
585 hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
586 untracked: Untracked,
587 dep_graph: DepGraph,
588 on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
589 queries: &'tcx dyn query::QueryEngine<'tcx>,
590 query_kinds: &'tcx [DepKindStruct<'tcx>],
591 ) -> GlobalCtxt<'tcx> {
592 let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
593 s.emit_fatal(err);
594 });
595 let interners = CtxtInterners::new(arena);
596 let common_types = CommonTypes::new(&interners, s, &untracked);
597 let common_lifetimes = CommonLifetimes::new(&interners);
598 let common_consts = CommonConsts::new(&interners, &common_types);
599
600 GlobalCtxt {
601 sess: s,
602 lint_store,
603 arena,
604 hir_arena,
605 interners,
606 dep_graph,
607 prof: s.prof.clone(),
608 types: common_types,
609 lifetimes: common_lifetimes,
610 consts: common_consts,
611 untracked,
612 on_disk_cache,
613 queries,
614 query_caches: query::QueryCaches::default(),
615 query_kinds,
616 ty_rcache: Default::default(),
617 pred_rcache: Default::default(),
618 selection_cache: Default::default(),
619 evaluation_cache: Default::default(),
620 data_layout,
621 alloc_map: Lock::new(interpret::AllocMap::new()),
622 }
623 }
624
625 /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
626 #[track_caller]
627 pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
628 self.mk_ty(Error(reported))
629 }
630
631 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
632 #[track_caller]
633 pub fn ty_error(self) -> Ty<'tcx> {
634 self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
635 }
636
637 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
638 /// ensure it gets used.
639 #[track_caller]
640 pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
641 let reported = self.sess.delay_span_bug(span, msg);
642 self.mk_ty(Error(reported))
643 }
644
645 /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
646 #[track_caller]
647 pub fn const_error_with_guaranteed(
648 self,
649 ty: Ty<'tcx>,
650 reported: ErrorGuaranteed,
651 ) -> Const<'tcx> {
652 self.mk_const(ty::ConstKind::Error(reported), ty)
653 }
654
655 /// Like [TyCtxt::ty_error] but for constants.
656 #[track_caller]
657 pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
658 self.const_error_with_message(
659 ty,
660 DUMMY_SP,
661 "ty::ConstKind::Error constructed but no error reported",
662 )
663 }
664
665 /// Like [TyCtxt::ty_error_with_message] but for constants.
666 #[track_caller]
667 pub fn const_error_with_message<S: Into<MultiSpan>>(
668 self,
669 ty: Ty<'tcx>,
670 span: S,
671 msg: &str,
672 ) -> Const<'tcx> {
673 let reported = self.sess.delay_span_bug(span, msg);
674 self.mk_const(ty::ConstKind::Error(reported), ty)
675 }
676
677 pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
678 let cname = self.crate_name(LOCAL_CRATE);
679 self.sess.consider_optimizing(cname.as_str(), msg)
680 }
681
682 /// Obtain all lang items of this crate and all dependencies (recursively)
683 pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
684 self.get_lang_items(())
685 }
686
687 /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
688 /// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
689 pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
690 self.all_diagnostic_items(()).name_to_id.get(&name).copied()
691 }
692
693 /// Obtain the diagnostic item's name
694 pub fn get_diagnostic_name(self, id: DefId) -> Option<Symbol> {
695 self.diagnostic_items(id.krate).id_to_name.get(&id).copied()
696 }
697
698 /// Check whether the diagnostic item with the given `name` has the given `DefId`.
699 pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool {
700 self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
701 }
702
703 /// Returns `true` if the node pointed to by `def_id` is a generator for an async construct.
704 pub fn generator_is_async(self, def_id: DefId) -> bool {
705 matches!(self.generator_kind(def_id), Some(hir::GeneratorKind::Async(_)))
706 }
707
708 pub fn stability(self) -> &'tcx stability::Index {
709 self.stability_index(())
710 }
711
712 pub fn features(self) -> &'tcx rustc_feature::Features {
713 self.features_query(())
714 }
715
716 pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
717 // Accessing the DefKey is ok, since it is part of DefPathHash.
718 if let Some(id) = id.as_local() {
719 self.definitions_untracked().def_key(id)
720 } else {
721 self.untracked.cstore.def_key(id)
722 }
723 }
724
725 /// Converts a `DefId` into its fully expanded `DefPath` (every
726 /// `DefId` is really just an interned `DefPath`).
727 ///
728 /// Note that if `id` is not local to this crate, the result will
729 /// be a non-local `DefPath`.
730 pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
731 // Accessing the DefPath is ok, since it is part of DefPathHash.
732 if let Some(id) = id.as_local() {
733 self.definitions_untracked().def_path(id)
734 } else {
735 self.untracked.cstore.def_path(id)
736 }
737 }
738
739 #[inline]
740 pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
741 // Accessing the DefPathHash is ok, it is incr. comp. stable.
742 if let Some(def_id) = def_id.as_local() {
743 self.definitions_untracked().def_path_hash(def_id)
744 } else {
745 self.untracked.cstore.def_path_hash(def_id)
746 }
747 }
748
749 #[inline]
750 pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
751 if crate_num == LOCAL_CRATE {
752 self.sess.local_stable_crate_id()
753 } else {
754 self.untracked.cstore.stable_crate_id(crate_num)
755 }
756 }
757
758 /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
759 /// that the crate in question has already been loaded by the CrateStore.
760 #[inline]
761 pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
762 if stable_crate_id == self.sess.local_stable_crate_id() {
763 LOCAL_CRATE
764 } else {
765 self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
766 }
767 }
768
769 /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
770 /// session, if it still exists. This is used during incremental compilation to
771 /// turn a deserialized `DefPathHash` into its current `DefId`.
772 pub fn def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() -> !) -> DefId {
773 debug!("def_path_hash_to_def_id({:?})", hash);
774
775 let stable_crate_id = hash.stable_crate_id();
776
777 // If this is a DefPathHash from the local crate, we can look up the
778 // DefId in the tcx's `Definitions`.
779 if stable_crate_id == self.sess.local_stable_crate_id() {
780 self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
781 } else {
782 // If this is a DefPathHash from an upstream crate, let the CrateStore map
783 // it to a DefId.
784 let cstore = &*self.untracked.cstore;
785 let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
786 cstore.def_path_hash_to_def_id(cnum, hash)
787 }
788 }
789
790 pub fn def_path_debug_str(self, def_id: DefId) -> String {
791 // We are explicitly not going through queries here in order to get
792 // crate name and stable crate id since this code is called from debug!()
793 // statements within the query system and we'd run into endless
794 // recursion otherwise.
795 let (crate_name, stable_crate_id) = if def_id.is_local() {
796 (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
797 } else {
798 let cstore = &*self.untracked.cstore;
799 (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
800 };
801
802 format!(
803 "{}[{:04x}]{}",
804 crate_name,
805 // Don't print the whole stable crate id. That's just
806 // annoying in debug output.
807 stable_crate_id.to_u64() >> 8 * 6,
808 self.def_path(def_id).to_string_no_crate_verbose()
809 )
810 }
811 }
812
813 impl<'tcx> TyCtxtAt<'tcx> {
814 /// Create a new definition within the incr. comp. engine.
815 pub fn create_def(
816 self,
817 parent: LocalDefId,
818 data: hir::definitions::DefPathData,
819 ) -> TyCtxtFeed<'tcx, LocalDefId> {
820 // This function modifies `self.definitions` using a side-effect.
821 // We need to ensure that these side effects are re-run by the incr. comp. engine.
822 // Depending on the forever-red node will tell the graph that the calling query
823 // needs to be re-evaluated.
824 self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
825
826 // The following call has the side effect of modifying the tables inside `definitions`.
827 // These very tables are relied on by the incr. comp. engine to decode DepNodes and to
828 // decode the on-disk cache.
829 //
830 // Any LocalDefId which is used within queries, either as key or result, either:
831 // - has been created before the construction of the TyCtxt;
832 // - has been created by this call to `create_def`.
833 // As a consequence, this LocalDefId is always re-created before it is needed by the incr.
834 // comp. engine itself.
835 //
836 // This call also writes to the value of `source_span` and `expn_that_defined` queries.
837 // This is fine because:
838 // - those queries are `eval_always` so we won't miss their result changing;
839 // - this write will have happened before these queries are called.
840 let key = self.untracked.definitions.write().create_def(parent, data);
841
842 let feed = TyCtxtFeed { tcx: self.tcx, key };
843 feed.def_span(self.span);
844 feed
845 }
846 }
847
848 impl<'tcx> TyCtxt<'tcx> {
849 pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
850 // Create a dependency to the red node to be sure we re-execute this when the amount of
851 // definitions change.
852 self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
853
854 let definitions = &self.untracked.definitions;
855 std::iter::from_generator(|| {
856 let mut i = 0;
857
858 // Recompute the number of definitions each time, because our caller may be creating
859 // new ones.
860 while i < { definitions.read().num_definitions() } {
861 let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
862 yield LocalDefId { local_def_index };
863 i += 1;
864 }
865
866 // Leak a read lock once we finish iterating on definitions, to prevent adding new ones.
867 definitions.leak();
868 })
869 }
870
871 pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
872 // Create a dependency to the crate to be sure we re-execute this when the amount of
873 // definitions change.
874 self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
875
876 // Leak a read lock once we start iterating on definitions, to prevent adding new ones
877 // while iterating. If some query needs to add definitions, it should be `ensure`d above.
878 let definitions = self.untracked.definitions.leak();
879 definitions.def_path_table()
880 }
881
882 pub fn def_path_hash_to_def_index_map(
883 self,
884 ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap {
885 // Create a dependency to the crate to be sure we re-execute this when the amount of
886 // definitions change.
887 self.ensure().hir_crate(());
888 // Leak a read lock once we start iterating on definitions, to prevent adding new ones
889 // while iterating. If some query needs to add definitions, it should be `ensure`d above.
890 let definitions = self.untracked.definitions.leak();
891 definitions.def_path_hash_to_def_index_map()
892 }
893
894 /// Note that this is *untracked* and should only be used within the query
895 /// system if the result is otherwise tracked through queries
896 pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn {
897 &*self.untracked.cstore
898 }
899
900 /// Note that this is *untracked* and should only be used within the query
901 /// system if the result is otherwise tracked through queries
902 #[inline]
903 pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
904 self.untracked.definitions.read()
905 }
906
907 /// Note that this is *untracked* and should only be used within the query
908 /// system if the result is otherwise tracked through queries
909 #[inline]
910 pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
911 self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
912 }
913
914 #[inline(always)]
915 pub fn with_stable_hashing_context<R>(
916 self,
917 f: impl FnOnce(StableHashingContext<'_>) -> R,
918 ) -> R {
919 f(StableHashingContext::new(self.sess, &self.untracked))
920 }
921
922 pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
923 self.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
924 }
925
926 /// If `true`, we should use lazy normalization for constants, otherwise
927 /// we still evaluate them eagerly.
928 #[inline]
929 pub fn lazy_normalization(self) -> bool {
930 let features = self.features();
931 // Note: We only use lazy normalization for generic const expressions.
932 features.generic_const_exprs
933 }
934
935 #[inline]
936 pub fn local_crate_exports_generics(self) -> bool {
937 debug_assert!(self.sess.opts.share_generics());
938
939 self.sess.crate_types().iter().any(|crate_type| {
940 match crate_type {
941 CrateType::Executable
942 | CrateType::Staticlib
943 | CrateType::ProcMacro
944 | CrateType::Cdylib => false,
945
946 // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
947 // We want to block export of generics from dylibs,
948 // but we must fix rust-lang/rust#65890 before we can
949 // do that robustly.
950 CrateType::Dylib => true,
951
952 CrateType::Rlib => true,
953 }
954 })
955 }
956
957 /// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
958 pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
959 let (suitable_region_binding_scope, bound_region) = match *region {
960 ty::ReFree(ref free_region) => {
961 (free_region.scope.expect_local(), free_region.bound_region)
962 }
963 ty::ReEarlyBound(ref ebr) => (
964 self.local_parent(ebr.def_id.expect_local()),
965 ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
966 ),
967 _ => return None, // not a free region
968 };
969
970 let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
971 Some(Node::Item(..) | Node::TraitItem(..)) => false,
972 Some(Node::ImplItem(..)) => {
973 self.is_bound_region_in_impl_item(suitable_region_binding_scope)
974 }
975 _ => return None,
976 };
977
978 Some(FreeRegionInfo {
979 def_id: suitable_region_binding_scope,
980 boundregion: bound_region,
981 is_impl_item,
982 })
983 }
984
985 /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
986 pub fn return_type_impl_or_dyn_traits(
987 self,
988 scope_def_id: LocalDefId,
989 ) -> Vec<&'tcx hir::Ty<'tcx>> {
990 let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
991 let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
992 return vec![];
993 };
994
995 let mut v = TraitObjectVisitor(vec![], self.hir());
996 v.visit_ty(hir_output);
997 v.0
998 }
999
1000 pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
1001 // `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
1002 match self.hir().get_by_def_id(scope_def_id) {
1003 Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
1004 Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
1005 Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
1006 Node::Expr(&hir::Expr { kind: ExprKind::Closure { .. }, .. }) => {}
1007 _ => return None,
1008 }
1009
1010 let ret_ty = self.type_of(scope_def_id);
1011 match ret_ty.kind() {
1012 ty::FnDef(_, _) => {
1013 let sig = ret_ty.fn_sig(self);
1014 let output = self.erase_late_bound_regions(sig.output());
1015 if output.is_impl_trait() {
1016 let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
1017 let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
1018 Some((output, fn_decl.output.span()))
1019 } else {
1020 None
1021 }
1022 }
1023 _ => None,
1024 }
1025 }
1026
1027 /// Checks if the bound region is in Impl Item.
1028 pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
1029 let container_id = self.parent(suitable_region_binding_scope.to_def_id());
1030 if self.impl_trait_ref(container_id).is_some() {
1031 // For now, we do not try to target impls of traits. This is
1032 // because this message is going to suggest that the user
1033 // change the fn signature, but they may not be free to do so,
1034 // since the signature must match the trait.
1035 //
1036 // FIXME(#42706) -- in some cases, we could do better here.
1037 return true;
1038 }
1039 false
1040 }
1041
1042 /// Determines whether identifiers in the assembly have strict naming rules.
1043 /// Currently, only NVPTX* targets need it.
1044 pub fn has_strict_asm_symbol_naming(self) -> bool {
1045 self.sess.target.arch.contains("nvptx")
1046 }
1047
1048 /// Returns `&'static core::panic::Location<'static>`.
1049 pub fn caller_location_ty(self) -> Ty<'tcx> {
1050 self.mk_imm_ref(
1051 self.lifetimes.re_static,
1052 self.bound_type_of(self.require_lang_item(LangItem::PanicLocation, None))
1053 .subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
1054 )
1055 }
1056
1057 /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
1058 pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
1059 match self.def_kind(def_id) {
1060 DefKind::Generator => match self.generator_kind(def_id).unwrap() {
1061 rustc_hir::GeneratorKind::Async(..) => ("an", "async closure"),
1062 rustc_hir::GeneratorKind::Gen => ("a", "generator"),
1063 },
1064 def_kind => (def_kind.article(), def_kind.descr(def_id)),
1065 }
1066 }
1067
1068 pub fn type_length_limit(self) -> Limit {
1069 self.limits(()).type_length_limit
1070 }
1071
1072 pub fn recursion_limit(self) -> Limit {
1073 self.limits(()).recursion_limit
1074 }
1075
1076 pub fn move_size_limit(self) -> Limit {
1077 self.limits(()).move_size_limit
1078 }
1079
1080 pub fn const_eval_limit(self) -> Limit {
1081 self.limits(()).const_eval_limit
1082 }
1083
1084 pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
1085 iter::once(LOCAL_CRATE)
1086 .chain(self.crates(()).iter().copied())
1087 .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
1088 }
1089
1090 #[inline]
1091 pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
1092 self.visibility(def_id).expect_local()
1093 }
1094 }
1095
1096 /// A trait implemented for all `X<'a>` types that can be safely and
1097 /// efficiently converted to `X<'tcx>` as long as they are part of the
1098 /// provided `TyCtxt<'tcx>`.
1099 /// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>`
1100 /// by looking them up in their respective interners.
1101 ///
1102 /// However, this is still not the best implementation as it does
1103 /// need to compare the components, even for interned values.
1104 /// It would be more efficient if `TypedArena` provided a way to
1105 /// determine whether the address is in the allocated range.
1106 ///
1107 /// `None` is returned if the value or one of the components is not part
1108 /// of the provided context.
1109 /// For `Ty`, `None` can be returned if either the type interner doesn't
1110 /// contain the `TyKind` key or if the address of the interned
1111 /// pointer differs. The latter case is possible if a primitive type,
1112 /// e.g., `()` or `u8`, was interned in a different context.
1113 pub trait Lift<'tcx>: fmt::Debug {
1114 type Lifted: fmt::Debug + 'tcx;
1115 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
1116 }
1117
1118 macro_rules! nop_lift {
1119 ($set:ident; $ty:ty => $lifted:ty) => {
1120 impl<'a, 'tcx> Lift<'tcx> for $ty {
1121 type Lifted = $lifted;
1122 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
1123 if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)) {
1124 // SAFETY: `self` is interned and therefore valid
1125 // for the entire lifetime of the `TyCtxt`.
1126 Some(unsafe { mem::transmute(self) })
1127 } else {
1128 None
1129 }
1130 }
1131 }
1132 };
1133 }
1134
1135 // Can't use the macros as we have reuse the `substs` here.
1136 //
1137 // See `intern_type_list` for more info.
1138 impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
1139 type Lifted = &'tcx List<Ty<'tcx>>;
1140 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
1141 if self.is_empty() {
1142 return Some(List::empty());
1143 }
1144 if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
1145 // SAFETY: `self` is interned and therefore valid
1146 // for the entire lifetime of the `TyCtxt`.
1147 Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
1148 } else {
1149 None
1150 }
1151 }
1152 }
1153
1154 macro_rules! nop_list_lift {
1155 ($set:ident; $ty:ty => $lifted:ty) => {
1156 impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
1157 type Lifted = &'tcx List<$lifted>;
1158 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
1159 if self.is_empty() {
1160 return Some(List::empty());
1161 }
1162 if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
1163 Some(unsafe { mem::transmute(self) })
1164 } else {
1165 None
1166 }
1167 }
1168 }
1169 };
1170 }
1171
1172 nop_lift! {type_; Ty<'a> => Ty<'tcx>}
1173 nop_lift! {region; Region<'a> => Region<'tcx>}
1174 nop_lift! {const_; Const<'a> => Const<'tcx>}
1175 nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
1176 nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
1177
1178 nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
1179 nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
1180 nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
1181 nop_list_lift! {projs; ProjectionKind => ProjectionKind}
1182 nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
1183
1184 // This is the impl for `&'a InternalSubsts<'a>`.
1185 nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
1186
1187 CloneLiftImpls! { for<'tcx> {
1188 Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
1189 } }
1190
1191 pub mod tls {
1192 use super::{ptr_eq, GlobalCtxt, TyCtxt};
1193
1194 use crate::dep_graph::TaskDepsRef;
1195 use crate::ty::query;
1196 use rustc_data_structures::sync::{self, Lock};
1197 use rustc_errors::Diagnostic;
1198 use std::mem;
1199 use thin_vec::ThinVec;
1200
1201 #[cfg(not(parallel_compiler))]
1202 use std::cell::Cell;
1203
1204 #[cfg(parallel_compiler)]
1205 use rustc_rayon_core as rayon_core;
1206
1207 /// This is the implicit state of rustc. It contains the current
1208 /// `TyCtxt` and query. It is updated when creating a local interner or
1209 /// executing a new query. Whenever there's a `TyCtxt` value available
1210 /// you should also have access to an `ImplicitCtxt` through the functions
1211 /// in this module.
1212 #[derive(Clone)]
1213 pub struct ImplicitCtxt<'a, 'tcx> {
1214 /// The current `TyCtxt`.
1215 pub tcx: TyCtxt<'tcx>,
1216
1217 /// The current query job, if any. This is updated by `JobOwner::start` in
1218 /// `ty::query::plumbing` when executing a query.
1219 pub query: Option<query::QueryJobId>,
1220
1221 /// Where to store diagnostics for the current query job, if any.
1222 /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
1223 pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
1224
1225 /// Used to prevent queries from calling too deeply.
1226 pub query_depth: usize,
1227
1228 /// The current dep graph task. This is used to add dependencies to queries
1229 /// when executing them.
1230 pub task_deps: TaskDepsRef<'a>,
1231 }
1232
1233 impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
1234 pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
1235 let tcx = TyCtxt { gcx };
1236 ImplicitCtxt {
1237 tcx,
1238 query: None,
1239 diagnostics: None,
1240 query_depth: 0,
1241 task_deps: TaskDepsRef::Ignore,
1242 }
1243 }
1244 }
1245
1246 /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
1247 /// to `value` during the call to `f`. It is restored to its previous value after.
1248 /// This is used to set the pointer to the new `ImplicitCtxt`.
1249 #[cfg(parallel_compiler)]
1250 #[inline]
1251 fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1252 rayon_core::tlv::with(value, f)
1253 }
1254
1255 /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
1256 /// This is used to get the pointer to the current `ImplicitCtxt`.
1257 #[cfg(parallel_compiler)]
1258 #[inline]
1259 pub fn get_tlv() -> usize {
1260 rayon_core::tlv::get()
1261 }
1262
1263 #[cfg(not(parallel_compiler))]
1264 thread_local! {
1265 /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
1266 static TLV: Cell<usize> = const { Cell::new(0) };
1267 }
1268
1269 /// Sets TLV to `value` during the call to `f`.
1270 /// It is restored to its previous value after.
1271 /// This is used to set the pointer to the new `ImplicitCtxt`.
1272 #[cfg(not(parallel_compiler))]
1273 #[inline]
1274 fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1275 let old = get_tlv();
1276 let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
1277 TLV.with(|tlv| tlv.set(value));
1278 f()
1279 }
1280
1281 /// Gets the pointer to the current `ImplicitCtxt`.
1282 #[cfg(not(parallel_compiler))]
1283 #[inline]
1284 fn get_tlv() -> usize {
1285 TLV.with(|tlv| tlv.get())
1286 }
1287
1288 /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
1289 #[inline]
1290 pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
1291 where
1292 F: FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
1293 {
1294 set_tlv(context as *const _ as usize, || f(&context))
1295 }
1296
1297 /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
1298 #[inline]
1299 pub fn with_context_opt<F, R>(f: F) -> R
1300 where
1301 F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
1302 {
1303 let context = get_tlv();
1304 if context == 0 {
1305 f(None)
1306 } else {
1307 // We could get an `ImplicitCtxt` pointer from another thread.
1308 // Ensure that `ImplicitCtxt` is `Sync`.
1309 sync::assert_sync::<ImplicitCtxt<'_, '_>>();
1310
1311 unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) }
1312 }
1313 }
1314
1315 /// Allows access to the current `ImplicitCtxt`.
1316 /// Panics if there is no `ImplicitCtxt` available.
1317 #[inline]
1318 pub fn with_context<F, R>(f: F) -> R
1319 where
1320 F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
1321 {
1322 with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
1323 }
1324
1325 /// Allows access to the current `ImplicitCtxt` whose tcx field is the same as the tcx argument
1326 /// passed in. This means the closure is given an `ImplicitCtxt` with the same `'tcx` lifetime
1327 /// as the `TyCtxt` passed in.
1328 /// This will panic if you pass it a `TyCtxt` which is different from the current
1329 /// `ImplicitCtxt`'s `tcx` field.
1330 #[inline]
1331 pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
1332 where
1333 F: FnOnce(&ImplicitCtxt<'_, 'tcx>) -> R,
1334 {
1335 with_context(|context| unsafe {
1336 assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
1337 let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
1338 f(context)
1339 })
1340 }
1341
1342 /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
1343 /// Panics if there is no `ImplicitCtxt` available.
1344 #[inline]
1345 pub fn with<F, R>(f: F) -> R
1346 where
1347 F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
1348 {
1349 with_context(|context| f(context.tcx))
1350 }
1351
1352 /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
1353 /// The closure is passed None if there is no `ImplicitCtxt` available.
1354 #[inline]
1355 pub fn with_opt<F, R>(f: F) -> R
1356 where
1357 F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
1358 {
1359 with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
1360 }
1361 }
1362
1363 macro_rules! sty_debug_print {
1364 ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
1365 // Curious inner module to allow variant names to be used as
1366 // variable names.
1367 #[allow(non_snake_case)]
1368 mod inner {
1369 use crate::ty::{self, TyCtxt};
1370 use crate::ty::context::InternedInSet;
1371
1372 #[derive(Copy, Clone)]
1373 struct DebugStat {
1374 total: usize,
1375 lt_infer: usize,
1376 ty_infer: usize,
1377 ct_infer: usize,
1378 all_infer: usize,
1379 }
1380
1381 pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
1382 let mut total = DebugStat {
1383 total: 0,
1384 lt_infer: 0,
1385 ty_infer: 0,
1386 ct_infer: 0,
1387 all_infer: 0,
1388 };
1389 $(let mut $variant = total;)*
1390
1391 let shards = tcx.interners.type_.lock_shards();
1392 let types = shards.iter().flat_map(|shard| shard.keys());
1393 for &InternedInSet(t) in types {
1394 let variant = match t.internee {
1395 ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
1396 ty::Float(..) | ty::Str | ty::Never => continue,
1397 ty::Error(_) => /* unimportant */ continue,
1398 $(ty::$variant(..) => &mut $variant,)*
1399 };
1400 let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
1401 let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
1402 let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
1403
1404 variant.total += 1;
1405 total.total += 1;
1406 if lt { total.lt_infer += 1; variant.lt_infer += 1 }
1407 if ty { total.ty_infer += 1; variant.ty_infer += 1 }
1408 if ct { total.ct_infer += 1; variant.ct_infer += 1 }
1409 if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
1410 }
1411 writeln!(fmt, "Ty interner total ty lt ct all")?;
1412 $(writeln!(fmt, " {:18}: {uses:6} {usespc:4.1}%, \
1413 {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1414 stringify!($variant),
1415 uses = $variant.total,
1416 usespc = $variant.total as f64 * 100.0 / total.total as f64,
1417 ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
1418 lt = $variant.lt_infer as f64 * 100.0 / total.total as f64,
1419 ct = $variant.ct_infer as f64 * 100.0 / total.total as f64,
1420 all = $variant.all_infer as f64 * 100.0 / total.total as f64)?;
1421 )*
1422 writeln!(fmt, " total {uses:6} \
1423 {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
1424 uses = total.total,
1425 ty = total.ty_infer as f64 * 100.0 / total.total as f64,
1426 lt = total.lt_infer as f64 * 100.0 / total.total as f64,
1427 ct = total.ct_infer as f64 * 100.0 / total.total as f64,
1428 all = total.all_infer as f64 * 100.0 / total.total as f64)
1429 }
1430 }
1431
1432 inner::go($fmt, $ctxt)
1433 }}
1434 }
1435
1436 impl<'tcx> TyCtxt<'tcx> {
1437 pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx {
1438 struct DebugStats<'tcx>(TyCtxt<'tcx>);
1439
1440 impl<'tcx> std::fmt::Debug for DebugStats<'tcx> {
1441 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1442 sty_debug_print!(
1443 fmt,
1444 self.0,
1445 Adt,
1446 Array,
1447 Slice,
1448 RawPtr,
1449 Ref,
1450 FnDef,
1451 FnPtr,
1452 Placeholder,
1453 Generator,
1454 GeneratorWitness,
1455 Dynamic,
1456 Closure,
1457 Tuple,
1458 Bound,
1459 Param,
1460 Infer,
1461 Alias,
1462 Foreign
1463 )?;
1464
1465 writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
1466 writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
1467 writeln!(
1468 fmt,
1469 "Const Allocation interner: #{}",
1470 self.0.interners.const_allocation.len()
1471 )?;
1472 writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
1473
1474 Ok(())
1475 }
1476 }
1477
1478 DebugStats(self)
1479 }
1480 }
1481
1482 // This type holds a `T` in the interner. The `T` is stored in the arena and
1483 // this type just holds a pointer to it, but it still effectively owns it. It
1484 // impls `Borrow` so that it can be looked up using the original
1485 // (non-arena-memory-owning) types.
1486 struct InternedInSet<'tcx, T: ?Sized>(&'tcx T);
1487
1488 impl<'tcx, T: 'tcx + ?Sized> Clone for InternedInSet<'tcx, T> {
1489 fn clone(&self) -> Self {
1490 InternedInSet(self.0)
1491 }
1492 }
1493
1494 impl<'tcx, T: 'tcx + ?Sized> Copy for InternedInSet<'tcx, T> {}
1495
1496 impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
1497 fn into_pointer(&self) -> *const () {
1498 self.0 as *const _ as *const ()
1499 }
1500 }
1501
1502 #[allow(rustc::usage_of_ty_tykind)]
1503 impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1504 fn borrow(&self) -> &T {
1505 &self.0.internee
1506 }
1507 }
1508
1509 impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1510 fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
1511 // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1512 // `x == y`.
1513 self.0.internee == other.0.internee
1514 }
1515 }
1516
1517 impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
1518
1519 impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
1520 fn hash<H: Hasher>(&self, s: &mut H) {
1521 // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1522 self.0.internee.hash(s)
1523 }
1524 }
1525
1526 impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
1527 fn borrow(&self) -> &[T] {
1528 &self.0[..]
1529 }
1530 }
1531
1532 impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> {
1533 fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool {
1534 // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
1535 // `x == y`.
1536 self.0[..] == other.0[..]
1537 }
1538 }
1539
1540 impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {}
1541
1542 impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
1543 fn hash<H: Hasher>(&self, s: &mut H) {
1544 // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
1545 self.0[..].hash(s)
1546 }
1547 }
1548
1549 macro_rules! direct_interners {
1550 ($($name:ident: $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
1551 $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
1552 fn borrow<'a>(&'a self) -> &'a $ty {
1553 &self.0
1554 }
1555 }
1556
1557 impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
1558 fn eq(&self, other: &Self) -> bool {
1559 // The `Borrow` trait requires that `x.borrow() == y.borrow()`
1560 // equals `x == y`.
1561 self.0 == other.0
1562 }
1563 }
1564
1565 impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}
1566
1567 impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
1568 fn hash<H: Hasher>(&self, s: &mut H) {
1569 // The `Borrow` trait requires that `x.borrow().hash(s) ==
1570 // x.hash(s)`.
1571 self.0.hash(s)
1572 }
1573 }
1574
1575 impl<'tcx> TyCtxt<'tcx> {
1576 pub fn $method(self, v: $ty) -> $ret_ty {
1577 $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
1578 InternedInSet(self.interners.arena.alloc(v))
1579 }).0))
1580 }
1581 })+
1582 }
1583 }
1584
1585 direct_interners! {
1586 region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
1587 const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
1588 const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
1589 layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
1590 adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
1591 }
1592
1593 macro_rules! slice_interners {
1594 ($($field:ident: $method:ident($ty:ty)),+ $(,)?) => (
1595 impl<'tcx> TyCtxt<'tcx> {
1596 $(pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
1597 self.interners.$field.intern_ref(v, || {
1598 InternedInSet(List::from_arena(&*self.arena, v))
1599 }).0
1600 })+
1601 }
1602 );
1603 }
1604
1605 slice_interners!(
1606 const_lists: _intern_const_list(Const<'tcx>),
1607 substs: _intern_substs(GenericArg<'tcx>),
1608 canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
1609 poly_existential_predicates:
1610 _intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
1611 predicates: _intern_predicates(Predicate<'tcx>),
1612 projs: _intern_projs(ProjectionKind),
1613 place_elems: _intern_place_elems(PlaceElem<'tcx>),
1614 bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
1615 );
1616
1617 impl<'tcx> TyCtxt<'tcx> {
1618 /// Given a `fn` type, returns an equivalent `unsafe fn` type;
1619 /// that is, a `fn` type that is equivalent in every way for being
1620 /// unsafe.
1621 pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
1622 assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
1623 self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
1624 }
1625
1626 /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
1627 /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
1628 pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
1629 self.super_traits_of(trait_def_id).any(|trait_did| {
1630 self.associated_items(trait_did)
1631 .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
1632 .is_some()
1633 })
1634 }
1635
1636 /// Given a `ty`, return whether it's an `impl Future<...>`.
1637 pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
1638 let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
1639 let future_trait = self.require_lang_item(LangItem::Future, None);
1640
1641 self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
1642 let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
1643 return false;
1644 };
1645 trait_predicate.trait_ref.def_id == future_trait
1646 && trait_predicate.polarity == ImplPolarity::Positive
1647 })
1648 }
1649
1650 /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally)
1651 /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
1652 /// to identify which traits may define a given associated type to help avoid cycle errors.
1653 /// Returns a `DefId` iterator.
1654 fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
1655 let mut set = FxHashSet::default();
1656 let mut stack = vec![trait_def_id];
1657
1658 set.insert(trait_def_id);
1659
1660 iter::from_fn(move || -> Option<DefId> {
1661 let trait_did = stack.pop()?;
1662 let generic_predicates = self.super_predicates_of(trait_did);
1663
1664 for (predicate, _) in generic_predicates.predicates {
1665 if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) =
1666 predicate.kind().skip_binder()
1667 {
1668 if set.insert(data.def_id()) {
1669 stack.push(data.def_id());
1670 }
1671 }
1672 }
1673
1674 Some(trait_did)
1675 })
1676 }
1677
1678 /// Given a closure signature, returns an equivalent fn signature. Detuples
1679 /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
1680 /// you would get a `fn(u32, i32)`.
1681 /// `unsafety` determines the unsafety of the fn signature. If you pass
1682 /// `hir::Unsafety::Unsafe` in the previous example, then you would get
1683 /// an `unsafe fn (u32, i32)`.
1684 /// It cannot convert a closure that requires unsafe.
1685 pub fn signature_unclosure(
1686 self,
1687 sig: PolyFnSig<'tcx>,
1688 unsafety: hir::Unsafety,
1689 ) -> PolyFnSig<'tcx> {
1690 sig.map_bound(|s| {
1691 let params_iter = match s.inputs()[0].kind() {
1692 ty::Tuple(params) => params.into_iter(),
1693 _ => bug!(),
1694 };
1695 self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
1696 })
1697 }
1698
1699 /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
1700 /// `*r == kind`.
1701 #[inline]
1702 pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
1703 if *r == kind { r } else { self.mk_region(kind) }
1704 }
1705
1706 #[allow(rustc::usage_of_ty_tykind)]
1707 #[inline]
1708 pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
1709 self.interners.intern_ty(
1710 st,
1711 self.sess,
1712 // This is only used to create a stable hashing context.
1713 &self.untracked,
1714 )
1715 }
1716
1717 #[inline]
1718 pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
1719 self.interners.intern_predicate(
1720 binder,
1721 self.sess,
1722 // This is only used to create a stable hashing context.
1723 &self.untracked,
1724 )
1725 }
1726
1727 #[inline]
1728 pub fn reuse_or_mk_predicate(
1729 self,
1730 pred: Predicate<'tcx>,
1731 binder: Binder<'tcx, PredicateKind<'tcx>>,
1732 ) -> Predicate<'tcx> {
1733 if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
1734 }
1735
1736 pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
1737 match tm {
1738 IntTy::Isize => self.types.isize,
1739 IntTy::I8 => self.types.i8,
1740 IntTy::I16 => self.types.i16,
1741 IntTy::I32 => self.types.i32,
1742 IntTy::I64 => self.types.i64,
1743 IntTy::I128 => self.types.i128,
1744 }
1745 }
1746
1747 pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> {
1748 match tm {
1749 UintTy::Usize => self.types.usize,
1750 UintTy::U8 => self.types.u8,
1751 UintTy::U16 => self.types.u16,
1752 UintTy::U32 => self.types.u32,
1753 UintTy::U64 => self.types.u64,
1754 UintTy::U128 => self.types.u128,
1755 }
1756 }
1757
1758 pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> {
1759 match tm {
1760 FloatTy::F32 => self.types.f32,
1761 FloatTy::F64 => self.types.f64,
1762 }
1763 }
1764
1765 #[inline]
1766 pub fn mk_static_str(self) -> Ty<'tcx> {
1767 self.mk_imm_ref(self.lifetimes.re_static, self.types.str_)
1768 }
1769
1770 #[inline]
1771 pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
1772 // Take a copy of substs so that we own the vectors inside.
1773 self.mk_ty(Adt(def, substs))
1774 }
1775
1776 #[inline]
1777 pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
1778 self.mk_ty(Foreign(def_id))
1779 }
1780
1781 fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
1782 let adt_def = self.adt_def(wrapper_def_id);
1783 let substs =
1784 InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind {
1785 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
1786 GenericParamDefKind::Type { has_default, .. } => {
1787 if param.index == 0 {
1788 ty_param.into()
1789 } else {
1790 assert!(has_default);
1791 self.bound_type_of(param.def_id).subst(self, substs).into()
1792 }
1793 }
1794 });
1795 self.mk_ty(Adt(adt_def, substs))
1796 }
1797
1798 #[inline]
1799 pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
1800 let def_id = self.require_lang_item(LangItem::OwnedBox, None);
1801 self.mk_generic_adt(def_id, ty)
1802 }
1803
1804 #[inline]
1805 pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
1806 let def_id = self.lang_items().get(item)?;
1807 Some(self.mk_generic_adt(def_id, ty))
1808 }
1809
1810 #[inline]
1811 pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
1812 let def_id = self.get_diagnostic_item(name)?;
1813 Some(self.mk_generic_adt(def_id, ty))
1814 }
1815
1816 #[inline]
1817 pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
1818 let def_id = self.require_lang_item(LangItem::MaybeUninit, None);
1819 self.mk_generic_adt(def_id, ty)
1820 }
1821
1822 #[inline]
1823 pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
1824 self.mk_ty(RawPtr(tm))
1825 }
1826
1827 #[inline]
1828 pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
1829 self.mk_ty(Ref(r, tm.ty, tm.mutbl))
1830 }
1831
1832 #[inline]
1833 pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
1834 self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
1835 }
1836
1837 #[inline]
1838 pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
1839 self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
1840 }
1841
1842 #[inline]
1843 pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
1844 self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut })
1845 }
1846
1847 #[inline]
1848 pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
1849 self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not })
1850 }
1851
1852 #[inline]
1853 pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
1854 self.mk_ty(Array(ty, ty::Const::from_usize(self, n)))
1855 }
1856
1857 #[inline]
1858 pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
1859 self.mk_ty(Slice(ty))
1860 }
1861
1862 #[inline]
1863 pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
1864 self.mk_ty(Tuple(self.intern_type_list(&ts)))
1865 }
1866
1867 pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
1868 iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts))))
1869 }
1870
1871 #[inline]
1872 pub fn mk_unit(self) -> Ty<'tcx> {
1873 self.types.unit
1874 }
1875
1876 #[inline]
1877 pub fn mk_diverging_default(self) -> Ty<'tcx> {
1878 if self.features().never_type_fallback { self.types.never } else { self.types.unit }
1879 }
1880
1881 #[inline]
1882 pub fn mk_fn_def(
1883 self,
1884 def_id: DefId,
1885 substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
1886 ) -> Ty<'tcx> {
1887 let substs = self.check_substs(def_id, substs);
1888 self.mk_ty(FnDef(def_id, substs))
1889 }
1890
1891 #[inline(always)]
1892 fn check_substs(
1893 self,
1894 _def_id: DefId,
1895 substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
1896 ) -> SubstsRef<'tcx> {
1897 let substs = substs.into_iter().map(Into::into);
1898 #[cfg(debug_assertions)]
1899 {
1900 let n = self.generics_of(_def_id).count();
1901 assert_eq!(
1902 (n, Some(n)),
1903 substs.size_hint(),
1904 "wrong number of generic parameters for {_def_id:?}: {:?}",
1905 substs.collect::<Vec<_>>(),
1906 );
1907 }
1908 self.mk_substs(substs)
1909 }
1910
1911 #[inline]
1912 pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
1913 self.mk_ty(FnPtr(fty))
1914 }
1915
1916 #[inline]
1917 pub fn mk_dynamic(
1918 self,
1919 obj: &'tcx List<PolyExistentialPredicate<'tcx>>,
1920 reg: ty::Region<'tcx>,
1921 repr: DynKind,
1922 ) -> Ty<'tcx> {
1923 self.mk_ty(Dynamic(obj, reg, repr))
1924 }
1925
1926 #[inline]
1927 pub fn mk_projection(
1928 self,
1929 item_def_id: DefId,
1930 substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
1931 ) -> Ty<'tcx> {
1932 self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
1933 }
1934
1935 #[inline]
1936 pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> {
1937 self.mk_ty(Closure(closure_id, closure_substs))
1938 }
1939
1940 #[inline]
1941 pub fn mk_generator(
1942 self,
1943 id: DefId,
1944 generator_substs: SubstsRef<'tcx>,
1945 movability: hir::Movability,
1946 ) -> Ty<'tcx> {
1947 self.mk_ty(Generator(id, generator_substs, movability))
1948 }
1949
1950 #[inline]
1951 pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
1952 self.mk_ty(GeneratorWitness(types))
1953 }
1954
1955 /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
1956 pub fn mk_task_context(self) -> Ty<'tcx> {
1957 let context_did = self.require_lang_item(LangItem::Context, None);
1958 let context_adt_ref = self.adt_def(context_did);
1959 let context_substs = self.intern_substs(&[self.lifetimes.re_erased.into()]);
1960 let context_ty = self.mk_adt(context_adt_ref, context_substs);
1961 self.mk_mut_ref(self.lifetimes.re_erased, context_ty)
1962 }
1963
1964 #[inline]
1965 pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
1966 self.mk_ty_infer(TyVar(v))
1967 }
1968
1969 #[inline]
1970 pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
1971 self.mk_const_internal(ty::ConstData { kind: kind.into(), ty })
1972 }
1973
1974 #[inline]
1975 pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
1976 self.mk_ty_infer(IntVar(v))
1977 }
1978
1979 #[inline]
1980 pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
1981 self.mk_ty_infer(FloatVar(v))
1982 }
1983
1984 #[inline]
1985 pub fn mk_ty_infer(self, it: InferTy) -> Ty<'tcx> {
1986 self.mk_ty(Infer(it))
1987 }
1988
1989 #[inline]
1990 pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
1991 self.mk_ty(Param(ParamTy { index, name }))
1992 }
1993
1994 pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
1995 match param.kind {
1996 GenericParamDefKind::Lifetime => {
1997 self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
1998 }
1999 GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
2000 GenericParamDefKind::Const { .. } => self
2001 .mk_const(
2002 ParamConst { index: param.index, name: param.name },
2003 self.type_of(param.def_id),
2004 )
2005 .into(),
2006 }
2007 }
2008
2009 #[inline]
2010 pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
2011 self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
2012 }
2013
2014 pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
2015 self.mk_place_elem(place, PlaceElem::Field(f, ty))
2016 }
2017
2018 pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
2019 self.mk_place_elem(place, PlaceElem::Deref)
2020 }
2021
2022 pub fn mk_place_downcast(
2023 self,
2024 place: Place<'tcx>,
2025 adt_def: AdtDef<'tcx>,
2026 variant_index: VariantIdx,
2027 ) -> Place<'tcx> {
2028 self.mk_place_elem(
2029 place,
2030 PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
2031 )
2032 }
2033
2034 pub fn mk_place_downcast_unnamed(
2035 self,
2036 place: Place<'tcx>,
2037 variant_index: VariantIdx,
2038 ) -> Place<'tcx> {
2039 self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
2040 }
2041
2042 pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
2043 self.mk_place_elem(place, PlaceElem::Index(index))
2044 }
2045
2046 /// This method copies `Place`'s projection, add an element and reintern it. Should not be used
2047 /// to build a full `Place` it's just a convenient way to grab a projection and modify it in
2048 /// flight.
2049 pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
2050 let mut projection = place.projection.to_vec();
2051 projection.push(elem);
2052
2053 Place { local: place.local, projection: self.intern_place_elems(&projection) }
2054 }
2055
2056 pub fn intern_poly_existential_predicates(
2057 self,
2058 eps: &[PolyExistentialPredicate<'tcx>],
2059 ) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
2060 assert!(!eps.is_empty());
2061 assert!(
2062 eps.array_windows()
2063 .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
2064 != Ordering::Greater)
2065 );
2066 self._intern_poly_existential_predicates(eps)
2067 }
2068
2069 pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
2070 // FIXME consider asking the input slice to be sorted to avoid
2071 // re-interning permutations, in which case that would be asserted
2072 // here.
2073 if preds.is_empty() {
2074 // The macro-generated method below asserts we don't intern an empty slice.
2075 List::empty()
2076 } else {
2077 self._intern_predicates(preds)
2078 }
2079 }
2080
2081 pub fn mk_const_list<I: InternAs<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>>(
2082 self,
2083 iter: I,
2084 ) -> I::Output {
2085 iter.intern_with(|xs| self.intern_const_list(xs))
2086 }
2087
2088 pub fn intern_const_list(self, cs: &[ty::Const<'tcx>]) -> &'tcx List<ty::Const<'tcx>> {
2089 if cs.is_empty() { List::empty() } else { self._intern_const_list(cs) }
2090 }
2091
2092 pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
2093 if ts.is_empty() {
2094 List::empty()
2095 } else {
2096 // Actually intern type lists as lists of `GenericArg`s.
2097 //
2098 // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
2099 // as explained in ty_slice_as_generic_arg`. With this,
2100 // we guarantee that even when transmuting between `List<Ty<'tcx>>`
2101 // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
2102 // lists is upheld.
2103 let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts));
2104 substs.try_as_type_list().unwrap()
2105 }
2106 }
2107
2108 pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
2109 if ts.is_empty() { List::empty() } else { self._intern_substs(ts) }
2110 }
2111
2112 pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
2113 if ps.is_empty() { List::empty() } else { self._intern_projs(ps) }
2114 }
2115
2116 pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
2117 if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
2118 }
2119
2120 pub fn intern_canonical_var_infos(
2121 self,
2122 ts: &[CanonicalVarInfo<'tcx>],
2123 ) -> CanonicalVarInfos<'tcx> {
2124 if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
2125 }
2126
2127 pub fn intern_bound_variable_kinds(
2128 self,
2129 ts: &[ty::BoundVariableKind],
2130 ) -> &'tcx List<ty::BoundVariableKind> {
2131 if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
2132 }
2133
2134 pub fn mk_fn_sig<I>(
2135 self,
2136 inputs: I,
2137 output: I::Item,
2138 c_variadic: bool,
2139 unsafety: hir::Unsafety,
2140 abi: abi::Abi,
2141 ) -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
2142 where
2143 I: Iterator<Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>,
2144 {
2145 inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
2146 inputs_and_output: self.intern_type_list(xs),
2147 c_variadic,
2148 unsafety,
2149 abi,
2150 })
2151 }
2152
2153 pub fn mk_poly_existential_predicates<
2154 I: InternAs<PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>>,
2155 >(
2156 self,
2157 iter: I,
2158 ) -> I::Output {
2159 iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
2160 }
2161
2162 pub fn mk_predicates<I: InternAs<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>>(
2163 self,
2164 iter: I,
2165 ) -> I::Output {
2166 iter.intern_with(|xs| self.intern_predicates(xs))
2167 }
2168
2169 pub fn mk_type_list<I: InternAs<Ty<'tcx>, &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output {
2170 iter.intern_with(|xs| self.intern_type_list(xs))
2171 }
2172
2173 pub fn mk_substs<I: InternAs<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>>(
2174 self,
2175 iter: I,
2176 ) -> I::Output {
2177 iter.intern_with(|xs| self.intern_substs(xs))
2178 }
2179
2180 pub fn mk_place_elems<I: InternAs<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>>(
2181 self,
2182 iter: I,
2183 ) -> I::Output {
2184 iter.intern_with(|xs| self.intern_place_elems(xs))
2185 }
2186
2187 pub fn mk_substs_trait(
2188 self,
2189 self_ty: Ty<'tcx>,
2190 rest: impl IntoIterator<Item = GenericArg<'tcx>>,
2191 ) -> SubstsRef<'tcx> {
2192 self.mk_substs(iter::once(self_ty.into()).chain(rest))
2193 }
2194
2195 pub fn mk_trait_ref(
2196 self,
2197 trait_def_id: DefId,
2198 substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
2199 ) -> ty::TraitRef<'tcx> {
2200 let substs = self.check_substs(trait_def_id, substs);
2201 ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
2202 }
2203
2204 pub fn mk_alias_ty(
2205 self,
2206 def_id: DefId,
2207 substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
2208 ) -> ty::AliasTy<'tcx> {
2209 let substs = self.check_substs(def_id, substs);
2210 ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
2211 }
2212
2213 pub fn mk_bound_variable_kinds<
2214 I: InternAs<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
2215 >(
2216 self,
2217 iter: I,
2218 ) -> I::Output {
2219 iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
2220 }
2221
2222 /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
2223 /// typically generated by `#[derive(LintDiagnostic)]`).
2224 pub fn emit_spanned_lint(
2225 self,
2226 lint: &'static Lint,
2227 hir_id: HirId,
2228 span: impl Into<MultiSpan>,
2229 decorator: impl for<'a> DecorateLint<'a, ()>,
2230 ) {
2231 let msg = decorator.msg();
2232 let (level, src) = self.lint_level_at_node(lint, hir_id);
2233 struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
2234 decorator.decorate_lint(diag)
2235 })
2236 }
2237
2238 /// Emit a lint at the appropriate level for a hir node, with an associated span.
2239 ///
2240 /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
2241 ///
2242 /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
2243 #[rustc_lint_diagnostics]
2244 pub fn struct_span_lint_hir(
2245 self,
2246 lint: &'static Lint,
2247 hir_id: HirId,
2248 span: impl Into<MultiSpan>,
2249 msg: impl Into<DiagnosticMessage>,
2250 decorate: impl for<'a, 'b> FnOnce(
2251 &'b mut DiagnosticBuilder<'a, ()>,
2252 ) -> &'b mut DiagnosticBuilder<'a, ()>,
2253 ) {
2254 let (level, src) = self.lint_level_at_node(lint, hir_id);
2255 struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
2256 }
2257
2258 /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
2259 /// generated by `#[derive(LintDiagnostic)]`).
2260 pub fn emit_lint(
2261 self,
2262 lint: &'static Lint,
2263 id: HirId,
2264 decorator: impl for<'a> DecorateLint<'a, ()>,
2265 ) {
2266 self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
2267 }
2268
2269 /// Emit a lint at the appropriate level for a hir node.
2270 ///
2271 /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
2272 ///
2273 /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
2274 #[rustc_lint_diagnostics]
2275 pub fn struct_lint_node(
2276 self,
2277 lint: &'static Lint,
2278 id: HirId,
2279 msg: impl Into<DiagnosticMessage>,
2280 decorate: impl for<'a, 'b> FnOnce(
2281 &'b mut DiagnosticBuilder<'a, ()>,
2282 ) -> &'b mut DiagnosticBuilder<'a, ()>,
2283 ) {
2284 let (level, src) = self.lint_level_at_node(lint, id);
2285 struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
2286 }
2287
2288 pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
2289 let map = self.in_scope_traits_map(id.owner)?;
2290 let candidates = map.get(&id.local_id)?;
2291 Some(&*candidates)
2292 }
2293
2294 pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
2295 debug!(?id, "named_region");
2296 self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
2297 }
2298
2299 pub fn is_late_bound(self, id: HirId) -> bool {
2300 self.is_late_bound_map(id.owner.def_id).map_or(false, |set| {
2301 let def_id = self.hir().local_def_id(id);
2302 set.contains(&def_id)
2303 })
2304 }
2305
2306 pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
2307 self.mk_bound_variable_kinds(
2308 self.late_bound_vars_map(id.owner)
2309 .and_then(|map| map.get(&id.local_id).cloned())
2310 .unwrap_or_else(|| {
2311 bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
2312 })
2313 .iter(),
2314 )
2315 }
2316
2317 /// Whether the `def_id` counts as const fn in the current crate, considering all active
2318 /// feature gates
2319 pub fn is_const_fn(self, def_id: DefId) -> bool {
2320 if self.is_const_fn_raw(def_id) {
2321 match self.lookup_const_stability(def_id) {
2322 Some(stability) if stability.is_const_unstable() => {
2323 // has a `rustc_const_unstable` attribute, check whether the user enabled the
2324 // corresponding feature gate.
2325 self.features()
2326 .declared_lib_features
2327 .iter()
2328 .any(|&(sym, _)| sym == stability.feature)
2329 }
2330 // functions without const stability are either stable user written
2331 // const fn or the user is using feature gates and we thus don't
2332 // care what they do
2333 _ => true,
2334 }
2335 } else {
2336 false
2337 }
2338 }
2339
2340 /// Whether the trait impl is marked const. This does not consider stability or feature gates.
2341 pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool {
2342 let Some(local_def_id) = def_id.as_local() else { return false };
2343 let hir_id = self.local_def_id_to_hir_id(local_def_id);
2344 let node = self.hir().get(hir_id);
2345
2346 matches!(
2347 node,
2348 hir::Node::Item(hir::Item {
2349 kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
2350 ..
2351 })
2352 )
2353 }
2354 }
2355
2356 impl<'tcx> TyCtxtAt<'tcx> {
2357 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
2358 #[track_caller]
2359 pub fn ty_error(self) -> Ty<'tcx> {
2360 self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
2361 }
2362
2363 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
2364 /// ensure it gets used.
2365 #[track_caller]
2366 pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
2367 self.tcx.ty_error_with_message(self.span, msg)
2368 }
2369
2370 pub fn mk_trait_ref(
2371 self,
2372 trait_lang_item: LangItem,
2373 substs: impl IntoIterator<Item = impl Into<ty::GenericArg<'tcx>>>,
2374 ) -> ty::TraitRef<'tcx> {
2375 let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span));
2376 self.tcx.mk_trait_ref(trait_def_id, substs)
2377 }
2378 }
2379
2380 /// Parameter attributes that can only be determined by examining the body of a function instead
2381 /// of just its signature.
2382 ///
2383 /// These can be useful for optimization purposes when a function is directly called. We compute
2384 /// them and store them into the crate metadata so that downstream crates can make use of them.
2385 ///
2386 /// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
2387 /// future.
2388 #[derive(Clone, Copy, PartialEq, Debug, Default, TyDecodable, TyEncodable, HashStable)]
2389 pub struct DeducedParamAttrs {
2390 /// The parameter is marked immutable in the function and contains no `UnsafeCell` (i.e. its
2391 /// type is freeze).
2392 pub read_only: bool,
2393 }
2394
2395 // We are comparing types with different invariant lifetimes, so `ptr::eq`
2396 // won't work for us.
2397 fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
2398 t as *const () == u as *const ()
2399 }
2400
2401 pub fn provide(providers: &mut ty::query::Providers) {
2402 providers.module_reexports =
2403 |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
2404 providers.maybe_unused_trait_imports =
2405 |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
2406 providers.maybe_unused_extern_crates =
2407 |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
2408 providers.names_imported_by_glob_use = |tcx, id| {
2409 tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
2410 };
2411
2412 providers.extern_mod_stmt_cnum =
2413 |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
2414 providers.is_panic_runtime = |tcx, cnum| {
2415 assert_eq!(cnum, LOCAL_CRATE);
2416 tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
2417 };
2418 providers.is_compiler_builtins = |tcx, cnum| {
2419 assert_eq!(cnum, LOCAL_CRATE);
2420 tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins)
2421 };
2422 providers.has_panic_handler = |tcx, cnum| {
2423 assert_eq!(cnum, LOCAL_CRATE);
2424 // We want to check if the panic handler was defined in this crate
2425 tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
2426 };
2427 providers.source_span =
2428 |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
2429 }