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