• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{
2     hir::place::Place as HirPlace,
3     infer::canonical::Canonical,
4     traits::ObligationCause,
5     ty::{
6         self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
7         GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
8     },
9 };
10 use rustc_data_structures::{
11     fx::{FxHashMap, FxIndexMap},
12     sync::Lrc,
13     unord::{UnordItems, UnordSet},
14 };
15 use rustc_errors::ErrorGuaranteed;
16 use rustc_hir as hir;
17 use rustc_hir::{
18     def::{DefKind, Res},
19     def_id::{DefId, LocalDefId, LocalDefIdMap},
20     hir_id::OwnerId,
21     HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
22 };
23 use rustc_index::{Idx, IndexVec};
24 use rustc_macros::HashStable;
25 use rustc_middle::mir::FakeReadCause;
26 use rustc_session::Session;
27 use rustc_span::Span;
28 use rustc_target::abi::FieldIdx;
29 use std::{collections::hash_map::Entry, hash::Hash, iter};
30 
31 use super::RvalueScopes;
32 
33 #[derive(TyEncodable, TyDecodable, Debug, HashStable)]
34 pub struct TypeckResults<'tcx> {
35     /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
36     pub hir_owner: OwnerId,
37 
38     /// Resolved definitions for `<T>::X` associated paths and
39     /// method calls, including those of overloaded operators.
40     type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
41 
42     /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
43     /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
44     /// about the field you also need definition of the variant to which the field
45     /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
46     field_indices: ItemLocalMap<FieldIdx>,
47 
48     /// Stores the types for various nodes in the AST. Note that this table
49     /// is not guaranteed to be populated outside inference. See
50     /// typeck::check::fn_ctxt for details.
51     node_types: ItemLocalMap<Ty<'tcx>>,
52 
53     /// Stores the type parameters which were substituted to obtain the type
54     /// of this node. This only applies to nodes that refer to entities
55     /// parameterized by type parameters, such as generic fns, types, or
56     /// other items.
57     node_substs: ItemLocalMap<SubstsRef<'tcx>>,
58 
59     /// This will either store the canonicalized types provided by the user
60     /// or the substitutions that the user explicitly gave (if any) attached
61     /// to `id`. These will not include any inferred values. The canonical form
62     /// is used to capture things like `_` or other unspecified values.
63     ///
64     /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
65     /// canonical substitutions would include only `for<X> { Vec<X> }`.
66     ///
67     /// See also `AscribeUserType` statement in MIR.
68     user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
69 
70     /// Stores the canonicalized types provided by the user. See also
71     /// `AscribeUserType` statement in MIR.
72     pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
73 
74     adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
75 
76     /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
77     pat_binding_modes: ItemLocalMap<BindingMode>,
78 
79     /// Stores the types which were implicitly dereferenced in pattern binding modes
80     /// for later usage in THIR lowering. For example,
81     ///
82     /// ```
83     /// match &&Some(5i32) {
84     ///     Some(n) => {},
85     ///     _ => {},
86     /// }
87     /// ```
88     /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
89     ///
90     /// See:
91     /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
92     pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
93 
94     /// Records the reasons that we picked the kind of each closure;
95     /// not all closures are present in the map.
96     closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
97 
98     /// For each fn, records the "liberated" types of its arguments
99     /// and return type. Liberated means that all bound regions
100     /// (including late-bound regions) are replaced with free
101     /// equivalents. This table is not used in codegen (since regions
102     /// are erased there) and hence is not serialized to metadata.
103     ///
104     /// This table also contains the "revealed" values for any `impl Trait`
105     /// that appear in the signature and whose values are being inferred
106     /// by this function.
107     ///
108     /// # Example
109     ///
110     /// ```rust
111     /// # use std::fmt::Debug;
112     /// fn foo(x: &u32) -> impl Debug { *x }
113     /// ```
114     ///
115     /// The function signature here would be:
116     ///
117     /// ```ignore (illustrative)
118     /// for<'a> fn(&'a u32) -> Foo
119     /// ```
120     ///
121     /// where `Foo` is an opaque type created for this function.
122     ///
123     ///
124     /// The *liberated* form of this would be
125     ///
126     /// ```ignore (illustrative)
127     /// fn(&'a u32) -> u32
128     /// ```
129     ///
130     /// Note that `'a` is not bound (it would be an `ReFree`) and
131     /// that the `Foo` opaque type is replaced by its hidden type.
132     liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
133 
134     /// For each FRU expression, record the normalized types of the fields
135     /// of the struct - this is needed because it is non-trivial to
136     /// normalize while preserving regions. This table is used only in
137     /// MIR construction and hence is not serialized to metadata.
138     fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
139 
140     /// For every coercion cast we add the HIR node ID of the cast
141     /// expression to this set.
142     coercion_casts: ItemLocalSet,
143 
144     /// Set of trait imports actually used in the method resolution.
145     /// This is used for warning unused imports. During type
146     /// checking, this `Lrc` should not be cloned: it must have a ref-count
147     /// of 1 so that we can insert things into the set mutably.
148     pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
149 
150     /// If any errors occurred while type-checking this body,
151     /// this field will be set to `Some(ErrorGuaranteed)`.
152     pub tainted_by_errors: Option<ErrorGuaranteed>,
153 
154     /// All the opaque types that have hidden types set by this function.
155     /// We also store the type here, so that the compiler can use it as a hint
156     /// for figuring out hidden types, even if they are only set in dead code
157     /// (which doesn't show up in MIR).
158     pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
159 
160     /// Tracks the minimum captures required for a closure;
161     /// see `MinCaptureInformationMap` for more details.
162     pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
163 
164     /// Tracks the fake reads required for a closure and the reason for the fake read.
165     /// When performing pattern matching for closures, there are times we don't end up
166     /// reading places that are mentioned in a closure (because of _ patterns). However,
167     /// to ensure the places are initialized, we introduce fake reads.
168     /// Consider these two examples:
169     /// ``` (discriminant matching with only wildcard arm)
170     /// let x: u8;
171     /// let c = || match x { _ => () };
172     /// ```
173     /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
174     /// want to capture it. However, we do still want an error here, because `x` should have
175     /// to be initialized at the point where c is created. Therefore, we add a "fake read"
176     /// instead.
177     /// ``` (destructured assignments)
178     /// let c = || {
179     ///     let (t1, t2) = t;
180     /// }
181     /// ```
182     /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
183     /// we never capture `t`. This becomes an issue when we build MIR as we require
184     /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
185     /// issue by fake reading `t`.
186     pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
187 
188     /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
189     /// by applying extended parameter rules.
190     /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
191     pub rvalue_scopes: RvalueScopes,
192 
193     /// Stores the type, expression, span and optional scope span of all types
194     /// that are live across the yield of this generator (if a generator).
195     pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
196 
197     /// Stores the predicates that apply on generator witness types.
198     /// formatting modified file tests/ui/generator/retain-resume-ref.rs
199     pub generator_interior_predicates:
200         FxHashMap<LocalDefId, Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
201 
202     /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
203     /// as `&[u8]`, depending on the pattern in which they are used.
204     /// This hashset records all instances where we behave
205     /// like this to allow `const_to_pat` to reliably handle this situation.
206     pub treat_byte_string_as_slice: ItemLocalSet,
207 
208     /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
209     /// on closure size.
210     pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
211 
212     /// Container types and field indices of `offset_of!` expressions
213     offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
214 }
215 
216 /// Whenever a value may be live across a generator yield, the type of that value winds up in the
217 /// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
218 /// captured types that can be useful for diagnostics. In particular, it stores the span that
219 /// caused a given type to be recorded, along with the scope that enclosed the value (which can
220 /// be used to find the await that the value is live across).
221 ///
222 /// For example:
223 ///
224 /// ```ignore (pseudo-Rust)
225 /// async move {
226 ///     let x: T = expr;
227 ///     foo.await
228 ///     ...
229 /// }
230 /// ```
231 ///
232 /// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
233 /// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
234 #[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
235 #[derive(TypeFoldable, TypeVisitable)]
236 pub struct GeneratorInteriorTypeCause<'tcx> {
237     /// Type of the captured binding.
238     pub ty: Ty<'tcx>,
239     /// Span of the binding that was captured.
240     pub span: Span,
241     /// Span of the scope of the captured binding.
242     pub scope_span: Option<Span>,
243     /// Span of `.await` or `yield` expression.
244     pub yield_span: Span,
245     /// Expr which the type evaluated from.
246     pub expr: Option<hir::HirId>,
247 }
248 
249 // This type holds diagnostic information on generators and async functions across crate boundaries
250 // and is used to provide better error messages
251 #[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
252 pub struct GeneratorDiagnosticData<'tcx> {
253     pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
254     pub hir_owner: DefId,
255     pub nodes_types: ItemLocalMap<Ty<'tcx>>,
256     pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
257 }
258 
259 impl<'tcx> TypeckResults<'tcx> {
new(hir_owner: OwnerId) -> TypeckResults<'tcx>260     pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
261         TypeckResults {
262             hir_owner,
263             type_dependent_defs: Default::default(),
264             field_indices: Default::default(),
265             user_provided_types: Default::default(),
266             user_provided_sigs: Default::default(),
267             node_types: Default::default(),
268             node_substs: Default::default(),
269             adjustments: Default::default(),
270             pat_binding_modes: Default::default(),
271             pat_adjustments: Default::default(),
272             closure_kind_origins: Default::default(),
273             liberated_fn_sigs: Default::default(),
274             fru_field_types: Default::default(),
275             coercion_casts: Default::default(),
276             used_trait_imports: Lrc::new(Default::default()),
277             tainted_by_errors: None,
278             concrete_opaque_types: Default::default(),
279             closure_min_captures: Default::default(),
280             closure_fake_reads: Default::default(),
281             rvalue_scopes: Default::default(),
282             generator_interior_types: ty::Binder::dummy(Default::default()),
283             generator_interior_predicates: Default::default(),
284             treat_byte_string_as_slice: Default::default(),
285             closure_size_eval: Default::default(),
286             offset_of_data: Default::default(),
287         }
288     }
289 
290     /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res291     pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
292         match *qpath {
293             hir::QPath::Resolved(_, ref path) => path.res,
294             hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
295                 .type_dependent_def(id)
296                 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
297         }
298     }
299 
type_dependent_defs( &self, ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>>300     pub fn type_dependent_defs(
301         &self,
302     ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
303         LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
304     }
305 
type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)>306     pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
307         validate_hir_id_for_typeck_results(self.hir_owner, id);
308         self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
309     }
310 
type_dependent_def_id(&self, id: HirId) -> Option<DefId>311     pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
312         self.type_dependent_def(id).map(|(_, def_id)| def_id)
313     }
314 
type_dependent_defs_mut( &mut self, ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>>315     pub fn type_dependent_defs_mut(
316         &mut self,
317     ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
318         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
319     }
320 
field_indices(&self) -> LocalTableInContext<'_, FieldIdx>321     pub fn field_indices(&self) -> LocalTableInContext<'_, FieldIdx> {
322         LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
323     }
324 
field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx>325     pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx> {
326         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
327     }
328 
field_index(&self, id: hir::HirId) -> FieldIdx329     pub fn field_index(&self, id: hir::HirId) -> FieldIdx {
330         self.field_indices().get(id).cloned().expect("no index for a field")
331     }
332 
opt_field_index(&self, id: hir::HirId) -> Option<FieldIdx>333     pub fn opt_field_index(&self, id: hir::HirId) -> Option<FieldIdx> {
334         self.field_indices().get(id).cloned()
335     }
336 
user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>>337     pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
338         LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
339     }
340 
user_provided_types_mut( &mut self, ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>>341     pub fn user_provided_types_mut(
342         &mut self,
343     ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
344         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
345     }
346 
node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>>347     pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
348         LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
349     }
350 
node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>>351     pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
352         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
353     }
354 
get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx>355     pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
356         let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
357             vec.iter()
358                 .map(|item| {
359                     GeneratorInteriorTypeCause {
360                         ty: item.ty,
361                         span: item.span,
362                         scope_span: item.scope_span,
363                         yield_span: item.yield_span,
364                         expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
365                     }
366                 })
367                 .collect::<Vec<_>>()
368         });
369         GeneratorDiagnosticData {
370             generator_interior_types: generator_interior_type,
371             hir_owner: self.hir_owner.to_def_id(),
372             nodes_types: self.node_types.clone(),
373             adjustments: self.adjustments.clone(),
374         }
375     }
376 
node_type(&self, id: hir::HirId) -> Ty<'tcx>377     pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
378         self.node_type_opt(id).unwrap_or_else(|| {
379             bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
380         })
381     }
382 
node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>>383     pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
384         validate_hir_id_for_typeck_results(self.hir_owner, id);
385         self.node_types.get(&id.local_id).cloned()
386     }
387 
node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>>388     pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
389         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
390     }
391 
node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx>392     pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
393         validate_hir_id_for_typeck_results(self.hir_owner, id);
394         self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
395     }
396 
node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>>397     pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
398         validate_hir_id_for_typeck_results(self.hir_owner, id);
399         self.node_substs.get(&id.local_id).cloned()
400     }
401 
402     /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
403     /// doesn't provide type parameter substitutions.
404     ///
405     /// [`expr_ty`]: TypeckResults::expr_ty
pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx>406     pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
407         self.node_type(pat.hir_id)
408     }
409 
410     /// Returns the type of an expression as a monotype.
411     ///
412     /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
413     /// some cases, we insert `Adjustment` annotations such as auto-deref or
414     /// auto-ref. The type returned by this function does not consider such
415     /// adjustments. See `expr_ty_adjusted()` instead.
416     ///
417     /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
418     /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
419     /// instead of `fn(ty) -> T with T = isize`.
expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx>420     pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
421         self.node_type(expr.hir_id)
422     }
423 
expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>>424     pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
425         self.node_type_opt(expr.hir_id)
426     }
427 
adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>>428     pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
429         LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
430     }
431 
adjustments_mut( &mut self, ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>>432     pub fn adjustments_mut(
433         &mut self,
434     ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
435         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
436     }
437 
expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>]438     pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
439         validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
440         self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
441     }
442 
443     /// Returns the type of `expr`, considering any `Adjustment`
444     /// entry recorded for that expression.
expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx>445     pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
446         self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
447     }
448 
expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>>449     pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
450         self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
451     }
452 
is_method_call(&self, expr: &hir::Expr<'_>) -> bool453     pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
454         // Only paths and method calls/overloaded operators have
455         // entries in type_dependent_defs, ignore the former here.
456         if let hir::ExprKind::Path(_) = expr.kind {
457             return false;
458         }
459 
460         matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
461     }
462 
extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode>463     pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
464         self.pat_binding_modes().get(id).copied().or_else(|| {
465             s.delay_span_bug(sp, "missing binding mode");
466             None
467         })
468     }
469 
pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode>470     pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
471         LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
472     }
473 
pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode>474     pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
475         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
476     }
477 
pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>>478     pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
479         LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
480     }
481 
pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>>482     pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
483         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
484     }
485 
486     /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
487     /// by the closure.
closure_min_captures_flattened( &self, closure_def_id: LocalDefId, ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>>488     pub fn closure_min_captures_flattened(
489         &self,
490         closure_def_id: LocalDefId,
491     ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
492         self.closure_min_captures
493             .get(&closure_def_id)
494             .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
495             .into_iter()
496             .flatten()
497     }
498 
closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)>499     pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
500         LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
501     }
502 
closure_kind_origins_mut( &mut self, ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)>503     pub fn closure_kind_origins_mut(
504         &mut self,
505     ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
506         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
507     }
508 
liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>>509     pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
510         LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
511     }
512 
liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>>513     pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
514         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
515     }
516 
fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>>517     pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
518         LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
519     }
520 
fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>>521     pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
522         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
523     }
524 
is_coercion_cast(&self, hir_id: hir::HirId) -> bool525     pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
526         validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
527         self.coercion_casts.contains(&hir_id.local_id)
528     }
529 
set_coercion_cast(&mut self, id: ItemLocalId)530     pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
531         self.coercion_casts.insert(id);
532     }
533 
coercion_casts(&self) -> &ItemLocalSet534     pub fn coercion_casts(&self) -> &ItemLocalSet {
535         &self.coercion_casts
536     }
537 
offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<FieldIdx>)>538     pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
539         LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
540     }
541 
offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<FieldIdx>)>542     pub fn offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
543         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
544     }
545 }
546 
547 /// Validate that the given HirId (respectively its `local_id` part) can be
548 /// safely used as a key in the maps of a TypeckResults. For that to be
549 /// the case, the HirId must have the same `owner` as all the other IDs in
550 /// this table (signified by `hir_owner`). Otherwise the HirId
551 /// would be in a different frame of reference and using its `local_id`
552 /// would result in lookup errors, or worse, in silently wrong data being
553 /// stored/returned.
554 #[inline]
validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId)555 fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
556     if hir_id.owner != hir_owner {
557         invalid_hir_id_for_typeck_results(hir_owner, hir_id);
558     }
559 }
560 
561 #[cold]
562 #[inline(never)]
invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId)563 fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
564     ty::tls::with(|tcx| {
565         bug!(
566             "node {} cannot be placed in TypeckResults with hir_owner {:?}",
567             tcx.hir().node_to_string(hir_id),
568             hir_owner
569         )
570     });
571 }
572 
573 pub struct LocalTableInContext<'a, V> {
574     hir_owner: OwnerId,
575     data: &'a ItemLocalMap<V>,
576 }
577 
578 impl<'a, V> LocalTableInContext<'a, V> {
contains_key(&self, id: hir::HirId) -> bool579     pub fn contains_key(&self, id: hir::HirId) -> bool {
580         validate_hir_id_for_typeck_results(self.hir_owner, id);
581         self.data.contains_key(&id.local_id)
582     }
583 
get(&self, id: hir::HirId) -> Option<&'a V>584     pub fn get(&self, id: hir::HirId) -> Option<&'a V> {
585         validate_hir_id_for_typeck_results(self.hir_owner, id);
586         self.data.get(&id.local_id)
587     }
588 
items( &'a self, ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>>589     pub fn items(
590         &'a self,
591     ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>>
592     {
593         self.data.items().map(|(id, value)| (*id, value))
594     }
595 
items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)>596     pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> {
597         self.data.to_sorted_stable_ord()
598     }
599 }
600 
601 impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
602     type Output = V;
603 
index(&self, key: hir::HirId) -> &V604     fn index(&self, key: hir::HirId) -> &V {
605         self.get(key).expect("LocalTableInContext: key not found")
606     }
607 }
608 
609 pub struct LocalTableInContextMut<'a, V> {
610     hir_owner: OwnerId,
611     data: &'a mut ItemLocalMap<V>,
612 }
613 
614 impl<'a, V> LocalTableInContextMut<'a, V> {
get_mut(&mut self, id: hir::HirId) -> Option<&mut V>615     pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
616         validate_hir_id_for_typeck_results(self.hir_owner, id);
617         self.data.get_mut(&id.local_id)
618     }
619 
entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V>620     pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
621         validate_hir_id_for_typeck_results(self.hir_owner, id);
622         self.data.entry(id.local_id)
623     }
624 
insert(&mut self, id: hir::HirId, val: V) -> Option<V>625     pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
626         validate_hir_id_for_typeck_results(self.hir_owner, id);
627         self.data.insert(id.local_id, val)
628     }
629 
remove(&mut self, id: hir::HirId) -> Option<V>630     pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
631         validate_hir_id_for_typeck_results(self.hir_owner, id);
632         self.data.remove(&id.local_id)
633     }
634 
extend( &mut self, items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>, )635     pub fn extend(
636         &mut self,
637         items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
638     ) {
639         self.data.extend(items.map(|(id, value)| {
640             validate_hir_id_for_typeck_results(self.hir_owner, id);
641             (id.local_id, value)
642         }))
643     }
644 }
645 
646 rustc_index::newtype_index! {
647     #[derive(HashStable)]
648     #[debug_format = "UserType({})"]
649     pub struct UserTypeAnnotationIndex {
650         const START_INDEX = 0;
651     }
652 }
653 
654 /// Mapping of type annotation indices to canonical user type annotations.
655 pub type CanonicalUserTypeAnnotations<'tcx> =
656     IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
657 
658 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
659 pub struct CanonicalUserTypeAnnotation<'tcx> {
660     pub user_ty: Box<CanonicalUserType<'tcx>>,
661     pub span: Span,
662     pub inferred_ty: Ty<'tcx>,
663 }
664 
665 /// Canonical user type annotation.
666 pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
667 
668 impl<'tcx> CanonicalUserType<'tcx> {
669     /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
670     /// i.e., each thing is mapped to a canonical variable with the same index.
is_identity(&self) -> bool671     pub fn is_identity(&self) -> bool {
672         match self.value {
673             UserType::Ty(_) => false,
674             UserType::TypeOf(_, user_substs) => {
675                 if user_substs.user_self_ty.is_some() {
676                     return false;
677                 }
678 
679                 iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
680                     match kind.unpack() {
681                         GenericArgKind::Type(ty) => match ty.kind() {
682                             ty::Bound(debruijn, b) => {
683                                 // We only allow a `ty::INNERMOST` index in substitutions.
684                                 assert_eq!(*debruijn, ty::INNERMOST);
685                                 cvar == b.var
686                             }
687                             _ => false,
688                         },
689 
690                         GenericArgKind::Lifetime(r) => match *r {
691                             ty::ReLateBound(debruijn, br) => {
692                                 // We only allow a `ty::INNERMOST` index in substitutions.
693                                 assert_eq!(debruijn, ty::INNERMOST);
694                                 cvar == br.var
695                             }
696                             _ => false,
697                         },
698 
699                         GenericArgKind::Const(ct) => match ct.kind() {
700                             ty::ConstKind::Bound(debruijn, b) => {
701                                 // We only allow a `ty::INNERMOST` index in substitutions.
702                                 assert_eq!(debruijn, ty::INNERMOST);
703                                 cvar == b
704                             }
705                             _ => false,
706                         },
707                     }
708                 })
709             }
710         }
711     }
712 }
713 
714 /// A user-given type annotation attached to a constant. These arise
715 /// from constants that are named via paths, like `Foo::<A>::new` and
716 /// so forth.
717 #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
718 #[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
719 pub enum UserType<'tcx> {
720     Ty(Ty<'tcx>),
721 
722     /// The canonical type is the result of `type_of(def_id)` with the
723     /// given substitutions applied.
724     TypeOf(DefId, UserSubsts<'tcx>),
725 }
726