]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | //! type context book-keeping |
2 | ||
8bb4bdeb | 3 | use dep_graph::DepGraph; |
ea8adc8c | 4 | use dep_graph::{DepNode, DepConstructor}; |
3b2f2976 | 5 | use errors::DiagnosticBuilder; |
e9174d1e | 6 | use session::Session; |
b7449926 XL |
7 | use session::config::{BorrowckMode, OutputFilenames}; |
8 | use session::config::CrateType; | |
e9174d1e | 9 | use middle; |
13cf67c4 | 10 | use hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node}; |
ea8adc8c XL |
11 | use hir::def::{Def, Export}; |
12 | use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; | |
32a655c1 | 13 | use hir::map as hir_map; |
3b2f2976 XL |
14 | use hir::map::DefPathHash; |
15 | use lint::{self, Lint}; | |
ea8adc8c | 16 | use ich::{StableHashingContext, NodeIdHashingMode}; |
0731742a | 17 | use infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; |
ff7c6d11 | 18 | use infer::outlives::free_region_map::FreeRegionMap; |
b7449926 | 19 | use middle::cstore::CrateStoreDyn; |
ea8adc8c | 20 | use middle::cstore::EncodedMetadata; |
32a655c1 | 21 | use middle::lang_items; |
ea8adc8c | 22 | use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; |
e9174d1e | 23 | use middle::stability; |
0bf4aa26 | 24 | use mir::{self, Mir, interpret, ProjectionKind}; |
94b46f34 | 25 | use mir::interpret::Allocation; |
0731742a | 26 | use ty::subst::{Kind, Substs, Subst}; |
8bb4bdeb | 27 | use ty::ReprOptions; |
54a0048b | 28 | use traits; |
0bf4aa26 | 29 | use traits::{Clause, Clauses, GoalKind, Goal, Goals}; |
041b39d2 | 30 | use ty::{self, Ty, TypeAndMut}; |
b7449926 | 31 | use ty::{TyS, TyKind, List}; |
0731742a | 32 | use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst}; |
7cac9316 XL |
33 | use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; |
34 | use ty::RegionKind; | |
54a0048b | 35 | use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; |
b7449926 | 36 | use ty::TyKind::*; |
94b46f34 | 37 | use ty::GenericParamDefKind; |
a1dfa0c6 | 38 | use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; |
94b46f34 | 39 | use ty::query; |
7cac9316 | 40 | use ty::steal::Steal; |
0731742a XL |
41 | use ty::subst::{UserSubsts, UnpackedKind}; |
42 | use ty::{BoundVar, BindingMode}; | |
0bf4aa26 XL |
43 | use ty::CanonicalPolyFnSig; |
44 | use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap}; | |
476ff2be | 45 | use util::nodemap::{FxHashMap, FxHashSet}; |
a1dfa0c6 | 46 | use rustc_data_structures::interner::HashInterner; |
b7449926 | 47 | use smallvec::SmallVec; |
ea8adc8c XL |
48 | use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, |
49 | StableHasher, StableHasherResult, | |
50 | StableVec}; | |
83c7162d | 51 | use arena::{TypedArena, SyncDroplessArena}; |
0731742a | 52 | use rustc_data_structures::indexed_vec::{Idx, IndexVec}; |
94b46f34 | 53 | use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal}; |
ea8adc8c | 54 | use std::any::Any; |
e9174d1e | 55 | use std::borrow::Borrow; |
7cac9316 | 56 | use std::cmp::Ordering; |
3b2f2976 | 57 | use std::collections::hash_map::{self, Entry}; |
e9174d1e | 58 | use std::hash::{Hash, Hasher}; |
8faf50e0 | 59 | use std::fmt; |
a7813a04 | 60 | use std::mem; |
b7449926 | 61 | use std::ops::{Deref, Bound}; |
0731742a | 62 | use std::ptr; |
c30ab7b3 | 63 | use std::iter; |
ea8adc8c XL |
64 | use std::sync::mpsc; |
65 | use std::sync::Arc; | |
0731742a | 66 | use std::marker::PhantomData; |
83c7162d | 67 | use rustc_target::spec::abi; |
0531ce1d | 68 | use syntax::ast::{self, NodeId}; |
b039eaaf | 69 | use syntax::attr; |
b7449926 | 70 | use syntax::source_map::MultiSpan; |
8faf50e0 | 71 | use syntax::edition::Edition; |
0531ce1d XL |
72 | use syntax::feature_gate; |
73 | use syntax::symbol::{Symbol, keywords, InternedString}; | |
7cac9316 | 74 | use syntax_pos::Span; |
e9174d1e | 75 | |
54a0048b | 76 | use hir; |
e9174d1e | 77 | |
ff7c6d11 | 78 | pub struct AllArenas<'tcx> { |
94b46f34 | 79 | pub global: WorkerLocal<GlobalArenas<'tcx>>, |
83c7162d | 80 | pub interner: SyncDroplessArena, |
0731742a | 81 | global_ctxt: Option<GlobalCtxt<'tcx>>, |
ff7c6d11 XL |
82 | } |
83 | ||
84 | impl<'tcx> AllArenas<'tcx> { | |
85 | pub fn new() -> Self { | |
86 | AllArenas { | |
0bf4aa26 XL |
87 | global: WorkerLocal::new(|_| GlobalArenas::default()), |
88 | interner: SyncDroplessArena::default(), | |
0731742a | 89 | global_ctxt: None, |
ff7c6d11 XL |
90 | } |
91 | } | |
92 | } | |
93 | ||
e9174d1e | 94 | /// Internal storage |
0bf4aa26 | 95 | #[derive(Default)] |
32a655c1 | 96 | pub struct GlobalArenas<'tcx> { |
e9174d1e | 97 | // internings |
ff7c6d11 | 98 | layout: TypedArena<LayoutDetails>, |
e9174d1e SL |
99 | |
100 | // references | |
8bb4bdeb | 101 | generics: TypedArena<ty::Generics>, |
476ff2be SL |
102 | trait_def: TypedArena<ty::TraitDef>, |
103 | adt_def: TypedArena<ty::AdtDef>, | |
7cac9316 XL |
104 | steal_mir: TypedArena<Steal<Mir<'tcx>>>, |
105 | mir: TypedArena<Mir<'tcx>>, | |
32a655c1 | 106 | tables: TypedArena<ty::TypeckTables<'tcx>>, |
ff7c6d11 XL |
107 | /// miri allocations |
108 | const_allocs: TypedArena<interpret::Allocation>, | |
e9174d1e SL |
109 | } |
110 | ||
a1dfa0c6 | 111 | type InternedSet<'tcx, T> = Lock<FxHashMap<Interned<'tcx, T>, ()>>; |
83c7162d | 112 | |
a7813a04 | 113 | pub struct CtxtInterners<'tcx> { |
32a655c1 | 114 | /// The arena that types, regions, etc are allocated from |
83c7162d | 115 | arena: &'tcx SyncDroplessArena, |
a7813a04 XL |
116 | |
117 | /// Specifically use a speedy hash algorithm for these hash sets, | |
118 | /// they're accessed quite often. | |
83c7162d | 119 | type_: InternedSet<'tcx, TyS<'tcx>>, |
b7449926 | 120 | type_list: InternedSet<'tcx, List<Ty<'tcx>>>, |
83c7162d | 121 | substs: InternedSet<'tcx, Substs<'tcx>>, |
b7449926 | 122 | canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>, |
83c7162d | 123 | region: InternedSet<'tcx, RegionKind>, |
b7449926 XL |
124 | existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>, |
125 | predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, | |
b7449926 | 126 | clauses: InternedSet<'tcx, List<Clause<'tcx>>>, |
0bf4aa26 XL |
127 | goal: InternedSet<'tcx, GoalKind<'tcx>>, |
128 | goal_list: InternedSet<'tcx, List<Goal<'tcx>>>, | |
129 | projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>, | |
0731742a | 130 | lazy_const: InternedSet<'tcx, LazyConst<'tcx>>, |
a7813a04 XL |
131 | } |
132 | ||
133 | impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { | |
83c7162d | 134 | fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> { |
a7813a04 | 135 | CtxtInterners { |
041b39d2 | 136 | arena, |
83c7162d XL |
137 | type_: Default::default(), |
138 | type_list: Default::default(), | |
139 | substs: Default::default(), | |
140 | region: Default::default(), | |
141 | existential_predicates: Default::default(), | |
142 | canonical_var_infos: Default::default(), | |
143 | predicates: Default::default(), | |
83c7162d | 144 | clauses: Default::default(), |
0bf4aa26 XL |
145 | goal: Default::default(), |
146 | goal_list: Default::default(), | |
147 | projs: Default::default(), | |
0731742a | 148 | lazy_const: Default::default(), |
a7813a04 XL |
149 | } |
150 | } | |
151 | ||
94b46f34 | 152 | /// Intern a type |
a1dfa0c6 | 153 | #[inline(never)] |
94b46f34 XL |
154 | fn intern_ty( |
155 | local: &CtxtInterners<'tcx>, | |
156 | global: &CtxtInterners<'gcx>, | |
b7449926 | 157 | st: TyKind<'tcx> |
94b46f34 XL |
158 | ) -> Ty<'tcx> { |
159 | let flags = super::flags::FlagComputation::for_sty(&st); | |
160 | ||
161 | // HACK(eddyb) Depend on flags being accurate to | |
162 | // determine that all contents are in the global tcx. | |
163 | // See comments on Lift for why we can't use that. | |
164 | if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) { | |
a1dfa0c6 XL |
165 | local.type_.borrow_mut().intern(st, |st| { |
166 | let ty_struct = TyS { | |
167 | sty: st, | |
168 | flags: flags.flags, | |
169 | outer_exclusive_binder: flags.outer_exclusive_binder, | |
170 | }; | |
a7813a04 | 171 | |
a1dfa0c6 XL |
172 | // Make sure we don't end up with inference |
173 | // types/regions in the global interner | |
0731742a | 174 | if ptr::eq(local, global) { |
a1dfa0c6 XL |
175 | bug!("Attempted to intern `{:?}` which contains \ |
176 | inference types/regions in the global type context", | |
177 | &ty_struct); | |
178 | } | |
a7813a04 | 179 | |
a1dfa0c6 XL |
180 | Interned(local.arena.alloc(ty_struct)) |
181 | }).0 | |
94b46f34 | 182 | } else { |
a1dfa0c6 XL |
183 | global.type_.borrow_mut().intern(st, |st| { |
184 | let ty_struct = TyS { | |
185 | sty: st, | |
186 | flags: flags.flags, | |
187 | outer_exclusive_binder: flags.outer_exclusive_binder, | |
188 | }; | |
94b46f34 | 189 | |
a1dfa0c6 XL |
190 | // This is safe because all the types the ty_struct can point to |
191 | // already is in the global arena | |
192 | let ty_struct: TyS<'gcx> = unsafe { | |
193 | mem::transmute(ty_struct) | |
194 | }; | |
a7813a04 | 195 | |
a1dfa0c6 XL |
196 | Interned(global.arena.alloc(ty_struct)) |
197 | }).0 | |
94b46f34 XL |
198 | } |
199 | } | |
a7813a04 XL |
200 | } |
201 | ||
e9174d1e | 202 | pub struct CommonTypes<'tcx> { |
a1dfa0c6 | 203 | pub unit: Ty<'tcx>, |
e9174d1e SL |
204 | pub bool: Ty<'tcx>, |
205 | pub char: Ty<'tcx>, | |
206 | pub isize: Ty<'tcx>, | |
207 | pub i8: Ty<'tcx>, | |
208 | pub i16: Ty<'tcx>, | |
209 | pub i32: Ty<'tcx>, | |
210 | pub i64: Ty<'tcx>, | |
32a655c1 | 211 | pub i128: Ty<'tcx>, |
e9174d1e SL |
212 | pub usize: Ty<'tcx>, |
213 | pub u8: Ty<'tcx>, | |
214 | pub u16: Ty<'tcx>, | |
215 | pub u32: Ty<'tcx>, | |
216 | pub u64: Ty<'tcx>, | |
32a655c1 | 217 | pub u128: Ty<'tcx>, |
e9174d1e SL |
218 | pub f32: Ty<'tcx>, |
219 | pub f64: Ty<'tcx>, | |
5bcae85e | 220 | pub never: Ty<'tcx>, |
e9174d1e | 221 | pub err: Ty<'tcx>, |
cc61c64b | 222 | |
7cac9316 XL |
223 | pub re_empty: Region<'tcx>, |
224 | pub re_static: Region<'tcx>, | |
225 | pub re_erased: Region<'tcx>, | |
e9174d1e SL |
226 | } |
227 | ||
3b2f2976 XL |
228 | pub struct LocalTableInContext<'a, V: 'a> { |
229 | local_id_root: Option<DefId>, | |
230 | data: &'a ItemLocalMap<V> | |
231 | } | |
232 | ||
233 | /// Validate that the given HirId (respectively its `local_id` part) can be | |
234 | /// safely used as a key in the tables of a TypeckTable. For that to be | |
235 | /// the case, the HirId must have the same `owner` as all the other IDs in | |
236 | /// this table (signified by `local_id_root`). Otherwise the HirId | |
237 | /// would be in a different frame of reference and using its `local_id` | |
238 | /// would result in lookup errors, or worse, in silently wrong data being | |
239 | /// stored/returned. | |
240 | fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>, | |
241 | hir_id: hir::HirId, | |
242 | mut_access: bool) { | |
243 | if cfg!(debug_assertions) { | |
244 | if let Some(local_id_root) = local_id_root { | |
245 | if hir_id.owner != local_id_root.index { | |
246 | ty::tls::with(|tcx| { | |
0731742a | 247 | let node_id = tcx.hir().hir_to_node_id(hir_id); |
3b2f2976 XL |
248 | |
249 | bug!("node {} with HirId::owner {:?} cannot be placed in \ | |
250 | TypeckTables with local_id_root {:?}", | |
0731742a | 251 | tcx.hir().node_to_string(node_id), |
0bf4aa26 XL |
252 | DefId::local(hir_id.owner), |
253 | local_id_root) | |
3b2f2976 XL |
254 | }); |
255 | } | |
256 | } else { | |
257 | // We use "Null Object" TypeckTables in some of the analysis passes. | |
258 | // These are just expected to be empty and their `local_id_root` is | |
259 | // `None`. Therefore we cannot verify whether a given `HirId` would | |
260 | // be a valid key for the given table. Instead we make sure that | |
261 | // nobody tries to write to such a Null Object table. | |
262 | if mut_access { | |
263 | bug!("access to invalid TypeckTables") | |
264 | } | |
265 | } | |
266 | } | |
267 | } | |
268 | ||
269 | impl<'a, V> LocalTableInContext<'a, V> { | |
270 | pub fn contains_key(&self, id: hir::HirId) -> bool { | |
271 | validate_hir_id_for_typeck_tables(self.local_id_root, id, false); | |
272 | self.data.contains_key(&id.local_id) | |
273 | } | |
274 | ||
275 | pub fn get(&self, id: hir::HirId) -> Option<&V> { | |
276 | validate_hir_id_for_typeck_tables(self.local_id_root, id, false); | |
277 | self.data.get(&id.local_id) | |
278 | } | |
279 | ||
0bf4aa26 | 280 | pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> { |
3b2f2976 XL |
281 | self.data.iter() |
282 | } | |
283 | } | |
284 | ||
285 | impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> { | |
286 | type Output = V; | |
287 | ||
288 | fn index(&self, key: hir::HirId) -> &V { | |
289 | self.get(key).expect("LocalTableInContext: key not found") | |
290 | } | |
291 | } | |
292 | ||
293 | pub struct LocalTableInContextMut<'a, V: 'a> { | |
294 | local_id_root: Option<DefId>, | |
295 | data: &'a mut ItemLocalMap<V> | |
296 | } | |
297 | ||
298 | impl<'a, V> LocalTableInContextMut<'a, V> { | |
299 | pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> { | |
300 | validate_hir_id_for_typeck_tables(self.local_id_root, id, true); | |
301 | self.data.get_mut(&id.local_id) | |
302 | } | |
303 | ||
0bf4aa26 | 304 | pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> { |
3b2f2976 XL |
305 | validate_hir_id_for_typeck_tables(self.local_id_root, id, true); |
306 | self.data.entry(id.local_id) | |
307 | } | |
308 | ||
309 | pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> { | |
310 | validate_hir_id_for_typeck_tables(self.local_id_root, id, true); | |
311 | self.data.insert(id.local_id, val) | |
312 | } | |
313 | ||
314 | pub fn remove(&mut self, id: hir::HirId) -> Option<V> { | |
315 | validate_hir_id_for_typeck_tables(self.local_id_root, id, true); | |
316 | self.data.remove(&id.local_id) | |
317 | } | |
318 | } | |
319 | ||
ea8adc8c | 320 | #[derive(RustcEncodable, RustcDecodable, Debug)] |
32a655c1 | 321 | pub struct TypeckTables<'tcx> { |
3b2f2976 XL |
322 | /// The HirId::owner all ItemLocalIds in this table are relative to. |
323 | pub local_id_root: Option<DefId>, | |
324 | ||
7cac9316 XL |
325 | /// Resolved definitions for `<T>::X` associated paths and |
326 | /// method calls, including those of overloaded operators. | |
3b2f2976 | 327 | type_dependent_defs: ItemLocalMap<Def>, |
476ff2be | 328 | |
83c7162d XL |
329 | /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`) |
330 | /// or patterns (`S { field }`). The index is often useful by itself, but to learn more | |
331 | /// about the field you also need definition of the variant to which the field | |
332 | /// belongs, but it may not exist if it's a tuple field (`tuple.0`). | |
333 | field_indices: ItemLocalMap<usize>, | |
334 | ||
e9174d1e SL |
335 | /// Stores the types for various nodes in the AST. Note that this table |
336 | /// is not guaranteed to be populated until after typeck. See | |
337 | /// typeck::check::fn_ctxt for details. | |
3b2f2976 | 338 | node_types: ItemLocalMap<Ty<'tcx>>, |
e9174d1e SL |
339 | |
340 | /// Stores the type parameters which were substituted to obtain the type | |
341 | /// of this node. This only applies to nodes that refer to entities | |
342 | /// parameterized by type parameters, such as generic fns, types, or | |
343 | /// other items. | |
3b2f2976 | 344 | node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, |
e9174d1e | 345 | |
0731742a XL |
346 | /// This will either store the canonicalized types provided by the user |
347 | /// or the substitutions that the user explicitly gave (if any) attached | |
348 | /// to `id`. These will not include any inferred values. The canonical form | |
349 | /// is used to capture things like `_` or other unspecified values. | |
350 | /// | |
351 | /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the | |
352 | /// canonical substitutions would include only `for<X> { Vec<X> }`. | |
353 | /// | |
354 | /// See also `AscribeUserType` statement in MIR. | |
355 | user_provided_types: ItemLocalMap<CanonicalUserTypeAnnotation<'tcx>>, | |
0bf4aa26 XL |
356 | |
357 | /// Stores the canonicalized types provided by the user. See also | |
358 | /// `AscribeUserType` statement in MIR. | |
359 | pub user_provided_sigs: DefIdMap<CanonicalPolyFnSig<'tcx>>, | |
360 | ||
3b2f2976 XL |
361 | adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>, |
362 | ||
ea8adc8c | 363 | /// Stores the actual binding mode for all instances of hir::BindingAnnotation. |
3b2f2976 | 364 | pat_binding_modes: ItemLocalMap<BindingMode>, |
e9174d1e | 365 | |
ea8adc8c XL |
366 | /// Stores the types which were implicitly dereferenced in pattern binding modes |
367 | /// for later usage in HAIR lowering. For example, | |
368 | /// | |
369 | /// ``` | |
370 | /// match &&Some(5i32) { | |
371 | /// Some(n) => {}, | |
372 | /// _ => {}, | |
373 | /// } | |
374 | /// ``` | |
375 | /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored. | |
376 | /// | |
377 | /// See: | |
378 | /// https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions | |
379 | pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>, | |
380 | ||
e9174d1e | 381 | /// Borrows |
9e0c209e | 382 | pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, |
e9174d1e | 383 | |
ff7c6d11 XL |
384 | /// Records the reasons that we picked the kind of each closure; |
385 | /// not all closures are present in the map. | |
386 | closure_kind_origins: ItemLocalMap<(Span, ast::Name)>, | |
ea8adc8c | 387 | |
92a42be0 SL |
388 | /// For each fn, records the "liberated" types of its arguments |
389 | /// and return type. Liberated means that all bound regions | |
390 | /// (including late-bound regions) are replaced with free | |
94b46f34 | 391 | /// equivalents. This table is not used in codegen (since regions |
92a42be0 | 392 | /// are erased there) and hence is not serialized to metadata. |
3b2f2976 | 393 | liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>, |
7453a54e SL |
394 | |
395 | /// For each FRU expression, record the normalized types of the fields | |
396 | /// of the struct - this is needed because it is non-trivial to | |
397 | /// normalize while preserving regions. This table is used only in | |
398 | /// MIR construction and hence is not serialized to metadata. | |
3b2f2976 | 399 | fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>, |
32a655c1 SL |
400 | |
401 | /// Maps a cast expression to its kind. This is keyed on the | |
402 | /// *from* expression of the cast, not the cast itself. | |
3b2f2976 | 403 | cast_kinds: ItemLocalMap<ty::cast::CastKind>, |
8bb4bdeb XL |
404 | |
405 | /// Set of trait imports actually used in the method resolution. | |
abe05a73 | 406 | /// This is used for warning unused imports. During type |
0531ce1d | 407 | /// checking, this `Lrc` should not be cloned: it must have a ref-count |
abe05a73 | 408 | /// of 1 so that we can insert things into the set mutably. |
0531ce1d | 409 | pub used_trait_imports: Lrc<DefIdSet>, |
8bb4bdeb XL |
410 | |
411 | /// If any errors occurred while type-checking this body, | |
412 | /// this field will be set to `true`. | |
413 | pub tainted_by_errors: bool, | |
414 | ||
415 | /// Stores the free-region relationships that were deduced from | |
416 | /// its where clauses and parameter types. These are then | |
417 | /// read-again by borrowck. | |
7cac9316 | 418 | pub free_region_map: FreeRegionMap<'tcx>, |
94b46f34 XL |
419 | |
420 | /// All the existential types that are restricted to concrete types | |
421 | /// by this function | |
422 | pub concrete_existential_types: FxHashMap<DefId, Ty<'tcx>>, | |
0731742a XL |
423 | |
424 | /// Given the closure ID this map provides the list of UpvarIDs used by it. | |
425 | /// The upvarID contains the HIR node ID and it also contains the full path | |
426 | /// leading to the member of the struct or tuple that is used instead of the | |
427 | /// entire variable. | |
428 | pub upvar_list: ty::UpvarListMap, | |
e9174d1e SL |
429 | } |
430 | ||
32a655c1 | 431 | impl<'tcx> TypeckTables<'tcx> { |
3b2f2976 | 432 | pub fn empty(local_id_root: Option<DefId>) -> TypeckTables<'tcx> { |
32a655c1 | 433 | TypeckTables { |
3b2f2976 | 434 | local_id_root, |
a1dfa0c6 XL |
435 | type_dependent_defs: Default::default(), |
436 | field_indices: Default::default(), | |
0731742a | 437 | user_provided_types: Default::default(), |
0bf4aa26 | 438 | user_provided_sigs: Default::default(), |
a1dfa0c6 XL |
439 | node_types: Default::default(), |
440 | node_substs: Default::default(), | |
a1dfa0c6 XL |
441 | adjustments: Default::default(), |
442 | pat_binding_modes: Default::default(), | |
443 | pat_adjustments: Default::default(), | |
0bf4aa26 | 444 | upvar_capture_map: Default::default(), |
a1dfa0c6 XL |
445 | closure_kind_origins: Default::default(), |
446 | liberated_fn_sigs: Default::default(), | |
447 | fru_field_types: Default::default(), | |
448 | cast_kinds: Default::default(), | |
449 | used_trait_imports: Lrc::new(Default::default()), | |
8bb4bdeb | 450 | tainted_by_errors: false, |
0bf4aa26 XL |
451 | free_region_map: Default::default(), |
452 | concrete_existential_types: Default::default(), | |
0731742a | 453 | upvar_list: Default::default(), |
e9174d1e SL |
454 | } |
455 | } | |
c30ab7b3 | 456 | |
476ff2be | 457 | /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node. |
3b2f2976 | 458 | pub fn qpath_def(&self, qpath: &hir::QPath, id: hir::HirId) -> Def { |
476ff2be SL |
459 | match *qpath { |
460 | hir::QPath::Resolved(_, ref path) => path.def, | |
461 | hir::QPath::TypeRelative(..) => { | |
3b2f2976 XL |
462 | validate_hir_id_for_typeck_tables(self.local_id_root, id, false); |
463 | self.type_dependent_defs.get(&id.local_id).cloned().unwrap_or(Def::Err) | |
476ff2be SL |
464 | } |
465 | } | |
466 | } | |
467 | ||
0bf4aa26 | 468 | pub fn type_dependent_defs(&self) -> LocalTableInContext<'_, Def> { |
3b2f2976 XL |
469 | LocalTableInContext { |
470 | local_id_root: self.local_id_root, | |
471 | data: &self.type_dependent_defs | |
472 | } | |
473 | } | |
474 | ||
0bf4aa26 | 475 | pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut<'_, Def> { |
3b2f2976 XL |
476 | LocalTableInContextMut { |
477 | local_id_root: self.local_id_root, | |
478 | data: &mut self.type_dependent_defs | |
479 | } | |
480 | } | |
481 | ||
0bf4aa26 | 482 | pub fn field_indices(&self) -> LocalTableInContext<'_, usize> { |
83c7162d XL |
483 | LocalTableInContext { |
484 | local_id_root: self.local_id_root, | |
485 | data: &self.field_indices | |
486 | } | |
487 | } | |
488 | ||
0bf4aa26 | 489 | pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> { |
83c7162d XL |
490 | LocalTableInContextMut { |
491 | local_id_root: self.local_id_root, | |
492 | data: &mut self.field_indices | |
493 | } | |
494 | } | |
495 | ||
0731742a XL |
496 | pub fn user_provided_types( |
497 | &self | |
498 | ) -> LocalTableInContext<'_, CanonicalUserTypeAnnotation<'tcx>> { | |
0531ce1d XL |
499 | LocalTableInContext { |
500 | local_id_root: self.local_id_root, | |
0731742a | 501 | data: &self.user_provided_types |
0531ce1d XL |
502 | } |
503 | } | |
504 | ||
0731742a XL |
505 | pub fn user_provided_types_mut( |
506 | &mut self | |
507 | ) -> LocalTableInContextMut<'_, CanonicalUserTypeAnnotation<'tcx>> { | |
0531ce1d XL |
508 | LocalTableInContextMut { |
509 | local_id_root: self.local_id_root, | |
0731742a | 510 | data: &mut self.user_provided_types |
0531ce1d XL |
511 | } |
512 | } | |
513 | ||
0bf4aa26 | 514 | pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> { |
3b2f2976 XL |
515 | LocalTableInContext { |
516 | local_id_root: self.local_id_root, | |
517 | data: &self.node_types | |
518 | } | |
519 | } | |
520 | ||
0bf4aa26 | 521 | pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> { |
3b2f2976 XL |
522 | LocalTableInContextMut { |
523 | local_id_root: self.local_id_root, | |
524 | data: &mut self.node_types | |
525 | } | |
526 | } | |
527 | ||
528 | pub fn node_id_to_type(&self, id: hir::HirId) -> Ty<'tcx> { | |
0bf4aa26 XL |
529 | self.node_id_to_type_opt(id).unwrap_or_else(|| |
530 | bug!("node_id_to_type: no type for node `{}`", | |
531 | tls::with(|tcx| { | |
0731742a XL |
532 | let id = tcx.hir().hir_to_node_id(id); |
533 | tcx.hir().node_to_string(id) | |
0bf4aa26 XL |
534 | })) |
535 | ) | |
c30ab7b3 SL |
536 | } |
537 | ||
3b2f2976 XL |
538 | pub fn node_id_to_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> { |
539 | validate_hir_id_for_typeck_tables(self.local_id_root, id, false); | |
540 | self.node_types.get(&id.local_id).cloned() | |
541 | } | |
542 | ||
0bf4aa26 | 543 | pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, &'tcx Substs<'tcx>> { |
3b2f2976 XL |
544 | LocalTableInContextMut { |
545 | local_id_root: self.local_id_root, | |
546 | data: &mut self.node_substs | |
547 | } | |
548 | } | |
549 | ||
550 | pub fn node_substs(&self, id: hir::HirId) -> &'tcx Substs<'tcx> { | |
551 | validate_hir_id_for_typeck_tables(self.local_id_root, id, false); | |
0bf4aa26 | 552 | self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| Substs::empty()) |
c30ab7b3 SL |
553 | } |
554 | ||
3b2f2976 XL |
555 | pub fn node_substs_opt(&self, id: hir::HirId) -> Option<&'tcx Substs<'tcx>> { |
556 | validate_hir_id_for_typeck_tables(self.local_id_root, id, false); | |
557 | self.node_substs.get(&id.local_id).cloned() | |
c30ab7b3 SL |
558 | } |
559 | ||
560 | // Returns the type of a pattern as a monotype. Like @expr_ty, this function | |
561 | // doesn't provide type parameter substitutions. | |
562 | pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { | |
3b2f2976 | 563 | self.node_id_to_type(pat.hir_id) |
c30ab7b3 SL |
564 | } |
565 | ||
566 | pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> { | |
3b2f2976 | 567 | self.node_id_to_type_opt(pat.hir_id) |
c30ab7b3 SL |
568 | } |
569 | ||
570 | // Returns the type of an expression as a monotype. | |
571 | // | |
572 | // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in | |
573 | // some cases, we insert `Adjustment` annotations such as auto-deref or | |
574 | // auto-ref. The type returned by this function does not consider such | |
575 | // adjustments. See `expr_ty_adjusted()` instead. | |
576 | // | |
0731742a | 577 | // NB (2): This type doesn't provide type parameter substitutions; e.g., if you |
c30ab7b3 SL |
578 | // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" |
579 | // instead of "fn(ty) -> T with T = isize". | |
580 | pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> { | |
3b2f2976 | 581 | self.node_id_to_type(expr.hir_id) |
c30ab7b3 SL |
582 | } |
583 | ||
584 | pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> { | |
3b2f2976 XL |
585 | self.node_id_to_type_opt(expr.hir_id) |
586 | } | |
587 | ||
0bf4aa26 | 588 | pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> { |
3b2f2976 XL |
589 | LocalTableInContext { |
590 | local_id_root: self.local_id_root, | |
591 | data: &self.adjustments | |
592 | } | |
593 | } | |
594 | ||
595 | pub fn adjustments_mut(&mut self) | |
0bf4aa26 | 596 | -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> { |
3b2f2976 XL |
597 | LocalTableInContextMut { |
598 | local_id_root: self.local_id_root, | |
599 | data: &mut self.adjustments | |
600 | } | |
c30ab7b3 SL |
601 | } |
602 | ||
7cac9316 XL |
603 | pub fn expr_adjustments(&self, expr: &hir::Expr) |
604 | -> &[ty::adjustment::Adjustment<'tcx>] { | |
3b2f2976 XL |
605 | validate_hir_id_for_typeck_tables(self.local_id_root, expr.hir_id, false); |
606 | self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..]) | |
7cac9316 XL |
607 | } |
608 | ||
c30ab7b3 SL |
609 | /// Returns the type of `expr`, considering any `Adjustment` |
610 | /// entry recorded for that expression. | |
611 | pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> { | |
7cac9316 XL |
612 | self.expr_adjustments(expr) |
613 | .last() | |
c30ab7b3 SL |
614 | .map_or_else(|| self.expr_ty(expr), |adj| adj.target) |
615 | } | |
616 | ||
617 | pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> { | |
7cac9316 XL |
618 | self.expr_adjustments(expr) |
619 | .last() | |
620 | .map(|adj| adj.target) | |
621 | .or_else(|| self.expr_ty_opt(expr)) | |
c30ab7b3 SL |
622 | } |
623 | ||
7cac9316 XL |
624 | pub fn is_method_call(&self, expr: &hir::Expr) -> bool { |
625 | // Only paths and method calls/overloaded operators have | |
626 | // entries in type_dependent_defs, ignore the former here. | |
8faf50e0 | 627 | if let hir::ExprKind::Path(_) = expr.node { |
7cac9316 XL |
628 | return false; |
629 | } | |
c30ab7b3 | 630 | |
3b2f2976 | 631 | match self.type_dependent_defs().get(expr.hir_id) { |
7cac9316 XL |
632 | Some(&Def::Method(_)) => true, |
633 | _ => false | |
634 | } | |
c30ab7b3 SL |
635 | } |
636 | ||
0bf4aa26 | 637 | pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> { |
3b2f2976 XL |
638 | LocalTableInContext { |
639 | local_id_root: self.local_id_root, | |
640 | data: &self.pat_binding_modes | |
641 | } | |
642 | } | |
643 | ||
644 | pub fn pat_binding_modes_mut(&mut self) | |
0bf4aa26 | 645 | -> LocalTableInContextMut<'_, BindingMode> { |
3b2f2976 XL |
646 | LocalTableInContextMut { |
647 | local_id_root: self.local_id_root, | |
648 | data: &mut self.pat_binding_modes | |
649 | } | |
650 | } | |
651 | ||
0bf4aa26 | 652 | pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> { |
ea8adc8c XL |
653 | LocalTableInContext { |
654 | local_id_root: self.local_id_root, | |
655 | data: &self.pat_adjustments, | |
656 | } | |
657 | } | |
658 | ||
659 | pub fn pat_adjustments_mut(&mut self) | |
0bf4aa26 | 660 | -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> { |
ea8adc8c XL |
661 | LocalTableInContextMut { |
662 | local_id_root: self.local_id_root, | |
663 | data: &mut self.pat_adjustments, | |
664 | } | |
665 | } | |
666 | ||
041b39d2 XL |
667 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { |
668 | self.upvar_capture_map[&upvar_id] | |
c30ab7b3 | 669 | } |
3b2f2976 | 670 | |
0bf4aa26 | 671 | pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, ast::Name)> { |
3b2f2976 XL |
672 | LocalTableInContext { |
673 | local_id_root: self.local_id_root, | |
ff7c6d11 | 674 | data: &self.closure_kind_origins |
3b2f2976 XL |
675 | } |
676 | } | |
677 | ||
0bf4aa26 | 678 | pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<'_, (Span, ast::Name)> { |
3b2f2976 XL |
679 | LocalTableInContextMut { |
680 | local_id_root: self.local_id_root, | |
ff7c6d11 | 681 | data: &mut self.closure_kind_origins |
3b2f2976 XL |
682 | } |
683 | } | |
684 | ||
0bf4aa26 | 685 | pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> { |
3b2f2976 XL |
686 | LocalTableInContext { |
687 | local_id_root: self.local_id_root, | |
688 | data: &self.liberated_fn_sigs | |
689 | } | |
690 | } | |
691 | ||
0bf4aa26 | 692 | pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> { |
3b2f2976 XL |
693 | LocalTableInContextMut { |
694 | local_id_root: self.local_id_root, | |
695 | data: &mut self.liberated_fn_sigs | |
696 | } | |
697 | } | |
698 | ||
0bf4aa26 | 699 | pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> { |
3b2f2976 XL |
700 | LocalTableInContext { |
701 | local_id_root: self.local_id_root, | |
702 | data: &self.fru_field_types | |
703 | } | |
704 | } | |
705 | ||
0bf4aa26 | 706 | pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> { |
3b2f2976 XL |
707 | LocalTableInContextMut { |
708 | local_id_root: self.local_id_root, | |
709 | data: &mut self.fru_field_types | |
710 | } | |
711 | } | |
712 | ||
0bf4aa26 | 713 | pub fn cast_kinds(&self) -> LocalTableInContext<'_, ty::cast::CastKind> { |
3b2f2976 XL |
714 | LocalTableInContext { |
715 | local_id_root: self.local_id_root, | |
716 | data: &self.cast_kinds | |
717 | } | |
718 | } | |
719 | ||
0bf4aa26 | 720 | pub fn cast_kinds_mut(&mut self) -> LocalTableInContextMut<'_, ty::cast::CastKind> { |
3b2f2976 XL |
721 | LocalTableInContextMut { |
722 | local_id_root: self.local_id_root, | |
723 | data: &mut self.cast_kinds | |
724 | } | |
725 | } | |
726 | } | |
727 | ||
0531ce1d | 728 | impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> { |
3b2f2976 | 729 | fn hash_stable<W: StableHasherResult>(&self, |
0531ce1d | 730 | hcx: &mut StableHashingContext<'a>, |
3b2f2976 XL |
731 | hasher: &mut StableHasher<W>) { |
732 | let ty::TypeckTables { | |
733 | local_id_root, | |
734 | ref type_dependent_defs, | |
83c7162d | 735 | ref field_indices, |
0731742a | 736 | ref user_provided_types, |
0bf4aa26 | 737 | ref user_provided_sigs, |
3b2f2976 XL |
738 | ref node_types, |
739 | ref node_substs, | |
740 | ref adjustments, | |
741 | ref pat_binding_modes, | |
ea8adc8c | 742 | ref pat_adjustments, |
3b2f2976 | 743 | ref upvar_capture_map, |
ff7c6d11 | 744 | ref closure_kind_origins, |
3b2f2976 XL |
745 | ref liberated_fn_sigs, |
746 | ref fru_field_types, | |
747 | ||
748 | ref cast_kinds, | |
749 | ||
750 | ref used_trait_imports, | |
751 | tainted_by_errors, | |
752 | ref free_region_map, | |
94b46f34 | 753 | ref concrete_existential_types, |
0731742a XL |
754 | ref upvar_list, |
755 | ||
3b2f2976 XL |
756 | } = *self; |
757 | ||
758 | hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { | |
ea8adc8c | 759 | type_dependent_defs.hash_stable(hcx, hasher); |
83c7162d | 760 | field_indices.hash_stable(hcx, hasher); |
0731742a | 761 | user_provided_types.hash_stable(hcx, hasher); |
0bf4aa26 | 762 | user_provided_sigs.hash_stable(hcx, hasher); |
ea8adc8c XL |
763 | node_types.hash_stable(hcx, hasher); |
764 | node_substs.hash_stable(hcx, hasher); | |
765 | adjustments.hash_stable(hcx, hasher); | |
766 | pat_binding_modes.hash_stable(hcx, hasher); | |
767 | pat_adjustments.hash_stable(hcx, hasher); | |
768 | hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| { | |
3b2f2976 | 769 | let ty::UpvarId { |
a1dfa0c6 | 770 | var_path, |
3b2f2976 XL |
771 | closure_expr_id |
772 | } = *up_var_id; | |
773 | ||
774 | let local_id_root = | |
775 | local_id_root.expect("trying to hash invalid TypeckTables"); | |
776 | ||
ea8adc8c | 777 | let var_owner_def_id = DefId { |
3b2f2976 | 778 | krate: local_id_root.krate, |
a1dfa0c6 | 779 | index: var_path.hir_id.owner, |
3b2f2976 XL |
780 | }; |
781 | let closure_def_id = DefId { | |
782 | krate: local_id_root.krate, | |
abe05a73 | 783 | index: closure_expr_id.to_def_id().index, |
3b2f2976 | 784 | }; |
ea8adc8c | 785 | (hcx.def_path_hash(var_owner_def_id), |
a1dfa0c6 | 786 | var_path.hir_id.local_id, |
ea8adc8c | 787 | hcx.def_path_hash(closure_def_id)) |
3b2f2976 XL |
788 | }); |
789 | ||
ff7c6d11 | 790 | closure_kind_origins.hash_stable(hcx, hasher); |
ea8adc8c XL |
791 | liberated_fn_sigs.hash_stable(hcx, hasher); |
792 | fru_field_types.hash_stable(hcx, hasher); | |
793 | cast_kinds.hash_stable(hcx, hasher); | |
ea8adc8c | 794 | used_trait_imports.hash_stable(hcx, hasher); |
3b2f2976 XL |
795 | tainted_by_errors.hash_stable(hcx, hasher); |
796 | free_region_map.hash_stable(hcx, hasher); | |
94b46f34 | 797 | concrete_existential_types.hash_stable(hcx, hasher); |
0731742a | 798 | upvar_list.hash_stable(hcx, hasher); |
3b2f2976 XL |
799 | }) |
800 | } | |
e9174d1e SL |
801 | } |
802 | ||
0731742a XL |
803 | newtype_index! { |
804 | pub struct UserTypeAnnotationIndex { | |
805 | DEBUG_FORMAT = "UserTypeAnnotation({})", | |
806 | const START_INDEX = 0, | |
807 | } | |
808 | } | |
809 | ||
810 | /// Mapping of type annotation indices to canonical user type annotations. | |
811 | pub type CanonicalUserTypeAnnotations<'tcx> = | |
812 | IndexVec<UserTypeAnnotationIndex, (Span, CanonicalUserTypeAnnotation<'tcx>)>; | |
813 | ||
814 | /// Canonicalized user type annotation. | |
815 | pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>; | |
816 | ||
817 | impl CanonicalUserTypeAnnotation<'gcx> { | |
818 | /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`, | |
819 | /// i.e. each thing is mapped to a canonical variable with the same index. | |
820 | pub fn is_identity(&self) -> bool { | |
821 | match self.value { | |
822 | UserTypeAnnotation::Ty(_) => false, | |
823 | UserTypeAnnotation::TypeOf(_, user_substs) => { | |
824 | if user_substs.user_self_ty.is_some() { | |
825 | return false; | |
826 | } | |
827 | ||
828 | user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { | |
829 | match kind.unpack() { | |
830 | UnpackedKind::Type(ty) => match ty.sty { | |
831 | ty::Bound(debruijn, b) => { | |
832 | // We only allow a `ty::INNERMOST` index in substitutions. | |
833 | assert_eq!(debruijn, ty::INNERMOST); | |
834 | cvar == b.var | |
835 | } | |
836 | _ => false, | |
837 | }, | |
838 | ||
839 | UnpackedKind::Lifetime(r) => match r { | |
840 | ty::ReLateBound(debruijn, br) => { | |
841 | // We only allow a `ty::INNERMOST` index in substitutions. | |
842 | assert_eq!(*debruijn, ty::INNERMOST); | |
843 | cvar == br.assert_bound_var() | |
844 | } | |
845 | _ => false, | |
846 | }, | |
847 | } | |
848 | }) | |
849 | }, | |
850 | } | |
851 | } | |
852 | } | |
853 | ||
854 | /// A user-given type annotation attached to a constant. These arise | |
855 | /// from constants that are named via paths, like `Foo::<A>::new` and | |
856 | /// so forth. | |
857 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | |
858 | pub enum UserTypeAnnotation<'tcx> { | |
859 | Ty(Ty<'tcx>), | |
860 | ||
861 | /// The canonical type is the result of `type_of(def_id)` with the | |
862 | /// given substitutions applied. | |
863 | TypeOf(DefId, UserSubsts<'tcx>), | |
864 | } | |
865 | ||
866 | EnumTypeFoldableImpl! { | |
867 | impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> { | |
868 | (UserTypeAnnotation::Ty)(ty), | |
869 | (UserTypeAnnotation::TypeOf)(def, substs), | |
870 | } | |
871 | } | |
872 | ||
873 | EnumLiftImpl! { | |
874 | impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> { | |
875 | type Lifted = UserTypeAnnotation<'tcx>; | |
876 | (UserTypeAnnotation::Ty)(ty), | |
877 | (UserTypeAnnotation::TypeOf)(def, substs), | |
878 | } | |
879 | } | |
880 | ||
e9174d1e | 881 | impl<'tcx> CommonTypes<'tcx> { |
a7813a04 | 882 | fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { |
94b46f34 | 883 | let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); |
cc61c64b | 884 | let mk_region = |r| { |
a1dfa0c6 XL |
885 | interners.region.borrow_mut().intern(r, |r| { |
886 | Interned(interners.arena.alloc(r)) | |
887 | }).0 | |
cc61c64b | 888 | }; |
a1dfa0c6 | 889 | |
e9174d1e | 890 | CommonTypes { |
a1dfa0c6 | 891 | unit: mk(Tuple(List::empty())), |
b7449926 XL |
892 | bool: mk(Bool), |
893 | char: mk(Char), | |
894 | never: mk(Never), | |
895 | err: mk(Error), | |
896 | isize: mk(Int(ast::IntTy::Isize)), | |
897 | i8: mk(Int(ast::IntTy::I8)), | |
898 | i16: mk(Int(ast::IntTy::I16)), | |
899 | i32: mk(Int(ast::IntTy::I32)), | |
900 | i64: mk(Int(ast::IntTy::I64)), | |
901 | i128: mk(Int(ast::IntTy::I128)), | |
902 | usize: mk(Uint(ast::UintTy::Usize)), | |
903 | u8: mk(Uint(ast::UintTy::U8)), | |
904 | u16: mk(Uint(ast::UintTy::U16)), | |
905 | u32: mk(Uint(ast::UintTy::U32)), | |
906 | u64: mk(Uint(ast::UintTy::U64)), | |
907 | u128: mk(Uint(ast::UintTy::U128)), | |
908 | f32: mk(Float(ast::FloatTy::F32)), | |
909 | f64: mk(Float(ast::FloatTy::F64)), | |
cc61c64b | 910 | |
7cac9316 XL |
911 | re_empty: mk_region(RegionKind::ReEmpty), |
912 | re_static: mk_region(RegionKind::ReStatic), | |
913 | re_erased: mk_region(RegionKind::ReErased), | |
e9174d1e SL |
914 | } |
915 | } | |
916 | } | |
917 | ||
0bf4aa26 XL |
918 | // This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime |
919 | // conflict. | |
920 | #[derive(Debug)] | |
921 | pub struct FreeRegionInfo { | |
922 | // def id corresponding to FreeRegion | |
923 | pub def_id: DefId, | |
924 | // the bound region corresponding to FreeRegion | |
925 | pub boundregion: ty::BoundRegion, | |
926 | // checks if bound region is in Impl Item | |
927 | pub is_impl_item: bool, | |
928 | } | |
929 | ||
ea8adc8c XL |
930 | /// The central data structure of the compiler. It stores references |
931 | /// to the various **arenas** and also houses the results of the | |
ff7c6d11 | 932 | /// various **compiler queries** that have been performed. See the |
0531ce1d | 933 | /// [rustc guide] for more details. |
ff7c6d11 | 934 | /// |
a1dfa0c6 | 935 | /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html |
a7813a04 | 936 | #[derive(Copy, Clone)] |
8faf50e0 | 937 | pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> { |
0731742a XL |
938 | gcx: &'gcx GlobalCtxt<'gcx>, |
939 | interners: &'tcx CtxtInterners<'tcx>, | |
940 | dummy: PhantomData<&'a ()>, | |
a7813a04 | 941 | } |
e9174d1e | 942 | |
0731742a XL |
943 | impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> { |
944 | type Target = &'gcx GlobalCtxt<'gcx>; | |
a1dfa0c6 | 945 | #[inline(always)] |
a7813a04 XL |
946 | fn deref(&self) -> &Self::Target { |
947 | &self.gcx | |
948 | } | |
949 | } | |
950 | ||
951 | pub struct GlobalCtxt<'tcx> { | |
94b46f34 | 952 | global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>, |
a7813a04 | 953 | global_interners: CtxtInterners<'tcx>, |
e9174d1e | 954 | |
94b46f34 | 955 | cstore: &'tcx CrateStoreDyn, |
ea8adc8c | 956 | |
8bb4bdeb XL |
957 | pub sess: &'tcx Session, |
958 | ||
9cc50fc6 SL |
959 | pub dep_graph: DepGraph, |
960 | ||
e9174d1e SL |
961 | /// Common types, pre-interned for your convenience. |
962 | pub types: CommonTypes<'tcx>, | |
963 | ||
5bcae85e SL |
964 | /// Map indicating what traits are in scope for places where this |
965 | /// is relevant; generated by resolve. | |
ea8adc8c | 966 | trait_map: FxHashMap<DefIndex, |
0531ce1d XL |
967 | Lrc<FxHashMap<ItemLocalId, |
968 | Lrc<StableVec<TraitCandidate>>>>>, | |
5bcae85e | 969 | |
cc61c64b | 970 | /// Export map produced by name resolution. |
0531ce1d | 971 | export_map: FxHashMap<DefId, Lrc<Vec<Export>>>, |
cc61c64b | 972 | |
0731742a | 973 | hir_map: hir_map::Map<'tcx>, |
7cac9316 XL |
974 | |
975 | /// A map from DefPathHash -> DefId. Includes DefIds from the local crate | |
976 | /// as well as all upstream crates. Only populated in incremental mode. | |
977 | pub def_path_hash_to_def_id: Option<FxHashMap<DefPathHash, DefId>>, | |
978 | ||
0731742a | 979 | pub queries: query::Queries<'tcx>, |
c30ab7b3 | 980 | |
b7449926 | 981 | // Records the free variables referenced by every closure |
9cc50fc6 SL |
982 | // expression. Do not track deps for this, just recompute it from |
983 | // scratch every time. | |
0531ce1d | 984 | freevars: FxHashMap<DefId, Lrc<Vec<hir::Freevar>>>, |
9cc50fc6 | 985 | |
ea8adc8c | 986 | maybe_unused_trait_imports: FxHashSet<DefId>, |
ea8adc8c | 987 | maybe_unused_extern_crates: Vec<(DefId, Span)>, |
0bf4aa26 XL |
988 | /// Extern prelude entries. The value is `true` if the entry was introduced |
989 | /// via `extern crate` item and not `--extern` option or compiler built-in. | |
990 | pub extern_prelude: FxHashMap<ast::Name, bool>, | |
3b2f2976 | 991 | |
9cc50fc6 | 992 | // Internal cache for metadata decoding. No need to track deps on this. |
83c7162d | 993 | pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>, |
9cc50fc6 | 994 | |
e9174d1e SL |
995 | /// Caches the results of trait selection. This cache is used |
996 | /// for things that do not have to do with the parameters in scope. | |
997 | pub selection_cache: traits::SelectionCache<'tcx>, | |
998 | ||
92a42be0 SL |
999 | /// Caches the results of trait evaluation. This cache is used |
1000 | /// for things that do not have to do with the parameters in scope. | |
1001 | /// Merge this with `selection_cache`? | |
1002 | pub evaluation_cache: traits::EvaluationCache<'tcx>, | |
1003 | ||
54a0048b SL |
1004 | /// The definite name of the current crate after taking into account |
1005 | /// attributes, commandline parameters, etc. | |
476ff2be | 1006 | pub crate_name: Symbol, |
54a0048b SL |
1007 | |
1008 | /// Data layout specification for the current target. | |
1009 | pub data_layout: TargetDataLayout, | |
1010 | ||
a1dfa0c6 | 1011 | stability_interner: Lock<FxHashMap<&'tcx attr::Stability, ()>>, |
32a655c1 | 1012 | |
94b46f34 | 1013 | /// Stores the value of constants (and deduplicates the actual memory) |
a1dfa0c6 | 1014 | allocation_interner: Lock<FxHashMap<&'tcx Allocation, ()>>, |
94b46f34 | 1015 | |
0731742a | 1016 | pub alloc_map: Lock<interpret::AllocMap<'tcx>>, |
ff7c6d11 | 1017 | |
a1dfa0c6 | 1018 | layout_interner: Lock<FxHashMap<&'tcx LayoutDetails, ()>>, |
ea8adc8c XL |
1019 | |
1020 | /// A general purpose channel to throw data out the back towards LLVM worker | |
1021 | /// threads. | |
1022 | /// | |
94b46f34 | 1023 | /// This is intended to only get used during the codegen phase of the compiler |
ea8adc8c XL |
1024 | /// when satisfying the query for a particular codegen unit. Internally in |
1025 | /// the query it'll send data along this channel to get processed later. | |
83c7162d | 1026 | pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>, |
ea8adc8c XL |
1027 | |
1028 | output_filenames: Arc<OutputFilenames>, | |
e9174d1e | 1029 | } |
e9174d1e | 1030 | |
0531ce1d | 1031 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
a7813a04 | 1032 | /// Get the global TyCtxt. |
0531ce1d | 1033 | #[inline] |
0731742a | 1034 | pub fn global_tcx(self) -> TyCtxt<'gcx, 'gcx, 'gcx> { |
a7813a04 | 1035 | TyCtxt { |
0531ce1d XL |
1036 | gcx: self.gcx, |
1037 | interners: &self.gcx.global_interners, | |
0731742a | 1038 | dummy: PhantomData, |
a7813a04 XL |
1039 | } |
1040 | } | |
a7813a04 | 1041 | |
0731742a XL |
1042 | #[inline(always)] |
1043 | pub fn hir(self) -> &'a hir_map::Map<'gcx> { | |
1044 | &self.hir_map | |
1045 | } | |
1046 | ||
8bb4bdeb | 1047 | pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { |
32a655c1 | 1048 | self.global_arenas.generics.alloc(generics) |
9e0c209e SL |
1049 | } |
1050 | ||
7cac9316 XL |
1051 | pub fn alloc_steal_mir(self, mir: Mir<'gcx>) -> &'gcx Steal<Mir<'gcx>> { |
1052 | self.global_arenas.steal_mir.alloc(Steal::new(mir)) | |
1053 | } | |
1054 | ||
1055 | pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx Mir<'gcx> { | |
1056 | self.global_arenas.mir.alloc(mir) | |
32a655c1 SL |
1057 | } |
1058 | ||
1059 | pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> { | |
1060 | self.global_arenas.tables.alloc(tables) | |
c30ab7b3 SL |
1061 | } |
1062 | ||
476ff2be | 1063 | pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef { |
32a655c1 | 1064 | self.global_arenas.trait_def.alloc(def) |
e9174d1e SL |
1065 | } |
1066 | ||
476ff2be SL |
1067 | pub fn alloc_adt_def(self, |
1068 | did: DefId, | |
1069 | kind: AdtKind, | |
a1dfa0c6 | 1070 | variants: IndexVec<VariantIdx, ty::VariantDef>, |
8bb4bdeb | 1071 | repr: ReprOptions) |
476ff2be | 1072 | -> &'gcx ty::AdtDef { |
8bb4bdeb | 1073 | let def = ty::AdtDef::new(self, did, kind, variants, repr); |
32a655c1 | 1074 | self.global_arenas.adt_def.alloc(def) |
e9174d1e SL |
1075 | } |
1076 | ||
0731742a | 1077 | pub fn intern_const_alloc(self, alloc: Allocation) -> &'gcx Allocation { |
a1dfa0c6 XL |
1078 | self.allocation_interner.borrow_mut().intern(alloc, |alloc| { |
1079 | self.global_arenas.const_allocs.alloc(alloc) | |
1080 | }) | |
ff7c6d11 XL |
1081 | } |
1082 | ||
b7449926 | 1083 | /// Allocates a byte or string literal for `mir::interpret`, read-only |
94b46f34 | 1084 | pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { |
ff7c6d11 | 1085 | // create an allocation that just contains these bytes |
a1dfa0c6 | 1086 | let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ()); |
ff7c6d11 | 1087 | let alloc = self.intern_const_alloc(alloc); |
94b46f34 | 1088 | self.alloc_map.lock().allocate(alloc) |
ff7c6d11 XL |
1089 | } |
1090 | ||
a7813a04 | 1091 | pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability { |
a1dfa0c6 XL |
1092 | self.stability_interner.borrow_mut().intern(stab, |stab| { |
1093 | self.global_interners.arena.alloc(stab) | |
1094 | }) | |
54a0048b SL |
1095 | } |
1096 | ||
ff7c6d11 | 1097 | pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails { |
a1dfa0c6 XL |
1098 | self.layout_interner.borrow_mut().intern(layout, |layout| { |
1099 | self.global_arenas.layout.alloc(layout) | |
1100 | }) | |
e9174d1e SL |
1101 | } |
1102 | ||
b7449926 XL |
1103 | /// Returns a range of the start/end indices specified with the |
1104 | /// `rustc_layout_scalar_valid_range` attribute. | |
1105 | pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) { | |
1106 | let attrs = self.get_attrs(def_id); | |
1107 | let get = |name| { | |
1108 | let attr = match attrs.iter().find(|a| a.check_name(name)) { | |
1109 | Some(attr) => attr, | |
1110 | None => return Bound::Unbounded, | |
1111 | }; | |
1112 | for meta in attr.meta_item_list().expect("rustc_layout_scalar_valid_range takes args") { | |
1113 | match meta.literal().expect("attribute takes lit").node { | |
1114 | ast::LitKind::Int(a, _) => return Bound::Included(a), | |
1115 | _ => span_bug!(attr.span, "rustc_layout_scalar_valid_range expects int arg"), | |
1116 | } | |
1117 | } | |
1118 | span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute"); | |
1119 | }; | |
1120 | (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end")) | |
1121 | } | |
1122 | ||
a7813a04 | 1123 | pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> { |
e9174d1e SL |
1124 | value.lift_to_tcx(self) |
1125 | } | |
1126 | ||
a7813a04 XL |
1127 | /// Like lift, but only tries in the global tcx. |
1128 | pub fn lift_to_global<T: ?Sized + Lift<'gcx>>(self, value: &T) -> Option<T::Lifted> { | |
1129 | value.lift_to_tcx(self.global_tcx()) | |
1130 | } | |
1131 | ||
1132 | /// Returns true if self is the same as self.global_tcx(). | |
1133 | fn is_global(self) -> bool { | |
0731742a | 1134 | ptr::eq(self.interners, &self.global_interners) |
a7813a04 XL |
1135 | } |
1136 | ||
1137 | /// Create a type context and call the closure with a `TyCtxt` reference | |
e9174d1e SL |
1138 | /// to the context. The closure enforces that the type context and any interned |
1139 | /// value (types, substs, etc.) can only be used while `ty::tls` has a valid | |
1140 | /// reference to the context, to allow formatting values that need it. | |
b039eaaf | 1141 | pub fn create_and_enter<F, R>(s: &'tcx Session, |
94b46f34 XL |
1142 | cstore: &'tcx CrateStoreDyn, |
1143 | local_providers: ty::query::Providers<'tcx>, | |
1144 | extern_providers: ty::query::Providers<'tcx>, | |
0731742a | 1145 | arenas: &'tcx mut AllArenas<'tcx>, |
32a655c1 | 1146 | resolutions: ty::Resolutions, |
32a655c1 | 1147 | hir: hir_map::Map<'tcx>, |
94b46f34 | 1148 | on_disk_query_result_cache: query::OnDiskCache<'tcx>, |
32a655c1 | 1149 | crate_name: &str, |
0531ce1d | 1150 | tx: mpsc::Sender<Box<dyn Any + Send>>, |
ea8adc8c | 1151 | output_filenames: &OutputFilenames, |
a7813a04 XL |
1152 | f: F) -> R |
1153 | where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R | |
e9174d1e | 1154 | { |
83c7162d XL |
1155 | let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| { |
1156 | s.fatal(&err); | |
1157 | }); | |
ff7c6d11 | 1158 | let interners = CtxtInterners::new(&arenas.interner); |
a7813a04 | 1159 | let common_types = CommonTypes::new(&interners); |
32a655c1 | 1160 | let dep_graph = hir.dep_graph.clone(); |
ea8adc8c | 1161 | let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); |
8bb4bdeb XL |
1162 | let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); |
1163 | providers[LOCAL_CRATE] = local_providers; | |
7cac9316 XL |
1164 | |
1165 | let def_path_hash_to_def_id = if s.opts.build_dep_graph() { | |
0531ce1d | 1166 | let upstream_def_path_tables: Vec<(CrateNum, Lrc<_>)> = cstore |
ea8adc8c | 1167 | .crates_untracked() |
7cac9316 | 1168 | .iter() |
ea8adc8c | 1169 | .map(|&cnum| (cnum, cstore.def_path_table(cnum))) |
7cac9316 XL |
1170 | .collect(); |
1171 | ||
1172 | let def_path_tables = || { | |
1173 | upstream_def_path_tables | |
1174 | .iter() | |
1175 | .map(|&(cnum, ref rc)| (cnum, &**rc)) | |
1176 | .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))) | |
1177 | }; | |
1178 | ||
1179 | // Precompute the capacity of the hashmap so we don't have to | |
1180 | // re-allocate when populating it. | |
1181 | let capacity = def_path_tables().map(|(_, t)| t.size()).sum::<usize>(); | |
1182 | ||
1183 | let mut map: FxHashMap<_, _> = FxHashMap::with_capacity_and_hasher( | |
1184 | capacity, | |
1185 | ::std::default::Default::default() | |
1186 | ); | |
1187 | ||
1188 | for (cnum, def_path_table) in def_path_tables() { | |
1189 | def_path_table.add_def_path_hashes_to(cnum, &mut map); | |
1190 | } | |
1191 | ||
1192 | Some(map) | |
1193 | } else { | |
1194 | None | |
1195 | }; | |
1196 | ||
0bf4aa26 | 1197 | let mut trait_map: FxHashMap<_, Lrc<FxHashMap<_, _>>> = FxHashMap::default(); |
ea8adc8c XL |
1198 | for (k, v) in resolutions.trait_map { |
1199 | let hir_id = hir.node_to_hir_id(k); | |
b7449926 | 1200 | let map = trait_map.entry(hir_id.owner).or_default(); |
0531ce1d | 1201 | Lrc::get_mut(map).unwrap() |
0bf4aa26 XL |
1202 | .insert(hir_id.local_id, |
1203 | Lrc::new(StableVec::new(v))); | |
ea8adc8c | 1204 | } |
ea8adc8c | 1205 | |
0731742a | 1206 | arenas.global_ctxt = Some(GlobalCtxt { |
8bb4bdeb | 1207 | sess: s, |
ea8adc8c | 1208 | cstore, |
ff7c6d11 | 1209 | global_arenas: &arenas.global, |
a7813a04 | 1210 | global_interners: interners, |
0bf4aa26 | 1211 | dep_graph, |
e9174d1e | 1212 | types: common_types, |
ea8adc8c XL |
1213 | trait_map, |
1214 | export_map: resolutions.export_map.into_iter().map(|(k, v)| { | |
0531ce1d | 1215 | (k, Lrc::new(v)) |
ea8adc8c XL |
1216 | }).collect(), |
1217 | freevars: resolutions.freevars.into_iter().map(|(k, v)| { | |
0531ce1d | 1218 | (hir.local_def_id(k), Lrc::new(v)) |
ea8adc8c XL |
1219 | }).collect(), |
1220 | maybe_unused_trait_imports: | |
1221 | resolutions.maybe_unused_trait_imports | |
1222 | .into_iter() | |
1223 | .map(|id| hir.local_def_id(id)) | |
1224 | .collect(), | |
1225 | maybe_unused_extern_crates: | |
1226 | resolutions.maybe_unused_extern_crates | |
1227 | .into_iter() | |
1228 | .map(|(id, sp)| (hir.local_def_id(id), sp)) | |
1229 | .collect(), | |
4462d4a0 | 1230 | extern_prelude: resolutions.extern_prelude, |
0731742a | 1231 | hir_map: hir, |
041b39d2 | 1232 | def_path_hash_to_def_id, |
b7449926 XL |
1233 | queries: query::Queries::new( |
1234 | providers, | |
1235 | extern_providers, | |
1236 | on_disk_query_result_cache, | |
1237 | ), | |
0bf4aa26 XL |
1238 | rcache: Default::default(), |
1239 | selection_cache: Default::default(), | |
1240 | evaluation_cache: Default::default(), | |
476ff2be | 1241 | crate_name: Symbol::intern(crate_name), |
041b39d2 | 1242 | data_layout, |
0bf4aa26 XL |
1243 | layout_interner: Default::default(), |
1244 | stability_interner: Default::default(), | |
1245 | allocation_interner: Default::default(), | |
94b46f34 | 1246 | alloc_map: Lock::new(interpret::AllocMap::new()), |
83c7162d | 1247 | tx_to_llvm_workers: Lock::new(tx), |
ea8adc8c | 1248 | output_filenames: Arc::new(output_filenames.clone()), |
0731742a XL |
1249 | }); |
1250 | ||
1251 | let gcx = arenas.global_ctxt.as_ref().unwrap(); | |
83c7162d | 1252 | |
94b46f34 XL |
1253 | sync::assert_send_val(&gcx); |
1254 | ||
0731742a XL |
1255 | let r = tls::enter_global(gcx, f); |
1256 | ||
1257 | gcx.queries.record_computed_queries(s); | |
1258 | ||
1259 | r | |
e9174d1e | 1260 | } |
cc61c64b XL |
1261 | |
1262 | pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool { | |
1263 | let cname = self.crate_name(LOCAL_CRATE).as_str(); | |
1264 | self.sess.consider_optimizing(&cname, msg) | |
1265 | } | |
ea8adc8c | 1266 | |
b7449926 XL |
1267 | pub fn lib_features(self) -> Lrc<middle::lib_features::LibFeatures> { |
1268 | self.get_lib_features(LOCAL_CRATE) | |
1269 | } | |
1270 | ||
0531ce1d | 1271 | pub fn lang_items(self) -> Lrc<middle::lang_items::LanguageItems> { |
ea8adc8c XL |
1272 | self.get_lang_items(LOCAL_CRATE) |
1273 | } | |
1274 | ||
0531ce1d XL |
1275 | /// Due to missing llvm support for lowering 128 bit math to software emulation |
1276 | /// (on some targets), the lowering can be done in MIR. | |
1277 | /// | |
1278 | /// This function only exists until said support is implemented. | |
1279 | pub fn is_binop_lang_item(&self, def_id: DefId) -> Option<(mir::BinOp, bool)> { | |
1280 | let items = self.lang_items(); | |
1281 | let def_id = Some(def_id); | |
1282 | if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) } | |
1283 | else if items.u128_add_fn() == def_id { Some((mir::BinOp::Add, false)) } | |
1284 | else if items.i128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) } | |
1285 | else if items.u128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) } | |
1286 | else if items.i128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) } | |
1287 | else if items.u128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) } | |
1288 | else if items.i128_div_fn() == def_id { Some((mir::BinOp::Div, false)) } | |
1289 | else if items.u128_div_fn() == def_id { Some((mir::BinOp::Div, false)) } | |
1290 | else if items.i128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) } | |
1291 | else if items.u128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) } | |
1292 | else if items.i128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) } | |
1293 | else if items.u128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) } | |
1294 | else if items.i128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) } | |
1295 | else if items.u128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) } | |
1296 | else if items.i128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) } | |
1297 | else if items.u128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) } | |
1298 | else if items.i128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) } | |
1299 | else if items.u128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) } | |
1300 | else if items.i128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) } | |
1301 | else if items.u128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) } | |
1302 | else if items.i128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) } | |
1303 | else if items.u128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) } | |
1304 | else if items.i128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) } | |
1305 | else if items.u128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) } | |
1306 | else { None } | |
1307 | } | |
1308 | ||
1309 | pub fn stability(self) -> Lrc<stability::Index<'tcx>> { | |
ff7c6d11 | 1310 | self.stability_index(LOCAL_CRATE) |
ea8adc8c XL |
1311 | } |
1312 | ||
0531ce1d | 1313 | pub fn crates(self) -> Lrc<Vec<CrateNum>> { |
ea8adc8c XL |
1314 | self.all_crate_nums(LOCAL_CRATE) |
1315 | } | |
1316 | ||
0531ce1d XL |
1317 | pub fn features(self) -> Lrc<feature_gate::Features> { |
1318 | self.features_query(LOCAL_CRATE) | |
1319 | } | |
1320 | ||
ea8adc8c XL |
1321 | pub fn def_key(self, id: DefId) -> hir_map::DefKey { |
1322 | if id.is_local() { | |
0731742a | 1323 | self.hir().def_key(id) |
ea8adc8c XL |
1324 | } else { |
1325 | self.cstore.def_key(id) | |
1326 | } | |
1327 | } | |
1328 | ||
1329 | /// Convert a `DefId` into its fully expanded `DefPath` (every | |
1330 | /// `DefId` is really just an interned def-path). | |
1331 | /// | |
1332 | /// Note that if `id` is not local to this crate, the result will | |
1333 | /// be a non-local `DefPath`. | |
1334 | pub fn def_path(self, id: DefId) -> hir_map::DefPath { | |
1335 | if id.is_local() { | |
0731742a | 1336 | self.hir().def_path(id) |
ea8adc8c XL |
1337 | } else { |
1338 | self.cstore.def_path(id) | |
1339 | } | |
1340 | } | |
1341 | ||
1342 | #[inline] | |
1343 | pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { | |
1344 | if def_id.is_local() { | |
0731742a | 1345 | self.hir().definitions().def_path_hash(def_id.index) |
ea8adc8c XL |
1346 | } else { |
1347 | self.cstore.def_path_hash(def_id) | |
1348 | } | |
1349 | } | |
1350 | ||
1351 | pub fn def_path_debug_str(self, def_id: DefId) -> String { | |
1352 | // We are explicitly not going through queries here in order to get | |
1353 | // crate name and disambiguator since this code is called from debug!() | |
1354 | // statements within the query system and we'd run into endless | |
1355 | // recursion otherwise. | |
1356 | let (crate_name, crate_disambiguator) = if def_id.is_local() { | |
1357 | (self.crate_name.clone(), | |
1358 | self.sess.local_crate_disambiguator()) | |
1359 | } else { | |
1360 | (self.cstore.crate_name_untracked(def_id.krate), | |
1361 | self.cstore.crate_disambiguator_untracked(def_id.krate)) | |
1362 | }; | |
1363 | ||
1364 | format!("{}[{}]{}", | |
1365 | crate_name, | |
1366 | // Don't print the whole crate disambiguator. That's just | |
1367 | // annoying in debug output. | |
abe05a73 | 1368 | &(crate_disambiguator.to_fingerprint().to_hex())[..4], |
ea8adc8c XL |
1369 | self.def_path(def_id).to_string_no_crate()) |
1370 | } | |
1371 | ||
1372 | pub fn metadata_encoding_version(self) -> Vec<u8> { | |
1373 | self.cstore.metadata_encoding_version().to_vec() | |
1374 | } | |
1375 | ||
1376 | // Note that this is *untracked* and should only be used within the query | |
1377 | // system if the result is otherwise tracked through queries | |
0531ce1d | 1378 | pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc<dyn Any> { |
ea8adc8c XL |
1379 | self.cstore.crate_data_as_rc_any(cnum) |
1380 | } | |
1381 | ||
0731742a | 1382 | #[inline(always)] |
0531ce1d | 1383 | pub fn create_stable_hashing_context(self) -> StableHashingContext<'a> { |
0731742a | 1384 | let krate = self.gcx.hir_map.forest.untracked_krate(); |
ea8adc8c XL |
1385 | |
1386 | StableHashingContext::new(self.sess, | |
1387 | krate, | |
0731742a | 1388 | self.hir().definitions(), |
ea8adc8c XL |
1389 | self.cstore) |
1390 | } | |
1391 | ||
1392 | // This method makes sure that we have a DepNode and a Fingerprint for | |
1393 | // every upstream crate. It needs to be called once right after the tcx is | |
1394 | // created. | |
1395 | // With full-fledged red/green, the method will probably become unnecessary | |
1396 | // as this will be done on-demand. | |
1397 | pub fn allocate_metadata_dep_nodes(self) { | |
1398 | // We cannot use the query versions of crates() and crate_hash(), since | |
1399 | // those would need the DepNodes that we are allocating here. | |
1400 | for cnum in self.cstore.crates_untracked() { | |
1401 | let dep_node = DepNode::new(self, DepConstructor::CrateMetadata(cnum)); | |
1402 | let crate_hash = self.cstore.crate_hash_untracked(cnum); | |
1403 | self.dep_graph.with_task(dep_node, | |
1404 | self, | |
1405 | crate_hash, | |
1406 | |_, x| x // No transformation needed | |
1407 | ); | |
1408 | } | |
1409 | } | |
1410 | ||
1411 | // This method exercises the `in_scope_traits_map` query for all possible | |
1412 | // values so that we have their fingerprints available in the DepGraph. | |
1413 | // This is only required as long as we still use the old dependency tracking | |
1414 | // which needs to have the fingerprints of all input nodes beforehand. | |
1415 | pub fn precompute_in_scope_traits_hashes(self) { | |
1416 | for &def_index in self.trait_map.keys() { | |
1417 | self.in_scope_traits_map(def_index); | |
1418 | } | |
1419 | } | |
abe05a73 XL |
1420 | |
1421 | pub fn serialize_query_result_cache<E>(self, | |
1422 | encoder: &mut E) | |
1423 | -> Result<(), E::Error> | |
1424 | where E: ty::codec::TyEncoder | |
1425 | { | |
94b46f34 XL |
1426 | self.queries.on_disk_cache.serialize(self.global_tcx(), encoder) |
1427 | } | |
1428 | ||
0bf4aa26 XL |
1429 | /// This checks whether one is allowed to have pattern bindings |
1430 | /// that bind-by-move on a match arm that has a guard, e.g.: | |
1431 | /// | |
1432 | /// ```rust | |
1433 | /// match foo { A(inner) if { /* something */ } => ..., ... } | |
1434 | /// ``` | |
1435 | /// | |
1436 | /// It is separate from check_for_mutation_in_guard_via_ast_walk, | |
1437 | /// because that method has a narrower effect that can be toggled | |
1438 | /// off via a separate `-Z` flag, at least for the short term. | |
1439 | pub fn allow_bind_by_move_patterns_with_guards(self) -> bool { | |
1440 | self.features().bind_by_move_pattern_guards && self.use_mir_borrowck() | |
1441 | } | |
1442 | ||
94b46f34 XL |
1443 | /// If true, we should use a naive AST walk to determine if match |
1444 | /// guard could perform bad mutations (or mutable-borrows). | |
1445 | pub fn check_for_mutation_in_guard_via_ast_walk(self) -> bool { | |
0bf4aa26 XL |
1446 | // If someone requests the feature, then be a little more |
1447 | // careful and ensure that MIR-borrowck is enabled (which can | |
1448 | // happen via edition selection, via `feature(nll)`, or via an | |
1449 | // appropriate `-Z` flag) before disabling the mutation check. | |
1450 | if self.allow_bind_by_move_patterns_with_guards() { | |
1451 | return false; | |
1452 | } | |
1453 | ||
1454 | return true; | |
abe05a73 XL |
1455 | } |
1456 | ||
8faf50e0 XL |
1457 | /// If true, we should use the AST-based borrowck (we may *also* use |
1458 | /// the MIR-based borrowck). | |
1459 | pub fn use_ast_borrowck(self) -> bool { | |
1460 | self.borrowck_mode().use_ast() | |
1461 | } | |
1462 | ||
0531ce1d XL |
1463 | /// If true, we should use the MIR-based borrowck (we may *also* use |
1464 | /// the AST-based borrowck). | |
83c7162d XL |
1465 | pub fn use_mir_borrowck(self) -> bool { |
1466 | self.borrowck_mode().use_mir() | |
1467 | } | |
1468 | ||
8faf50e0 XL |
1469 | /// If true, we should use the MIR-based borrow check, but also |
1470 | /// fall back on the AST borrow check if the MIR-based one errors. | |
1471 | pub fn migrate_borrowck(self) -> bool { | |
1472 | self.borrowck_mode().migrate() | |
1473 | } | |
1474 | ||
94b46f34 XL |
1475 | /// If true, make MIR codegen for `match` emit a temp that holds a |
1476 | /// borrow of the input to the match expression. | |
1477 | pub fn generate_borrow_of_any_match_input(&self) -> bool { | |
1478 | self.emit_read_for_match() | |
1479 | } | |
1480 | ||
0bf4aa26 | 1481 | /// If true, make MIR codegen for `match` emit FakeRead |
94b46f34 XL |
1482 | /// statements (which simulate the maximal effect of executing the |
1483 | /// patterns in a match arm). | |
1484 | pub fn emit_read_for_match(&self) -> bool { | |
1485 | self.use_mir_borrowck() && !self.sess.opts.debugging_opts.nll_dont_emit_read_for_match | |
1486 | } | |
1487 | ||
83c7162d XL |
1488 | /// If true, pattern variables for use in guards on match arms |
1489 | /// will be bound as references to the data, and occurrences of | |
1490 | /// those variables in the guard expression will implicitly | |
1491 | /// dereference those bindings. (See rust-lang/rust#27282.) | |
1492 | pub fn all_pat_vars_are_implicit_refs_within_guards(self) -> bool { | |
0531ce1d XL |
1493 | self.borrowck_mode().use_mir() |
1494 | } | |
1495 | ||
1496 | /// If true, we should enable two-phase borrows checks. This is | |
b7449926 XL |
1497 | /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`, |
1498 | /// or by opting into an edition after 2015. | |
0531ce1d | 1499 | pub fn two_phase_borrows(self) -> bool { |
13cf67c4 XL |
1500 | self.sess.rust_2018() || self.features().nll || |
1501 | self.sess.opts.debugging_opts.two_phase_borrows | |
0531ce1d XL |
1502 | } |
1503 | ||
1504 | /// What mode(s) of borrowck should we run? AST? MIR? both? | |
1505 | /// (Also considers the `#![feature(nll)]` setting.) | |
1506 | pub fn borrowck_mode(&self) -> BorrowckMode { | |
8faf50e0 XL |
1507 | // Here are the main constraints we need to deal with: |
1508 | // | |
1509 | // 1. An opts.borrowck_mode of `BorrowckMode::Ast` is | |
1510 | // synonymous with no `-Z borrowck=...` flag at all. | |
1511 | // (This is arguably a historical accident.) | |
1512 | // | |
1513 | // 2. `BorrowckMode::Migrate` is the limited migration to | |
1514 | // NLL that we are deploying with the 2018 edition. | |
1515 | // | |
1516 | // 3. We want to allow developers on the Nightly channel | |
1517 | // to opt back into the "hard error" mode for NLL, | |
1518 | // (which they can do via specifying `#![feature(nll)]` | |
1519 | // explicitly in their crate). | |
1520 | // | |
1521 | // So, this precedence list is how pnkfelix chose to work with | |
1522 | // the above constraints: | |
1523 | // | |
1524 | // * `#![feature(nll)]` *always* means use NLL with hard | |
1525 | // errors. (To simplify the code here, it now even overrides | |
1526 | // a user's attempt to specify `-Z borrowck=compare`, which | |
1527 | // we arguably do not need anymore and should remove.) | |
1528 | // | |
1529 | // * Otherwise, if no `-Z borrowck=...` flag was given (or | |
1530 | // if `borrowck=ast` was specified), then use the default | |
1531 | // as required by the edition. | |
1532 | // | |
1533 | // * Otherwise, use the behavior requested via `-Z borrowck=...` | |
1534 | ||
1535 | if self.features().nll { return BorrowckMode::Mir; } | |
1536 | ||
0531ce1d XL |
1537 | match self.sess.opts.borrowck_mode { |
1538 | mode @ BorrowckMode::Mir | | |
8faf50e0 XL |
1539 | mode @ BorrowckMode::Compare | |
1540 | mode @ BorrowckMode::Migrate => mode, | |
1541 | ||
1542 | BorrowckMode::Ast => match self.sess.edition() { | |
1543 | Edition::Edition2015 => BorrowckMode::Ast, | |
1544 | Edition::Edition2018 => BorrowckMode::Migrate, | |
8faf50e0 | 1545 | }, |
0531ce1d XL |
1546 | } |
1547 | } | |
1548 | ||
83c7162d XL |
1549 | #[inline] |
1550 | pub fn local_crate_exports_generics(self) -> bool { | |
b7449926 | 1551 | debug_assert!(self.sess.opts.share_generics()); |
83c7162d XL |
1552 | |
1553 | self.sess.crate_types.borrow().iter().any(|crate_type| { | |
1554 | match crate_type { | |
b7449926 XL |
1555 | CrateType::Executable | |
1556 | CrateType::Staticlib | | |
1557 | CrateType::ProcMacro | | |
1558 | CrateType::Cdylib => false, | |
1559 | CrateType::Rlib | | |
1560 | CrateType::Dylib => true, | |
83c7162d XL |
1561 | } |
1562 | }) | |
0531ce1d | 1563 | } |
0bf4aa26 XL |
1564 | |
1565 | // This method returns the DefId and the BoundRegion corresponding to the given region. | |
1566 | pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> { | |
1567 | let (suitable_region_binding_scope, bound_region) = match *region { | |
1568 | ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), | |
1569 | ty::ReEarlyBound(ref ebr) => ( | |
1570 | self.parent_def_id(ebr.def_id).unwrap(), | |
1571 | ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), | |
1572 | ), | |
1573 | _ => return None, // not a free region | |
1574 | }; | |
1575 | ||
0731742a | 1576 | let node_id = self.hir() |
0bf4aa26 XL |
1577 | .as_local_node_id(suitable_region_binding_scope) |
1578 | .unwrap(); | |
0731742a | 1579 | let is_impl_item = match self.hir().find(node_id) { |
0bf4aa26 XL |
1580 | Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false, |
1581 | Some(Node::ImplItem(..)) => { | |
1582 | self.is_bound_region_in_impl_item(suitable_region_binding_scope) | |
1583 | } | |
1584 | _ => return None, | |
1585 | }; | |
1586 | ||
1587 | return Some(FreeRegionInfo { | |
1588 | def_id: suitable_region_binding_scope, | |
1589 | boundregion: bound_region, | |
1590 | is_impl_item: is_impl_item, | |
1591 | }); | |
1592 | } | |
1593 | ||
1594 | pub fn return_type_impl_trait( | |
1595 | &self, | |
1596 | scope_def_id: DefId, | |
1597 | ) -> Option<Ty<'tcx>> { | |
13cf67c4 | 1598 | // HACK: `type_of_def_id()` will fail on these (#55796), so return None |
0731742a XL |
1599 | let node_id = self.hir().as_local_node_id(scope_def_id).unwrap(); |
1600 | match self.hir().get(node_id) { | |
13cf67c4 XL |
1601 | Node::Item(item) => { |
1602 | match item.node { | |
1603 | ItemKind::Fn(..) => { /* type_of_def_id() will work */ } | |
1604 | _ => { | |
1605 | return None; | |
1606 | } | |
1607 | } | |
1608 | } | |
1609 | _ => { /* type_of_def_id() will work or panic */ } | |
1610 | } | |
1611 | ||
0bf4aa26 XL |
1612 | let ret_ty = self.type_of(scope_def_id); |
1613 | match ret_ty.sty { | |
1614 | ty::FnDef(_, _) => { | |
1615 | let sig = ret_ty.fn_sig(*self); | |
1616 | let output = self.erase_late_bound_regions(&sig.output()); | |
1617 | if output.is_impl_trait() { | |
1618 | Some(output) | |
1619 | } else { | |
1620 | None | |
1621 | } | |
1622 | } | |
1623 | _ => None | |
1624 | } | |
1625 | } | |
1626 | ||
1627 | // Here we check if the bound region is in Impl Item. | |
1628 | pub fn is_bound_region_in_impl_item( | |
1629 | &self, | |
1630 | suitable_region_binding_scope: DefId, | |
1631 | ) -> bool { | |
1632 | let container_id = self.associated_item(suitable_region_binding_scope) | |
1633 | .container | |
1634 | .id(); | |
1635 | if self.impl_trait_ref(container_id).is_some() { | |
1636 | // For now, we do not try to target impls of traits. This is | |
1637 | // because this message is going to suggest that the user | |
1638 | // change the fn signature, but they may not be free to do so, | |
1639 | // since the signature must match the trait. | |
1640 | // | |
1641 | // FIXME(#42706) -- in some cases, we could do better here. | |
1642 | return true; | |
1643 | } | |
1644 | false | |
1645 | } | |
ea8adc8c XL |
1646 | } |
1647 | ||
1648 | impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { | |
b7449926 | 1649 | pub fn encode_metadata(self) |
ff7c6d11 | 1650 | -> EncodedMetadata |
ea8adc8c | 1651 | { |
b7449926 | 1652 | self.cstore.encode_metadata(self) |
ea8adc8c | 1653 | } |
e9174d1e SL |
1654 | } |
1655 | ||
0731742a | 1656 | impl<'gcx> GlobalCtxt<'gcx> { |
32a655c1 | 1657 | /// Call the closure with a local `TyCtxt` using the given arena. |
0731742a XL |
1658 | /// `interners` is a slot passed so we can create a CtxtInterners |
1659 | /// with the same lifetime as `arena`. | |
1660 | pub fn enter_local<'tcx, F, R>( | |
1661 | &'gcx self, | |
83c7162d | 1662 | arena: &'tcx SyncDroplessArena, |
0731742a | 1663 | interners: &'tcx mut Option<CtxtInterners<'tcx>>, |
83c7162d XL |
1664 | f: F |
1665 | ) -> R | |
1666 | where | |
0731742a XL |
1667 | F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R, |
1668 | 'gcx: 'tcx, | |
a7813a04 | 1669 | { |
0731742a | 1670 | *interners = Some(CtxtInterners::new(&arena)); |
83c7162d XL |
1671 | let tcx = TyCtxt { |
1672 | gcx: self, | |
0731742a XL |
1673 | interners: interners.as_ref().unwrap(), |
1674 | dummy: PhantomData, | |
83c7162d XL |
1675 | }; |
1676 | ty::tls::with_related_context(tcx.global_tcx(), |icx| { | |
1677 | let new_icx = ty::tls::ImplicitCtxt { | |
1678 | tcx, | |
1679 | query: icx.query.clone(), | |
0731742a | 1680 | diagnostics: icx.diagnostics, |
83c7162d | 1681 | layout_depth: icx.layout_depth, |
0731742a | 1682 | task_deps: icx.task_deps, |
83c7162d | 1683 | }; |
0731742a XL |
1684 | ty::tls::enter_context(&new_icx, |_| { |
1685 | f(tcx) | |
83c7162d XL |
1686 | }) |
1687 | }) | |
a7813a04 XL |
1688 | } |
1689 | } | |
1690 | ||
e9174d1e SL |
1691 | /// A trait implemented for all X<'a> types which can be safely and |
1692 | /// efficiently converted to X<'tcx> as long as they are part of the | |
54a0048b | 1693 | /// provided TyCtxt<'tcx>. |
e9174d1e SL |
1694 | /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx> |
1695 | /// by looking them up in their respective interners. | |
a7813a04 XL |
1696 | /// |
1697 | /// However, this is still not the best implementation as it does | |
1698 | /// need to compare the components, even for interned values. | |
1699 | /// It would be more efficient if TypedArena provided a way to | |
1700 | /// determine whether the address is in the allocated range. | |
1701 | /// | |
e9174d1e SL |
1702 | /// None is returned if the value or one of the components is not part |
1703 | /// of the provided context. | |
1704 | /// For Ty, None can be returned if either the type interner doesn't | |
b7449926 | 1705 | /// contain the TyKind key or if the address of the interned |
e9174d1e | 1706 | /// pointer differs. The latter case is possible if a primitive type, |
0731742a | 1707 | /// e.g., `()` or `u8`, was interned in a different context. |
8faf50e0 XL |
1708 | pub trait Lift<'tcx>: fmt::Debug { |
1709 | type Lifted: fmt::Debug + 'tcx; | |
a7813a04 | 1710 | fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>; |
e9174d1e SL |
1711 | } |
1712 | ||
a7813a04 | 1713 | |
0731742a XL |
1714 | macro_rules! nop_lift { |
1715 | ($ty:ty => $lifted:ty) => { | |
1716 | impl<'a, 'tcx> Lift<'tcx> for $ty { | |
1717 | type Lifted = $lifted; | |
1718 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> { | |
1719 | if tcx.interners.arena.in_arena(*self as *const _) { | |
1720 | return Some(unsafe { mem::transmute(*self) }); | |
1721 | } | |
1722 | // Also try in the global tcx if we're not that. | |
1723 | if !tcx.is_global() { | |
1724 | self.lift_to_tcx(tcx.global_tcx()) | |
1725 | } else { | |
1726 | None | |
1727 | } | |
1728 | } | |
ea8adc8c | 1729 | } |
0731742a | 1730 | }; |
ea8adc8c XL |
1731 | } |
1732 | ||
0731742a XL |
1733 | macro_rules! nop_list_lift { |
1734 | ($ty:ty => $lifted:ty) => { | |
1735 | impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { | |
1736 | type Lifted = &'tcx List<$lifted>; | |
1737 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> { | |
1738 | if self.is_empty() { | |
1739 | return Some(List::empty()); | |
1740 | } | |
1741 | if tcx.interners.arena.in_arena(*self as *const _) { | |
1742 | return Some(unsafe { mem::transmute(*self) }); | |
1743 | } | |
1744 | // Also try in the global tcx if we're not that. | |
1745 | if !tcx.is_global() { | |
1746 | self.lift_to_tcx(tcx.global_tcx()) | |
1747 | } else { | |
1748 | None | |
1749 | } | |
1750 | } | |
a7813a04 | 1751 | } |
0731742a | 1752 | }; |
a7813a04 XL |
1753 | } |
1754 | ||
0731742a XL |
1755 | nop_lift!{Ty<'a> => Ty<'tcx>} |
1756 | nop_lift!{Region<'a> => Region<'tcx>} | |
1757 | nop_lift!{Goal<'a> => Goal<'tcx>} | |
1758 | nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>} | |
476ff2be | 1759 | |
0731742a XL |
1760 | nop_list_lift!{Goal<'a> => Goal<'tcx>} |
1761 | nop_list_lift!{Clause<'a> => Clause<'tcx>} | |
1762 | nop_list_lift!{Ty<'a> => Ty<'tcx>} | |
1763 | nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>} | |
1764 | nop_list_lift!{Predicate<'a> => Predicate<'tcx>} | |
1765 | nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo} | |
1766 | nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>} | |
7cac9316 | 1767 | |
0731742a XL |
1768 | // this is the impl for `&'a Substs<'a>` |
1769 | nop_list_lift!{Kind<'a> => Kind<'tcx>} | |
0531ce1d | 1770 | |
0731742a XL |
1771 | impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { |
1772 | type Lifted = &'tcx mir::interpret::Allocation; | |
0bf4aa26 | 1773 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> { |
0731742a XL |
1774 | assert!(tcx.global_arenas.const_allocs.in_arena(*self as *const _)); |
1775 | Some(unsafe { mem::transmute(*self) }) | |
0bf4aa26 XL |
1776 | } |
1777 | } | |
1778 | ||
e9174d1e | 1779 | pub mod tls { |
83c7162d | 1780 | use super::{GlobalCtxt, TyCtxt}; |
e9174d1e SL |
1781 | |
1782 | use std::fmt; | |
83c7162d | 1783 | use std::mem; |
0731742a XL |
1784 | use std::marker::PhantomData; |
1785 | use std::ptr; | |
3157f602 | 1786 | use syntax_pos; |
94b46f34 | 1787 | use ty::query; |
83c7162d XL |
1788 | use errors::{Diagnostic, TRACK_DIAGNOSTICS}; |
1789 | use rustc_data_structures::OnDrop; | |
94b46f34 | 1790 | use rustc_data_structures::sync::{self, Lrc, Lock}; |
0731742a XL |
1791 | use rustc_data_structures::thin_vec::ThinVec; |
1792 | use dep_graph::TaskDeps; | |
83c7162d | 1793 | |
94b46f34 XL |
1794 | #[cfg(not(parallel_queries))] |
1795 | use std::cell::Cell; | |
1796 | ||
1797 | #[cfg(parallel_queries)] | |
1798 | use rayon_core; | |
1799 | ||
83c7162d XL |
1800 | /// This is the implicit state of rustc. It contains the current |
1801 | /// TyCtxt and query. It is updated when creating a local interner or | |
1802 | /// executing a new query. Whenever there's a TyCtxt value available | |
1803 | /// you should also have access to an ImplicitCtxt through the functions | |
1804 | /// in this module. | |
1805 | #[derive(Clone)] | |
0731742a | 1806 | pub struct ImplicitCtxt<'a, 'gcx: 'tcx, 'tcx> { |
83c7162d XL |
1807 | /// The current TyCtxt. Initially created by `enter_global` and updated |
1808 | /// by `enter_local` with a new local interner | |
0731742a | 1809 | pub tcx: TyCtxt<'tcx, 'gcx, 'tcx>, |
83c7162d | 1810 | |
0731742a | 1811 | /// The current query job, if any. This is updated by JobOwner::start in |
94b46f34 XL |
1812 | /// ty::query::plumbing when executing a query |
1813 | pub query: Option<Lrc<query::QueryJob<'gcx>>>, | |
83c7162d | 1814 | |
0731742a XL |
1815 | /// Where to store diagnostics for the current query job, if any. |
1816 | /// This is updated by JobOwner::start in ty::query::plumbing when executing a query | |
1817 | pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>, | |
1818 | ||
83c7162d XL |
1819 | /// Used to prevent layout from recursing too deeply. |
1820 | pub layout_depth: usize, | |
1821 | ||
1822 | /// The current dep graph task. This is used to add dependencies to queries | |
1823 | /// when executing them | |
0731742a | 1824 | pub task_deps: Option<&'a Lock<TaskDeps>>, |
83c7162d XL |
1825 | } |
1826 | ||
94b46f34 XL |
1827 | /// Sets Rayon's thread local variable which is preserved for Rayon jobs |
1828 | /// to `value` during the call to `f`. It is restored to its previous value after. | |
1829 | /// This is used to set the pointer to the new ImplicitCtxt. | |
1830 | #[cfg(parallel_queries)] | |
0731742a | 1831 | #[inline] |
94b46f34 XL |
1832 | fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R { |
1833 | rayon_core::tlv::with(value, f) | |
1834 | } | |
1835 | ||
1836 | /// Gets Rayon's thread local variable which is preserved for Rayon jobs. | |
1837 | /// This is used to get the pointer to the current ImplicitCtxt. | |
1838 | #[cfg(parallel_queries)] | |
0731742a | 1839 | #[inline] |
94b46f34 XL |
1840 | fn get_tlv() -> usize { |
1841 | rayon_core::tlv::get() | |
1842 | } | |
1843 | ||
1844 | /// A thread local variable which stores a pointer to the current ImplicitCtxt | |
1845 | #[cfg(not(parallel_queries))] | |
83c7162d | 1846 | thread_local!(static TLV: Cell<usize> = Cell::new(0)); |
e9174d1e | 1847 | |
94b46f34 XL |
1848 | /// Sets TLV to `value` during the call to `f`. |
1849 | /// It is restored to its previous value after. | |
1850 | /// This is used to set the pointer to the new ImplicitCtxt. | |
1851 | #[cfg(not(parallel_queries))] | |
0731742a | 1852 | #[inline] |
83c7162d XL |
1853 | fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R { |
1854 | let old = get_tlv(); | |
1855 | let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old))); | |
1856 | TLV.with(|tlv| tlv.set(value)); | |
1857 | f() | |
1858 | } | |
e9174d1e | 1859 | |
94b46f34 XL |
1860 | /// This is used to get the pointer to the current ImplicitCtxt. |
1861 | #[cfg(not(parallel_queries))] | |
83c7162d XL |
1862 | fn get_tlv() -> usize { |
1863 | TLV.with(|tlv| tlv.get()) | |
7453a54e | 1864 | } |
e9174d1e | 1865 | |
83c7162d XL |
1866 | /// This is a callback from libsyntax as it cannot access the implicit state |
1867 | /// in librustc otherwise | |
0bf4aa26 | 1868 | fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
0731742a XL |
1869 | with_opt(|tcx| { |
1870 | if let Some(tcx) = tcx { | |
1871 | write!(f, "{}", tcx.sess.source_map().span_to_string(span)) | |
1872 | } else { | |
1873 | syntax_pos::default_span_debug(span, f) | |
1874 | } | |
e9174d1e SL |
1875 | }) |
1876 | } | |
1877 | ||
83c7162d XL |
1878 | /// This is a callback from libsyntax as it cannot access the implicit state |
1879 | /// in librustc otherwise. It is used to when diagnostic messages are | |
1880 | /// emitted and stores them in the current query, if there is one. | |
1881 | fn track_diagnostic(diagnostic: &Diagnostic) { | |
94b46f34 XL |
1882 | with_context_opt(|icx| { |
1883 | if let Some(icx) = icx { | |
0731742a XL |
1884 | if let Some(ref diagnostics) = icx.diagnostics { |
1885 | let mut diagnostics = diagnostics.lock(); | |
1886 | diagnostics.extend(Some(diagnostic.clone())); | |
94b46f34 | 1887 | } |
83c7162d XL |
1888 | } |
1889 | }) | |
1890 | } | |
1891 | ||
1892 | /// Sets up the callbacks from libsyntax on the current thread | |
1893 | pub fn with_thread_locals<F, R>(f: F) -> R | |
1894 | where F: FnOnce() -> R | |
a7813a04 | 1895 | { |
3157f602 | 1896 | syntax_pos::SPAN_DEBUG.with(|span_dbg| { |
e9174d1e SL |
1897 | let original_span_debug = span_dbg.get(); |
1898 | span_dbg.set(span_debug); | |
83c7162d XL |
1899 | |
1900 | let _on_drop = OnDrop(move || { | |
1901 | span_dbg.set(original_span_debug); | |
1902 | }); | |
1903 | ||
1904 | TRACK_DIAGNOSTICS.with(|current| { | |
1905 | let original = current.get(); | |
1906 | current.set(track_diagnostic); | |
1907 | ||
1908 | let _on_drop = OnDrop(move || { | |
1909 | current.set(original); | |
1910 | }); | |
1911 | ||
1912 | f() | |
1913 | }) | |
b039eaaf | 1914 | }) |
e9174d1e SL |
1915 | } |
1916 | ||
83c7162d | 1917 | /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f` |
0731742a | 1918 | #[inline] |
83c7162d XL |
1919 | pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>, |
1920 | f: F) -> R | |
1921 | where F: FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R | |
a7813a04 | 1922 | { |
83c7162d XL |
1923 | set_tlv(context as *const _ as usize, || { |
1924 | f(&context) | |
a7813a04 XL |
1925 | }) |
1926 | } | |
1927 | ||
83c7162d XL |
1928 | /// Enters GlobalCtxt by setting up libsyntax callbacks and |
1929 | /// creating a initial TyCtxt and ImplicitCtxt. | |
1930 | /// This happens once per rustc session and TyCtxts only exists | |
1931 | /// inside the `f` function. | |
0731742a XL |
1932 | pub fn enter_global<'gcx, F, R>(gcx: &'gcx GlobalCtxt<'gcx>, f: F) -> R |
1933 | where F: FnOnce(TyCtxt<'gcx, 'gcx, 'gcx>) -> R | |
a7813a04 | 1934 | { |
83c7162d | 1935 | with_thread_locals(|| { |
94b46f34 XL |
1936 | // Update GCX_PTR to indicate there's a GlobalCtxt available |
1937 | GCX_PTR.with(|lock| { | |
1938 | *lock.lock() = gcx as *const _ as usize; | |
1939 | }); | |
1940 | // Set GCX_PTR back to 0 when we exit | |
1941 | let _on_drop = OnDrop(move || { | |
1942 | GCX_PTR.with(|lock| *lock.lock() = 0); | |
1943 | }); | |
1944 | ||
83c7162d | 1945 | let tcx = TyCtxt { |
041b39d2 | 1946 | gcx, |
83c7162d | 1947 | interners: &gcx.global_interners, |
0731742a | 1948 | dummy: PhantomData, |
83c7162d XL |
1949 | }; |
1950 | let icx = ImplicitCtxt { | |
1951 | tcx, | |
1952 | query: None, | |
0731742a | 1953 | diagnostics: None, |
83c7162d | 1954 | layout_depth: 0, |
0731742a | 1955 | task_deps: None, |
83c7162d XL |
1956 | }; |
1957 | enter_context(&icx, |_| { | |
1958 | f(tcx) | |
a7813a04 | 1959 | }) |
7453a54e | 1960 | }) |
e9174d1e SL |
1961 | } |
1962 | ||
94b46f34 XL |
1963 | /// Stores a pointer to the GlobalCtxt if one is available. |
1964 | /// This is used to access the GlobalCtxt in the deadlock handler | |
1965 | /// given to Rayon. | |
1966 | scoped_thread_local!(pub static GCX_PTR: Lock<usize>); | |
1967 | ||
1968 | /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local. | |
1969 | /// This is used in the deadlock handler. | |
1970 | pub unsafe fn with_global<F, R>(f: F) -> R | |
1971 | where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
1972 | { | |
1973 | let gcx = GCX_PTR.with(|lock| *lock.lock()); | |
1974 | assert!(gcx != 0); | |
1975 | let gcx = &*(gcx as *const GlobalCtxt<'_>); | |
1976 | let tcx = TyCtxt { | |
1977 | gcx, | |
1978 | interners: &gcx.global_interners, | |
0731742a | 1979 | dummy: PhantomData, |
94b46f34 XL |
1980 | }; |
1981 | let icx = ImplicitCtxt { | |
1982 | query: None, | |
0731742a | 1983 | diagnostics: None, |
94b46f34 XL |
1984 | tcx, |
1985 | layout_depth: 0, | |
0731742a | 1986 | task_deps: None, |
94b46f34 XL |
1987 | }; |
1988 | enter_context(&icx, |_| f(tcx)) | |
1989 | } | |
1990 | ||
83c7162d | 1991 | /// Allows access to the current ImplicitCtxt in a closure if one is available |
0731742a | 1992 | #[inline] |
83c7162d XL |
1993 | pub fn with_context_opt<F, R>(f: F) -> R |
1994 | where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R | |
a7813a04 | 1995 | { |
83c7162d XL |
1996 | let context = get_tlv(); |
1997 | if context == 0 { | |
e9174d1e | 1998 | f(None) |
83c7162d | 1999 | } else { |
94b46f34 XL |
2000 | // We could get a ImplicitCtxt pointer from another thread. |
2001 | // Ensure that ImplicitCtxt is Sync | |
0bf4aa26 | 2002 | sync::assert_sync::<ImplicitCtxt<'_, '_, '_>>(); |
94b46f34 | 2003 | |
0bf4aa26 | 2004 | unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_, '_>))) } |
e9174d1e SL |
2005 | } |
2006 | } | |
83c7162d XL |
2007 | |
2008 | /// Allows access to the current ImplicitCtxt. | |
2009 | /// Panics if there is no ImplicitCtxt available | |
0731742a | 2010 | #[inline] |
83c7162d XL |
2011 | pub fn with_context<F, R>(f: F) -> R |
2012 | where F: for<'a, 'gcx, 'tcx> FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R | |
2013 | { | |
2014 | with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls"))) | |
2015 | } | |
2016 | ||
2017 | /// Allows access to the current ImplicitCtxt whose tcx field has the same global | |
2018 | /// interner as the tcx argument passed in. This means the closure is given an ImplicitCtxt | |
2019 | /// with the same 'gcx lifetime as the TyCtxt passed in. | |
2020 | /// This will panic if you pass it a TyCtxt which has a different global interner from | |
2021 | /// the current ImplicitCtxt's tcx field. | |
0731742a | 2022 | #[inline] |
83c7162d XL |
2023 | pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R |
2024 | where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R | |
2025 | { | |
2026 | with_context(|context| { | |
2027 | unsafe { | |
0731742a | 2028 | assert!(ptr::eq(context.tcx.gcx, tcx.gcx)); |
0bf4aa26 | 2029 | let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context); |
83c7162d XL |
2030 | f(context) |
2031 | } | |
2032 | }) | |
2033 | } | |
2034 | ||
2035 | /// Allows access to the current ImplicitCtxt whose tcx field has the same global | |
2036 | /// interner and local interner as the tcx argument passed in. This means the closure | |
2037 | /// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in. | |
2038 | /// This will panic if you pass it a TyCtxt which has a different global interner or | |
2039 | /// a different local interner from the current ImplicitCtxt's tcx field. | |
0731742a | 2040 | #[inline] |
83c7162d XL |
2041 | pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R |
2042 | where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R | |
2043 | { | |
2044 | with_context(|context| { | |
2045 | unsafe { | |
0731742a XL |
2046 | assert!(ptr::eq(context.tcx.gcx, tcx.gcx)); |
2047 | assert!(ptr::eq(context.tcx.interners, tcx.interners)); | |
0bf4aa26 | 2048 | let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context); |
83c7162d XL |
2049 | f(context) |
2050 | } | |
2051 | }) | |
2052 | } | |
2053 | ||
2054 | /// Allows access to the TyCtxt in the current ImplicitCtxt. | |
2055 | /// Panics if there is no ImplicitCtxt available | |
0731742a | 2056 | #[inline] |
83c7162d XL |
2057 | pub fn with<F, R>(f: F) -> R |
2058 | where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
2059 | { | |
2060 | with_context(|context| f(context.tcx)) | |
2061 | } | |
2062 | ||
2063 | /// Allows access to the TyCtxt in the current ImplicitCtxt. | |
2064 | /// The closure is passed None if there is no ImplicitCtxt available | |
0731742a | 2065 | #[inline] |
83c7162d XL |
2066 | pub fn with_opt<F, R>(f: F) -> R |
2067 | where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R | |
2068 | { | |
2069 | with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx))) | |
2070 | } | |
e9174d1e SL |
2071 | } |
2072 | ||
2073 | macro_rules! sty_debug_print { | |
2074 | ($ctxt: expr, $($variant: ident),*) => {{ | |
2075 | // curious inner module to allow variant names to be used as | |
2076 | // variable names. | |
2077 | #[allow(non_snake_case)] | |
2078 | mod inner { | |
54a0048b | 2079 | use ty::{self, TyCtxt}; |
a7813a04 XL |
2080 | use ty::context::Interned; |
2081 | ||
e9174d1e SL |
2082 | #[derive(Copy, Clone)] |
2083 | struct DebugStat { | |
2084 | total: usize, | |
2085 | region_infer: usize, | |
2086 | ty_infer: usize, | |
2087 | both_infer: usize, | |
2088 | } | |
2089 | ||
0bf4aa26 | 2090 | pub fn go(tcx: TyCtxt<'_, '_, '_>) { |
e9174d1e SL |
2091 | let mut total = DebugStat { |
2092 | total: 0, | |
2093 | region_infer: 0, ty_infer: 0, both_infer: 0, | |
2094 | }; | |
2095 | $(let mut $variant = total;)* | |
2096 | ||
a1dfa0c6 | 2097 | for &Interned(t) in tcx.interners.type_.borrow().keys() { |
e9174d1e | 2098 | let variant = match t.sty { |
b7449926 XL |
2099 | ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | |
2100 | ty::Float(..) | ty::Str | ty::Never => continue, | |
2101 | ty::Error => /* unimportant */ continue, | |
e9174d1e SL |
2102 | $(ty::$variant(..) => &mut $variant,)* |
2103 | }; | |
7cac9316 XL |
2104 | let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER); |
2105 | let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER); | |
e9174d1e SL |
2106 | |
2107 | variant.total += 1; | |
2108 | total.total += 1; | |
2109 | if region { total.region_infer += 1; variant.region_infer += 1 } | |
2110 | if ty { total.ty_infer += 1; variant.ty_infer += 1 } | |
2111 | if region && ty { total.both_infer += 1; variant.both_infer += 1 } | |
2112 | } | |
2113 | println!("Ty interner total ty region both"); | |
2114 | $(println!(" {:18}: {uses:6} {usespc:4.1}%, \ | |
0bf4aa26 | 2115 | {ty:4.1}% {region:5.1}% {both:4.1}%", |
e9174d1e SL |
2116 | stringify!($variant), |
2117 | uses = $variant.total, | |
2118 | usespc = $variant.total as f64 * 100.0 / total.total as f64, | |
2119 | ty = $variant.ty_infer as f64 * 100.0 / total.total as f64, | |
2120 | region = $variant.region_infer as f64 * 100.0 / total.total as f64, | |
2121 | both = $variant.both_infer as f64 * 100.0 / total.total as f64); | |
2122 | )* | |
2123 | println!(" total {uses:6} \ | |
0bf4aa26 | 2124 | {ty:4.1}% {region:5.1}% {both:4.1}%", |
e9174d1e SL |
2125 | uses = total.total, |
2126 | ty = total.ty_infer as f64 * 100.0 / total.total as f64, | |
2127 | region = total.region_infer as f64 * 100.0 / total.total as f64, | |
2128 | both = total.both_infer as f64 * 100.0 / total.total as f64) | |
2129 | } | |
2130 | } | |
2131 | ||
2132 | inner::go($ctxt) | |
2133 | }} | |
2134 | } | |
2135 | ||
a7813a04 XL |
2136 | impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { |
2137 | pub fn print_debug_stats(self) { | |
e9174d1e SL |
2138 | sty_debug_print!( |
2139 | self, | |
a1dfa0c6 XL |
2140 | Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, Placeholder, |
2141 | Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound, | |
0bf4aa26 | 2142 | Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign); |
e9174d1e | 2143 | |
a7813a04 | 2144 | println!("Substs interner: #{}", self.interners.substs.borrow().len()); |
a7813a04 | 2145 | println!("Region interner: #{}", self.interners.region.borrow().len()); |
32a655c1 | 2146 | println!("Stability interner: #{}", self.stability_interner.borrow().len()); |
94b46f34 | 2147 | println!("Allocation interner: #{}", self.allocation_interner.borrow().len()); |
32a655c1 | 2148 | println!("Layout interner: #{}", self.layout_interner.borrow().len()); |
e9174d1e SL |
2149 | } |
2150 | } | |
2151 | ||
2152 | ||
a7813a04 XL |
2153 | /// An entry in an interner. |
2154 | struct Interned<'tcx, T: 'tcx+?Sized>(&'tcx T); | |
e9174d1e | 2155 | |
a1dfa0c6 XL |
2156 | impl<'tcx, T: 'tcx+?Sized> Clone for Interned<'tcx, T> { |
2157 | fn clone(&self) -> Self { | |
2158 | Interned(self.0) | |
2159 | } | |
2160 | } | |
2161 | impl<'tcx, T: 'tcx+?Sized> Copy for Interned<'tcx, T> {} | |
2162 | ||
0731742a | 2163 | // N.B., an `Interned<Ty>` compares and hashes as a sty. |
a7813a04 XL |
2164 | impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { |
2165 | fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { | |
2166 | self.0.sty == other.0.sty | |
e9174d1e SL |
2167 | } |
2168 | } | |
2169 | ||
a7813a04 | 2170 | impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {} |
e9174d1e | 2171 | |
a7813a04 | 2172 | impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { |
e9174d1e | 2173 | fn hash<H: Hasher>(&self, s: &mut H) { |
a7813a04 | 2174 | self.0.sty.hash(s) |
e9174d1e SL |
2175 | } |
2176 | } | |
2177 | ||
b7449926 XL |
2178 | impl<'tcx: 'lcx, 'lcx> Borrow<TyKind<'lcx>> for Interned<'tcx, TyS<'tcx>> { |
2179 | fn borrow<'a>(&'a self) -> &'a TyKind<'lcx> { | |
a7813a04 | 2180 | &self.0.sty |
e9174d1e SL |
2181 | } |
2182 | } | |
2183 | ||
0731742a | 2184 | // N.B., an `Interned<List<T>>` compares and hashes as its elements. |
b7449926 XL |
2185 | impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> { |
2186 | fn eq(&self, other: &Interned<'tcx, List<T>>) -> bool { | |
9e0c209e SL |
2187 | self.0[..] == other.0[..] |
2188 | } | |
2189 | } | |
2190 | ||
b7449926 | 2191 | impl<'tcx, T: Eq> Eq for Interned<'tcx, List<T>> {} |
9e0c209e | 2192 | |
b7449926 | 2193 | impl<'tcx, T: Hash> Hash for Interned<'tcx, List<T>> { |
9e0c209e SL |
2194 | fn hash<H: Hasher>(&self, s: &mut H) { |
2195 | self.0[..].hash(s) | |
2196 | } | |
2197 | } | |
2198 | ||
b7449926 | 2199 | impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, List<Ty<'tcx>>> { |
a7813a04 | 2200 | fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { |
9e0c209e | 2201 | &self.0[..] |
a7813a04 | 2202 | } |
e9174d1e SL |
2203 | } |
2204 | ||
b7449926 | 2205 | impl<'tcx: 'lcx, 'lcx> Borrow<[CanonicalVarInfo]> for Interned<'tcx, List<CanonicalVarInfo>> { |
0531ce1d XL |
2206 | fn borrow<'a>(&'a self) -> &'a [CanonicalVarInfo] { |
2207 | &self.0[..] | |
2208 | } | |
2209 | } | |
2210 | ||
c30ab7b3 SL |
2211 | impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, Substs<'tcx>> { |
2212 | fn borrow<'a>(&'a self) -> &'a [Kind<'lcx>] { | |
2213 | &self.0[..] | |
a7813a04 XL |
2214 | } |
2215 | } | |
e9174d1e | 2216 | |
0bf4aa26 XL |
2217 | impl<'tcx: 'lcx, 'lcx> Borrow<[ProjectionKind<'lcx>]> |
2218 | for Interned<'tcx, List<ProjectionKind<'tcx>>> { | |
2219 | fn borrow<'a>(&'a self) -> &'a [ProjectionKind<'lcx>] { | |
2220 | &self.0[..] | |
2221 | } | |
2222 | } | |
2223 | ||
7cac9316 XL |
2224 | impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> { |
2225 | fn borrow<'a>(&'a self) -> &'a RegionKind { | |
2226 | &self.0 | |
e9174d1e | 2227 | } |
a7813a04 | 2228 | } |
e9174d1e | 2229 | |
0bf4aa26 XL |
2230 | impl<'tcx: 'lcx, 'lcx> Borrow<GoalKind<'lcx>> for Interned<'tcx, GoalKind<'tcx>> { |
2231 | fn borrow<'a>(&'a self) -> &'a GoalKind<'lcx> { | |
2232 | &self.0 | |
2233 | } | |
2234 | } | |
2235 | ||
0731742a XL |
2236 | impl<'tcx: 'lcx, 'lcx> Borrow<LazyConst<'lcx>> for Interned<'tcx, LazyConst<'tcx>> { |
2237 | fn borrow<'a>(&'a self) -> &'a LazyConst<'lcx> { | |
2238 | &self.0 | |
2239 | } | |
2240 | } | |
2241 | ||
476ff2be | 2242 | impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> |
b7449926 | 2243 | for Interned<'tcx, List<ExistentialPredicate<'tcx>>> { |
476ff2be SL |
2244 | fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] { |
2245 | &self.0[..] | |
2246 | } | |
2247 | } | |
2248 | ||
7cac9316 | 2249 | impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]> |
b7449926 | 2250 | for Interned<'tcx, List<Predicate<'tcx>>> { |
7cac9316 XL |
2251 | fn borrow<'a>(&'a self) -> &'a [Predicate<'lcx>] { |
2252 | &self.0[..] | |
2253 | } | |
2254 | } | |
2255 | ||
ea8adc8c XL |
2256 | impl<'tcx: 'lcx, 'lcx> Borrow<Const<'lcx>> for Interned<'tcx, Const<'tcx>> { |
2257 | fn borrow<'a>(&'a self) -> &'a Const<'lcx> { | |
2258 | &self.0 | |
2259 | } | |
2260 | } | |
2261 | ||
83c7162d | 2262 | impl<'tcx: 'lcx, 'lcx> Borrow<[Clause<'lcx>]> |
b7449926 | 2263 | for Interned<'tcx, List<Clause<'tcx>>> { |
83c7162d XL |
2264 | fn borrow<'a>(&'a self) -> &'a [Clause<'lcx>] { |
2265 | &self.0[..] | |
2266 | } | |
2267 | } | |
2268 | ||
2269 | impl<'tcx: 'lcx, 'lcx> Borrow<[Goal<'lcx>]> | |
b7449926 | 2270 | for Interned<'tcx, List<Goal<'tcx>>> { |
83c7162d XL |
2271 | fn borrow<'a>(&'a self) -> &'a [Goal<'lcx>] { |
2272 | &self.0[..] | |
2273 | } | |
2274 | } | |
2275 | ||
9e0c209e SL |
2276 | macro_rules! intern_method { |
2277 | ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, | |
94b46f34 | 2278 | $alloc_method:expr, |
9e0c209e | 2279 | $alloc_to_key:expr, |
83c7162d | 2280 | $keep_in_local_tcx:expr) -> $ty:ty) => { |
a7813a04 XL |
2281 | impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { |
2282 | pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { | |
94b46f34 | 2283 | let key = ($alloc_to_key)(&v); |
e9174d1e | 2284 | |
a7813a04 XL |
2285 | // HACK(eddyb) Depend on flags being accurate to |
2286 | // determine that all contents are in the global tcx. | |
2287 | // See comments on Lift for why we can't use that. | |
94b46f34 | 2288 | if ($keep_in_local_tcx)(&v) { |
a1dfa0c6 XL |
2289 | self.interners.$name.borrow_mut().intern_ref(key, || { |
2290 | // Make sure we don't end up with inference | |
2291 | // types/regions in the global tcx. | |
2292 | if self.is_global() { | |
2293 | bug!("Attempted to intern `{:?}` which contains \ | |
2294 | inference types/regions in the global type context", | |
2295 | v); | |
2296 | } | |
2297 | ||
2298 | Interned($alloc_method(&self.interners.arena, v)) | |
2299 | }).0 | |
94b46f34 | 2300 | } else { |
a1dfa0c6 XL |
2301 | self.global_interners.$name.borrow_mut().intern_ref(key, || { |
2302 | // This transmutes $alloc<'tcx> to $alloc<'gcx> | |
2303 | let v = unsafe { | |
2304 | mem::transmute(v) | |
2305 | }; | |
2306 | let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v); | |
2307 | // Cast to 'gcx | |
2308 | let i = unsafe { mem::transmute(i) }; | |
2309 | Interned(i) | |
2310 | }).0 | |
94b46f34 | 2311 | } |
e9174d1e | 2312 | } |
9e0c209e SL |
2313 | } |
2314 | } | |
2315 | } | |
2316 | ||
2317 | macro_rules! direct_interners { | |
83c7162d | 2318 | ($lt_tcx:tt, $($name:ident: $method:ident($keep_in_local_tcx:expr) -> $ty:ty),+) => { |
9e0c209e SL |
2319 | $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { |
2320 | fn eq(&self, other: &Self) -> bool { | |
2321 | self.0 == other.0 | |
2322 | } | |
2323 | } | |
2324 | ||
2325 | impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} | |
2326 | ||
2327 | impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { | |
2328 | fn hash<H: Hasher>(&self, s: &mut H) { | |
2329 | self.0.hash(s) | |
2330 | } | |
2331 | } | |
2332 | ||
83c7162d XL |
2333 | intern_method!( |
2334 | $lt_tcx, | |
94b46f34 XL |
2335 | $name: $method($ty, |
2336 | |a: &$lt_tcx SyncDroplessArena, v| -> &$lt_tcx $ty { a.alloc(v) }, | |
2337 | |x| x, | |
2338 | $keep_in_local_tcx) -> $ty);)+ | |
a7813a04 XL |
2339 | } |
2340 | } | |
e9174d1e | 2341 | |
3b2f2976 | 2342 | pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { |
a7813a04 XL |
2343 | x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) |
2344 | } | |
e9174d1e | 2345 | |
9e0c209e | 2346 | direct_interners!('tcx, |
83c7162d | 2347 | region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind, |
0731742a XL |
2348 | goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>, |
2349 | lazy_const: mk_lazy_const(|c: &LazyConst<'_>| keep_local(&c)) -> LazyConst<'tcx> | |
a7813a04 | 2350 | ); |
e9174d1e | 2351 | |
c30ab7b3 SL |
2352 | macro_rules! slice_interners { |
2353 | ($($field:ident: $method:ident($ty:ident)),+) => ( | |
94b46f34 XL |
2354 | $(intern_method!( 'tcx, $field: $method( |
2355 | &[$ty<'tcx>], | |
b7449926 | 2356 | |a, v| List::from_arena(a, v), |
94b46f34 | 2357 | Deref::deref, |
0bf4aa26 | 2358 | |xs: &[$ty<'_>]| xs.iter().any(keep_local)) -> List<$ty<'tcx>>);)+ |
c30ab7b3 SL |
2359 | ) |
2360 | } | |
2361 | ||
2362 | slice_interners!( | |
476ff2be | 2363 | existential_predicates: _intern_existential_predicates(ExistentialPredicate), |
7cac9316 | 2364 | predicates: _intern_predicates(Predicate), |
c30ab7b3 | 2365 | type_list: _intern_type_list(Ty), |
83c7162d XL |
2366 | substs: _intern_substs(Kind), |
2367 | clauses: _intern_clauses(Clause), | |
0bf4aa26 XL |
2368 | goal_list: _intern_goals(Goal), |
2369 | projs: _intern_projs(ProjectionKind) | |
9e0c209e | 2370 | ); |
e9174d1e | 2371 | |
0531ce1d XL |
2372 | // This isn't a perfect fit: CanonicalVarInfo slices are always |
2373 | // allocated in the global arena, so this `intern_method!` macro is | |
2374 | // overly general. But we just return false for the code that checks | |
2375 | // whether they belong in the thread-local arena, so no harm done, and | |
2376 | // seems better than open-coding the rest. | |
2377 | intern_method! { | |
2378 | 'tcx, | |
2379 | canonical_var_infos: _intern_canonical_var_infos( | |
2380 | &[CanonicalVarInfo], | |
b7449926 | 2381 | |a, v| List::from_arena(a, v), |
0531ce1d | 2382 | Deref::deref, |
0531ce1d | 2383 | |_xs: &[CanonicalVarInfo]| -> bool { false } |
b7449926 | 2384 | ) -> List<CanonicalVarInfo> |
0531ce1d XL |
2385 | } |
2386 | ||
a7813a04 | 2387 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
ff7c6d11 XL |
2388 | /// Given a `fn` type, returns an equivalent `unsafe fn` type; |
2389 | /// that is, a `fn` type that is equivalent in every way for being | |
2390 | /// unsafe. | |
8bb4bdeb XL |
2391 | pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { |
2392 | assert_eq!(sig.unsafety(), hir::Unsafety::Normal); | |
2393 | self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { | |
a7813a04 | 2394 | unsafety: hir::Unsafety::Unsafe, |
8bb4bdeb | 2395 | ..sig |
a7813a04 | 2396 | })) |
e9174d1e SL |
2397 | } |
2398 | ||
ff7c6d11 XL |
2399 | /// Given a closure signature `sig`, returns an equivalent `fn` |
2400 | /// type with the same signature. Detuples and so forth -- so | |
0731742a | 2401 | /// e.g., if we have a sig with `Fn<(u32, i32)>` then you would get |
ff7c6d11 XL |
2402 | /// a `fn(u32, i32)`. |
2403 | pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { | |
2404 | let converted_sig = sig.map_bound(|s| { | |
2405 | let params_iter = match s.inputs()[0].sty { | |
b7449926 | 2406 | ty::Tuple(params) => { |
ff7c6d11 XL |
2407 | params.into_iter().cloned() |
2408 | } | |
2409 | _ => bug!(), | |
2410 | }; | |
2411 | self.mk_fn_sig( | |
2412 | params_iter, | |
2413 | s.output(), | |
2414 | s.variadic, | |
2415 | hir::Unsafety::Normal, | |
2416 | abi::Abi::Rust, | |
2417 | ) | |
2418 | }); | |
2419 | ||
2420 | self.mk_fn_ptr(converted_sig) | |
2421 | } | |
2422 | ||
a1dfa0c6 | 2423 | #[inline] |
b7449926 | 2424 | pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> { |
94b46f34 | 2425 | CtxtInterners::intern_ty(&self.interners, &self.global_interners, st) |
e9174d1e SL |
2426 | } |
2427 | ||
a7813a04 | 2428 | pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> { |
e9174d1e | 2429 | match tm { |
2c00a5a8 | 2430 | ast::IntTy::Isize => self.types.isize, |
7453a54e SL |
2431 | ast::IntTy::I8 => self.types.i8, |
2432 | ast::IntTy::I16 => self.types.i16, | |
2433 | ast::IntTy::I32 => self.types.i32, | |
2434 | ast::IntTy::I64 => self.types.i64, | |
32a655c1 | 2435 | ast::IntTy::I128 => self.types.i128, |
e9174d1e SL |
2436 | } |
2437 | } | |
2438 | ||
a7813a04 | 2439 | pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'tcx> { |
e9174d1e | 2440 | match tm { |
2c00a5a8 | 2441 | ast::UintTy::Usize => self.types.usize, |
7453a54e SL |
2442 | ast::UintTy::U8 => self.types.u8, |
2443 | ast::UintTy::U16 => self.types.u16, | |
2444 | ast::UintTy::U32 => self.types.u32, | |
2445 | ast::UintTy::U64 => self.types.u64, | |
32a655c1 | 2446 | ast::UintTy::U128 => self.types.u128, |
e9174d1e SL |
2447 | } |
2448 | } | |
2449 | ||
a7813a04 | 2450 | pub fn mk_mach_float(self, tm: ast::FloatTy) -> Ty<'tcx> { |
e9174d1e | 2451 | match tm { |
7453a54e SL |
2452 | ast::FloatTy::F32 => self.types.f32, |
2453 | ast::FloatTy::F64 => self.types.f64, | |
e9174d1e SL |
2454 | } |
2455 | } | |
2456 | ||
a1dfa0c6 | 2457 | #[inline] |
a7813a04 | 2458 | pub fn mk_str(self) -> Ty<'tcx> { |
b7449926 | 2459 | self.mk_ty(Str) |
e9174d1e SL |
2460 | } |
2461 | ||
a1dfa0c6 | 2462 | #[inline] |
a7813a04 | 2463 | pub fn mk_static_str(self) -> Ty<'tcx> { |
cc61c64b | 2464 | self.mk_imm_ref(self.types.re_static, self.mk_str()) |
e9174d1e SL |
2465 | } |
2466 | ||
a1dfa0c6 | 2467 | #[inline] |
476ff2be | 2468 | pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
e9174d1e | 2469 | // take a copy of substs so that we own the vectors inside |
b7449926 | 2470 | self.mk_ty(Adt(def, substs)) |
e9174d1e SL |
2471 | } |
2472 | ||
a1dfa0c6 | 2473 | #[inline] |
abe05a73 | 2474 | pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> { |
b7449926 | 2475 | self.mk_ty(Foreign(def_id)) |
abe05a73 XL |
2476 | } |
2477 | ||
a7813a04 | 2478 | pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
32a655c1 | 2479 | let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); |
7cac9316 | 2480 | let adt_def = self.adt_def(def_id); |
94b46f34 XL |
2481 | let substs = Substs::for_item(self, def_id, |param, substs| { |
2482 | match param.kind { | |
2483 | GenericParamDefKind::Lifetime => bug!(), | |
2484 | GenericParamDefKind::Type { has_default, .. } => { | |
2485 | if param.index == 0 { | |
2486 | ty.into() | |
2487 | } else { | |
2488 | assert!(has_default); | |
2489 | self.type_of(param.def_id).subst(self, substs).into() | |
2490 | } | |
2491 | } | |
2492 | } | |
2493 | }); | |
b7449926 | 2494 | self.mk_ty(Adt(adt_def, substs)) |
e9174d1e SL |
2495 | } |
2496 | ||
a1dfa0c6 | 2497 | #[inline] |
a7813a04 | 2498 | pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
b7449926 | 2499 | self.mk_ty(RawPtr(tm)) |
e9174d1e SL |
2500 | } |
2501 | ||
a1dfa0c6 | 2502 | #[inline] |
7cac9316 | 2503 | pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
b7449926 | 2504 | self.mk_ty(Ref(r, tm.ty, tm.mutbl)) |
e9174d1e SL |
2505 | } |
2506 | ||
a1dfa0c6 | 2507 | #[inline] |
7cac9316 | 2508 | pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
2509 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable}) |
2510 | } | |
2511 | ||
a1dfa0c6 | 2512 | #[inline] |
7cac9316 | 2513 | pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
2514 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) |
2515 | } | |
2516 | ||
a1dfa0c6 | 2517 | #[inline] |
a7813a04 | 2518 | pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
2519 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable}) |
2520 | } | |
2521 | ||
a1dfa0c6 | 2522 | #[inline] |
a7813a04 | 2523 | pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
2524 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) |
2525 | } | |
2526 | ||
a1dfa0c6 | 2527 | #[inline] |
a7813a04 | 2528 | pub fn mk_nil_ptr(self) -> Ty<'tcx> { |
b7449926 | 2529 | self.mk_imm_ptr(self.mk_unit()) |
e9174d1e SL |
2530 | } |
2531 | ||
a1dfa0c6 | 2532 | #[inline] |
ea8adc8c | 2533 | pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { |
0731742a XL |
2534 | self.mk_ty(Array(ty, self.mk_lazy_const( |
2535 | ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n)) | |
2536 | ))) | |
e9174d1e SL |
2537 | } |
2538 | ||
a1dfa0c6 | 2539 | #[inline] |
a7813a04 | 2540 | pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
b7449926 | 2541 | self.mk_ty(Slice(ty)) |
e9174d1e SL |
2542 | } |
2543 | ||
a1dfa0c6 | 2544 | #[inline] |
0531ce1d | 2545 | pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { |
b7449926 | 2546 | self.mk_ty(Tuple(self.intern_type_list(ts))) |
c30ab7b3 SL |
2547 | } |
2548 | ||
0531ce1d | 2549 | pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output { |
b7449926 | 2550 | iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(ts)))) |
e9174d1e SL |
2551 | } |
2552 | ||
a1dfa0c6 | 2553 | #[inline] |
b7449926 | 2554 | pub fn mk_unit(self) -> Ty<'tcx> { |
a1dfa0c6 | 2555 | self.types.unit |
e9174d1e SL |
2556 | } |
2557 | ||
a1dfa0c6 | 2558 | #[inline] |
5bcae85e | 2559 | pub fn mk_diverging_default(self) -> Ty<'tcx> { |
0531ce1d | 2560 | if self.features().never_type { |
5bcae85e SL |
2561 | self.types.never |
2562 | } else { | |
0531ce1d | 2563 | self.intern_tup(&[]) |
5bcae85e SL |
2564 | } |
2565 | } | |
2566 | ||
a1dfa0c6 | 2567 | #[inline] |
a7813a04 | 2568 | pub fn mk_bool(self) -> Ty<'tcx> { |
b7449926 | 2569 | self.mk_ty(Bool) |
e9174d1e SL |
2570 | } |
2571 | ||
a1dfa0c6 | 2572 | #[inline] |
a7813a04 | 2573 | pub fn mk_fn_def(self, def_id: DefId, |
041b39d2 | 2574 | substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
b7449926 | 2575 | self.mk_ty(FnDef(def_id, substs)) |
54a0048b SL |
2576 | } |
2577 | ||
a1dfa0c6 | 2578 | #[inline] |
8bb4bdeb | 2579 | pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { |
b7449926 | 2580 | self.mk_ty(FnPtr(fty)) |
e9174d1e SL |
2581 | } |
2582 | ||
a1dfa0c6 | 2583 | #[inline] |
476ff2be SL |
2584 | pub fn mk_dynamic( |
2585 | self, | |
b7449926 | 2586 | obj: ty::Binder<&'tcx List<ExistentialPredicate<'tcx>>>, |
7cac9316 | 2587 | reg: ty::Region<'tcx> |
476ff2be | 2588 | ) -> Ty<'tcx> { |
b7449926 | 2589 | self.mk_ty(Dynamic(obj, reg)) |
e9174d1e SL |
2590 | } |
2591 | ||
a1dfa0c6 | 2592 | #[inline] |
a7813a04 | 2593 | pub fn mk_projection(self, |
041b39d2 XL |
2594 | item_def_id: DefId, |
2595 | substs: &'tcx Substs<'tcx>) | |
476ff2be | 2596 | -> Ty<'tcx> { |
b7449926 | 2597 | self.mk_ty(Projection(ProjectionTy { |
3b2f2976 XL |
2598 | item_def_id, |
2599 | substs, | |
041b39d2 | 2600 | })) |
476ff2be | 2601 | } |
e9174d1e | 2602 | |
a1dfa0c6 | 2603 | #[inline] |
94b46f34 | 2604 | pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>) |
0bf4aa26 | 2605 | -> Ty<'tcx> { |
b7449926 | 2606 | self.mk_ty(Closure(closure_id, closure_substs)) |
e9174d1e SL |
2607 | } |
2608 | ||
a1dfa0c6 | 2609 | #[inline] |
ea8adc8c XL |
2610 | pub fn mk_generator(self, |
2611 | id: DefId, | |
94b46f34 XL |
2612 | generator_substs: GeneratorSubsts<'tcx>, |
2613 | movability: hir::GeneratorMovability) | |
ea8adc8c | 2614 | -> Ty<'tcx> { |
b7449926 | 2615 | self.mk_ty(Generator(id, generator_substs, movability)) |
ea8adc8c XL |
2616 | } |
2617 | ||
a1dfa0c6 | 2618 | #[inline] |
b7449926 XL |
2619 | pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List<Ty<'tcx>>>) -> Ty<'tcx> { |
2620 | self.mk_ty(GeneratorWitness(types)) | |
2c00a5a8 XL |
2621 | } |
2622 | ||
a1dfa0c6 | 2623 | #[inline] |
a7813a04 | 2624 | pub fn mk_var(self, v: TyVid) -> Ty<'tcx> { |
e9174d1e SL |
2625 | self.mk_infer(TyVar(v)) |
2626 | } | |
2627 | ||
a1dfa0c6 | 2628 | #[inline] |
a7813a04 | 2629 | pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { |
e9174d1e SL |
2630 | self.mk_infer(IntVar(v)) |
2631 | } | |
2632 | ||
a1dfa0c6 | 2633 | #[inline] |
a7813a04 | 2634 | pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { |
e9174d1e SL |
2635 | self.mk_infer(FloatVar(v)) |
2636 | } | |
2637 | ||
a1dfa0c6 | 2638 | #[inline] |
a7813a04 | 2639 | pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> { |
b7449926 | 2640 | self.mk_ty(Infer(it)) |
e9174d1e SL |
2641 | } |
2642 | ||
a1dfa0c6 | 2643 | #[inline] |
94b46f34 | 2644 | pub fn mk_ty_param(self, |
0bf4aa26 XL |
2645 | index: u32, |
2646 | name: InternedString) -> Ty<'tcx> { | |
b7449926 | 2647 | self.mk_ty(Param(ParamTy { idx: index, name: name })) |
e9174d1e SL |
2648 | } |
2649 | ||
a1dfa0c6 | 2650 | #[inline] |
a7813a04 | 2651 | pub fn mk_self_type(self) -> Ty<'tcx> { |
0731742a | 2652 | self.mk_ty_param(0, keywords::SelfUpper.name().as_interned_str()) |
e9174d1e SL |
2653 | } |
2654 | ||
94b46f34 XL |
2655 | pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> { |
2656 | match param.kind { | |
2657 | GenericParamDefKind::Lifetime => { | |
2658 | self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() | |
2659 | } | |
2660 | GenericParamDefKind::Type {..} => self.mk_ty_param(param.index, param.name).into(), | |
2661 | } | |
e9174d1e | 2662 | } |
9cc50fc6 | 2663 | |
a1dfa0c6 | 2664 | #[inline] |
b7449926 XL |
2665 | pub fn mk_opaque(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
2666 | self.mk_ty(Opaque(def_id, substs)) | |
5bcae85e SL |
2667 | } |
2668 | ||
476ff2be | 2669 | pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>]) |
b7449926 | 2670 | -> &'tcx List<ExistentialPredicate<'tcx>> { |
476ff2be | 2671 | assert!(!eps.is_empty()); |
94b46f34 | 2672 | assert!(eps.windows(2).all(|w| w[0].stable_cmp(self, &w[1]) != Ordering::Greater)); |
476ff2be SL |
2673 | self._intern_existential_predicates(eps) |
2674 | } | |
2675 | ||
7cac9316 | 2676 | pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) |
b7449926 | 2677 | -> &'tcx List<Predicate<'tcx>> { |
7cac9316 XL |
2678 | // FIXME consider asking the input slice to be sorted to avoid |
2679 | // re-interning permutations, in which case that would be asserted | |
2680 | // here. | |
2681 | if preds.len() == 0 { | |
2682 | // The macro-generated method below asserts we don't intern an empty slice. | |
b7449926 | 2683 | List::empty() |
7cac9316 XL |
2684 | } else { |
2685 | self._intern_predicates(preds) | |
2686 | } | |
2687 | } | |
2688 | ||
b7449926 | 2689 | pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> { |
c30ab7b3 | 2690 | if ts.len() == 0 { |
b7449926 | 2691 | List::empty() |
c30ab7b3 SL |
2692 | } else { |
2693 | self._intern_type_list(ts) | |
2694 | } | |
2695 | } | |
2696 | ||
b7449926 | 2697 | pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx List<Kind<'tcx>> { |
c30ab7b3 | 2698 | if ts.len() == 0 { |
b7449926 | 2699 | List::empty() |
c30ab7b3 SL |
2700 | } else { |
2701 | self._intern_substs(ts) | |
2702 | } | |
2703 | } | |
2704 | ||
0bf4aa26 XL |
2705 | pub fn intern_projs(self, ps: &[ProjectionKind<'tcx>]) -> &'tcx List<ProjectionKind<'tcx>> { |
2706 | if ps.len() == 0 { | |
2707 | List::empty() | |
2708 | } else { | |
2709 | self._intern_projs(ps) | |
2710 | } | |
2711 | } | |
2712 | ||
0531ce1d XL |
2713 | pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'gcx> { |
2714 | if ts.len() == 0 { | |
b7449926 | 2715 | List::empty() |
0531ce1d XL |
2716 | } else { |
2717 | self.global_tcx()._intern_canonical_var_infos(ts) | |
2718 | } | |
2719 | } | |
2720 | ||
83c7162d XL |
2721 | pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> { |
2722 | if ts.len() == 0 { | |
b7449926 | 2723 | List::empty() |
83c7162d XL |
2724 | } else { |
2725 | self._intern_clauses(ts) | |
2726 | } | |
2727 | } | |
2728 | ||
2729 | pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> { | |
2730 | if ts.len() == 0 { | |
b7449926 | 2731 | List::empty() |
83c7162d XL |
2732 | } else { |
2733 | self._intern_goals(ts) | |
2734 | } | |
2735 | } | |
2736 | ||
8bb4bdeb XL |
2737 | pub fn mk_fn_sig<I>(self, |
2738 | inputs: I, | |
2739 | output: I::Item, | |
2740 | variadic: bool, | |
2741 | unsafety: hir::Unsafety, | |
2742 | abi: abi::Abi) | |
476ff2be SL |
2743 | -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output |
2744 | where I: Iterator, | |
2745 | I::Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>> | |
2746 | { | |
2747 | inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig { | |
2748 | inputs_and_output: self.intern_type_list(xs), | |
8bb4bdeb | 2749 | variadic, unsafety, abi |
476ff2be SL |
2750 | }) |
2751 | } | |
2752 | ||
2753 | pub fn mk_existential_predicates<I: InternAs<[ExistentialPredicate<'tcx>], | |
b7449926 | 2754 | &'tcx List<ExistentialPredicate<'tcx>>>>(self, iter: I) |
476ff2be SL |
2755 | -> I::Output { |
2756 | iter.intern_with(|xs| self.intern_existential_predicates(xs)) | |
2757 | } | |
2758 | ||
7cac9316 | 2759 | pub fn mk_predicates<I: InternAs<[Predicate<'tcx>], |
b7449926 | 2760 | &'tcx List<Predicate<'tcx>>>>(self, iter: I) |
7cac9316 XL |
2761 | -> I::Output { |
2762 | iter.intern_with(|xs| self.intern_predicates(xs)) | |
2763 | } | |
2764 | ||
c30ab7b3 | 2765 | pub fn mk_type_list<I: InternAs<[Ty<'tcx>], |
b7449926 | 2766 | &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output { |
c30ab7b3 SL |
2767 | iter.intern_with(|xs| self.intern_type_list(xs)) |
2768 | } | |
2769 | ||
2770 | pub fn mk_substs<I: InternAs<[Kind<'tcx>], | |
b7449926 | 2771 | &'tcx List<Kind<'tcx>>>>(self, iter: I) -> I::Output { |
c30ab7b3 SL |
2772 | iter.intern_with(|xs| self.intern_substs(xs)) |
2773 | } | |
2774 | ||
2775 | pub fn mk_substs_trait(self, | |
94b46f34 XL |
2776 | self_ty: Ty<'tcx>, |
2777 | rest: &[Kind<'tcx>]) | |
c30ab7b3 SL |
2778 | -> &'tcx Substs<'tcx> |
2779 | { | |
94b46f34 | 2780 | self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned())) |
c30ab7b3 | 2781 | } |
3b2f2976 | 2782 | |
83c7162d XL |
2783 | pub fn mk_clauses<I: InternAs<[Clause<'tcx>], Clauses<'tcx>>>(self, iter: I) -> I::Output { |
2784 | iter.intern_with(|xs| self.intern_clauses(xs)) | |
2785 | } | |
2786 | ||
2787 | pub fn mk_goals<I: InternAs<[Goal<'tcx>], Goals<'tcx>>>(self, iter: I) -> I::Output { | |
2788 | iter.intern_with(|xs| self.intern_goals(xs)) | |
2789 | } | |
2790 | ||
94b46f34 XL |
2791 | pub fn lint_hir<S: Into<MultiSpan>>(self, |
2792 | lint: &'static Lint, | |
2793 | hir_id: HirId, | |
2794 | span: S, | |
2795 | msg: &str) { | |
2796 | self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit() | |
83c7162d XL |
2797 | } |
2798 | ||
3b2f2976 XL |
2799 | pub fn lint_node<S: Into<MultiSpan>>(self, |
2800 | lint: &'static Lint, | |
2801 | id: NodeId, | |
2802 | span: S, | |
2803 | msg: &str) { | |
2804 | self.struct_span_lint_node(lint, id, span.into(), msg).emit() | |
2805 | } | |
2806 | ||
94b46f34 | 2807 | pub fn lint_hir_note<S: Into<MultiSpan>>(self, |
0731742a XL |
2808 | lint: &'static Lint, |
2809 | hir_id: HirId, | |
2810 | span: S, | |
2811 | msg: &str, | |
2812 | note: &str) { | |
94b46f34 XL |
2813 | let mut err = self.struct_span_lint_hir(lint, hir_id, span.into(), msg); |
2814 | err.note(note); | |
2815 | err.emit() | |
2816 | } | |
2817 | ||
3b2f2976 XL |
2818 | pub fn lint_node_note<S: Into<MultiSpan>>(self, |
2819 | lint: &'static Lint, | |
2820 | id: NodeId, | |
2821 | span: S, | |
2822 | msg: &str, | |
2823 | note: &str) { | |
2824 | let mut err = self.struct_span_lint_node(lint, id, span.into(), msg); | |
2825 | err.note(note); | |
2826 | err.emit() | |
2827 | } | |
2828 | ||
2829 | pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId) | |
2830 | -> (lint::Level, lint::LintSource) | |
2831 | { | |
2832 | // Right now we insert a `with_ignore` node in the dep graph here to | |
2833 | // ignore the fact that `lint_levels` below depends on the entire crate. | |
2834 | // For now this'll prevent false positives of recompiling too much when | |
2835 | // anything changes. | |
2836 | // | |
2837 | // Once red/green incremental compilation lands we should be able to | |
2838 | // remove this because while the crate changes often the lint level map | |
2839 | // will change rarely. | |
2840 | self.dep_graph.with_ignore(|| { | |
2841 | let sets = self.lint_levels(LOCAL_CRATE); | |
2842 | loop { | |
0731742a | 2843 | let hir_id = self.hir().definitions().node_to_hir_id(id); |
0531ce1d | 2844 | if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) { |
3b2f2976 XL |
2845 | return pair |
2846 | } | |
0731742a | 2847 | let next = self.hir().get_parent_node(id); |
3b2f2976 XL |
2848 | if next == id { |
2849 | bug!("lint traversal reached the root of the crate"); | |
2850 | } | |
2851 | id = next; | |
2852 | } | |
2853 | }) | |
2854 | } | |
2855 | ||
94b46f34 XL |
2856 | pub fn struct_span_lint_hir<S: Into<MultiSpan>>(self, |
2857 | lint: &'static Lint, | |
2858 | hir_id: HirId, | |
2859 | span: S, | |
2860 | msg: &str) | |
2861 | -> DiagnosticBuilder<'tcx> | |
2862 | { | |
0731742a | 2863 | let node_id = self.hir().hir_to_node_id(hir_id); |
94b46f34 XL |
2864 | let (level, src) = self.lint_level_at_node(lint, node_id); |
2865 | lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg) | |
2866 | } | |
2867 | ||
3b2f2976 XL |
2868 | pub fn struct_span_lint_node<S: Into<MultiSpan>>(self, |
2869 | lint: &'static Lint, | |
2870 | id: NodeId, | |
2871 | span: S, | |
2872 | msg: &str) | |
2873 | -> DiagnosticBuilder<'tcx> | |
2874 | { | |
2875 | let (level, src) = self.lint_level_at_node(lint, id); | |
2876 | lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg) | |
2877 | } | |
2878 | ||
2879 | pub fn struct_lint_node(self, lint: &'static Lint, id: NodeId, msg: &str) | |
2880 | -> DiagnosticBuilder<'tcx> | |
2881 | { | |
2882 | let (level, src) = self.lint_level_at_node(lint, id); | |
2883 | lint::struct_lint_level(self.sess, lint, level, src, None, msg) | |
2884 | } | |
ea8adc8c | 2885 | |
0531ce1d | 2886 | pub fn in_scope_traits(self, id: HirId) -> Option<Lrc<StableVec<TraitCandidate>>> { |
ea8adc8c XL |
2887 | self.in_scope_traits_map(id.owner) |
2888 | .and_then(|map| map.get(&id.local_id).cloned()) | |
2889 | } | |
2890 | ||
2891 | pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> { | |
2892 | self.named_region_map(id.owner) | |
2893 | .and_then(|map| map.get(&id.local_id).cloned()) | |
2894 | } | |
2895 | ||
2896 | pub fn is_late_bound(self, id: HirId) -> bool { | |
2897 | self.is_late_bound_map(id.owner) | |
2898 | .map(|set| set.contains(&id.local_id)) | |
2899 | .unwrap_or(false) | |
2900 | } | |
2901 | ||
2902 | pub fn object_lifetime_defaults(self, id: HirId) | |
0531ce1d | 2903 | -> Option<Lrc<Vec<ObjectLifetimeDefault>>> |
ea8adc8c XL |
2904 | { |
2905 | self.object_lifetime_defaults_map(id.owner) | |
2906 | .and_then(|map| map.get(&id.local_id).cloned()) | |
2907 | } | |
e9174d1e | 2908 | } |
c30ab7b3 SL |
2909 | |
2910 | pub trait InternAs<T: ?Sized, R> { | |
2911 | type Output; | |
7cac9316 | 2912 | fn intern_with<F>(self, f: F) -> Self::Output |
c30ab7b3 SL |
2913 | where F: FnOnce(&T) -> R; |
2914 | } | |
2915 | ||
2916 | impl<I, T, R, E> InternAs<[T], R> for I | |
2917 | where E: InternIteratorElement<T, R>, | |
2918 | I: Iterator<Item=E> { | |
2919 | type Output = E::Output; | |
2920 | fn intern_with<F>(self, f: F) -> Self::Output | |
2921 | where F: FnOnce(&[T]) -> R { | |
2922 | E::intern_with(self, f) | |
2923 | } | |
2924 | } | |
2925 | ||
2926 | pub trait InternIteratorElement<T, R>: Sized { | |
2927 | type Output; | |
2928 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output; | |
2929 | } | |
2930 | ||
2931 | impl<T, R> InternIteratorElement<T, R> for T { | |
2932 | type Output = R; | |
2933 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { | |
b7449926 | 2934 | f(&iter.collect::<SmallVec<[_; 8]>>()) |
c30ab7b3 SL |
2935 | } |
2936 | } | |
2937 | ||
cc61c64b XL |
2938 | impl<'a, T, R> InternIteratorElement<T, R> for &'a T |
2939 | where T: Clone + 'a | |
2940 | { | |
2941 | type Output = R; | |
2942 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { | |
b7449926 | 2943 | f(&iter.cloned().collect::<SmallVec<[_; 8]>>()) |
cc61c64b XL |
2944 | } |
2945 | } | |
2946 | ||
c30ab7b3 SL |
2947 | impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> { |
2948 | type Output = Result<R, E>; | |
2949 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { | |
b7449926 | 2950 | Ok(f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?)) |
c30ab7b3 SL |
2951 | } |
2952 | } | |
ea8adc8c | 2953 | |
0bf4aa26 | 2954 | pub fn provide(providers: &mut ty::query::Providers<'_>) { |
ea8adc8c XL |
2955 | providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned(); |
2956 | providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned(); | |
ea8adc8c XL |
2957 | providers.crate_name = |tcx, id| { |
2958 | assert_eq!(id, LOCAL_CRATE); | |
2959 | tcx.crate_name | |
2960 | }; | |
b7449926 XL |
2961 | providers.get_lib_features = |tcx, id| { |
2962 | assert_eq!(id, LOCAL_CRATE); | |
2963 | Lrc::new(middle::lib_features::collect(tcx)) | |
2964 | }; | |
ea8adc8c XL |
2965 | providers.get_lang_items = |tcx, id| { |
2966 | assert_eq!(id, LOCAL_CRATE); | |
b7449926 | 2967 | Lrc::new(middle::lang_items::collect(tcx)) |
ea8adc8c XL |
2968 | }; |
2969 | providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned(); | |
2970 | providers.maybe_unused_trait_import = |tcx, id| { | |
2971 | tcx.maybe_unused_trait_imports.contains(&id) | |
2972 | }; | |
2973 | providers.maybe_unused_extern_crates = |tcx, cnum| { | |
2974 | assert_eq!(cnum, LOCAL_CRATE); | |
0531ce1d | 2975 | Lrc::new(tcx.maybe_unused_extern_crates.clone()) |
ea8adc8c XL |
2976 | }; |
2977 | ||
2978 | providers.stability_index = |tcx, cnum| { | |
2979 | assert_eq!(cnum, LOCAL_CRATE); | |
0531ce1d | 2980 | Lrc::new(stability::Index::new(tcx)) |
ea8adc8c XL |
2981 | }; |
2982 | providers.lookup_stability = |tcx, id| { | |
2983 | assert_eq!(id.krate, LOCAL_CRATE); | |
0731742a | 2984 | let id = tcx.hir().definitions().def_index_to_hir_id(id.index); |
ea8adc8c XL |
2985 | tcx.stability().local_stability(id) |
2986 | }; | |
2987 | providers.lookup_deprecation_entry = |tcx, id| { | |
2988 | assert_eq!(id.krate, LOCAL_CRATE); | |
0731742a | 2989 | let id = tcx.hir().definitions().def_index_to_hir_id(id.index); |
ea8adc8c XL |
2990 | tcx.stability().local_deprecation_entry(id) |
2991 | }; | |
2992 | providers.extern_mod_stmt_cnum = |tcx, id| { | |
0731742a | 2993 | let id = tcx.hir().as_local_node_id(id).unwrap(); |
ea8adc8c XL |
2994 | tcx.cstore.extern_mod_stmt_cnum_untracked(id) |
2995 | }; | |
2996 | providers.all_crate_nums = |tcx, cnum| { | |
2997 | assert_eq!(cnum, LOCAL_CRATE); | |
0531ce1d | 2998 | Lrc::new(tcx.cstore.crates_untracked()) |
ea8adc8c XL |
2999 | }; |
3000 | providers.postorder_cnums = |tcx, cnum| { | |
3001 | assert_eq!(cnum, LOCAL_CRATE); | |
0531ce1d | 3002 | Lrc::new(tcx.cstore.postorder_cnums_untracked()) |
ea8adc8c XL |
3003 | }; |
3004 | providers.output_filenames = |tcx, cnum| { | |
3005 | assert_eq!(cnum, LOCAL_CRATE); | |
3006 | tcx.output_filenames.clone() | |
3007 | }; | |
0531ce1d | 3008 | providers.features_query = |tcx, cnum| { |
ea8adc8c | 3009 | assert_eq!(cnum, LOCAL_CRATE); |
0531ce1d | 3010 | Lrc::new(tcx.sess.features_untracked().clone()) |
ea8adc8c | 3011 | }; |
0531ce1d | 3012 | providers.is_panic_runtime = |tcx, cnum| { |
ea8adc8c | 3013 | assert_eq!(cnum, LOCAL_CRATE); |
0731742a | 3014 | attr::contains_name(tcx.hir().krate_attrs(), "panic_runtime") |
ea8adc8c | 3015 | }; |
0531ce1d XL |
3016 | providers.is_compiler_builtins = |tcx, cnum| { |
3017 | assert_eq!(cnum, LOCAL_CRATE); | |
0731742a | 3018 | attr::contains_name(tcx.hir().krate_attrs(), "compiler_builtins") |
abe05a73 | 3019 | }; |
ea8adc8c | 3020 | } |