]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/context.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc / ty / context.rs
CommitLineData
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 13use dep_graph::{DepGraph, DepTrackingMap};
e9174d1e 14use session::Session;
e9174d1e 15use middle;
5bcae85e 16use hir::TraitMap;
54a0048b 17use hir::def::DefMap;
9e0c209e 18use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
a7813a04
XL
19use hir::map as ast_map;
20use hir::map::{DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
e9174d1e
SL
21use middle::free_region::FreeRegionMap;
22use middle::region::RegionMaps;
23use middle::resolve_lifetime;
24use middle::stability;
9e0c209e 25use ty::subst::Substs;
54a0048b
SL
26use traits;
27use ty::{self, TraitRef, Ty, TypeAndMut};
9e0c209e
SL
28use ty::{TyS, TypeVariants, Slice};
29use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
54a0048b 30use hir::FreevarMap;
9e0c209e 31use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject};
54a0048b
SL
32use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
33use ty::TypeVariants::*;
34use ty::layout::{Layout, TargetDataLayout};
35use ty::maps;
9cc50fc6 36use util::common::MemoizationMap;
e9174d1e 37use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
a7813a04 38use util::nodemap::{FnvHashMap, FnvHashSet};
e9174d1e
SL
39
40use arena::TypedArena;
41use std::borrow::Borrow;
42use std::cell::{Cell, RefCell, Ref};
43use std::hash::{Hash, Hasher};
a7813a04
XL
44use std::mem;
45use std::ops::Deref;
e9174d1e 46use std::rc::Rc;
b039eaaf
SL
47use syntax::ast::{self, Name, NodeId};
48use syntax::attr;
a7813a04 49use syntax::parse::token::{self, keywords};
e9174d1e 50
54a0048b 51use hir;
e9174d1e
SL
52
53/// Internal storage
54pub 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
70impl<'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
88pub 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
103impl<'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
179pub 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
198pub 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 239impl<'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
255impl<'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)]
283pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
284 gcx: &'a GlobalCtxt<'gcx>,
285 interners: &'a CtxtInterners<'tcx>
286}
e9174d1e 287
a7813a04
XL
288impl<'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
295pub 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
500impl<'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
510impl<'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
772impl<'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.
799pub 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
804impl<'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
821impl<'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
838impl<'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
855impl<'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
873impl<'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
892pub 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
972macro_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
1036impl<'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.
1053struct Interned<'tcx, T: 'tcx+?Sized>(&'tcx T);
e9174d1e 1054
a7813a04
XL
1055// NB: An Interned<Ty> compares and hashes as a sty.
1056impl<'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 1062impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {}
e9174d1e 1063
a7813a04 1064impl<'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
1070impl<'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.
1077impl<'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
1083impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice<T>> {}
1084
1085impl<'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
1091impl<'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
1097impl<'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
1103impl<'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
1109impl<'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
1115macro_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
1164macro_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
1184fn 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
1188direct_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
1203intern_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
1209impl<'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}