1 //! Type context book-keeping.
3 #![allow(rustc::usage_of_ty_tykind)]
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}
;
14 Body
, BorrowCheckResult
, Field
, Local
, Place
, PlaceElem
, ProjectionKind
, Promoted
,
16 use crate::thir
::Thir
;
18 use crate::ty
::query
::{self, TyCtxtAt}
;
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
,
26 use crate::ty
::{GenericArg, InternalSubsts, SubstsRef}
;
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}
;
38 DecorateLint
, DiagnosticBuilder
, DiagnosticMessage
, ErrorGuaranteed
, MultiSpan
,
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
;
47 Constness
, ExprKind
, HirId
, ImplItemKind
, ItemKind
, Node
, TraitCandidate
, TraitItemKind
,
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}
;
70 use std
::borrow
::Borrow
;
71 use std
::cmp
::Ordering
;
73 use std
::hash
::{Hash, Hasher}
;
76 use std
::ops
::{Bound, Deref}
;
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
84 fn new_empty(source_map
: &'tcx SourceMap
) -> Self
88 fn drop_serialized_data(&self, tcx
: TyCtxt
<'tcx
>);
90 fn serialize(&self, tcx
: TyCtxt
<'tcx
>, encoder
: FileEncoder
) -> FileEncodeResult
;
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
>;
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
;
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
;
124 type InternedSet
<'tcx
, T
> = ShardedHashMap
<InternedInSet
<'tcx
, T
>, ()>;
126 pub struct CtxtInterners
<'tcx
> {
127 /// The arena that types, regions, etc. are allocated from.
128 arena
: &'tcx WorkerLocal
<Arena
<'tcx
>>,
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
>,
149 impl<'tcx
> CtxtInterners
<'tcx
> {
150 fn new(arena
: &'tcx WorkerLocal
<Arena
<'tcx
>>) -> CtxtInterners
<'tcx
> {
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(),
172 #[allow(rustc::usage_of_ty_tykind)]
174 fn intern_ty(&self, kind
: TyKind
<'tcx
>, sess
: &Session
, untracked
: &Untracked
) -> Ty
<'tcx
> {
175 Ty(Interned
::new_unchecked(
177 .intern(kind
, |kind
| {
178 let flags
= super::flags
::FlagComputation
::for_kind(&kind
);
179 let stable_hash
= self.stable_hash(&flags
, sess
, untracked
, &kind
);
181 InternedInSet(self.arena
.alloc(WithCachedTypeInfo
{
185 outer_exclusive_binder
: flags
.outer_exclusive_binder
,
192 fn stable_hash
<'a
, T
: HashStable
<StableHashingContext
<'a
>>>(
194 flags
: &ty
::flags
::FlagComputation
,
196 untracked
: &'a Untracked
,
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() {
204 let mut hasher
= StableHasher
::new();
205 let mut hcx
= StableHashingContext
::new(sess
, untracked
);
206 val
.hash_stable(&mut hcx
, &mut hasher
);
214 kind
: Binder
<'tcx
, PredicateKind
<'tcx
>>,
216 untracked
: &Untracked
,
217 ) -> Predicate
<'tcx
> {
218 Predicate(Interned
::new_unchecked(
220 .intern(kind
, |kind
| {
221 let flags
= super::flags
::FlagComputation
::for_predicate(kind
);
223 let stable_hash
= self.stable_hash(&flags
, sess
, untracked
, &kind
);
225 InternedInSet(self.arena
.alloc(WithCachedTypeInfo
{
229 outer_exclusive_binder
: flags
.outer_exclusive_binder
,
237 pub struct CommonTypes
<'tcx
> {
257 pub self_param
: Ty
<'tcx
>,
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
>,
265 pub struct CommonLifetimes
<'tcx
> {
267 pub re_static
: Region
<'tcx
>,
269 /// Erased region, used outside of type inference.
270 pub re_erased
: Region
<'tcx
>,
273 pub struct CommonConsts
<'tcx
> {
274 pub unit
: Const
<'tcx
>,
277 impl<'tcx
> CommonTypes
<'tcx
> {
279 interners
: &CtxtInterners
<'tcx
>,
281 untracked
: &Untracked
,
282 ) -> CommonTypes
<'tcx
> {
283 let mk
= |ty
| interners
.intern_ty(ty
, sess
, untracked
);
286 unit
: mk(Tuple(List
::empty())),
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
)),
305 self_param
: mk(ty
::Param(ty
::ParamTy { index: 0, name: kw::SelfUpper }
)),
307 trait_object_dummy_self
: mk(Infer(ty
::FreshTy(0))),
312 impl<'tcx
> CommonLifetimes
<'tcx
> {
313 fn new(interners
: &CtxtInterners
<'tcx
>) -> CommonLifetimes
<'tcx
> {
315 Region(Interned
::new_unchecked(
316 interners
.region
.intern(r
, |r
| InternedInSet(interners
.arena
.alloc(r
))).0,
320 CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
324 impl<'tcx
> CommonConsts
<'tcx
> {
325 fn new(interners
: &CtxtInterners
<'tcx
>, types
: &CommonTypes
<'tcx
>) -> CommonConsts
<'tcx
> {
327 Const(Interned
::new_unchecked(
328 interners
.const_
.intern(c
, |c
| InternedInSet(interners
.arena
.alloc(c
))).0,
333 unit
: mk_const(ty
::ConstData
{
334 kind
: ty
::ConstKind
::Value(ty
::ValTree
::zst()),
341 /// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
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
,
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.
361 impl<'tcx
> TyCtxt
<'tcx
> {
362 pub fn feed_unit_query(self) -> TyCtxtFeed
<'tcx
, ()> {
363 TyCtxtFeed { tcx: self, key: () }
365 pub fn feed_local_crate(self) -> TyCtxtFeed
<'tcx
, CrateNum
> {
366 TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
370 impl<'tcx
, KEY
: Copy
> TyCtxtFeed
<'tcx
, KEY
> {
372 pub fn key(&self) -> KEY
{
377 impl<'tcx
> TyCtxtFeed
<'tcx
, LocalDefId
> {
379 pub fn def_id(&self) -> LocalDefId
{
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.
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
>,
397 impl<'tcx
> Deref
for TyCtxt
<'tcx
> {
398 type Target
= &'tcx GlobalCtxt
<'tcx
>;
400 fn deref(&self) -> &Self::Target
{
405 pub struct GlobalCtxt
<'tcx
> {
406 pub arena
: &'tcx WorkerLocal
<Arena
<'tcx
>>,
407 pub hir_arena
: &'tcx WorkerLocal
<hir
::Arena
<'tcx
>>,
409 interners
: CtxtInterners
<'tcx
>,
411 pub sess
: &'tcx Session
,
413 /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
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
>,
419 pub dep_graph
: DepGraph
,
421 pub prof
: SelfProfilerRef
,
423 /// Common types, pre-interned for your convenience.
424 pub types
: CommonTypes
<'tcx
>,
426 /// Common lifetimes, pre-interned for your convenience.
427 pub lifetimes
: CommonLifetimes
<'tcx
>,
429 /// Common consts, pre-interned for your convenience.
430 pub consts
: CommonConsts
<'tcx
>,
432 untracked
: Untracked
,
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
>>,
440 pub queries
: &'tcx
dyn query
::QueryEngine
<'tcx
>,
441 pub query_caches
: query
::QueryCaches
<'tcx
>,
442 pub(crate) query_kinds
: &'tcx
[DepKindStruct
<'tcx
>],
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
>>>,
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
>,
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
>,
457 /// Data layout specification for the current target.
458 pub data_layout
: TargetDataLayout
,
460 /// Stores memory for globals (statics/consts).
461 pub(crate) alloc_map
: Lock
<interpret
::AllocMap
<'tcx
>>,
464 impl<'tcx
> TyCtxt
<'tcx
> {
465 /// Expects a body and returns its codegen attributes.
467 /// Unlike `codegen_fn_attrs`, this returns `CodegenFnAttrs::EMPTY` for
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
)
475 DefKind
::AnonConst
| DefKind
::AssocConst
| DefKind
::Const
| DefKind
::InlineConst
477 CodegenFnAttrs
::EMPTY
480 "body_codegen_fn_attrs called on unexpected definition: {:?} {:?}",
487 pub fn typeck_opt_const_arg(
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
))
498 pub fn mir_borrowck_opt_const_arg(
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
))
505 self.mir_borrowck(def
.did
)
509 pub fn alloc_steal_thir(self, thir
: Thir
<'tcx
>) -> &'tcx Steal
<Thir
<'tcx
>> {
510 self.arena
.alloc(Steal
::new(thir
))
513 pub fn alloc_steal_mir(self, mir
: Body
<'tcx
>) -> &'tcx Steal
<Body
<'tcx
>> {
514 self.arena
.alloc(Steal
::new(mir
))
517 pub fn alloc_steal_promoted(
519 promoted
: IndexVec
<Promoted
, Body
<'tcx
>>,
520 ) -> &'tcx Steal
<IndexVec
<Promoted
, Body
<'tcx
>>> {
521 self.arena
.alloc(Steal
::new(promoted
))
524 pub fn alloc_adt_def(
528 variants
: IndexVec
<VariantIdx
, ty
::VariantDef
>,
530 ) -> ty
::AdtDef
<'tcx
> {
531 self.intern_adt_def(ty
::AdtDefData
::new(self, did
, kind
, variants
, repr
))
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
)
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
>) {
547 let Some(attr
) = self.get_attr(def_id
, name
) else {
548 return Bound
::Unbounded
;
550 debug
!("layout_scalar_valid_range: attr={:?}", attr
);
553 ast
::NestedMetaItem
::Lit(ast
::MetaItemLit
{
554 kind
: ast
::LitKind
::Int(a
, _
),
558 ) = attr
.meta_item_list().as_deref()
563 .delay_span_bug(attr
.span
, "invalid rustc_layout_scalar_valid_range attribute");
568 get(sym
::rustc_layout_scalar_valid_range_start
),
569 get(sym
::rustc_layout_scalar_valid_range_end
),
573 pub fn lift
<T
: Lift
<'tcx
>>(self, value
: T
) -> Option
<T
::Lifted
> {
574 value
.lift_to_tcx(self)
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(
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
,
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
| {
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
);
607 prof
: s
.prof
.clone(),
609 lifetimes
: common_lifetimes
,
610 consts
: common_consts
,
614 query_caches
: query
::QueryCaches
::default(),
616 ty_rcache
: Default
::default(),
617 pred_rcache
: Default
::default(),
618 selection_cache
: Default
::default(),
619 evaluation_cache
: Default
::default(),
621 alloc_map
: Lock
::new(interpret
::AllocMap
::new()),
625 /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
627 pub fn ty_error_with_guaranteed(self, reported
: ErrorGuaranteed
) -> Ty
<'tcx
> {
628 self.mk_ty(Error(reported
))
631 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
633 pub fn ty_error(self) -> Ty
<'tcx
> {
634 self.ty_error_with_message(DUMMY_SP
, "TyKind::Error constructed but no error reported")
637 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
638 /// ensure it gets used.
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
))
645 /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
647 pub fn const_error_with_guaranteed(
650 reported
: ErrorGuaranteed
,
652 self.mk_const(ty
::ConstKind
::Error(reported
), ty
)
655 /// Like [TyCtxt::ty_error] but for constants.
657 pub fn const_error(self, ty
: Ty
<'tcx
>) -> Const
<'tcx
> {
658 self.const_error_with_message(
661 "ty::ConstKind::Error constructed but no error reported",
665 /// Like [TyCtxt::ty_error_with_message] but for constants.
667 pub fn const_error_with_message
<S
: Into
<MultiSpan
>>(
673 let reported
= self.sess
.delay_span_bug(span
, msg
);
674 self.mk_const(ty
::ConstKind
::Error(reported
), ty
)
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
)
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(())
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()
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()
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
)
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(_
)))
708 pub fn stability(self) -> &'tcx stability
::Index
{
709 self.stability_index(())
712 pub fn features(self) -> &'tcx rustc_feature
::Features
{
713 self.features_query(())
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
)
721 self.untracked
.cstore
.def_key(id
)
725 /// Converts a `DefId` into its fully expanded `DefPath` (every
726 /// `DefId` is really just an interned `DefPath`).
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
)
735 self.untracked
.cstore
.def_path(id
)
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
)
745 self.untracked
.cstore
.def_path_hash(def_id
)
750 pub fn stable_crate_id(self, crate_num
: CrateNum
) -> StableCrateId
{
751 if crate_num
== LOCAL_CRATE
{
752 self.sess
.local_stable_crate_id()
754 self.untracked
.cstore
.stable_crate_id(crate_num
)
758 /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
759 /// that the crate in question has already been loaded by the CrateStore.
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() {
765 self.untracked
.cstore
.stable_crate_id_to_crate_num(stable_crate_id
)
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
);
775 let stable_crate_id
= hash
.stable_crate_id();
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()
782 // If this is a DefPathHash from an upstream crate, let the CrateStore map
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
)
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())
798 let cstore
= &*self.untracked
.cstore
;
799 (cstore
.crate_name(def_id
.krate
), cstore
.stable_crate_id(def_id
.krate
))
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()
813 impl<'tcx
> TyCtxtAt
<'tcx
> {
814 /// Create a new definition within the incr. comp. engine.
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
);
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.
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.
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
);
842 let feed
= TyCtxtFeed { tcx: self.tcx, key }
;
843 feed
.def_span(self.span
);
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
);
854 let definitions
= &self.untracked
.definitions
;
855 std
::iter
::from_generator(|| {
858 // Recompute the number of definitions each time, because our caller may be creating
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 }
;
866 // Leak a read lock once we finish iterating on definitions, to prevent adding new ones.
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
);
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()
882 pub fn def_path_hash_to_def_index_map(
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()
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
900 /// Note that this is *untracked* and should only be used within the query
901 /// system if the result is otherwise tracked through queries
903 pub fn definitions_untracked(self) -> ReadGuard
<'tcx
, Definitions
> {
904 self.untracked
.definitions
.read()
907 /// Note that this is *untracked* and should only be used within the query
908 /// system if the result is otherwise tracked through queries
910 pub fn source_span_untracked(self, def_id
: LocalDefId
) -> Span
{
911 self.untracked
.source_span
.get(def_id
).copied().unwrap_or(DUMMY_SP
)
915 pub fn with_stable_hashing_context
<R
>(
917 f
: impl FnOnce(StableHashingContext
<'_
>) -> R
,
919 f(StableHashingContext
::new(self.sess
, &self.untracked
))
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
))
926 /// If `true`, we should use lazy normalization for constants, otherwise
927 /// we still evaluate them eagerly.
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
936 pub fn local_crate_exports_generics(self) -> bool
{
937 debug_assert
!(self.sess
.opts
.share_generics());
939 self.sess
.crate_types().iter().any(|crate_type
| {
941 CrateType
::Executable
942 | CrateType
::Staticlib
943 | CrateType
::ProcMacro
944 | CrateType
::Cdylib
=> false,
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
950 CrateType
::Dylib
=> true,
952 CrateType
::Rlib
=> true,
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
)
963 ty
::ReEarlyBound(ref ebr
) => (
964 self.local_parent(ebr
.def_id
.expect_local()),
965 ty
::BoundRegionKind
::BrNamed(ebr
.def_id
, ebr
.name
),
967 _
=> return None
, // not a free region
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
)
978 Some(FreeRegionInfo
{
979 def_id
: suitable_region_binding_scope
,
980 boundregion
: bound_region
,
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(
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 {
995 let mut v
= TraitObjectVisitor(vec
![], self.hir());
996 v
.visit_ty(hir_output
);
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 { .. }
, .. }) => {}
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()))
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.
1036 // FIXME(#42706) -- in some cases, we could do better here.
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")
1048 /// Returns `&'static core::panic::Location<'static>`.
1049 pub fn caller_location_ty(self) -> Ty
<'tcx
> {
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())),
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"),
1064 def_kind
=> (def_kind
.article(), def_kind
.descr(def_id
)),
1068 pub fn type_length_limit(self) -> Limit
{
1069 self.limits(()).type_length_limit
1072 pub fn recursion_limit(self) -> Limit
{
1073 self.limits(()).recursion_limit
1076 pub fn move_size_limit(self) -> Limit
{
1077 self.limits(()).move_size_limit
1080 pub fn const_eval_limit(self) -> Limit
{
1081 self.limits(()).const_eval_limit
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())
1091 pub fn local_visibility(self, def_id
: LocalDefId
) -> Visibility
{
1092 self.visibility(def_id
).expect_local()
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.
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.
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
>;
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) }
)
1135 // Can't use the macros as we have reuse the `substs` here.
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());
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) }
)
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());
1162 if tcx
.interners
.$set
.contains_pointer_to(&InternedInSet(self)) {
1163 Some(unsafe { mem::transmute(self) }
)
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>}
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}
1184 // This is the impl for `&'a InternalSubsts<'a>`.
1185 nop_list_lift
! {substs; GenericArg<'a> => GenericArg<'tcx>}
1187 CloneLiftImpls
! { for<'tcx
> {
1188 Constness
, traits
::WellFormedLoc
, ImplPolarity
, crate::mir
::ReturnConstraint
,
1192 use super::{ptr_eq, GlobalCtxt, TyCtxt}
;
1194 use crate::dep_graph
::TaskDepsRef
;
1195 use crate::ty
::query
;
1196 use rustc_data_structures
::sync
::{self, Lock}
;
1197 use rustc_errors
::Diagnostic
;
1199 use thin_vec
::ThinVec
;
1201 #[cfg(not(parallel_compiler))]
1202 use std
::cell
::Cell
;
1204 #[cfg(parallel_compiler)]
1205 use rustc_rayon_core
as rayon_core
;
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
1213 pub struct ImplicitCtxt
<'a
, 'tcx
> {
1214 /// The current `TyCtxt`.
1215 pub tcx
: TyCtxt
<'tcx
>,
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
>,
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
>>>,
1225 /// Used to prevent queries from calling too deeply.
1226 pub query_depth
: usize,
1228 /// The current dep graph task. This is used to add dependencies to queries
1229 /// when executing them.
1230 pub task_deps
: TaskDepsRef
<'a
>,
1233 impl<'a
, 'tcx
> ImplicitCtxt
<'a
, 'tcx
> {
1234 pub fn new(gcx
: &'tcx GlobalCtxt
<'tcx
>) -> Self {
1235 let tcx
= TyCtxt { gcx }
;
1241 task_deps
: TaskDepsRef
::Ignore
,
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)]
1251 fn set_tlv
<F
: FnOnce() -> R
, R
>(value
: usize, f
: F
) -> R
{
1252 rayon_core
::tlv
::with(value
, f
)
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)]
1259 pub fn get_tlv() -> usize {
1260 rayon_core
::tlv
::get()
1263 #[cfg(not(parallel_compiler))]
1265 /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
1266 static TLV
: Cell
<usize> = const { Cell::new(0) }
;
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))]
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
));
1281 /// Gets the pointer to the current `ImplicitCtxt`.
1282 #[cfg(not(parallel_compiler))]
1284 fn get_tlv() -> usize {
1285 TLV
.with(|tlv
| tlv
.get())
1288 /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
1290 pub fn enter_context
<'a
, 'tcx
, F
, R
>(context
: &ImplicitCtxt
<'a
, 'tcx
>, f
: F
) -> R
1292 F
: FnOnce(&ImplicitCtxt
<'a
, 'tcx
>) -> R
,
1294 set_tlv(context
as *const _
as usize, || f(&context
))
1297 /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
1299 pub fn with_context_opt
<F
, R
>(f
: F
) -> R
1301 F
: for<'a
, 'tcx
> FnOnce(Option
<&ImplicitCtxt
<'a
, 'tcx
>>) -> R
,
1303 let context
= get_tlv();
1307 // We could get an `ImplicitCtxt` pointer from another thread.
1308 // Ensure that `ImplicitCtxt` is `Sync`.
1309 sync
::assert_sync
::<ImplicitCtxt
<'_
, '_
>>();
1311 unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) }
1315 /// Allows access to the current `ImplicitCtxt`.
1316 /// Panics if there is no `ImplicitCtxt` available.
1318 pub fn with_context
<F
, R
>(f
: F
) -> R
1320 F
: for<'a
, 'tcx
> FnOnce(&ImplicitCtxt
<'a
, 'tcx
>) -> R
,
1322 with_context_opt(|opt_context
| f(opt_context
.expect("no ImplicitCtxt stored in tls")))
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.
1331 pub fn with_related_context
<'tcx
, F
, R
>(tcx
: TyCtxt
<'tcx
>, f
: F
) -> R
1333 F
: FnOnce(&ImplicitCtxt
<'_
, 'tcx
>) -> R
,
1335 with_context(|context
| unsafe {
1336 assert
!(ptr_eq(context
.tcx
.gcx
, tcx
.gcx
));
1337 let context
: &ImplicitCtxt
<'_
, '_
> = mem
::transmute(context
);
1342 /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
1343 /// Panics if there is no `ImplicitCtxt` available.
1345 pub fn with
<F
, R
>(f
: F
) -> R
1347 F
: for<'tcx
> FnOnce(TyCtxt
<'tcx
>) -> R
,
1349 with_context(|context
| f(context
.tcx
))
1352 /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
1353 /// The closure is passed None if there is no `ImplicitCtxt` available.
1355 pub fn with_opt
<F
, R
>(f
: F
) -> R
1357 F
: for<'tcx
> FnOnce(Option
<TyCtxt
<'tcx
>>) -> R
,
1359 with_context_opt(|opt_context
| f(opt_context
.map(|context
| context
.tcx
)))
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
1367 #[allow(non_snake_case)]
1369 use crate::ty
::{self, TyCtxt}
;
1370 use crate::ty
::context
::InternedInSet
;
1372 #[derive(Copy, Clone)]
1381 pub fn go(fmt
: &mut std
::fmt
::Formatter
<'_
>, tcx
: TyCtxt
<'_
>) -> std
::fmt
::Result
{
1382 let mut total
= DebugStat
{
1389 $
(let mut $variant
= total
;)*
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
,)*
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
);
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 }
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)?
;
1422 writeln
!(fmt
, " total {uses:6} \
1423 {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
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)
1432 inner
::go($fmt
, $ctxt
)
1436 impl<'tcx
> TyCtxt
<'tcx
> {
1437 pub fn debug_stats(self) -> impl std
::fmt
::Debug
+ 'tcx
{
1438 struct DebugStats
<'tcx
>(TyCtxt
<'tcx
>);
1440 impl<'tcx
> std
::fmt
::Debug
for DebugStats
<'tcx
> {
1441 fn fmt(&self, fmt
: &mut std
::fmt
::Formatter
<'_
>) -> std
::fmt
::Result
{
1465 writeln
!(fmt
, "InternalSubsts interner: #{}", self.0.interners
.substs
.len())?
;
1466 writeln
!(fmt
, "Region interner: #{}", self.0.interners
.region
.len())?
;
1469 "Const Allocation interner: #{}",
1470 self.0.interners
.const_allocation
.len()
1472 writeln
!(fmt
, "Layout interner: #{}", self.0.interners
.layout
.len())?
;
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
);
1488 impl<'tcx
, T
: 'tcx
+ ?Sized
> Clone
for InternedInSet
<'tcx
, T
> {
1489 fn clone(&self) -> Self {
1490 InternedInSet(self.0)
1494 impl<'tcx
, T
: 'tcx
+ ?Sized
> Copy
for InternedInSet
<'tcx
, T
> {}
1496 impl<'tcx
, T
: 'tcx
+ ?Sized
> IntoPointer
for InternedInSet
<'tcx
, T
> {
1497 fn into_pointer(&self) -> *const () {
1498 self.0 as *const _
as *const ()
1502 #[allow(rustc::usage_of_ty_tykind)]
1503 impl<'tcx
, T
> Borrow
<T
> for InternedInSet
<'tcx
, WithCachedTypeInfo
<T
>> {
1504 fn borrow(&self) -> &T
{
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
1513 self.0.internee
== other
.0.internee
1517 impl<'tcx
, T
: Eq
> Eq
for InternedInSet
<'tcx
, WithCachedTypeInfo
<T
>> {}
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
)
1526 impl<'tcx
, T
> Borrow
<[T
]> for InternedInSet
<'tcx
, List
<T
>> {
1527 fn borrow(&self) -> &[T
] {
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
1536 self.0[..] == other
.0[..]
1540 impl<'tcx
, T
: Eq
> Eq
for InternedInSet
<'tcx
, List
<T
>> {}
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)`.
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
{
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()`
1565 impl<'tcx
> Eq
for InternedInSet
<'tcx
, $ty
> {}
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) ==
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
))
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
>,
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
))
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
),
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
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 }
))
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
)
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
);
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 {
1645 trait_predicate
.trait_ref
.def_id
== future_trait
1646 && trait_predicate
.polarity
== ImplPolarity
::Positive
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
];
1658 set
.insert(trait_def_id
);
1660 iter
::from_fn(move || -> Option
<DefId
> {
1661 let trait_did
= stack
.pop()?
;
1662 let generic_predicates
= self.super_predicates_of(trait_did
);
1664 for (predicate
, _
) in generic_predicates
.predicates
{
1665 if let ty
::PredicateKind
::Clause(ty
::Clause
::Trait(data
)) =
1666 predicate
.kind().skip_binder()
1668 if set
.insert(data
.def_id()) {
1669 stack
.push(data
.def_id());
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(
1687 sig
: PolyFnSig
<'tcx
>,
1688 unsafety
: hir
::Unsafety
,
1689 ) -> PolyFnSig
<'tcx
> {
1691 let params_iter
= match s
.inputs()[0].kind() {
1692 ty
::Tuple(params
) => params
.into_iter(),
1695 self.mk_fn_sig(params_iter
, s
.output(), s
.c_variadic
, unsafety
, abi
::Abi
::Rust
)
1699 /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
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) }
1706 #[allow(rustc::usage_of_ty_tykind)]
1708 pub fn mk_ty(self, st
: TyKind
<'tcx
>) -> Ty
<'tcx
> {
1709 self.interners
.intern_ty(
1712 // This is only used to create a stable hashing context.
1718 pub fn mk_predicate(self, binder
: Binder
<'tcx
, PredicateKind
<'tcx
>>) -> Predicate
<'tcx
> {
1719 self.interners
.intern_predicate(
1722 // This is only used to create a stable hashing context.
1728 pub fn reuse_or_mk_predicate(
1730 pred
: Predicate
<'tcx
>,
1731 binder
: Binder
<'tcx
, PredicateKind
<'tcx
>>,
1732 ) -> Predicate
<'tcx
> {
1733 if pred
.kind() != binder { self.mk_predicate(binder) }
else { pred }
1736 pub fn mk_mach_int(self, tm
: IntTy
) -> Ty
<'tcx
> {
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
,
1747 pub fn mk_mach_uint(self, tm
: UintTy
) -> Ty
<'tcx
> {
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
,
1758 pub fn mk_mach_float(self, tm
: FloatTy
) -> Ty
<'tcx
> {
1760 FloatTy
::F32
=> self.types
.f32,
1761 FloatTy
::F64
=> self.types
.f64,
1766 pub fn mk_static_str(self) -> Ty
<'tcx
> {
1767 self.mk_imm_ref(self.lifetimes
.re_static
, self.types
.str_
)
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
))
1777 pub fn mk_foreign(self, def_id
: DefId
) -> Ty
<'tcx
> {
1778 self.mk_ty(Foreign(def_id
))
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
);
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 {
1790 assert
!(has_default
);
1791 self.bound_type_of(param
.def_id
).subst(self, substs
).into()
1795 self.mk_ty(Adt(adt_def
, substs
))
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
)
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
))
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
))
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
)
1823 pub fn mk_ptr(self, tm
: TypeAndMut
<'tcx
>) -> Ty
<'tcx
> {
1824 self.mk_ty(RawPtr(tm
))
1828 pub fn mk_ref(self, r
: Region
<'tcx
>, tm
: TypeAndMut
<'tcx
>) -> Ty
<'tcx
> {
1829 self.mk_ty(Ref(r
, tm
.ty
, tm
.mutbl
))
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 }
)
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 }
)
1843 pub fn mk_mut_ptr(self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
1844 self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut }
)
1848 pub fn mk_imm_ptr(self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
1849 self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not }
)
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
)))
1858 pub fn mk_slice(self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
1859 self.mk_ty(Slice(ty
))
1863 pub fn intern_tup(self, ts
: &[Ty
<'tcx
>]) -> Ty
<'tcx
> {
1864 self.mk_ty(Tuple(self.intern_type_list(&ts
)))
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
))))
1872 pub fn mk_unit(self) -> Ty
<'tcx
> {
1877 pub fn mk_diverging_default(self) -> Ty
<'tcx
> {
1878 if self.features().never_type_fallback { self.types.never }
else { self.types.unit }
1885 substs
: impl IntoIterator
<Item
= impl Into
<GenericArg
<'tcx
>>>,
1887 let substs
= self.check_substs(def_id
, substs
);
1888 self.mk_ty(FnDef(def_id
, substs
))
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)]
1900 let n
= self.generics_of(_def_id
).count();
1904 "wrong number of generic parameters for {_def_id:?}: {:?}",
1905 substs
.collect
::<Vec
<_
>>(),
1908 self.mk_substs(substs
)
1912 pub fn mk_fn_ptr(self, fty
: PolyFnSig
<'tcx
>) -> Ty
<'tcx
> {
1913 self.mk_ty(FnPtr(fty
))
1919 obj
: &'tcx List
<PolyExistentialPredicate
<'tcx
>>,
1920 reg
: ty
::Region
<'tcx
>,
1923 self.mk_ty(Dynamic(obj
, reg
, repr
))
1927 pub fn mk_projection(
1930 substs
: impl IntoIterator
<Item
= impl Into
<GenericArg
<'tcx
>>>,
1932 self.mk_ty(Alias(ty
::Projection
, self.mk_alias_ty(item_def_id
, substs
)))
1936 pub fn mk_closure(self, closure_id
: DefId
, closure_substs
: SubstsRef
<'tcx
>) -> Ty
<'tcx
> {
1937 self.mk_ty(Closure(closure_id
, closure_substs
))
1941 pub fn mk_generator(
1944 generator_substs
: SubstsRef
<'tcx
>,
1945 movability
: hir
::Movability
,
1947 self.mk_ty(Generator(id
, generator_substs
, movability
))
1951 pub fn mk_generator_witness(self, types
: ty
::Binder
<'tcx
, &'tcx List
<Ty
<'tcx
>>>) -> Ty
<'tcx
> {
1952 self.mk_ty(GeneratorWitness(types
))
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
)
1965 pub fn mk_ty_var(self, v
: TyVid
) -> Ty
<'tcx
> {
1966 self.mk_ty_infer(TyVar(v
))
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 }
)
1975 pub fn mk_int_var(self, v
: IntVid
) -> Ty
<'tcx
> {
1976 self.mk_ty_infer(IntVar(v
))
1980 pub fn mk_float_var(self, v
: FloatVid
) -> Ty
<'tcx
> {
1981 self.mk_ty_infer(FloatVar(v
))
1985 pub fn mk_ty_infer(self, it
: InferTy
) -> Ty
<'tcx
> {
1986 self.mk_ty(Infer(it
))
1990 pub fn mk_ty_param(self, index
: u32, name
: Symbol
) -> Ty
<'tcx
> {
1991 self.mk_ty(Param(ParamTy { index, name }
))
1994 pub fn mk_param_from_def(self, param
: &ty
::GenericParamDef
) -> GenericArg
<'tcx
> {
1996 GenericParamDefKind
::Lifetime
=> {
1997 self.mk_region(ty
::ReEarlyBound(param
.to_early_bound_region_data())).into()
1999 GenericParamDefKind
::Type { .. }
=> self.mk_ty_param(param
.index
, param
.name
).into(),
2000 GenericParamDefKind
::Const { .. }
=> self
2002 ParamConst { index: param.index, name: param.name }
,
2003 self.type_of(param
.def_id
),
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
)))
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
))
2018 pub fn mk_place_deref(self, place
: Place
<'tcx
>) -> Place
<'tcx
> {
2019 self.mk_place_elem(place
, PlaceElem
::Deref
)
2022 pub fn mk_place_downcast(
2025 adt_def
: AdtDef
<'tcx
>,
2026 variant_index
: VariantIdx
,
2030 PlaceElem
::Downcast(Some(adt_def
.variant(variant_index
).name
), variant_index
),
2034 pub fn mk_place_downcast_unnamed(
2037 variant_index
: VariantIdx
,
2039 self.mk_place_elem(place
, PlaceElem
::Downcast(None
, variant_index
))
2042 pub fn mk_place_index(self, place
: Place
<'tcx
>, index
: Local
) -> Place
<'tcx
> {
2043 self.mk_place_elem(place
, PlaceElem
::Index(index
))
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
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
);
2053 Place { local: place.local, projection: self.intern_place_elems(&projection) }
2056 pub fn intern_poly_existential_predicates(
2058 eps
: &[PolyExistentialPredicate
<'tcx
>],
2059 ) -> &'tcx List
<PolyExistentialPredicate
<'tcx
>> {
2060 assert
!(!eps
.is_empty());
2063 .all(|[a
, b
]| a
.skip_binder().stable_cmp(self, &b
.skip_binder())
2064 != Ordering
::Greater
)
2066 self._intern_poly_existential_predicates(eps
)
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
2073 if preds
.is_empty() {
2074 // The macro-generated method below asserts we don't intern an empty slice.
2077 self._intern_predicates(preds
)
2081 pub fn mk_const_list
<I
: InternAs
<ty
::Const
<'tcx
>, &'tcx List
<ty
::Const
<'tcx
>>>>(
2085 iter
.intern_with(|xs
| self.intern_const_list(xs
))
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) }
2092 pub fn intern_type_list(self, ts
: &[Ty
<'tcx
>]) -> &'tcx List
<Ty
<'tcx
>> {
2096 // Actually intern type lists as lists of `GenericArg`s.
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
2103 let substs
= self._intern_substs(ty
::subst
::ty_slice_as_generic_args(ts
));
2104 substs
.try_as_type_list().unwrap()
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) }
2112 pub fn intern_projs(self, ps
: &[ProjectionKind
]) -> &'tcx List
<ProjectionKind
> {
2113 if ps
.is_empty() { List::empty() }
else { self._intern_projs(ps) }
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) }
2120 pub fn intern_canonical_var_infos(
2122 ts
: &[CanonicalVarInfo
<'tcx
>],
2123 ) -> CanonicalVarInfos
<'tcx
> {
2124 if ts
.is_empty() { List::empty() }
else { self._intern_canonical_var_infos(ts) }
2127 pub fn intern_bound_variable_kinds(
2129 ts
: &[ty
::BoundVariableKind
],
2130 ) -> &'tcx List
<ty
::BoundVariableKind
> {
2131 if ts
.is_empty() { List::empty() }
else { self._intern_bound_variable_kinds(ts) }
2134 pub fn mk_fn_sig
<I
>(
2139 unsafety
: hir
::Unsafety
,
2141 ) -> <I
::Item
as InternIteratorElement
<Ty
<'tcx
>, ty
::FnSig
<'tcx
>>>::Output
2143 I
: Iterator
<Item
: InternIteratorElement
<Ty
<'tcx
>, ty
::FnSig
<'tcx
>>>,
2145 inputs
.chain(iter
::once(output
)).intern_with(|xs
| ty
::FnSig
{
2146 inputs_and_output
: self.intern_type_list(xs
),
2153 pub fn mk_poly_existential_predicates
<
2154 I
: InternAs
<PolyExistentialPredicate
<'tcx
>, &'tcx List
<PolyExistentialPredicate
<'tcx
>>>,
2159 iter
.intern_with(|xs
| self.intern_poly_existential_predicates(xs
))
2162 pub fn mk_predicates
<I
: InternAs
<Predicate
<'tcx
>, &'tcx List
<Predicate
<'tcx
>>>>(
2166 iter
.intern_with(|xs
| self.intern_predicates(xs
))
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
))
2173 pub fn mk_substs
<I
: InternAs
<GenericArg
<'tcx
>, &'tcx List
<GenericArg
<'tcx
>>>>(
2177 iter
.intern_with(|xs
| self.intern_substs(xs
))
2180 pub fn mk_place_elems
<I
: InternAs
<PlaceElem
<'tcx
>, &'tcx List
<PlaceElem
<'tcx
>>>>(
2184 iter
.intern_with(|xs
| self.intern_place_elems(xs
))
2187 pub fn mk_substs_trait(
2190 rest
: impl IntoIterator
<Item
= GenericArg
<'tcx
>>,
2191 ) -> SubstsRef
<'tcx
> {
2192 self.mk_substs(iter
::once(self_ty
.into()).chain(rest
))
2195 pub fn mk_trait_ref(
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: () }
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: () }
2213 pub fn mk_bound_variable_kinds
<
2214 I
: InternAs
<ty
::BoundVariableKind
, &'tcx List
<ty
::BoundVariableKind
>>,
2219 iter
.intern_with(|xs
| self.intern_bound_variable_kinds(xs
))
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(
2226 lint
: &'
static Lint
,
2228 span
: impl Into
<MultiSpan
>,
2229 decorator
: impl for<'a
> DecorateLint
<'a
, ()>,
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
)
2238 /// Emit a lint at the appropriate level for a hir node, with an associated span.
2240 /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
2242 /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
2243 #[rustc_lint_diagnostics]
2244 pub fn struct_span_lint_hir(
2246 lint
: &'
static Lint
,
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
, ()>,
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
);
2258 /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
2259 /// generated by `#[derive(LintDiagnostic)]`).
2262 lint
: &'
static Lint
,
2264 decorator
: impl for<'a
> DecorateLint
<'a
, ()>,
2266 self.struct_lint_node(lint
, id
, decorator
.msg(), |diag
| decorator
.decorate_lint(diag
))
2269 /// Emit a lint at the appropriate level for a hir node.
2271 /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
2273 /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
2274 #[rustc_lint_diagnostics]
2275 pub fn struct_lint_node(
2277 lint
: &'
static Lint
,
2279 msg
: impl Into
<DiagnosticMessage
>,
2280 decorate
: impl for<'a
, 'b
> FnOnce(
2281 &'b
mut DiagnosticBuilder
<'a
, ()>,
2282 ) -> &'b
mut DiagnosticBuilder
<'a
, ()>,
2284 let (level
, src
) = self.lint_level_at_node(lint
, id
);
2285 struct_lint_level(self.sess
, lint
, level
, src
, None
, msg
, decorate
);
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
)?
;
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())
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
)
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
)
2317 /// Whether the `def_id` counts as const fn in the current crate, considering all active
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.
2326 .declared_lib_features
2328 .any(|&(sym
, _
)| sym
== stability
.feature
)
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
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
);
2348 hir
::Node
::Item(hir
::Item
{
2349 kind
: hir
::ItemKind
::Impl(hir
::Impl { constness: hir::Constness::Const, .. }
),
2356 impl<'tcx
> TyCtxtAt
<'tcx
> {
2357 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
2359 pub fn ty_error(self) -> Ty
<'tcx
> {
2360 self.tcx
.ty_error_with_message(self.span
, "TyKind::Error constructed but no error reported")
2363 /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
2364 /// ensure it gets used.
2366 pub fn ty_error_with_message(self, msg
: &str) -> Ty
<'tcx
> {
2367 self.tcx
.ty_error_with_message(self.span
, msg
)
2370 pub fn mk_trait_ref(
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
)
2380 /// Parameter attributes that can only be determined by examining the body of a function instead
2381 /// of just its signature.
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.
2386 /// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
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
,
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 ()
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())
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
)
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
)
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())
2427 providers
.source_span
=
2428 |tcx
, def_id
| tcx
.untracked
.source_span
.get(def_id
).copied().unwrap_or(DUMMY_SP
);