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::{Name, NodeId};
45 use syntax::parse::token::special_idents;
48 use rustc_front::attr;
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(hir::TyIs)),
150 i8: mk(TyInt(hir::TyI8)),
151 i16: mk(TyInt(hir::TyI16)),
152 i32: mk(TyInt(hir::TyI32)),
153 i64: mk(TyInt(hir::TyI64)),
154 usize: mk(TyUint(hir::TyUs)),
155 u8: mk(TyUint(hir::TyU8)),
156 u16: mk(TyUint(hir::TyU16)),
157 u32: mk(TyUint(hir::TyU32)),
158 u64: mk(TyUint(hir::TyU64)),
159 f32: mk(TyFloat(hir::TyF32)),
160 f64: mk(TyFloat(hir::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 /// A method will be in this list if and only if it is a destructor.
249 pub destructors: RefCell<DefIdSet>,
251 /// Maps a DefId of a type to a list of its inherent impls.
252 /// Contains implementations of methods that are inherent to a type.
253 /// Methods in these implementations don't need to be exported.
254 pub inherent_impls: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
256 /// Maps a DefId of an impl to a list of its items.
257 /// Note that this contains all of the impls that we know about,
258 /// including ones in other crates. It's not clear that this is the best
260 pub impl_items: RefCell<DefIdMap<Vec<ty::ImplOrTraitItemId>>>,
262 /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
263 /// present in this set can be warned about.
264 pub used_unsafe: RefCell<NodeSet>,
266 /// Set of nodes which mark locals as mutable which end up getting used at
267 /// some point. Local variable definitions not in this set can be warned
269 pub used_mut_nodes: RefCell<NodeSet>,
271 /// The set of external nominal types whose implementations have been read.
272 /// This is used for lazy resolution of methods.
273 pub populated_external_types: RefCell<DefIdSet>,
274 /// The set of external primitive types whose implementations have been read.
275 /// FIXME(arielb1): why is this separate from populated_external_types?
276 pub populated_external_primitive_impls: RefCell<DefIdSet>,
278 /// These caches are used by const_eval when decoding external constants.
279 pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
280 pub extern_const_variants: RefCell<DefIdMap<NodeId>>,
281 pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
283 pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
286 /// The types that must be asserted to be the same size for `transmute`
287 /// to be valid. We gather up these restrictions in the intrinsicck pass
288 /// and check them in trans.
289 pub transmute_restrictions: RefCell<Vec<ty::TransmuteRestriction<'tcx>>>,
291 /// Maps any item's def-id to its stability index.
292 pub stability: RefCell<stability::Index<'tcx>>,
294 /// Caches the results of trait selection. This cache is used
295 /// for things that do not have to do with the parameters in scope.
296 pub selection_cache: traits::SelectionCache<'tcx>,
298 /// A set of predicates that have been fulfilled *somewhere*.
299 /// This is used to avoid duplicate work. Predicates are only
300 /// added to this set when they mention only "global" names
301 /// (i.e., no type or lifetime parameters).
302 pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>,
304 /// Caches the representation hints for struct definitions.
305 pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
307 /// Maps Expr NodeId's to their constant qualification.
308 pub const_qualif_map: RefCell<NodeMap<middle::check_const::ConstQualif>>,
310 /// Caches CoerceUnsized kinds for impls on custom types.
311 pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
313 /// Maps a cast expression to its kind. This is keyed on the
314 /// *from* expression of the cast, not the cast itself.
315 pub cast_kinds: RefCell<NodeMap<ty::cast::CastKind>>,
317 /// Maps Fn items to a collection of fragment infos.
319 /// The main goal is to identify data (each of which may be moved
320 /// or assigned) whose subparts are not moved nor assigned
321 /// (i.e. their state is *unfragmented*) and corresponding ast
322 /// nodes where the path to that data is moved or assigned.
324 /// In the long term, unfragmented values will have their
325 /// destructor entirely driven by a single stack-local drop-flag,
326 /// and their parents, the collections of the unfragmented values
327 /// (or more simply, "fragmented values"), are mapped to the
328 /// corresponding collections of stack-local drop-flags.
330 /// (However, in the short term that is not the case; e.g. some
331 /// unfragmented paths still need to be zeroed, namely when they
332 /// reference parent data from an outer scope that was not
333 /// entirely moved, and therefore that needs to be zeroed so that
334 /// we do not get double-drop when we hit the end of the parent
337 /// Also: currently the table solely holds keys for node-ids of
338 /// unfragmented values (see `FragmentInfo` enum definition), but
339 /// longer-term we will need to also store mappings from
340 /// fragmented data to the set of unfragmented pieces that
342 pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>,
344 impl<'tcx> ctxt<'tcx> {
345 pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind {
346 *self.tables.borrow().closure_kinds.get(&def_id).unwrap()
349 pub fn closure_type(&self,
351 substs: &ClosureSubsts<'tcx>)
352 -> ty::ClosureTy<'tcx>
354 self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
357 pub fn type_parameter_def(&self,
359 -> ty::TypeParameterDef<'tcx>
361 self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
364 pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> {
365 fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> {
369 Ref::map(self.tables.borrow(), projection)
372 pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
373 self.tables.borrow_mut().node_types.insert(id, ty);
376 pub fn intern_trait_def(&self, def: ty::TraitDef<'tcx>)
377 -> &'tcx ty::TraitDef<'tcx> {
378 let did = def.trait_ref.def_id;
379 let interned = self.arenas.trait_defs.alloc(def);
380 self.trait_defs.borrow_mut().insert(did, interned);
384 pub fn alloc_trait_def(&self, def: ty::TraitDef<'tcx>)
385 -> &'tcx ty::TraitDef<'tcx> {
386 self.arenas.trait_defs.alloc(def)
389 pub fn intern_adt_def(&self,
392 variants: Vec<ty::VariantDefData<'tcx, 'tcx>>)
393 -> ty::AdtDefMaster<'tcx> {
394 let def = ty::AdtDefData::new(self, did, kind, variants);
395 let interned = self.arenas.adt_defs.alloc(def);
396 // this will need a transmute when reverse-variance is removed
397 self.adt_defs.borrow_mut().insert(did, interned);
401 pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
402 if let Some(st) = self.stability_interner.borrow().get(&stab) {
406 let interned = self.arenas.stability.alloc(stab);
407 self.stability_interner.borrow_mut().insert(interned, interned);
411 pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
412 self.free_region_maps.borrow_mut()
416 pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
417 self.free_region_maps.borrow()[&id].clone()
420 pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> {
421 value.lift_to_tcx(self)
424 /// Create a type context and call the closure with a `&ty::ctxt` reference
425 /// to the context. The closure enforces that the type context and any interned
426 /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
427 /// reference to the context, to allow formatting values that need it.
428 pub fn create_and_enter<F, R>(s: Session,
429 arenas: &'tcx CtxtArenas<'tcx>,
431 named_region_map: resolve_lifetime::NamedRegionMap,
432 map: ast_map::Map<'tcx>,
433 freevars: RefCell<FreevarMap>,
434 region_maps: RegionMaps,
435 lang_items: middle::lang_items::LanguageItems,
436 stability: stability::Index<'tcx>,
437 f: F) -> (Session, R)
438 where F: FnOnce(&ctxt<'tcx>) -> R
440 let interner = RefCell::new(FnvHashMap());
441 let common_types = CommonTypes::new(&arenas.type_, &interner);
446 substs_interner: RefCell::new(FnvHashMap()),
447 bare_fn_interner: RefCell::new(FnvHashMap()),
448 region_interner: RefCell::new(FnvHashMap()),
449 stability_interner: RefCell::new(FnvHashMap()),
451 named_region_map: named_region_map,
452 region_maps: region_maps,
453 free_region_maps: RefCell::new(FnvHashMap()),
454 item_variance_map: RefCell::new(DefIdMap()),
455 variance_computed: Cell::new(false),
458 tables: RefCell::new(Tables::empty()),
459 impl_trait_refs: RefCell::new(DefIdMap()),
460 trait_defs: RefCell::new(DefIdMap()),
461 adt_defs: RefCell::new(DefIdMap()),
462 predicates: RefCell::new(DefIdMap()),
463 super_predicates: RefCell::new(DefIdMap()),
464 fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
467 tcache: RefCell::new(DefIdMap()),
468 rcache: RefCell::new(FnvHashMap()),
469 tc_cache: RefCell::new(FnvHashMap()),
470 ast_ty_to_ty_cache: RefCell::new(NodeMap()),
471 impl_or_trait_items: RefCell::new(DefIdMap()),
472 trait_item_def_ids: RefCell::new(DefIdMap()),
473 trait_items_cache: RefCell::new(DefIdMap()),
474 ty_param_defs: RefCell::new(NodeMap()),
475 normalized_cache: RefCell::new(FnvHashMap()),
476 lang_items: lang_items,
477 provided_method_sources: RefCell::new(DefIdMap()),
478 destructors: RefCell::new(DefIdSet()),
479 inherent_impls: RefCell::new(DefIdMap()),
480 impl_items: RefCell::new(DefIdMap()),
481 used_unsafe: RefCell::new(NodeSet()),
482 used_mut_nodes: RefCell::new(NodeSet()),
483 populated_external_types: RefCell::new(DefIdSet()),
484 populated_external_primitive_impls: RefCell::new(DefIdSet()),
485 extern_const_statics: RefCell::new(DefIdMap()),
486 extern_const_variants: RefCell::new(DefIdMap()),
487 extern_const_fns: RefCell::new(DefIdMap()),
488 node_lint_levels: RefCell::new(FnvHashMap()),
489 transmute_restrictions: RefCell::new(Vec::new()),
490 stability: RefCell::new(stability),
491 selection_cache: traits::SelectionCache::new(),
492 repr_hint_cache: RefCell::new(DefIdMap()),
493 const_qualif_map: RefCell::new(NodeMap()),
494 custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
495 cast_kinds: RefCell::new(NodeMap()),
496 fragment_infos: RefCell::new(DefIdMap()),
501 /// A trait implemented for all X<'a> types which can be safely and
502 /// efficiently converted to X<'tcx> as long as they are part of the
503 /// provided ty::ctxt<'tcx>.
504 /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
505 /// by looking them up in their respective interners.
506 /// None is returned if the value or one of the components is not part
507 /// of the provided context.
508 /// For Ty, None can be returned if either the type interner doesn't
509 /// contain the TypeVariants key or if the address of the interned
510 /// pointer differs. The latter case is possible if a primitive type,
511 /// e.g. `()` or `u8`, was interned in a different context.
512 pub trait Lift<'tcx> {
514 fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>;
517 impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
518 type Lifted = Ty<'tcx>;
519 fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> {
520 if let Some(&ty) = tcx.interner.borrow().get(&self.sty) {
521 if *self as *const _ == ty as *const _ {
529 impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
530 type Lifted = &'tcx Substs<'tcx>;
531 fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> {
532 if let Some(&substs) = tcx.substs_interner.borrow().get(*self) {
533 if *self as *const _ == substs as *const _ {
544 use session::Session;
549 /// Marker type used for the scoped TLS slot.
550 /// The type context cannot be used directly because the scoped TLS
551 /// in libstd doesn't allow types generic over lifetimes.
552 struct ThreadLocalTyCx;
554 scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
556 fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
558 write!(f, "{}", tcx.sess.codemap().span_to_string(span))
562 pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
564 let result = codemap::SPAN_DEBUG.with(|span_dbg| {
565 let original_span_debug = span_dbg.get();
566 span_dbg.set(span_debug);
567 let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
568 let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
569 span_dbg.set(original_span_debug);
575 pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
576 TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) }))
579 pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
580 if TLS_TCX.is_set() {
588 macro_rules! sty_debug_print {
589 ($ctxt: expr, $($variant: ident),*) => {{
590 // curious inner module to allow variant names to be used as
592 #[allow(non_snake_case)]
595 #[derive(Copy, Clone)]
603 pub fn go(tcx: &ty::ctxt) {
604 let mut total = DebugStat {
606 region_infer: 0, ty_infer: 0, both_infer: 0,
608 $(let mut $variant = total;)*
611 for (_, t) in tcx.interner.borrow().iter() {
612 let variant = match t.sty {
613 ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
614 ty::TyFloat(..) | ty::TyStr => continue,
615 ty::TyError => /* unimportant */ continue,
616 $(ty::$variant(..) => &mut $variant,)*
618 let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
619 let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
623 if region { total.region_infer += 1; variant.region_infer += 1 }
624 if ty { total.ty_infer += 1; variant.ty_infer += 1 }
625 if region && ty { total.both_infer += 1; variant.both_infer += 1 }
627 println!("Ty interner total ty region both");
628 $(println!(" {:18}: {uses:6} {usespc:4.1}%, \
629 {ty:4.1}% {region:5.1}% {both:4.1}%",
630 stringify!($variant),
631 uses = $variant.total,
632 usespc = $variant.total as f64 * 100.0 / total.total as f64,
633 ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
634 region = $variant.region_infer as f64 * 100.0 / total.total as f64,
635 both = $variant.both_infer as f64 * 100.0 / total.total as f64);
637 println!(" total {uses:6} \
638 {ty:4.1}% {region:5.1}% {both:4.1}%",
640 ty = total.ty_infer as f64 * 100.0 / total.total as f64,
641 region = total.region_infer as f64 * 100.0 / total.total as f64,
642 both = total.both_infer as f64 * 100.0 / total.total as f64)
650 impl<'tcx> ctxt<'tcx> {
651 pub fn print_debug_stats(&self) {
654 TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
655 TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
657 println!("Substs interner: #{}", self.substs_interner.borrow().len());
658 println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
659 println!("Region interner: #{}", self.region_interner.borrow().len());
660 println!("Stability interner: #{}", self.stability_interner.borrow().len());
665 /// An entry in the type interner.
666 pub struct InternedTy<'tcx> {
670 // NB: An InternedTy compares and hashes as a sty.
671 impl<'tcx> PartialEq for InternedTy<'tcx> {
672 fn eq(&self, other: &InternedTy<'tcx>) -> bool {
673 self.ty.sty == other.ty.sty
677 impl<'tcx> Eq for InternedTy<'tcx> {}
679 impl<'tcx> Hash for InternedTy<'tcx> {
680 fn hash<H: Hasher>(&self, s: &mut H) {
685 impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
686 fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> {
691 fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
693 bounds[1..].iter().enumerate().all(
694 |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
697 impl<'tcx> ctxt<'tcx> {
699 pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
700 if let Some(substs) = self.substs_interner.borrow().get(&substs) {
704 let substs = self.arenas.substs.alloc(substs);
705 self.substs_interner.borrow_mut().insert(substs, substs);
709 /// Create an unsafe fn ty based on a safe fn ty.
710 pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
711 assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
712 let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
713 unsafety: hir::Unsafety::Unsafe,
715 sig: bare_fn.sig.clone()
717 self.mk_fn(None, unsafe_fn_ty_a)
720 pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
721 if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) {
725 let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
726 self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
730 pub fn mk_region(&self, region: Region) -> &'tcx Region {
731 if let Some(region) = self.region_interner.borrow().get(®ion) {
735 let region = self.arenas.region.alloc(region);
736 self.region_interner.borrow_mut().insert(region, region);
740 fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
741 interner: &RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
742 st: TypeVariants<'tcx>)
744 let ty: Ty /* don't be &mut TyS */ = {
745 let mut interner = interner.borrow_mut();
746 match interner.get(&st) {
747 Some(ty) => return *ty,
751 let flags = super::flags::FlagComputation::for_sty(&st);
754 () => type_arena.alloc(TyS { sty: st,
755 flags: Cell::new(flags.flags),
756 region_depth: flags.depth, }),
759 interner.insert(InternedTy { ty: ty }, ty);
763 debug!("Interned type: {:?} Pointer: {:?}",
764 ty, ty as *const TyS);
768 // Interns a type/name combination, stores the resulting box in cx.interner,
769 // and returns the box as cast to an unsafe ptr (see comments for Ty above).
770 pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
771 ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
774 pub fn mk_mach_int(&self, tm: hir::IntTy) -> Ty<'tcx> {
776 hir::TyIs => self.types.isize,
777 hir::TyI8 => self.types.i8,
778 hir::TyI16 => self.types.i16,
779 hir::TyI32 => self.types.i32,
780 hir::TyI64 => self.types.i64,
784 pub fn mk_mach_uint(&self, tm: hir::UintTy) -> Ty<'tcx> {
786 hir::TyUs => self.types.usize,
787 hir::TyU8 => self.types.u8,
788 hir::TyU16 => self.types.u16,
789 hir::TyU32 => self.types.u32,
790 hir::TyU64 => self.types.u64,
794 pub fn mk_mach_float(&self, tm: hir::FloatTy) -> Ty<'tcx> {
796 hir::TyF32 => self.types.f32,
797 hir::TyF64 => self.types.f64,
801 pub fn mk_str(&self) -> Ty<'tcx> {
805 pub fn mk_static_str(&self) -> Ty<'tcx> {
806 self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
809 pub fn mk_enum(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
810 // take a copy of substs so that we own the vectors inside
811 self.mk_ty(TyEnum(def, substs))
814 pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
815 self.mk_ty(TyBox(ty))
818 pub fn mk_ptr(&self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
819 self.mk_ty(TyRawPtr(tm))
822 pub fn mk_ref(&self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
823 self.mk_ty(TyRef(r, tm))
826 pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
827 self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable})
830 pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
831 self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
834 pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
835 self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable})
838 pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
839 self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable})
842 pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
843 self.mk_imm_ptr(self.mk_nil())
846 pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> {
847 self.mk_ty(TyArray(ty, n))
850 pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
851 self.mk_ty(TySlice(ty))
854 pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
855 self.mk_ty(TyTuple(ts))
858 pub fn mk_nil(&self) -> Ty<'tcx> {
859 self.mk_tup(Vec::new())
862 pub fn mk_bool(&self) -> Ty<'tcx> {
867 opt_def_id: Option<DefId>,
868 fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
869 self.mk_ty(TyBareFn(opt_def_id, fty))
872 pub fn mk_ctor_fn(&self,
874 input_tys: &[Ty<'tcx>],
875 output: Ty<'tcx>) -> Ty<'tcx> {
876 let input_args = input_tys.iter().cloned().collect();
877 self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
878 unsafety: hir::Unsafety::Normal,
880 sig: ty::Binder(ty::FnSig {
882 output: ty::FnConverging(output),
888 pub fn mk_trait(&self,
889 principal: ty::PolyTraitRef<'tcx>,
890 bounds: ExistentialBounds<'tcx>)
893 assert!(bound_list_is_sorted(&bounds.projection_bounds));
895 let inner = box TraitTy {
896 principal: principal,
899 self.mk_ty(TyTrait(inner))
902 pub fn mk_projection(&self,
903 trait_ref: TraitRef<'tcx>,
906 // take a copy of substs so that we own the vectors inside
907 let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
908 self.mk_ty(TyProjection(inner))
911 pub fn mk_struct(&self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
912 // take a copy of substs so that we own the vectors inside
913 self.mk_ty(TyStruct(def, substs))
916 pub fn mk_closure(&self,
918 substs: &'tcx Substs<'tcx>,
921 self.mk_closure_from_closure_substs(closure_id, Box::new(ClosureSubsts {
927 pub fn mk_closure_from_closure_substs(&self,
929 closure_substs: Box<ClosureSubsts<'tcx>>)
931 self.mk_ty(TyClosure(closure_id, closure_substs))
934 pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
935 self.mk_infer(TyVar(v))
938 pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> {
939 self.mk_infer(IntVar(v))
942 pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> {
943 self.mk_infer(FloatVar(v))
946 pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> {
947 self.mk_ty(TyInfer(it))
950 pub fn mk_param(&self,
951 space: subst::ParamSpace,
953 name: Name) -> Ty<'tcx> {
954 self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
957 pub fn mk_self_type(&self) -> Ty<'tcx> {
958 self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name)
961 pub fn mk_param_from_def(&self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
962 self.mk_param(def.space, def.index, def.name)