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