]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/ty/context.rs
f32e86e276c711380c07803e9b707bc75def7e87
[rust.git] / src / librustc / middle / ty / context.rs
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
13 // FIXME: (@jroesch) @eddyb should remove this when he renames ctxt
14 #![allow(non_camel_case_types)]
15
16 use front::map as ast_map;
17 use session::Session;
18 use lint;
19 use middle;
20 use middle::def::DefMap;
21 use middle::def_id::DefId;
22 use middle::free_region::FreeRegionMap;
23 use middle::region::RegionMaps;
24 use middle::resolve_lifetime;
25 use middle::stability;
26 use middle::subst::{self, Subst, Substs};
27 use middle::traits;
28 use middle::ty::{self, TraitRef, Ty, TypeAndMut};
29 use middle::ty::{TyS, TypeVariants};
30 use middle::ty::{AdtDef, ClosureSubsts, ExistentialBounds, Region};
31 use middle::ty::{FreevarMap, GenericPredicates};
32 use middle::ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy};
33 use middle::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
34 use middle::ty::TypeVariants::*;
35 use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
36 use util::nodemap::FnvHashMap;
37
38 use arena::TypedArena;
39 use std::borrow::Borrow;
40 use std::cell::{Cell, RefCell, Ref};
41 use std::hash::{Hash, Hasher};
42 use std::rc::Rc;
43 use syntax::abi;
44 use syntax::ast::{self, Name, NodeId};
45 use syntax::attr;
46 use syntax::parse::token::special_idents;
47
48 use rustc_front::hir;
49
50 /// Internal storage
51 pub struct CtxtArenas<'tcx> {
52     // internings
53     type_: TypedArena<TyS<'tcx>>,
54     substs: TypedArena<Substs<'tcx>>,
55     bare_fn: TypedArena<BareFnTy<'tcx>>,
56     region: TypedArena<Region>,
57     stability: TypedArena<attr::Stability>,
58
59     // references
60     trait_defs: TypedArena<ty::TraitDef<'tcx>>,
61     adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
62 }
63
64 impl<'tcx> CtxtArenas<'tcx> {
65     pub fn new() -> CtxtArenas<'tcx> {
66         CtxtArenas {
67             type_: TypedArena::new(),
68             substs: TypedArena::new(),
69             bare_fn: TypedArena::new(),
70             region: TypedArena::new(),
71             stability: TypedArena::new(),
72
73             trait_defs: TypedArena::new(),
74             adt_defs: TypedArena::new()
75         }
76     }
77 }
78
79 pub struct CommonTypes<'tcx> {
80     pub bool: Ty<'tcx>,
81     pub char: Ty<'tcx>,
82     pub isize: Ty<'tcx>,
83     pub i8: Ty<'tcx>,
84     pub i16: Ty<'tcx>,
85     pub i32: Ty<'tcx>,
86     pub i64: Ty<'tcx>,
87     pub usize: Ty<'tcx>,
88     pub u8: Ty<'tcx>,
89     pub u16: Ty<'tcx>,
90     pub u32: Ty<'tcx>,
91     pub u64: Ty<'tcx>,
92     pub f32: Ty<'tcx>,
93     pub f64: Ty<'tcx>,
94     pub err: Ty<'tcx>,
95 }
96
97 pub struct Tables<'tcx> {
98     /// Stores the types for various nodes in the AST.  Note that this table
99     /// is not guaranteed to be populated until after typeck.  See
100     /// typeck::check::fn_ctxt for details.
101     pub node_types: NodeMap<Ty<'tcx>>,
102
103     /// Stores the type parameters which were substituted to obtain the type
104     /// of this node.  This only applies to nodes that refer to entities
105     /// parameterized by type parameters, such as generic fns, types, or
106     /// other items.
107     pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>,
108
109     pub adjustments: NodeMap<ty::adjustment::AutoAdjustment<'tcx>>,
110
111     pub method_map: ty::MethodMap<'tcx>,
112
113     /// Borrows
114     pub upvar_capture_map: ty::UpvarCaptureMap,
115
116     /// Records the type of each closure. The def ID is the ID of the
117     /// expression defining the closure.
118     pub closure_tys: DefIdMap<ty::ClosureTy<'tcx>>,
119
120     /// Records the type of each closure. The def ID is the ID of the
121     /// expression defining the closure.
122     pub closure_kinds: DefIdMap<ty::ClosureKind>,
123 }
124
125 impl<'tcx> Tables<'tcx> {
126     pub fn empty() -> Tables<'tcx> {
127         Tables {
128             node_types: FnvHashMap(),
129             item_substs: NodeMap(),
130             adjustments: NodeMap(),
131             method_map: FnvHashMap(),
132             upvar_capture_map: FnvHashMap(),
133             closure_tys: DefIdMap(),
134             closure_kinds: DefIdMap(),
135         }
136     }
137 }
138
139 impl<'tcx> CommonTypes<'tcx> {
140     fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
141            interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
142            -> CommonTypes<'tcx>
143     {
144         let mk = |sty| ctxt::intern_ty(arena, interner, sty);
145         CommonTypes {
146             bool: mk(TyBool),
147             char: mk(TyChar),
148             err: mk(TyError),
149             isize: mk(TyInt(ast::TyIs)),
150             i8: mk(TyInt(ast::TyI8)),
151             i16: mk(TyInt(ast::TyI16)),
152             i32: mk(TyInt(ast::TyI32)),
153             i64: mk(TyInt(ast::TyI64)),
154             usize: mk(TyUint(ast::TyUs)),
155             u8: mk(TyUint(ast::TyU8)),
156             u16: mk(TyUint(ast::TyU16)),
157             u32: mk(TyUint(ast::TyU32)),
158             u64: mk(TyUint(ast::TyU64)),
159             f32: mk(TyFloat(ast::TyF32)),
160             f64: mk(TyFloat(ast::TyF64)),
161         }
162     }
163 }
164
165 /// The data structure to keep track of all the information that typechecker
166 /// generates so that so that it can be reused and doesn't have to be redone
167 /// later on.
168 pub struct ctxt<'tcx> {
169     /// The arenas that types etc are allocated from.
170     arenas: &'tcx CtxtArenas<'tcx>,
171
172     /// Specifically use a speedy hash algorithm for this hash map, it's used
173     /// quite often.
174     // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
175     // queried from a HashSet.
176     interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
177
178     // FIXME as above, use a hashset if equivalent elements can be queried.
179     substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
180     bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
181     region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
182     stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
183
184     /// Common types, pre-interned for your convenience.
185     pub types: CommonTypes<'tcx>,
186
187     pub sess: Session,
188     pub def_map: DefMap,
189
190     pub named_region_map: resolve_lifetime::NamedRegionMap,
191
192     pub region_maps: RegionMaps,
193
194     // For each fn declared in the local crate, type check stores the
195     // free-region relationships that were deduced from its where
196     // clauses and parameter types. These are then read-again by
197     // borrowck. (They are not used during trans, and hence are not
198     // serialized or needed for cross-crate fns.)
199     free_region_maps: RefCell<NodeMap<FreeRegionMap>>,
200     // FIXME: jroesch make this a refcell
201
202     pub tables: RefCell<Tables<'tcx>>,
203
204     /// Maps from a trait item to the trait item "descriptor"
205     pub impl_or_trait_items: RefCell<DefIdMap<ty::ImplOrTraitItem<'tcx>>>,
206
207     /// Maps from a trait def-id to a list of the def-ids of its trait items
208     pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ty::ImplOrTraitItemId>>>>,
209
210     /// A cache for the trait_items() routine
211     pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ty::ImplOrTraitItem<'tcx>>>>>,
212
213     pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
214     pub trait_defs: RefCell<DefIdMap<&'tcx ty::TraitDef<'tcx>>>,
215     pub adt_defs: RefCell<DefIdMap<ty::AdtDefMaster<'tcx>>>,
216
217     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
218     /// associated predicates.
219     pub predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
220
221     /// Maps from the def-id of a trait to the list of
222     /// super-predicates. This is a subset of the full list of
223     /// predicates. We store these in a separate map because we must
224     /// evaluate them even during type conversion, often before the
225     /// full predicates are available (note that supertraits have
226     /// additional acyclicity requirements).
227     pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
228
229     pub map: ast_map::Map<'tcx>,
230     pub freevars: RefCell<FreevarMap>,
231     pub tcache: RefCell<DefIdMap<ty::TypeScheme<'tcx>>>,
232     pub rcache: RefCell<FnvHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
233     pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
234     pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
235     pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
236     pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
237     pub lang_items: middle::lang_items::LanguageItems,
238     /// A mapping of fake provided method def_ids to the default implementation
239     pub provided_method_sources: RefCell<DefIdMap<DefId>>,
240
241     /// Maps from def-id of a type or region parameter to its
242     /// (inferred) variance.
243     pub item_variance_map: RefCell<DefIdMap<Rc<ty::ItemVariances>>>,
244
245     /// True if the variance has been computed yet; false otherwise.
246     pub variance_computed: Cell<bool>,
247
248     /// Maps a DefId of a type to a list of its inherent impls.
249     /// Contains implementations of methods that are inherent to a type.
250     /// Methods in these implementations don't need to be exported.
251     pub inherent_impls: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
252
253     /// Maps a DefId of an impl to a list of its items.
254     /// Note that this contains all of the impls that we know about,
255     /// including ones in other crates. It's not clear that this is the best
256     /// way to do it.
257     pub impl_items: RefCell<DefIdMap<Vec<ty::ImplOrTraitItemId>>>,
258
259     /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
260     /// present in this set can be warned about.
261     pub used_unsafe: RefCell<NodeSet>,
262
263     /// Set of nodes which mark locals as mutable which end up getting used at
264     /// some point. Local variable definitions not in this set can be warned
265     /// about.
266     pub used_mut_nodes: RefCell<NodeSet>,
267
268     /// The set of external nominal types whose implementations have been read.
269     /// This is used for lazy resolution of methods.
270     pub populated_external_types: RefCell<DefIdSet>,
271     /// The set of external primitive types whose implementations have been read.
272     /// FIXME(arielb1): why is this separate from populated_external_types?
273     pub populated_external_primitive_impls: RefCell<DefIdSet>,
274
275     /// These caches are used by const_eval when decoding external constants.
276     pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
277     pub extern_const_variants: RefCell<DefIdMap<NodeId>>,
278     pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
279
280     pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
281                                               lint::LevelSource>>,
282
283     /// The types that must be asserted to be the same size for `transmute`
284     /// to be valid. We gather up these restrictions in the intrinsicck pass
285     /// and check them in trans.
286     pub transmute_restrictions: RefCell<Vec<ty::TransmuteRestriction<'tcx>>>,
287
288     /// Maps any item's def-id to its stability index.
289     pub stability: RefCell<stability::Index<'tcx>>,
290
291     /// Caches the results of trait selection. This cache is used
292     /// for things that do not have to do with the parameters in scope.
293     pub selection_cache: traits::SelectionCache<'tcx>,
294
295     /// A set of predicates that have been fulfilled *somewhere*.
296     /// This is used to avoid duplicate work. Predicates are only
297     /// added to this set when they mention only "global" names
298     /// (i.e., no type or lifetime parameters).
299     pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>,
300
301     /// Caches the representation hints for struct definitions.
302     pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
303
304     /// Maps Expr NodeId's to their constant qualification.
305     pub const_qualif_map: RefCell<NodeMap<middle::check_const::ConstQualif>>,
306
307     /// Caches CoerceUnsized kinds for impls on custom types.
308     pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
309
310     /// Maps a cast expression to its kind. This is keyed on the
311     /// *from* expression of the cast, not the cast itself.
312     pub cast_kinds: RefCell<NodeMap<ty::cast::CastKind>>,
313
314     /// Maps Fn items to a collection of fragment infos.
315     ///
316     /// The main goal is to identify data (each of which may be moved
317     /// or assigned) whose subparts are not moved nor assigned
318     /// (i.e. their state is *unfragmented*) and corresponding ast
319     /// nodes where the path to that data is moved or assigned.
320     ///
321     /// In the long term, unfragmented values will have their
322     /// destructor entirely driven by a single stack-local drop-flag,
323     /// and their parents, the collections of the unfragmented values
324     /// (or more simply, "fragmented values"), are mapped to the
325     /// corresponding collections of stack-local drop-flags.
326     ///
327     /// (However, in the short term that is not the case; e.g. some
328     /// unfragmented paths still need to be zeroed, namely when they
329     /// reference parent data from an outer scope that was not
330     /// entirely moved, and therefore that needs to be zeroed so that
331     /// we do not get double-drop when we hit the end of the parent
332     /// scope.)
333     ///
334     /// Also: currently the table solely holds keys for node-ids of
335     /// unfragmented values (see `FragmentInfo` enum definition), but
336     /// longer-term we will need to also store mappings from
337     /// fragmented data to the set of unfragmented pieces that
338     /// constitute it.
339     pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>,
340 }
341 impl<'tcx> ctxt<'tcx> {
342     pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind {
343         *self.tables.borrow().closure_kinds.get(&def_id).unwrap()
344     }
345
346     pub fn closure_type(&self,
347                         def_id: DefId,
348                         substs: &ClosureSubsts<'tcx>)
349                         -> ty::ClosureTy<'tcx>
350     {
351         self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
352     }
353
354     pub fn type_parameter_def(&self,
355                               node_id: NodeId)
356                               -> ty::TypeParameterDef<'tcx>
357     {
358         self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
359     }
360
361     pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> {
362         fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> {
363             &tables.node_types
364         }
365
366         Ref::map(self.tables.borrow(), projection)
367     }
368
369     pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
370         self.tables.borrow_mut().node_types.insert(id, ty);
371     }
372
373     pub fn intern_trait_def(&self, def: ty::TraitDef<'tcx>)
374                             -> &'tcx ty::TraitDef<'tcx> {
375         let did = def.trait_ref.def_id;
376         let interned = self.arenas.trait_defs.alloc(def);
377         self.trait_defs.borrow_mut().insert(did, interned);
378         interned
379     }
380
381     pub fn alloc_trait_def(&self, def: ty::TraitDef<'tcx>)
382                            -> &'tcx ty::TraitDef<'tcx> {
383         self.arenas.trait_defs.alloc(def)
384     }
385
386     pub fn intern_adt_def(&self,
387                           did: DefId,
388                           kind: ty::AdtKind,
389                           variants: Vec<ty::VariantDefData<'tcx, 'tcx>>)
390                           -> ty::AdtDefMaster<'tcx> {
391         let def = ty::AdtDefData::new(self, did, kind, variants);
392         let interned = self.arenas.adt_defs.alloc(def);
393         // this will need a transmute when reverse-variance is removed
394         self.adt_defs.borrow_mut().insert(did, interned);
395         interned
396     }
397
398     pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
399         if let Some(st) = self.stability_interner.borrow().get(&stab) {
400             return st;
401         }
402
403         let interned = self.arenas.stability.alloc(stab);
404         self.stability_interner.borrow_mut().insert(interned, interned);
405         interned
406     }
407
408     pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
409         self.free_region_maps.borrow_mut()
410                              .insert(id, map);
411     }
412
413     pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
414         self.free_region_maps.borrow()[&id].clone()
415     }
416
417     pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> {
418         value.lift_to_tcx(self)
419     }
420
421     /// Create a type context and call the closure with a `&ty::ctxt` reference
422     /// to the context. The closure enforces that the type context and any interned
423     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
424     /// reference to the context, to allow formatting values that need it.
425     pub fn create_and_enter<F, R>(s: Session,
426                                  arenas: &'tcx CtxtArenas<'tcx>,
427                                  def_map: DefMap,
428                                  named_region_map: resolve_lifetime::NamedRegionMap,
429                                  map: ast_map::Map<'tcx>,
430                                  freevars: RefCell<FreevarMap>,
431                                  region_maps: RegionMaps,
432                                  lang_items: middle::lang_items::LanguageItems,
433                                  stability: stability::Index<'tcx>,
434                                  f: F) -> (Session, R)
435                                  where F: FnOnce(&ctxt<'tcx>) -> R
436     {
437         let interner = RefCell::new(FnvHashMap());
438         let common_types = CommonTypes::new(&arenas.type_, &interner);
439
440         tls::enter(ctxt {
441             arenas: arenas,
442             interner: interner,
443             substs_interner: RefCell::new(FnvHashMap()),
444             bare_fn_interner: RefCell::new(FnvHashMap()),
445             region_interner: RefCell::new(FnvHashMap()),
446             stability_interner: RefCell::new(FnvHashMap()),
447             types: common_types,
448             named_region_map: named_region_map,
449             region_maps: region_maps,
450             free_region_maps: RefCell::new(FnvHashMap()),
451             item_variance_map: RefCell::new(DefIdMap()),
452             variance_computed: Cell::new(false),
453             sess: s,
454             def_map: def_map,
455             tables: RefCell::new(Tables::empty()),
456             impl_trait_refs: RefCell::new(DefIdMap()),
457             trait_defs: RefCell::new(DefIdMap()),
458             adt_defs: RefCell::new(DefIdMap()),
459             predicates: RefCell::new(DefIdMap()),
460             super_predicates: RefCell::new(DefIdMap()),
461             fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
462             map: map,
463             freevars: freevars,
464             tcache: RefCell::new(DefIdMap()),
465             rcache: RefCell::new(FnvHashMap()),
466             tc_cache: RefCell::new(FnvHashMap()),
467             ast_ty_to_ty_cache: RefCell::new(NodeMap()),
468             impl_or_trait_items: RefCell::new(DefIdMap()),
469             trait_item_def_ids: RefCell::new(DefIdMap()),
470             trait_items_cache: RefCell::new(DefIdMap()),
471             ty_param_defs: RefCell::new(NodeMap()),
472             normalized_cache: RefCell::new(FnvHashMap()),
473             lang_items: lang_items,
474             provided_method_sources: RefCell::new(DefIdMap()),
475             inherent_impls: RefCell::new(DefIdMap()),
476             impl_items: RefCell::new(DefIdMap()),
477             used_unsafe: RefCell::new(NodeSet()),
478             used_mut_nodes: RefCell::new(NodeSet()),
479             populated_external_types: RefCell::new(DefIdSet()),
480             populated_external_primitive_impls: RefCell::new(DefIdSet()),
481             extern_const_statics: RefCell::new(DefIdMap()),
482             extern_const_variants: RefCell::new(DefIdMap()),
483             extern_const_fns: RefCell::new(DefIdMap()),
484             node_lint_levels: RefCell::new(FnvHashMap()),
485             transmute_restrictions: RefCell::new(Vec::new()),
486             stability: RefCell::new(stability),
487             selection_cache: traits::SelectionCache::new(),
488             repr_hint_cache: RefCell::new(DefIdMap()),
489             const_qualif_map: RefCell::new(NodeMap()),
490             custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
491             cast_kinds: RefCell::new(NodeMap()),
492             fragment_infos: RefCell::new(DefIdMap()),
493        }, f)
494     }
495 }
496
497 /// A trait implemented for all X<'a> types which can be safely and
498 /// efficiently converted to X<'tcx> as long as they are part of the
499 /// provided ty::ctxt<'tcx>.
500 /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
501 /// by looking them up in their respective interners.
502 /// None is returned if the value or one of the components is not part
503 /// of the provided context.
504 /// For Ty, None can be returned if either the type interner doesn't
505 /// contain the TypeVariants key or if the address of the interned
506 /// pointer differs. The latter case is possible if a primitive type,
507 /// e.g. `()` or `u8`, was interned in a different context.
508 pub trait Lift<'tcx> {
509     type Lifted;
510     fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>;
511 }
512
513 impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
514     type Lifted = Ty<'tcx>;
515     fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> {
516         if let Some(&ty) = tcx.interner.borrow().get(&self.sty) {
517             if *self as *const _ == ty as *const _ {
518                 return Some(ty);
519             }
520         }
521         None
522     }
523 }
524
525 impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
526     type Lifted = &'tcx Substs<'tcx>;
527     fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> {
528         if let Some(&substs) = tcx.substs_interner.borrow().get(*self) {
529             if *self as *const _ == substs as *const _ {
530                 return Some(substs);
531             }
532         }
533         None
534     }
535 }
536
537
538 pub mod tls {
539     use middle::ty;
540     use session::Session;
541
542     use std::fmt;
543     use syntax::codemap;
544
545     /// Marker type used for the scoped TLS slot.
546     /// The type context cannot be used directly because the scoped TLS
547     /// in libstd doesn't allow types generic over lifetimes.
548     struct ThreadLocalTyCx;
549
550     scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
551
552     fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
553         with(|tcx| {
554             write!(f, "{}", tcx.sess.codemap().span_to_string(span))
555         })
556     }
557
558     pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
559                                                            -> (Session, R) {
560         let result = codemap::SPAN_DEBUG.with(|span_dbg| {
561             let original_span_debug = span_dbg.get();
562             span_dbg.set(span_debug);
563             let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
564             let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
565             span_dbg.set(original_span_debug);
566             result
567         });
568         (tcx.sess, result)
569     }
570
571     pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
572         TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) }))
573     }
574
575     pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
576         if TLS_TCX.is_set() {
577             with(|v| f(Some(v)))
578         } else {
579             f(None)
580         }
581     }
582 }
583
584 macro_rules! sty_debug_print {
585     ($ctxt: expr, $($variant: ident),*) => {{
586         // curious inner module to allow variant names to be used as
587         // variable names.
588         #[allow(non_snake_case)]
589         mod inner {
590             use middle::ty;
591             #[derive(Copy, Clone)]
592             struct DebugStat {
593                 total: usize,
594                 region_infer: usize,
595                 ty_infer: usize,
596                 both_infer: usize,
597             }
598
599             pub fn go(tcx: &ty::ctxt) {
600                 let mut total = DebugStat {
601                     total: 0,
602                     region_infer: 0, ty_infer: 0, both_infer: 0,
603                 };
604                 $(let mut $variant = total;)*
605
606
607                 for (_, t) in tcx.interner.borrow().iter() {
608                     let variant = match t.sty {
609                         ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
610                             ty::TyFloat(..) | ty::TyStr => continue,
611                         ty::TyError => /* unimportant */ continue,
612                         $(ty::$variant(..) => &mut $variant,)*
613                     };
614                     let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
615                     let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
616
617                     variant.total += 1;
618                     total.total += 1;
619                     if region { total.region_infer += 1; variant.region_infer += 1 }
620                     if ty { total.ty_infer += 1; variant.ty_infer += 1 }
621                     if region && ty { total.both_infer += 1; variant.both_infer += 1 }
622                 }
623                 println!("Ty interner             total           ty region  both");
624                 $(println!("    {:18}: {uses:6} {usespc:4.1}%, \
625 {ty:4.1}% {region:5.1}% {both:4.1}%",
626                            stringify!($variant),
627                            uses = $variant.total,
628                            usespc = $variant.total as f64 * 100.0 / total.total as f64,
629                            ty = $variant.ty_infer as f64 * 100.0  / total.total as f64,
630                            region = $variant.region_infer as f64 * 100.0  / total.total as f64,
631                            both = $variant.both_infer as f64 * 100.0  / total.total as f64);
632                   )*
633                 println!("                  total {uses:6}        \
634 {ty:4.1}% {region:5.1}% {both:4.1}%",
635                          uses = total.total,
636                          ty = total.ty_infer as f64 * 100.0  / total.total as f64,
637                          region = total.region_infer as f64 * 100.0  / total.total as f64,
638                          both = total.both_infer as f64 * 100.0  / total.total as f64)
639             }
640         }
641
642         inner::go($ctxt)
643     }}
644 }
645
646 impl<'tcx> ctxt<'tcx> {
647     pub fn print_debug_stats(&self) {
648         sty_debug_print!(
649             self,
650             TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
651             TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
652
653         println!("Substs interner: #{}", self.substs_interner.borrow().len());
654         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
655         println!("Region interner: #{}", self.region_interner.borrow().len());
656         println!("Stability interner: #{}", self.stability_interner.borrow().len());
657     }
658 }
659
660
661 /// An entry in the type interner.
662 pub struct InternedTy<'tcx> {
663     ty: Ty<'tcx>
664 }
665
666 // NB: An InternedTy compares and hashes as a sty.
667 impl<'tcx> PartialEq for InternedTy<'tcx> {
668     fn eq(&self, other: &InternedTy<'tcx>) -> bool {
669         self.ty.sty == other.ty.sty
670     }
671 }
672
673 impl<'tcx> Eq for InternedTy<'tcx> {}
674
675 impl<'tcx> Hash for InternedTy<'tcx> {
676     fn hash<H: Hasher>(&self, s: &mut H) {
677         self.ty.sty.hash(s)
678     }
679 }
680
681 impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
682     fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> {
683         &self.ty.sty
684     }
685 }
686
687 fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
688     bounds.is_empty() ||
689         bounds[1..].iter().enumerate().all(
690             |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
691 }
692
693 impl<'tcx> ctxt<'tcx> {
694     // Type constructors
695     pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
696         if let Some(substs) = self.substs_interner.borrow().get(&substs) {
697             return *substs;
698         }
699
700         let substs = self.arenas.substs.alloc(substs);
701         self.substs_interner.borrow_mut().insert(substs, substs);
702         substs
703     }
704
705     /// Create an unsafe fn ty based on a safe fn ty.
706     pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
707         assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
708         let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
709             unsafety: hir::Unsafety::Unsafe,
710             abi: bare_fn.abi,
711             sig: bare_fn.sig.clone()
712         });
713         self.mk_fn(None, unsafe_fn_ty_a)
714     }
715
716     pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
717         if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) {
718             return *bare_fn;
719         }
720
721         let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
722         self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
723         bare_fn
724     }
725
726     pub fn mk_region(&self, region: Region) -> &'tcx Region {
727         if let Some(region) = self.region_interner.borrow().get(&region) {
728             return *region;
729         }
730
731         let region = self.arenas.region.alloc(region);
732         self.region_interner.borrow_mut().insert(region, region);
733         region
734     }
735
736     fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
737                  interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
738                  st: TypeVariants<'tcx>)
739                  -> Ty<'tcx> {
740         let ty: Ty /* don't be &mut TyS */ = {
741             let mut interner = interner.borrow_mut();
742             match interner.get(&st) {
743                 Some(ty) => return *ty,
744                 _ => ()
745             }
746
747             let flags = super::flags::FlagComputation::for_sty(&st);
748
749             let ty = match () {
750                 () => type_arena.alloc(TyS { sty: st,
751                                              flags: Cell::new(flags.flags),
752                                              region_depth: flags.depth, }),
753             };
754
755             interner.insert(InternedTy { ty: ty }, ty);
756             ty
757         };
758
759         debug!("Interned type: {:?} Pointer: {:?}",
760             ty, ty as *const TyS);
761         ty
762     }
763
764     // Interns a type/name combination, stores the resulting box in cx.interner,
765     // and returns the box as cast to an unsafe ptr (see comments for Ty above).
766     pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
767         ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
768     }
769
770     pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
771         match tm {
772             ast::TyIs   => self.types.isize,
773             ast::TyI8   => self.types.i8,
774             ast::TyI16  => self.types.i16,
775             ast::TyI32  => self.types.i32,
776             ast::TyI64  => self.types.i64,
777         }
778     }
779
780     pub fn mk_mach_uint(&self, tm: ast::UintTy) -> Ty<'tcx> {
781         match tm {
782             ast::TyUs   => self.types.usize,
783             ast::TyU8   => self.types.u8,
784             ast::TyU16  => self.types.u16,
785             ast::TyU32  => self.types.u32,
786             ast::TyU64  => self.types.u64,
787         }
788     }
789
790     pub fn mk_mach_float(&self, tm: ast::FloatTy) -> Ty<'tcx> {
791         match tm {
792             ast::TyF32  => self.types.f32,
793             ast::TyF64  => self.types.f64,
794         }
795     }
796
797     pub fn mk_str(&self) -> Ty<'tcx> {
798         self.mk_ty(TyStr)
799     }
800
801     pub fn mk_static_str(&self) -> Ty<'tcx> {
802         self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
803     }
804
805     pub fn mk_enum(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
806         // take a copy of substs so that we own the vectors inside
807         self.mk_ty(TyEnum(def, substs))
808     }
809
810     pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
811         self.mk_ty(TyBox(ty))
812     }
813
814     pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
815         self.mk_ty(TyRawPtr(tm))
816     }
817
818     pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
819         self.mk_ty(TyRef(r, tm))
820     }
821
822     pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
823         self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable})
824     }
825
826     pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
827         self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
828     }
829
830     pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
831         self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable})
832     }
833
834     pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
835         self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
836     }
837
838     pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
839         self.mk_imm_ptr(self.mk_nil())
840     }
841
842     pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> {
843         self.mk_ty(TyArray(ty, n))
844     }
845
846     pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
847         self.mk_ty(TySlice(ty))
848     }
849
850     pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
851         self.mk_ty(TyTuple(ts))
852     }
853
854     pub fn mk_nil(&self) -> Ty<'tcx> {
855         self.mk_tup(Vec::new())
856     }
857
858     pub fn mk_bool(&self) -> Ty<'tcx> {
859         self.mk_ty(TyBool)
860     }
861
862     pub fn mk_fn(&self,
863                  opt_def_id: Option<DefId>,
864                  fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
865         self.mk_ty(TyBareFn(opt_def_id, fty))
866     }
867
868     pub fn mk_ctor_fn(&self,
869                       def_id: DefId,
870                       input_tys: &[Ty<'tcx>],
871                       output: Ty<'tcx>) -> Ty<'tcx> {
872         let input_args = input_tys.iter().cloned().collect();
873         self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
874             unsafety: hir::Unsafety::Normal,
875             abi: abi::Rust,
876             sig: ty::Binder(ty::FnSig {
877                 inputs: input_args,
878                 output: ty::FnConverging(output),
879                 variadic: false
880             })
881         }))
882     }
883
884     pub fn mk_trait(&self,
885                     principal: ty::PolyTraitRef<'tcx>,
886                     bounds: ExistentialBounds<'tcx>)
887                     -> Ty<'tcx>
888     {
889         assert!(bound_list_is_sorted(&bounds.projection_bounds));
890
891         let inner = box TraitTy {
892             principal: principal,
893             bounds: bounds
894         };
895         self.mk_ty(TyTrait(inner))
896     }
897
898     pub fn mk_projection(&self,
899                          trait_ref: TraitRef<'tcx>,
900                          item_name: Name)
901                          -> Ty<'tcx> {
902         // take a copy of substs so that we own the vectors inside
903         let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
904         self.mk_ty(TyProjection(inner))
905     }
906
907     pub fn mk_struct(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
908         // take a copy of substs so that we own the vectors inside
909         self.mk_ty(TyStruct(def, substs))
910     }
911
912     pub fn mk_closure(&self,
913                       closure_id: DefId,
914                       substs: &'tcx Substs<'tcx>,
915                       tys: Vec<Ty<'tcx>>)
916                       -> Ty<'tcx> {
917         self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
918             func_substs: substs,
919             upvar_tys: tys
920         }))
921     }
922
923     pub fn mk_closure_from_closure_substs(&self,
924                                           closure_id: DefId,
925                                           closure_substs: Box<ClosureSubsts<'tcx>>)
926                                           -> Ty<'tcx> {
927         self.mk_ty(TyClosure(closure_id, closure_substs))
928     }
929
930     pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
931         self.mk_infer(TyVar(v))
932     }
933
934     pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> {
935         self.mk_infer(IntVar(v))
936     }
937
938     pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> {
939         self.mk_infer(FloatVar(v))
940     }
941
942     pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> {
943         self.mk_ty(TyInfer(it))
944     }
945
946     pub fn mk_param(&self,
947                     space: subst::ParamSpace,
948                     index: u32,
949                     name: Name) -> Ty<'tcx> {
950         self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
951     }
952
953     pub fn mk_self_type(&self) -> Ty<'tcx> {
954         self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name)
955     }
956
957     pub fn mk_param_from_def(&self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
958         self.mk_param(def.space, def.index, def.name)
959     }
960 }