rustc_middle/ty/
typeck_results.rs

1use std::collections::hash_map::Entry;
2use std::hash::Hash;
3use std::iter;
4
5use rustc_abi::{FieldIdx, VariantIdx};
6use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
7use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
8use rustc_errors::ErrorGuaranteed;
9use rustc_hir::def::{DefKind, Res};
10use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
11use rustc_hir::hir_id::OwnerId;
12use rustc_hir::{
13    self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
14};
15use rustc_index::IndexVec;
16use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
17use rustc_session::Session;
18use rustc_span::Span;
19
20use super::RvalueScopes;
21use crate::hir::place::Place as HirPlace;
22use crate::infer::canonical::Canonical;
23use crate::mir::FakeReadCause;
24use crate::traits::ObligationCause;
25use crate::ty::{
26    self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs,
27    GenericArgsRef, Ty, UserArgs, tls,
28};
29
30#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
31pub struct TypeckResults<'tcx> {
32    /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
33    pub hir_owner: OwnerId,
34
35    /// Resolved definitions for `<T>::X` associated paths and
36    /// method calls, including those of overloaded operators.
37    type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
38
39    /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
40    /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
41    /// about the field you also need definition of the variant to which the field
42    /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
43    field_indices: ItemLocalMap<FieldIdx>,
44
45    /// Stores the types for various nodes in the AST. Note that this table
46    /// is not guaranteed to be populated outside inference. See
47    /// typeck::check::fn_ctxt for details.
48    node_types: ItemLocalMap<Ty<'tcx>>,
49
50    /// Stores the type parameters which were instantiated to obtain the type
51    /// of this node. This only applies to nodes that refer to entities
52    /// parameterized by type parameters, such as generic fns, types, or
53    /// other items.
54    node_args: ItemLocalMap<GenericArgsRef<'tcx>>,
55
56    /// This will either store the canonicalized types provided by the user
57    /// or the generic parameters that the user explicitly gave (if any) attached
58    /// to `id`. These will not include any inferred values. The canonical form
59    /// is used to capture things like `_` or other unspecified values.
60    ///
61    /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
62    /// canonical generic parameters would include only `for<X> { Vec<X> }`.
63    ///
64    /// See also `AscribeUserType` statement in MIR.
65    user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
66
67    /// Stores the canonicalized types provided by the user. See also
68    /// `AscribeUserType` statement in MIR.
69    pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
70
71    adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
72
73    /// Stores the actual binding mode for all instances of [`BindingMode`].
74    pat_binding_modes: ItemLocalMap<BindingMode>,
75
76    /// Top-level patterns incompatible with Rust 2024's match ergonomics. These will be translated
77    /// to a form valid in all Editions, either as a lint diagnostic or hard error.
78    rust_2024_migration_desugared_pats: ItemLocalMap<Rust2024IncompatiblePatInfo>,
79
80    /// Stores the types which were implicitly dereferenced in pattern binding modes or deref
81    /// patterns for later usage in THIR lowering. For example,
82    ///
83    /// ```
84    /// match &&Some(5i32) {
85    ///     Some(n) => {},
86    ///     _ => {},
87    /// }
88    /// ```
89    /// leads to a `vec![&&Option<i32>, &Option<i32>]` and
90    ///
91    /// ```
92    /// #![feature(deref_patterns)]
93    /// match &Box::new(Some(5i32)) {
94    ///     Some(n) => {},
95    ///     _ => {},
96    /// }
97    /// ```
98    /// leads to a `vec![&Box<Option<i32>>, Box<Option<i32>>]`. Empty vectors are not stored.
99    ///
100    /// See:
101    /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
102    pat_adjustments: ItemLocalMap<Vec<ty::adjustment::PatAdjustment<'tcx>>>,
103
104    /// Set of reference patterns that match against a match-ergonomics inserted reference
105    /// (as opposed to against a reference in the scrutinee type).
106    skipped_ref_pats: ItemLocalSet,
107
108    /// Records the reasons that we picked the kind of each closure;
109    /// not all closures are present in the map.
110    closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
111
112    /// For each fn, records the "liberated" types of its arguments
113    /// and return type. Liberated means that all bound regions
114    /// (including late-bound regions) are replaced with free
115    /// equivalents. This table is not used in codegen (since regions
116    /// are erased there) and hence is not serialized to metadata.
117    ///
118    /// This table also contains the "revealed" values for any `impl Trait`
119    /// that appear in the signature and whose values are being inferred
120    /// by this function.
121    ///
122    /// # Example
123    ///
124    /// ```rust
125    /// # use std::fmt::Debug;
126    /// fn foo(x: &u32) -> impl Debug { *x }
127    /// ```
128    ///
129    /// The function signature here would be:
130    ///
131    /// ```ignore (illustrative)
132    /// for<'a> fn(&'a u32) -> Foo
133    /// ```
134    ///
135    /// where `Foo` is an opaque type created for this function.
136    ///
137    ///
138    /// The *liberated* form of this would be
139    ///
140    /// ```ignore (illustrative)
141    /// fn(&'a u32) -> u32
142    /// ```
143    ///
144    /// Note that `'a` is not bound (it would be an `ReLateParam`) and
145    /// that the `Foo` opaque type is replaced by its hidden type.
146    liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
147
148    /// For each FRU expression, record the normalized types of the fields
149    /// of the struct - this is needed because it is non-trivial to
150    /// normalize while preserving regions. This table is used only in
151    /// MIR construction and hence is not serialized to metadata.
152    fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
153
154    /// For every coercion cast we add the HIR node ID of the cast
155    /// expression to this set.
156    coercion_casts: ItemLocalSet,
157
158    /// Set of trait imports actually used in the method resolution.
159    /// This is used for warning unused imports.
160    pub used_trait_imports: UnordSet<LocalDefId>,
161
162    /// If any errors occurred while type-checking this body,
163    /// this field will be set to `Some(ErrorGuaranteed)`.
164    pub tainted_by_errors: Option<ErrorGuaranteed>,
165
166    /// All the opaque types that have hidden types set by this function.
167    /// We also store the type here, so that the compiler can use it as a hint
168    /// for figuring out hidden types, even if they are only set in dead code
169    /// (which doesn't show up in MIR).
170    pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
171
172    /// Tracks the minimum captures required for a closure;
173    /// see `MinCaptureInformationMap` for more details.
174    pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
175
176    /// Tracks the fake reads required for a closure and the reason for the fake read.
177    /// When performing pattern matching for closures, there are times we don't end up
178    /// reading places that are mentioned in a closure (because of _ patterns). However,
179    /// to ensure the places are initialized, we introduce fake reads.
180    /// Consider these two examples:
181    /// ```ignore (discriminant matching with only wildcard arm)
182    /// let x: u8;
183    /// let c = || match x { _ => () };
184    /// ```
185    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
186    /// want to capture it. However, we do still want an error here, because `x` should have
187    /// to be initialized at the point where c is created. Therefore, we add a "fake read"
188    /// instead.
189    /// ```ignore (destructured assignments)
190    /// let c = || {
191    ///     let (t1, t2) = t;
192    /// }
193    /// ```
194    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
195    /// we never capture `t`. This becomes an issue when we build MIR as we require
196    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
197    /// issue by fake reading `t`.
198    pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, HirId)>>,
199
200    /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
201    /// by applying extended parameter rules.
202    /// Details may be found in `rustc_hir_analysis::check::rvalue_scopes`.
203    pub rvalue_scopes: RvalueScopes,
204
205    /// Stores the predicates that apply on coroutine witness types.
206    /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
207    pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
208
209    /// Goals proven during HIR typeck which may be potentially region dependent.
210    ///
211    /// Borrowck *uniquifies* regions which may cause these goal to be ambiguous in MIR
212    /// type check. We ICE if goals fail in borrowck to detect bugs during MIR building or
213    /// missed checks in HIR typeck. To avoid ICE due to region dependence we store all
214    /// goals which may be region dependent and reprove them in case borrowck encounters
215    /// an error.
216    pub potentially_region_dependent_goals:
217        FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
218
219    /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
220    /// on closure size.
221    pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
222
223    /// Stores the types involved in calls to `transmute` intrinsic. These are meant to be checked
224    /// outside of typeck and borrowck to avoid cycles with opaque types and coroutine layout
225    /// computation.
226    pub transmutes_to_check: Vec<(Ty<'tcx>, Ty<'tcx>, HirId)>,
227
228    /// Container types and field indices of `offset_of!` expressions
229    offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
230}
231
232impl<'tcx> TypeckResults<'tcx> {
233    pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
234        TypeckResults {
235            hir_owner,
236            type_dependent_defs: Default::default(),
237            field_indices: Default::default(),
238            user_provided_types: Default::default(),
239            user_provided_sigs: Default::default(),
240            node_types: Default::default(),
241            node_args: Default::default(),
242            adjustments: Default::default(),
243            pat_binding_modes: Default::default(),
244            pat_adjustments: Default::default(),
245            rust_2024_migration_desugared_pats: Default::default(),
246            skipped_ref_pats: Default::default(),
247            closure_kind_origins: Default::default(),
248            liberated_fn_sigs: Default::default(),
249            fru_field_types: Default::default(),
250            coercion_casts: Default::default(),
251            used_trait_imports: Default::default(),
252            tainted_by_errors: None,
253            concrete_opaque_types: Default::default(),
254            closure_min_captures: Default::default(),
255            closure_fake_reads: Default::default(),
256            rvalue_scopes: Default::default(),
257            coroutine_stalled_predicates: Default::default(),
258            potentially_region_dependent_goals: Default::default(),
259            closure_size_eval: Default::default(),
260            transmutes_to_check: Default::default(),
261            offset_of_data: Default::default(),
262        }
263    }
264
265    /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
266    pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
267        match *qpath {
268            hir::QPath::Resolved(_, path) => path.res,
269            hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
270                .type_dependent_def(id)
271                .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
272        }
273    }
274
275    pub fn type_dependent_defs(
276        &self,
277    ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
278        LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
279    }
280
281    pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
282        validate_hir_id_for_typeck_results(self.hir_owner, id);
283        self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
284    }
285
286    pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
287        self.type_dependent_def(id).map(|(_, def_id)| def_id)
288    }
289
290    pub fn type_dependent_defs_mut(
291        &mut self,
292    ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
293        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
294    }
295
296    pub fn field_indices(&self) -> LocalTableInContext<'_, FieldIdx> {
297        LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
298    }
299
300    pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx> {
301        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
302    }
303
304    pub fn field_index(&self, id: HirId) -> FieldIdx {
305        self.field_indices().get(id).cloned().expect("no index for a field")
306    }
307
308    pub fn opt_field_index(&self, id: HirId) -> Option<FieldIdx> {
309        self.field_indices().get(id).cloned()
310    }
311
312    pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
313        LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
314    }
315
316    pub fn user_provided_types_mut(
317        &mut self,
318    ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
319        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
320    }
321
322    pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
323        LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
324    }
325
326    pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
327        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
328    }
329
330    pub fn node_type(&self, id: HirId) -> Ty<'tcx> {
331        self.node_type_opt(id).unwrap_or_else(|| {
332            bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir_id_to_string(id)))
333        })
334    }
335
336    pub fn node_type_opt(&self, id: HirId) -> Option<Ty<'tcx>> {
337        validate_hir_id_for_typeck_results(self.hir_owner, id);
338        self.node_types.get(&id.local_id).cloned()
339    }
340
341    pub fn node_args_mut(&mut self) -> LocalTableInContextMut<'_, GenericArgsRef<'tcx>> {
342        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_args }
343    }
344
345    pub fn node_args(&self, id: HirId) -> GenericArgsRef<'tcx> {
346        validate_hir_id_for_typeck_results(self.hir_owner, id);
347        self.node_args.get(&id.local_id).cloned().unwrap_or_else(|| GenericArgs::empty())
348    }
349
350    pub fn node_args_opt(&self, id: HirId) -> Option<GenericArgsRef<'tcx>> {
351        validate_hir_id_for_typeck_results(self.hir_owner, id);
352        self.node_args.get(&id.local_id).cloned()
353    }
354
355    /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
356    /// doesn't provide type parameter args.
357    ///
358    /// [`expr_ty`]: TypeckResults::expr_ty
359    pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
360        self.node_type(pat.hir_id)
361    }
362
363    /// Returns the type of an expression as a monotype.
364    ///
365    /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
366    /// some cases, we insert `Adjustment` annotations such as auto-deref or
367    /// auto-ref. The type returned by this function does not consider such
368    /// adjustments. See [`Self::expr_ty_adjusted`] instead.
369    ///
370    /// NB (2): This type doesn't provide type parameter args; e.g., if you
371    /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
372    /// instead of `fn(ty) -> T with T = isize`.
373    pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
374        self.node_type(expr.hir_id)
375    }
376
377    pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
378        self.node_type_opt(expr.hir_id)
379    }
380
381    pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
382        LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
383    }
384
385    pub fn adjustments_mut(
386        &mut self,
387    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
388        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
389    }
390
391    pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
392        validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
393        self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
394    }
395
396    /// Returns the type of `expr`, considering any `Adjustment`
397    /// entry recorded for that expression.
398    pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
399        self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
400    }
401
402    pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
403        self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
404    }
405
406    pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
407        // Only paths and method calls/overloaded operators have
408        // entries in type_dependent_defs, ignore the former here.
409        if let hir::ExprKind::Path(_) = expr.kind {
410            return false;
411        }
412
413        matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
414    }
415
416    /// Returns the computed binding mode for a `PatKind::Binding` pattern
417    /// (after match ergonomics adjustments).
418    pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> BindingMode {
419        self.pat_binding_modes().get(id).copied().unwrap_or_else(|| {
420            s.dcx().span_bug(sp, "missing binding mode");
421        })
422    }
423
424    pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
425        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
426    }
427
428    pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
429        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
430    }
431
432    pub fn pat_adjustments(
433        &self,
434    ) -> LocalTableInContext<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
435        LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
436    }
437
438    pub fn pat_adjustments_mut(
439        &mut self,
440    ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
441        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
442    }
443
444    pub fn rust_2024_migration_desugared_pats(
445        &self,
446    ) -> LocalTableInContext<'_, Rust2024IncompatiblePatInfo> {
447        LocalTableInContext {
448            hir_owner: self.hir_owner,
449            data: &self.rust_2024_migration_desugared_pats,
450        }
451    }
452
453    pub fn rust_2024_migration_desugared_pats_mut(
454        &mut self,
455    ) -> LocalTableInContextMut<'_, Rust2024IncompatiblePatInfo> {
456        LocalTableInContextMut {
457            hir_owner: self.hir_owner,
458            data: &mut self.rust_2024_migration_desugared_pats,
459        }
460    }
461
462    pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> {
463        LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats }
464    }
465
466    pub fn skipped_ref_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
467        LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.skipped_ref_pats }
468    }
469
470    /// Does the pattern recursively contain a `ref mut` binding in it?
471    ///
472    /// This is used to determined whether a `deref` pattern should emit a `Deref`
473    /// or `DerefMut` call for its pattern scrutinee.
474    ///
475    /// This is computed from the typeck results since we want to make
476    /// sure to apply any match-ergonomics adjustments, which we cannot
477    /// determine from the HIR alone.
478    pub fn pat_has_ref_mut_binding(&self, pat: &hir::Pat<'_>) -> bool {
479        let mut has_ref_mut = false;
480        pat.walk(|pat| {
481            if let hir::PatKind::Binding(_, id, _, _) = pat.kind
482                && let Some(BindingMode(ByRef::Yes(Mutability::Mut), _)) =
483                    self.pat_binding_modes().get(id)
484            {
485                has_ref_mut = true;
486                // No need to continue recursing
487                false
488            } else {
489                true
490            }
491        });
492        has_ref_mut
493    }
494
495    /// How should a deref pattern find the place for its inner pattern to match on?
496    ///
497    /// In most cases, if the pattern recursively contains a `ref mut` binding, we find the inner
498    /// pattern's scrutinee by calling `DerefMut::deref_mut`, and otherwise we call `Deref::deref`.
499    /// However, for boxes we can use a built-in deref instead, which doesn't borrow the scrutinee;
500    /// in this case, we return `ByRef::No`.
501    pub fn deref_pat_borrow_mode(&self, pointer_ty: Ty<'_>, inner: &hir::Pat<'_>) -> ByRef {
502        if pointer_ty.is_box() {
503            ByRef::No
504        } else {
505            let mutable = self.pat_has_ref_mut_binding(inner);
506            ByRef::Yes(if mutable { Mutability::Mut } else { Mutability::Not })
507        }
508    }
509
510    /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
511    /// by the closure.
512    pub fn closure_min_captures_flattened(
513        &self,
514        closure_def_id: LocalDefId,
515    ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
516        self.closure_min_captures
517            .get(&closure_def_id)
518            .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
519            .into_iter()
520            .flatten()
521    }
522
523    pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
524        LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
525    }
526
527    pub fn closure_kind_origins_mut(
528        &mut self,
529    ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
530        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
531    }
532
533    pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
534        LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
535    }
536
537    pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
538        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
539    }
540
541    pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
542        LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
543    }
544
545    pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
546        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
547    }
548
549    pub fn is_coercion_cast(&self, hir_id: HirId) -> bool {
550        validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
551        self.coercion_casts.contains(&hir_id.local_id)
552    }
553
554    pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
555        self.coercion_casts.insert(id);
556    }
557
558    pub fn coercion_casts(&self) -> &ItemLocalSet {
559        &self.coercion_casts
560    }
561
562    pub fn offset_of_data(
563        &self,
564    ) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
565        LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
566    }
567
568    pub fn offset_of_data_mut(
569        &mut self,
570    ) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
571        LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
572    }
573}
574
575/// Validate that the given HirId (respectively its `local_id` part) can be
576/// safely used as a key in the maps of a TypeckResults. For that to be
577/// the case, the HirId must have the same `owner` as all the other IDs in
578/// this table (signified by `hir_owner`). Otherwise the HirId
579/// would be in a different frame of reference and using its `local_id`
580/// would result in lookup errors, or worse, in silently wrong data being
581/// stored/returned.
582#[inline]
583fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
584    if hir_id.owner != hir_owner {
585        invalid_hir_id_for_typeck_results(hir_owner, hir_id);
586    }
587}
588
589#[cold]
590#[inline(never)]
591fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
592    ty::tls::with(|tcx| {
593        bug!(
594            "node {} cannot be placed in TypeckResults with hir_owner {:?}",
595            tcx.hir_id_to_string(hir_id),
596            hir_owner
597        )
598    });
599}
600
601pub struct LocalTableInContext<'a, V> {
602    hir_owner: OwnerId,
603    data: &'a ItemLocalMap<V>,
604}
605
606impl<'a, V> LocalTableInContext<'a, V> {
607    pub fn contains_key(&self, id: HirId) -> bool {
608        validate_hir_id_for_typeck_results(self.hir_owner, id);
609        self.data.contains_key(&id.local_id)
610    }
611
612    pub fn get(&self, id: HirId) -> Option<&'a V> {
613        validate_hir_id_for_typeck_results(self.hir_owner, id);
614        self.data.get(&id.local_id)
615    }
616
617    pub fn items(
618        &self,
619    ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>>
620    {
621        self.data.items().map(|(id, value)| (*id, value))
622    }
623
624    pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> {
625        self.data.items().map(|(&k, v)| (k, v)).into_sorted_stable_ord_by_key(|(k, _)| k)
626    }
627}
628
629impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
630    type Output = V;
631
632    fn index(&self, key: HirId) -> &V {
633        self.get(key).unwrap_or_else(|| {
634            bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key)
635        })
636    }
637}
638
639pub struct LocalTableInContextMut<'a, V> {
640    hir_owner: OwnerId,
641    data: &'a mut ItemLocalMap<V>,
642}
643
644impl<'a, V> LocalTableInContextMut<'a, V> {
645    pub fn get_mut(&mut self, id: HirId) -> Option<&mut V> {
646        validate_hir_id_for_typeck_results(self.hir_owner, id);
647        self.data.get_mut(&id.local_id)
648    }
649
650    pub fn get(&mut self, id: HirId) -> Option<&V> {
651        validate_hir_id_for_typeck_results(self.hir_owner, id);
652        self.data.get(&id.local_id)
653    }
654
655    pub fn entry(&mut self, id: HirId) -> Entry<'_, hir::ItemLocalId, V> {
656        validate_hir_id_for_typeck_results(self.hir_owner, id);
657        self.data.entry(id.local_id)
658    }
659
660    pub fn insert(&mut self, id: HirId, val: V) -> Option<V> {
661        validate_hir_id_for_typeck_results(self.hir_owner, id);
662        self.data.insert(id.local_id, val)
663    }
664
665    pub fn remove(&mut self, id: HirId) -> Option<V> {
666        validate_hir_id_for_typeck_results(self.hir_owner, id);
667        self.data.remove(&id.local_id)
668    }
669
670    pub fn extend(&mut self, items: UnordItems<(HirId, V), impl Iterator<Item = (HirId, V)>>) {
671        self.data.extend_unord(items.map(|(id, value)| {
672            validate_hir_id_for_typeck_results(self.hir_owner, id);
673            (id.local_id, value)
674        }))
675    }
676}
677
678#[derive(Clone, Copy, Debug)]
679pub struct LocalSetInContext<'a> {
680    hir_owner: OwnerId,
681    data: &'a ItemLocalSet,
682}
683
684impl<'a> LocalSetInContext<'a> {
685    pub fn is_empty(&self) -> bool {
686        self.data.is_empty()
687    }
688
689    pub fn contains(&self, id: hir::HirId) -> bool {
690        validate_hir_id_for_typeck_results(self.hir_owner, id);
691        self.data.contains(&id.local_id)
692    }
693}
694
695#[derive(Debug)]
696pub struct LocalSetInContextMut<'a> {
697    hir_owner: OwnerId,
698    data: &'a mut ItemLocalSet,
699}
700
701impl<'a> LocalSetInContextMut<'a> {
702    pub fn is_empty(&self) -> bool {
703        self.data.is_empty()
704    }
705
706    pub fn contains(&self, id: hir::HirId) -> bool {
707        validate_hir_id_for_typeck_results(self.hir_owner, id);
708        self.data.contains(&id.local_id)
709    }
710    pub fn insert(&mut self, id: hir::HirId) -> bool {
711        validate_hir_id_for_typeck_results(self.hir_owner, id);
712        self.data.insert(id.local_id)
713    }
714
715    pub fn remove(&mut self, id: hir::HirId) -> bool {
716        validate_hir_id_for_typeck_results(self.hir_owner, id);
717        self.data.remove(&id.local_id)
718    }
719}
720
721rustc_index::newtype_index! {
722    #[derive(HashStable)]
723    #[encodable]
724    #[debug_format = "UserType({})"]
725    pub struct UserTypeAnnotationIndex {
726        const START_INDEX = 0;
727    }
728}
729
730/// Mapping of type annotation indices to canonical user type annotations.
731pub type CanonicalUserTypeAnnotations<'tcx> =
732    IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
733
734#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
735pub struct CanonicalUserTypeAnnotation<'tcx> {
736    #[type_foldable(identity)]
737    #[type_visitable(ignore)]
738    pub user_ty: Box<CanonicalUserType<'tcx>>,
739    pub span: Span,
740    pub inferred_ty: Ty<'tcx>,
741}
742
743/// Canonical user type annotation.
744pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
745
746#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
747#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
748pub struct UserType<'tcx> {
749    pub kind: UserTypeKind<'tcx>,
750    pub bounds: ty::Clauses<'tcx>,
751}
752
753impl<'tcx> UserType<'tcx> {
754    pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> {
755        UserType { kind, bounds: ty::ListWithCachedTypeInfo::empty() }
756    }
757
758    /// A user type annotation with additional bounds that need to be enforced.
759    /// These bounds are lowered from `impl Trait` in bindings.
760    pub fn new_with_bounds(kind: UserTypeKind<'tcx>, bounds: ty::Clauses<'tcx>) -> UserType<'tcx> {
761        UserType { kind, bounds }
762    }
763}
764
765/// A user-given type annotation attached to a constant. These arise
766/// from constants that are named via paths, like `Foo::<A>::new` and
767/// so forth.
768#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
769#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
770pub enum UserTypeKind<'tcx> {
771    Ty(Ty<'tcx>),
772
773    /// The canonical type is the result of `type_of(def_id)` with the
774    /// given generic parameters applied.
775    TypeOf(DefId, UserArgs<'tcx>),
776}
777
778pub trait IsIdentity {
779    fn is_identity(&self) -> bool;
780}
781
782impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
783    /// Returns `true` if this represents the generic parameters of the form `[?0, ?1, ?2]`,
784    /// i.e., each thing is mapped to a canonical variable with the same index.
785    fn is_identity(&self) -> bool {
786        if !self.value.bounds.is_empty() {
787            return false;
788        }
789
790        match self.value.kind {
791            UserTypeKind::Ty(_) => false,
792            UserTypeKind::TypeOf(_, user_args) => {
793                if user_args.user_self_ty.is_some() {
794                    return false;
795                }
796
797                iter::zip(user_args.args, BoundVar::ZERO..).all(|(arg, cvar)| {
798                    match arg.kind() {
799                        GenericArgKind::Type(ty) => match ty.kind() {
800                            ty::Bound(debruijn, b) => {
801                                // We only allow a `ty::INNERMOST` index in generic parameters.
802                                assert_eq!(*debruijn, ty::INNERMOST);
803                                cvar == b.var
804                            }
805                            _ => false,
806                        },
807
808                        GenericArgKind::Lifetime(r) => match r.kind() {
809                            ty::ReBound(debruijn, b) => {
810                                // We only allow a `ty::INNERMOST` index in generic parameters.
811                                assert_eq!(debruijn, ty::INNERMOST);
812                                cvar == b.var
813                            }
814                            _ => false,
815                        },
816
817                        GenericArgKind::Const(ct) => match ct.kind() {
818                            ty::ConstKind::Bound(debruijn, b) => {
819                                // We only allow a `ty::INNERMOST` index in generic parameters.
820                                assert_eq!(debruijn, ty::INNERMOST);
821                                cvar == b.var
822                            }
823                            _ => false,
824                        },
825                    }
826                })
827            }
828        }
829    }
830}
831
832impl<'tcx> std::fmt::Display for UserType<'tcx> {
833    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834        if self.bounds.is_empty() {
835            self.kind.fmt(f)
836        } else {
837            self.kind.fmt(f)?;
838            write!(f, " + ")?;
839            std::fmt::Debug::fmt(&self.bounds, f)
840        }
841    }
842}
843
844impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
845    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
846        match self {
847            Self::Ty(arg0) => {
848                ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0))
849            }
850            Self::TypeOf(arg0, arg1) => write!(f, "TypeOf({:?}, {:?})", arg0, arg1),
851        }
852    }
853}
854
855/// Information on a pattern incompatible with Rust 2024, for use by the error/migration diagnostic
856/// emitted during THIR construction.
857#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
858pub struct Rust2024IncompatiblePatInfo {
859    /// Labeled spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024.
860    pub primary_labels: Vec<(Span, String)>,
861    /// Whether any binding modifiers occur under a non-`move` default binding mode.
862    pub bad_modifiers: bool,
863    /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode.
864    pub bad_ref_pats: bool,
865    /// If `true`, we can give a simpler suggestion solely by eliding explicit binding modifiers.
866    pub suggest_eliding_modes: bool,
867}