]>
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 | ||
9cc50fc6 | 13 | use dep_graph::{DepGraph, DepTrackingMap}; |
e9174d1e | 14 | use session::Session; |
e9174d1e | 15 | use middle; |
5bcae85e | 16 | use hir::TraitMap; |
54a0048b | 17 | use hir::def::DefMap; |
9e0c209e | 18 | use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; |
a7813a04 XL |
19 | use hir::map as ast_map; |
20 | use hir::map::{DefKey, DefPath, DefPathData, DisambiguatedDefPathData}; | |
e9174d1e SL |
21 | use middle::free_region::FreeRegionMap; |
22 | use middle::region::RegionMaps; | |
23 | use middle::resolve_lifetime; | |
24 | use middle::stability; | |
9e0c209e | 25 | use ty::subst::Substs; |
54a0048b SL |
26 | use traits; |
27 | use ty::{self, TraitRef, Ty, TypeAndMut}; | |
9e0c209e SL |
28 | use ty::{TyS, TypeVariants, Slice}; |
29 | use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; | |
54a0048b | 30 | use hir::FreevarMap; |
9e0c209e | 31 | use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject}; |
54a0048b SL |
32 | use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; |
33 | use ty::TypeVariants::*; | |
34 | use ty::layout::{Layout, TargetDataLayout}; | |
35 | use ty::maps; | |
9cc50fc6 | 36 | use util::common::MemoizationMap; |
e9174d1e | 37 | use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; |
a7813a04 | 38 | use util::nodemap::{FnvHashMap, FnvHashSet}; |
e9174d1e SL |
39 | |
40 | use arena::TypedArena; | |
41 | use std::borrow::Borrow; | |
42 | use std::cell::{Cell, RefCell, Ref}; | |
43 | use std::hash::{Hash, Hasher}; | |
a7813a04 XL |
44 | use std::mem; |
45 | use std::ops::Deref; | |
e9174d1e | 46 | use std::rc::Rc; |
b039eaaf SL |
47 | use syntax::ast::{self, Name, NodeId}; |
48 | use syntax::attr; | |
a7813a04 | 49 | use syntax::parse::token::{self, keywords}; |
e9174d1e | 50 | |
54a0048b | 51 | use hir; |
e9174d1e SL |
52 | |
53 | /// Internal storage | |
54 | pub struct CtxtArenas<'tcx> { | |
55 | // internings | |
56 | type_: TypedArena<TyS<'tcx>>, | |
a7813a04 | 57 | type_list: TypedArena<Vec<Ty<'tcx>>>, |
e9174d1e SL |
58 | substs: TypedArena<Substs<'tcx>>, |
59 | bare_fn: TypedArena<BareFnTy<'tcx>>, | |
60 | region: TypedArena<Region>, | |
61 | stability: TypedArena<attr::Stability>, | |
54a0048b | 62 | layout: TypedArena<Layout>, |
e9174d1e SL |
63 | |
64 | // references | |
9e0c209e | 65 | generics: TypedArena<ty::Generics<'tcx>>, |
e9174d1e SL |
66 | trait_defs: TypedArena<ty::TraitDef<'tcx>>, |
67 | adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>, | |
68 | } | |
69 | ||
70 | impl<'tcx> CtxtArenas<'tcx> { | |
71 | pub fn new() -> CtxtArenas<'tcx> { | |
72 | CtxtArenas { | |
73 | type_: TypedArena::new(), | |
a7813a04 | 74 | type_list: TypedArena::new(), |
e9174d1e SL |
75 | substs: TypedArena::new(), |
76 | bare_fn: TypedArena::new(), | |
77 | region: TypedArena::new(), | |
78 | stability: TypedArena::new(), | |
54a0048b | 79 | layout: TypedArena::new(), |
e9174d1e | 80 | |
9e0c209e | 81 | generics: TypedArena::new(), |
e9174d1e SL |
82 | trait_defs: TypedArena::new(), |
83 | adt_defs: TypedArena::new() | |
84 | } | |
85 | } | |
86 | } | |
87 | ||
a7813a04 XL |
88 | pub struct CtxtInterners<'tcx> { |
89 | /// The arenas that types etc are allocated from. | |
90 | arenas: &'tcx CtxtArenas<'tcx>, | |
91 | ||
92 | /// Specifically use a speedy hash algorithm for these hash sets, | |
93 | /// they're accessed quite often. | |
94 | type_: RefCell<FnvHashSet<Interned<'tcx, TyS<'tcx>>>>, | |
9e0c209e | 95 | type_list: RefCell<FnvHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>, |
a7813a04 XL |
96 | substs: RefCell<FnvHashSet<Interned<'tcx, Substs<'tcx>>>>, |
97 | bare_fn: RefCell<FnvHashSet<Interned<'tcx, BareFnTy<'tcx>>>>, | |
98 | region: RefCell<FnvHashSet<Interned<'tcx, Region>>>, | |
99 | stability: RefCell<FnvHashSet<&'tcx attr::Stability>>, | |
100 | layout: RefCell<FnvHashSet<&'tcx Layout>>, | |
101 | } | |
102 | ||
103 | impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { | |
104 | fn new(arenas: &'tcx CtxtArenas<'tcx>) -> CtxtInterners<'tcx> { | |
105 | CtxtInterners { | |
106 | arenas: arenas, | |
107 | type_: RefCell::new(FnvHashSet()), | |
108 | type_list: RefCell::new(FnvHashSet()), | |
109 | substs: RefCell::new(FnvHashSet()), | |
110 | bare_fn: RefCell::new(FnvHashSet()), | |
111 | region: RefCell::new(FnvHashSet()), | |
112 | stability: RefCell::new(FnvHashSet()), | |
113 | layout: RefCell::new(FnvHashSet()) | |
114 | } | |
115 | } | |
116 | ||
117 | /// Intern a type. global_interners is Some only if this is | |
118 | /// a local interner and global_interners is its counterpart. | |
119 | fn intern_ty(&self, st: TypeVariants<'tcx>, | |
120 | global_interners: Option<&CtxtInterners<'gcx>>) | |
121 | -> Ty<'tcx> { | |
122 | let ty = { | |
123 | let mut interner = self.type_.borrow_mut(); | |
124 | let global_interner = global_interners.map(|interners| { | |
125 | interners.type_.borrow_mut() | |
126 | }); | |
127 | if let Some(&Interned(ty)) = interner.get(&st) { | |
128 | return ty; | |
129 | } | |
130 | if let Some(ref interner) = global_interner { | |
131 | if let Some(&Interned(ty)) = interner.get(&st) { | |
132 | return ty; | |
133 | } | |
134 | } | |
135 | ||
136 | let flags = super::flags::FlagComputation::for_sty(&st); | |
137 | let ty_struct = TyS { | |
138 | sty: st, | |
139 | flags: Cell::new(flags.flags), | |
140 | region_depth: flags.depth, | |
141 | }; | |
142 | ||
143 | // HACK(eddyb) Depend on flags being accurate to | |
144 | // determine that all contents are in the global tcx. | |
145 | // See comments on Lift for why we can't use that. | |
146 | if !flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) { | |
147 | if let Some(interner) = global_interners { | |
148 | let ty_struct: TyS<'gcx> = unsafe { | |
149 | mem::transmute(ty_struct) | |
150 | }; | |
151 | let ty: Ty<'gcx> = interner.arenas.type_.alloc(ty_struct); | |
152 | global_interner.unwrap().insert(Interned(ty)); | |
153 | return ty; | |
154 | } | |
155 | } else { | |
156 | // Make sure we don't end up with inference | |
157 | // types/regions in the global tcx. | |
158 | if global_interners.is_none() { | |
159 | drop(interner); | |
160 | bug!("Attempted to intern `{:?}` which contains \ | |
161 | inference types/regions in the global type context", | |
162 | &ty_struct); | |
163 | } | |
164 | } | |
165 | ||
166 | // Don't be &mut TyS. | |
167 | let ty: Ty<'tcx> = self.arenas.type_.alloc(ty_struct); | |
168 | interner.insert(Interned(ty)); | |
169 | ty | |
170 | }; | |
171 | ||
172 | debug!("Interned type: {:?} Pointer: {:?}", | |
173 | ty, ty as *const TyS); | |
174 | ty | |
175 | } | |
176 | ||
177 | } | |
178 | ||
e9174d1e SL |
179 | pub struct CommonTypes<'tcx> { |
180 | pub bool: Ty<'tcx>, | |
181 | pub char: Ty<'tcx>, | |
182 | pub isize: Ty<'tcx>, | |
183 | pub i8: Ty<'tcx>, | |
184 | pub i16: Ty<'tcx>, | |
185 | pub i32: Ty<'tcx>, | |
186 | pub i64: Ty<'tcx>, | |
187 | pub usize: Ty<'tcx>, | |
188 | pub u8: Ty<'tcx>, | |
189 | pub u16: Ty<'tcx>, | |
190 | pub u32: Ty<'tcx>, | |
191 | pub u64: Ty<'tcx>, | |
192 | pub f32: Ty<'tcx>, | |
193 | pub f64: Ty<'tcx>, | |
5bcae85e | 194 | pub never: Ty<'tcx>, |
e9174d1e SL |
195 | pub err: Ty<'tcx>, |
196 | } | |
197 | ||
198 | pub struct Tables<'tcx> { | |
199 | /// Stores the types for various nodes in the AST. Note that this table | |
200 | /// is not guaranteed to be populated until after typeck. See | |
201 | /// typeck::check::fn_ctxt for details. | |
202 | pub node_types: NodeMap<Ty<'tcx>>, | |
203 | ||
204 | /// Stores the type parameters which were substituted to obtain the type | |
205 | /// of this node. This only applies to nodes that refer to entities | |
206 | /// parameterized by type parameters, such as generic fns, types, or | |
207 | /// other items. | |
208 | pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>, | |
209 | ||
210 | pub adjustments: NodeMap<ty::adjustment::AutoAdjustment<'tcx>>, | |
211 | ||
212 | pub method_map: ty::MethodMap<'tcx>, | |
213 | ||
214 | /// Borrows | |
9e0c209e | 215 | pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, |
e9174d1e SL |
216 | |
217 | /// Records the type of each closure. The def ID is the ID of the | |
218 | /// expression defining the closure. | |
219 | pub closure_tys: DefIdMap<ty::ClosureTy<'tcx>>, | |
220 | ||
221 | /// Records the type of each closure. The def ID is the ID of the | |
222 | /// expression defining the closure. | |
223 | pub closure_kinds: DefIdMap<ty::ClosureKind>, | |
92a42be0 SL |
224 | |
225 | /// For each fn, records the "liberated" types of its arguments | |
226 | /// and return type. Liberated means that all bound regions | |
227 | /// (including late-bound regions) are replaced with free | |
228 | /// equivalents. This table is not used in trans (since regions | |
229 | /// are erased there) and hence is not serialized to metadata. | |
230 | pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>, | |
7453a54e SL |
231 | |
232 | /// For each FRU expression, record the normalized types of the fields | |
233 | /// of the struct - this is needed because it is non-trivial to | |
234 | /// normalize while preserving regions. This table is used only in | |
235 | /// MIR construction and hence is not serialized to metadata. | |
236 | pub fru_field_types: NodeMap<Vec<Ty<'tcx>>> | |
e9174d1e SL |
237 | } |
238 | ||
a7813a04 | 239 | impl<'a, 'gcx, 'tcx> Tables<'tcx> { |
e9174d1e SL |
240 | pub fn empty() -> Tables<'tcx> { |
241 | Tables { | |
242 | node_types: FnvHashMap(), | |
243 | item_substs: NodeMap(), | |
244 | adjustments: NodeMap(), | |
245 | method_map: FnvHashMap(), | |
246 | upvar_capture_map: FnvHashMap(), | |
247 | closure_tys: DefIdMap(), | |
248 | closure_kinds: DefIdMap(), | |
92a42be0 | 249 | liberated_fn_sigs: NodeMap(), |
7453a54e | 250 | fru_field_types: NodeMap() |
e9174d1e SL |
251 | } |
252 | } | |
253 | } | |
254 | ||
255 | impl<'tcx> CommonTypes<'tcx> { | |
a7813a04 XL |
256 | fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { |
257 | let mk = |sty| interners.intern_ty(sty, None); | |
e9174d1e SL |
258 | CommonTypes { |
259 | bool: mk(TyBool), | |
260 | char: mk(TyChar), | |
5bcae85e | 261 | never: mk(TyNever), |
e9174d1e | 262 | err: mk(TyError), |
7453a54e SL |
263 | isize: mk(TyInt(ast::IntTy::Is)), |
264 | i8: mk(TyInt(ast::IntTy::I8)), | |
265 | i16: mk(TyInt(ast::IntTy::I16)), | |
266 | i32: mk(TyInt(ast::IntTy::I32)), | |
267 | i64: mk(TyInt(ast::IntTy::I64)), | |
268 | usize: mk(TyUint(ast::UintTy::Us)), | |
269 | u8: mk(TyUint(ast::UintTy::U8)), | |
270 | u16: mk(TyUint(ast::UintTy::U16)), | |
271 | u32: mk(TyUint(ast::UintTy::U32)), | |
272 | u64: mk(TyUint(ast::UintTy::U64)), | |
273 | f32: mk(TyFloat(ast::FloatTy::F32)), | |
274 | f64: mk(TyFloat(ast::FloatTy::F64)), | |
e9174d1e SL |
275 | } |
276 | } | |
277 | } | |
278 | ||
279 | /// The data structure to keep track of all the information that typechecker | |
280 | /// generates so that so that it can be reused and doesn't have to be redone | |
281 | /// later on. | |
a7813a04 XL |
282 | #[derive(Copy, Clone)] |
283 | pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
284 | gcx: &'a GlobalCtxt<'gcx>, | |
285 | interners: &'a CtxtInterners<'tcx> | |
286 | } | |
e9174d1e | 287 | |
a7813a04 XL |
288 | impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> { |
289 | type Target = &'a GlobalCtxt<'gcx>; | |
290 | fn deref(&self) -> &Self::Target { | |
291 | &self.gcx | |
292 | } | |
293 | } | |
294 | ||
295 | pub struct GlobalCtxt<'tcx> { | |
296 | global_interners: CtxtInterners<'tcx>, | |
e9174d1e | 297 | |
a7813a04 | 298 | pub specializes_cache: RefCell<traits::SpecializesCache>, |
e9174d1e | 299 | |
9cc50fc6 SL |
300 | pub dep_graph: DepGraph, |
301 | ||
e9174d1e SL |
302 | /// Common types, pre-interned for your convenience. |
303 | pub types: CommonTypes<'tcx>, | |
304 | ||
b039eaaf | 305 | pub sess: &'tcx Session, |
5bcae85e SL |
306 | |
307 | /// Map from path id to the results from resolve; generated | |
308 | /// initially by resolve and updated during typeck in some cases | |
309 | /// (e.g., UFCS paths) | |
92a42be0 | 310 | pub def_map: RefCell<DefMap>, |
e9174d1e | 311 | |
5bcae85e SL |
312 | /// Map indicating what traits are in scope for places where this |
313 | /// is relevant; generated by resolve. | |
314 | pub trait_map: TraitMap, | |
315 | ||
e9174d1e SL |
316 | pub named_region_map: resolve_lifetime::NamedRegionMap, |
317 | ||
318 | pub region_maps: RegionMaps, | |
319 | ||
320 | // For each fn declared in the local crate, type check stores the | |
321 | // free-region relationships that were deduced from its where | |
322 | // clauses and parameter types. These are then read-again by | |
323 | // borrowck. (They are not used during trans, and hence are not | |
324 | // serialized or needed for cross-crate fns.) | |
325 | free_region_maps: RefCell<NodeMap<FreeRegionMap>>, | |
326 | // FIXME: jroesch make this a refcell | |
327 | ||
328 | pub tables: RefCell<Tables<'tcx>>, | |
329 | ||
330 | /// Maps from a trait item to the trait item "descriptor" | |
9cc50fc6 | 331 | pub impl_or_trait_items: RefCell<DepTrackingMap<maps::ImplOrTraitItems<'tcx>>>, |
e9174d1e | 332 | |
9e0c209e SL |
333 | /// Maps from an impl/trait def-id to a list of the def-ids of its items |
334 | pub impl_or_trait_item_def_ids: RefCell<DepTrackingMap<maps::ImplOrTraitItemDefIds<'tcx>>>, | |
e9174d1e | 335 | |
9cc50fc6 SL |
336 | /// A cache for the trait_items() routine; note that the routine |
337 | /// itself pushes the `TraitItems` dependency node. | |
338 | trait_items_cache: RefCell<DepTrackingMap<maps::TraitItems<'tcx>>>, | |
e9174d1e | 339 | |
9cc50fc6 SL |
340 | pub impl_trait_refs: RefCell<DepTrackingMap<maps::ImplTraitRefs<'tcx>>>, |
341 | pub trait_defs: RefCell<DepTrackingMap<maps::TraitDefs<'tcx>>>, | |
342 | pub adt_defs: RefCell<DepTrackingMap<maps::AdtDefs<'tcx>>>, | |
e9174d1e SL |
343 | |
344 | /// Maps from the def-id of an item (trait/struct/enum/fn) to its | |
9e0c209e SL |
345 | /// associated generics and predicates. |
346 | pub generics: RefCell<DepTrackingMap<maps::Generics<'tcx>>>, | |
9cc50fc6 | 347 | pub predicates: RefCell<DepTrackingMap<maps::Predicates<'tcx>>>, |
e9174d1e SL |
348 | |
349 | /// Maps from the def-id of a trait to the list of | |
350 | /// super-predicates. This is a subset of the full list of | |
351 | /// predicates. We store these in a separate map because we must | |
352 | /// evaluate them even during type conversion, often before the | |
353 | /// full predicates are available (note that supertraits have | |
354 | /// additional acyclicity requirements). | |
9cc50fc6 | 355 | pub super_predicates: RefCell<DepTrackingMap<maps::Predicates<'tcx>>>, |
e9174d1e SL |
356 | |
357 | pub map: ast_map::Map<'tcx>, | |
9cc50fc6 SL |
358 | |
359 | // Records the free variables refrenced by every closure | |
360 | // expression. Do not track deps for this, just recompute it from | |
361 | // scratch every time. | |
e9174d1e | 362 | pub freevars: RefCell<FreevarMap>, |
9cc50fc6 | 363 | |
a7813a04 XL |
364 | pub maybe_unused_trait_imports: NodeSet, |
365 | ||
9cc50fc6 SL |
366 | // Records the type of every item. |
367 | pub tcache: RefCell<DepTrackingMap<maps::Tcache<'tcx>>>, | |
368 | ||
369 | // Internal cache for metadata decoding. No need to track deps on this. | |
e9174d1e | 370 | pub rcache: RefCell<FnvHashMap<ty::CReaderCacheKey, Ty<'tcx>>>, |
9cc50fc6 SL |
371 | |
372 | // Cache for the type-contents routine. FIXME -- track deps? | |
e9174d1e | 373 | pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, ty::contents::TypeContents>>, |
9cc50fc6 | 374 | |
9cc50fc6 | 375 | // FIXME no dep tracking, but we should be able to remove this |
e9174d1e | 376 | pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>, |
9cc50fc6 SL |
377 | |
378 | // FIXME dep tracking -- should be harmless enough | |
e9174d1e | 379 | pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>, |
9cc50fc6 | 380 | |
e9174d1e | 381 | pub lang_items: middle::lang_items::LanguageItems, |
e9174d1e SL |
382 | |
383 | /// Maps from def-id of a type or region parameter to its | |
384 | /// (inferred) variance. | |
9cc50fc6 | 385 | pub item_variance_map: RefCell<DepTrackingMap<maps::ItemVariances<'tcx>>>, |
e9174d1e SL |
386 | |
387 | /// True if the variance has been computed yet; false otherwise. | |
388 | pub variance_computed: Cell<bool>, | |
389 | ||
390 | /// Maps a DefId of a type to a list of its inherent impls. | |
391 | /// Contains implementations of methods that are inherent to a type. | |
392 | /// Methods in these implementations don't need to be exported. | |
9cc50fc6 | 393 | pub inherent_impls: RefCell<DepTrackingMap<maps::InherentImpls<'tcx>>>, |
e9174d1e | 394 | |
e9174d1e SL |
395 | /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not |
396 | /// present in this set can be warned about. | |
397 | pub used_unsafe: RefCell<NodeSet>, | |
398 | ||
399 | /// Set of nodes which mark locals as mutable which end up getting used at | |
400 | /// some point. Local variable definitions not in this set can be warned | |
401 | /// about. | |
402 | pub used_mut_nodes: RefCell<NodeSet>, | |
403 | ||
a7813a04 XL |
404 | /// Set of trait imports actually used in the method resolution. |
405 | /// This is used for warning unused imports. | |
406 | pub used_trait_imports: RefCell<NodeSet>, | |
407 | ||
e9174d1e SL |
408 | /// The set of external nominal types whose implementations have been read. |
409 | /// This is used for lazy resolution of methods. | |
410 | pub populated_external_types: RefCell<DefIdSet>, | |
9cc50fc6 | 411 | |
e9174d1e SL |
412 | /// The set of external primitive types whose implementations have been read. |
413 | /// FIXME(arielb1): why is this separate from populated_external_types? | |
414 | pub populated_external_primitive_impls: RefCell<DefIdSet>, | |
415 | ||
54a0048b SL |
416 | /// Cache used by const_eval when decoding external constants. |
417 | /// Contains `None` when the constant has been fetched but doesn't exist. | |
418 | /// Constains `Some(expr_id, type)` otherwise. | |
419 | /// `type` is `None` in case it's not a primitive type | |
420 | pub extern_const_statics: RefCell<DefIdMap<Option<(NodeId, Option<Ty<'tcx>>)>>>, | |
421 | /// Cache used by const_eval when decoding extern const fns | |
e9174d1e SL |
422 | pub extern_const_fns: RefCell<DefIdMap<NodeId>>, |
423 | ||
e9174d1e SL |
424 | /// Maps any item's def-id to its stability index. |
425 | pub stability: RefCell<stability::Index<'tcx>>, | |
426 | ||
427 | /// Caches the results of trait selection. This cache is used | |
428 | /// for things that do not have to do with the parameters in scope. | |
429 | pub selection_cache: traits::SelectionCache<'tcx>, | |
430 | ||
92a42be0 SL |
431 | /// Caches the results of trait evaluation. This cache is used |
432 | /// for things that do not have to do with the parameters in scope. | |
433 | /// Merge this with `selection_cache`? | |
434 | pub evaluation_cache: traits::EvaluationCache<'tcx>, | |
435 | ||
e9174d1e SL |
436 | /// A set of predicates that have been fulfilled *somewhere*. |
437 | /// This is used to avoid duplicate work. Predicates are only | |
438 | /// added to this set when they mention only "global" names | |
439 | /// (i.e., no type or lifetime parameters). | |
7453a54e | 440 | pub fulfilled_predicates: RefCell<traits::GlobalFulfilledPredicates<'tcx>>, |
e9174d1e SL |
441 | |
442 | /// Caches the representation hints for struct definitions. | |
9cc50fc6 | 443 | repr_hint_cache: RefCell<DepTrackingMap<maps::ReprHints<'tcx>>>, |
e9174d1e SL |
444 | |
445 | /// Maps Expr NodeId's to their constant qualification. | |
7453a54e | 446 | pub const_qualif_map: RefCell<NodeMap<middle::const_qualif::ConstQualif>>, |
e9174d1e SL |
447 | |
448 | /// Caches CoerceUnsized kinds for impls on custom types. | |
449 | pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>, | |
450 | ||
451 | /// Maps a cast expression to its kind. This is keyed on the | |
452 | /// *from* expression of the cast, not the cast itself. | |
453 | pub cast_kinds: RefCell<NodeMap<ty::cast::CastKind>>, | |
454 | ||
455 | /// Maps Fn items to a collection of fragment infos. | |
456 | /// | |
457 | /// The main goal is to identify data (each of which may be moved | |
458 | /// or assigned) whose subparts are not moved nor assigned | |
459 | /// (i.e. their state is *unfragmented*) and corresponding ast | |
460 | /// nodes where the path to that data is moved or assigned. | |
461 | /// | |
462 | /// In the long term, unfragmented values will have their | |
463 | /// destructor entirely driven by a single stack-local drop-flag, | |
464 | /// and their parents, the collections of the unfragmented values | |
465 | /// (or more simply, "fragmented values"), are mapped to the | |
466 | /// corresponding collections of stack-local drop-flags. | |
467 | /// | |
468 | /// (However, in the short term that is not the case; e.g. some | |
469 | /// unfragmented paths still need to be zeroed, namely when they | |
470 | /// reference parent data from an outer scope that was not | |
471 | /// entirely moved, and therefore that needs to be zeroed so that | |
472 | /// we do not get double-drop when we hit the end of the parent | |
473 | /// scope.) | |
474 | /// | |
475 | /// Also: currently the table solely holds keys for node-ids of | |
476 | /// unfragmented values (see `FragmentInfo` enum definition), but | |
477 | /// longer-term we will need to also store mappings from | |
478 | /// fragmented data to the set of unfragmented pieces that | |
479 | /// constitute it. | |
480 | pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>, | |
54a0048b SL |
481 | |
482 | /// The definite name of the current crate after taking into account | |
483 | /// attributes, commandline parameters, etc. | |
484 | pub crate_name: token::InternedString, | |
485 | ||
486 | /// Data layout specification for the current target. | |
487 | pub data_layout: TargetDataLayout, | |
488 | ||
489 | /// Cache for layouts computed from types. | |
490 | pub layout_cache: RefCell<FnvHashMap<Ty<'tcx>, &'tcx Layout>>, | |
9e0c209e SL |
491 | |
492 | /// Used to prevent layout from recursing too deeply. | |
493 | pub layout_depth: Cell<usize>, | |
494 | ||
495 | /// Map from function to the `#[derive]` mode that it's defining. Only used | |
496 | /// by `rustc-macro` crates. | |
497 | pub derive_macros: RefCell<NodeMap<token::InternedString>>, | |
e9174d1e | 498 | } |
e9174d1e | 499 | |
a7813a04 XL |
500 | impl<'tcx> GlobalCtxt<'tcx> { |
501 | /// Get the global TyCtxt. | |
502 | pub fn global_tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { | |
503 | TyCtxt { | |
504 | gcx: self, | |
505 | interners: &self.global_interners | |
506 | } | |
507 | } | |
508 | } | |
509 | ||
510 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { | |
9e0c209e | 511 | pub fn crate_name(self, cnum: CrateNum) -> token::InternedString { |
54a0048b SL |
512 | if cnum == LOCAL_CRATE { |
513 | self.crate_name.clone() | |
514 | } else { | |
515 | self.sess.cstore.crate_name(cnum) | |
516 | } | |
517 | } | |
518 | ||
9e0c209e SL |
519 | pub fn original_crate_name(self, cnum: CrateNum) -> token::InternedString { |
520 | if cnum == LOCAL_CRATE { | |
521 | self.crate_name.clone() | |
522 | } else { | |
523 | self.sess.cstore.original_crate_name(cnum) | |
524 | } | |
525 | } | |
526 | ||
527 | pub fn crate_disambiguator(self, cnum: CrateNum) -> token::InternedString { | |
54a0048b | 528 | if cnum == LOCAL_CRATE { |
5bcae85e | 529 | self.sess.local_crate_disambiguator() |
54a0048b SL |
530 | } else { |
531 | self.sess.cstore.crate_disambiguator(cnum) | |
532 | } | |
533 | } | |
534 | ||
a7813a04 XL |
535 | /// Given a def-key `key` and a crate `krate`, finds the def-index |
536 | /// that `krate` assigned to `key`. This `DefIndex` will always be | |
537 | /// relative to `krate`. | |
538 | /// | |
539 | /// Returns `None` if there is no `DefIndex` with that key. | |
9e0c209e | 540 | pub fn def_index_for_def_key(self, krate: CrateNum, key: DefKey) |
a7813a04 XL |
541 | -> Option<DefIndex> { |
542 | if krate == LOCAL_CRATE { | |
543 | self.map.def_index_for_def_key(key) | |
544 | } else { | |
545 | self.sess.cstore.def_index_for_def_key(krate, key) | |
546 | } | |
547 | } | |
548 | ||
549 | pub fn retrace_path(self, path: &DefPath) -> Option<DefId> { | |
5bcae85e | 550 | debug!("retrace_path(path={:?}, krate={:?})", path, self.crate_name(path.krate)); |
a7813a04 XL |
551 | |
552 | let root_key = DefKey { | |
553 | parent: None, | |
554 | disambiguated_data: DisambiguatedDefPathData { | |
555 | data: DefPathData::CrateRoot, | |
556 | disambiguator: 0, | |
557 | }, | |
558 | }; | |
559 | ||
560 | let root_index = self.def_index_for_def_key(path.krate, root_key) | |
561 | .expect("no root key?"); | |
562 | ||
563 | debug!("retrace_path: root_index={:?}", root_index); | |
564 | ||
565 | let mut index = root_index; | |
566 | for data in &path.data { | |
567 | let key = DefKey { parent: Some(index), disambiguated_data: data.clone() }; | |
568 | debug!("retrace_path: key={:?}", key); | |
569 | match self.def_index_for_def_key(path.krate, key) { | |
570 | Some(i) => index = i, | |
571 | None => return None, | |
572 | } | |
573 | } | |
574 | ||
575 | Some(DefId { krate: path.krate, index: index }) | |
576 | } | |
577 | ||
578 | pub fn type_parameter_def(self, | |
e9174d1e SL |
579 | node_id: NodeId) |
580 | -> ty::TypeParameterDef<'tcx> | |
581 | { | |
582 | self.ty_param_defs.borrow().get(&node_id).unwrap().clone() | |
583 | } | |
584 | ||
a7813a04 | 585 | pub fn node_types(self) -> Ref<'a, NodeMap<Ty<'tcx>>> { |
e9174d1e SL |
586 | fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> { |
587 | &tables.node_types | |
588 | } | |
589 | ||
590 | Ref::map(self.tables.borrow(), projection) | |
591 | } | |
592 | ||
a7813a04 | 593 | pub fn node_type_insert(self, id: NodeId, ty: Ty<'gcx>) { |
e9174d1e SL |
594 | self.tables.borrow_mut().node_types.insert(id, ty); |
595 | } | |
596 | ||
9e0c209e SL |
597 | pub fn alloc_generics(self, generics: ty::Generics<'gcx>) |
598 | -> &'gcx ty::Generics<'gcx> { | |
599 | self.global_interners.arenas.generics.alloc(generics) | |
600 | } | |
601 | ||
a7813a04 XL |
602 | pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>) |
603 | -> &'gcx ty::TraitDef<'gcx> { | |
e9174d1e | 604 | let did = def.trait_ref.def_id; |
9e0c209e | 605 | let interned = self.alloc_trait_def(def); |
92a42be0 | 606 | if let Some(prev) = self.trait_defs.borrow_mut().insert(did, interned) { |
54a0048b | 607 | bug!("Tried to overwrite interned TraitDef: {:?}", prev) |
92a42be0 | 608 | } |
9e0c209e | 609 | self.generics.borrow_mut().insert(did, interned.generics); |
e9174d1e SL |
610 | interned |
611 | } | |
612 | ||
a7813a04 XL |
613 | pub fn alloc_trait_def(self, def: ty::TraitDef<'gcx>) |
614 | -> &'gcx ty::TraitDef<'gcx> { | |
615 | self.global_interners.arenas.trait_defs.alloc(def) | |
e9174d1e SL |
616 | } |
617 | ||
5bcae85e SL |
618 | pub fn insert_adt_def(self, did: DefId, adt_def: ty::AdtDefMaster<'gcx>) { |
619 | // this will need a transmute when reverse-variance is removed | |
620 | if let Some(prev) = self.adt_defs.borrow_mut().insert(did, adt_def) { | |
621 | bug!("Tried to overwrite interned AdtDef: {:?}", prev) | |
622 | } | |
623 | } | |
624 | ||
a7813a04 | 625 | pub fn intern_adt_def(self, |
e9174d1e | 626 | did: DefId, |
9e0c209e | 627 | kind: AdtKind, |
a7813a04 XL |
628 | variants: Vec<ty::VariantDefData<'gcx, 'gcx>>) |
629 | -> ty::AdtDefMaster<'gcx> { | |
e9174d1e | 630 | let def = ty::AdtDefData::new(self, did, kind, variants); |
a7813a04 | 631 | let interned = self.global_interners.arenas.adt_defs.alloc(def); |
5bcae85e | 632 | self.insert_adt_def(did, interned); |
e9174d1e SL |
633 | interned |
634 | } | |
635 | ||
a7813a04 XL |
636 | pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability { |
637 | if let Some(st) = self.global_interners.stability.borrow().get(&stab) { | |
e9174d1e SL |
638 | return st; |
639 | } | |
640 | ||
a7813a04 XL |
641 | let interned = self.global_interners.arenas.stability.alloc(stab); |
642 | if let Some(prev) = self.global_interners.stability | |
92a42be0 | 643 | .borrow_mut() |
a7813a04 | 644 | .replace(interned) { |
54a0048b SL |
645 | bug!("Tried to overwrite interned Stability: {:?}", prev) |
646 | } | |
647 | interned | |
648 | } | |
649 | ||
a7813a04 XL |
650 | pub fn intern_layout(self, layout: Layout) -> &'gcx Layout { |
651 | if let Some(layout) = self.global_interners.layout.borrow().get(&layout) { | |
54a0048b SL |
652 | return layout; |
653 | } | |
654 | ||
a7813a04 XL |
655 | let interned = self.global_interners.arenas.layout.alloc(layout); |
656 | if let Some(prev) = self.global_interners.layout | |
54a0048b | 657 | .borrow_mut() |
a7813a04 | 658 | .replace(interned) { |
54a0048b | 659 | bug!("Tried to overwrite interned Layout: {:?}", prev) |
92a42be0 | 660 | } |
e9174d1e SL |
661 | interned |
662 | } | |
663 | ||
a7813a04 | 664 | pub fn store_free_region_map(self, id: NodeId, map: FreeRegionMap) { |
92a42be0 | 665 | if self.free_region_maps.borrow_mut().insert(id, map).is_some() { |
54a0048b | 666 | bug!("Tried to overwrite interned FreeRegionMap for NodeId {:?}", id) |
92a42be0 | 667 | } |
e9174d1e SL |
668 | } |
669 | ||
a7813a04 | 670 | pub fn free_region_map(self, id: NodeId) -> FreeRegionMap { |
e9174d1e SL |
671 | self.free_region_maps.borrow()[&id].clone() |
672 | } | |
673 | ||
a7813a04 | 674 | pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> { |
e9174d1e SL |
675 | value.lift_to_tcx(self) |
676 | } | |
677 | ||
a7813a04 XL |
678 | /// Like lift, but only tries in the global tcx. |
679 | pub fn lift_to_global<T: ?Sized + Lift<'gcx>>(self, value: &T) -> Option<T::Lifted> { | |
680 | value.lift_to_tcx(self.global_tcx()) | |
681 | } | |
682 | ||
683 | /// Returns true if self is the same as self.global_tcx(). | |
684 | fn is_global(self) -> bool { | |
685 | let local = self.interners as *const _; | |
686 | let global = &self.global_interners as *const _; | |
687 | local as usize == global as usize | |
688 | } | |
689 | ||
690 | /// Create a type context and call the closure with a `TyCtxt` reference | |
e9174d1e SL |
691 | /// to the context. The closure enforces that the type context and any interned |
692 | /// value (types, substs, etc.) can only be used while `ty::tls` has a valid | |
693 | /// reference to the context, to allow formatting values that need it. | |
b039eaaf | 694 | pub fn create_and_enter<F, R>(s: &'tcx Session, |
a7813a04 | 695 | arenas: &'tcx CtxtArenas<'tcx>, |
3157f602 | 696 | def_map: DefMap, |
5bcae85e | 697 | trait_map: TraitMap, |
a7813a04 XL |
698 | named_region_map: resolve_lifetime::NamedRegionMap, |
699 | map: ast_map::Map<'tcx>, | |
700 | freevars: FreevarMap, | |
701 | maybe_unused_trait_imports: NodeSet, | |
702 | region_maps: RegionMaps, | |
703 | lang_items: middle::lang_items::LanguageItems, | |
704 | stability: stability::Index<'tcx>, | |
54a0048b | 705 | crate_name: &str, |
a7813a04 XL |
706 | f: F) -> R |
707 | where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R | |
e9174d1e | 708 | { |
54a0048b | 709 | let data_layout = TargetDataLayout::parse(s); |
a7813a04 XL |
710 | let interners = CtxtInterners::new(arenas); |
711 | let common_types = CommonTypes::new(&interners); | |
7453a54e SL |
712 | let dep_graph = map.dep_graph.clone(); |
713 | let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone()); | |
a7813a04 XL |
714 | tls::enter_global(GlobalCtxt { |
715 | specializes_cache: RefCell::new(traits::SpecializesCache::new()), | |
716 | global_interners: interners, | |
9cc50fc6 | 717 | dep_graph: dep_graph.clone(), |
e9174d1e SL |
718 | types: common_types, |
719 | named_region_map: named_region_map, | |
720 | region_maps: region_maps, | |
721 | free_region_maps: RefCell::new(FnvHashMap()), | |
9cc50fc6 | 722 | item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
e9174d1e SL |
723 | variance_computed: Cell::new(false), |
724 | sess: s, | |
3157f602 | 725 | def_map: RefCell::new(def_map), |
5bcae85e | 726 | trait_map: trait_map, |
e9174d1e | 727 | tables: RefCell::new(Tables::empty()), |
9cc50fc6 SL |
728 | impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
729 | trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), | |
730 | adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), | |
9e0c209e | 731 | generics: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
9cc50fc6 SL |
732 | predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
733 | super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), | |
7453a54e | 734 | fulfilled_predicates: RefCell::new(fulfilled_predicates), |
e9174d1e | 735 | map: map, |
92a42be0 | 736 | freevars: RefCell::new(freevars), |
a7813a04 | 737 | maybe_unused_trait_imports: maybe_unused_trait_imports, |
9cc50fc6 | 738 | tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
e9174d1e SL |
739 | rcache: RefCell::new(FnvHashMap()), |
740 | tc_cache: RefCell::new(FnvHashMap()), | |
9cc50fc6 | 741 | impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
9e0c209e | 742 | impl_or_trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
9cc50fc6 | 743 | trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
e9174d1e SL |
744 | ty_param_defs: RefCell::new(NodeMap()), |
745 | normalized_cache: RefCell::new(FnvHashMap()), | |
746 | lang_items: lang_items, | |
9cc50fc6 | 747 | inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
e9174d1e SL |
748 | used_unsafe: RefCell::new(NodeSet()), |
749 | used_mut_nodes: RefCell::new(NodeSet()), | |
a7813a04 | 750 | used_trait_imports: RefCell::new(NodeSet()), |
e9174d1e SL |
751 | populated_external_types: RefCell::new(DefIdSet()), |
752 | populated_external_primitive_impls: RefCell::new(DefIdSet()), | |
753 | extern_const_statics: RefCell::new(DefIdMap()), | |
e9174d1e | 754 | extern_const_fns: RefCell::new(DefIdMap()), |
e9174d1e SL |
755 | stability: RefCell::new(stability), |
756 | selection_cache: traits::SelectionCache::new(), | |
92a42be0 | 757 | evaluation_cache: traits::EvaluationCache::new(), |
9cc50fc6 | 758 | repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), |
e9174d1e SL |
759 | const_qualif_map: RefCell::new(NodeMap()), |
760 | custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), | |
761 | cast_kinds: RefCell::new(NodeMap()), | |
54a0048b SL |
762 | fragment_infos: RefCell::new(DefIdMap()), |
763 | crate_name: token::intern_and_get_ident(crate_name), | |
764 | data_layout: data_layout, | |
765 | layout_cache: RefCell::new(FnvHashMap()), | |
9e0c209e SL |
766 | layout_depth: Cell::new(0), |
767 | derive_macros: RefCell::new(NodeMap()), | |
e9174d1e SL |
768 | }, f) |
769 | } | |
770 | } | |
771 | ||
a7813a04 XL |
772 | impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { |
773 | /// Call the closure with a local `TyCtxt` using the given arenas. | |
774 | pub fn enter_local<F, R>(&self, arenas: &'tcx CtxtArenas<'tcx>, f: F) -> R | |
775 | where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
776 | { | |
777 | let interners = CtxtInterners::new(arenas); | |
778 | tls::enter(self, &interners, f) | |
779 | } | |
780 | } | |
781 | ||
e9174d1e SL |
782 | /// A trait implemented for all X<'a> types which can be safely and |
783 | /// efficiently converted to X<'tcx> as long as they are part of the | |
54a0048b | 784 | /// provided TyCtxt<'tcx>. |
e9174d1e SL |
785 | /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx> |
786 | /// by looking them up in their respective interners. | |
a7813a04 XL |
787 | /// |
788 | /// However, this is still not the best implementation as it does | |
789 | /// need to compare the components, even for interned values. | |
790 | /// It would be more efficient if TypedArena provided a way to | |
791 | /// determine whether the address is in the allocated range. | |
792 | /// | |
e9174d1e SL |
793 | /// None is returned if the value or one of the components is not part |
794 | /// of the provided context. | |
795 | /// For Ty, None can be returned if either the type interner doesn't | |
796 | /// contain the TypeVariants key or if the address of the interned | |
797 | /// pointer differs. The latter case is possible if a primitive type, | |
798 | /// e.g. `()` or `u8`, was interned in a different context. | |
799 | pub trait Lift<'tcx> { | |
800 | type Lifted; | |
a7813a04 | 801 | fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>; |
e9174d1e SL |
802 | } |
803 | ||
804 | impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { | |
805 | type Lifted = Ty<'tcx>; | |
a7813a04 XL |
806 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> { |
807 | if let Some(&Interned(ty)) = tcx.interners.type_.borrow().get(&self.sty) { | |
e9174d1e SL |
808 | if *self as *const _ == ty as *const _ { |
809 | return Some(ty); | |
810 | } | |
811 | } | |
a7813a04 XL |
812 | // Also try in the global tcx if we're not that. |
813 | if !tcx.is_global() { | |
814 | self.lift_to_tcx(tcx.global_tcx()) | |
815 | } else { | |
816 | None | |
817 | } | |
e9174d1e SL |
818 | } |
819 | } | |
820 | ||
821 | impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { | |
822 | type Lifted = &'tcx Substs<'tcx>; | |
a7813a04 XL |
823 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> { |
824 | if let Some(&Interned(substs)) = tcx.interners.substs.borrow().get(*self) { | |
e9174d1e SL |
825 | if *self as *const _ == substs as *const _ { |
826 | return Some(substs); | |
827 | } | |
828 | } | |
a7813a04 XL |
829 | // Also try in the global tcx if we're not that. |
830 | if !tcx.is_global() { | |
831 | self.lift_to_tcx(tcx.global_tcx()) | |
832 | } else { | |
833 | None | |
834 | } | |
835 | } | |
836 | } | |
837 | ||
838 | impl<'a, 'tcx> Lift<'tcx> for &'a Region { | |
839 | type Lifted = &'tcx Region; | |
840 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> { | |
841 | if let Some(&Interned(region)) = tcx.interners.region.borrow().get(*self) { | |
842 | if *self as *const _ == region as *const _ { | |
843 | return Some(region); | |
844 | } | |
845 | } | |
846 | // Also try in the global tcx if we're not that. | |
847 | if !tcx.is_global() { | |
848 | self.lift_to_tcx(tcx.global_tcx()) | |
849 | } else { | |
850 | None | |
851 | } | |
852 | } | |
853 | } | |
854 | ||
9e0c209e SL |
855 | impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> { |
856 | type Lifted = &'tcx Slice<Ty<'tcx>>; | |
857 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) | |
858 | -> Option<&'tcx Slice<Ty<'tcx>>> { | |
859 | if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) { | |
a7813a04 XL |
860 | if *self as *const _ == list as *const _ { |
861 | return Some(list); | |
862 | } | |
863 | } | |
864 | // Also try in the global tcx if we're not that. | |
865 | if !tcx.is_global() { | |
866 | self.lift_to_tcx(tcx.global_tcx()) | |
867 | } else { | |
868 | None | |
869 | } | |
870 | } | |
871 | } | |
872 | ||
873 | impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> { | |
874 | type Lifted = &'tcx BareFnTy<'tcx>; | |
875 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) | |
876 | -> Option<&'tcx BareFnTy<'tcx>> { | |
877 | if let Some(&Interned(fty)) = tcx.interners.bare_fn.borrow().get(*self) { | |
878 | if *self as *const _ == fty as *const _ { | |
879 | return Some(fty); | |
880 | } | |
881 | } | |
882 | // Also try in the global tcx if we're not that. | |
883 | if !tcx.is_global() { | |
884 | self.lift_to_tcx(tcx.global_tcx()) | |
885 | } else { | |
886 | None | |
887 | } | |
e9174d1e SL |
888 | } |
889 | } | |
890 | ||
891 | ||
892 | pub mod tls { | |
a7813a04 | 893 | use super::{CtxtInterners, GlobalCtxt, TyCtxt}; |
e9174d1e | 894 | |
7453a54e | 895 | use std::cell::Cell; |
e9174d1e | 896 | use std::fmt; |
3157f602 | 897 | use syntax_pos; |
e9174d1e | 898 | |
a7813a04 | 899 | /// Marker types used for the scoped TLS slot. |
e9174d1e SL |
900 | /// The type context cannot be used directly because the scoped TLS |
901 | /// in libstd doesn't allow types generic over lifetimes. | |
a7813a04 XL |
902 | enum ThreadLocalGlobalCtxt {} |
903 | enum ThreadLocalInterners {} | |
e9174d1e | 904 | |
7453a54e | 905 | thread_local! { |
a7813a04 XL |
906 | static TLS_TCX: Cell<Option<(*const ThreadLocalGlobalCtxt, |
907 | *const ThreadLocalInterners)>> = Cell::new(None) | |
7453a54e | 908 | } |
e9174d1e | 909 | |
3157f602 | 910 | fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter) -> fmt::Result { |
e9174d1e SL |
911 | with(|tcx| { |
912 | write!(f, "{}", tcx.sess.codemap().span_to_string(span)) | |
913 | }) | |
914 | } | |
915 | ||
a7813a04 XL |
916 | pub fn enter_global<'gcx, F, R>(gcx: GlobalCtxt<'gcx>, f: F) -> R |
917 | where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R | |
918 | { | |
3157f602 | 919 | syntax_pos::SPAN_DEBUG.with(|span_dbg| { |
e9174d1e SL |
920 | let original_span_debug = span_dbg.get(); |
921 | span_dbg.set(span_debug); | |
a7813a04 | 922 | let result = enter(&gcx, &gcx.global_interners, f); |
e9174d1e SL |
923 | span_dbg.set(original_span_debug); |
924 | result | |
b039eaaf | 925 | }) |
e9174d1e SL |
926 | } |
927 | ||
a7813a04 XL |
928 | pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(gcx: &'a GlobalCtxt<'gcx>, |
929 | interners: &'a CtxtInterners<'tcx>, | |
930 | f: F) -> R | |
931 | where F: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
932 | { | |
933 | let gcx_ptr = gcx as *const _ as *const ThreadLocalGlobalCtxt; | |
934 | let interners_ptr = interners as *const _ as *const ThreadLocalInterners; | |
935 | TLS_TCX.with(|tls| { | |
936 | let prev = tls.get(); | |
937 | tls.set(Some((gcx_ptr, interners_ptr))); | |
938 | let ret = f(TyCtxt { | |
939 | gcx: gcx, | |
940 | interners: interners | |
941 | }); | |
942 | tls.set(prev); | |
943 | ret | |
944 | }) | |
945 | } | |
946 | ||
947 | pub fn with<F, R>(f: F) -> R | |
948 | where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
949 | { | |
7453a54e | 950 | TLS_TCX.with(|tcx| { |
a7813a04 XL |
951 | let (gcx, interners) = tcx.get().unwrap(); |
952 | let gcx = unsafe { &*(gcx as *const GlobalCtxt) }; | |
953 | let interners = unsafe { &*(interners as *const CtxtInterners) }; | |
954 | f(TyCtxt { | |
955 | gcx: gcx, | |
956 | interners: interners | |
957 | }) | |
7453a54e | 958 | }) |
e9174d1e SL |
959 | } |
960 | ||
a7813a04 XL |
961 | pub fn with_opt<F, R>(f: F) -> R |
962 | where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R | |
963 | { | |
7453a54e | 964 | if TLS_TCX.with(|tcx| tcx.get().is_some()) { |
e9174d1e SL |
965 | with(|v| f(Some(v))) |
966 | } else { | |
967 | f(None) | |
968 | } | |
969 | } | |
970 | } | |
971 | ||
972 | macro_rules! sty_debug_print { | |
973 | ($ctxt: expr, $($variant: ident),*) => {{ | |
974 | // curious inner module to allow variant names to be used as | |
975 | // variable names. | |
976 | #[allow(non_snake_case)] | |
977 | mod inner { | |
54a0048b | 978 | use ty::{self, TyCtxt}; |
a7813a04 XL |
979 | use ty::context::Interned; |
980 | ||
e9174d1e SL |
981 | #[derive(Copy, Clone)] |
982 | struct DebugStat { | |
983 | total: usize, | |
984 | region_infer: usize, | |
985 | ty_infer: usize, | |
986 | both_infer: usize, | |
987 | } | |
988 | ||
a7813a04 | 989 | pub fn go(tcx: TyCtxt) { |
e9174d1e SL |
990 | let mut total = DebugStat { |
991 | total: 0, | |
992 | region_infer: 0, ty_infer: 0, both_infer: 0, | |
993 | }; | |
994 | $(let mut $variant = total;)* | |
995 | ||
996 | ||
a7813a04 | 997 | for &Interned(t) in tcx.interners.type_.borrow().iter() { |
e9174d1e SL |
998 | let variant = match t.sty { |
999 | ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | | |
5bcae85e | 1000 | ty::TyFloat(..) | ty::TyStr | ty::TyNever => continue, |
e9174d1e SL |
1001 | ty::TyError => /* unimportant */ continue, |
1002 | $(ty::$variant(..) => &mut $variant,)* | |
1003 | }; | |
1004 | let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER); | |
1005 | let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER); | |
1006 | ||
1007 | variant.total += 1; | |
1008 | total.total += 1; | |
1009 | if region { total.region_infer += 1; variant.region_infer += 1 } | |
1010 | if ty { total.ty_infer += 1; variant.ty_infer += 1 } | |
1011 | if region && ty { total.both_infer += 1; variant.both_infer += 1 } | |
1012 | } | |
1013 | println!("Ty interner total ty region both"); | |
1014 | $(println!(" {:18}: {uses:6} {usespc:4.1}%, \ | |
1015 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
1016 | stringify!($variant), | |
1017 | uses = $variant.total, | |
1018 | usespc = $variant.total as f64 * 100.0 / total.total as f64, | |
1019 | ty = $variant.ty_infer as f64 * 100.0 / total.total as f64, | |
1020 | region = $variant.region_infer as f64 * 100.0 / total.total as f64, | |
1021 | both = $variant.both_infer as f64 * 100.0 / total.total as f64); | |
1022 | )* | |
1023 | println!(" total {uses:6} \ | |
1024 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
1025 | uses = total.total, | |
1026 | ty = total.ty_infer as f64 * 100.0 / total.total as f64, | |
1027 | region = total.region_infer as f64 * 100.0 / total.total as f64, | |
1028 | both = total.both_infer as f64 * 100.0 / total.total as f64) | |
1029 | } | |
1030 | } | |
1031 | ||
1032 | inner::go($ctxt) | |
1033 | }} | |
1034 | } | |
1035 | ||
a7813a04 XL |
1036 | impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { |
1037 | pub fn print_debug_stats(self) { | |
e9174d1e SL |
1038 | sty_debug_print!( |
1039 | self, | |
9e0c209e SL |
1040 | TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, |
1041 | TyTrait, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); | |
e9174d1e | 1042 | |
a7813a04 XL |
1043 | println!("Substs interner: #{}", self.interners.substs.borrow().len()); |
1044 | println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len()); | |
1045 | println!("Region interner: #{}", self.interners.region.borrow().len()); | |
1046 | println!("Stability interner: #{}", self.interners.stability.borrow().len()); | |
1047 | println!("Layout interner: #{}", self.interners.layout.borrow().len()); | |
e9174d1e SL |
1048 | } |
1049 | } | |
1050 | ||
1051 | ||
a7813a04 XL |
1052 | /// An entry in an interner. |
1053 | struct Interned<'tcx, T: 'tcx+?Sized>(&'tcx T); | |
e9174d1e | 1054 | |
a7813a04 XL |
1055 | // NB: An Interned<Ty> compares and hashes as a sty. |
1056 | impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { | |
1057 | fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { | |
1058 | self.0.sty == other.0.sty | |
e9174d1e SL |
1059 | } |
1060 | } | |
1061 | ||
a7813a04 | 1062 | impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {} |
e9174d1e | 1063 | |
a7813a04 | 1064 | impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { |
e9174d1e | 1065 | fn hash<H: Hasher>(&self, s: &mut H) { |
a7813a04 | 1066 | self.0.sty.hash(s) |
e9174d1e SL |
1067 | } |
1068 | } | |
1069 | ||
a7813a04 XL |
1070 | impl<'tcx: 'lcx, 'lcx> Borrow<TypeVariants<'lcx>> for Interned<'tcx, TyS<'tcx>> { |
1071 | fn borrow<'a>(&'a self) -> &'a TypeVariants<'lcx> { | |
1072 | &self.0.sty | |
e9174d1e SL |
1073 | } |
1074 | } | |
1075 | ||
9e0c209e SL |
1076 | // NB: An Interned<Slice<T>> compares and hashes as its elements. |
1077 | impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, Slice<T>> { | |
1078 | fn eq(&self, other: &Interned<'tcx, Slice<T>>) -> bool { | |
1079 | self.0[..] == other.0[..] | |
1080 | } | |
1081 | } | |
1082 | ||
1083 | impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice<T>> {} | |
1084 | ||
1085 | impl<'tcx, T: Hash> Hash for Interned<'tcx, Slice<T>> { | |
1086 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1087 | self.0[..].hash(s) | |
1088 | } | |
1089 | } | |
1090 | ||
1091 | impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, Slice<Ty<'tcx>>> { | |
a7813a04 | 1092 | fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { |
9e0c209e | 1093 | &self.0[..] |
a7813a04 | 1094 | } |
e9174d1e SL |
1095 | } |
1096 | ||
a7813a04 XL |
1097 | impl<'tcx: 'lcx, 'lcx> Borrow<Substs<'lcx>> for Interned<'tcx, Substs<'tcx>> { |
1098 | fn borrow<'a>(&'a self) -> &'a Substs<'lcx> { | |
1099 | self.0 | |
1100 | } | |
1101 | } | |
e9174d1e | 1102 | |
a7813a04 XL |
1103 | impl<'tcx: 'lcx, 'lcx> Borrow<BareFnTy<'lcx>> for Interned<'tcx, BareFnTy<'tcx>> { |
1104 | fn borrow<'a>(&'a self) -> &'a BareFnTy<'lcx> { | |
1105 | self.0 | |
e9174d1e | 1106 | } |
a7813a04 | 1107 | } |
e9174d1e | 1108 | |
a7813a04 XL |
1109 | impl<'tcx> Borrow<Region> for Interned<'tcx, Region> { |
1110 | fn borrow<'a>(&'a self) -> &'a Region { | |
1111 | self.0 | |
e9174d1e | 1112 | } |
a7813a04 | 1113 | } |
e9174d1e | 1114 | |
9e0c209e SL |
1115 | macro_rules! intern_method { |
1116 | ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, | |
1117 | $alloc_to_key:expr, | |
1118 | $alloc_to_ret:expr, | |
1119 | $needs_infer:expr) -> $ty:ty) => { | |
a7813a04 XL |
1120 | impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { |
1121 | pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { | |
9e0c209e SL |
1122 | { |
1123 | let key = ($alloc_to_key)(&v); | |
1124 | if let Some(i) = self.interners.$name.borrow().get(key) { | |
a7813a04 XL |
1125 | return i.0; |
1126 | } | |
9e0c209e SL |
1127 | if !self.is_global() { |
1128 | if let Some(i) = self.global_interners.$name.borrow().get(key) { | |
1129 | return i.0; | |
1130 | } | |
1131 | } | |
a7813a04 | 1132 | } |
e9174d1e | 1133 | |
a7813a04 XL |
1134 | // HACK(eddyb) Depend on flags being accurate to |
1135 | // determine that all contents are in the global tcx. | |
1136 | // See comments on Lift for why we can't use that. | |
1137 | if !($needs_infer)(&v) { | |
1138 | if !self.is_global() { | |
1139 | let v = unsafe { | |
1140 | mem::transmute(v) | |
1141 | }; | |
9e0c209e | 1142 | let i = ($alloc_to_ret)(self.global_interners.arenas.$name.alloc(v)); |
a7813a04 XL |
1143 | self.global_interners.$name.borrow_mut().insert(Interned(i)); |
1144 | return i; | |
1145 | } | |
1146 | } else { | |
1147 | // Make sure we don't end up with inference | |
1148 | // types/regions in the global tcx. | |
1149 | if self.is_global() { | |
1150 | bug!("Attempted to intern `{:?}` which contains \ | |
1151 | inference types/regions in the global type context", | |
1152 | v); | |
1153 | } | |
1154 | } | |
1155 | ||
9e0c209e | 1156 | let i = ($alloc_to_ret)(self.interners.arenas.$name.alloc(v)); |
a7813a04 XL |
1157 | self.interners.$name.borrow_mut().insert(Interned(i)); |
1158 | i | |
e9174d1e | 1159 | } |
9e0c209e SL |
1160 | } |
1161 | } | |
1162 | } | |
1163 | ||
1164 | macro_rules! direct_interners { | |
1165 | ($lt_tcx:tt, $($name:ident: $method:ident($needs_infer:expr) -> $ty:ty),+) => { | |
1166 | $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { | |
1167 | fn eq(&self, other: &Self) -> bool { | |
1168 | self.0 == other.0 | |
1169 | } | |
1170 | } | |
1171 | ||
1172 | impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} | |
1173 | ||
1174 | impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { | |
1175 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1176 | self.0.hash(s) | |
1177 | } | |
1178 | } | |
1179 | ||
1180 | intern_method!($lt_tcx, $name: $method($ty, |x| x, |x| x, $needs_infer) -> $ty);)+ | |
a7813a04 XL |
1181 | } |
1182 | } | |
e9174d1e | 1183 | |
a7813a04 XL |
1184 | fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { |
1185 | x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) | |
1186 | } | |
e9174d1e | 1187 | |
9e0c209e SL |
1188 | direct_interners!('tcx, |
1189 | substs: mk_substs(|substs: &Substs| { | |
1190 | substs.params().iter().any(keep_local) | |
a7813a04 | 1191 | }) -> Substs<'tcx>, |
9e0c209e | 1192 | bare_fn: mk_bare_fn(|fty: &BareFnTy| { |
a7813a04 XL |
1193 | keep_local(&fty.sig) |
1194 | }) -> BareFnTy<'tcx>, | |
9e0c209e SL |
1195 | region: mk_region(|r| { |
1196 | match r { | |
1197 | &ty::ReVar(_) | &ty::ReSkolemized(..) => true, | |
1198 | _ => false | |
1199 | } | |
1200 | }) -> Region | |
a7813a04 | 1201 | ); |
e9174d1e | 1202 | |
9e0c209e SL |
1203 | intern_method!('tcx, |
1204 | type_list: mk_type_list(Vec<Ty<'tcx>>, Deref::deref, |xs: &[Ty]| -> &Slice<Ty> { | |
1205 | unsafe { mem::transmute(xs) } | |
1206 | }, keep_local) -> Slice<Ty<'tcx>> | |
1207 | ); | |
e9174d1e | 1208 | |
a7813a04 XL |
1209 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
1210 | /// Create an unsafe fn ty based on a safe fn ty. | |
1211 | pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { | |
1212 | assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal); | |
1213 | self.mk_fn_ptr(self.mk_bare_fn(ty::BareFnTy { | |
1214 | unsafety: hir::Unsafety::Unsafe, | |
1215 | abi: bare_fn.abi, | |
1216 | sig: bare_fn.sig.clone() | |
1217 | })) | |
e9174d1e SL |
1218 | } |
1219 | ||
a7813a04 | 1220 | // Interns a type/name combination, stores the resulting box in cx.interners, |
e9174d1e | 1221 | // and returns the box as cast to an unsafe ptr (see comments for Ty above). |
a7813a04 XL |
1222 | pub fn mk_ty(self, st: TypeVariants<'tcx>) -> Ty<'tcx> { |
1223 | let global_interners = if !self.is_global() { | |
1224 | Some(&self.global_interners) | |
1225 | } else { | |
1226 | None | |
1227 | }; | |
1228 | self.interners.intern_ty(st, global_interners) | |
e9174d1e SL |
1229 | } |
1230 | ||
a7813a04 | 1231 | pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> { |
e9174d1e | 1232 | match tm { |
7453a54e SL |
1233 | ast::IntTy::Is => self.types.isize, |
1234 | ast::IntTy::I8 => self.types.i8, | |
1235 | ast::IntTy::I16 => self.types.i16, | |
1236 | ast::IntTy::I32 => self.types.i32, | |
1237 | ast::IntTy::I64 => self.types.i64, | |
e9174d1e SL |
1238 | } |
1239 | } | |
1240 | ||
a7813a04 | 1241 | pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'tcx> { |
e9174d1e | 1242 | match tm { |
7453a54e SL |
1243 | ast::UintTy::Us => self.types.usize, |
1244 | ast::UintTy::U8 => self.types.u8, | |
1245 | ast::UintTy::U16 => self.types.u16, | |
1246 | ast::UintTy::U32 => self.types.u32, | |
1247 | ast::UintTy::U64 => self.types.u64, | |
e9174d1e SL |
1248 | } |
1249 | } | |
1250 | ||
a7813a04 | 1251 | pub fn mk_mach_float(self, tm: ast::FloatTy) -> Ty<'tcx> { |
e9174d1e | 1252 | match tm { |
7453a54e SL |
1253 | ast::FloatTy::F32 => self.types.f32, |
1254 | ast::FloatTy::F64 => self.types.f64, | |
e9174d1e SL |
1255 | } |
1256 | } | |
1257 | ||
a7813a04 | 1258 | pub fn mk_str(self) -> Ty<'tcx> { |
e9174d1e SL |
1259 | self.mk_ty(TyStr) |
1260 | } | |
1261 | ||
a7813a04 | 1262 | pub fn mk_static_str(self) -> Ty<'tcx> { |
e9174d1e SL |
1263 | self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str()) |
1264 | } | |
1265 | ||
9e0c209e | 1266 | pub fn mk_adt(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
e9174d1e | 1267 | // take a copy of substs so that we own the vectors inside |
9e0c209e | 1268 | self.mk_ty(TyAdt(def, substs)) |
e9174d1e SL |
1269 | } |
1270 | ||
a7813a04 | 1271 | pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1272 | self.mk_ty(TyBox(ty)) |
1273 | } | |
1274 | ||
a7813a04 | 1275 | pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1276 | self.mk_ty(TyRawPtr(tm)) |
1277 | } | |
1278 | ||
a7813a04 | 1279 | pub fn mk_ref(self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1280 | self.mk_ty(TyRef(r, tm)) |
1281 | } | |
1282 | ||
a7813a04 | 1283 | pub fn mk_mut_ref(self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1284 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable}) |
1285 | } | |
1286 | ||
a7813a04 | 1287 | pub fn mk_imm_ref(self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1288 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) |
1289 | } | |
1290 | ||
a7813a04 | 1291 | pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1292 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable}) |
1293 | } | |
1294 | ||
a7813a04 | 1295 | pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1296 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) |
1297 | } | |
1298 | ||
a7813a04 | 1299 | pub fn mk_nil_ptr(self) -> Ty<'tcx> { |
e9174d1e SL |
1300 | self.mk_imm_ptr(self.mk_nil()) |
1301 | } | |
1302 | ||
a7813a04 | 1303 | pub fn mk_array(self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> { |
e9174d1e SL |
1304 | self.mk_ty(TyArray(ty, n)) |
1305 | } | |
1306 | ||
a7813a04 | 1307 | pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1308 | self.mk_ty(TySlice(ty)) |
1309 | } | |
1310 | ||
a7813a04 XL |
1311 | pub fn mk_tup(self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> { |
1312 | self.mk_ty(TyTuple(self.mk_type_list(ts))) | |
e9174d1e SL |
1313 | } |
1314 | ||
a7813a04 | 1315 | pub fn mk_nil(self) -> Ty<'tcx> { |
e9174d1e SL |
1316 | self.mk_tup(Vec::new()) |
1317 | } | |
1318 | ||
5bcae85e SL |
1319 | pub fn mk_diverging_default(self) -> Ty<'tcx> { |
1320 | if self.sess.features.borrow().never_type { | |
1321 | self.types.never | |
1322 | } else { | |
1323 | self.mk_nil() | |
1324 | } | |
1325 | } | |
1326 | ||
a7813a04 | 1327 | pub fn mk_bool(self) -> Ty<'tcx> { |
e9174d1e SL |
1328 | self.mk_ty(TyBool) |
1329 | } | |
1330 | ||
a7813a04 | 1331 | pub fn mk_fn_def(self, def_id: DefId, |
54a0048b | 1332 | substs: &'tcx Substs<'tcx>, |
a7813a04 XL |
1333 | fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { |
1334 | self.mk_ty(TyFnDef(def_id, substs, fty)) | |
54a0048b SL |
1335 | } |
1336 | ||
a7813a04 XL |
1337 | pub fn mk_fn_ptr(self, fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { |
1338 | self.mk_ty(TyFnPtr(fty)) | |
e9174d1e SL |
1339 | } |
1340 | ||
9e0c209e SL |
1341 | pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> { |
1342 | obj.projection_bounds.sort_by_key(|b| b.sort_key(self)); | |
1343 | self.mk_ty(TyTrait(box obj)) | |
e9174d1e SL |
1344 | } |
1345 | ||
a7813a04 | 1346 | pub fn mk_projection(self, |
e9174d1e SL |
1347 | trait_ref: TraitRef<'tcx>, |
1348 | item_name: Name) | |
1349 | -> Ty<'tcx> { | |
1350 | // take a copy of substs so that we own the vectors inside | |
1351 | let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; | |
1352 | self.mk_ty(TyProjection(inner)) | |
1353 | } | |
1354 | ||
a7813a04 | 1355 | pub fn mk_closure(self, |
e9174d1e SL |
1356 | closure_id: DefId, |
1357 | substs: &'tcx Substs<'tcx>, | |
1358 | tys: Vec<Ty<'tcx>>) | |
1359 | -> Ty<'tcx> { | |
a7813a04 | 1360 | self.mk_closure_from_closure_substs(closure_id, ClosureSubsts { |
e9174d1e | 1361 | func_substs: substs, |
a7813a04 XL |
1362 | upvar_tys: self.mk_type_list(tys) |
1363 | }) | |
e9174d1e SL |
1364 | } |
1365 | ||
a7813a04 | 1366 | pub fn mk_closure_from_closure_substs(self, |
e9174d1e | 1367 | closure_id: DefId, |
a7813a04 | 1368 | closure_substs: ClosureSubsts<'tcx>) |
e9174d1e SL |
1369 | -> Ty<'tcx> { |
1370 | self.mk_ty(TyClosure(closure_id, closure_substs)) | |
1371 | } | |
1372 | ||
a7813a04 | 1373 | pub fn mk_var(self, v: TyVid) -> Ty<'tcx> { |
e9174d1e SL |
1374 | self.mk_infer(TyVar(v)) |
1375 | } | |
1376 | ||
a7813a04 | 1377 | pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { |
e9174d1e SL |
1378 | self.mk_infer(IntVar(v)) |
1379 | } | |
1380 | ||
a7813a04 | 1381 | pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { |
e9174d1e SL |
1382 | self.mk_infer(FloatVar(v)) |
1383 | } | |
1384 | ||
a7813a04 | 1385 | pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> { |
e9174d1e SL |
1386 | self.mk_ty(TyInfer(it)) |
1387 | } | |
1388 | ||
a7813a04 | 1389 | pub fn mk_param(self, |
e9174d1e SL |
1390 | index: u32, |
1391 | name: Name) -> Ty<'tcx> { | |
9e0c209e | 1392 | self.mk_ty(TyParam(ParamTy { idx: index, name: name })) |
e9174d1e SL |
1393 | } |
1394 | ||
a7813a04 | 1395 | pub fn mk_self_type(self) -> Ty<'tcx> { |
9e0c209e | 1396 | self.mk_param(0, keywords::SelfType.name()) |
e9174d1e SL |
1397 | } |
1398 | ||
a7813a04 | 1399 | pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { |
9e0c209e | 1400 | self.mk_param(def.index, def.name) |
e9174d1e | 1401 | } |
9cc50fc6 | 1402 | |
5bcae85e SL |
1403 | pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
1404 | self.mk_ty(TyAnon(def_id, substs)) | |
1405 | } | |
1406 | ||
a7813a04 | 1407 | pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> { |
9cc50fc6 | 1408 | self.trait_items_cache.memoize(trait_did, || { |
9e0c209e | 1409 | let def_ids = self.impl_or_trait_items(trait_did); |
9cc50fc6 | 1410 | Rc::new(def_ids.iter() |
9e0c209e | 1411 | .map(|&def_id| self.impl_or_trait_item(def_id)) |
9cc50fc6 SL |
1412 | .collect()) |
1413 | }) | |
1414 | } | |
1415 | ||
1416 | /// Obtain the representation annotation for a struct definition. | |
a7813a04 | 1417 | pub fn lookup_repr_hints(self, did: DefId) -> Rc<Vec<attr::ReprAttr>> { |
9cc50fc6 | 1418 | self.repr_hint_cache.memoize(did, || { |
9e0c209e SL |
1419 | Rc::new(self.get_attrs(did).iter().flat_map(|meta| { |
1420 | attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter() | |
1421 | }).collect()) | |
9cc50fc6 SL |
1422 | }) |
1423 | } | |
e9174d1e | 1424 | } |