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 dep_graph
::{DepGraph, DepTrackingMap}
;
17 use front
::map
as ast_map
;
21 use middle
::cstore
::CrateStore
;
22 use middle
::def
::DefMap
;
23 use middle
::def_id
::DefId
;
24 use middle
::free_region
::FreeRegionMap
;
25 use middle
::region
::RegionMaps
;
26 use middle
::resolve_lifetime
;
27 use middle
::stability
;
28 use middle
::subst
::{self, Subst, Substs}
;
30 use middle
::ty
::{self, TraitRef, Ty, TypeAndMut}
;
31 use middle
::ty
::{TyS, TypeVariants}
;
32 use middle
::ty
::{AdtDef, ClosureSubsts, ExistentialBounds, Region}
;
33 use middle
::ty
::{FreevarMap}
;
34 use middle
::ty
::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy}
;
35 use middle
::ty
::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}
;
36 use middle
::ty
::TypeVariants
::*;
38 use util
::common
::MemoizationMap
;
39 use util
::nodemap
::{NodeMap, NodeSet, DefIdMap, DefIdSet}
;
40 use util
::nodemap
::FnvHashMap
;
42 use arena
::TypedArena
;
43 use std
::borrow
::Borrow
;
44 use std
::cell
::{Cell, RefCell, Ref}
;
45 use std
::hash
::{Hash, Hasher}
;
48 use syntax
::ast
::{self, Name, NodeId}
;
50 use syntax
::parse
::token
::special_idents
;
55 pub struct CtxtArenas
<'tcx
> {
57 type_
: TypedArena
<TyS
<'tcx
>>,
58 substs
: TypedArena
<Substs
<'tcx
>>,
59 bare_fn
: TypedArena
<BareFnTy
<'tcx
>>,
60 region
: TypedArena
<Region
>,
61 stability
: TypedArena
<attr
::Stability
>,
64 trait_defs
: TypedArena
<ty
::TraitDef
<'tcx
>>,
65 adt_defs
: TypedArena
<ty
::AdtDefData
<'tcx
, 'tcx
>>,
68 impl<'tcx
> CtxtArenas
<'tcx
> {
69 pub fn new() -> CtxtArenas
<'tcx
> {
71 type_
: TypedArena
::new(),
72 substs
: TypedArena
::new(),
73 bare_fn
: TypedArena
::new(),
74 region
: TypedArena
::new(),
75 stability
: TypedArena
::new(),
77 trait_defs
: TypedArena
::new(),
78 adt_defs
: TypedArena
::new()
83 pub struct CommonTypes
<'tcx
> {
101 pub struct Tables
<'tcx
> {
102 /// Stores the types for various nodes in the AST. Note that this table
103 /// is not guaranteed to be populated until after typeck. See
104 /// typeck::check::fn_ctxt for details.
105 pub node_types
: NodeMap
<Ty
<'tcx
>>,
107 /// Stores the type parameters which were substituted to obtain the type
108 /// of this node. This only applies to nodes that refer to entities
109 /// parameterized by type parameters, such as generic fns, types, or
111 pub item_substs
: NodeMap
<ty
::ItemSubsts
<'tcx
>>,
113 pub adjustments
: NodeMap
<ty
::adjustment
::AutoAdjustment
<'tcx
>>,
115 pub method_map
: ty
::MethodMap
<'tcx
>,
118 pub upvar_capture_map
: ty
::UpvarCaptureMap
,
120 /// Records the type of each closure. The def ID is the ID of the
121 /// expression defining the closure.
122 pub closure_tys
: DefIdMap
<ty
::ClosureTy
<'tcx
>>,
124 /// Records the type of each closure. The def ID is the ID of the
125 /// expression defining the closure.
126 pub closure_kinds
: DefIdMap
<ty
::ClosureKind
>,
128 /// For each fn, records the "liberated" types of its arguments
129 /// and return type. Liberated means that all bound regions
130 /// (including late-bound regions) are replaced with free
131 /// equivalents. This table is not used in trans (since regions
132 /// are erased there) and hence is not serialized to metadata.
133 pub liberated_fn_sigs
: NodeMap
<ty
::FnSig
<'tcx
>>,
135 /// For each FRU expression, record the normalized types of the fields
136 /// of the struct - this is needed because it is non-trivial to
137 /// normalize while preserving regions. This table is used only in
138 /// MIR construction and hence is not serialized to metadata.
139 pub fru_field_types
: NodeMap
<Vec
<Ty
<'tcx
>>>
142 impl<'tcx
> Tables
<'tcx
> {
143 pub fn empty() -> Tables
<'tcx
> {
145 node_types
: FnvHashMap(),
146 item_substs
: NodeMap(),
147 adjustments
: NodeMap(),
148 method_map
: FnvHashMap(),
149 upvar_capture_map
: FnvHashMap(),
150 closure_tys
: DefIdMap(),
151 closure_kinds
: DefIdMap(),
152 liberated_fn_sigs
: NodeMap(),
153 fru_field_types
: NodeMap()
157 pub fn closure_kind(this
: &RefCell
<Self>,
158 tcx
: &ty
::ctxt
<'tcx
>,
161 // If this is a local def-id, it should be inserted into the
162 // tables by typeck; else, it will be retreived from
163 // the external crate metadata.
164 if let Some(&kind
) = this
.borrow().closure_kinds
.get(&def_id
) {
168 let kind
= tcx
.sess
.cstore
.closure_kind(tcx
, def_id
);
169 this
.borrow_mut().closure_kinds
.insert(def_id
, kind
);
173 pub fn closure_type(this
: &RefCell
<Self>,
174 tcx
: &ty
::ctxt
<'tcx
>,
176 substs
: &ClosureSubsts
<'tcx
>)
177 -> ty
::ClosureTy
<'tcx
>
179 // If this is a local def-id, it should be inserted into the
180 // tables by typeck; else, it will be retreived from
181 // the external crate metadata.
182 if let Some(ty
) = this
.borrow().closure_tys
.get(&def_id
) {
183 return ty
.subst(tcx
, &substs
.func_substs
);
186 let ty
= tcx
.sess
.cstore
.closure_ty(tcx
, def_id
);
187 this
.borrow_mut().closure_tys
.insert(def_id
, ty
.clone());
188 ty
.subst(tcx
, &substs
.func_substs
)
192 impl<'tcx
> CommonTypes
<'tcx
> {
193 fn new(arena
: &'tcx TypedArena
<TyS
<'tcx
>>,
194 interner
: &RefCell
<FnvHashMap
<InternedTy
<'tcx
>, Ty
<'tcx
>>>)
197 let mk
= |sty
| ctxt
::intern_ty(arena
, interner
, sty
);
202 isize: mk(TyInt(ast
::IntTy
::Is
)),
203 i8: mk(TyInt(ast
::IntTy
::I8
)),
204 i16: mk(TyInt(ast
::IntTy
::I16
)),
205 i32: mk(TyInt(ast
::IntTy
::I32
)),
206 i64: mk(TyInt(ast
::IntTy
::I64
)),
207 usize: mk(TyUint(ast
::UintTy
::Us
)),
208 u8: mk(TyUint(ast
::UintTy
::U8
)),
209 u16: mk(TyUint(ast
::UintTy
::U16
)),
210 u32: mk(TyUint(ast
::UintTy
::U32
)),
211 u64: mk(TyUint(ast
::UintTy
::U64
)),
212 f32: mk(TyFloat(ast
::FloatTy
::F32
)),
213 f64: mk(TyFloat(ast
::FloatTy
::F64
)),
218 /// The data structure to keep track of all the information that typechecker
219 /// generates so that so that it can be reused and doesn't have to be redone
221 pub struct ctxt
<'tcx
> {
222 /// The arenas that types etc are allocated from.
223 arenas
: &'tcx CtxtArenas
<'tcx
>,
225 /// Specifically use a speedy hash algorithm for this hash map, it's used
227 // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
228 // queried from a HashSet.
229 interner
: RefCell
<FnvHashMap
<InternedTy
<'tcx
>, Ty
<'tcx
>>>,
231 // FIXME as above, use a hashset if equivalent elements can be queried.
232 substs_interner
: RefCell
<FnvHashMap
<&'tcx Substs
<'tcx
>, &'tcx Substs
<'tcx
>>>,
233 bare_fn_interner
: RefCell
<FnvHashMap
<&'tcx BareFnTy
<'tcx
>, &'tcx BareFnTy
<'tcx
>>>,
234 region_interner
: RefCell
<FnvHashMap
<&'tcx Region
, &'tcx Region
>>,
235 stability_interner
: RefCell
<FnvHashMap
<&'tcx attr
::Stability
, &'tcx attr
::Stability
>>,
237 pub dep_graph
: DepGraph
,
239 /// Common types, pre-interned for your convenience.
240 pub types
: CommonTypes
<'tcx
>,
242 pub sess
: &'tcx Session
,
243 pub def_map
: RefCell
<DefMap
>,
245 pub named_region_map
: resolve_lifetime
::NamedRegionMap
,
247 pub region_maps
: RegionMaps
,
249 // For each fn declared in the local crate, type check stores the
250 // free-region relationships that were deduced from its where
251 // clauses and parameter types. These are then read-again by
252 // borrowck. (They are not used during trans, and hence are not
253 // serialized or needed for cross-crate fns.)
254 free_region_maps
: RefCell
<NodeMap
<FreeRegionMap
>>,
255 // FIXME: jroesch make this a refcell
257 pub tables
: RefCell
<Tables
<'tcx
>>,
259 /// Maps from a trait item to the trait item "descriptor"
260 pub impl_or_trait_items
: RefCell
<DepTrackingMap
<maps
::ImplOrTraitItems
<'tcx
>>>,
262 /// Maps from a trait def-id to a list of the def-ids of its trait items
263 pub trait_item_def_ids
: RefCell
<DepTrackingMap
<maps
::TraitItemDefIds
<'tcx
>>>,
265 /// A cache for the trait_items() routine; note that the routine
266 /// itself pushes the `TraitItems` dependency node.
267 trait_items_cache
: RefCell
<DepTrackingMap
<maps
::TraitItems
<'tcx
>>>,
269 pub impl_trait_refs
: RefCell
<DepTrackingMap
<maps
::ImplTraitRefs
<'tcx
>>>,
270 pub trait_defs
: RefCell
<DepTrackingMap
<maps
::TraitDefs
<'tcx
>>>,
271 pub adt_defs
: RefCell
<DepTrackingMap
<maps
::AdtDefs
<'tcx
>>>,
273 /// Maps from the def-id of an item (trait/struct/enum/fn) to its
274 /// associated predicates.
275 pub predicates
: RefCell
<DepTrackingMap
<maps
::Predicates
<'tcx
>>>,
277 /// Maps from the def-id of a trait to the list of
278 /// super-predicates. This is a subset of the full list of
279 /// predicates. We store these in a separate map because we must
280 /// evaluate them even during type conversion, often before the
281 /// full predicates are available (note that supertraits have
282 /// additional acyclicity requirements).
283 pub super_predicates
: RefCell
<DepTrackingMap
<maps
::Predicates
<'tcx
>>>,
285 pub map
: ast_map
::Map
<'tcx
>,
287 // Records the free variables refrenced by every closure
288 // expression. Do not track deps for this, just recompute it from
289 // scratch every time.
290 pub freevars
: RefCell
<FreevarMap
>,
292 // Records the type of every item.
293 pub tcache
: RefCell
<DepTrackingMap
<maps
::Tcache
<'tcx
>>>,
295 // Internal cache for metadata decoding. No need to track deps on this.
296 pub rcache
: RefCell
<FnvHashMap
<ty
::CReaderCacheKey
, Ty
<'tcx
>>>,
298 // Cache for the type-contents routine. FIXME -- track deps?
299 pub tc_cache
: RefCell
<FnvHashMap
<Ty
<'tcx
>, ty
::contents
::TypeContents
>>,
301 // Cache for various types within a method body and so forth.
303 // FIXME this should be made local to typeck, but it is currently used by one lint
304 pub ast_ty_to_ty_cache
: RefCell
<NodeMap
<Ty
<'tcx
>>>,
306 // FIXME no dep tracking, but we should be able to remove this
307 pub ty_param_defs
: RefCell
<NodeMap
<ty
::TypeParameterDef
<'tcx
>>>,
309 // FIXME dep tracking -- should be harmless enough
310 pub normalized_cache
: RefCell
<FnvHashMap
<Ty
<'tcx
>, Ty
<'tcx
>>>,
312 pub lang_items
: middle
::lang_items
::LanguageItems
,
314 /// Maps from def-id of a type or region parameter to its
315 /// (inferred) variance.
316 pub item_variance_map
: RefCell
<DepTrackingMap
<maps
::ItemVariances
<'tcx
>>>,
318 /// True if the variance has been computed yet; false otherwise.
319 pub variance_computed
: Cell
<bool
>,
321 /// Maps a DefId of a type to a list of its inherent impls.
322 /// Contains implementations of methods that are inherent to a type.
323 /// Methods in these implementations don't need to be exported.
324 pub inherent_impls
: RefCell
<DepTrackingMap
<maps
::InherentImpls
<'tcx
>>>,
326 /// Maps a DefId of an impl to a list of its items.
327 /// Note that this contains all of the impls that we know about,
328 /// including ones in other crates. It's not clear that this is the best
330 pub impl_items
: RefCell
<DepTrackingMap
<maps
::ImplItems
<'tcx
>>>,
332 /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
333 /// present in this set can be warned about.
334 pub used_unsafe
: RefCell
<NodeSet
>,
336 /// Set of nodes which mark locals as mutable which end up getting used at
337 /// some point. Local variable definitions not in this set can be warned
339 pub used_mut_nodes
: RefCell
<NodeSet
>,
341 /// The set of external nominal types whose implementations have been read.
342 /// This is used for lazy resolution of methods.
343 pub populated_external_types
: RefCell
<DefIdSet
>,
345 /// The set of external primitive types whose implementations have been read.
346 /// FIXME(arielb1): why is this separate from populated_external_types?
347 pub populated_external_primitive_impls
: RefCell
<DefIdSet
>,
349 /// These caches are used by const_eval when decoding external constants.
350 pub extern_const_statics
: RefCell
<DefIdMap
<NodeId
>>,
351 pub extern_const_fns
: RefCell
<DefIdMap
<NodeId
>>,
353 pub node_lint_levels
: RefCell
<FnvHashMap
<(NodeId
, lint
::LintId
),
356 /// The types that must be asserted to be the same size for `transmute`
357 /// to be valid. We gather up these restrictions in the intrinsicck pass
358 /// and check them in trans.
359 pub transmute_restrictions
: RefCell
<Vec
<ty
::TransmuteRestriction
<'tcx
>>>,
361 /// Maps any item's def-id to its stability index.
362 pub stability
: RefCell
<stability
::Index
<'tcx
>>,
364 /// Caches the results of trait selection. This cache is used
365 /// for things that do not have to do with the parameters in scope.
366 pub selection_cache
: traits
::SelectionCache
<'tcx
>,
368 /// Caches the results of trait evaluation. This cache is used
369 /// for things that do not have to do with the parameters in scope.
370 /// Merge this with `selection_cache`?
371 pub evaluation_cache
: traits
::EvaluationCache
<'tcx
>,
373 /// A set of predicates that have been fulfilled *somewhere*.
374 /// This is used to avoid duplicate work. Predicates are only
375 /// added to this set when they mention only "global" names
376 /// (i.e., no type or lifetime parameters).
377 pub fulfilled_predicates
: RefCell
<traits
::GlobalFulfilledPredicates
<'tcx
>>,
379 /// Caches the representation hints for struct definitions.
380 repr_hint_cache
: RefCell
<DepTrackingMap
<maps
::ReprHints
<'tcx
>>>,
382 /// Maps Expr NodeId's to their constant qualification.
383 pub const_qualif_map
: RefCell
<NodeMap
<middle
::const_qualif
::ConstQualif
>>,
385 /// Caches CoerceUnsized kinds for impls on custom types.
386 pub custom_coerce_unsized_kinds
: RefCell
<DefIdMap
<ty
::adjustment
::CustomCoerceUnsized
>>,
388 /// Maps a cast expression to its kind. This is keyed on the
389 /// *from* expression of the cast, not the cast itself.
390 pub cast_kinds
: RefCell
<NodeMap
<ty
::cast
::CastKind
>>,
392 /// Maps Fn items to a collection of fragment infos.
394 /// The main goal is to identify data (each of which may be moved
395 /// or assigned) whose subparts are not moved nor assigned
396 /// (i.e. their state is *unfragmented*) and corresponding ast
397 /// nodes where the path to that data is moved or assigned.
399 /// In the long term, unfragmented values will have their
400 /// destructor entirely driven by a single stack-local drop-flag,
401 /// and their parents, the collections of the unfragmented values
402 /// (or more simply, "fragmented values"), are mapped to the
403 /// corresponding collections of stack-local drop-flags.
405 /// (However, in the short term that is not the case; e.g. some
406 /// unfragmented paths still need to be zeroed, namely when they
407 /// reference parent data from an outer scope that was not
408 /// entirely moved, and therefore that needs to be zeroed so that
409 /// we do not get double-drop when we hit the end of the parent
412 /// Also: currently the table solely holds keys for node-ids of
413 /// unfragmented values (see `FragmentInfo` enum definition), but
414 /// longer-term we will need to also store mappings from
415 /// fragmented data to the set of unfragmented pieces that
417 pub fragment_infos
: RefCell
<DefIdMap
<Vec
<ty
::FragmentInfo
>>>,
420 impl<'tcx
> ctxt
<'tcx
> {
421 pub fn type_parameter_def(&self,
423 -> ty
::TypeParameterDef
<'tcx
>
425 self.ty_param_defs
.borrow().get(&node_id
).unwrap().clone()
428 pub fn node_types(&self) -> Ref
<NodeMap
<Ty
<'tcx
>>> {
429 fn projection
<'a
, 'tcx
>(tables
: &'a Tables
<'tcx
>) -> &'a NodeMap
<Ty
<'tcx
>> {
433 Ref
::map(self.tables
.borrow(), projection
)
436 pub fn node_type_insert(&self, id
: NodeId
, ty
: Ty
<'tcx
>) {
437 self.tables
.borrow_mut().node_types
.insert(id
, ty
);
440 pub fn intern_trait_def(&self, def
: ty
::TraitDef
<'tcx
>)
441 -> &'tcx ty
::TraitDef
<'tcx
> {
442 let did
= def
.trait_ref
.def_id
;
443 let interned
= self.arenas
.trait_defs
.alloc(def
);
444 if let Some(prev
) = self.trait_defs
.borrow_mut().insert(did
, interned
) {
445 self.sess
.bug(&format
!("Tried to overwrite interned TraitDef: {:?}",
451 pub fn alloc_trait_def(&self, def
: ty
::TraitDef
<'tcx
>)
452 -> &'tcx ty
::TraitDef
<'tcx
> {
453 self.arenas
.trait_defs
.alloc(def
)
456 pub fn intern_adt_def(&self,
459 variants
: Vec
<ty
::VariantDefData
<'tcx
, 'tcx
>>)
460 -> ty
::AdtDefMaster
<'tcx
> {
461 let def
= ty
::AdtDefData
::new(self, did
, kind
, variants
);
462 let interned
= self.arenas
.adt_defs
.alloc(def
);
463 // this will need a transmute when reverse-variance is removed
464 if let Some(prev
) = self.adt_defs
.borrow_mut().insert(did
, interned
) {
465 self.sess
.bug(&format
!("Tried to overwrite interned AdtDef: {:?}",
471 pub fn intern_stability(&self, stab
: attr
::Stability
) -> &'tcx attr
::Stability
{
472 if let Some(st
) = self.stability_interner
.borrow().get(&stab
) {
476 let interned
= self.arenas
.stability
.alloc(stab
);
477 if let Some(prev
) = self.stability_interner
479 .insert(interned
, interned
) {
480 self.sess
.bug(&format
!("Tried to overwrite interned Stability: {:?}",
486 pub fn store_free_region_map(&self, id
: NodeId
, map
: FreeRegionMap
) {
487 if self.free_region_maps
.borrow_mut().insert(id
, map
).is_some() {
488 self.sess
.bug(&format
!("Tried to overwrite interned FreeRegionMap for NodeId {:?}",
493 pub fn free_region_map(&self, id
: NodeId
) -> FreeRegionMap
{
494 self.free_region_maps
.borrow()[&id
].clone()
497 pub fn lift
<T
: ?Sized
+ Lift
<'tcx
>>(&self, value
: &T
) -> Option
<T
::Lifted
> {
498 value
.lift_to_tcx(self)
501 /// Create a type context and call the closure with a `&ty::ctxt` reference
502 /// to the context. The closure enforces that the type context and any interned
503 /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
504 /// reference to the context, to allow formatting values that need it.
505 pub fn create_and_enter
<F
, R
>(s
: &'tcx Session
,
506 arenas
: &'tcx CtxtArenas
<'tcx
>,
507 def_map
: RefCell
<DefMap
>,
508 named_region_map
: resolve_lifetime
::NamedRegionMap
,
509 map
: ast_map
::Map
<'tcx
>,
510 freevars
: FreevarMap
,
511 region_maps
: RegionMaps
,
512 lang_items
: middle
::lang_items
::LanguageItems
,
513 stability
: stability
::Index
<'tcx
>,
515 where F
: FnOnce(&ctxt
<'tcx
>) -> R
517 let interner
= RefCell
::new(FnvHashMap());
518 let common_types
= CommonTypes
::new(&arenas
.type_
, &interner
);
519 let dep_graph
= map
.dep_graph
.clone();
520 let fulfilled_predicates
= traits
::GlobalFulfilledPredicates
::new(dep_graph
.clone());
524 substs_interner
: RefCell
::new(FnvHashMap()),
525 bare_fn_interner
: RefCell
::new(FnvHashMap()),
526 region_interner
: RefCell
::new(FnvHashMap()),
527 stability_interner
: RefCell
::new(FnvHashMap()),
528 dep_graph
: dep_graph
.clone(),
530 named_region_map
: named_region_map
,
531 region_maps
: region_maps
,
532 free_region_maps
: RefCell
::new(FnvHashMap()),
533 item_variance_map
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
534 variance_computed
: Cell
::new(false),
537 tables
: RefCell
::new(Tables
::empty()),
538 impl_trait_refs
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
539 trait_defs
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
540 adt_defs
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
541 predicates
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
542 super_predicates
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
543 fulfilled_predicates
: RefCell
::new(fulfilled_predicates
),
545 freevars
: RefCell
::new(freevars
),
546 tcache
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
547 rcache
: RefCell
::new(FnvHashMap()),
548 tc_cache
: RefCell
::new(FnvHashMap()),
549 ast_ty_to_ty_cache
: RefCell
::new(NodeMap()),
550 impl_or_trait_items
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
551 trait_item_def_ids
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
552 trait_items_cache
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
553 ty_param_defs
: RefCell
::new(NodeMap()),
554 normalized_cache
: RefCell
::new(FnvHashMap()),
555 lang_items
: lang_items
,
556 inherent_impls
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
557 impl_items
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
558 used_unsafe
: RefCell
::new(NodeSet()),
559 used_mut_nodes
: RefCell
::new(NodeSet()),
560 populated_external_types
: RefCell
::new(DefIdSet()),
561 populated_external_primitive_impls
: RefCell
::new(DefIdSet()),
562 extern_const_statics
: RefCell
::new(DefIdMap()),
563 extern_const_fns
: RefCell
::new(DefIdMap()),
564 node_lint_levels
: RefCell
::new(FnvHashMap()),
565 transmute_restrictions
: RefCell
::new(Vec
::new()),
566 stability
: RefCell
::new(stability
),
567 selection_cache
: traits
::SelectionCache
::new(),
568 evaluation_cache
: traits
::EvaluationCache
::new(),
569 repr_hint_cache
: RefCell
::new(DepTrackingMap
::new(dep_graph
.clone())),
570 const_qualif_map
: RefCell
::new(NodeMap()),
571 custom_coerce_unsized_kinds
: RefCell
::new(DefIdMap()),
572 cast_kinds
: RefCell
::new(NodeMap()),
573 fragment_infos
: RefCell
::new(DefIdMap())
578 /// A trait implemented for all X<'a> types which can be safely and
579 /// efficiently converted to X<'tcx> as long as they are part of the
580 /// provided ty::ctxt<'tcx>.
581 /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx>
582 /// by looking them up in their respective interners.
583 /// None is returned if the value or one of the components is not part
584 /// of the provided context.
585 /// For Ty, None can be returned if either the type interner doesn't
586 /// contain the TypeVariants key or if the address of the interned
587 /// pointer differs. The latter case is possible if a primitive type,
588 /// e.g. `()` or `u8`, was interned in a different context.
589 pub trait Lift
<'tcx
> {
591 fn lift_to_tcx(&self, tcx
: &ctxt
<'tcx
>) -> Option
<Self::Lifted
>;
594 impl<'a
, 'tcx
> Lift
<'tcx
> for Ty
<'a
> {
595 type Lifted
= Ty
<'tcx
>;
596 fn lift_to_tcx(&self, tcx
: &ctxt
<'tcx
>) -> Option
<Ty
<'tcx
>> {
597 if let Some(&ty
) = tcx
.interner
.borrow().get(&self.sty
) {
598 if *self as *const _
== ty
as *const _
{
606 impl<'a
, 'tcx
> Lift
<'tcx
> for &'a Substs
<'a
> {
607 type Lifted
= &'tcx Substs
<'tcx
>;
608 fn lift_to_tcx(&self, tcx
: &ctxt
<'tcx
>) -> Option
<&'tcx Substs
<'tcx
>> {
609 if let Some(&substs
) = tcx
.substs_interner
.borrow().get(*self) {
610 if *self as *const _
== substs
as *const _
{
626 /// Marker type used for the scoped TLS slot.
627 /// The type context cannot be used directly because the scoped TLS
628 /// in libstd doesn't allow types generic over lifetimes.
629 struct ThreadLocalTyCx
;
632 static TLS_TCX
: Cell
<Option
<*const ThreadLocalTyCx
>> = Cell
::new(None
)
635 fn span_debug(span
: codemap
::Span
, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
637 write
!(f
, "{}", tcx
.sess
.codemap().span_to_string(span
))
641 pub fn enter
<'tcx
, F
: FnOnce(&ty
::ctxt
<'tcx
>) -> R
, R
>(tcx
: ty
::ctxt
<'tcx
>, f
: F
) -> R
{
642 codemap
::SPAN_DEBUG
.with(|span_dbg
| {
643 let original_span_debug
= span_dbg
.get();
644 span_dbg
.set(span_debug
);
645 let tls_ptr
= &tcx
as *const _
as *const ThreadLocalTyCx
;
646 let result
= TLS_TCX
.with(|tls
| {
647 let prev
= tls
.get();
648 tls
.set(Some(tls_ptr
));
653 span_dbg
.set(original_span_debug
);
658 pub fn with
<F
: FnOnce(&ty
::ctxt
) -> R
, R
>(f
: F
) -> R
{
660 let tcx
= tcx
.get().unwrap();
661 f(unsafe { &*(tcx as *const ty::ctxt) }
)
665 pub fn with_opt
<F
: FnOnce(Option
<&ty
::ctxt
>) -> R
, R
>(f
: F
) -> R
{
666 if TLS_TCX
.with(|tcx
| tcx
.get().is_some()) {
674 macro_rules
! sty_debug_print
{
675 ($ctxt
: expr
, $
($variant
: ident
),*) => {{
676 // curious inner module to allow variant names to be used as
678 #[allow(non_snake_case)]
681 #[derive(Copy, Clone)]
689 pub fn go(tcx
: &ty
::ctxt
) {
690 let mut total
= DebugStat
{
692 region_infer
: 0, ty_infer
: 0, both_infer
: 0,
694 $
(let mut $variant
= total
;)*
697 for (_
, t
) in tcx
.interner
.borrow().iter() {
698 let variant
= match t
.sty
{
699 ty
::TyBool
| ty
::TyChar
| ty
::TyInt(..) | ty
::TyUint(..) |
700 ty
::TyFloat(..) | ty
::TyStr
=> continue,
701 ty
::TyError
=> /* unimportant */ continue,
702 $
(ty
::$
variant(..) => &mut $variant
,)*
704 let region
= t
.flags
.get().intersects(ty
::TypeFlags
::HAS_RE_INFER
);
705 let ty
= t
.flags
.get().intersects(ty
::TypeFlags
::HAS_TY_INFER
);
709 if region { total.region_infer += 1; variant.region_infer += 1 }
710 if ty { total.ty_infer += 1; variant.ty_infer += 1 }
711 if region
&& ty { total.both_infer += 1; variant.both_infer += 1 }
713 println
!("Ty interner total ty region both");
714 $
(println
!(" {:18}: {uses:6} {usespc:4.1}%, \
715 {ty:4.1}% {region:5.1}% {both:4.1}%",
716 stringify
!($variant
),
717 uses
= $variant
.total
,
718 usespc
= $variant
.total
as f64 * 100.0 / total
.total
as f64,
719 ty
= $variant
.ty_infer
as f64 * 100.0 / total
.total
as f64,
720 region
= $variant
.region_infer
as f64 * 100.0 / total
.total
as f64,
721 both
= $variant
.both_infer
as f64 * 100.0 / total
.total
as f64);
723 println
!(" total {uses:6} \
724 {ty:4.1}% {region:5.1}% {both:4.1}%",
726 ty
= total
.ty_infer
as f64 * 100.0 / total
.total
as f64,
727 region
= total
.region_infer
as f64 * 100.0 / total
.total
as f64,
728 both
= total
.both_infer
as f64 * 100.0 / total
.total
as f64)
736 impl<'tcx
> ctxt
<'tcx
> {
737 pub fn print_debug_stats(&self) {
740 TyEnum
, TyBox
, TyArray
, TySlice
, TyRawPtr
, TyRef
, TyBareFn
, TyTrait
,
741 TyStruct
, TyClosure
, TyTuple
, TyParam
, TyInfer
, TyProjection
);
743 println
!("Substs interner: #{}", self.substs_interner
.borrow().len());
744 println
!("BareFnTy interner: #{}", self.bare_fn_interner
.borrow().len());
745 println
!("Region interner: #{}", self.region_interner
.borrow().len());
746 println
!("Stability interner: #{}", self.stability_interner
.borrow().len());
751 /// An entry in the type interner.
752 pub struct InternedTy
<'tcx
> {
756 // NB: An InternedTy compares and hashes as a sty.
757 impl<'tcx
> PartialEq
for InternedTy
<'tcx
> {
758 fn eq(&self, other
: &InternedTy
<'tcx
>) -> bool
{
759 self.ty
.sty
== other
.ty
.sty
763 impl<'tcx
> Eq
for InternedTy
<'tcx
> {}
765 impl<'tcx
> Hash
for InternedTy
<'tcx
> {
766 fn hash
<H
: Hasher
>(&self, s
: &mut H
) {
771 impl<'tcx
> Borrow
<TypeVariants
<'tcx
>> for InternedTy
<'tcx
> {
772 fn borrow
<'a
>(&'a
self) -> &'a TypeVariants
<'tcx
> {
777 fn bound_list_is_sorted(bounds
: &[ty
::PolyProjectionPredicate
]) -> bool
{
779 bounds
[1..].iter().enumerate().all(
780 |(index
, bound
)| bounds
[index
].sort_key() <= bound
.sort_key())
783 impl<'tcx
> ctxt
<'tcx
> {
785 pub fn mk_substs(&self, substs
: Substs
<'tcx
>) -> &'tcx Substs
<'tcx
> {
786 if let Some(substs
) = self.substs_interner
.borrow().get(&substs
) {
790 let substs
= self.arenas
.substs
.alloc(substs
);
791 self.substs_interner
.borrow_mut().insert(substs
, substs
);
795 /// Create an unsafe fn ty based on a safe fn ty.
796 pub fn safe_to_unsafe_fn_ty(&self, bare_fn
: &BareFnTy
<'tcx
>) -> Ty
<'tcx
> {
797 assert_eq
!(bare_fn
.unsafety
, hir
::Unsafety
::Normal
);
798 let unsafe_fn_ty_a
= self.mk_bare_fn(ty
::BareFnTy
{
799 unsafety
: hir
::Unsafety
::Unsafe
,
801 sig
: bare_fn
.sig
.clone()
803 self.mk_fn(None
, unsafe_fn_ty_a
)
806 pub fn mk_bare_fn(&self, bare_fn
: BareFnTy
<'tcx
>) -> &'tcx BareFnTy
<'tcx
> {
807 if let Some(bare_fn
) = self.bare_fn_interner
.borrow().get(&bare_fn
) {
811 let bare_fn
= self.arenas
.bare_fn
.alloc(bare_fn
);
812 self.bare_fn_interner
.borrow_mut().insert(bare_fn
, bare_fn
);
816 pub fn mk_region(&self, region
: Region
) -> &'tcx Region
{
817 if let Some(region
) = self.region_interner
.borrow().get(®ion
) {
821 let region
= self.arenas
.region
.alloc(region
);
822 self.region_interner
.borrow_mut().insert(region
, region
);
826 fn intern_ty(type_arena
: &'tcx TypedArena
<TyS
<'tcx
>>,
827 interner
: &RefCell
<FnvHashMap
<InternedTy
<'tcx
>, Ty
<'tcx
>>>,
828 st
: TypeVariants
<'tcx
>)
830 let ty
: Ty
/* don't be &mut TyS */ = {
831 let mut interner
= interner
.borrow_mut();
832 match interner
.get(&st
) {
833 Some(ty
) => return *ty
,
837 let flags
= super::flags
::FlagComputation
::for_sty(&st
);
840 () => type_arena
.alloc(TyS
{ sty
: st
,
841 flags
: Cell
::new(flags
.flags
),
842 region_depth
: flags
.depth
, }),
845 interner
.insert(InternedTy { ty: ty }
, ty
);
849 debug
!("Interned type: {:?} Pointer: {:?}",
850 ty
, ty
as *const TyS
);
854 // Interns a type/name combination, stores the resulting box in cx.interner,
855 // and returns the box as cast to an unsafe ptr (see comments for Ty above).
856 pub fn mk_ty(&self, st
: TypeVariants
<'tcx
>) -> Ty
<'tcx
> {
857 ctxt
::intern_ty(&self.arenas
.type_
, &self.interner
, st
)
860 pub fn mk_mach_int(&self, tm
: ast
::IntTy
) -> Ty
<'tcx
> {
862 ast
::IntTy
::Is
=> self.types
.isize,
863 ast
::IntTy
::I8
=> self.types
.i8,
864 ast
::IntTy
::I16
=> self.types
.i16,
865 ast
::IntTy
::I32
=> self.types
.i32,
866 ast
::IntTy
::I64
=> self.types
.i64,
870 pub fn mk_mach_uint(&self, tm
: ast
::UintTy
) -> Ty
<'tcx
> {
872 ast
::UintTy
::Us
=> self.types
.usize,
873 ast
::UintTy
::U8
=> self.types
.u8,
874 ast
::UintTy
::U16
=> self.types
.u16,
875 ast
::UintTy
::U32
=> self.types
.u32,
876 ast
::UintTy
::U64
=> self.types
.u64,
880 pub fn mk_mach_float(&self, tm
: ast
::FloatTy
) -> Ty
<'tcx
> {
882 ast
::FloatTy
::F32
=> self.types
.f32,
883 ast
::FloatTy
::F64
=> self.types
.f64,
887 pub fn mk_str(&self) -> Ty
<'tcx
> {
891 pub fn mk_static_str(&self) -> Ty
<'tcx
> {
892 self.mk_imm_ref(self.mk_region(ty
::ReStatic
), self.mk_str())
895 pub fn mk_enum(&self, def
: AdtDef
<'tcx
>, substs
: &'tcx Substs
<'tcx
>) -> Ty
<'tcx
> {
896 // take a copy of substs so that we own the vectors inside
897 self.mk_ty(TyEnum(def
, substs
))
900 pub fn mk_box(&self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
901 self.mk_ty(TyBox(ty
))
904 pub fn mk_ptr(&self, tm
: TypeAndMut
<'tcx
>) -> Ty
<'tcx
> {
905 self.mk_ty(TyRawPtr(tm
))
908 pub fn mk_ref(&self, r
: &'tcx Region
, tm
: TypeAndMut
<'tcx
>) -> Ty
<'tcx
> {
909 self.mk_ty(TyRef(r
, tm
))
912 pub fn mk_mut_ref(&self, r
: &'tcx Region
, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
913 self.mk_ref(r
, TypeAndMut {ty: ty, mutbl: hir::MutMutable}
)
916 pub fn mk_imm_ref(&self, r
: &'tcx Region
, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
917 self.mk_ref(r
, TypeAndMut {ty: ty, mutbl: hir::MutImmutable}
)
920 pub fn mk_mut_ptr(&self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
921 self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable}
)
924 pub fn mk_imm_ptr(&self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
925 self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable}
)
928 pub fn mk_nil_ptr(&self) -> Ty
<'tcx
> {
929 self.mk_imm_ptr(self.mk_nil())
932 pub fn mk_array(&self, ty
: Ty
<'tcx
>, n
: usize) -> Ty
<'tcx
> {
933 self.mk_ty(TyArray(ty
, n
))
936 pub fn mk_slice(&self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
937 self.mk_ty(TySlice(ty
))
940 pub fn mk_tup(&self, ts
: Vec
<Ty
<'tcx
>>) -> Ty
<'tcx
> {
941 self.mk_ty(TyTuple(ts
))
944 pub fn mk_nil(&self) -> Ty
<'tcx
> {
945 self.mk_tup(Vec
::new())
948 pub fn mk_bool(&self) -> Ty
<'tcx
> {
953 opt_def_id
: Option
<DefId
>,
954 fty
: &'tcx BareFnTy
<'tcx
>) -> Ty
<'tcx
> {
955 self.mk_ty(TyBareFn(opt_def_id
, fty
))
958 pub fn mk_ctor_fn(&self,
960 input_tys
: &[Ty
<'tcx
>],
961 output
: Ty
<'tcx
>) -> Ty
<'tcx
> {
962 let input_args
= input_tys
.iter().cloned().collect();
963 self.mk_fn(Some(def_id
), self.mk_bare_fn(BareFnTy
{
964 unsafety
: hir
::Unsafety
::Normal
,
966 sig
: ty
::Binder(ty
::FnSig
{
968 output
: ty
::FnConverging(output
),
974 pub fn mk_trait(&self,
975 principal
: ty
::PolyTraitRef
<'tcx
>,
976 bounds
: ExistentialBounds
<'tcx
>)
979 assert
!(bound_list_is_sorted(&bounds
.projection_bounds
));
981 let inner
= box TraitTy
{
982 principal
: principal
,
985 self.mk_ty(TyTrait(inner
))
988 pub fn mk_projection(&self,
989 trait_ref
: TraitRef
<'tcx
>,
992 // take a copy of substs so that we own the vectors inside
993 let inner
= ProjectionTy { trait_ref: trait_ref, item_name: item_name }
;
994 self.mk_ty(TyProjection(inner
))
997 pub fn mk_struct(&self, def
: AdtDef
<'tcx
>, substs
: &'tcx Substs
<'tcx
>) -> Ty
<'tcx
> {
998 // take a copy of substs so that we own the vectors inside
999 self.mk_ty(TyStruct(def
, substs
))
1002 pub fn mk_closure(&self,
1004 substs
: &'tcx Substs
<'tcx
>,
1007 self.mk_closure_from_closure_substs(closure_id
, Box
::new(ClosureSubsts
{
1008 func_substs
: substs
,
1013 pub fn mk_closure_from_closure_substs(&self,
1015 closure_substs
: Box
<ClosureSubsts
<'tcx
>>)
1017 self.mk_ty(TyClosure(closure_id
, closure_substs
))
1020 pub fn mk_var(&self, v
: TyVid
) -> Ty
<'tcx
> {
1021 self.mk_infer(TyVar(v
))
1024 pub fn mk_int_var(&self, v
: IntVid
) -> Ty
<'tcx
> {
1025 self.mk_infer(IntVar(v
))
1028 pub fn mk_float_var(&self, v
: FloatVid
) -> Ty
<'tcx
> {
1029 self.mk_infer(FloatVar(v
))
1032 pub fn mk_infer(&self, it
: InferTy
) -> Ty
<'tcx
> {
1033 self.mk_ty(TyInfer(it
))
1036 pub fn mk_param(&self,
1037 space
: subst
::ParamSpace
,
1039 name
: Name
) -> Ty
<'tcx
> {
1040 self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }
))
1043 pub fn mk_self_type(&self) -> Ty
<'tcx
> {
1044 self.mk_param(subst
::SelfSpace
, 0, special_idents
::type_self
.name
)
1047 pub fn mk_param_from_def(&self, def
: &ty
::TypeParameterDef
) -> Ty
<'tcx
> {
1048 self.mk_param(def
.space
, def
.index
, def
.name
)
1051 pub fn trait_items(&self, trait_did
: DefId
) -> Rc
<Vec
<ty
::ImplOrTraitItem
<'tcx
>>> {
1052 self.trait_items_cache
.memoize(trait_did
, || {
1053 let def_ids
= self.trait_item_def_ids(trait_did
);
1054 Rc
::new(def_ids
.iter()
1055 .map(|d
| self.impl_or_trait_item(d
.def_id()))
1060 /// Obtain the representation annotation for a struct definition.
1061 pub fn lookup_repr_hints(&self, did
: DefId
) -> Rc
<Vec
<attr
::ReprAttr
>> {
1062 self.repr_hint_cache
.memoize(did
, || {
1063 Rc
::new(if did
.is_local() {
1064 self.get_attrs(did
).iter().flat_map(|meta
| {
1065 attr
::find_repr_attrs(self.sess
.diagnostic(), meta
).into_iter()
1068 self.sess
.cstore
.repr_attrs(did
)