]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! type context book-keeping | |
12 | ||
8bb4bdeb | 13 | use dep_graph::DepGraph; |
e9174d1e | 14 | use session::Session; |
8bb4bdeb | 15 | use lint; |
e9174d1e | 16 | use middle; |
5bcae85e | 17 | use hir::TraitMap; |
476ff2be | 18 | use hir::def::Def; |
32a655c1 SL |
19 | use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; |
20 | use hir::map as hir_map; | |
21 | use hir::map::DisambiguatedDefPathData; | |
e9174d1e | 22 | use middle::free_region::FreeRegionMap; |
32a655c1 | 23 | use middle::lang_items; |
e9174d1e SL |
24 | use middle::region::RegionMaps; |
25 | use middle::resolve_lifetime; | |
26 | use middle::stability; | |
c30ab7b3 SL |
27 | use mir::Mir; |
28 | use ty::subst::{Kind, Substs}; | |
8bb4bdeb | 29 | use ty::ReprOptions; |
54a0048b SL |
30 | use traits; |
31 | use ty::{self, TraitRef, Ty, TypeAndMut}; | |
9e0c209e SL |
32 | use ty::{TyS, TypeVariants, Slice}; |
33 | use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; | |
54a0048b | 34 | use hir::FreevarMap; |
8bb4bdeb | 35 | use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; |
54a0048b SL |
36 | use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; |
37 | use ty::TypeVariants::*; | |
38 | use ty::layout::{Layout, TargetDataLayout}; | |
32a655c1 | 39 | use ty::inhabitedness::DefIdForest; |
54a0048b | 40 | use ty::maps; |
e9174d1e | 41 | use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; |
476ff2be | 42 | use util::nodemap::{FxHashMap, FxHashSet}; |
c30ab7b3 | 43 | use rustc_data_structures::accumulate_vec::AccumulateVec; |
e9174d1e | 44 | |
32a655c1 | 45 | use arena::{TypedArena, DroplessArena}; |
8bb4bdeb | 46 | use rustc_data_structures::indexed_vec::IndexVec; |
e9174d1e | 47 | use std::borrow::Borrow; |
c30ab7b3 | 48 | use std::cell::{Cell, RefCell}; |
e9174d1e | 49 | use std::hash::{Hash, Hasher}; |
a7813a04 XL |
50 | use std::mem; |
51 | use std::ops::Deref; | |
c30ab7b3 | 52 | use std::iter; |
476ff2be | 53 | use std::cmp::Ordering; |
8bb4bdeb | 54 | use syntax::abi; |
b039eaaf SL |
55 | use syntax::ast::{self, Name, NodeId}; |
56 | use syntax::attr; | |
476ff2be | 57 | use syntax::symbol::{Symbol, keywords}; |
e9174d1e | 58 | |
54a0048b | 59 | use hir; |
e9174d1e SL |
60 | |
61 | /// Internal storage | |
32a655c1 | 62 | pub struct GlobalArenas<'tcx> { |
e9174d1e | 63 | // internings |
54a0048b | 64 | layout: TypedArena<Layout>, |
e9174d1e SL |
65 | |
66 | // references | |
8bb4bdeb | 67 | generics: TypedArena<ty::Generics>, |
476ff2be SL |
68 | trait_def: TypedArena<ty::TraitDef>, |
69 | adt_def: TypedArena<ty::AdtDef>, | |
c30ab7b3 | 70 | mir: TypedArena<RefCell<Mir<'tcx>>>, |
32a655c1 | 71 | tables: TypedArena<ty::TypeckTables<'tcx>>, |
e9174d1e SL |
72 | } |
73 | ||
32a655c1 SL |
74 | impl<'tcx> GlobalArenas<'tcx> { |
75 | pub fn new() -> GlobalArenas<'tcx> { | |
76 | GlobalArenas { | |
54a0048b | 77 | layout: TypedArena::new(), |
9e0c209e | 78 | generics: TypedArena::new(), |
c30ab7b3 SL |
79 | trait_def: TypedArena::new(), |
80 | adt_def: TypedArena::new(), | |
32a655c1 SL |
81 | mir: TypedArena::new(), |
82 | tables: TypedArena::new(), | |
e9174d1e SL |
83 | } |
84 | } | |
85 | } | |
86 | ||
a7813a04 | 87 | pub struct CtxtInterners<'tcx> { |
32a655c1 SL |
88 | /// The arena that types, regions, etc are allocated from |
89 | arena: &'tcx DroplessArena, | |
a7813a04 XL |
90 | |
91 | /// Specifically use a speedy hash algorithm for these hash sets, | |
92 | /// they're accessed quite often. | |
476ff2be SL |
93 | type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>, |
94 | type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>, | |
95 | substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>, | |
476ff2be | 96 | region: RefCell<FxHashSet<Interned<'tcx, Region>>>, |
476ff2be | 97 | existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>, |
a7813a04 XL |
98 | } |
99 | ||
100 | impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { | |
32a655c1 | 101 | fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> { |
a7813a04 | 102 | CtxtInterners { |
32a655c1 | 103 | arena: arena, |
476ff2be SL |
104 | type_: RefCell::new(FxHashSet()), |
105 | type_list: RefCell::new(FxHashSet()), | |
106 | substs: RefCell::new(FxHashSet()), | |
476ff2be | 107 | region: RefCell::new(FxHashSet()), |
476ff2be | 108 | existential_predicates: RefCell::new(FxHashSet()), |
a7813a04 XL |
109 | } |
110 | } | |
111 | ||
112 | /// Intern a type. global_interners is Some only if this is | |
113 | /// a local interner and global_interners is its counterpart. | |
114 | fn intern_ty(&self, st: TypeVariants<'tcx>, | |
115 | global_interners: Option<&CtxtInterners<'gcx>>) | |
116 | -> Ty<'tcx> { | |
117 | let ty = { | |
118 | let mut interner = self.type_.borrow_mut(); | |
119 | let global_interner = global_interners.map(|interners| { | |
120 | interners.type_.borrow_mut() | |
121 | }); | |
122 | if let Some(&Interned(ty)) = interner.get(&st) { | |
123 | return ty; | |
124 | } | |
125 | if let Some(ref interner) = global_interner { | |
126 | if let Some(&Interned(ty)) = interner.get(&st) { | |
127 | return ty; | |
128 | } | |
129 | } | |
130 | ||
131 | let flags = super::flags::FlagComputation::for_sty(&st); | |
132 | let ty_struct = TyS { | |
133 | sty: st, | |
134 | flags: Cell::new(flags.flags), | |
135 | region_depth: flags.depth, | |
136 | }; | |
137 | ||
138 | // HACK(eddyb) Depend on flags being accurate to | |
139 | // determine that all contents are in the global tcx. | |
140 | // See comments on Lift for why we can't use that. | |
141 | if !flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) { | |
142 | if let Some(interner) = global_interners { | |
143 | let ty_struct: TyS<'gcx> = unsafe { | |
144 | mem::transmute(ty_struct) | |
145 | }; | |
32a655c1 | 146 | let ty: Ty<'gcx> = interner.arena.alloc(ty_struct); |
a7813a04 XL |
147 | global_interner.unwrap().insert(Interned(ty)); |
148 | return ty; | |
149 | } | |
150 | } else { | |
151 | // Make sure we don't end up with inference | |
152 | // types/regions in the global tcx. | |
153 | if global_interners.is_none() { | |
154 | drop(interner); | |
155 | bug!("Attempted to intern `{:?}` which contains \ | |
156 | inference types/regions in the global type context", | |
157 | &ty_struct); | |
158 | } | |
159 | } | |
160 | ||
161 | // Don't be &mut TyS. | |
32a655c1 | 162 | let ty: Ty<'tcx> = self.arena.alloc(ty_struct); |
a7813a04 XL |
163 | interner.insert(Interned(ty)); |
164 | ty | |
165 | }; | |
166 | ||
167 | debug!("Interned type: {:?} Pointer: {:?}", | |
168 | ty, ty as *const TyS); | |
169 | ty | |
170 | } | |
171 | ||
172 | } | |
173 | ||
e9174d1e SL |
174 | pub struct CommonTypes<'tcx> { |
175 | pub bool: Ty<'tcx>, | |
176 | pub char: Ty<'tcx>, | |
177 | pub isize: Ty<'tcx>, | |
178 | pub i8: Ty<'tcx>, | |
179 | pub i16: Ty<'tcx>, | |
180 | pub i32: Ty<'tcx>, | |
181 | pub i64: Ty<'tcx>, | |
32a655c1 | 182 | pub i128: Ty<'tcx>, |
e9174d1e SL |
183 | pub usize: Ty<'tcx>, |
184 | pub u8: Ty<'tcx>, | |
185 | pub u16: Ty<'tcx>, | |
186 | pub u32: Ty<'tcx>, | |
187 | pub u64: Ty<'tcx>, | |
32a655c1 | 188 | pub u128: Ty<'tcx>, |
e9174d1e SL |
189 | pub f32: Ty<'tcx>, |
190 | pub f64: Ty<'tcx>, | |
5bcae85e | 191 | pub never: Ty<'tcx>, |
e9174d1e SL |
192 | pub err: Ty<'tcx>, |
193 | } | |
194 | ||
32a655c1 SL |
195 | #[derive(RustcEncodable, RustcDecodable)] |
196 | pub struct TypeckTables<'tcx> { | |
476ff2be SL |
197 | /// Resolved definitions for `<T>::X` associated paths. |
198 | pub type_relative_path_defs: NodeMap<Def>, | |
199 | ||
e9174d1e SL |
200 | /// Stores the types for various nodes in the AST. Note that this table |
201 | /// is not guaranteed to be populated until after typeck. See | |
202 | /// typeck::check::fn_ctxt for details. | |
203 | pub node_types: NodeMap<Ty<'tcx>>, | |
204 | ||
205 | /// Stores the type parameters which were substituted to obtain the type | |
206 | /// of this node. This only applies to nodes that refer to entities | |
207 | /// parameterized by type parameters, such as generic fns, types, or | |
208 | /// other items. | |
209 | pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>, | |
210 | ||
c30ab7b3 | 211 | pub adjustments: NodeMap<ty::adjustment::Adjustment<'tcx>>, |
e9174d1e SL |
212 | |
213 | pub method_map: ty::MethodMap<'tcx>, | |
214 | ||
215 | /// Borrows | |
9e0c209e | 216 | pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, |
e9174d1e | 217 | |
32a655c1 | 218 | /// Records the type of each closure. |
8bb4bdeb | 219 | pub closure_tys: NodeMap<ty::PolyFnSig<'tcx>>, |
e9174d1e | 220 | |
8bb4bdeb | 221 | /// Records the kind of each closure. |
32a655c1 | 222 | pub closure_kinds: NodeMap<ty::ClosureKind>, |
92a42be0 SL |
223 | |
224 | /// For each fn, records the "liberated" types of its arguments | |
225 | /// and return type. Liberated means that all bound regions | |
226 | /// (including late-bound regions) are replaced with free | |
227 | /// equivalents. This table is not used in trans (since regions | |
228 | /// are erased there) and hence is not serialized to metadata. | |
229 | pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>, | |
7453a54e SL |
230 | |
231 | /// For each FRU expression, record the normalized types of the fields | |
232 | /// of the struct - this is needed because it is non-trivial to | |
233 | /// normalize while preserving regions. This table is used only in | |
234 | /// MIR construction and hence is not serialized to metadata. | |
32a655c1 SL |
235 | pub fru_field_types: NodeMap<Vec<Ty<'tcx>>>, |
236 | ||
237 | /// Maps a cast expression to its kind. This is keyed on the | |
238 | /// *from* expression of the cast, not the cast itself. | |
239 | pub cast_kinds: NodeMap<ty::cast::CastKind>, | |
8bb4bdeb XL |
240 | |
241 | /// Lints for the body of this fn generated by typeck. | |
242 | pub lints: lint::LintTable, | |
243 | ||
244 | /// Set of trait imports actually used in the method resolution. | |
245 | /// This is used for warning unused imports. | |
246 | pub used_trait_imports: DefIdSet, | |
247 | ||
248 | /// If any errors occurred while type-checking this body, | |
249 | /// this field will be set to `true`. | |
250 | pub tainted_by_errors: bool, | |
251 | ||
252 | /// Stores the free-region relationships that were deduced from | |
253 | /// its where clauses and parameter types. These are then | |
254 | /// read-again by borrowck. | |
255 | pub free_region_map: FreeRegionMap, | |
e9174d1e SL |
256 | } |
257 | ||
32a655c1 SL |
258 | impl<'tcx> TypeckTables<'tcx> { |
259 | pub fn empty() -> TypeckTables<'tcx> { | |
260 | TypeckTables { | |
476ff2be SL |
261 | type_relative_path_defs: NodeMap(), |
262 | node_types: FxHashMap(), | |
e9174d1e SL |
263 | item_substs: NodeMap(), |
264 | adjustments: NodeMap(), | |
476ff2be SL |
265 | method_map: FxHashMap(), |
266 | upvar_capture_map: FxHashMap(), | |
32a655c1 SL |
267 | closure_tys: NodeMap(), |
268 | closure_kinds: NodeMap(), | |
92a42be0 | 269 | liberated_fn_sigs: NodeMap(), |
32a655c1 SL |
270 | fru_field_types: NodeMap(), |
271 | cast_kinds: NodeMap(), | |
8bb4bdeb XL |
272 | lints: lint::LintTable::new(), |
273 | used_trait_imports: DefIdSet(), | |
274 | tainted_by_errors: false, | |
275 | free_region_map: FreeRegionMap::new(), | |
e9174d1e SL |
276 | } |
277 | } | |
c30ab7b3 | 278 | |
476ff2be SL |
279 | /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node. |
280 | pub fn qpath_def(&self, qpath: &hir::QPath, id: NodeId) -> Def { | |
281 | match *qpath { | |
282 | hir::QPath::Resolved(_, ref path) => path.def, | |
283 | hir::QPath::TypeRelative(..) => { | |
284 | self.type_relative_path_defs.get(&id).cloned().unwrap_or(Def::Err) | |
285 | } | |
286 | } | |
287 | } | |
288 | ||
c30ab7b3 SL |
289 | pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> { |
290 | match self.node_id_to_type_opt(id) { | |
291 | Some(ty) => ty, | |
292 | None => { | |
293 | bug!("node_id_to_type: no type for node `{}`", | |
32a655c1 | 294 | tls::with(|tcx| tcx.hir.node_to_string(id))) |
c30ab7b3 SL |
295 | } |
296 | } | |
297 | } | |
298 | ||
299 | pub fn node_id_to_type_opt(&self, id: NodeId) -> Option<Ty<'tcx>> { | |
300 | self.node_types.get(&id).cloned() | |
301 | } | |
302 | ||
303 | pub fn node_id_item_substs(&self, id: NodeId) -> Option<&'tcx Substs<'tcx>> { | |
304 | self.item_substs.get(&id).map(|ts| ts.substs) | |
305 | } | |
306 | ||
307 | // Returns the type of a pattern as a monotype. Like @expr_ty, this function | |
308 | // doesn't provide type parameter substitutions. | |
309 | pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { | |
310 | self.node_id_to_type(pat.id) | |
311 | } | |
312 | ||
313 | pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> { | |
314 | self.node_id_to_type_opt(pat.id) | |
315 | } | |
316 | ||
317 | // Returns the type of an expression as a monotype. | |
318 | // | |
319 | // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in | |
320 | // some cases, we insert `Adjustment` annotations such as auto-deref or | |
321 | // auto-ref. The type returned by this function does not consider such | |
322 | // adjustments. See `expr_ty_adjusted()` instead. | |
323 | // | |
324 | // NB (2): This type doesn't provide type parameter substitutions; e.g. if you | |
325 | // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" | |
326 | // instead of "fn(ty) -> T with T = isize". | |
327 | pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> { | |
328 | self.node_id_to_type(expr.id) | |
329 | } | |
330 | ||
331 | pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> { | |
332 | self.node_id_to_type_opt(expr.id) | |
333 | } | |
334 | ||
335 | /// Returns the type of `expr`, considering any `Adjustment` | |
336 | /// entry recorded for that expression. | |
337 | pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> { | |
338 | self.adjustments.get(&expr.id) | |
339 | .map_or_else(|| self.expr_ty(expr), |adj| adj.target) | |
340 | } | |
341 | ||
342 | pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> { | |
343 | self.adjustments.get(&expr.id) | |
344 | .map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr)) | |
345 | } | |
346 | ||
347 | pub fn is_method_call(&self, expr_id: NodeId) -> bool { | |
348 | self.method_map.contains_key(&ty::MethodCall::expr(expr_id)) | |
349 | } | |
350 | ||
351 | pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool { | |
352 | self.method_map.contains_key(&ty::MethodCall::autoderef(expr_id, autoderefs)) | |
353 | } | |
354 | ||
355 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> { | |
356 | Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone()) | |
357 | } | |
e9174d1e SL |
358 | } |
359 | ||
360 | impl<'tcx> CommonTypes<'tcx> { | |
a7813a04 XL |
361 | fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { |
362 | let mk = |sty| interners.intern_ty(sty, None); | |
e9174d1e SL |
363 | CommonTypes { |
364 | bool: mk(TyBool), | |
365 | char: mk(TyChar), | |
5bcae85e | 366 | never: mk(TyNever), |
e9174d1e | 367 | err: mk(TyError), |
7453a54e SL |
368 | isize: mk(TyInt(ast::IntTy::Is)), |
369 | i8: mk(TyInt(ast::IntTy::I8)), | |
370 | i16: mk(TyInt(ast::IntTy::I16)), | |
371 | i32: mk(TyInt(ast::IntTy::I32)), | |
372 | i64: mk(TyInt(ast::IntTy::I64)), | |
32a655c1 | 373 | i128: mk(TyInt(ast::IntTy::I128)), |
7453a54e SL |
374 | usize: mk(TyUint(ast::UintTy::Us)), |
375 | u8: mk(TyUint(ast::UintTy::U8)), | |
376 | u16: mk(TyUint(ast::UintTy::U16)), | |
377 | u32: mk(TyUint(ast::UintTy::U32)), | |
378 | u64: mk(TyUint(ast::UintTy::U64)), | |
32a655c1 | 379 | u128: mk(TyUint(ast::UintTy::U128)), |
7453a54e SL |
380 | f32: mk(TyFloat(ast::FloatTy::F32)), |
381 | f64: mk(TyFloat(ast::FloatTy::F64)), | |
e9174d1e SL |
382 | } |
383 | } | |
384 | } | |
385 | ||
386 | /// The data structure to keep track of all the information that typechecker | |
387 | /// generates so that so that it can be reused and doesn't have to be redone | |
388 | /// later on. | |
a7813a04 XL |
389 | #[derive(Copy, Clone)] |
390 | pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
391 | gcx: &'a GlobalCtxt<'gcx>, | |
392 | interners: &'a CtxtInterners<'tcx> | |
393 | } | |
e9174d1e | 394 | |
a7813a04 XL |
395 | impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> { |
396 | type Target = &'a GlobalCtxt<'gcx>; | |
397 | fn deref(&self) -> &Self::Target { | |
398 | &self.gcx | |
399 | } | |
400 | } | |
401 | ||
402 | pub struct GlobalCtxt<'tcx> { | |
32a655c1 | 403 | global_arenas: &'tcx GlobalArenas<'tcx>, |
a7813a04 | 404 | global_interners: CtxtInterners<'tcx>, |
e9174d1e | 405 | |
8bb4bdeb XL |
406 | pub sess: &'tcx Session, |
407 | ||
a7813a04 | 408 | pub specializes_cache: RefCell<traits::SpecializesCache>, |
e9174d1e | 409 | |
9cc50fc6 SL |
410 | pub dep_graph: DepGraph, |
411 | ||
e9174d1e SL |
412 | /// Common types, pre-interned for your convenience. |
413 | pub types: CommonTypes<'tcx>, | |
414 | ||
5bcae85e SL |
415 | /// Map indicating what traits are in scope for places where this |
416 | /// is relevant; generated by resolve. | |
417 | pub trait_map: TraitMap, | |
418 | ||
e9174d1e SL |
419 | pub named_region_map: resolve_lifetime::NamedRegionMap, |
420 | ||
421 | pub region_maps: RegionMaps, | |
422 | ||
32a655c1 | 423 | pub hir: hir_map::Map<'tcx>, |
8bb4bdeb | 424 | pub maps: maps::Maps<'tcx>, |
c30ab7b3 | 425 | |
9cc50fc6 SL |
426 | // Records the free variables refrenced by every closure |
427 | // expression. Do not track deps for this, just recompute it from | |
428 | // scratch every time. | |
e9174d1e | 429 | pub freevars: RefCell<FreevarMap>, |
9cc50fc6 | 430 | |
a7813a04 XL |
431 | pub maybe_unused_trait_imports: NodeSet, |
432 | ||
9cc50fc6 | 433 | // Internal cache for metadata decoding. No need to track deps on this. |
476ff2be | 434 | pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>, |
9cc50fc6 SL |
435 | |
436 | // Cache for the type-contents routine. FIXME -- track deps? | |
476ff2be | 437 | pub tc_cache: RefCell<FxHashMap<Ty<'tcx>, ty::contents::TypeContents>>, |
9cc50fc6 | 438 | |
9cc50fc6 | 439 | // FIXME dep tracking -- should be harmless enough |
476ff2be | 440 | pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>, |
9cc50fc6 | 441 | |
32a655c1 SL |
442 | pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>, |
443 | ||
e9174d1e | 444 | pub lang_items: middle::lang_items::LanguageItems, |
e9174d1e | 445 | |
e9174d1e SL |
446 | /// True if the variance has been computed yet; false otherwise. |
447 | pub variance_computed: Cell<bool>, | |
448 | ||
e9174d1e SL |
449 | /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not |
450 | /// present in this set can be warned about. | |
451 | pub used_unsafe: RefCell<NodeSet>, | |
452 | ||
453 | /// Set of nodes which mark locals as mutable which end up getting used at | |
454 | /// some point. Local variable definitions not in this set can be warned | |
455 | /// about. | |
456 | pub used_mut_nodes: RefCell<NodeSet>, | |
457 | ||
458 | /// The set of external nominal types whose implementations have been read. | |
459 | /// This is used for lazy resolution of methods. | |
460 | pub populated_external_types: RefCell<DefIdSet>, | |
9cc50fc6 | 461 | |
e9174d1e SL |
462 | /// The set of external primitive types whose implementations have been read. |
463 | /// FIXME(arielb1): why is this separate from populated_external_types? | |
464 | pub populated_external_primitive_impls: RefCell<DefIdSet>, | |
465 | ||
e9174d1e SL |
466 | /// Maps any item's def-id to its stability index. |
467 | pub stability: RefCell<stability::Index<'tcx>>, | |
468 | ||
469 | /// Caches the results of trait selection. This cache is used | |
470 | /// for things that do not have to do with the parameters in scope. | |
471 | pub selection_cache: traits::SelectionCache<'tcx>, | |
472 | ||
92a42be0 SL |
473 | /// Caches the results of trait evaluation. This cache is used |
474 | /// for things that do not have to do with the parameters in scope. | |
475 | /// Merge this with `selection_cache`? | |
476 | pub evaluation_cache: traits::EvaluationCache<'tcx>, | |
477 | ||
e9174d1e SL |
478 | /// A set of predicates that have been fulfilled *somewhere*. |
479 | /// This is used to avoid duplicate work. Predicates are only | |
480 | /// added to this set when they mention only "global" names | |
481 | /// (i.e., no type or lifetime parameters). | |
7453a54e | 482 | pub fulfilled_predicates: RefCell<traits::GlobalFulfilledPredicates<'tcx>>, |
e9174d1e | 483 | |
32a655c1 SL |
484 | /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. |
485 | pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>, | |
e9174d1e | 486 | |
e9174d1e SL |
487 | /// Maps Fn items to a collection of fragment infos. |
488 | /// | |
489 | /// The main goal is to identify data (each of which may be moved | |
490 | /// or assigned) whose subparts are not moved nor assigned | |
491 | /// (i.e. their state is *unfragmented*) and corresponding ast | |
492 | /// nodes where the path to that data is moved or assigned. | |
493 | /// | |
494 | /// In the long term, unfragmented values will have their | |
495 | /// destructor entirely driven by a single stack-local drop-flag, | |
496 | /// and their parents, the collections of the unfragmented values | |
497 | /// (or more simply, "fragmented values"), are mapped to the | |
498 | /// corresponding collections of stack-local drop-flags. | |
499 | /// | |
500 | /// (However, in the short term that is not the case; e.g. some | |
501 | /// unfragmented paths still need to be zeroed, namely when they | |
502 | /// reference parent data from an outer scope that was not | |
503 | /// entirely moved, and therefore that needs to be zeroed so that | |
504 | /// we do not get double-drop when we hit the end of the parent | |
505 | /// scope.) | |
506 | /// | |
507 | /// Also: currently the table solely holds keys for node-ids of | |
508 | /// unfragmented values (see `FragmentInfo` enum definition), but | |
509 | /// longer-term we will need to also store mappings from | |
510 | /// fragmented data to the set of unfragmented pieces that | |
511 | /// constitute it. | |
512 | pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>, | |
54a0048b SL |
513 | |
514 | /// The definite name of the current crate after taking into account | |
515 | /// attributes, commandline parameters, etc. | |
476ff2be | 516 | pub crate_name: Symbol, |
54a0048b SL |
517 | |
518 | /// Data layout specification for the current target. | |
519 | pub data_layout: TargetDataLayout, | |
520 | ||
521 | /// Cache for layouts computed from types. | |
476ff2be | 522 | pub layout_cache: RefCell<FxHashMap<Ty<'tcx>, &'tcx Layout>>, |
9e0c209e SL |
523 | |
524 | /// Used to prevent layout from recursing too deeply. | |
525 | pub layout_depth: Cell<usize>, | |
526 | ||
527 | /// Map from function to the `#[derive]` mode that it's defining. Only used | |
c30ab7b3 | 528 | /// by `proc-macro` crates. |
476ff2be | 529 | pub derive_macros: RefCell<NodeMap<Symbol>>, |
32a655c1 SL |
530 | |
531 | stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>, | |
532 | ||
533 | layout_interner: RefCell<FxHashSet<&'tcx Layout>>, | |
8bb4bdeb XL |
534 | |
535 | /// A vector of every trait accessible in the whole crate | |
536 | /// (i.e. including those from subcrates). This is used only for | |
537 | /// error reporting, and so is lazily initialised and generally | |
538 | /// shouldn't taint the common path (hence the RefCell). | |
539 | pub all_traits: RefCell<Option<Vec<DefId>>>, | |
540 | ||
541 | /// HIR Ty -> Ty lowering cache. | |
542 | pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>, | |
e9174d1e | 543 | } |
e9174d1e | 544 | |
a7813a04 XL |
545 | impl<'tcx> GlobalCtxt<'tcx> { |
546 | /// Get the global TyCtxt. | |
547 | pub fn global_tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { | |
548 | TyCtxt { | |
549 | gcx: self, | |
550 | interners: &self.global_interners | |
551 | } | |
552 | } | |
553 | } | |
554 | ||
555 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { | |
476ff2be | 556 | pub fn crate_name(self, cnum: CrateNum) -> Symbol { |
54a0048b | 557 | if cnum == LOCAL_CRATE { |
476ff2be | 558 | self.crate_name |
54a0048b SL |
559 | } else { |
560 | self.sess.cstore.crate_name(cnum) | |
561 | } | |
562 | } | |
563 | ||
476ff2be | 564 | pub fn original_crate_name(self, cnum: CrateNum) -> Symbol { |
9e0c209e SL |
565 | if cnum == LOCAL_CRATE { |
566 | self.crate_name.clone() | |
567 | } else { | |
568 | self.sess.cstore.original_crate_name(cnum) | |
569 | } | |
570 | } | |
571 | ||
476ff2be | 572 | pub fn crate_disambiguator(self, cnum: CrateNum) -> Symbol { |
54a0048b | 573 | if cnum == LOCAL_CRATE { |
5bcae85e | 574 | self.sess.local_crate_disambiguator() |
54a0048b SL |
575 | } else { |
576 | self.sess.cstore.crate_disambiguator(cnum) | |
577 | } | |
578 | } | |
579 | ||
c30ab7b3 SL |
580 | pub fn retrace_path(self, |
581 | krate: CrateNum, | |
582 | path_data: &[DisambiguatedDefPathData]) | |
583 | -> Option<DefId> { | |
584 | debug!("retrace_path(path={:?}, krate={:?})", path_data, self.crate_name(krate)); | |
a7813a04 | 585 | |
32a655c1 SL |
586 | if krate == LOCAL_CRATE { |
587 | self.hir | |
588 | .definitions() | |
589 | .def_path_table() | |
590 | .retrace_path(path_data) | |
591 | .map(|def_index| DefId { krate: krate, index: def_index }) | |
592 | } else { | |
593 | self.sess.cstore.retrace_path(krate, path_data) | |
a7813a04 | 594 | } |
a7813a04 XL |
595 | } |
596 | ||
8bb4bdeb | 597 | pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics { |
32a655c1 | 598 | self.global_arenas.generics.alloc(generics) |
9e0c209e SL |
599 | } |
600 | ||
c30ab7b3 | 601 | pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> { |
32a655c1 SL |
602 | self.global_arenas.mir.alloc(RefCell::new(mir)) |
603 | } | |
604 | ||
605 | pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> { | |
606 | self.global_arenas.tables.alloc(tables) | |
c30ab7b3 SL |
607 | } |
608 | ||
476ff2be | 609 | pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef { |
32a655c1 | 610 | self.global_arenas.trait_def.alloc(def) |
e9174d1e SL |
611 | } |
612 | ||
476ff2be SL |
613 | pub fn alloc_adt_def(self, |
614 | did: DefId, | |
615 | kind: AdtKind, | |
8bb4bdeb XL |
616 | variants: Vec<ty::VariantDef>, |
617 | repr: ReprOptions) | |
476ff2be | 618 | -> &'gcx ty::AdtDef { |
8bb4bdeb | 619 | let def = ty::AdtDef::new(self, did, kind, variants, repr); |
32a655c1 | 620 | self.global_arenas.adt_def.alloc(def) |
e9174d1e SL |
621 | } |
622 | ||
a7813a04 | 623 | pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability { |
32a655c1 | 624 | if let Some(st) = self.stability_interner.borrow().get(&stab) { |
e9174d1e SL |
625 | return st; |
626 | } | |
627 | ||
32a655c1 SL |
628 | let interned = self.global_interners.arena.alloc(stab); |
629 | if let Some(prev) = self.stability_interner.borrow_mut().replace(interned) { | |
54a0048b SL |
630 | bug!("Tried to overwrite interned Stability: {:?}", prev) |
631 | } | |
632 | interned | |
633 | } | |
634 | ||
a7813a04 | 635 | pub fn intern_layout(self, layout: Layout) -> &'gcx Layout { |
32a655c1 | 636 | if let Some(layout) = self.layout_interner.borrow().get(&layout) { |
54a0048b SL |
637 | return layout; |
638 | } | |
639 | ||
32a655c1 SL |
640 | let interned = self.global_arenas.layout.alloc(layout); |
641 | if let Some(prev) = self.layout_interner.borrow_mut().replace(interned) { | |
54a0048b | 642 | bug!("Tried to overwrite interned Layout: {:?}", prev) |
92a42be0 | 643 | } |
e9174d1e SL |
644 | interned |
645 | } | |
646 | ||
a7813a04 | 647 | pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> { |
e9174d1e SL |
648 | value.lift_to_tcx(self) |
649 | } | |
650 | ||
a7813a04 XL |
651 | /// Like lift, but only tries in the global tcx. |
652 | pub fn lift_to_global<T: ?Sized + Lift<'gcx>>(self, value: &T) -> Option<T::Lifted> { | |
653 | value.lift_to_tcx(self.global_tcx()) | |
654 | } | |
655 | ||
656 | /// Returns true if self is the same as self.global_tcx(). | |
657 | fn is_global(self) -> bool { | |
658 | let local = self.interners as *const _; | |
659 | let global = &self.global_interners as *const _; | |
660 | local as usize == global as usize | |
661 | } | |
662 | ||
663 | /// Create a type context and call the closure with a `TyCtxt` reference | |
e9174d1e SL |
664 | /// to the context. The closure enforces that the type context and any interned |
665 | /// value (types, substs, etc.) can only be used while `ty::tls` has a valid | |
666 | /// reference to the context, to allow formatting values that need it. | |
b039eaaf | 667 | pub fn create_and_enter<F, R>(s: &'tcx Session, |
8bb4bdeb XL |
668 | local_providers: ty::maps::Providers<'tcx>, |
669 | extern_providers: ty::maps::Providers<'tcx>, | |
32a655c1 SL |
670 | arenas: &'tcx GlobalArenas<'tcx>, |
671 | arena: &'tcx DroplessArena, | |
672 | resolutions: ty::Resolutions, | |
a7813a04 | 673 | named_region_map: resolve_lifetime::NamedRegionMap, |
32a655c1 | 674 | hir: hir_map::Map<'tcx>, |
a7813a04 XL |
675 | region_maps: RegionMaps, |
676 | lang_items: middle::lang_items::LanguageItems, | |
677 | stability: stability::Index<'tcx>, | |
32a655c1 | 678 | crate_name: &str, |
a7813a04 XL |
679 | f: F) -> R |
680 | where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R | |
e9174d1e | 681 | { |
54a0048b | 682 | let data_layout = TargetDataLayout::parse(s); |
32a655c1 | 683 | let interners = CtxtInterners::new(arena); |
a7813a04 | 684 | let common_types = CommonTypes::new(&interners); |
32a655c1 | 685 | let dep_graph = hir.dep_graph.clone(); |
7453a54e | 686 | let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone()); |
8bb4bdeb XL |
687 | let max_cnum = s.cstore.crates().iter().map(|c| c.as_usize()).max().unwrap_or(0); |
688 | let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); | |
689 | providers[LOCAL_CRATE] = local_providers; | |
a7813a04 | 690 | tls::enter_global(GlobalCtxt { |
8bb4bdeb | 691 | sess: s, |
a7813a04 | 692 | specializes_cache: RefCell::new(traits::SpecializesCache::new()), |
32a655c1 | 693 | global_arenas: arenas, |
a7813a04 | 694 | global_interners: interners, |
9cc50fc6 | 695 | dep_graph: dep_graph.clone(), |
e9174d1e SL |
696 | types: common_types, |
697 | named_region_map: named_region_map, | |
698 | region_maps: region_maps, | |
e9174d1e | 699 | variance_computed: Cell::new(false), |
32a655c1 | 700 | trait_map: resolutions.trait_map, |
7453a54e | 701 | fulfilled_predicates: RefCell::new(fulfilled_predicates), |
32a655c1 | 702 | hir: hir, |
8bb4bdeb | 703 | maps: maps::Maps::new(dep_graph, providers), |
32a655c1 SL |
704 | freevars: RefCell::new(resolutions.freevars), |
705 | maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, | |
476ff2be SL |
706 | rcache: RefCell::new(FxHashMap()), |
707 | tc_cache: RefCell::new(FxHashMap()), | |
476ff2be | 708 | normalized_cache: RefCell::new(FxHashMap()), |
32a655c1 | 709 | inhabitedness_cache: RefCell::new(FxHashMap()), |
e9174d1e | 710 | lang_items: lang_items, |
e9174d1e SL |
711 | used_unsafe: RefCell::new(NodeSet()), |
712 | used_mut_nodes: RefCell::new(NodeSet()), | |
713 | populated_external_types: RefCell::new(DefIdSet()), | |
714 | populated_external_primitive_impls: RefCell::new(DefIdSet()), | |
e9174d1e SL |
715 | stability: RefCell::new(stability), |
716 | selection_cache: traits::SelectionCache::new(), | |
92a42be0 | 717 | evaluation_cache: traits::EvaluationCache::new(), |
32a655c1 | 718 | rvalue_promotable_to_static: RefCell::new(NodeMap()), |
54a0048b | 719 | fragment_infos: RefCell::new(DefIdMap()), |
476ff2be | 720 | crate_name: Symbol::intern(crate_name), |
54a0048b | 721 | data_layout: data_layout, |
476ff2be | 722 | layout_cache: RefCell::new(FxHashMap()), |
32a655c1 | 723 | layout_interner: RefCell::new(FxHashSet()), |
9e0c209e SL |
724 | layout_depth: Cell::new(0), |
725 | derive_macros: RefCell::new(NodeMap()), | |
32a655c1 | 726 | stability_interner: RefCell::new(FxHashSet()), |
8bb4bdeb XL |
727 | all_traits: RefCell::new(None), |
728 | ast_ty_to_ty_cache: RefCell::new(NodeMap()), | |
e9174d1e SL |
729 | }, f) |
730 | } | |
731 | } | |
732 | ||
a7813a04 | 733 | impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { |
32a655c1 SL |
734 | /// Call the closure with a local `TyCtxt` using the given arena. |
735 | pub fn enter_local<F, R>(&self, arena: &'tcx DroplessArena, f: F) -> R | |
a7813a04 XL |
736 | where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R |
737 | { | |
32a655c1 | 738 | let interners = CtxtInterners::new(arena); |
a7813a04 XL |
739 | tls::enter(self, &interners, f) |
740 | } | |
741 | } | |
742 | ||
e9174d1e SL |
743 | /// A trait implemented for all X<'a> types which can be safely and |
744 | /// efficiently converted to X<'tcx> as long as they are part of the | |
54a0048b | 745 | /// provided TyCtxt<'tcx>. |
e9174d1e SL |
746 | /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx> |
747 | /// by looking them up in their respective interners. | |
a7813a04 XL |
748 | /// |
749 | /// However, this is still not the best implementation as it does | |
750 | /// need to compare the components, even for interned values. | |
751 | /// It would be more efficient if TypedArena provided a way to | |
752 | /// determine whether the address is in the allocated range. | |
753 | /// | |
e9174d1e SL |
754 | /// None is returned if the value or one of the components is not part |
755 | /// of the provided context. | |
756 | /// For Ty, None can be returned if either the type interner doesn't | |
757 | /// contain the TypeVariants key or if the address of the interned | |
758 | /// pointer differs. The latter case is possible if a primitive type, | |
759 | /// e.g. `()` or `u8`, was interned in a different context. | |
760 | pub trait Lift<'tcx> { | |
761 | type Lifted; | |
a7813a04 | 762 | fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>; |
e9174d1e SL |
763 | } |
764 | ||
765 | impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { | |
766 | type Lifted = Ty<'tcx>; | |
a7813a04 | 767 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> { |
32a655c1 SL |
768 | if tcx.interners.arena.in_arena(*self as *const _) { |
769 | return Some(unsafe { mem::transmute(*self) }); | |
e9174d1e | 770 | } |
a7813a04 XL |
771 | // Also try in the global tcx if we're not that. |
772 | if !tcx.is_global() { | |
773 | self.lift_to_tcx(tcx.global_tcx()) | |
774 | } else { | |
775 | None | |
776 | } | |
e9174d1e SL |
777 | } |
778 | } | |
779 | ||
780 | impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { | |
781 | type Lifted = &'tcx Substs<'tcx>; | |
a7813a04 | 782 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> { |
c30ab7b3 SL |
783 | if self.len() == 0 { |
784 | return Some(Slice::empty()); | |
785 | } | |
32a655c1 SL |
786 | if tcx.interners.arena.in_arena(&self[..] as *const _) { |
787 | return Some(unsafe { mem::transmute(*self) }); | |
e9174d1e | 788 | } |
a7813a04 XL |
789 | // Also try in the global tcx if we're not that. |
790 | if !tcx.is_global() { | |
791 | self.lift_to_tcx(tcx.global_tcx()) | |
792 | } else { | |
793 | None | |
794 | } | |
795 | } | |
796 | } | |
797 | ||
798 | impl<'a, 'tcx> Lift<'tcx> for &'a Region { | |
799 | type Lifted = &'tcx Region; | |
800 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> { | |
32a655c1 SL |
801 | if tcx.interners.arena.in_arena(*self as *const _) { |
802 | return Some(unsafe { mem::transmute(*self) }); | |
a7813a04 XL |
803 | } |
804 | // Also try in the global tcx if we're not that. | |
805 | if !tcx.is_global() { | |
806 | self.lift_to_tcx(tcx.global_tcx()) | |
807 | } else { | |
808 | None | |
809 | } | |
810 | } | |
811 | } | |
812 | ||
9e0c209e SL |
813 | impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> { |
814 | type Lifted = &'tcx Slice<Ty<'tcx>>; | |
815 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) | |
816 | -> Option<&'tcx Slice<Ty<'tcx>>> { | |
c30ab7b3 SL |
817 | if self.len() == 0 { |
818 | return Some(Slice::empty()); | |
819 | } | |
32a655c1 SL |
820 | if tcx.interners.arena.in_arena(*self as *const _) { |
821 | return Some(unsafe { mem::transmute(*self) }); | |
a7813a04 XL |
822 | } |
823 | // Also try in the global tcx if we're not that. | |
824 | if !tcx.is_global() { | |
825 | self.lift_to_tcx(tcx.global_tcx()) | |
826 | } else { | |
827 | None | |
828 | } | |
829 | } | |
830 | } | |
831 | ||
476ff2be SL |
832 | impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> { |
833 | type Lifted = &'tcx Slice<ExistentialPredicate<'tcx>>; | |
834 | fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) | |
835 | -> Option<&'tcx Slice<ExistentialPredicate<'tcx>>> { | |
836 | if self.is_empty() { | |
837 | return Some(Slice::empty()); | |
838 | } | |
32a655c1 SL |
839 | if tcx.interners.arena.in_arena(*self as *const _) { |
840 | return Some(unsafe { mem::transmute(*self) }); | |
476ff2be SL |
841 | } |
842 | // Also try in the global tcx if we're not that. | |
843 | if !tcx.is_global() { | |
844 | self.lift_to_tcx(tcx.global_tcx()) | |
845 | } else { | |
846 | None | |
847 | } | |
848 | } | |
849 | } | |
850 | ||
e9174d1e | 851 | pub mod tls { |
a7813a04 | 852 | use super::{CtxtInterners, GlobalCtxt, TyCtxt}; |
e9174d1e | 853 | |
7453a54e | 854 | use std::cell::Cell; |
e9174d1e | 855 | use std::fmt; |
3157f602 | 856 | use syntax_pos; |
e9174d1e | 857 | |
a7813a04 | 858 | /// Marker types used for the scoped TLS slot. |
e9174d1e SL |
859 | /// The type context cannot be used directly because the scoped TLS |
860 | /// in libstd doesn't allow types generic over lifetimes. | |
a7813a04 XL |
861 | enum ThreadLocalGlobalCtxt {} |
862 | enum ThreadLocalInterners {} | |
e9174d1e | 863 | |
7453a54e | 864 | thread_local! { |
a7813a04 XL |
865 | static TLS_TCX: Cell<Option<(*const ThreadLocalGlobalCtxt, |
866 | *const ThreadLocalInterners)>> = Cell::new(None) | |
7453a54e | 867 | } |
e9174d1e | 868 | |
3157f602 | 869 | fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter) -> fmt::Result { |
e9174d1e SL |
870 | with(|tcx| { |
871 | write!(f, "{}", tcx.sess.codemap().span_to_string(span)) | |
872 | }) | |
873 | } | |
874 | ||
a7813a04 XL |
875 | pub fn enter_global<'gcx, F, R>(gcx: GlobalCtxt<'gcx>, f: F) -> R |
876 | where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R | |
877 | { | |
3157f602 | 878 | syntax_pos::SPAN_DEBUG.with(|span_dbg| { |
e9174d1e SL |
879 | let original_span_debug = span_dbg.get(); |
880 | span_dbg.set(span_debug); | |
a7813a04 | 881 | let result = enter(&gcx, &gcx.global_interners, f); |
e9174d1e SL |
882 | span_dbg.set(original_span_debug); |
883 | result | |
b039eaaf | 884 | }) |
e9174d1e SL |
885 | } |
886 | ||
a7813a04 XL |
887 | pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(gcx: &'a GlobalCtxt<'gcx>, |
888 | interners: &'a CtxtInterners<'tcx>, | |
889 | f: F) -> R | |
890 | where F: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
891 | { | |
892 | let gcx_ptr = gcx as *const _ as *const ThreadLocalGlobalCtxt; | |
893 | let interners_ptr = interners as *const _ as *const ThreadLocalInterners; | |
894 | TLS_TCX.with(|tls| { | |
895 | let prev = tls.get(); | |
896 | tls.set(Some((gcx_ptr, interners_ptr))); | |
897 | let ret = f(TyCtxt { | |
898 | gcx: gcx, | |
899 | interners: interners | |
900 | }); | |
901 | tls.set(prev); | |
902 | ret | |
903 | }) | |
904 | } | |
905 | ||
906 | pub fn with<F, R>(f: F) -> R | |
907 | where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R | |
908 | { | |
7453a54e | 909 | TLS_TCX.with(|tcx| { |
a7813a04 XL |
910 | let (gcx, interners) = tcx.get().unwrap(); |
911 | let gcx = unsafe { &*(gcx as *const GlobalCtxt) }; | |
912 | let interners = unsafe { &*(interners as *const CtxtInterners) }; | |
913 | f(TyCtxt { | |
914 | gcx: gcx, | |
915 | interners: interners | |
916 | }) | |
7453a54e | 917 | }) |
e9174d1e SL |
918 | } |
919 | ||
a7813a04 XL |
920 | pub fn with_opt<F, R>(f: F) -> R |
921 | where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R | |
922 | { | |
7453a54e | 923 | if TLS_TCX.with(|tcx| tcx.get().is_some()) { |
e9174d1e SL |
924 | with(|v| f(Some(v))) |
925 | } else { | |
926 | f(None) | |
927 | } | |
928 | } | |
929 | } | |
930 | ||
931 | macro_rules! sty_debug_print { | |
932 | ($ctxt: expr, $($variant: ident),*) => {{ | |
933 | // curious inner module to allow variant names to be used as | |
934 | // variable names. | |
935 | #[allow(non_snake_case)] | |
936 | mod inner { | |
54a0048b | 937 | use ty::{self, TyCtxt}; |
a7813a04 XL |
938 | use ty::context::Interned; |
939 | ||
e9174d1e SL |
940 | #[derive(Copy, Clone)] |
941 | struct DebugStat { | |
942 | total: usize, | |
943 | region_infer: usize, | |
944 | ty_infer: usize, | |
945 | both_infer: usize, | |
946 | } | |
947 | ||
a7813a04 | 948 | pub fn go(tcx: TyCtxt) { |
e9174d1e SL |
949 | let mut total = DebugStat { |
950 | total: 0, | |
951 | region_infer: 0, ty_infer: 0, both_infer: 0, | |
952 | }; | |
953 | $(let mut $variant = total;)* | |
954 | ||
955 | ||
a7813a04 | 956 | for &Interned(t) in tcx.interners.type_.borrow().iter() { |
e9174d1e SL |
957 | let variant = match t.sty { |
958 | ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | | |
5bcae85e | 959 | ty::TyFloat(..) | ty::TyStr | ty::TyNever => continue, |
e9174d1e SL |
960 | ty::TyError => /* unimportant */ continue, |
961 | $(ty::$variant(..) => &mut $variant,)* | |
962 | }; | |
963 | let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER); | |
964 | let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER); | |
965 | ||
966 | variant.total += 1; | |
967 | total.total += 1; | |
968 | if region { total.region_infer += 1; variant.region_infer += 1 } | |
969 | if ty { total.ty_infer += 1; variant.ty_infer += 1 } | |
970 | if region && ty { total.both_infer += 1; variant.both_infer += 1 } | |
971 | } | |
972 | println!("Ty interner total ty region both"); | |
973 | $(println!(" {:18}: {uses:6} {usespc:4.1}%, \ | |
974 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
975 | stringify!($variant), | |
976 | uses = $variant.total, | |
977 | usespc = $variant.total as f64 * 100.0 / total.total as f64, | |
978 | ty = $variant.ty_infer as f64 * 100.0 / total.total as f64, | |
979 | region = $variant.region_infer as f64 * 100.0 / total.total as f64, | |
980 | both = $variant.both_infer as f64 * 100.0 / total.total as f64); | |
981 | )* | |
982 | println!(" total {uses:6} \ | |
983 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
984 | uses = total.total, | |
985 | ty = total.ty_infer as f64 * 100.0 / total.total as f64, | |
986 | region = total.region_infer as f64 * 100.0 / total.total as f64, | |
987 | both = total.both_infer as f64 * 100.0 / total.total as f64) | |
988 | } | |
989 | } | |
990 | ||
991 | inner::go($ctxt) | |
992 | }} | |
993 | } | |
994 | ||
a7813a04 XL |
995 | impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { |
996 | pub fn print_debug_stats(self) { | |
e9174d1e SL |
997 | sty_debug_print!( |
998 | self, | |
32a655c1 | 999 | TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, |
476ff2be | 1000 | TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); |
e9174d1e | 1001 | |
a7813a04 | 1002 | println!("Substs interner: #{}", self.interners.substs.borrow().len()); |
a7813a04 | 1003 | println!("Region interner: #{}", self.interners.region.borrow().len()); |
32a655c1 SL |
1004 | println!("Stability interner: #{}", self.stability_interner.borrow().len()); |
1005 | println!("Layout interner: #{}", self.layout_interner.borrow().len()); | |
e9174d1e SL |
1006 | } |
1007 | } | |
1008 | ||
1009 | ||
a7813a04 XL |
1010 | /// An entry in an interner. |
1011 | struct Interned<'tcx, T: 'tcx+?Sized>(&'tcx T); | |
e9174d1e | 1012 | |
a7813a04 XL |
1013 | // NB: An Interned<Ty> compares and hashes as a sty. |
1014 | impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { | |
1015 | fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { | |
1016 | self.0.sty == other.0.sty | |
e9174d1e SL |
1017 | } |
1018 | } | |
1019 | ||
a7813a04 | 1020 | impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {} |
e9174d1e | 1021 | |
a7813a04 | 1022 | impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { |
e9174d1e | 1023 | fn hash<H: Hasher>(&self, s: &mut H) { |
a7813a04 | 1024 | self.0.sty.hash(s) |
e9174d1e SL |
1025 | } |
1026 | } | |
1027 | ||
a7813a04 XL |
1028 | impl<'tcx: 'lcx, 'lcx> Borrow<TypeVariants<'lcx>> for Interned<'tcx, TyS<'tcx>> { |
1029 | fn borrow<'a>(&'a self) -> &'a TypeVariants<'lcx> { | |
1030 | &self.0.sty | |
e9174d1e SL |
1031 | } |
1032 | } | |
1033 | ||
9e0c209e SL |
1034 | // NB: An Interned<Slice<T>> compares and hashes as its elements. |
1035 | impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, Slice<T>> { | |
1036 | fn eq(&self, other: &Interned<'tcx, Slice<T>>) -> bool { | |
1037 | self.0[..] == other.0[..] | |
1038 | } | |
1039 | } | |
1040 | ||
1041 | impl<'tcx, T: Eq> Eq for Interned<'tcx, Slice<T>> {} | |
1042 | ||
1043 | impl<'tcx, T: Hash> Hash for Interned<'tcx, Slice<T>> { | |
1044 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1045 | self.0[..].hash(s) | |
1046 | } | |
1047 | } | |
1048 | ||
1049 | impl<'tcx: 'lcx, 'lcx> Borrow<[Ty<'lcx>]> for Interned<'tcx, Slice<Ty<'tcx>>> { | |
a7813a04 | 1050 | fn borrow<'a>(&'a self) -> &'a [Ty<'lcx>] { |
9e0c209e | 1051 | &self.0[..] |
a7813a04 | 1052 | } |
e9174d1e SL |
1053 | } |
1054 | ||
c30ab7b3 SL |
1055 | impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, Substs<'tcx>> { |
1056 | fn borrow<'a>(&'a self) -> &'a [Kind<'lcx>] { | |
1057 | &self.0[..] | |
a7813a04 XL |
1058 | } |
1059 | } | |
e9174d1e | 1060 | |
a7813a04 XL |
1061 | impl<'tcx> Borrow<Region> for Interned<'tcx, Region> { |
1062 | fn borrow<'a>(&'a self) -> &'a Region { | |
1063 | self.0 | |
e9174d1e | 1064 | } |
a7813a04 | 1065 | } |
e9174d1e | 1066 | |
476ff2be SL |
1067 | impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> |
1068 | for Interned<'tcx, Slice<ExistentialPredicate<'tcx>>> { | |
1069 | fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] { | |
1070 | &self.0[..] | |
1071 | } | |
1072 | } | |
1073 | ||
9e0c209e SL |
1074 | macro_rules! intern_method { |
1075 | ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, | |
c30ab7b3 | 1076 | $alloc_method:ident, |
9e0c209e SL |
1077 | $alloc_to_key:expr, |
1078 | $alloc_to_ret:expr, | |
1079 | $needs_infer:expr) -> $ty:ty) => { | |
a7813a04 XL |
1080 | impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { |
1081 | pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { | |
9e0c209e SL |
1082 | { |
1083 | let key = ($alloc_to_key)(&v); | |
1084 | if let Some(i) = self.interners.$name.borrow().get(key) { | |
a7813a04 XL |
1085 | return i.0; |
1086 | } | |
9e0c209e SL |
1087 | if !self.is_global() { |
1088 | if let Some(i) = self.global_interners.$name.borrow().get(key) { | |
1089 | return i.0; | |
1090 | } | |
1091 | } | |
a7813a04 | 1092 | } |
e9174d1e | 1093 | |
a7813a04 XL |
1094 | // HACK(eddyb) Depend on flags being accurate to |
1095 | // determine that all contents are in the global tcx. | |
1096 | // See comments on Lift for why we can't use that. | |
1097 | if !($needs_infer)(&v) { | |
1098 | if !self.is_global() { | |
1099 | let v = unsafe { | |
1100 | mem::transmute(v) | |
1101 | }; | |
32a655c1 | 1102 | let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v)); |
a7813a04 XL |
1103 | self.global_interners.$name.borrow_mut().insert(Interned(i)); |
1104 | return i; | |
1105 | } | |
1106 | } else { | |
1107 | // Make sure we don't end up with inference | |
1108 | // types/regions in the global tcx. | |
1109 | if self.is_global() { | |
1110 | bug!("Attempted to intern `{:?}` which contains \ | |
1111 | inference types/regions in the global type context", | |
1112 | v); | |
1113 | } | |
1114 | } | |
1115 | ||
32a655c1 | 1116 | let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v)); |
a7813a04 XL |
1117 | self.interners.$name.borrow_mut().insert(Interned(i)); |
1118 | i | |
e9174d1e | 1119 | } |
9e0c209e SL |
1120 | } |
1121 | } | |
1122 | } | |
1123 | ||
1124 | macro_rules! direct_interners { | |
1125 | ($lt_tcx:tt, $($name:ident: $method:ident($needs_infer:expr) -> $ty:ty),+) => { | |
1126 | $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { | |
1127 | fn eq(&self, other: &Self) -> bool { | |
1128 | self.0 == other.0 | |
1129 | } | |
1130 | } | |
1131 | ||
1132 | impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} | |
1133 | ||
1134 | impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { | |
1135 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1136 | self.0.hash(s) | |
1137 | } | |
1138 | } | |
1139 | ||
c30ab7b3 | 1140 | intern_method!($lt_tcx, $name: $method($ty, alloc, |x| x, |x| x, $needs_infer) -> $ty);)+ |
a7813a04 XL |
1141 | } |
1142 | } | |
e9174d1e | 1143 | |
a7813a04 XL |
1144 | fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { |
1145 | x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) | |
1146 | } | |
e9174d1e | 1147 | |
9e0c209e | 1148 | direct_interners!('tcx, |
9e0c209e SL |
1149 | region: mk_region(|r| { |
1150 | match r { | |
1151 | &ty::ReVar(_) | &ty::ReSkolemized(..) => true, | |
1152 | _ => false | |
1153 | } | |
1154 | }) -> Region | |
a7813a04 | 1155 | ); |
e9174d1e | 1156 | |
c30ab7b3 SL |
1157 | macro_rules! slice_interners { |
1158 | ($($field:ident: $method:ident($ty:ident)),+) => ( | |
1159 | $(intern_method!('tcx, $field: $method(&[$ty<'tcx>], alloc_slice, Deref::deref, | |
1160 | |xs: &[$ty]| -> &Slice<$ty> { | |
1161 | unsafe { mem::transmute(xs) } | |
1162 | }, |xs: &[$ty]| xs.iter().any(keep_local)) -> Slice<$ty<'tcx>>);)+ | |
1163 | ) | |
1164 | } | |
1165 | ||
1166 | slice_interners!( | |
476ff2be | 1167 | existential_predicates: _intern_existential_predicates(ExistentialPredicate), |
c30ab7b3 SL |
1168 | type_list: _intern_type_list(Ty), |
1169 | substs: _intern_substs(Kind) | |
9e0c209e | 1170 | ); |
e9174d1e | 1171 | |
a7813a04 XL |
1172 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
1173 | /// Create an unsafe fn ty based on a safe fn ty. | |
8bb4bdeb XL |
1174 | pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> { |
1175 | assert_eq!(sig.unsafety(), hir::Unsafety::Normal); | |
1176 | self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { | |
a7813a04 | 1177 | unsafety: hir::Unsafety::Unsafe, |
8bb4bdeb | 1178 | ..sig |
a7813a04 | 1179 | })) |
e9174d1e SL |
1180 | } |
1181 | ||
a7813a04 | 1182 | // Interns a type/name combination, stores the resulting box in cx.interners, |
e9174d1e | 1183 | // and returns the box as cast to an unsafe ptr (see comments for Ty above). |
a7813a04 XL |
1184 | pub fn mk_ty(self, st: TypeVariants<'tcx>) -> Ty<'tcx> { |
1185 | let global_interners = if !self.is_global() { | |
1186 | Some(&self.global_interners) | |
1187 | } else { | |
1188 | None | |
1189 | }; | |
1190 | self.interners.intern_ty(st, global_interners) | |
e9174d1e SL |
1191 | } |
1192 | ||
a7813a04 | 1193 | pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> { |
e9174d1e | 1194 | match tm { |
7453a54e SL |
1195 | ast::IntTy::Is => self.types.isize, |
1196 | ast::IntTy::I8 => self.types.i8, | |
1197 | ast::IntTy::I16 => self.types.i16, | |
1198 | ast::IntTy::I32 => self.types.i32, | |
1199 | ast::IntTy::I64 => self.types.i64, | |
32a655c1 | 1200 | ast::IntTy::I128 => self.types.i128, |
e9174d1e SL |
1201 | } |
1202 | } | |
1203 | ||
a7813a04 | 1204 | pub fn mk_mach_uint(self, tm: ast::UintTy) -> Ty<'tcx> { |
e9174d1e | 1205 | match tm { |
7453a54e SL |
1206 | ast::UintTy::Us => self.types.usize, |
1207 | ast::UintTy::U8 => self.types.u8, | |
1208 | ast::UintTy::U16 => self.types.u16, | |
1209 | ast::UintTy::U32 => self.types.u32, | |
1210 | ast::UintTy::U64 => self.types.u64, | |
32a655c1 | 1211 | ast::UintTy::U128 => self.types.u128, |
e9174d1e SL |
1212 | } |
1213 | } | |
1214 | ||
a7813a04 | 1215 | pub fn mk_mach_float(self, tm: ast::FloatTy) -> Ty<'tcx> { |
e9174d1e | 1216 | match tm { |
7453a54e SL |
1217 | ast::FloatTy::F32 => self.types.f32, |
1218 | ast::FloatTy::F64 => self.types.f64, | |
e9174d1e SL |
1219 | } |
1220 | } | |
1221 | ||
a7813a04 | 1222 | pub fn mk_str(self) -> Ty<'tcx> { |
e9174d1e SL |
1223 | self.mk_ty(TyStr) |
1224 | } | |
1225 | ||
a7813a04 | 1226 | pub fn mk_static_str(self) -> Ty<'tcx> { |
e9174d1e SL |
1227 | self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str()) |
1228 | } | |
1229 | ||
476ff2be | 1230 | pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
e9174d1e | 1231 | // take a copy of substs so that we own the vectors inside |
9e0c209e | 1232 | self.mk_ty(TyAdt(def, substs)) |
e9174d1e SL |
1233 | } |
1234 | ||
a7813a04 | 1235 | pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
32a655c1 SL |
1236 | let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); |
1237 | let adt_def = self.lookup_adt_def(def_id); | |
1238 | let substs = self.mk_substs(iter::once(Kind::from(ty))); | |
1239 | self.mk_ty(TyAdt(adt_def, substs)) | |
e9174d1e SL |
1240 | } |
1241 | ||
a7813a04 | 1242 | pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1243 | self.mk_ty(TyRawPtr(tm)) |
1244 | } | |
1245 | ||
a7813a04 | 1246 | pub fn mk_ref(self, r: &'tcx Region, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1247 | self.mk_ty(TyRef(r, tm)) |
1248 | } | |
1249 | ||
a7813a04 | 1250 | pub fn mk_mut_ref(self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1251 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable}) |
1252 | } | |
1253 | ||
a7813a04 | 1254 | pub fn mk_imm_ref(self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1255 | self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) |
1256 | } | |
1257 | ||
a7813a04 | 1258 | pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1259 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable}) |
1260 | } | |
1261 | ||
a7813a04 | 1262 | pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1263 | self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) |
1264 | } | |
1265 | ||
a7813a04 | 1266 | pub fn mk_nil_ptr(self) -> Ty<'tcx> { |
e9174d1e SL |
1267 | self.mk_imm_ptr(self.mk_nil()) |
1268 | } | |
1269 | ||
a7813a04 | 1270 | pub fn mk_array(self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> { |
e9174d1e SL |
1271 | self.mk_ty(TyArray(ty, n)) |
1272 | } | |
1273 | ||
a7813a04 | 1274 | pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1275 | self.mk_ty(TySlice(ty)) |
1276 | } | |
1277 | ||
8bb4bdeb XL |
1278 | pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> { |
1279 | self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)) | |
c30ab7b3 SL |
1280 | } |
1281 | ||
8bb4bdeb XL |
1282 | pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I, |
1283 | defaulted: bool) -> I::Output { | |
1284 | iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))) | |
e9174d1e SL |
1285 | } |
1286 | ||
a7813a04 | 1287 | pub fn mk_nil(self) -> Ty<'tcx> { |
8bb4bdeb | 1288 | self.intern_tup(&[], false) |
e9174d1e SL |
1289 | } |
1290 | ||
5bcae85e SL |
1291 | pub fn mk_diverging_default(self) -> Ty<'tcx> { |
1292 | if self.sess.features.borrow().never_type { | |
1293 | self.types.never | |
1294 | } else { | |
8bb4bdeb | 1295 | self.intern_tup(&[], true) |
5bcae85e SL |
1296 | } |
1297 | } | |
1298 | ||
a7813a04 | 1299 | pub fn mk_bool(self) -> Ty<'tcx> { |
e9174d1e SL |
1300 | self.mk_ty(TyBool) |
1301 | } | |
1302 | ||
a7813a04 | 1303 | pub fn mk_fn_def(self, def_id: DefId, |
54a0048b | 1304 | substs: &'tcx Substs<'tcx>, |
8bb4bdeb | 1305 | fty: PolyFnSig<'tcx>) -> Ty<'tcx> { |
a7813a04 | 1306 | self.mk_ty(TyFnDef(def_id, substs, fty)) |
54a0048b SL |
1307 | } |
1308 | ||
8bb4bdeb | 1309 | pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { |
a7813a04 | 1310 | self.mk_ty(TyFnPtr(fty)) |
e9174d1e SL |
1311 | } |
1312 | ||
476ff2be SL |
1313 | pub fn mk_dynamic( |
1314 | self, | |
1315 | obj: ty::Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, | |
1316 | reg: &'tcx ty::Region | |
1317 | ) -> Ty<'tcx> { | |
1318 | self.mk_ty(TyDynamic(obj, reg)) | |
e9174d1e SL |
1319 | } |
1320 | ||
a7813a04 | 1321 | pub fn mk_projection(self, |
e9174d1e SL |
1322 | trait_ref: TraitRef<'tcx>, |
1323 | item_name: Name) | |
476ff2be SL |
1324 | -> Ty<'tcx> { |
1325 | // take a copy of substs so that we own the vectors inside | |
1326 | let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; | |
1327 | self.mk_ty(TyProjection(inner)) | |
1328 | } | |
e9174d1e | 1329 | |
a7813a04 | 1330 | pub fn mk_closure(self, |
e9174d1e | 1331 | closure_id: DefId, |
476ff2be SL |
1332 | substs: &'tcx Substs<'tcx>) |
1333 | -> Ty<'tcx> { | |
a7813a04 | 1334 | self.mk_closure_from_closure_substs(closure_id, ClosureSubsts { |
476ff2be | 1335 | substs: substs |
a7813a04 | 1336 | }) |
e9174d1e SL |
1337 | } |
1338 | ||
a7813a04 | 1339 | pub fn mk_closure_from_closure_substs(self, |
e9174d1e | 1340 | closure_id: DefId, |
a7813a04 | 1341 | closure_substs: ClosureSubsts<'tcx>) |
e9174d1e SL |
1342 | -> Ty<'tcx> { |
1343 | self.mk_ty(TyClosure(closure_id, closure_substs)) | |
1344 | } | |
1345 | ||
a7813a04 | 1346 | pub fn mk_var(self, v: TyVid) -> Ty<'tcx> { |
e9174d1e SL |
1347 | self.mk_infer(TyVar(v)) |
1348 | } | |
1349 | ||
a7813a04 | 1350 | pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> { |
e9174d1e SL |
1351 | self.mk_infer(IntVar(v)) |
1352 | } | |
1353 | ||
a7813a04 | 1354 | pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> { |
e9174d1e SL |
1355 | self.mk_infer(FloatVar(v)) |
1356 | } | |
1357 | ||
a7813a04 | 1358 | pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> { |
e9174d1e SL |
1359 | self.mk_ty(TyInfer(it)) |
1360 | } | |
1361 | ||
a7813a04 | 1362 | pub fn mk_param(self, |
e9174d1e SL |
1363 | index: u32, |
1364 | name: Name) -> Ty<'tcx> { | |
9e0c209e | 1365 | self.mk_ty(TyParam(ParamTy { idx: index, name: name })) |
e9174d1e SL |
1366 | } |
1367 | ||
a7813a04 | 1368 | pub fn mk_self_type(self) -> Ty<'tcx> { |
9e0c209e | 1369 | self.mk_param(0, keywords::SelfType.name()) |
e9174d1e SL |
1370 | } |
1371 | ||
a7813a04 | 1372 | pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { |
9e0c209e | 1373 | self.mk_param(def.index, def.name) |
e9174d1e | 1374 | } |
9cc50fc6 | 1375 | |
5bcae85e SL |
1376 | pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
1377 | self.mk_ty(TyAnon(def_id, substs)) | |
1378 | } | |
1379 | ||
476ff2be SL |
1380 | pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>]) |
1381 | -> &'tcx Slice<ExistentialPredicate<'tcx>> { | |
1382 | assert!(!eps.is_empty()); | |
1383 | assert!(eps.windows(2).all(|w| w[0].cmp(self, &w[1]) != Ordering::Greater)); | |
1384 | self._intern_existential_predicates(eps) | |
1385 | } | |
1386 | ||
c30ab7b3 SL |
1387 | pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> { |
1388 | if ts.len() == 0 { | |
1389 | Slice::empty() | |
1390 | } else { | |
1391 | self._intern_type_list(ts) | |
1392 | } | |
1393 | } | |
1394 | ||
1395 | pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice<Kind<'tcx>> { | |
1396 | if ts.len() == 0 { | |
1397 | Slice::empty() | |
1398 | } else { | |
1399 | self._intern_substs(ts) | |
1400 | } | |
1401 | } | |
1402 | ||
8bb4bdeb XL |
1403 | pub fn mk_fn_sig<I>(self, |
1404 | inputs: I, | |
1405 | output: I::Item, | |
1406 | variadic: bool, | |
1407 | unsafety: hir::Unsafety, | |
1408 | abi: abi::Abi) | |
476ff2be SL |
1409 | -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output |
1410 | where I: Iterator, | |
1411 | I::Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>> | |
1412 | { | |
1413 | inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig { | |
1414 | inputs_and_output: self.intern_type_list(xs), | |
8bb4bdeb | 1415 | variadic, unsafety, abi |
476ff2be SL |
1416 | }) |
1417 | } | |
1418 | ||
1419 | pub fn mk_existential_predicates<I: InternAs<[ExistentialPredicate<'tcx>], | |
1420 | &'tcx Slice<ExistentialPredicate<'tcx>>>>(self, iter: I) | |
1421 | -> I::Output { | |
1422 | iter.intern_with(|xs| self.intern_existential_predicates(xs)) | |
1423 | } | |
1424 | ||
c30ab7b3 SL |
1425 | pub fn mk_type_list<I: InternAs<[Ty<'tcx>], |
1426 | &'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output { | |
1427 | iter.intern_with(|xs| self.intern_type_list(xs)) | |
1428 | } | |
1429 | ||
1430 | pub fn mk_substs<I: InternAs<[Kind<'tcx>], | |
1431 | &'tcx Slice<Kind<'tcx>>>>(self, iter: I) -> I::Output { | |
1432 | iter.intern_with(|xs| self.intern_substs(xs)) | |
1433 | } | |
1434 | ||
1435 | pub fn mk_substs_trait(self, | |
1436 | s: Ty<'tcx>, | |
1437 | t: &[Ty<'tcx>]) | |
1438 | -> &'tcx Substs<'tcx> | |
1439 | { | |
1440 | self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from)) | |
1441 | } | |
e9174d1e | 1442 | } |
c30ab7b3 SL |
1443 | |
1444 | pub trait InternAs<T: ?Sized, R> { | |
1445 | type Output; | |
1446 | fn intern_with<F>(self, F) -> Self::Output | |
1447 | where F: FnOnce(&T) -> R; | |
1448 | } | |
1449 | ||
1450 | impl<I, T, R, E> InternAs<[T], R> for I | |
1451 | where E: InternIteratorElement<T, R>, | |
1452 | I: Iterator<Item=E> { | |
1453 | type Output = E::Output; | |
1454 | fn intern_with<F>(self, f: F) -> Self::Output | |
1455 | where F: FnOnce(&[T]) -> R { | |
1456 | E::intern_with(self, f) | |
1457 | } | |
1458 | } | |
1459 | ||
1460 | pub trait InternIteratorElement<T, R>: Sized { | |
1461 | type Output; | |
1462 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output; | |
1463 | } | |
1464 | ||
1465 | impl<T, R> InternIteratorElement<T, R> for T { | |
1466 | type Output = R; | |
1467 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { | |
1468 | f(&iter.collect::<AccumulateVec<[_; 8]>>()) | |
1469 | } | |
1470 | } | |
1471 | ||
1472 | impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> { | |
1473 | type Output = Result<R, E>; | |
1474 | fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { | |
1475 | Ok(f(&iter.collect::<Result<AccumulateVec<[_; 8]>, _>>()?)) | |
1476 | } | |
1477 | } |