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