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