context.rs 108.9 KB
Newer Older
A
Alexander Regueiro 已提交
1
//! Type context book-keeping.
2

3
use crate::arena::Arena;
C
Camille GILLOT 已提交
4
use crate::dep_graph::{DepGraph, DepKind, DepKindStruct};
5
use crate::hir::place::Place as HirPlace;
M
Mark Mansi 已提交
6
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
P
pierwill 已提交
7
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
8
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath};
M
Mark Mansi 已提交
9
use crate::middle::stability;
10
use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
11 12 13
use crate::mir::{
    Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
};
14
use crate::thir::Thir;
M
Mark Mansi 已提交
15
use crate::traits;
16
use crate::ty::query::{self, TyCtxtAt};
17
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
M
Mark Rousskov 已提交
18
use crate::ty::TyKind::*;
19
use crate::ty::{
20
    self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
N
Nicholas Nethercote 已提交
21 22 23 24
    ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy,
    FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List,
    ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region,
    RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
25
};
U
Ujjwal Sharma 已提交
26
use rustc_ast as ast;
27
use rustc_data_structures::fingerprint::Fingerprint;
28
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
29
use rustc_data_structures::intern::{Interned, WithStableHash};
30
use rustc_data_structures::memmap::Mmap;
31
use rustc_data_structures::profiling::SelfProfilerRef;
32
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
C
Camille GILLOT 已提交
33
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
34
use rustc_data_structures::steal::Steal;
35
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
36
use rustc_data_structures::vec_map::VecMap;
D
David Wood 已提交
37
use rustc_errors::{ErrorGuaranteed, MultiSpan};
M
Mazdak Farrokhzad 已提交
38 39
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
40
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
41
use rustc_hir::intravisit::Visitor;
42
use rustc_hir::lang_items::LangItem;
43
use rustc_hir::{
44 45
    Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
    Node, TraitCandidate, TraitItemKind,
46
};
47
use rustc_index::vec::{Idx, IndexVec};
M
Mark Rousskov 已提交
48
use rustc_macros::HashStable;
R
Roxane 已提交
49
use rustc_middle::mir::FakeReadCause;
C
Camille GILLOT 已提交
50
use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext};
51
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
52
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
53
use rustc_session::lint::{Level, Lint};
54
use rustc_session::Limit;
M
Mazdak Farrokhzad 已提交
55
use rustc_session::Session;
56
use rustc_span::def_id::{DefPathHash, StableCrateId};
D
David Wood 已提交
57
use rustc_span::source_map::SourceMap;
58
use rustc_span::symbol::{kw, sym, Ident, Symbol};
59
use rustc_span::{Span, DUMMY_SP};
60
use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
M
Mark Rousskov 已提交
61
use rustc_target::spec::abi;
M
Mazdak Farrokhzad 已提交
62

63
use rustc_type_ir::TypeFlags;
M
Mark Rousskov 已提交
64
use smallvec::SmallVec;
65
use std::any::Any;
66
use std::borrow::Borrow;
67
use std::cmp::Ordering;
68
use std::collections::hash_map::{self, Entry};
N
Niko Matsakis 已提交
69
use std::fmt;
M
Mark Rousskov 已提交
70
use std::hash::{Hash, Hasher};
71
use std::iter;
M
Mark Rousskov 已提交
72 73
use std::mem;
use std::ops::{Bound, Deref};
A
Alex Crichton 已提交
74
use std::sync::Arc;
75

C
Camille GILLOT 已提交
76
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
77
    /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
78
    fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
79 80 81 82 83 84 85
    where
        Self: Sized;

    fn new_empty(source_map: &'tcx SourceMap) -> Self
    where
        Self: Sized;

86 87
    fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);

88 89 90
    fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult;
}

91 92
/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
M
mark 已提交
93 94
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[derive(TyEncodable, TyDecodable, HashStable)]
95 96 97 98
pub struct DelaySpanBugEmitted {
    pub reported: ErrorGuaranteed,
    _priv: (),
}
M
mark 已提交
99

100
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
101

102
pub struct CtxtInterners<'tcx> {
103
    /// The arena that types, regions, etc. are allocated from.
J
John Kåre Alsaker 已提交
104
    arena: &'tcx WorkerLocal<Arena<'tcx>>,
105

106 107
    // Specifically use a speedy hash algorithm for these hash sets, since
    // they're accessed quite often.
108
    type_: InternedSet<'tcx, WithStableHash<TyS<'tcx>>>,
C
csmoe 已提交
109
    substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
V
varkor 已提交
110
    canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
111
    region: InternedSet<'tcx, RegionKind>,
J
Jack Huey 已提交
112 113
    poly_existential_predicates:
        InternedSet<'tcx, List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>>,
114
    predicate: InternedSet<'tcx, PredicateS<'tcx>>,
V
varkor 已提交
115
    predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
116
    projs: InternedSet<'tcx, List<ProjectionKind>>,
117
    place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
N
Nicholas Nethercote 已提交
118
    const_: InternedSet<'tcx, ConstS<'tcx>>,
119
    const_allocation: InternedSet<'tcx, Allocation>,
J
Jack Huey 已提交
120
    bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
121
    layout: InternedSet<'tcx, LayoutS<'tcx>>,
122
    adt_def: InternedSet<'tcx, AdtDefData>,
123 124
}

125
impl<'tcx> CtxtInterners<'tcx> {
J
John Kåre Alsaker 已提交
126
    fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
127
        CtxtInterners {
128 129 130 131
            arena,
            type_: Default::default(),
            substs: Default::default(),
            region: Default::default(),
J
Jack Huey 已提交
132
            poly_existential_predicates: Default::default(),
133
            canonical_var_infos: Default::default(),
134
            predicate: Default::default(),
135
            predicates: Default::default(),
136
            projs: Default::default(),
137
            place_elems: Default::default(),
O
Oliver Scherer 已提交
138
            const_: Default::default(),
139
            const_allocation: Default::default(),
J
Jack Huey 已提交
140
            bound_variable_kinds: Default::default(),
141
            layout: Default::default(),
A
Aaron Hill 已提交
142
            adt_def: Default::default(),
143 144 145
        }
    }

146
    /// Interns a type.
M
Mark Rousskov 已提交
147
    #[allow(rustc::usage_of_ty_tykind)]
148
    #[inline(never)]
149 150 151 152 153 154
    fn intern_ty(
        &self,
        kind: TyKind<'tcx>,
        sess: &Session,
        resolutions: &ty::ResolverOutputs,
    ) -> Ty<'tcx> {
N
Nicholas Nethercote 已提交
155 156 157 158 159
        Ty(Interned::new_unchecked(
            self.type_
                .intern(kind, |kind| {
                    let flags = super::flags::FlagComputation::for_kind(&kind);

160 161 162 163 164
                    // It's impossible to hash inference regions (and will ICE), so we don't need to try to cache them.
                    // Without incremental, we rarely stable-hash types, so let's not do it proactively.
                    let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER)
                        || sess.opts.incremental.is_none()
                    {
165 166 167
                        Fingerprint::ZERO
                    } else {
                        let mut hasher = StableHasher::new();
168
                        let mut hcx = StableHashingContext::ignore_spans(
169 170 171 172
                            sess,
                            &resolutions.definitions,
                            &*resolutions.cstore,
                        );
173
                        kind.hash_stable(&mut hcx, &mut hasher);
174 175 176
                        hasher.finish()
                    };

N
Nicholas Nethercote 已提交
177 178 179 180 181
                    let ty_struct = TyS {
                        kind,
                        flags: flags.flags,
                        outer_exclusive_binder: flags.outer_exclusive_binder,
                    };
182

183 184 185
                    InternedInSet(
                        self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }),
                    )
N
Nicholas Nethercote 已提交
186 187 188
                })
                .0,
        ))
189
    }
190 191

    #[inline(never)]
192 193 194 195 196
    fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
        Predicate(Interned::new_unchecked(
            self.predicate
                .intern(kind, |kind| {
                    let flags = super::flags::FlagComputation::for_predicate(kind);
197

198 199 200 201 202 203 204 205 206 207
                    let predicate_struct = PredicateS {
                        kind,
                        flags: flags.flags,
                        outer_exclusive_binder: flags.outer_exclusive_binder,
                    };

                    InternedInSet(self.arena.alloc(predicate_struct))
                })
                .0,
        ))
208
    }
209 210
}

211
pub struct CommonTypes<'tcx> {
212
    pub unit: Ty<'tcx>,
213 214 215 216 217 218 219
    pub bool: Ty<'tcx>,
    pub char: Ty<'tcx>,
    pub isize: Ty<'tcx>,
    pub i8: Ty<'tcx>,
    pub i16: Ty<'tcx>,
    pub i32: Ty<'tcx>,
    pub i64: Ty<'tcx>,
220
    pub i128: Ty<'tcx>,
221 222 223 224 225
    pub usize: Ty<'tcx>,
    pub u8: Ty<'tcx>,
    pub u16: Ty<'tcx>,
    pub u32: Ty<'tcx>,
    pub u64: Ty<'tcx>,
226
    pub u128: Ty<'tcx>,
227 228
    pub f32: Ty<'tcx>,
    pub f64: Ty<'tcx>,
B
Bastian Kauschke 已提交
229
    pub str_: Ty<'tcx>,
A
Andrew Cann 已提交
230
    pub never: Ty<'tcx>,
231
    pub self_param: Ty<'tcx>,
232

233 234 235 236
    /// Dummy type used for the `Self` of a `TraitRef` created for converting
    /// a trait object, and which gets removed in `ExistentialTraitRef`.
    /// This type must not appear anywhere in other converted types.
    pub trait_object_dummy_self: Ty<'tcx>,
237
}
238

239
pub struct CommonLifetimes<'tcx> {
N
Niko Matsakis 已提交
240
    /// `ReEmpty` in the root universe.
N
Niko Matsakis 已提交
241 242
    pub re_root_empty: Region<'tcx>,

N
Niko Matsakis 已提交
243
    /// `ReStatic`
N
Niko Matsakis 已提交
244
    pub re_static: Region<'tcx>,
N
Niko Matsakis 已提交
245

246
    /// Erased region, used outside of type inference.
N
Niko Matsakis 已提交
247
    pub re_erased: Region<'tcx>,
V
varkor 已提交
248
}
V
varkor 已提交
249

V
varkor 已提交
250
pub struct CommonConsts<'tcx> {
N
Nicholas Nethercote 已提交
251
    pub unit: Const<'tcx>,
252 253
}

254
pub struct LocalTableInContext<'a, V> {
255
    hir_owner: LocalDefId,
M
Mark Rousskov 已提交
256
    data: &'a ItemLocalMap<V>,
257 258 259
}

/// Validate that the given HirId (respectively its `local_id` part) can be
260
/// safely used as a key in the maps of a TypeckResults. For that to be
261
/// the case, the HirId must have the same `owner` as all the other IDs in
262
/// this table (signified by `hir_owner`). Otherwise the HirId
263 264 265
/// would be in a different frame of reference and using its `local_id`
/// would result in lookup errors, or worse, in silently wrong data being
/// stored/returned.
266
#[inline]
267
fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) {
268
    if hir_id.owner != hir_owner {
269
        invalid_hir_id_for_typeck_results(hir_owner, hir_id);
270 271 272
    }
}

273 274 275 276 277 278 279 280 281 282 283 284 285
#[cold]
#[inline(never)]
fn invalid_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) {
    ty::tls::with(|tcx| {
        bug!(
            "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
            tcx.hir().node_to_string(hir_id),
            hir_id.owner,
            hir_owner
        )
    });
}

286 287
impl<'a, V> LocalTableInContext<'a, V> {
    pub fn contains_key(&self, id: hir::HirId) -> bool {
288
        validate_hir_id_for_typeck_results(self.hir_owner, id);
289 290 291 292
        self.data.contains_key(&id.local_id)
    }

    pub fn get(&self, id: hir::HirId) -> Option<&V> {
293
        validate_hir_id_for_typeck_results(self.hir_owner, id);
294 295 296
        self.data.get(&id.local_id)
    }

297
    pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
298 299 300 301 302 303 304 305 306 307 308 309
        self.data.iter()
    }
}

impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
    type Output = V;

    fn index(&self, key: hir::HirId) -> &V {
        self.get(key).expect("LocalTableInContext: key not found")
    }
}

310
pub struct LocalTableInContextMut<'a, V> {
311
    hir_owner: LocalDefId,
M
Mark Rousskov 已提交
312
    data: &'a mut ItemLocalMap<V>,
313 314 315 316
}

impl<'a, V> LocalTableInContextMut<'a, V> {
    pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
317
        validate_hir_id_for_typeck_results(self.hir_owner, id);
318 319 320
        self.data.get_mut(&id.local_id)
    }

321
    pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
322
        validate_hir_id_for_typeck_results(self.hir_owner, id);
323 324 325 326
        self.data.entry(id.local_id)
    }

    pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
327
        validate_hir_id_for_typeck_results(self.hir_owner, id);
328 329 330 331
        self.data.insert(id.local_id, val)
    }

    pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
332
        validate_hir_id_for_typeck_results(self.hir_owner, id);
333 334 335 336
        self.data.remove(&id.local_id)
    }
}

337 338 339 340 341 342 343 344 345 346
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
/// captured types that can be useful for diagnostics. In particular, it stores the span that
/// caused a given type to be recorded, along with the scope that enclosed the value (which can
/// be used to find the await that the value is live across).
///
/// For example:
///
/// ```ignore (pseudo-Rust)
/// async move {
347
///     let x: T = expr;
348 349 350 351 352
///     foo.await
///     ...
/// }
/// ```
///
353 354
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
M
Matthew Jasper 已提交
355
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
J
Jack Huey 已提交
356
#[derive(TypeFoldable)]
357 358 359 360 361 362 363
pub struct GeneratorInteriorTypeCause<'tcx> {
    /// Type of the captured binding.
    pub ty: Ty<'tcx>,
    /// Span of the binding that was captured.
    pub span: Span,
    /// Span of the scope of the captured binding.
    pub scope_span: Option<Span>,
C
csmoe 已提交
364 365
    /// Span of `.await` or `yield` expression.
    pub yield_span: Span,
366 367
    /// Expr which the type evaluated from.
    pub expr: Option<hir::HirId>,
368 369
}

M
Matthew Jasper 已提交
370
#[derive(TyEncodable, TyDecodable, Debug)]
371
pub struct TypeckResults<'tcx> {
372
    /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
373
    pub hir_owner: LocalDefId,
374

375 376
    /// Resolved definitions for `<T>::X` associated paths and
    /// method calls, including those of overloaded operators.
M
mark 已提交
377
    type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
378

379 380 381 382 383 384
    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
    /// about the field you also need definition of the variant to which the field
    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
    field_indices: ItemLocalMap<usize>,

A
Alexander Regueiro 已提交
385
    /// Stores the types for various nodes in the AST. Note that this table
386
    /// is not guaranteed to be populated outside inference. See
387
    /// typeck::check::fn_ctxt for details.
388
    node_types: ItemLocalMap<Ty<'tcx>>,
389 390

    /// Stores the type parameters which were substituted to obtain the type
A
Alexander Regueiro 已提交
391
    /// of this node. This only applies to nodes that refer to entities
392 393
    /// parameterized by type parameters, such as generic fns, types, or
    /// other items.
C
csmoe 已提交
394
    node_substs: ItemLocalMap<SubstsRef<'tcx>>,
395

D
David Wood 已提交
396 397 398 399 400 401 402 403 404
    /// This will either store the canonicalized types provided by the user
    /// or the substitutions that the user explicitly gave (if any) attached
    /// to `id`. These will not include any inferred values. The canonical form
    /// is used to capture things like `_` or other unspecified values.
    ///
    /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
    /// canonical substitutions would include only `for<X> { Vec<X> }`.
    ///
    /// See also `AscribeUserType` statement in MIR.
405
    user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
406 407 408

    /// Stores the canonicalized types provided by the user. See also
    /// `AscribeUserType` statement in MIR.
409
    pub user_provided_sigs: DefIdMap<CanonicalPolyFnSig<'tcx>>,
410

411
    adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
412

413
    /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
414
    pat_binding_modes: ItemLocalMap<BindingMode>,
415

416
    /// Stores the types which were implicitly dereferenced in pattern binding modes
417
    /// for later usage in THIR lowering. For example,
418 419 420 421 422 423 424 425 426 427
    ///
    /// ```
    /// match &&Some(5i32) {
    ///     Some(n) => {},
    ///     _ => {},
    /// }
    /// ```
    /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
    ///
    /// See:
G
Guillaume Gomez 已提交
428
    /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
429 430
    pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,

431 432
    /// Records the reasons that we picked the kind of each closure;
    /// not all closures are present in the map.
433
    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
J
John Kåre Alsaker 已提交
434

435 436 437
    /// For each fn, records the "liberated" types of its arguments
    /// and return type. Liberated means that all bound regions
    /// (including late-bound regions) are replaced with free
I
Irina Popa 已提交
438
    /// equivalents. This table is not used in codegen (since regions
439
    /// are erased there) and hence is not serialized to metadata.
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
    ///
    /// This table also contains the "revealed" values for any `impl Trait`
    /// that appear in the signature and whose values are being inferred
    /// by this function.
    ///
    /// # Example
    ///
    /// ```rust
    /// fn foo(x: &u32) -> impl Debug { *x }
    /// ```
    ///
    /// The function signature here would be:
    ///
    /// ```
    /// for<'a> fn(&'a u32) -> Foo
    /// ```
    ///
    /// where `Foo` is an opaque type created for this function.
    ///
    ///
    /// The *liberated* form of this would be
    ///
    /// ```
    /// fn(&'a u32) -> u32
    /// ```
    ///
    /// Note that `'a` is not bound (it would be an `ReFree`) and
    /// that the `Foo` opaque type is replaced by its hidden type.
468
    liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
469 470 471 472 473

    /// For each FRU expression, record the normalized types of the fields
    /// of the struct - this is needed because it is non-trivial to
    /// normalize while preserving regions. This table is used only in
    /// MIR construction and hence is not serialized to metadata.
474
    fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
475

S
Saleem Jaffer 已提交
476 477 478
    /// For every coercion cast we add the HIR node ID of the cast
    /// expression to this set.
    coercion_casts: ItemLocalSet,
479

480
    /// Set of trait imports actually used in the method resolution.
C
cjkenn 已提交
481
    /// This is used for warning unused imports. During type
482
    /// checking, this `Lrc` should not be cloned: it must have a ref-count
C
cjkenn 已提交
483
    /// of 1 so that we can insert things into the set mutably.
484
    pub used_trait_imports: Lrc<FxHashSet<LocalDefId>>,
485 486

    /// If any errors occurred while type-checking this body,
M
mark 已提交
487 488
    /// this field will be set to `Some(ErrorGuaranteed)`.
    pub tainted_by_errors: Option<ErrorGuaranteed>,
489

490 491 492 493 494 495 496
    /// All the opaque types that have hidden types set
    /// by this function. For return-position-impl-trait we also store the
    /// type here, so that mir-borrowck can figure out hidden types,
    /// even if they are only set in dead code (which doesn't show up in MIR).
    /// For type-alias-impl-trait, this map is only used to prevent query cycles,
    /// so the hidden types are all `None`.
    pub concrete_opaque_types: VecMap<DefId, Option<Ty<'tcx>>>,
B
Blitzerr 已提交
497

A
Aman Arora 已提交
498 499
    /// Tracks the minimum captures required for a closure;
    /// see `MinCaptureInformationMap` for more details.
500
    pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
501

R
Roxane 已提交
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
    /// Tracks the fake reads required for a closure and the reason for the fake read.
    /// When performing pattern matching for closures, there are times we don't end up
    /// reading places that are mentioned in a closure (because of _ patterns). However,
    /// to ensure the places are initialized, we introduce fake reads.
    /// Consider these two examples:
    /// ``` (discriminant matching with only wildcard arm)
    /// let x: u8;
    /// let c = || match x { _ => () };
    /// ```
    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
    /// want to capture it. However, we do still want an error here, because `x` should have
    /// to be initialized at the point where c is created. Therefore, we add a "fake read"
    /// instead.
    /// ``` (destructured assignments)
    /// let c = || {
    ///     let (t1, t2) = t;
    /// }
    /// ```
    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
    /// we never capture `t`. This becomes an issue when we build MIR as we require
    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
    /// issue by fake reading `t`.
    pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
R
Roxane 已提交
525

C
csmoe 已提交
526
    /// Stores the type, expression, span and optional scope span of all types
527
    /// that are live across the yield of this generator (if a generator).
J
Jack Huey 已提交
528
    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
529 530 531 532 533 534

    /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
    /// as `&[u8]`, depending on the pattern  in which they are used.
    /// This hashset records all instances where we behave
    /// like this to allow `const_to_pat` to reliably handle this situation.
    pub treat_byte_string_as_slice: ItemLocalSet,
535 536 537 538

    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
    /// on closure size.
    pub closure_size_eval: FxHashMap<DefId, ClosureSizeProfileData<'tcx>>,
539 540
}

541 542 543
impl<'tcx> TypeckResults<'tcx> {
    pub fn new(hir_owner: LocalDefId) -> TypeckResults<'tcx> {
        TypeckResults {
544
            hir_owner,
545 546
            type_dependent_defs: Default::default(),
            field_indices: Default::default(),
D
David Wood 已提交
547
            user_provided_types: Default::default(),
548
            user_provided_sigs: Default::default(),
549 550 551 552 553 554 555 556
            node_types: Default::default(),
            node_substs: Default::default(),
            adjustments: Default::default(),
            pat_binding_modes: Default::default(),
            pat_adjustments: Default::default(),
            closure_kind_origins: Default::default(),
            liberated_fn_sigs: Default::default(),
            fru_field_types: Default::default(),
S
Saleem Jaffer 已提交
557
            coercion_casts: Default::default(),
558
            used_trait_imports: Lrc::new(Default::default()),
559
            tainted_by_errors: None,
V
varkor 已提交
560
            concrete_opaque_types: Default::default(),
561
            closure_min_captures: Default::default(),
R
Roxane 已提交
562
            closure_fake_reads: Default::default(),
J
Jack Huey 已提交
563
            generator_interior_types: ty::Binder::dummy(Default::default()),
564
            treat_byte_string_as_slice: Default::default(),
565
            closure_size_eval: Default::default(),
566 567
        }
    }
568

569
    /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
C
Camille GILLOT 已提交
570
    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
571
        match *qpath {
572
            hir::QPath::Resolved(_, ref path) => path.res,
D
David Wood 已提交
573
            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
M
Mark Rousskov 已提交
574
                .type_dependent_def(id)
575
                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
576 577 578
        }
    }

579 580
    pub fn type_dependent_defs(
        &self,
M
mark 已提交
581
    ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
582
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
583 584
    }

585
    pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
586
        validate_hir_id_for_typeck_results(self.hir_owner, id);
587
        self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
588 589 590
    }

    pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
591
        self.type_dependent_def(id).map(|(_, def_id)| def_id)
592 593
    }

594 595
    pub fn type_dependent_defs_mut(
        &mut self,
M
mark 已提交
596
    ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
597
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
598 599
    }

600
    pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
601
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
602 603
    }

604
    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
605
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
606 607
    }

M
Mark Rousskov 已提交
608
    pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
609
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
610 611
    }

D
David Wood 已提交
612
    pub fn user_provided_types_mut(
M
Mark Rousskov 已提交
613
        &mut self,
614
    ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
615
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
616 617
    }

618
    pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
619
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
620 621
    }

622
    pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
623
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
624 625
    }

L
ljedrz 已提交
626
    pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
M
Mark Rousskov 已提交
627 628 629
        self.node_type_opt(id).unwrap_or_else(|| {
            bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
        })
630 631
    }

L
ljedrz 已提交
632
    pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
633
        validate_hir_id_for_typeck_results(self.hir_owner, id);
634
        self.node_types.get(&id.local_id).cloned()
635 636
    }

C
csmoe 已提交
637
    pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
638
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
639 640
    }

C
csmoe 已提交
641
    pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
642
        validate_hir_id_for_typeck_results(self.hir_owner, id);
C
csmoe 已提交
643
        self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
644 645
    }

C
csmoe 已提交
646
    pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
647
        validate_hir_id_for_typeck_results(self.hir_owner, id);
648
        self.node_substs.get(&id.local_id).cloned()
649 650 651 652
    }

    // Returns the type of a pattern as a monotype. Like @expr_ty, this function
    // doesn't provide type parameter substitutions.
C
Camille GILLOT 已提交
653
    pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
L
ljedrz 已提交
654
        self.node_type(pat.hir_id)
655 656 657 658 659
    }

    // Returns the type of an expression as a monotype.
    //
    // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
660
    // some cases, we insert `Adjustment` annotations such as auto-deref or
661 662 663
    // auto-ref.  The type returned by this function does not consider such
    // adjustments.  See `expr_ty_adjusted()` instead.
    //
664
    // NB (2): This type doesn't provide type parameter substitutions; e.g., if you
665 666
    // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
    // instead of "fn(ty) -> T with T = isize".
C
Camille GILLOT 已提交
667
    pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
L
ljedrz 已提交
668
        self.node_type(expr.hir_id)
669 670
    }

C
Camille GILLOT 已提交
671
    pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
L
ljedrz 已提交
672
        self.node_type_opt(expr.hir_id)
673 674
    }

675
    pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
676
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
677 678
    }

M
Mark Rousskov 已提交
679 680 681
    pub fn adjustments_mut(
        &mut self,
    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
682
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
683 684
    }

C
Camille GILLOT 已提交
685
    pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
686
        validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
687
        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
688 689
    }

690 691
    /// Returns the type of `expr`, considering any `Adjustment`
    /// entry recorded for that expression.
C
Camille GILLOT 已提交
692
    pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
M
Mark Rousskov 已提交
693
        self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
694 695
    }

C
Camille GILLOT 已提交
696
    pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
M
Mark Rousskov 已提交
697
        self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
698
    }
699

C
Camille GILLOT 已提交
700
    pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
701 702
        // Only paths and method calls/overloaded operators have
        // entries in type_dependent_defs, ignore the former here.
V
varkor 已提交
703
        if let hir::ExprKind::Path(_) = expr.kind {
704 705
            return false;
        }
706

707
        matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
708 709
    }

710 711 712 713 714 715 716
    pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
        self.pat_binding_modes().get(id).copied().or_else(|| {
            s.delay_span_bug(sp, "missing binding mode");
            None
        })
    }

717
    pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
718
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
719 720
    }

M
Mark Rousskov 已提交
721
    pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
722
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
723 724
    }

725
    pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
726
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
727 728
    }

M
Mark Rousskov 已提交
729
    pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
730
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
731 732
    }

733 734 735 736 737 738 739 740 741 742 743 744 745
    /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
    /// by the closure.
    pub fn closure_min_captures_flattened(
        &self,
        closure_def_id: DefId,
    ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
        self.closure_min_captures
            .get(&closure_def_id)
            .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
            .into_iter()
            .flatten()
    }

746
    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
747
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
748 749
    }

750 751 752
    pub fn closure_kind_origins_mut(
        &mut self,
    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
753
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
754 755
    }

756
    pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
757
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
758
    }
759

760
    pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
761
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
762 763
    }

764
    pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
765
        LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
766 767
    }

768
    pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
769
        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
770 771
    }

S
Saleem Jaffer 已提交
772
    pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
773
        validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
S
Saleem Jaffer 已提交
774
        self.coercion_casts.contains(&hir_id.local_id)
775 776
    }

S
Saleem Jaffer 已提交
777 778 779 780 781 782
    pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
        self.coercion_casts.insert(id);
    }

    pub fn coercion_casts(&self) -> &ItemLocalSet {
        &self.coercion_casts
783 784 785
    }
}

786
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
787
    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
788
        let ty::TypeckResults {
A
Aman Arora 已提交
789
            hir_owner,
790
            ref type_dependent_defs,
791
            ref field_indices,
D
David Wood 已提交
792
            ref user_provided_types,
793
            ref user_provided_sigs,
794 795 796 797
            ref node_types,
            ref node_substs,
            ref adjustments,
            ref pat_binding_modes,
798
            ref pat_adjustments,
799
            ref closure_kind_origins,
800 801
            ref liberated_fn_sigs,
            ref fru_field_types,
S
Saleem Jaffer 已提交
802
            ref coercion_casts,
803 804
            ref used_trait_imports,
            tainted_by_errors,
V
varkor 已提交
805
            ref concrete_opaque_types,
806
            ref closure_min_captures,
R
Roxane 已提交
807
            ref closure_fake_reads,
808
            ref generator_interior_types,
809
            ref treat_byte_string_as_slice,
810
            ref closure_size_eval,
811 812 813
        } = *self;

        hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
A
Aman Arora 已提交
814 815
            hcx.local_def_path_hash(hir_owner);

816
            type_dependent_defs.hash_stable(hcx, hasher);
817
            field_indices.hash_stable(hcx, hasher);
D
David Wood 已提交
818
            user_provided_types.hash_stable(hcx, hasher);
819
            user_provided_sigs.hash_stable(hcx, hasher);
820 821 822 823
            node_types.hash_stable(hcx, hasher);
            node_substs.hash_stable(hcx, hasher);
            adjustments.hash_stable(hcx, hasher);
            pat_binding_modes.hash_stable(hcx, hasher);
824
            pat_adjustments.hash_stable(hcx, hasher);
825

826
            closure_kind_origins.hash_stable(hcx, hasher);
827 828
            liberated_fn_sigs.hash_stable(hcx, hasher);
            fru_field_types.hash_stable(hcx, hasher);
S
Saleem Jaffer 已提交
829
            coercion_casts.hash_stable(hcx, hasher);
830
            used_trait_imports.hash_stable(hcx, hasher);
831
            tainted_by_errors.hash_stable(hcx, hasher);
V
varkor 已提交
832
            concrete_opaque_types.hash_stable(hcx, hasher);
833
            closure_min_captures.hash_stable(hcx, hasher);
R
Roxane 已提交
834
            closure_fake_reads.hash_stable(hcx, hasher);
835
            generator_interior_types.hash_stable(hcx, hasher);
836
            treat_byte_string_as_slice.hash_stable(hcx, hasher);
837
            closure_size_eval.hash_stable(hcx, hasher);
838 839
        })
    }
840 841
}

842
rustc_index::newtype_index! {
D
David Wood 已提交
843
    pub struct UserTypeAnnotationIndex {
844
        derive [HashStable]
845
        DEBUG_FORMAT = "UserType({})",
D
David Wood 已提交
846 847 848 849 850 851
        const START_INDEX = 0,
    }
}

/// Mapping of type annotation indices to canonical user type annotations.
pub type CanonicalUserTypeAnnotations<'tcx> =
852 853
    IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;

M
Matthew Jasper 已提交
854
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
855 856 857
pub struct CanonicalUserTypeAnnotation<'tcx> {
    pub user_ty: CanonicalUserType<'tcx>,
    pub span: Span,
858
    pub inferred_ty: Ty<'tcx>,
859 860
}

D
David Wood 已提交
861
/// Canonicalized user type annotation.
862
pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
D
David Wood 已提交
863

864
impl<'tcx> CanonicalUserType<'tcx> {
D
David Wood 已提交
865
    /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
A
Alexander Regueiro 已提交
866
    /// i.e., each thing is mapped to a canonical variable with the same index.
D
David Wood 已提交
867 868
    pub fn is_identity(&self) -> bool {
        match self.value {
869 870
            UserType::Ty(_) => false,
            UserType::TypeOf(_, user_substs) => {
D
David Wood 已提交
871 872 873 874
                if user_substs.user_self_ty.is_some() {
                    return false;
                }

J
Josh Stone 已提交
875
                iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
D
David Wood 已提交
876
                    match kind.unpack() {
L
LeSeulArtichaut 已提交
877
                        GenericArgKind::Type(ty) => match ty.kind() {
D
David Wood 已提交
878 879
                            ty::Bound(debruijn, b) => {
                                // We only allow a `ty::INNERMOST` index in substitutions.
L
LeSeulArtichaut 已提交
880
                                assert_eq!(*debruijn, ty::INNERMOST);
D
David Wood 已提交
881 882 883 884 885
                                cvar == b.var
                            }
                            _ => false,
                        },

886
                        GenericArgKind::Lifetime(r) => match *r {
D
David Wood 已提交
887 888
                            ty::ReLateBound(debruijn, br) => {
                                // We only allow a `ty::INNERMOST` index in substitutions.
889
                                assert_eq!(debruijn, ty::INNERMOST);
890
                                cvar == br.var
D
David Wood 已提交
891 892 893
                            }
                            _ => false,
                        },
V
varkor 已提交
894

N
Nicholas Nethercote 已提交
895
                        GenericArgKind::Const(ct) => match ct.val() {
896
                            ty::ConstKind::Bound(debruijn, b) => {
V
varkor 已提交
897
                                // We only allow a `ty::INNERMOST` index in substitutions.
O
Oliver Scherer 已提交
898 899
                                assert_eq!(debruijn, ty::INNERMOST);
                                cvar == b
V
varkor 已提交
900 901 902
                            }
                            _ => false,
                        },
D
David Wood 已提交
903 904
                    }
                })
M
Mark Rousskov 已提交
905
            }
D
David Wood 已提交
906 907 908 909
        }
    }
}

A
Alexander Regueiro 已提交
910
/// A user-given type annotation attached to a constant. These arise
D
David Wood 已提交
911 912
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
M
Matthew Jasper 已提交
913
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
C
Camille GILLOT 已提交
914
#[derive(HashStable, TypeFoldable, Lift)]
915
pub enum UserType<'tcx> {
D
David Wood 已提交
916 917 918 919 920 921 922
    Ty(Ty<'tcx>),

    /// The canonical type is the result of `type_of(def_id)` with the
    /// given substitutions applied.
    TypeOf(DefId, UserSubsts<'tcx>),
}

923
impl<'tcx> CommonTypes<'tcx> {
924 925 926 927 928 929
    fn new(
        interners: &CtxtInterners<'tcx>,
        sess: &Session,
        resolutions: &ty::ResolverOutputs,
    ) -> CommonTypes<'tcx> {
        let mk = |ty| interners.intern_ty(ty, sess, resolutions);
930

931
        CommonTypes {
932
            unit: mk(Tuple(List::empty())),
933 934
            bool: mk(Bool),
            char: mk(Char),
V
varkor 已提交
935
            never: mk(Never),
936 937 938 939 940 941 942 943 944 945 946 947 948 949
            isize: mk(Int(ty::IntTy::Isize)),
            i8: mk(Int(ty::IntTy::I8)),
            i16: mk(Int(ty::IntTy::I16)),
            i32: mk(Int(ty::IntTy::I32)),
            i64: mk(Int(ty::IntTy::I64)),
            i128: mk(Int(ty::IntTy::I128)),
            usize: mk(Uint(ty::UintTy::Usize)),
            u8: mk(Uint(ty::UintTy::U8)),
            u16: mk(Uint(ty::UintTy::U16)),
            u32: mk(Uint(ty::UintTy::U32)),
            u64: mk(Uint(ty::UintTy::U64)),
            u128: mk(Uint(ty::UintTy::U128)),
            f32: mk(Float(ty::FloatTy::F32)),
            f64: mk(Float(ty::FloatTy::F64)),
B
Bastian Kauschke 已提交
950
            str_: mk(Str),
M
Mark Rousskov 已提交
951
            self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
952

953
            trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
954 955 956
        }
    }
}
957

958 959
impl<'tcx> CommonLifetimes<'tcx> {
    fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> {
960 961 962 963 964
        let mk = |r| {
            Region(Interned::new_unchecked(
                interners.region.intern(r, |r| InternedInSet(interners.arena.alloc(r))).0,
            ))
        };
965 966

        CommonLifetimes {
967 968 969
            re_root_empty: mk(ty::ReEmpty(ty::UniverseIndex::ROOT)),
            re_static: mk(ty::ReStatic),
            re_erased: mk(ty::ReErased),
970 971 972 973
        }
    }
}

V
varkor 已提交
974 975
impl<'tcx> CommonConsts<'tcx> {
    fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
N
Nicholas Nethercote 已提交
976 977 978 979 980
        let mk_const = |c| {
            Const(Interned::new_unchecked(
                interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0,
            ))
        };
V
varkor 已提交
981 982

        CommonConsts {
N
Nicholas Nethercote 已提交
983
            unit: mk_const(ty::ConstS {
984
                val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::ZST)),
985
                ty: types.unit,
986
            }),
V
varkor 已提交
987 988 989 990
        }
    }
}

991 992 993 994
// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
// conflict.
#[derive(Debug)]
pub struct FreeRegionInfo {
B
Bastian Kauschke 已提交
995 996
    // `LocalDefId` corresponding to FreeRegion
    pub def_id: LocalDefId,
997
    // the bound region corresponding to FreeRegion
998
    pub boundregion: ty::BoundRegionKind,
999 1000 1001 1002
    // checks if bound region is in Impl Item
    pub is_impl_item: bool,
}

N
Niko Matsakis 已提交
1003 1004
/// The central data structure of the compiler. It stores references
/// to the various **arenas** and also houses the results of the
M
Malo Jaffré 已提交
1005
/// various **compiler queries** that have been performed. See the
1006
/// [rustc dev guide] for more details.
M
Malo Jaffré 已提交
1007
///
1008
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
1009
#[derive(Copy, Clone)]
M
Mark Rousskov 已提交
1010
#[rustc_diagnostic_item = "TyCtxt"]
M
Mark Rousskov 已提交
1011
#[rustc_pass_by_value]
1012 1013
pub struct TyCtxt<'tcx> {
    gcx: &'tcx GlobalCtxt<'tcx>,
1014 1015
}

1016 1017
impl<'tcx> Deref for TyCtxt<'tcx> {
    type Target = &'tcx GlobalCtxt<'tcx>;
1018
    #[inline(always)]
1019
    fn deref(&self) -> &Self::Target {
1020 1021 1022 1023 1024
        &self.gcx
    }
}

pub struct GlobalCtxt<'tcx> {
C
Camille GILLOT 已提交
1025
    pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
1026

J
John Kåre Alsaker 已提交
1027
    interners: CtxtInterners<'tcx>,
1028

1029 1030
    pub sess: &'tcx Session,

1031 1032 1033 1034
    /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
    ///
    /// FIXME(Centril): consider `dyn LintStoreMarker` once
    /// we can upcast to `Any` for some additional type safety.
M
Mazdak Farrokhzad 已提交
1035
    pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
1036

N
Niko Matsakis 已提交
1037 1038
    pub dep_graph: DepGraph,

1039 1040
    pub prof: SelfProfilerRef,

1041 1042 1043
    /// Common types, pre-interned for your convenience.
    pub types: CommonTypes<'tcx>,

1044 1045 1046
    /// Common lifetimes, pre-interned for your convenience.
    pub lifetimes: CommonLifetimes<'tcx>,

V
varkor 已提交
1047 1048 1049
    /// Common consts, pre-interned for your convenience.
    pub consts: CommonConsts<'tcx>,

C
Camille GILLOT 已提交
1050 1051
    /// Output of the resolver.
    pub(crate) untracked_resolutions: ty::ResolverOutputs,
N
Niko Matsakis 已提交
1052

J
John Kåre Alsaker 已提交
1053
    pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>,
1054

1055 1056 1057 1058
    /// This provides access to the incremental compilation on-disk cache for query results.
    /// Do not access this directly. It is only meant to be used by
    /// `DepGraph::try_mark_green()` and the query infrastructure.
    /// This is `None` if we are not incremental compilation mode
1059
    pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
1060

1061
    pub queries: &'tcx dyn query::QueryEngine<'tcx>,
1062
    pub query_caches: query::QueryCaches<'tcx>,
C
Camille GILLOT 已提交
1063
    query_kinds: &'tcx [DepKindStruct],
1064

1065 1066 1067
    // Internal caches for metadata decoding. No need to track deps on this.
    pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
    pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
1068

1069 1070 1071 1072
    /// Caches the results of trait selection. This cache is used
    /// for things that do not have to do with the parameters in scope.
    pub selection_cache: traits::SelectionCache<'tcx>,

A
Ariel Ben-Yehuda 已提交
1073 1074 1075 1076 1077
    /// Caches the results of trait evaluation. This cache is used
    /// for things that do not have to do with the parameters in scope.
    /// Merge this with `selection_cache`?
    pub evaluation_cache: traits::EvaluationCache<'tcx>,

1078 1079
    /// The definite name of the current crate after taking into account
    /// attributes, commandline parameters, etc.
C
Camille GILLOT 已提交
1080
    crate_name: Symbol,
1081 1082 1083

    /// Data layout specification for the current target.
    pub data_layout: TargetDataLayout,
1084

1085
    /// Stores memory for globals (statics/consts).
1086
    pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
O
Oliver Schneider 已提交
1087

A
Alex Crichton 已提交
1088
    output_filenames: Arc<OutputFilenames>,
1089 1090
}

1091
impl<'tcx> TyCtxt<'tcx> {
1092
    pub fn typeck_opt_const_arg(
1093
        self,
B
Bastian Kauschke 已提交
1094
        def: ty::WithOptConstParam<LocalDefId>,
1095
    ) -> &'tcx TypeckResults<'tcx> {
B
Bastian Kauschke 已提交
1096
        if let Some(param_did) = def.const_param_did {
1097
            self.typeck_const_arg((def.did, param_did))
1098
        } else {
1099
            self.typeck(def.did)
1100 1101 1102
        }
    }

1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
    pub fn mir_borrowck_opt_const_arg(
        self,
        def: ty::WithOptConstParam<LocalDefId>,
    ) -> &'tcx BorrowCheckResult<'tcx> {
        if let Some(param_did) = def.const_param_did {
            self.mir_borrowck_const_arg((def.did, param_did))
        } else {
            self.mir_borrowck(def.did)
        }
    }

1114 1115 1116 1117
    pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
        self.arena.alloc(Steal::new(thir))
    }

B
Bastian Kauschke 已提交
1118 1119
    pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal<Body<'tcx>> {
        self.arena.alloc(Steal::new(mir))
1120 1121
    }

M
Mark Rousskov 已提交
1122 1123
    pub fn alloc_steal_promoted(
        self,
D
Dylan MacKenzie 已提交
1124
        promoted: IndexVec<Promoted, Body<'tcx>>,
B
Bastian Kauschke 已提交
1125 1126
    ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> {
        self.arena.alloc(Steal::new(promoted))
W
Wesley Wiser 已提交
1127 1128
    }

1129 1130 1131 1132 1133 1134
    pub fn alloc_adt_def(
        self,
        did: DefId,
        kind: AdtKind,
        variants: IndexVec<VariantIdx, ty::VariantDef>,
        repr: ReprOptions,
1135 1136
    ) -> ty::AdtDef<'tcx> {
        self.intern_adt_def(ty::AdtDefData::new(self, did, kind, variants, repr))
1137 1138
    }

1139
    /// Allocates a read-only byte or string literal for `mir::interpret`.
1140
    pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
1141
        // Create an allocation that just contains these bytes.
1142
        let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
O
Oliver Schneider 已提交
1143
        let alloc = self.intern_const_alloc(alloc);
1144
        self.create_memory_alloc(alloc)
O
Oliver Schneider 已提交
1145 1146
    }

1147 1148
    /// Returns a range of the start/end indices specified with the
    /// `rustc_layout_scalar_valid_range` attribute.
1149
    // FIXME(eddyb) this is an awkward spot for this method, maybe move it?
1150
    pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
1151
        let attrs = self.get_attrs(def_id);
1152
        let get = |name| {
E
est31 已提交
1153 1154
            let Some(attr) = attrs.iter().find(|a| a.has_name(name)) else {
                return Bound::Unbounded;
1155
            };
1156
            debug!("layout_scalar_valid_range: attr={:?}", attr);
1157
            if let Some(
M
Mark Rousskov 已提交
1158 1159 1160 1161 1162
                &[
                    ast::NestedMetaItem::Literal(ast::Lit {
                        kind: ast::LitKind::Int(a, _), ..
                    }),
                ],
1163 1164 1165 1166 1167 1168 1169
            ) = attr.meta_item_list().as_deref()
            {
                Bound::Included(a)
            } else {
                self.sess
                    .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute");
                Bound::Unbounded
1170 1171
            }
        };
M
Mark Rousskov 已提交
1172 1173 1174 1175
        (
            get(sym::rustc_layout_scalar_valid_range_start),
            get(sym::rustc_layout_scalar_valid_range_end),
        )
1176 1177
    }

B
Bastian Kauschke 已提交
1178
    pub fn lift<T: Lift<'tcx>>(self, value: T) -> Option<T::Lifted> {
1179 1180 1181
        value.lift_to_tcx(self)
    }

A
Alexander Regueiro 已提交
1182
    /// Creates a type context and call the closure with a `TyCtxt` reference
1183 1184 1185
    /// to the context. The closure enforces that the type context and any interned
    /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
    /// reference to the context, to allow formatting values that need it.
1186 1187
    pub fn create_global_ctxt(
        s: &'tcx Session,
M
Mazdak Farrokhzad 已提交
1188
        lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
C
Camille GILLOT 已提交
1189
        arena: &'tcx WorkerLocal<Arena<'tcx>>,
1190
        resolutions: ty::ResolverOutputs,
1191
        krate: &'tcx hir::Crate<'tcx>,
J
John Kåre Alsaker 已提交
1192
        dep_graph: DepGraph,
1193
        on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
1194
        queries: &'tcx dyn query::QueryEngine<'tcx>,
C
Camille GILLOT 已提交
1195
        query_kinds: &'tcx [DepKindStruct],
1196
        crate_name: &str,
1197
        output_filenames: OutputFilenames,
1198
    ) -> GlobalCtxt<'tcx> {
1199
        let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| {
1200 1201
            s.fatal(&err);
        });
J
John Kåre Alsaker 已提交
1202
        let interners = CtxtInterners::new(arena);
1203
        let common_types = CommonTypes::new(&interners, s, &resolutions);
1204
        let common_lifetimes = CommonLifetimes::new(&interners);
V
varkor 已提交
1205
        let common_consts = CommonConsts::new(&interners, &common_types);
1206

1207
        GlobalCtxt {
1208
            sess: s,
1209
            lint_store,
C
Camille GILLOT 已提交
1210
            arena,
J
John Kåre Alsaker 已提交
1211
            interners,
S
Shotaro Yamada 已提交
1212
            dep_graph,
C
Camille GILLOT 已提交
1213
            untracked_resolutions: resolutions,
1214
            prof: s.prof.clone(),
1215
            types: common_types,
1216
            lifetimes: common_lifetimes,
V
varkor 已提交
1217
            consts: common_consts,
1218
            untracked_crate: krate,
1219
            on_disk_cache,
1220
            queries,
1221
            query_caches: query::QueryCaches::default(),
C
Camille GILLOT 已提交
1222
            query_kinds,
1223 1224
            ty_rcache: Default::default(),
            pred_rcache: Default::default(),
1225 1226
            selection_cache: Default::default(),
            evaluation_cache: Default::default(),
1227
            crate_name: Symbol::intern(crate_name),
1228
            data_layout,
1229
            alloc_map: Lock::new(interpret::AllocMap::new()),
1230
            output_filenames: Arc::new(output_filenames),
1231
        }
1232
    }
1233

C
Camille GILLOT 已提交
1234
    crate fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct {
C
Camille GILLOT 已提交
1235 1236 1237
        &self.query_kinds[k as usize]
    }

1238 1239 1240
    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
    #[track_caller]
    pub fn ty_error(self) -> Ty<'tcx> {
M
mark 已提交
1241
        self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
1242 1243
    }

1244
    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
1245 1246 1247
    /// ensure it gets used.
    #[track_caller]
    pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
1248 1249
        let reported = self.sess.delay_span_bug(span, msg);
        self.mk_ty(Error(DelaySpanBugEmitted { reported, _priv: () }))
1250 1251
    }

L
lcnr 已提交
1252
    /// Like [TyCtxt::ty_error] but for constants.
1253
    #[track_caller]
N
Nicholas Nethercote 已提交
1254
    pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
L
lcnr 已提交
1255 1256 1257 1258 1259 1260 1261
        self.const_error_with_message(
            ty,
            DUMMY_SP,
            "ty::ConstKind::Error constructed but no error reported",
        )
    }

L
lcnr 已提交
1262
    /// Like [TyCtxt::ty_error_with_message] but for constants.
L
lcnr 已提交
1263 1264 1265 1266 1267 1268
    #[track_caller]
    pub fn const_error_with_message<S: Into<MultiSpan>>(
        self,
        ty: Ty<'tcx>,
        span: S,
        msg: &str,
N
Nicholas Nethercote 已提交
1269
    ) -> Const<'tcx> {
1270 1271 1272 1273 1274
        let reported = self.sess.delay_span_bug(span, msg);
        self.mk_const(ty::ConstS {
            val: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }),
            ty,
        })
1275 1276
    }

B
Bastian Kauschke 已提交
1277
    pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
N
Nicholas Nethercote 已提交
1278 1279
        let cname = self.crate_name(LOCAL_CRATE);
        self.sess.consider_optimizing(cname.as_str(), msg)
1280
    }
1281

O
Oliver Scherer 已提交
1282
    /// Obtain all lang items of this crate and all dependencies (recursively)
1283
    pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems {
C
Camille GILLOT 已提交
1284
        self.get_lang_items(())
1285
    }
1286

O
Oliver Scherer 已提交
1287 1288 1289
    /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
    /// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
    pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
C
Cameron Steffen 已提交
1290 1291 1292 1293 1294 1295
        self.all_diagnostic_items(()).name_to_id.get(&name).copied()
    }

    /// Obtain the diagnostic item's name
    pub fn get_diagnostic_name(self, id: DefId) -> Option<Symbol> {
        self.diagnostic_items(id.krate).id_to_name.get(&id).copied()
O
Oliver Scherer 已提交
1296 1297 1298 1299
    }

    /// Check whether the diagnostic item with the given `name` has the given `DefId`.
    pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool {
C
Cameron Steffen 已提交
1300
        self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
O
Oliver Scherer 已提交
1301 1302
    }

C
Camille GILLOT 已提交
1303
    pub fn stability(self) -> &'tcx stability::Index {
C
Camille GILLOT 已提交
1304
        self.stability_index(())
1305
    }
1306

1307
    pub fn features(self) -> &'tcx rustc_feature::Features {
C
Camille GILLOT 已提交
1308
        self.features_query(())
1309 1310
    }

1311
    pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
1312
        // Accessing the DefKey is ok, since it is part of DefPathHash.
C
Camille GILLOT 已提交
1313
        if let Some(id) = id.as_local() {
1314
            self.untracked_resolutions.definitions.def_key(id)
C
Camille GILLOT 已提交
1315 1316 1317
        } else {
            self.untracked_resolutions.cstore.def_key(id)
        }
1318 1319
    }

A
Alexander Regueiro 已提交
1320
    /// Converts a `DefId` into its fully expanded `DefPath` (every
1321
    /// `DefId` is really just an interned `DefPath`).
1322 1323 1324
    ///
    /// Note that if `id` is not local to this crate, the result will
    ///  be a non-local `DefPath`.
1325
    pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
1326
        // Accessing the DefPath is ok, since it is part of DefPathHash.
1327
        if let Some(id) = id.as_local() {
1328
            self.untracked_resolutions.definitions.def_path(id)
1329
        } else {
C
Camille GILLOT 已提交
1330
            self.untracked_resolutions.cstore.def_path(id)
1331
        }
1332 1333 1334
    }

    #[inline]
1335
    pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
1336
        // Accessing the DefPathHash is ok, it is incr. comp. stable.
1337
        if let Some(def_id) = def_id.as_local() {
C
Camille GILLOT 已提交
1338
            self.untracked_resolutions.definitions.def_path_hash(def_id)
1339
        } else {
C
Camille GILLOT 已提交
1340
            self.untracked_resolutions.cstore.def_path_hash(def_id)
1341 1342 1343
        }
    }

1344
    #[inline]
B
bjorn3 已提交
1345 1346 1347 1348
    pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
        if crate_num == LOCAL_CRATE {
            self.sess.local_stable_crate_id()
        } else {
1349
            self.untracked_resolutions.cstore.stable_crate_id(crate_num)
B
bjorn3 已提交
1350
        }
1351 1352
    }

1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
    /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
    /// that the crate in question has already been loaded by the CrateStore.
    #[inline]
    pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
        if stable_crate_id == self.sess.local_stable_crate_id() {
            LOCAL_CRATE
        } else {
            self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
        }
    }

1364 1365 1366
    /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
    /// session, if it still exists. This is used during incremental compilation to
    /// turn a deserialized `DefPathHash` into its current `DefId`.
1367
    pub fn def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() -> !) -> DefId {
1368 1369 1370 1371 1372 1373 1374
        debug!("def_path_hash_to_def_id({:?})", hash);

        let stable_crate_id = hash.stable_crate_id();

        // If this is a DefPathHash from the local crate, we can look up the
        // DefId in the tcx's `Definitions`.
        if stable_crate_id == self.sess.local_stable_crate_id() {
1375 1376 1377 1378
            self.untracked_resolutions
                .definitions
                .local_def_path_hash_to_def_id(hash, err)
                .to_def_id()
1379 1380 1381 1382 1383 1384 1385 1386 1387
        } else {
            // If this is a DefPathHash from an upstream crate, let the CrateStore map
            // it to a DefId.
            let cstore = &self.untracked_resolutions.cstore;
            let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
            cstore.def_path_hash_to_def_id(cnum, hash)
        }
    }

1388 1389
    pub fn def_path_debug_str(self, def_id: DefId) -> String {
        // We are explicitly not going through queries here in order to get
1390
        // crate name and stable crate id since this code is called from debug!()
1391 1392
        // statements within the query system and we'd run into endless
        // recursion otherwise.
1393 1394
        let (crate_name, stable_crate_id) = if def_id.is_local() {
            (self.crate_name, self.sess.local_stable_crate_id())
1395
        } else {
C
Camille GILLOT 已提交
1396
            let cstore = &self.untracked_resolutions.cstore;
1397
            (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
1398 1399
        };

M
Mark Rousskov 已提交
1400 1401 1402
        format!(
            "{}[{}]{}",
            crate_name,
1403
            // Don't print the whole stable crate id. That's just
M
Mark Rousskov 已提交
1404
            // annoying in debug output.
1405
            &(format!("{:08x}", stable_crate_id.to_u64()))[..4],
M
marmeladema 已提交
1406
            self.def_path(def_id).to_string_no_crate_verbose()
M
Mark Rousskov 已提交
1407
        )
1408
    }
1409

1410 1411 1412 1413 1414 1415 1416 1417 1418 1419
    /// Note that this is *untracked* and should only be used within the query
    /// system if the result is otherwise tracked through queries
    pub fn cstore_untracked(self) -> &'tcx ty::CrateStoreDyn {
        &*self.untracked_resolutions.cstore
    }

    /// Note that this is *untracked* and should only be used within the query
    /// system if the result is otherwise tracked through queries
    pub fn definitions_untracked(self) -> &'tcx hir::definitions::Definitions {
        &self.untracked_resolutions.definitions
1420
    }
1421

1422
    #[inline(always)]
1423
    pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
C
Camille GILLOT 已提交
1424
        let resolutions = &self.gcx.untracked_resolutions;
1425
        StableHashingContext::new(self.sess, &resolutions.definitions, &*resolutions.cstore)
1426
    }
1427

1428 1429
    #[inline(always)]
    pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> {
C
Camille GILLOT 已提交
1430 1431 1432 1433 1434 1435
        let resolutions = &self.gcx.untracked_resolutions;
        StableHashingContext::ignore_spans(
            self.sess,
            &resolutions.definitions,
            &*resolutions.cstore,
        )
1436 1437
    }

1438
    pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult {
1439
        self.on_disk_cache.as_ref().map_or(Ok(()), |c| c.serialize(self, encoder))
1440 1441
    }

1442 1443
    /// If `true`, we should use the MIR-based borrowck, but also
    /// fall back on the AST borrowck if the MIR-based one errors.
1444 1445 1446 1447
    pub fn migrate_borrowck(self) -> bool {
        self.borrowck_mode().migrate()
    }

1448 1449
    /// What mode(s) of borrowck should we run? AST? MIR? both?
    /// (Also considers the `#![feature(nll)]` setting.)
1450
    pub fn borrowck_mode(self) -> BorrowckMode {
F
Felix S. Klock II 已提交
1451 1452
        // Here are the main constraints we need to deal with:
        //
1453
        // 1. An opts.borrowck_mode of `BorrowckMode::Migrate` is
F
Felix S. Klock II 已提交
1454 1455
        //    synonymous with no `-Z borrowck=...` flag at all.
        //
1456
        // 2. We want to allow developers on the Nightly channel
F
Felix S. Klock II 已提交
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
        //    to opt back into the "hard error" mode for NLL,
        //    (which they can do via specifying `#![feature(nll)]`
        //    explicitly in their crate).
        //
        // So, this precedence list is how pnkfelix chose to work with
        // the above constraints:
        //
        // * `#![feature(nll)]` *always* means use NLL with hard
        //   errors. (To simplify the code here, it now even overrides
        //   a user's attempt to specify `-Z borrowck=compare`, which
        //   we arguably do not need anymore and should remove.)
        //
1469
        // * Otherwise, if no `-Z borrowck=...` then use migrate mode
F
Felix S. Klock II 已提交
1470 1471 1472
        //
        // * Otherwise, use the behavior requested via `-Z borrowck=...`

M
Mark Rousskov 已提交
1473 1474 1475
        if self.features().nll {
            return BorrowckMode::Mir;
        }
F
Felix S. Klock II 已提交
1476

1477
        self.sess.opts.borrowck_mode
1478 1479
    }

1480 1481 1482 1483
    /// If `true`, we should use lazy normalization for constants, otherwise
    /// we still evaluate them eagerly.
    #[inline]
    pub fn lazy_normalization(self) -> bool {
1484
        let features = self.features();
1485 1486
        // Note: We only use lazy normalization for generic const expressions.
        features.generic_const_exprs
1487 1488
    }

1489 1490
    #[inline]
    pub fn local_crate_exports_generics(self) -> bool {
1491
        debug_assert!(self.sess.opts.share_generics());
1492

1493
        self.sess.crate_types().iter().any(|crate_type| {
1494
            match crate_type {
M
Mark Rousskov 已提交
1495 1496 1497 1498
                CrateType::Executable
                | CrateType::Staticlib
                | CrateType::ProcMacro
                | CrateType::Cdylib => false,
1499 1500 1501 1502 1503

                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
                // We want to block export of generics from dylibs,
                // but we must fix rust-lang/rust#65890 before we can
                // do that robustly.
M
Mark Rousskov 已提交
1504
                CrateType::Dylib => true,
1505

M
Mark Rousskov 已提交
1506
                CrateType::Rlib => true,
1507 1508 1509
            }
        })
    }
1510

1511
    // Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
1512
    pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
1513
        let (suitable_region_binding_scope, bound_region) = match *region {
B
Bastian Kauschke 已提交
1514 1515
            ty::ReFree(ref free_region) => {
                (free_region.scope.expect_local(), free_region.bound_region)
M
Mark Rousskov 已提交
1516
            }
B
Bastian Kauschke 已提交
1517 1518
            ty::ReEarlyBound(ref ebr) => (
                self.parent(ebr.def_id).unwrap().expect_local(),
1519
                ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
B
Bastian Kauschke 已提交
1520
            ),
1521 1522 1523
            _ => return None, // not a free region
        };

1524
        let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
1525
            Some(Node::Item(..) | Node::TraitItem(..)) => false,
1526 1527 1528 1529 1530 1531
            Some(Node::ImplItem(..)) => {
                self.is_bound_region_in_impl_item(suitable_region_binding_scope)
            }
            _ => return None,
        };

1532
        Some(FreeRegionInfo {
1533 1534
            def_id: suitable_region_binding_scope,
            boundregion: bound_region,
1535
            is_impl_item,
1536
        })
1537 1538
    }

E
Esteban Küber 已提交
1539
    /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
1540
    pub fn return_type_impl_or_dyn_traits(
1541
        self,
1542 1543
        scope_def_id: LocalDefId,
    ) -> Vec<&'tcx hir::Ty<'tcx>> {
1544
        let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
E
est31 已提交
1545 1546
        let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
            return vec![];
1547 1548
        };

1549 1550 1551
        let mut v = TraitObjectVisitor(vec![], self.hir());
        v.visit_ty(hir_output);
        v.0
1552 1553
    }

1554
    pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
1555
        // `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
1556
        match self.hir().get_by_def_id(scope_def_id) {
1557 1558 1559 1560 1561
            Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {}
            Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {}
            Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {}
            Node::Expr(&hir::Expr { kind: ExprKind::Closure(..), .. }) => {}
            _ => return None,
1562 1563
        }

1564
        let ret_ty = self.type_of(scope_def_id);
L
LeSeulArtichaut 已提交
1565
        match ret_ty.kind() {
1566
            ty::FnDef(_, _) => {
1567
                let sig = ret_ty.fn_sig(self);
B
Bastian Kauschke 已提交
1568
                let output = self.erase_late_bound_regions(sig.output());
1569
                if output.is_impl_trait() {
1570
                    let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
C
csmoe 已提交
1571 1572
                    let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
                    Some((output, fn_decl.output.span()))
1573 1574 1575
                } else {
                    None
                }
1576
            }
M
Mark Rousskov 已提交
1577
            _ => None,
1578 1579 1580
        }
    }

1581
    // Checks if the bound region is in Impl Item.
1582
    pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
B
Bastian Kauschke 已提交
1583 1584
        let container_id =
            self.associated_item(suitable_region_binding_scope.to_def_id()).container.id();
1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595
        if self.impl_trait_ref(container_id).is_some() {
            // For now, we do not try to target impls of traits. This is
            // because this message is going to suggest that the user
            // change the fn signature, but they may not be free to do so,
            // since the signature must match the trait.
            //
            // FIXME(#42706) -- in some cases, we could do better here.
            return true;
        }
        false
    }
1596

1597
    /// Determines whether identifiers in the assembly have strict naming rules.
1598
    /// Currently, only NVPTX* targets need it.
1599
    pub fn has_strict_asm_symbol_naming(self) -> bool {
1600
        self.sess.target.arch.contains("nvptx")
1601
    }
1602 1603

    /// Returns `&'static core::panic::Location<'static>`.
1604
    pub fn caller_location_ty(self) -> Ty<'tcx> {
1605 1606
        self.mk_imm_ref(
            self.lifetimes.re_static,
1607
            self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
1608
                .subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
1609 1610
        )
    }
M
Mark Mansi 已提交
1611

M
Mark Mansi 已提交
1612
    /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
1613
    pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
1614 1615 1616 1617 1618 1619 1620
        match self.def_kind(def_id) {
            DefKind::Generator => match self.generator_kind(def_id).unwrap() {
                rustc_hir::GeneratorKind::Async(..) => ("an", "async closure"),
                rustc_hir::GeneratorKind::Gen => ("a", "generator"),
            },
            def_kind => (def_kind.article(), def_kind.descr(def_id)),
        }
M
Mark Mansi 已提交
1621
    }
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637

    pub fn type_length_limit(self) -> Limit {
        self.limits(()).type_length_limit
    }

    pub fn recursion_limit(self) -> Limit {
        self.limits(()).recursion_limit
    }

    pub fn move_size_limit(self) -> Limit {
        self.limits(()).move_size_limit
    }

    pub fn const_eval_limit(self) -> Limit {
        self.limits(()).const_eval_limit
    }
1638 1639 1640 1641 1642 1643

    pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
        iter::once(LOCAL_CRATE)
            .chain(self.crates(()).iter().copied())
            .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
    }
1644 1645
}

1646 1647 1648 1649
/// A trait implemented for all `X<'a>` types that can be safely and
/// efficiently converted to `X<'tcx>` as long as they are part of the
/// provided `TyCtxt<'tcx>`.
/// This can be done, for example, for `Ty<'tcx>` or `SubstsRef<'tcx>`
1650
/// by looking them up in their respective interners.
1651 1652 1653
///
/// However, this is still not the best implementation as it does
/// need to compare the components, even for interned values.
1654
/// It would be more efficient if `TypedArena` provided a way to
1655 1656
/// determine whether the address is in the allocated range.
///
1657
/// `None` is returned if the value or one of the components is not part
1658
/// of the provided context.
1659 1660
/// For `Ty`, `None` can be returned if either the type interner doesn't
/// contain the `TyKind` key or if the address of the interned
1661
/// pointer differs. The latter case is possible if a primitive type,
1662
/// e.g., `()` or `u8`, was interned in a different context.
N
Niko Matsakis 已提交
1663 1664
pub trait Lift<'tcx>: fmt::Debug {
    type Lifted: fmt::Debug + 'tcx;
B
Bastian Kauschke 已提交
1665
    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>;
1666 1667
}

N
Nicholas Nethercote 已提交
1668 1669 1670 1671 1672 1673
macro_rules! nop_lift {
    ($set:ident; $ty:ty => $lifted:ty) => {
        impl<'a, 'tcx> Lift<'tcx> for $ty {
            type Lifted = $lifted;
            fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                if tcx.interners.$set.contains_pointer_to(&InternedInSet(self.0.0)) {
L
lcnr 已提交
1674 1675
                    // SAFETY: `self` is interned and therefore valid
                    // for the entire lifetime of the `TyCtxt`.
N
Nicholas Nethercote 已提交
1676 1677 1678 1679 1680 1681 1682 1683 1684
                    Some(unsafe { mem::transmute(self) })
                } else {
                    None
                }
            }
        }
    };
}

1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
// Can't use the macros as we have reuse the `substs` here.
//
// See `intern_type_list` for more info.
impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
    type Lifted = &'tcx List<Ty<'tcx>>;
    fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
        if self.is_empty() {
            return Some(List::empty());
        }
        if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
L
lcnr 已提交
1695 1696 1697
            // SAFETY: `self` is interned and therefore valid
            // for the entire lifetime of the `TyCtxt`.
            Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
1698 1699 1700 1701 1702 1703
        } else {
            None
        }
    }
}

O
Oliver Scherer 已提交
1704
macro_rules! nop_list_lift {
1705
    ($set:ident; $ty:ty => $lifted:ty) => {
O
Oliver Scherer 已提交
1706
        impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
M
Mark Rousskov 已提交
1707
            type Lifted = &'tcx List<$lifted>;
B
Bastian Kauschke 已提交
1708
            fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
M
Mark Rousskov 已提交
1709 1710
                if self.is_empty() {
                    return Some(List::empty());
O
Oliver Scherer 已提交
1711
                }
1712
                if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
B
Bastian Kauschke 已提交
1713
                    Some(unsafe { mem::transmute(self) })
M
Mark Rousskov 已提交
1714 1715 1716 1717 1718
                } else {
                    None
                }
            }
        }
O
Oliver Scherer 已提交
1719
    };
1720 1721
}

1722
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
1723
nop_lift! {region; Region<'a> => Region<'tcx>}
N
Nicholas Nethercote 已提交
1724
nop_lift! {const_; Const<'a> => Const<'tcx>}
1725
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
1726
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
1727

J
Jack Huey 已提交
1728
nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>}
1729
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
V
varkor 已提交
1730
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
1731
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
J
Jack Huey 已提交
1732
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
1733

1734
// This is the impl for `&'a InternalSubsts<'a>`.
1735
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
1736

1737
CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
1738

1739
pub mod tls {
M
Mark Rousskov 已提交
1740
    use super::{ptr_eq, GlobalCtxt, TyCtxt};
1741

1742
    use crate::dep_graph::TaskDepsRef;
M
Mark Mansi 已提交
1743
    use crate::ty::query;
1744
    use rustc_data_structures::sync::{self, Lock};
1745
    use rustc_data_structures::thin_vec::ThinVec;
1746
    use rustc_errors::Diagnostic;
M
Mark Rousskov 已提交
1747
    use std::mem;
1748

1749
    #[cfg(not(parallel_compiler))]
1750 1751
    use std::cell::Cell;

1752
    #[cfg(parallel_compiler)]
M
Mark Mansi 已提交
1753
    use rustc_rayon_core as rayon_core;
1754

1755
    /// This is the implicit state of rustc. It contains the current
1756 1757 1758
    /// `TyCtxt` and query. It is updated when creating a local interner or
    /// executing a new query. Whenever there's a `TyCtxt` value available
    /// you should also have access to an `ImplicitCtxt` through the functions
1759
    /// in this module.
1760
    #[derive(Clone)]
1761
    pub struct ImplicitCtxt<'a, 'tcx> {
N
Nicholas Nethercote 已提交
1762
        /// The current `TyCtxt`.
1763
        pub tcx: TyCtxt<'tcx>,
1764

1765 1766
        /// The current query job, if any. This is updated by `JobOwner::start` in
        /// `ty::query::plumbing` when executing a query.
1767
        pub query: Option<query::QueryJobId>,
1768

1769
        /// Where to store diagnostics for the current query job, if any.
1770
        /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
1771 1772
        pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,

1773 1774
        /// Used to prevent layout from recursing too deeply.
        pub layout_depth: usize,
J
John Kåre Alsaker 已提交
1775 1776

        /// The current dep graph task. This is used to add dependencies to queries
1777
        /// when executing them.
1778
        pub task_deps: TaskDepsRef<'a>,
1779
    }
1780

N
Nicholas Nethercote 已提交
1781 1782 1783
    impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
        pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
            let tcx = TyCtxt { gcx };
1784 1785 1786 1787 1788 1789 1790
            ImplicitCtxt {
                tcx,
                query: None,
                diagnostics: None,
                layout_depth: 0,
                task_deps: TaskDepsRef::Ignore,
            }
N
Nicholas Nethercote 已提交
1791 1792 1793
        }
    }

1794
    /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
J
John Kåre Alsaker 已提交
1795
    /// to `value` during the call to `f`. It is restored to its previous value after.
1796
    /// This is used to set the pointer to the new `ImplicitCtxt`.
1797
    #[cfg(parallel_compiler)]
J
John Kåre Alsaker 已提交
1798
    #[inline]
1799 1800 1801 1802
    fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
        rayon_core::tlv::with(value, f)
    }

1803
    /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
1804
    /// This is used to get the pointer to the current `ImplicitCtxt`.
1805
    #[cfg(parallel_compiler)]
J
John Kåre Alsaker 已提交
1806
    #[inline]
N
Nicholas Nethercote 已提交
1807
    pub fn get_tlv() -> usize {
1808 1809 1810
        rayon_core::tlv::get()
    }

1811
    #[cfg(not(parallel_compiler))]
1812
    thread_local! {
1813
        /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
M
Mark Rousskov 已提交
1814
        static TLV: Cell<usize> = const { Cell::new(0) };
1815
    }
1816

J
John Kåre Alsaker 已提交
1817 1818
    /// Sets TLV to `value` during the call to `f`.
    /// It is restored to its previous value after.
1819
    /// This is used to set the pointer to the new `ImplicitCtxt`.
1820
    #[cfg(not(parallel_compiler))]
J
John Kåre Alsaker 已提交
1821
    #[inline]
1822 1823
    fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
        let old = get_tlv();
N
Nicholas Nethercote 已提交
1824
        let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
1825 1826 1827
        TLV.with(|tlv| tlv.set(value));
        f()
    }
1828

1829
    /// Gets the pointer to the current `ImplicitCtxt`.
1830
    #[cfg(not(parallel_compiler))]
1831
    #[inline]
1832 1833
    fn get_tlv() -> usize {
        TLV.with(|tlv| tlv.get())
1834
    }
1835

1836
    /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
J
John Kåre Alsaker 已提交
1837
    #[inline]
1838 1839 1840
    pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
    where
        F: FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
1841
    {
M
Mark Rousskov 已提交
1842
        set_tlv(context as *const _ as usize, || f(&context))
1843 1844
    }

1845
    /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
J
John Kåre Alsaker 已提交
1846
    #[inline]
1847
    pub fn with_context_opt<F, R>(f: F) -> R
1848 1849
    where
        F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
1850
    {
1851 1852
        let context = get_tlv();
        if context == 0 {
1853
            f(None)
1854
        } else {
F
Frank Steffahn 已提交
1855
            // We could get an `ImplicitCtxt` pointer from another thread.
1856
            // Ensure that `ImplicitCtxt` is `Sync`.
1857
            sync::assert_sync::<ImplicitCtxt<'_, '_>>();
J
John Kåre Alsaker 已提交
1858

1859
            unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) }
1860 1861
        }
    }
1862

1863 1864
    /// Allows access to the current `ImplicitCtxt`.
    /// Panics if there is no `ImplicitCtxt` available.
J
John Kåre Alsaker 已提交
1865
    #[inline]
1866
    pub fn with_context<F, R>(f: F) -> R
1867 1868
    where
        F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
1869 1870 1871 1872
    {
        with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
    }

B
bjorn3 已提交
1873 1874 1875 1876 1877
    /// Allows access to the current `ImplicitCtxt` whose tcx field is the same as the tcx argument
    /// passed in. This means the closure is given an `ImplicitCtxt` with the same `'tcx` lifetime
    /// as the `TyCtxt` passed in.
    /// This will panic if you pass it a `TyCtxt` which is different from the current
    /// `ImplicitCtxt`'s `tcx` field.
J
John Kåre Alsaker 已提交
1878
    #[inline]
1879
    pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
1880
    where
1881
        F: FnOnce(&ImplicitCtxt<'_, 'tcx>) -> R,
1882
    {
M
Mark Rousskov 已提交
1883 1884 1885 1886
        with_context(|context| unsafe {
            assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
            let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
            f(context)
1887 1888 1889
        })
    }

1890 1891
    /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
    /// Panics if there is no `ImplicitCtxt` available.
J
John Kåre Alsaker 已提交
1892
    #[inline]
1893
    pub fn with<F, R>(f: F) -> R
1894
    where
1895
        F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
1896
    {
1897
        with_context(|context| f(context.tcx))
1898 1899
    }

1900 1901
    /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
    /// The closure is passed None if there is no `ImplicitCtxt` available.
J
John Kåre Alsaker 已提交
1902
    #[inline]
1903
    pub fn with_opt<F, R>(f: F) -> R
1904
    where
1905
        F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
1906
    {
1907
        with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
1908 1909 1910 1911
    }
}

macro_rules! sty_debug_print {
1912
    ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
1913
        // Curious inner module to allow variant names to be used as
1914 1915 1916
        // variable names.
        #[allow(non_snake_case)]
        mod inner {
M
Mark Mansi 已提交
1917
            use crate::ty::{self, TyCtxt};
1918
            use crate::ty::context::InternedInSet;
1919

1920 1921 1922
            #[derive(Copy, Clone)]
            struct DebugStat {
                total: usize,
V
varkor 已提交
1923
                lt_infer: usize,
1924
                ty_infer: usize,
V
varkor 已提交
1925 1926
                ct_infer: usize,
                all_infer: usize,
1927 1928
            }

1929
            pub fn go(fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'_>) -> std::fmt::Result {
1930 1931
                let mut total = DebugStat {
                    total: 0,
V
varkor 已提交
1932 1933 1934 1935
                    lt_infer: 0,
                    ty_infer: 0,
                    ct_infer: 0,
                    all_infer: 0,
1936 1937 1938
                };
                $(let mut $variant = total;)*

1939 1940
                let shards = tcx.interners.type_.lock_shards();
                let types = shards.iter().flat_map(|shard| shard.keys());
1941
                for &InternedInSet(t) in types {
N
Nicholas Nethercote 已提交
1942
                    let variant = match t.kind {
1943 1944
                        ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                            ty::Float(..) | ty::Str | ty::Never => continue,
1945
                        ty::Error(_) => /* unimportant */ continue,
1946 1947
                        $(ty::$variant(..) => &mut $variant,)*
                    };
N
Nicholas Nethercote 已提交
1948 1949 1950
                    let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
                    let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
                    let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
1951 1952 1953

                    variant.total += 1;
                    total.total += 1;
V
varkor 已提交
1954
                    if lt { total.lt_infer += 1; variant.lt_infer += 1 }
1955
                    if ty { total.ty_infer += 1; variant.ty_infer += 1 }
V
varkor 已提交
1956 1957
                    if ct { total.ct_infer += 1; variant.ct_infer += 1 }
                    if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
1958
                }
1959 1960
                writeln!(fmt, "Ty interner             total           ty lt ct all")?;
                $(writeln!(fmt, "    {:18}: {uses:6} {usespc:4.1}%, \
V
varkor 已提交
1961 1962 1963 1964 1965 1966 1967
                            {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
                    stringify!($variant),
                    uses = $variant.total,
                    usespc = $variant.total as f64 * 100.0 / total.total as f64,
                    ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
                    lt = $variant.lt_infer as f64 * 100.0  / total.total as f64,
                    ct = $variant.ct_infer as f64 * 100.0  / total.total as f64,
1968
                    all = $variant.all_infer as f64 * 100.0  / total.total as f64)?;
V
varkor 已提交
1969
                )*
1970
                writeln!(fmt, "                  total {uses:6}        \
V
varkor 已提交
1971 1972 1973 1974 1975 1976
                          {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
                    uses = total.total,
                    ty = total.ty_infer as f64 * 100.0  / total.total as f64,
                    lt = total.lt_infer as f64 * 100.0  / total.total as f64,
                    ct = total.ct_infer as f64 * 100.0  / total.total as f64,
                    all = total.all_infer as f64 * 100.0  / total.total as f64)
1977 1978 1979
            }
        }

1980
        inner::go($fmt, $ctxt)
1981 1982 1983
    }}
}

1984
impl<'tcx> TyCtxt<'tcx> {
1985
    pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx {
O
Oliver Scherer 已提交
1986 1987
        struct DebugStats<'tcx>(TyCtxt<'tcx>);

1988
        impl<'tcx> std::fmt::Debug for DebugStats<'tcx> {
O
Oliver Scherer 已提交
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015
            fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                sty_debug_print!(
                    fmt,
                    self.0,
                    Adt,
                    Array,
                    Slice,
                    RawPtr,
                    Ref,
                    FnDef,
                    FnPtr,
                    Placeholder,
                    Generator,
                    GeneratorWitness,
                    Dynamic,
                    Closure,
                    Tuple,
                    Bound,
                    Param,
                    Infer,
                    Projection,
                    Opaque,
                    Foreign
                )?;

                writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
                writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
2016 2017 2018 2019 2020 2021
                writeln!(
                    fmt,
                    "Const Allocation interner: #{}",
                    self.0.interners.const_allocation.len()
                )?;
                writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
O
Oliver Scherer 已提交
2022 2023 2024 2025

                Ok(())
            }
        }
2026

O
Oliver Scherer 已提交
2027
        DebugStats(self)
2028 2029 2030
    }
}

2031 2032 2033 2034
// This type holds a `T` in the interner. The `T` is stored in the arena and
// this type just holds a pointer to it, but it still effectively owns it. It
// impls `Borrow` so that it can be looked up using the original
// (non-arena-memory-owning) types.
2035
struct InternedInSet<'tcx, T: ?Sized>(&'tcx T);
2036

2037
impl<'tcx, T: 'tcx + ?Sized> Clone for InternedInSet<'tcx, T> {
2038
    fn clone(&self) -> Self {
2039
        InternedInSet(self.0)
2040 2041
    }
}
2042

2043
impl<'tcx, T: 'tcx + ?Sized> Copy for InternedInSet<'tcx, T> {}
2044

2045
impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
2046 2047 2048 2049
    fn into_pointer(&self) -> *const () {
        self.0 as *const _ as *const ()
    }
}
2050 2051

#[allow(rustc::usage_of_ty_tykind)]
2052
impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
2053
    fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> {
N
Nicholas Nethercote 已提交
2054
        &self.0.kind
2055 2056 2057
    }
}

2058 2059
impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
    fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<TyS<'tcx>>>) -> bool {
2060 2061
        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
        // `x == y`.
N
Nicholas Nethercote 已提交
2062
        self.0.kind == other.0.kind
2063 2064 2065
    }
}

2066
impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {}
2067

2068
impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {
2069
    fn hash<H: Hasher>(&self, s: &mut H) {
2070
        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
N
Nicholas Nethercote 已提交
2071
        self.0.kind.hash(s)
2072 2073 2074
    }
}

2075
impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for InternedInSet<'tcx, PredicateS<'tcx>> {
2076 2077
    fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> {
        &self.0.kind
2078 2079
    }
}
2080

2081 2082
impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> {
    fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool {
2083 2084
        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
        // `x == y`.
2085 2086 2087 2088
        self.0.kind == other.0.kind
    }
}

2089
impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {}
2090

2091
impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> {
2092
    fn hash<H: Hasher>(&self, s: &mut H) {
2093
        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
2094 2095 2096 2097
        self.0.kind.hash(s)
    }
}

2098
impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
2099 2100
    fn borrow<'a>(&'a self) -> &'a [T] {
        &self.0[..]
2101 2102
    }
}
2103

2104 2105
impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> {
    fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool {
2106 2107
        // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
        // `x == y`.
2108 2109 2110 2111
        self.0[..] == other.0[..]
    }
}

2112
impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {}
2113

2114
impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
2115
    fn hash<H: Hasher>(&self, s: &mut H) {
2116
        // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
2117 2118 2119 2120 2121
        self.0[..].hash(s)
    }
}

macro_rules! direct_interners {
2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
    ($($name:ident: $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
        $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
            fn borrow<'a>(&'a self) -> &'a $ty {
                &self.0
            }
        }

        impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> {
            fn eq(&self, other: &Self) -> bool {
                // The `Borrow` trait requires that `x.borrow() == y.borrow()`
                // equals `x == y`.
                self.0 == other.0
            }
        }

        impl<'tcx> Eq for InternedInSet<'tcx, $ty> {}

        impl<'tcx> Hash for InternedInSet<'tcx, $ty> {
            fn hash<H: Hasher>(&self, s: &mut H) {
                // The `Borrow` trait requires that `x.borrow().hash(s) ==
                // x.hash(s)`.
                self.0.hash(s)
            }
        }

        impl<'tcx> TyCtxt<'tcx> {
            pub fn $method(self, v: $ty) -> $ret_ty {
                $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
                    InternedInSet(self.interners.arena.alloc(v))
                }).0))
            }
        })+
    }
}

direct_interners! {
    region: mk_region(RegionKind): Region -> Region<'tcx>,
N
Nicholas Nethercote 已提交
2159
    const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>,
2160
    const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
2161
    layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>,
2162
    adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
2163
}
2164

2165
macro_rules! slice_interners {
2166
    ($($field:ident: $method:ident($ty:ty)),+ $(,)?) => (
D
Dániel Buga 已提交
2167 2168
        impl<'tcx> TyCtxt<'tcx> {
            $(pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
2169
                self.interners.$field.intern_ref(v, || {
2170
                    InternedInSet(List::from_arena(&*self.arena, v))
2171
                }).0
D
Dániel Buga 已提交
2172 2173
            })+
        }
2174
    );
2175
}
2176

2177
slice_interners!(
2178
    substs: _intern_substs(GenericArg<'tcx>),
V
varkor 已提交
2179
    canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
J
Jack Huey 已提交
2180
    poly_existential_predicates:
J
Jack Huey 已提交
2181
        _intern_poly_existential_predicates(ty::Binder<'tcx, ExistentialPredicate<'tcx>>),
N
Nicholas Nethercote 已提交
2182
    predicates: _intern_predicates(Predicate<'tcx>),
2183
    projs: _intern_projs(ProjectionKind),
J
Jack Huey 已提交
2184
    place_elems: _intern_place_elems(PlaceElem<'tcx>),
J
Jack Huey 已提交
2185
    bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
2186 2187
);

2188
impl<'tcx> TyCtxt<'tcx> {
2189 2190 2191
    /// Given a `fn` type, returns an equivalent `unsafe fn` type;
    /// that is, a `fn` type that is equivalent in every way for being
    /// unsafe.
2192 2193
    pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
        assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
M
Mark Rousskov 已提交
2194
        self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
2195 2196
    }

2197 2198 2199 2200 2201 2202 2203 2204 2205 2206
    /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
    /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
    pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
        self.super_traits_of(trait_def_id).any(|trait_did| {
            self.associated_items(trait_did)
                .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
                .is_some()
        })
    }

B
Bruce Mitchener 已提交
2207
    /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally)
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221
    /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
    /// to identify which traits may define a given associated type to help avoid cycle errors.
    /// Returns a `DefId` iterator.
    fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
        let mut set = FxHashSet::default();
        let mut stack = vec![trait_def_id];

        set.insert(trait_def_id);

        iter::from_fn(move || -> Option<DefId> {
            let trait_did = stack.pop()?;
            let generic_predicates = self.super_predicates_of(trait_did);

            for (predicate, _) in generic_predicates.predicates {
D
Deadbeef 已提交
2222
                if let ty::PredicateKind::Trait(data) = predicate.kind().skip_binder() {
2223 2224 2225 2226 2227 2228 2229 2230 2231 2232
                    if set.insert(data.def_id()) {
                        stack.push(data.def_id());
                    }
                }
            }

            Some(trait_did)
        })
    }

2233 2234 2235 2236
    /// Given a closure signature, returns an equivalent fn signature. Detuples
    /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
    /// you would get a `fn(u32, i32)`.
    /// `unsafety` determines the unsafety of the fn signature. If you pass
T
Taiki Endo 已提交
2237 2238 2239
    /// `hir::Unsafety::Unsafe` in the previous example, then you would get
    /// an `unsafe fn (u32, i32)`.
    /// It cannot convert a closure that requires unsafe.
2240 2241 2242 2243 2244 2245
    pub fn signature_unclosure(
        self,
        sig: PolyFnSig<'tcx>,
        unsafety: hir::Unsafety,
    ) -> PolyFnSig<'tcx> {
        sig.map_bound(|s| {
L
LeSeulArtichaut 已提交
2246
            let params_iter = match s.inputs()[0].kind() {
L
lcnr 已提交
2247
                ty::Tuple(params) => params.into_iter(),
2248 2249
                _ => bug!(),
            };
M
Mark Rousskov 已提交
2250
            self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
2251
        })
2252 2253
    }

2254 2255 2256 2257 2258 2259 2260
    /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
    /// `*r == kind`.
    #[inline]
    pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind) -> Region<'tcx> {
        if *r == kind { r } else { self.mk_region(kind) }
    }

M
Mark Rousskov 已提交
2261
    #[allow(rustc::usage_of_ty_tykind)]
2262
    #[inline]
2263
    pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
2264
        self.interners.intern_ty(st, self.sess, &self.gcx.untracked_resolutions)
2265 2266
    }

2267
    #[inline]
J
Jack Huey 已提交
2268
    pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
2269
        self.interners.intern_predicate(binder)
2270 2271
    }

B
Bastian Kauschke 已提交
2272 2273 2274 2275
    #[inline]
    pub fn reuse_or_mk_predicate(
        self,
        pred: Predicate<'tcx>,
J
Jack Huey 已提交
2276
        binder: Binder<'tcx, PredicateKind<'tcx>>,
B
Bastian Kauschke 已提交
2277
    ) -> Predicate<'tcx> {
J
Jack Huey 已提交
2278
        if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
B
Bastian Kauschke 已提交
2279 2280
    }

2281
    pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
2282
        match tm {
2283 2284 2285 2286 2287 2288
            IntTy::Isize => self.types.isize,
            IntTy::I8 => self.types.i8,
            IntTy::I16 => self.types.i16,
            IntTy::I32 => self.types.i32,
            IntTy::I64 => self.types.i64,
            IntTy::I128 => self.types.i128,
2289 2290 2291
        }
    }

2292
    pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> {
2293
        match tm {
2294 2295 2296 2297 2298 2299
            UintTy::Usize => self.types.usize,
            UintTy::U8 => self.types.u8,
            UintTy::U16 => self.types.u16,
            UintTy::U32 => self.types.u32,
            UintTy::U64 => self.types.u64,
            UintTy::U128 => self.types.u128,
2300 2301 2302
        }
    }

2303
    pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> {
2304
        match tm {
2305 2306
            FloatTy::F32 => self.types.f32,
            FloatTy::F64 => self.types.f64,
2307 2308 2309
        }
    }

2310
    #[inline]
2311
    pub fn mk_static_str(self) -> Ty<'tcx> {
B
Bastian Kauschke 已提交
2312
        self.mk_imm_ref(self.lifetimes.re_static, self.types.str_)
2313 2314
    }

2315
    #[inline]
2316
    pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
2317
        // Take a copy of substs so that we own the vectors inside.
V
varkor 已提交
2318
        self.mk_ty(Adt(def, substs))
2319 2320
    }

2321
    #[inline]
P
Paul Lietar 已提交
2322
    pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
V
varkor 已提交
2323
        self.mk_ty(Foreign(def_id))
P
Paul Lietar 已提交
2324 2325
    }

2326 2327
    fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
        let adt_def = self.adt_def(wrapper_def_id);
M
Mark Rousskov 已提交
2328 2329
        let substs =
            InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind {
2330
                GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
2331
                GenericParamDefKind::Type { has_default, .. } => {
2332
                    if param.index == 0 {
2333
                        ty_param.into()
2334
                    } else {
2335
                        assert!(has_default);
2336
                        self.type_of(param.def_id).subst(self, substs).into()
V
varkor 已提交
2337 2338
                    }
                }
M
Mark Rousskov 已提交
2339
            });
V
varkor 已提交
2340
        self.mk_ty(Adt(adt_def, substs))
2341 2342
    }

2343 2344
    #[inline]
    pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
2345
        let def_id = self.require_lang_item(LangItem::OwnedBox, None);
2346 2347 2348
        self.mk_generic_adt(def_id, ty)
    }

2349
    #[inline]
2350
    pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
1
12101111 已提交
2351 2352
        let def_id = self.lang_items().require(item).ok()?;
        Some(self.mk_generic_adt(def_id, ty))
2353 2354
    }

2355 2356 2357 2358 2359 2360
    #[inline]
    pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
        let def_id = self.get_diagnostic_item(name)?;
        Some(self.mk_generic_adt(def_id, ty))
    }

2361 2362
    #[inline]
    pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
2363
        let def_id = self.require_lang_item(LangItem::MaybeUninit, None);
2364 2365 2366
        self.mk_generic_adt(def_id, ty)
    }

2367
    #[inline]
2368
    pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
V
varkor 已提交
2369
        self.mk_ty(RawPtr(tm))
2370 2371
    }

2372
    #[inline]
N
Niko Matsakis 已提交
2373
    pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
V
varkor 已提交
2374
        self.mk_ty(Ref(r, tm.ty, tm.mutbl))
2375 2376
    }

2377
    #[inline]
N
Niko Matsakis 已提交
2378
    pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2379
        self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
2380 2381
    }

2382
    #[inline]
N
Niko Matsakis 已提交
2383
    pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2384
        self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
2385 2386
    }

2387
    #[inline]
2388
    pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
2389
        self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut })
2390 2391
    }

2392
    #[inline]
2393
    pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
2394
        self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not })
2395 2396
    }

2397
    #[inline]
2398
    pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
M
Mark Rousskov 已提交
2399
        self.mk_ty(Array(ty, ty::Const::from_usize(self, n)))
2400 2401
    }

2402
    #[inline]
2403
    pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
V
varkor 已提交
2404
        self.mk_ty(Slice(ty))
2405 2406
    }

2407
    #[inline]
A
Andrew Cann 已提交
2408
    pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
L
lcnr 已提交
2409
        self.mk_ty(Tuple(self.intern_type_list(&ts)))
2410 2411
    }

A
Andrew Cann 已提交
2412
    pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
L
lcnr 已提交
2413
        iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts))))
2414 2415
    }

2416
    #[inline]
K
kenta7777 已提交
2417
    pub fn mk_unit(self) -> Ty<'tcx> {
2418
        self.types.unit
2419 2420
    }

2421
    #[inline]
2422
    pub fn mk_diverging_default(self) -> Ty<'tcx> {
M
Mark Rousskov 已提交
2423
        if self.features().never_type_fallback { self.types.never } else { self.types.unit }
2424 2425
    }

2426
    #[inline]
M
Mark Rousskov 已提交
2427
    pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
V
varkor 已提交
2428
        self.mk_ty(FnDef(def_id, substs))
2429 2430
    }

2431
    #[inline]
2432
    pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
V
varkor 已提交
2433
        self.mk_ty(FnPtr(fty))
2434 2435
    }

2436
    #[inline]
2437 2438
    pub fn mk_dynamic(
        self,
J
Jack Huey 已提交
2439
        obj: &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>,
M
Mark Rousskov 已提交
2440
        reg: ty::Region<'tcx>,
2441
    ) -> Ty<'tcx> {
V
varkor 已提交
2442
        self.mk_ty(Dynamic(obj, reg))
2443 2444
    }

2445
    #[inline]
M
Mark Rousskov 已提交
2446 2447 2448
    pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
        self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
    }
2449

2450
    #[inline]
M
Mark Rousskov 已提交
2451
    pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> {
V
varkor 已提交
2452
        self.mk_ty(Closure(closure_id, closure_substs))
2453 2454
    }

2455
    #[inline]
M
Mark Rousskov 已提交
2456 2457 2458 2459 2460 2461
    pub fn mk_generator(
        self,
        id: DefId,
        generator_substs: SubstsRef<'tcx>,
        movability: hir::Movability,
    ) -> Ty<'tcx> {
V
varkor 已提交
2462
        self.mk_ty(Generator(id, generator_substs, movability))
J
John Kåre Alsaker 已提交
2463 2464
    }

2465
    #[inline]
J
Jack Huey 已提交
2466
    pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
V
varkor 已提交
2467
        self.mk_ty(GeneratorWitness(types))
2468 2469
    }

2470
    #[inline]
V
varkor 已提交
2471
    pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
G
Gabriel Smith 已提交
2472
        self.mk_ty_infer(TyVar(v))
2473 2474
    }

V
varkor 已提交
2475
    #[inline]
N
Nicholas Nethercote 已提交
2476 2477
    pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
        self.mk_const(ty::ConstS { val: ty::ConstKind::Infer(InferConst::Var(v)), ty })
V
varkor 已提交
2478 2479
    }

2480
    #[inline]
2481
    pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
G
Gabriel Smith 已提交
2482
        self.mk_ty_infer(IntVar(v))
2483 2484
    }

2485
    #[inline]
2486
    pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
G
Gabriel Smith 已提交
2487
        self.mk_ty_infer(FloatVar(v))
2488 2489
    }

2490
    #[inline]
G
Gabriel Smith 已提交
2491
    pub fn mk_ty_infer(self, it: InferTy) -> Ty<'tcx> {
V
varkor 已提交
2492
        self.mk_ty(Infer(it))
2493 2494
    }

G
Gabriel Smith 已提交
2495
    #[inline]
N
Nicholas Nethercote 已提交
2496 2497
    pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> {
        self.mk_const(ty::ConstS { val: ty::ConstKind::Infer(ic), ty })
G
Gabriel Smith 已提交
2498 2499
    }

2500
    #[inline]
2501
    pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
2502
        self.mk_ty(Param(ParamTy { index, name }))
2503 2504
    }

V
varkor 已提交
2505
    #[inline]
N
Nicholas Nethercote 已提交
2506 2507
    pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> Const<'tcx> {
        self.mk_const(ty::ConstS { val: ty::ConstKind::Param(ParamConst { index, name }), ty })
V
varkor 已提交
2508 2509
    }

2510
    pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
V
varkor 已提交
2511 2512 2513 2514
        match param.kind {
            GenericParamDefKind::Lifetime => {
                self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
            }
V
varkor 已提交
2515
            GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
2516
            GenericParamDefKind::Const { .. } => {
V
varkor 已提交
2517 2518
                self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into()
            }
V
varkor 已提交
2519
        }
2520
    }
2521

2522
    #[inline]
C
csmoe 已提交
2523
    pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
2524
        self.mk_ty(Opaque(def_id, substs))
2525 2526
    }

2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537
    pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
        self.mk_place_elem(place, PlaceElem::Field(f, ty))
    }

    pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
        self.mk_place_elem(place, PlaceElem::Deref)
    }

    pub fn mk_place_downcast(
        self,
        place: Place<'tcx>,
2538
        adt_def: AdtDef<'tcx>,
2539 2540 2541 2542
        variant_index: VariantIdx,
    ) -> Place<'tcx> {
        self.mk_place_elem(
            place,
2543
            PlaceElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index),
2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565
        )
    }

    pub fn mk_place_downcast_unnamed(
        self,
        place: Place<'tcx>,
        variant_index: VariantIdx,
    ) -> Place<'tcx> {
        self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
    }

    pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
        self.mk_place_elem(place, PlaceElem::Index(index))
    }

    /// This method copies `Place`'s projection, add an element and reintern it. Should not be used
    /// to build a full `Place` it's just a convenient way to grab a projection and modify it in
    /// flight.
    pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
        let mut projection = place.projection.to_vec();
        projection.push(elem);

2566
        Place { local: place.local, projection: self.intern_place_elems(&projection) }
2567 2568
    }

J
Jack Huey 已提交
2569
    pub fn intern_poly_existential_predicates(
M
Mark Rousskov 已提交
2570
        self,
J
Jack Huey 已提交
2571 2572
        eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>],
    ) -> &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
2573
        assert!(!eps.is_empty());
J
Jack Huey 已提交
2574 2575 2576 2577 2578 2579
        assert!(
            eps.array_windows()
                .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
                    != Ordering::Greater)
        );
        self._intern_poly_existential_predicates(eps)
2580 2581
    }

M
Mark Rousskov 已提交
2582
    pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
2583 2584 2585
        // FIXME consider asking the input slice to be sorted to avoid
        // re-interning permutations, in which case that would be asserted
        // here.
2586
        if preds.is_empty() {
2587
            // The macro-generated method below asserts we don't intern an empty slice.
V
varkor 已提交
2588
            List::empty()
2589 2590 2591 2592 2593
        } else {
            self._intern_predicates(preds)
        }
    }

V
varkor 已提交
2594
    pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
        if ts.is_empty() {
            List::empty()
        } else {
            // Actually intern type lists as lists of `GenericArg`s.
            //
            // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
            // as explained in ty_slice_as_generic_arg`. With this,
            // we guarantee that even when transmuting between `List<Ty<'tcx>>`
            // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
            // lists is upheld.
            let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts));
            substs.try_as_type_list().unwrap()
        }
2608 2609
    }

2610
    pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
2611
        if ts.is_empty() { List::empty() } else { self._intern_substs(ts) }
2612 2613
    }

2614
    pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
2615
        if ps.is_empty() { List::empty() } else { self._intern_projs(ps) }
2616 2617
    }

2618
    pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
2619
        if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
2620 2621
    }

V
varkor 已提交
2622 2623 2624 2625
    pub fn intern_canonical_var_infos(
        self,
        ts: &[CanonicalVarInfo<'tcx>],
    ) -> CanonicalVarInfos<'tcx> {
2626
        if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
2627 2628
    }

J
Jack Huey 已提交
2629 2630 2631 2632 2633 2634 2635
    pub fn intern_bound_variable_kinds(
        self,
        ts: &[ty::BoundVariableKind],
    ) -> &'tcx List<ty::BoundVariableKind> {
        if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
    }

M
Mark Rousskov 已提交
2636 2637 2638 2639 2640 2641 2642 2643
    pub fn mk_fn_sig<I>(
        self,
        inputs: I,
        output: I::Item,
        c_variadic: bool,
        unsafety: hir::Unsafety,
        abi: abi::Abi,
    ) -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
2644 2645
    where
        I: Iterator<Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>,
2646 2647 2648
    {
        inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
            inputs_and_output: self.intern_type_list(xs),
M
Mark Rousskov 已提交
2649 2650 2651
            c_variadic,
            unsafety,
            abi,
2652 2653 2654
        })
    }

J
Jack Huey 已提交
2655 2656
    pub fn mk_poly_existential_predicates<
        I: InternAs<
J
Jack Huey 已提交
2657 2658
            [ty::Binder<'tcx, ExistentialPredicate<'tcx>>],
            &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>,
J
Jack Huey 已提交
2659
        >,
M
Mark Rousskov 已提交
2660 2661 2662 2663
    >(
        self,
        iter: I,
    ) -> I::Output {
J
Jack Huey 已提交
2664
        iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
2665 2666
    }

M
Mark Rousskov 已提交
2667 2668 2669 2670
    pub fn mk_predicates<I: InternAs<[Predicate<'tcx>], &'tcx List<Predicate<'tcx>>>>(
        self,
        iter: I,
    ) -> I::Output {
2671 2672 2673
        iter.intern_with(|xs| self.intern_predicates(xs))
    }

M
Mark Rousskov 已提交
2674
    pub fn mk_type_list<I: InternAs<[Ty<'tcx>], &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output {
2675 2676 2677
        iter.intern_with(|xs| self.intern_type_list(xs))
    }

M
Mark Rousskov 已提交
2678 2679 2680 2681
    pub fn mk_substs<I: InternAs<[GenericArg<'tcx>], &'tcx List<GenericArg<'tcx>>>>(
        self,
        iter: I,
    ) -> I::Output {
2682 2683 2684
        iter.intern_with(|xs| self.intern_substs(xs))
    }

M
Mark Rousskov 已提交
2685 2686 2687 2688
    pub fn mk_place_elems<I: InternAs<[PlaceElem<'tcx>], &'tcx List<PlaceElem<'tcx>>>>(
        self,
        iter: I,
    ) -> I::Output {
S
Santiago Pastorino 已提交
2689 2690 2691
        iter.intern_with(|xs| self.intern_place_elems(xs))
    }

M
Mark Rousskov 已提交
2692
    pub fn mk_substs_trait(self, self_ty: Ty<'tcx>, rest: &[GenericArg<'tcx>]) -> SubstsRef<'tcx> {
2693
        self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned()))
2694
    }
2695

J
Jack Huey 已提交
2696 2697 2698 2699 2700 2701 2702 2703 2704
    pub fn mk_bound_variable_kinds<
        I: InternAs<[ty::BoundVariableKind], &'tcx List<ty::BoundVariableKind>>,
    >(
        self,
        iter: I,
    ) -> I::Output {
        iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
    }

2705 2706
    /// Walks upwards from `id` to find a node which might change lint levels with attributes.
    /// It stops at `bound` and just returns it if reached.
M
Mazdak Farrokhzad 已提交
2707 2708
    pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
        let hir = self.hir();
2709 2710 2711
        loop {
            if id == bound {
                return bound;
2712
            }
M
Mazdak Farrokhzad 已提交
2713

2714
            if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
2715 2716
                return id;
            }
M
Mazdak Farrokhzad 已提交
2717
            let next = hir.get_parent_node(id);
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727
            if next == id {
                bug!("lint traversal reached the root of the crate");
            }
            id = next;
        }
    }

    pub fn lint_level_at_node(
        self,
        lint: &'static Lint,
M
Mark Rousskov 已提交
2728
        mut id: hir::HirId,
P
pierwill 已提交
2729
    ) -> (Level, LintLevelSource) {
C
Camille GILLOT 已提交
2730
        let sets = self.lint_levels(());
2731 2732
        loop {
            if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
M
Mark Rousskov 已提交
2733
                return pair;
2734
            }
2735
            let next = self.hir().get_parent_node(id);
2736 2737 2738 2739 2740
            if next == id {
                bug!("lint traversal reached the root of the crate");
            }
            id = next;
        }
2741 2742
    }

2743
    pub fn struct_span_lint_hir(
M
Mark Rousskov 已提交
2744 2745 2746
        self,
        lint: &'static Lint,
        hir_id: HirId,
2747
        span: impl Into<MultiSpan>,
2748
        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
J
jumbatm 已提交
2749
    ) {
L
ljedrz 已提交
2750
        let (level, src) = self.lint_level_at_node(lint, hir_id);
J
jumbatm 已提交
2751
        struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
2752 2753
    }

M
Mark Rousskov 已提交
2754 2755 2756 2757
    pub fn struct_lint_node(
        self,
        lint: &'static Lint,
        id: HirId,
2758
        decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
J
jumbatm 已提交
2759
    ) {
2760
        let (level, src) = self.lint_level_at_node(lint, id);
J
jumbatm 已提交
2761
        struct_lint_level(self.sess, lint, level, src, None, decorate);
2762
    }
A
Alex Crichton 已提交
2763

C
Camille GILLOT 已提交
2764 2765 2766 2767
    pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
        let map = self.in_scope_traits_map(id.owner)?;
        let candidates = map.get(&id.local_id)?;
        Some(&*candidates)
A
Alex Crichton 已提交
2768 2769 2770
    }

    pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
J
Jack Huey 已提交
2771
        debug!(?id, "named_region");
2772
        self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
A
Alex Crichton 已提交
2773 2774
    }

2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
    pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
        self.mk_bound_variable_kinds(
            self.late_bound_vars_map(id.owner)
                .and_then(|map| map.get(&id.local_id).cloned())
                .unwrap_or_else(|| {
                    bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
                })
                .iter(),
        )
    }
B
b-naber 已提交
2785

2786 2787
    pub fn lifetime_scope(self, id: HirId) -> Option<&'tcx LifetimeScopeForPath> {
        self.lifetime_scope_map(id.owner).as_ref().and_then(|map| map.get(&id.local_id))
B
b-naber 已提交
2788
    }
D
Deadbeef 已提交
2789 2790 2791 2792 2793 2794 2795 2796 2797

    /// Whether the `def_id` counts as const fn in the current crate, considering all active
    /// feature gates
    pub fn is_const_fn(self, def_id: DefId) -> bool {
        if self.is_const_fn_raw(def_id) {
            match self.lookup_const_stability(def_id) {
                Some(stability) if stability.level.is_unstable() => {
                    // has a `rustc_const_unstable` attribute, check whether the user enabled the
                    // corresponding feature gate.
2798 2799 2800 2801
                    self.features()
                        .declared_lib_features
                        .iter()
                        .any(|&(sym, _)| sym == stability.feature)
D
Deadbeef 已提交
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811
                }
                // functions without const stability are either stable user written
                // const fn or the user is using feature gates and we thus don't
                // care what they do
                _ => true,
            }
        } else {
            false
        }
    }
2812
}
2813

2814
impl<'tcx> TyCtxtAt<'tcx> {
J
Joshua Nelson 已提交
2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828
    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
    #[track_caller]
    pub fn ty_error(self) -> Ty<'tcx> {
        self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
    }

    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
    /// ensure it gets used.
    #[track_caller]
    pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
        self.tcx.ty_error_with_message(self.span, msg)
    }
}

2829 2830
pub trait InternAs<T: ?Sized, R> {
    type Output;
E
est31 已提交
2831
    fn intern_with<F>(self, f: F) -> Self::Output
M
Mark Rousskov 已提交
2832 2833
    where
        F: FnOnce(&T) -> R;
2834 2835 2836
}

impl<I, T, R, E> InternAs<[T], R> for I
M
Mark Rousskov 已提交
2837 2838 2839 2840
where
    E: InternIteratorElement<T, R>,
    I: Iterator<Item = E>,
{
2841 2842
    type Output = E::Output;
    fn intern_with<F>(self, f: F) -> Self::Output
M
Mark Rousskov 已提交
2843 2844 2845
    where
        F: FnOnce(&[T]) -> R,
    {
2846 2847 2848 2849 2850 2851
        E::intern_with(self, f)
    }
}

pub trait InternIteratorElement<T, R>: Sized {
    type Output;
M
Mark Rousskov 已提交
2852
    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output;
2853 2854 2855 2856
}

impl<T, R> InternIteratorElement<T, R> for T {
    type Output = R;
2857 2858 2859 2860 2861 2862
    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
        mut iter: I,
        f: F,
    ) -> Self::Output {
        // This code is hot enough that it's worth specializing for the most
        // common length lists, to avoid the overhead of `SmallVec` creation.
N
Nicholas Nethercote 已提交
2863 2864 2865
        // Lengths 0, 1, and 2 typically account for ~95% of cases. If
        // `size_hint` is incorrect a panic will occur via an `unwrap` or an
        // `assert`.
2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883
        match iter.size_hint() {
            (0, Some(0)) => {
                assert!(iter.next().is_none());
                f(&[])
            }
            (1, Some(1)) => {
                let t0 = iter.next().unwrap();
                assert!(iter.next().is_none());
                f(&[t0])
            }
            (2, Some(2)) => {
                let t0 = iter.next().unwrap();
                let t1 = iter.next().unwrap();
                assert!(iter.next().is_none());
                f(&[t0, t1])
            }
            _ => f(&iter.collect::<SmallVec<[_; 8]>>()),
        }
2884 2885 2886
    }
}

2887
impl<'a, T, R> InternIteratorElement<T, R> for &'a T
M
Mark Rousskov 已提交
2888 2889
where
    T: Clone + 'a,
2890 2891
{
    type Output = R;
M
Mark Rousskov 已提交
2892
    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
2893
        // This code isn't hot.
2894
        f(&iter.cloned().collect::<SmallVec<[_; 8]>>())
2895 2896 2897
    }
}

2898 2899
impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
    type Output = Result<R, E>;
M
Mark Rousskov 已提交
2900 2901 2902 2903
    fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
        mut iter: I,
        f: F,
    ) -> Self::Output {
2904 2905
        // This code is hot enough that it's worth specializing for the most
        // common length lists, to avoid the overhead of `SmallVec` creation.
N
Nicholas Nethercote 已提交
2906 2907 2908 2909
        // Lengths 0, 1, and 2 typically account for ~95% of cases. If
        // `size_hint` is incorrect a panic will occur via an `unwrap` or an
        // `assert`, unless a failure happens first, in which case the result
        // will be an error anyway.
2910
        Ok(match iter.size_hint() {
2911 2912 2913 2914
            (0, Some(0)) => {
                assert!(iter.next().is_none());
                f(&[])
            }
2915
            (1, Some(1)) => {
2916 2917 2918
                let t0 = iter.next().unwrap()?;
                assert!(iter.next().is_none());
                f(&[t0])
2919 2920 2921 2922
            }
            (2, Some(2)) => {
                let t0 = iter.next().unwrap()?;
                let t1 = iter.next().unwrap()?;
2923
                assert!(iter.next().is_none());
2924 2925
                f(&[t0, t1])
            }
M
Mark Rousskov 已提交
2926
            _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?),
2927
        })
2928 2929
    }
}
2930

2931 2932 2933 2934 2935 2936
// We are comparing types with different invariant lifetimes, so `ptr::eq`
// won't work for us.
fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
    t as *const () == u as *const ()
}

2937
pub fn provide(providers: &mut ty::query::Providers) {
C
Camille GILLOT 已提交
2938
    providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
2939 2940
    providers.module_reexports =
        |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
2941 2942 2943 2944
    providers.crate_name = |tcx, id| {
        assert_eq!(id, LOCAL_CRATE);
        tcx.crate_name
    };
C
Camille GILLOT 已提交
2945 2946 2947 2948 2949 2950 2951
    providers.maybe_unused_trait_import =
        |tcx, id| tcx.resolutions(()).maybe_unused_trait_imports.contains(&id);
    providers.maybe_unused_extern_crates =
        |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
    providers.names_imported_by_glob_use = |tcx, id| {
        tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
    };
2952

C
Camille GILLOT 已提交
2953 2954
    providers.extern_mod_stmt_cnum =
        |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
2955
    providers.output_filenames = |tcx, ()| &tcx.output_filenames;
C
Camille GILLOT 已提交
2956
    providers.features_query = |tcx, ()| tcx.sess.features_untracked();
2957 2958
    providers.is_panic_runtime = |tcx, cnum| {
        assert_eq!(cnum, LOCAL_CRATE);
2959
        tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
2960 2961 2962
    };
    providers.is_compiler_builtins = |tcx, cnum| {
        assert_eq!(cnum, LOCAL_CRATE);
2963
        tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins)
2964
    };
M
Mark Rousskov 已提交
2965 2966 2967 2968 2969
    providers.has_panic_handler = |tcx, cnum| {
        assert_eq!(cnum, LOCAL_CRATE);
        // We want to check if the panic handler was defined in this crate
        tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
    };
2970
}