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.
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.
11 //! type context book-keeping
13 // FIXME: (@jroesch) @eddyb should remove this when he renames ctxt
14 #![allow(non_camel_case_types)]
16 use front::map as ast_map;
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};
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;
38 use arena::TypedArena;
39 use std::borrow::Borrow;
40 use std::cell::{Cell, RefCell, Ref};
41 use std::hash::{Hash, Hasher};
44 use syntax::ast::{self, Name, NodeId};
46 use syntax::parse::token::special_idents;
51 pub struct CtxtArenas<'tcx> {
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>,
60 trait_defs: TypedArena<ty::TraitDef<'tcx>>,
61 adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
64 impl<'tcx> CtxtArenas<'tcx> {
65 pub fn new() -> CtxtArenas<'tcx> {
67 type_: TypedArena::new(),
68 substs: TypedArena::new(),
69 bare_fn: TypedArena::new(),
70 region: TypedArena::new(),
71 stability: TypedArena::new(),
73 trait_defs: TypedArena::new(),
74 adt_defs: TypedArena::new()
79 pub struct CommonTypes<'tcx> {
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>>,
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
107 pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>,
109 pub adjustments: NodeMap<ty::adjustment::AutoAdjustment<'tcx>>,
111 pub method_map: ty::MethodMap<'tcx>,
114 pub upvar_capture_map: ty::UpvarCaptureMap,
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>>,
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>,
125 impl<'tcx> Tables<'tcx> {
126 pub fn empty() -> Tables<'tcx> {
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(),
139 impl<'tcx> CommonTypes<'tcx> {
140 fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
141 interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>)
144 let mk = |sty| ctxt::intern_ty(arena, interner, sty);
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)),
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
168 pub struct ctxt<'tcx> {
169 /// The arenas that types etc are allocated from.
170 arenas: &'tcx CtxtArenas<'tcx>,
172 /// Specifically use a speedy hash algorithm for this hash map, it's used
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>>>,
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>>,
184 /// Common types, pre-interned for your convenience.
185 pub types: CommonTypes<'tcx>,
190 pub named_region_map: resolve_lifetime::NamedRegionMap,
192 pub region_maps: RegionMaps,
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
202 pub tables: RefCell<Tables<'tcx>>,
204 /// Maps from a trait item to the trait item "descriptor"
205 pub impl_or_trait_items: RefCell<DefIdMap<ty::ImplOrTraitItem<'tcx>>>,
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>>>>,
210 /// A cache for the trait_items() routine
211 pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ty::ImplOrTraitItem<'tcx>>>>>,
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>>>,
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>>>,
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>>>,
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>>,
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>>>,
245 /// True if the variance has been computed yet; false otherwise.
246 pub variance_computed: Cell<bool>,
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>>>>,
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
257 pub impl_items: RefCell<DefIdMap<Vec<ty::ImplOrTraitItemId>>>,
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>,
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
266 pub used_mut_nodes: RefCell<NodeSet>,
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>,
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>>,
280 pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
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>>>,
288 /// Maps any item's def-id to its stability index.
289 pub stability: RefCell<stability::Index<'tcx>>,
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>,
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>>,
301 /// Caches the representation hints for struct definitions.
302 pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
304 /// Maps Expr NodeId's to their constant qualification.
305 pub const_qualif_map: RefCell<NodeMap<middle::check_const::ConstQualif>>,
307 /// Caches CoerceUnsized kinds for impls on custom types.
308 pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
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>>,
314 /// Maps Fn items to a collection of fragment infos.
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.
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.
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
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
339 pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>,
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()
346 pub fn closure_type(&self,
348 substs: &ClosureSubsts<'tcx>)
349 -> ty::ClosureTy<'tcx>
351 self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
354 pub fn type_parameter_def(&self,
356 -> ty::TypeParameterDef<'tcx>
358 self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
361 pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> {
362 fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> {
366 Ref::map(self.tables.borrow(), projection)
369 pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
370 self.tables.borrow_mut().node_types.insert(id, ty);
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);
381 pub fn alloc_trait_def(&self, def: ty::TraitDef<'tcx>)
382 -> &'tcx ty::TraitDef<'tcx> {
383 self.arenas.trait_defs.alloc(def)
386 pub fn intern_adt_def(&self,
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);
398 pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
399 if let Some(st) = self.stability_interner.borrow().get(&stab) {
403 let interned = self.arenas.stability.alloc(stab);
404 self.stability_interner.borrow_mut().insert(interned, interned);
408 pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
409 self.free_region_maps.borrow_mut()
413 pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
414 self.free_region_maps.borrow()[&id].clone()
417 pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> {
418 value.lift_to_tcx(self)
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>,
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
437 let interner = RefCell::new(FnvHashMap());
438 let common_types = CommonTypes::new(&arenas.type_, &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()),
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),
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()),
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()),
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> {
510 fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>;
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 _ {
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 _ {
540 use session::Session;
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;
550 scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
552 fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
554 write!(f, "{}", tcx.sess.codemap().span_to_string(span))
558 pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
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);
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) }))
575 pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
576 if TLS_TCX.is_set() {
584 macro_rules! sty_debug_print {
585 ($ctxt: expr, $($variant: ident),*) => {{
586 // curious inner module to allow variant names to be used as
588 #[allow(non_snake_case)]
591 #[derive(Copy, Clone)]
599 pub fn go(tcx: &ty::ctxt) {
600 let mut total = DebugStat {
602 region_infer: 0, ty_infer: 0, both_infer: 0,
604 $(let mut $variant = total;)*
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,)*
614 let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
615 let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
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 }
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);
633 println!(" total {uses:6} \
634 {ty:4.1}% {region:5.1}% {both:4.1}%",
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)
646 impl<'tcx> ctxt<'tcx> {
647 pub fn print_debug_stats(&self) {
650 TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
651 TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
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());
661 /// An entry in the type interner.
662 pub struct InternedTy<'tcx> {
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
673 impl<'tcx> Eq for InternedTy<'tcx> {}
675 impl<'tcx> Hash for InternedTy<'tcx> {
676 fn hash<H: Hasher>(&self, s: &mut H) {
681 impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
682 fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> {
687 fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
689 bounds[1..].iter().enumerate().all(
690 |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
693 impl<'tcx> ctxt<'tcx> {
695 pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
696 if let Some(substs) = self.substs_interner.borrow().get(&substs) {
700 let substs = self.arenas.substs.alloc(substs);
701 self.substs_interner.borrow_mut().insert(substs, substs);
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,
711 sig: bare_fn.sig.clone()
713 self.mk_fn(None, unsafe_fn_ty_a)
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) {
721 let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
722 self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
726 pub fn mk_region(&self, region: Region) -> &'tcx Region {
727 if let Some(region) = self.region_interner.borrow().get(®ion) {
731 let region = self.arenas.region.alloc(region);
732 self.region_interner.borrow_mut().insert(region, region);
736 fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
737 interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
738 st: TypeVariants<'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,
747 let flags = super::flags::FlagComputation::for_sty(&st);
750 () => type_arena.alloc(TyS { sty: st,
751 flags: Cell::new(flags.flags),
752 region_depth: flags.depth, }),
755 interner.insert(InternedTy { ty: ty }, ty);
759 debug!("Interned type: {:?} Pointer: {:?}",
760 ty, ty as *const TyS);
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)
770 pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
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,
780 pub fn mk_mach_uint(&self, tm: ast::UintTy) -> Ty<'tcx> {
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,
790 pub fn mk_mach_float(&self, tm: ast::FloatTy) -> Ty<'tcx> {
792 ast::TyF32 => self.types.f32,
793 ast::TyF64 => self.types.f64,
797 pub fn mk_str(&self) -> Ty<'tcx> {
801 pub fn mk_static_str(&self) -> Ty<'tcx> {
802 self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
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))
810 pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
811 self.mk_ty(TyBox(ty))
814 pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
815 self.mk_ty(TyRawPtr(tm))
818 pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
819 self.mk_ty(TyRef(r, tm))
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})
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})
830 pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
831 self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable})
834 pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
835 self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
838 pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
839 self.mk_imm_ptr(self.mk_nil())
842 pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> {
843 self.mk_ty(TyArray(ty, n))
846 pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
847 self.mk_ty(TySlice(ty))
850 pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
851 self.mk_ty(TyTuple(ts))
854 pub fn mk_nil(&self) -> Ty<'tcx> {
855 self.mk_tup(Vec::new())
858 pub fn mk_bool(&self) -> Ty<'tcx> {
863 opt_def_id: Option<DefId>,
864 fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
865 self.mk_ty(TyBareFn(opt_def_id, fty))
868 pub fn mk_ctor_fn(&self,
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,
876 sig: ty::Binder(ty::FnSig {
878 output: ty::FnConverging(output),
884 pub fn mk_trait(&self,
885 principal: ty::PolyTraitRef<'tcx>,
886 bounds: ExistentialBounds<'tcx>)
889 assert!(bound_list_is_sorted(&bounds.projection_bounds));
891 let inner = box TraitTy {
892 principal: principal,
895 self.mk_ty(TyTrait(inner))
898 pub fn mk_projection(&self,
899 trait_ref: TraitRef<'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))
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))
912 pub fn mk_closure(&self,
914 substs: &'tcx Substs<'tcx>,
917 self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
923 pub fn mk_closure_from_closure_substs(&self,
925 closure_substs: Box<ClosureSubsts<'tcx>>)
927 self.mk_ty(TyClosure(closure_id, closure_substs))
930 pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
931 self.mk_infer(TyVar(v))
934 pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> {
935 self.mk_infer(IntVar(v))
938 pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> {
939 self.mk_infer(FloatVar(v))
942 pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> {
943 self.mk_ty(TyInfer(it))
946 pub fn mk_param(&self,
947 space: subst::ParamSpace,
949 name: Name) -> Ty<'tcx> {
950 self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
953 pub fn mk_self_type(&self) -> Ty<'tcx> {
954 self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name)
957 pub fn mk_param_from_def(&self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
958 self.mk_param(def.space, def.index, def.name)