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