]>
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 | //! This module contains TypeVariants and its major components | |
12 | ||
54a0048b | 13 | use hir::def_id::DefId; |
476ff2be | 14 | |
ea8adc8c | 15 | use middle::const_val::ConstVal; |
e9174d1e | 16 | use middle::region; |
abe05a73 | 17 | use rustc_data_structures::indexed_vec::Idx; |
041b39d2 | 18 | use ty::subst::{Substs, Subst}; |
476ff2be | 19 | use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; |
9e0c209e | 20 | use ty::{Slice, TyS}; |
476ff2be | 21 | use ty::subst::Kind; |
e9174d1e | 22 | |
476ff2be SL |
23 | use std::iter; |
24 | use std::cmp::Ordering; | |
e9174d1e | 25 | use syntax::abi; |
32a655c1 | 26 | use syntax::ast::{self, Name}; |
041b39d2 | 27 | use syntax::symbol::keywords; |
e9174d1e | 28 | |
9e0c209e | 29 | use serialize; |
9cc50fc6 | 30 | |
54a0048b | 31 | use hir; |
e9174d1e | 32 | |
e9174d1e SL |
33 | use self::InferTy::*; |
34 | use self::TypeVariants::*; | |
35 | ||
9e0c209e | 36 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
37 | pub struct TypeAndMut<'tcx> { |
38 | pub ty: Ty<'tcx>, | |
39 | pub mutbl: hir::Mutability, | |
40 | } | |
41 | ||
42 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, | |
43 | RustcEncodable, RustcDecodable, Copy)] | |
44 | /// A "free" region `fr` can be interpreted as "some region | |
45 | /// at least as big as the scope `fr.scope`". | |
46 | pub struct FreeRegion { | |
7cac9316 | 47 | pub scope: DefId, |
cc61c64b | 48 | pub bound_region: BoundRegion, |
e9174d1e SL |
49 | } |
50 | ||
51 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, | |
52 | RustcEncodable, RustcDecodable, Copy)] | |
53 | pub enum BoundRegion { | |
54 | /// An anonymous region parameter for a given fn (&T) | |
55 | BrAnon(u32), | |
56 | ||
57 | /// Named region parameters for functions (a in &'a T) | |
58 | /// | |
59 | /// The def-id is needed to distinguish free regions in | |
60 | /// the event of shadowing. | |
8bb4bdeb | 61 | BrNamed(DefId, Name), |
e9174d1e SL |
62 | |
63 | /// Fresh bound identifiers created during GLB computations. | |
64 | BrFresh(u32), | |
65 | ||
7cac9316 XL |
66 | /// Anonymous region for the implicit env pointer parameter |
67 | /// to a closure | |
cc61c64b | 68 | BrEnv, |
e9174d1e SL |
69 | } |
70 | ||
7cac9316 XL |
71 | impl BoundRegion { |
72 | pub fn is_named(&self) -> bool { | |
73 | match *self { | |
74 | BoundRegion::BrNamed(..) => true, | |
75 | _ => false, | |
76 | } | |
77 | } | |
78 | } | |
79 | ||
7cac9316 XL |
80 | /// NB: If you change this, you'll probably want to change the corresponding |
81 | /// AST structure in libsyntax/ast.rs as well. | |
9e0c209e | 82 | #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
83 | pub enum TypeVariants<'tcx> { |
84 | /// The primitive boolean type. Written as `bool`. | |
85 | TyBool, | |
86 | ||
87 | /// The primitive character type; holds a Unicode scalar value | |
88 | /// (a non-surrogate code point). Written as `char`. | |
89 | TyChar, | |
90 | ||
91 | /// A primitive signed integer type. For example, `i32`. | |
b039eaaf | 92 | TyInt(ast::IntTy), |
e9174d1e SL |
93 | |
94 | /// A primitive unsigned integer type. For example, `u32`. | |
b039eaaf | 95 | TyUint(ast::UintTy), |
e9174d1e SL |
96 | |
97 | /// A primitive floating-point type. For example, `f64`. | |
b039eaaf | 98 | TyFloat(ast::FloatTy), |
e9174d1e | 99 | |
9e0c209e | 100 | /// Structures, enumerations and unions. |
e9174d1e SL |
101 | /// |
102 | /// Substs here, possibly against intuition, *may* contain `TyParam`s. | |
103 | /// That is, even after substitution it is possible that there are type | |
9e0c209e SL |
104 | /// variables. This happens when the `TyAdt` corresponds to an ADT |
105 | /// definition and not a concrete use of it. | |
476ff2be | 106 | TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>), |
e9174d1e | 107 | |
abe05a73 XL |
108 | TyForeign(DefId), |
109 | ||
e9174d1e SL |
110 | /// The pointee of a string slice. Written as `str`. |
111 | TyStr, | |
112 | ||
113 | /// An array with the given length. Written as `[T; n]`. | |
ea8adc8c | 114 | TyArray(Ty<'tcx>, &'tcx ty::Const<'tcx>), |
e9174d1e SL |
115 | |
116 | /// The pointee of an array slice. Written as `[T]`. | |
117 | TySlice(Ty<'tcx>), | |
118 | ||
119 | /// A raw pointer. Written as `*mut T` or `*const T` | |
120 | TyRawPtr(TypeAndMut<'tcx>), | |
121 | ||
122 | /// A reference; a pointer with an associated lifetime. Written as | |
32a655c1 | 123 | /// `&'a mut T` or `&'a T`. |
7cac9316 | 124 | TyRef(Region<'tcx>, TypeAndMut<'tcx>), |
e9174d1e | 125 | |
54a0048b SL |
126 | /// The anonymous type of a function declaration/definition. Each |
127 | /// function has a unique type. | |
041b39d2 | 128 | TyFnDef(DefId, &'tcx Substs<'tcx>), |
54a0048b SL |
129 | |
130 | /// A pointer to a function. Written as `fn() -> i32`. | |
8bb4bdeb | 131 | TyFnPtr(PolyFnSig<'tcx>), |
e9174d1e SL |
132 | |
133 | /// A trait, defined with `trait`. | |
7cac9316 | 134 | TyDynamic(Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>), |
e9174d1e SL |
135 | |
136 | /// The anonymous type of a closure. Used to represent the type of | |
137 | /// `|a| a`. | |
a7813a04 | 138 | TyClosure(DefId, ClosureSubsts<'tcx>), |
e9174d1e | 139 | |
ea8adc8c XL |
140 | /// The anonymous type of a generator. Used to represent the type of |
141 | /// `|a| yield a`. | |
142 | TyGenerator(DefId, ClosureSubsts<'tcx>, GeneratorInterior<'tcx>), | |
143 | ||
2c00a5a8 XL |
144 | /// A type representin the types stored inside a generator. |
145 | /// This should only appear in GeneratorInteriors. | |
146 | TyGeneratorWitness(Binder<&'tcx Slice<Ty<'tcx>>>), | |
147 | ||
5bcae85e SL |
148 | /// The never type `!` |
149 | TyNever, | |
150 | ||
e9174d1e | 151 | /// A tuple type. For example, `(i32, bool)`. |
8bb4bdeb XL |
152 | /// The bool indicates whether this is a unit tuple and was created by |
153 | /// defaulting a diverging type variable with feature(never_type) disabled. | |
154 | /// It's only purpose is for raising future-compatibility warnings for when | |
155 | /// diverging type variables start defaulting to ! instead of (). | |
156 | TyTuple(&'tcx Slice<Ty<'tcx>>, bool), | |
e9174d1e SL |
157 | |
158 | /// The projection of an associated type. For example, | |
159 | /// `<T as Trait<..>>::N`. | |
160 | TyProjection(ProjectionTy<'tcx>), | |
161 | ||
5bcae85e SL |
162 | /// Anonymized (`impl Trait`) type found in a return type. |
163 | /// The DefId comes from the `impl Trait` ast::Ty node, and the | |
164 | /// substitutions are for the generics of the function in question. | |
476ff2be | 165 | /// After typeck, the concrete type can be found in the `types` map. |
5bcae85e SL |
166 | TyAnon(DefId, &'tcx Substs<'tcx>), |
167 | ||
e9174d1e SL |
168 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} |
169 | TyParam(ParamTy), | |
170 | ||
171 | /// A type variable used during type-checking. | |
172 | TyInfer(InferTy), | |
173 | ||
174 | /// A placeholder for a type which could not be computed; this is | |
175 | /// propagated to avoid useless error messages. | |
176 | TyError, | |
177 | } | |
178 | ||
179 | /// A closure can be modeled as a struct that looks like: | |
180 | /// | |
ff7c6d11 | 181 | /// struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> { |
e9174d1e SL |
182 | /// upvar0: U0, |
183 | /// ... | |
184 | /// upvark: Uk | |
185 | /// } | |
186 | /// | |
ff7c6d11 XL |
187 | /// where: |
188 | /// | |
189 | /// - 'l0...'li and T0...Tj are the lifetime and type parameters | |
190 | /// in scope on the function that defined the closure, | |
191 | /// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This | |
192 | /// is rather hackily encoded via a scalar type. See | |
193 | /// `TyS::to_opt_closure_kind` for details. | |
194 | /// - CS represents the *closure signature*, representing as a `fn()` | |
195 | /// type. For example, `fn(u32, u32) -> u32` would mean that the closure | |
196 | /// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait | |
197 | /// specified above. | |
198 | /// - U0...Uk are type parameters representing the types of its upvars | |
199 | /// (borrowed, if appropriate; that is, if Ui represents a by-ref upvar, | |
200 | /// and the up-var has the type `Foo`, then `Ui = &Foo`). | |
e9174d1e SL |
201 | /// |
202 | /// So, for example, given this function: | |
203 | /// | |
204 | /// fn foo<'a, T>(data: &'a mut T) { | |
205 | /// do(|| data.count += 1) | |
206 | /// } | |
207 | /// | |
208 | /// the type of the closure would be something like: | |
209 | /// | |
210 | /// struct Closure<'a, T, U0> { | |
211 | /// data: U0 | |
212 | /// } | |
213 | /// | |
214 | /// Note that the type of the upvar is not specified in the struct. | |
215 | /// You may wonder how the impl would then be able to use the upvar, | |
216 | /// if it doesn't know it's type? The answer is that the impl is | |
217 | /// (conceptually) not fully generic over Closure but rather tied to | |
218 | /// instances with the expected upvar types: | |
219 | /// | |
220 | /// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> { | |
221 | /// ... | |
222 | /// } | |
223 | /// | |
224 | /// You can see that the *impl* fully specified the type of the upvar | |
225 | /// and thus knows full well that `data` has type `&'b mut &'a mut T`. | |
226 | /// (Here, I am assuming that `data` is mut-borrowed.) | |
227 | /// | |
228 | /// Now, the last question you may ask is: Why include the upvar types | |
229 | /// as extra type parameters? The reason for this design is that the | |
230 | /// upvar types can reference lifetimes that are internal to the | |
231 | /// creating function. In my example above, for example, the lifetime | |
ea8adc8c XL |
232 | /// `'b` represents the scope of the closure itself; this is some |
233 | /// subset of `foo`, probably just the scope of the call to the to | |
e9174d1e SL |
234 | /// `do()`. If we just had the lifetime/type parameters from the |
235 | /// enclosing function, we couldn't name this lifetime `'b`. Note that | |
236 | /// there can also be lifetimes in the types of the upvars themselves, | |
237 | /// if one of them happens to be a reference to something that the | |
238 | /// creating fn owns. | |
239 | /// | |
240 | /// OK, you say, so why not create a more minimal set of parameters | |
241 | /// that just includes the extra lifetime parameters? The answer is | |
242 | /// primarily that it would be hard --- we don't know at the time when | |
243 | /// we create the closure type what the full types of the upvars are, | |
244 | /// nor do we know which are borrowed and which are not. In this | |
245 | /// design, we can just supply a fresh type parameter and figure that | |
246 | /// out later. | |
247 | /// | |
248 | /// All right, you say, but why include the type parameters from the | |
249 | /// original function then? The answer is that trans may need them | |
250 | /// when monomorphizing, and they may not appear in the upvars. A | |
251 | /// closure could capture no variables but still make use of some | |
252 | /// in-scope type parameter with a bound (e.g., if our example above | |
253 | /// had an extra `U: Default`, and the closure called `U::default()`). | |
254 | /// | |
255 | /// There is another reason. This design (implicitly) prohibits | |
256 | /// closures from capturing themselves (except via a trait | |
257 | /// object). This simplifies closure inference considerably, since it | |
258 | /// means that when we infer the kind of a closure or its upvars, we | |
259 | /// don't have to handle cycles where the decisions we make for | |
260 | /// closure C wind up influencing the decisions we ought to make for | |
261 | /// closure C (which would then require fixed point iteration to | |
262 | /// handle). Plus it fixes an ICE. :P | |
ff7c6d11 XL |
263 | /// |
264 | /// ## Generators | |
265 | /// | |
266 | /// Perhaps surprisingly, `ClosureSubsts` are also used for | |
267 | /// generators. In that case, what is written above is only half-true | |
268 | /// -- the set of type parameters is similar, but the role of CK and | |
269 | /// CS are different. CK represents the "yield type" and CS | |
270 | /// represents the "return type" of the generator. | |
271 | /// | |
272 | /// It'd be nice to split this struct into ClosureSubsts and | |
273 | /// GeneratorSubsts, I believe. -nmatsakis | |
9e0c209e | 274 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e | 275 | pub struct ClosureSubsts<'tcx> { |
476ff2be SL |
276 | /// Lifetime and type parameters from the enclosing function, |
277 | /// concatenated with the types of the upvars. | |
278 | /// | |
e9174d1e SL |
279 | /// These are separated out because trans wants to pass them around |
280 | /// when monomorphizing. | |
476ff2be SL |
281 | pub substs: &'tcx Substs<'tcx>, |
282 | } | |
e9174d1e | 283 | |
ff7c6d11 XL |
284 | /// Struct returned by `split()`. Note that these are subslices of the |
285 | /// parent slice and not canonical substs themselves. | |
286 | struct SplitClosureSubsts<'tcx> { | |
287 | closure_kind_ty: Ty<'tcx>, | |
288 | closure_sig_ty: Ty<'tcx>, | |
289 | upvar_kinds: &'tcx [Kind<'tcx>], | |
290 | } | |
291 | ||
292 | impl<'tcx> ClosureSubsts<'tcx> { | |
293 | /// Divides the closure substs into their respective | |
294 | /// components. Single source of truth with respect to the | |
295 | /// ordering. | |
296 | fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitClosureSubsts<'tcx> { | |
297 | let generics = tcx.generics_of(def_id); | |
298 | let parent_len = generics.parent_count(); | |
299 | SplitClosureSubsts { | |
300 | closure_kind_ty: self.substs[parent_len].as_type().expect("CK should be a type"), | |
301 | closure_sig_ty: self.substs[parent_len + 1].as_type().expect("CS should be a type"), | |
302 | upvar_kinds: &self.substs[parent_len + 2..], | |
303 | } | |
304 | } | |
305 | ||
476ff2be | 306 | #[inline] |
ff7c6d11 | 307 | pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> |
476ff2be SL |
308 | impl Iterator<Item=Ty<'tcx>> + 'tcx |
309 | { | |
ff7c6d11 XL |
310 | let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx); |
311 | upvar_kinds.iter().map(|t| t.as_type().expect("upvar should be type")) | |
312 | } | |
313 | ||
314 | /// Returns the closure kind for this closure; may return a type | |
315 | /// variable during inference. To get the closure kind during | |
316 | /// inference, use `infcx.closure_kind(def_id, substs)`. | |
317 | pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
318 | self.split(def_id, tcx).closure_kind_ty | |
319 | } | |
320 | ||
321 | /// Returns the type representing the closure signature for this | |
322 | /// closure; may contain type variables during inference. To get | |
323 | /// the closure signature during inference, use | |
324 | /// `infcx.fn_sig(def_id)`. | |
325 | pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
326 | self.split(def_id, tcx).closure_sig_ty | |
327 | } | |
328 | ||
329 | /// Returns the type representing the yield type of the generator. | |
330 | pub fn generator_yield_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
331 | self.closure_kind_ty(def_id, tcx) | |
332 | } | |
333 | ||
334 | /// Returns the type representing the return type of the generator. | |
335 | pub fn generator_return_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
336 | self.closure_sig_ty(def_id, tcx) | |
337 | } | |
338 | ||
339 | /// Return the "generator signature", which consists of its yield | |
340 | /// and return types. | |
341 | /// | |
342 | /// NB. Some bits of the code prefers to see this wrapped in a | |
343 | /// binder, but it never contains bound regions. Probably this | |
344 | /// function should be removed. | |
345 | pub fn generator_poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> { | |
346 | ty::Binder(self.generator_sig(def_id, tcx)) | |
347 | } | |
348 | ||
349 | /// Return the "generator signature", which consists of its yield | |
350 | /// and return types. | |
351 | pub fn generator_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> GenSig<'tcx> { | |
352 | ty::GenSig { | |
353 | yield_ty: self.generator_yield_ty(def_id, tcx), | |
354 | return_ty: self.generator_return_ty(def_id, tcx), | |
355 | } | |
356 | } | |
357 | } | |
358 | ||
359 | impl<'tcx> ClosureSubsts<'tcx> { | |
360 | /// Returns the closure kind for this closure; only usable outside | |
361 | /// of an inference context, because in that context we know that | |
362 | /// there are no type variables. | |
363 | /// | |
364 | /// If you have an inference context, use `infcx.closure_kind()`. | |
365 | pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::ClosureKind { | |
366 | self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap() | |
367 | } | |
368 | ||
369 | /// Extracts the signature from the closure; only usable outside | |
370 | /// of an inference context, because in that context we know that | |
371 | /// there are no type variables. | |
372 | /// | |
373 | /// If you have an inference context, use `infcx.closure_sig()`. | |
374 | pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { | |
375 | match self.closure_sig_ty(def_id, tcx).sty { | |
376 | ty::TyFnPtr(sig) => sig, | |
377 | ref t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t), | |
378 | } | |
476ff2be | 379 | } |
a7813a04 | 380 | } |
9cc50fc6 | 381 | |
ea8adc8c XL |
382 | impl<'a, 'gcx, 'tcx> ClosureSubsts<'tcx> { |
383 | /// This returns the types of the MIR locals which had to be stored across suspension points. | |
384 | /// It is calculated in rustc_mir::transform::generator::StateTransform. | |
385 | /// All the types here must be in the tuple in GeneratorInterior. | |
386 | pub fn state_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> | |
387 | impl Iterator<Item=Ty<'tcx>> + 'a | |
388 | { | |
389 | let state = tcx.generator_layout(def_id).fields.iter(); | |
390 | state.map(move |d| d.ty.subst(tcx, self.substs)) | |
391 | } | |
392 | ||
2c00a5a8 XL |
393 | /// This is the types of the fields of a generate which |
394 | /// is available before the generator transformation. | |
395 | /// It includes the upvars and the state discriminant which is u32. | |
396 | pub fn pre_transforms_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> | |
397 | impl Iterator<Item=Ty<'tcx>> + 'a | |
398 | { | |
399 | self.upvar_tys(def_id, tcx).chain(iter::once(tcx.types.u32)) | |
400 | } | |
401 | ||
ea8adc8c XL |
402 | /// This is the types of all the fields stored in a generator. |
403 | /// It includes the upvars, state types and the state discriminant which is u32. | |
404 | pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> | |
405 | impl Iterator<Item=Ty<'tcx>> + 'a | |
406 | { | |
2c00a5a8 | 407 | self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx)) |
ea8adc8c XL |
408 | } |
409 | } | |
410 | ||
411 | /// This describes the types that can be contained in a generator. | |
412 | /// It will be a type variable initially and unified in the last stages of typeck of a body. | |
413 | /// It contains a tuple of all the types that could end up on a generator frame. | |
414 | /// The state transformation MIR pass may only produce layouts which mention types in this tuple. | |
415 | /// Upvars are not counted here. | |
416 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] | |
417 | pub struct GeneratorInterior<'tcx> { | |
418 | pub witness: Ty<'tcx>, | |
2c00a5a8 | 419 | pub movable: bool, |
ea8adc8c XL |
420 | } |
421 | ||
476ff2be SL |
422 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
423 | pub enum ExistentialPredicate<'tcx> { | |
7cac9316 | 424 | /// e.g. Iterator |
476ff2be | 425 | Trait(ExistentialTraitRef<'tcx>), |
7cac9316 | 426 | /// e.g. Iterator::Item = T |
476ff2be | 427 | Projection(ExistentialProjection<'tcx>), |
7cac9316 | 428 | /// e.g. Send |
476ff2be SL |
429 | AutoTrait(DefId), |
430 | } | |
431 | ||
432 | impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> { | |
433 | pub fn cmp(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, other: &Self) -> Ordering { | |
434 | use self::ExistentialPredicate::*; | |
435 | match (*self, *other) { | |
436 | (Trait(_), Trait(_)) => Ordering::Equal, | |
041b39d2 XL |
437 | (Projection(ref a), Projection(ref b)) => |
438 | tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)), | |
476ff2be | 439 | (AutoTrait(ref a), AutoTrait(ref b)) => |
7cac9316 | 440 | tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash), |
476ff2be SL |
441 | (Trait(_), _) => Ordering::Less, |
442 | (Projection(_), Trait(_)) => Ordering::Greater, | |
443 | (Projection(_), _) => Ordering::Less, | |
444 | (AutoTrait(_), _) => Ordering::Greater, | |
445 | } | |
446 | } | |
447 | ||
448 | } | |
449 | ||
450 | impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> { | |
451 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) | |
452 | -> ty::Predicate<'tcx> { | |
453 | use ty::ToPredicate; | |
454 | match *self.skip_binder() { | |
455 | ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(), | |
456 | ExistentialPredicate::Projection(p) => | |
457 | ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))), | |
458 | ExistentialPredicate::AutoTrait(did) => { | |
459 | let trait_ref = Binder(ty::TraitRef { | |
460 | def_id: did, | |
461 | substs: tcx.mk_substs_trait(self_ty, &[]), | |
462 | }); | |
463 | trait_ref.to_predicate() | |
464 | } | |
465 | } | |
466 | } | |
467 | } | |
468 | ||
469 | impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<ExistentialPredicate<'tcx>> {} | |
470 | ||
471 | impl<'tcx> Slice<ExistentialPredicate<'tcx>> { | |
472 | pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> { | |
473 | match self.get(0) { | |
474 | Some(&ExistentialPredicate::Trait(tr)) => Some(tr), | |
cc61c64b | 475 | _ => None, |
476ff2be SL |
476 | } |
477 | } | |
478 | ||
479 | #[inline] | |
480 | pub fn projection_bounds<'a>(&'a self) -> | |
481 | impl Iterator<Item=ExistentialProjection<'tcx>> + 'a { | |
482 | self.iter().filter_map(|predicate| { | |
483 | match *predicate { | |
484 | ExistentialPredicate::Projection(p) => Some(p), | |
485 | _ => None, | |
486 | } | |
487 | }) | |
488 | } | |
489 | ||
490 | #[inline] | |
491 | pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a { | |
492 | self.iter().filter_map(|predicate| { | |
493 | match *predicate { | |
494 | ExistentialPredicate::AutoTrait(d) => Some(d), | |
495 | _ => None | |
496 | } | |
497 | }) | |
498 | } | |
499 | } | |
500 | ||
501 | impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> { | |
502 | pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> { | |
503 | self.skip_binder().principal().map(Binder) | |
504 | } | |
505 | ||
506 | #[inline] | |
507 | pub fn projection_bounds<'a>(&'a self) -> | |
508 | impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a { | |
509 | self.skip_binder().projection_bounds().map(Binder) | |
510 | } | |
511 | ||
512 | #[inline] | |
513 | pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a { | |
514 | self.skip_binder().auto_traits() | |
515 | } | |
516 | ||
517 | pub fn iter<'a>(&'a self) | |
518 | -> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx { | |
519 | self.skip_binder().iter().cloned().map(Binder) | |
520 | } | |
e9174d1e SL |
521 | } |
522 | ||
523 | /// A complete reference to a trait. These take numerous guises in syntax, | |
524 | /// but perhaps the most recognizable form is in a where clause: | |
525 | /// | |
526 | /// T : Foo<U> | |
527 | /// | |
528 | /// This would be represented by a trait-reference where the def-id is the | |
9e0c209e SL |
529 | /// def-id for the trait `Foo` and the substs define `T` as parameter 0, |
530 | /// and `U` as parameter 1. | |
e9174d1e SL |
531 | /// |
532 | /// Trait references also appear in object types like `Foo<U>`, but in | |
533 | /// that case the `Self` parameter is absent from the substitutions. | |
534 | /// | |
535 | /// Note that a `TraitRef` introduces a level of region binding, to | |
536 | /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a | |
537 | /// U>` or higher-ranked object types. | |
9e0c209e | 538 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
539 | pub struct TraitRef<'tcx> { |
540 | pub def_id: DefId, | |
541 | pub substs: &'tcx Substs<'tcx>, | |
542 | } | |
543 | ||
8bb4bdeb XL |
544 | impl<'tcx> TraitRef<'tcx> { |
545 | pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { | |
546 | TraitRef { def_id: def_id, substs: substs } | |
547 | } | |
548 | ||
549 | pub fn self_ty(&self) -> Ty<'tcx> { | |
550 | self.substs.type_at(0) | |
551 | } | |
552 | ||
553 | pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { | |
554 | // Select only the "input types" from a trait-reference. For | |
555 | // now this is all the types that appear in the | |
556 | // trait-reference, but it should eventually exclude | |
557 | // associated types. | |
558 | self.substs.types() | |
559 | } | |
560 | } | |
561 | ||
e9174d1e SL |
562 | pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>; |
563 | ||
564 | impl<'tcx> PolyTraitRef<'tcx> { | |
565 | pub fn self_ty(&self) -> Ty<'tcx> { | |
566 | self.0.self_ty() | |
567 | } | |
568 | ||
569 | pub fn def_id(&self) -> DefId { | |
570 | self.0.def_id | |
571 | } | |
572 | ||
573 | pub fn substs(&self) -> &'tcx Substs<'tcx> { | |
574 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
575 | self.0.substs | |
576 | } | |
577 | ||
9e0c209e | 578 | pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { |
e9174d1e SL |
579 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> |
580 | self.0.input_types() | |
581 | } | |
582 | ||
583 | pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { | |
584 | // Note that we preserve binding levels | |
585 | Binder(ty::TraitPredicate { trait_ref: self.0.clone() }) | |
586 | } | |
587 | } | |
588 | ||
9e0c209e SL |
589 | /// An existential reference to a trait, where `Self` is erased. |
590 | /// For example, the trait object `Trait<'a, 'b, X, Y>` is: | |
591 | /// | |
592 | /// exists T. T: Trait<'a, 'b, X, Y> | |
593 | /// | |
594 | /// The substitutions don't include the erased `Self`, only trait | |
595 | /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). | |
596 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] | |
597 | pub struct ExistentialTraitRef<'tcx> { | |
598 | pub def_id: DefId, | |
599 | pub substs: &'tcx Substs<'tcx>, | |
600 | } | |
601 | ||
476ff2be SL |
602 | impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { |
603 | pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'b { | |
9e0c209e SL |
604 | // Select only the "input types" from a trait-reference. For |
605 | // now this is all the types that appear in the | |
606 | // trait-reference, but it should eventually exclude | |
607 | // associated types. | |
608 | self.substs.types() | |
609 | } | |
476ff2be SL |
610 | |
611 | /// Object types don't have a self-type specified. Therefore, when | |
612 | /// we convert the principal trait-ref into a normal trait-ref, | |
613 | /// you must give *some* self-type. A common choice is `mk_err()` | |
614 | /// or some skolemized type. | |
615 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) | |
616 | -> ty::TraitRef<'tcx> { | |
617 | // otherwise the escaping regions would be captured by the binder | |
618 | assert!(!self_ty.has_escaping_regions()); | |
619 | ||
620 | ty::TraitRef { | |
621 | def_id: self.def_id, | |
622 | substs: tcx.mk_substs( | |
623 | iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())) | |
624 | } | |
625 | } | |
9e0c209e SL |
626 | } |
627 | ||
628 | pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>; | |
629 | ||
630 | impl<'tcx> PolyExistentialTraitRef<'tcx> { | |
631 | pub fn def_id(&self) -> DefId { | |
632 | self.0.def_id | |
633 | } | |
634 | ||
635 | pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { | |
636 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
637 | self.0.input_types() | |
638 | } | |
639 | } | |
640 | ||
e9174d1e SL |
641 | /// Binder is a binder for higher-ranked lifetimes. It is part of the |
642 | /// compiler's representation for things like `for<'a> Fn(&'a isize)` | |
643 | /// (which would be represented by the type `PolyTraitRef == | |
644 | /// Binder<TraitRef>`). Note that when we skolemize, instantiate, | |
645 | /// erase, or otherwise "discharge" these bound regions, we change the | |
646 | /// type from `Binder<T>` to just `T` (see | |
647 | /// e.g. `liberate_late_bound_regions`). | |
2c00a5a8 | 648 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
649 | pub struct Binder<T>(pub T); |
650 | ||
651 | impl<T> Binder<T> { | |
ff7c6d11 XL |
652 | /// Wraps `value` in a binder, asserting that `value` does not |
653 | /// contain any bound regions that would be bound by the | |
654 | /// binder. This is commonly used to 'inject' a value T into a | |
655 | /// different binding level. | |
656 | pub fn dummy<'tcx>(value: T) -> Binder<T> | |
657 | where T: TypeFoldable<'tcx> | |
658 | { | |
659 | assert!(!value.has_escaping_regions()); | |
660 | Binder(value) | |
661 | } | |
662 | ||
e9174d1e SL |
663 | /// Skips the binder and returns the "bound" value. This is a |
664 | /// risky thing to do because it's easy to get confused about | |
665 | /// debruijn indices and the like. It is usually better to | |
666 | /// discharge the binder using `no_late_bound_regions` or | |
667 | /// `replace_late_bound_regions` or something like | |
668 | /// that. `skip_binder` is only valid when you are either | |
669 | /// extracting data that has nothing to do with bound regions, you | |
670 | /// are doing some sort of test that does not involve bound | |
671 | /// regions, or you are being very careful about your depth | |
672 | /// accounting. | |
673 | /// | |
674 | /// Some examples where `skip_binder` is reasonable: | |
ff7c6d11 | 675 | /// |
e9174d1e SL |
676 | /// - extracting the def-id from a PolyTraitRef; |
677 | /// - comparing the self type of a PolyTraitRef to see if it is equal to | |
678 | /// a type parameter `X`, since the type `X` does not reference any regions | |
679 | pub fn skip_binder(&self) -> &T { | |
680 | &self.0 | |
681 | } | |
682 | ||
683 | pub fn as_ref(&self) -> Binder<&T> { | |
684 | ty::Binder(&self.0) | |
685 | } | |
686 | ||
cc61c64b | 687 | pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U> |
e9174d1e SL |
688 | where F: FnOnce(&T) -> U |
689 | { | |
690 | self.as_ref().map_bound(f) | |
691 | } | |
692 | ||
cc61c64b | 693 | pub fn map_bound<F, U>(self, f: F) -> Binder<U> |
e9174d1e SL |
694 | where F: FnOnce(T) -> U |
695 | { | |
696 | ty::Binder(f(self.0)) | |
697 | } | |
ff7c6d11 XL |
698 | |
699 | /// Unwraps and returns the value within, but only if it contains | |
700 | /// no bound regions at all. (In other words, if this binder -- | |
701 | /// and indeed any enclosing binder -- doesn't bind anything at | |
702 | /// all.) Otherwise, returns `None`. | |
703 | /// | |
704 | /// (One could imagine having a method that just unwraps a single | |
705 | /// binder, but permits late-bound regions bound by enclosing | |
706 | /// binders, but that would require adjusting the debruijn | |
707 | /// indices, and given the shallow binding structure we often use, | |
708 | /// would not be that useful.) | |
709 | pub fn no_late_bound_regions<'tcx>(self) -> Option<T> | |
710 | where T : TypeFoldable<'tcx> | |
711 | { | |
712 | if self.skip_binder().has_escaping_regions() { | |
713 | None | |
714 | } else { | |
715 | Some(self.skip_binder().clone()) | |
716 | } | |
717 | } | |
718 | ||
719 | /// Given two things that have the same binder level, | |
720 | /// and an operation that wraps on their contents, execute the operation | |
721 | /// and then wrap its result. | |
722 | /// | |
723 | /// `f` should consider bound regions at depth 1 to be free, and | |
724 | /// anything it produces with bound regions at depth 1 will be | |
725 | /// bound in the resulting return value. | |
726 | pub fn fuse<U,F,R>(self, u: Binder<U>, f: F) -> Binder<R> | |
727 | where F: FnOnce(T, U) -> R | |
728 | { | |
729 | ty::Binder(f(self.0, u.0)) | |
730 | } | |
731 | ||
732 | /// Split the contents into two things that share the same binder | |
733 | /// level as the original, returning two distinct binders. | |
734 | /// | |
735 | /// `f` should consider bound regions at depth 1 to be free, and | |
736 | /// anything it produces with bound regions at depth 1 will be | |
737 | /// bound in the resulting return values. | |
738 | pub fn split<U,V,F>(self, f: F) -> (Binder<U>, Binder<V>) | |
739 | where F: FnOnce(T) -> (U, V) | |
740 | { | |
741 | let (u, v) = f(self.0); | |
742 | (ty::Binder(u), ty::Binder(v)) | |
743 | } | |
e9174d1e SL |
744 | } |
745 | ||
e9174d1e SL |
746 | /// Represents the projection of an associated type. In explicit UFCS |
747 | /// form this would be written `<T as Trait<..>>::N`. | |
2c00a5a8 | 748 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e | 749 | pub struct ProjectionTy<'tcx> { |
041b39d2 XL |
750 | /// The parameters of the associated item. |
751 | pub substs: &'tcx Substs<'tcx>, | |
e9174d1e | 752 | |
7cac9316 XL |
753 | /// The DefId of the TraitItem for the associated type N. |
754 | /// | |
755 | /// Note that this is not the DefId of the TraitRef containing this | |
756 | /// associated type, which is in tcx.associated_item(item_def_id).container. | |
757 | pub item_def_id: DefId, | |
e9174d1e | 758 | } |
7cac9316 XL |
759 | |
760 | impl<'a, 'tcx> ProjectionTy<'tcx> { | |
761 | /// Construct a ProjectionTy by searching the trait from trait_ref for the | |
762 | /// associated item named item_name. | |
763 | pub fn from_ref_and_name( | |
764 | tcx: TyCtxt, trait_ref: ty::TraitRef<'tcx>, item_name: Name | |
765 | ) -> ProjectionTy<'tcx> { | |
ea8adc8c XL |
766 | let item_def_id = tcx.associated_items(trait_ref.def_id).find(|item| { |
767 | item.kind == ty::AssociatedKind::Type && | |
768 | tcx.hygienic_eq(item_name, item.name, trait_ref.def_id) | |
769 | }).unwrap().def_id; | |
7cac9316 XL |
770 | |
771 | ProjectionTy { | |
041b39d2 XL |
772 | substs: trait_ref.substs, |
773 | item_def_id, | |
7cac9316 XL |
774 | } |
775 | } | |
776 | ||
041b39d2 XL |
777 | /// Extracts the underlying trait reference from this projection. |
778 | /// For example, if this is a projection of `<T as Iterator>::Item`, | |
779 | /// then this function would return a `T: Iterator` trait reference. | |
780 | pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> { | |
781 | let def_id = tcx.associated_item(self.item_def_id).container.id(); | |
782 | ty::TraitRef { | |
3b2f2976 | 783 | def_id, |
041b39d2 XL |
784 | substs: self.substs, |
785 | } | |
786 | } | |
787 | ||
788 | pub fn self_ty(&self) -> Ty<'tcx> { | |
789 | self.substs.type_at(0) | |
7cac9316 XL |
790 | } |
791 | } | |
792 | ||
ea8adc8c XL |
793 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
794 | pub struct GenSig<'tcx> { | |
795 | pub yield_ty: Ty<'tcx>, | |
796 | pub return_ty: Ty<'tcx>, | |
797 | } | |
798 | ||
799 | pub type PolyGenSig<'tcx> = Binder<GenSig<'tcx>>; | |
800 | ||
801 | impl<'tcx> PolyGenSig<'tcx> { | |
802 | pub fn yield_ty(&self) -> ty::Binder<Ty<'tcx>> { | |
803 | self.map_bound_ref(|sig| sig.yield_ty) | |
804 | } | |
805 | pub fn return_ty(&self) -> ty::Binder<Ty<'tcx>> { | |
806 | self.map_bound_ref(|sig| sig.return_ty) | |
807 | } | |
808 | } | |
7cac9316 | 809 | |
e9174d1e SL |
810 | /// Signature of a function type, which I have arbitrarily |
811 | /// decided to use to refer to the input/output types. | |
812 | /// | |
813 | /// - `inputs` is the list of arguments and their modes. | |
814 | /// - `output` is the return type. | |
815 | /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) | |
8bb4bdeb | 816 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 817 | pub struct FnSig<'tcx> { |
476ff2be | 818 | pub inputs_and_output: &'tcx Slice<Ty<'tcx>>, |
8bb4bdeb XL |
819 | pub variadic: bool, |
820 | pub unsafety: hir::Unsafety, | |
821 | pub abi: abi::Abi, | |
e9174d1e SL |
822 | } |
823 | ||
476ff2be | 824 | impl<'tcx> FnSig<'tcx> { |
8bb4bdeb | 825 | pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { |
476ff2be SL |
826 | &self.inputs_and_output[..self.inputs_and_output.len() - 1] |
827 | } | |
828 | ||
829 | pub fn output(&self) -> Ty<'tcx> { | |
830 | self.inputs_and_output[self.inputs_and_output.len() - 1] | |
831 | } | |
832 | } | |
833 | ||
e9174d1e SL |
834 | pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>; |
835 | ||
836 | impl<'tcx> PolyFnSig<'tcx> { | |
8bb4bdeb | 837 | pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { |
476ff2be | 838 | Binder(self.skip_binder().inputs()) |
e9174d1e SL |
839 | } |
840 | pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { | |
476ff2be | 841 | self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) |
e9174d1e | 842 | } |
ff7c6d11 XL |
843 | pub fn inputs_and_output(&self) -> ty::Binder<&'tcx Slice<Ty<'tcx>>> { |
844 | self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) | |
845 | } | |
5bcae85e | 846 | pub fn output(&self) -> ty::Binder<Ty<'tcx>> { |
476ff2be | 847 | self.map_bound_ref(|fn_sig| fn_sig.output().clone()) |
e9174d1e SL |
848 | } |
849 | pub fn variadic(&self) -> bool { | |
850 | self.skip_binder().variadic | |
851 | } | |
8bb4bdeb XL |
852 | pub fn unsafety(&self) -> hir::Unsafety { |
853 | self.skip_binder().unsafety | |
854 | } | |
855 | pub fn abi(&self) -> abi::Abi { | |
856 | self.skip_binder().abi | |
857 | } | |
e9174d1e SL |
858 | } |
859 | ||
9e0c209e | 860 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 861 | pub struct ParamTy { |
e9174d1e SL |
862 | pub idx: u32, |
863 | pub name: Name, | |
864 | } | |
865 | ||
a7813a04 | 866 | impl<'a, 'gcx, 'tcx> ParamTy { |
9e0c209e SL |
867 | pub fn new(index: u32, name: Name) -> ParamTy { |
868 | ParamTy { idx: index, name: name } | |
e9174d1e SL |
869 | } |
870 | ||
871 | pub fn for_self() -> ParamTy { | |
9e0c209e | 872 | ParamTy::new(0, keywords::SelfType.name()) |
e9174d1e SL |
873 | } |
874 | ||
875 | pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { | |
9e0c209e | 876 | ParamTy::new(def.index, def.name) |
e9174d1e SL |
877 | } |
878 | ||
a7813a04 | 879 | pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { |
9e0c209e | 880 | tcx.mk_param(self.idx, self.name) |
e9174d1e SL |
881 | } |
882 | ||
883 | pub fn is_self(&self) -> bool { | |
9e0c209e SL |
884 | if self.name == keywords::SelfType.name() { |
885 | assert_eq!(self.idx, 0); | |
886 | true | |
887 | } else { | |
888 | false | |
889 | } | |
e9174d1e SL |
890 | } |
891 | } | |
892 | ||
893 | /// A [De Bruijn index][dbi] is a standard means of representing | |
894 | /// regions (and perhaps later types) in a higher-ranked setting. In | |
895 | /// particular, imagine a type like this: | |
896 | /// | |
897 | /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) | |
898 | /// ^ ^ | | | | |
899 | /// | | | | | | |
900 | /// | +------------+ 1 | | | |
901 | /// | | | | |
902 | /// +--------------------------------+ 2 | | |
903 | /// | | | |
904 | /// +------------------------------------------+ 1 | |
905 | /// | |
906 | /// In this type, there are two binders (the outer fn and the inner | |
907 | /// fn). We need to be able to determine, for any given region, which | |
908 | /// fn type it is bound by, the inner or the outer one. There are | |
909 | /// various ways you can do this, but a De Bruijn index is one of the | |
910 | /// more convenient and has some nice properties. The basic idea is to | |
911 | /// count the number of binders, inside out. Some examples should help | |
912 | /// clarify what I mean. | |
913 | /// | |
914 | /// Let's start with the reference type `&'b isize` that is the first | |
915 | /// argument to the inner function. This region `'b` is assigned a De | |
916 | /// Bruijn index of 1, meaning "the innermost binder" (in this case, a | |
917 | /// fn). The region `'a` that appears in the second argument type (`&'a | |
918 | /// isize`) would then be assigned a De Bruijn index of 2, meaning "the | |
919 | /// second-innermost binder". (These indices are written on the arrays | |
920 | /// in the diagram). | |
921 | /// | |
922 | /// What is interesting is that De Bruijn index attached to a particular | |
923 | /// variable will vary depending on where it appears. For example, | |
924 | /// the final type `&'a char` also refers to the region `'a` declared on | |
925 | /// the outermost fn. But this time, this reference is not nested within | |
926 | /// any other binders (i.e., it is not an argument to the inner fn, but | |
927 | /// rather the outer one). Therefore, in this case, it is assigned a | |
928 | /// De Bruijn index of 1, because the innermost binder in that location | |
929 | /// is the outer fn. | |
930 | /// | |
931 | /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index | |
abe05a73 | 932 | #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy, PartialOrd, Ord)] |
e9174d1e | 933 | pub struct DebruijnIndex { |
7cac9316 XL |
934 | /// We maintain the invariant that this is never 0. So 1 indicates |
935 | /// the innermost binder. To ensure this, create with `DebruijnIndex::new`. | |
e9174d1e SL |
936 | pub depth: u32, |
937 | } | |
938 | ||
7cac9316 XL |
939 | pub type Region<'tcx> = &'tcx RegionKind; |
940 | ||
e9174d1e SL |
941 | /// Representation of regions. |
942 | /// | |
943 | /// Unlike types, most region variants are "fictitious", not concrete, | |
944 | /// regions. Among these, `ReStatic`, `ReEmpty` and `ReScope` are the only | |
945 | /// ones representing concrete regions. | |
946 | /// | |
947 | /// ## Bound Regions | |
948 | /// | |
949 | /// These are regions that are stored behind a binder and must be substituted | |
950 | /// with some concrete region before being used. There are 2 kind of | |
476ff2be | 951 | /// bound regions: early-bound, which are bound in an item's Generics, |
e9174d1e SL |
952 | /// and are substituted by a Substs, and late-bound, which are part of |
953 | /// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by | |
954 | /// the likes of `liberate_late_bound_regions`. The distinction exists | |
955 | /// because higher-ranked lifetimes aren't supported in all places. See [1][2]. | |
956 | /// | |
957 | /// Unlike TyParam-s, bound regions are not supposed to exist "in the wild" | |
958 | /// outside their binder, e.g. in types passed to type inference, and | |
959 | /// should first be substituted (by skolemized regions, free regions, | |
960 | /// or region variables). | |
961 | /// | |
962 | /// ## Skolemized and Free Regions | |
963 | /// | |
964 | /// One often wants to work with bound regions without knowing their precise | |
965 | /// identity. For example, when checking a function, the lifetime of a borrow | |
966 | /// can end up being assigned to some region parameter. In these cases, | |
967 | /// it must be ensured that bounds on the region can't be accidentally | |
968 | /// assumed without being checked. | |
969 | /// | |
970 | /// The process of doing that is called "skolemization". The bound regions | |
971 | /// are replaced by skolemized markers, which don't satisfy any relation | |
3b2f2976 | 972 | /// not explicitly provided. |
e9174d1e SL |
973 | /// |
974 | /// There are 2 kinds of skolemized regions in rustc: `ReFree` and | |
975 | /// `ReSkolemized`. When checking an item's body, `ReFree` is supposed | |
976 | /// to be used. These also support explicit bounds: both the internally-stored | |
977 | /// *scope*, which the region is assumed to outlive, as well as other | |
978 | /// relations stored in the `FreeRegionMap`. Note that these relations | |
a7813a04 | 979 | /// aren't checked when you `make_subregion` (or `eq_types`), only by |
e9174d1e SL |
980 | /// `resolve_regions_and_report_errors`. |
981 | /// | |
982 | /// When working with higher-ranked types, some region relations aren't | |
983 | /// yet known, so you can't just call `resolve_regions_and_report_errors`. | |
984 | /// `ReSkolemized` is designed for this purpose. In these contexts, | |
985 | /// there's also the risk that some inference variable laying around will | |
986 | /// get unified with your skolemized region: if you want to check whether | |
987 | /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a` | |
988 | /// with a skolemized region `'%a`, the variable `'_` would just be | |
989 | /// instantiated to the skolemized region `'%a`, which is wrong because | |
990 | /// the inference variable is supposed to satisfy the relation | |
991 | /// *for every value of the skolemized region*. To ensure that doesn't | |
992 | /// happen, you can use `leak_check`. This is more clearly explained | |
993 | /// by infer/higher_ranked/README.md. | |
994 | /// | |
ff7c6d11 XL |
995 | /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ |
996 | /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ | |
abe05a73 | 997 | #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)] |
7cac9316 | 998 | pub enum RegionKind { |
e9174d1e SL |
999 | // Region bound in a type or fn declaration which will be |
1000 | // substituted 'early' -- that is, at the same time when type | |
1001 | // parameters are substituted. | |
1002 | ReEarlyBound(EarlyBoundRegion), | |
1003 | ||
1004 | // Region bound in a function scope, which will be substituted when the | |
1005 | // function is called. | |
1006 | ReLateBound(DebruijnIndex, BoundRegion), | |
1007 | ||
1008 | /// When checking a function body, the types of all arguments and so forth | |
1009 | /// that refer to bound region parameters are modified to refer to free | |
1010 | /// region parameters. | |
1011 | ReFree(FreeRegion), | |
1012 | ||
ea8adc8c | 1013 | /// A concrete region naming some statically determined scope |
e9174d1e SL |
1014 | /// (e.g. an expression or sequence of statements) within the |
1015 | /// current function. | |
ea8adc8c | 1016 | ReScope(region::Scope), |
e9174d1e SL |
1017 | |
1018 | /// Static data that has an "infinite" lifetime. Top in the region lattice. | |
1019 | ReStatic, | |
1020 | ||
1021 | /// A region variable. Should not exist after typeck. | |
1022 | ReVar(RegionVid), | |
1023 | ||
1024 | /// A skolemized region - basically the higher-ranked version of ReFree. | |
1025 | /// Should not exist after typeck. | |
1026 | ReSkolemized(SkolemizedRegionVid, BoundRegion), | |
1027 | ||
1028 | /// Empty lifetime is for data that is never accessed. | |
1029 | /// Bottom in the region lattice. We treat ReEmpty somewhat | |
1030 | /// specially; at least right now, we do not generate instances of | |
1031 | /// it during the GLB computations, but rather | |
1032 | /// generate an error instead. This is to improve error messages. | |
1033 | /// The only way to get an instance of ReEmpty is to have a region | |
1034 | /// variable with no constraints. | |
1035 | ReEmpty, | |
3157f602 XL |
1036 | |
1037 | /// Erased region, used by trait selection, in MIR and during trans. | |
1038 | ReErased, | |
ff7c6d11 XL |
1039 | |
1040 | /// These are regions bound in the "defining type" for a | |
1041 | /// closure. They are used ONLY as part of the | |
1042 | /// `ClosureRegionRequirements` that are produced by MIR borrowck. | |
1043 | /// See `ClosureRegionRequirements` for more details. | |
1044 | ReClosureBound(RegionVid), | |
e9174d1e SL |
1045 | } |
1046 | ||
7cac9316 | 1047 | impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {} |
9e0c209e | 1048 | |
abe05a73 | 1049 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, PartialOrd, Ord)] |
e9174d1e | 1050 | pub struct EarlyBoundRegion { |
7cac9316 | 1051 | pub def_id: DefId, |
e9174d1e SL |
1052 | pub index: u32, |
1053 | pub name: Name, | |
1054 | } | |
1055 | ||
9e0c209e | 1056 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 1057 | pub struct TyVid { |
3157f602 | 1058 | pub index: u32, |
e9174d1e SL |
1059 | } |
1060 | ||
9e0c209e | 1061 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 1062 | pub struct IntVid { |
cc61c64b | 1063 | pub index: u32, |
e9174d1e SL |
1064 | } |
1065 | ||
9e0c209e | 1066 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 1067 | pub struct FloatVid { |
cc61c64b | 1068 | pub index: u32, |
e9174d1e SL |
1069 | } |
1070 | ||
ff7c6d11 XL |
1071 | newtype_index!(RegionVid |
1072 | { | |
1073 | pub idx | |
1074 | DEBUG_FORMAT = custom, | |
1075 | }); | |
abe05a73 XL |
1076 | |
1077 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)] | |
e9174d1e | 1078 | pub struct SkolemizedRegionVid { |
cc61c64b | 1079 | pub index: u32, |
e9174d1e SL |
1080 | } |
1081 | ||
9e0c209e | 1082 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
1083 | pub enum InferTy { |
1084 | TyVar(TyVid), | |
1085 | IntVar(IntVid), | |
1086 | FloatVar(FloatVid), | |
1087 | ||
1088 | /// A `FreshTy` is one that is generated as a replacement for an | |
1089 | /// unbound type variable. This is convenient for caching etc. See | |
54a0048b | 1090 | /// `infer::freshen` for more details. |
e9174d1e SL |
1091 | FreshTy(u32), |
1092 | FreshIntTy(u32), | |
cc61c64b | 1093 | FreshFloatTy(u32), |
e9174d1e SL |
1094 | } |
1095 | ||
9e0c209e SL |
1096 | /// A `ProjectionPredicate` for an `ExistentialTraitRef`. |
1097 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] | |
1098 | pub struct ExistentialProjection<'tcx> { | |
041b39d2 XL |
1099 | pub item_def_id: DefId, |
1100 | pub substs: &'tcx Substs<'tcx>, | |
cc61c64b | 1101 | pub ty: Ty<'tcx>, |
e9174d1e SL |
1102 | } |
1103 | ||
9e0c209e SL |
1104 | pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>; |
1105 | ||
476ff2be | 1106 | impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { |
041b39d2 XL |
1107 | /// Extracts the underlying existential trait reference from this projection. |
1108 | /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`, | |
1109 | /// then this function would return a `exists T. T: Iterator` existential trait | |
1110 | /// reference. | |
1111 | pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> { | |
1112 | let def_id = tcx.associated_item(self.item_def_id).container.id(); | |
1113 | ty::ExistentialTraitRef{ | |
3b2f2976 | 1114 | def_id, |
041b39d2 XL |
1115 | substs: self.substs, |
1116 | } | |
9e0c209e SL |
1117 | } |
1118 | ||
1119 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
1120 | self_ty: Ty<'tcx>) | |
476ff2be | 1121 | -> ty::ProjectionPredicate<'tcx> |
9e0c209e SL |
1122 | { |
1123 | // otherwise the escaping regions would be captured by the binders | |
1124 | assert!(!self_ty.has_escaping_regions()); | |
1125 | ||
476ff2be | 1126 | ty::ProjectionPredicate { |
041b39d2 XL |
1127 | projection_ty: ty::ProjectionTy { |
1128 | item_def_id: self.item_def_id, | |
1129 | substs: tcx.mk_substs( | |
1130 | iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())), | |
1131 | }, | |
cc61c64b | 1132 | ty: self.ty, |
476ff2be | 1133 | } |
e9174d1e SL |
1134 | } |
1135 | } | |
1136 | ||
476ff2be | 1137 | impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { |
476ff2be SL |
1138 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) |
1139 | -> ty::PolyProjectionPredicate<'tcx> { | |
1140 | self.map_bound(|p| p.with_self_ty(tcx, self_ty)) | |
e9174d1e SL |
1141 | } |
1142 | } | |
1143 | ||
1144 | impl DebruijnIndex { | |
1145 | pub fn new(depth: u32) -> DebruijnIndex { | |
1146 | assert!(depth > 0); | |
1147 | DebruijnIndex { depth: depth } | |
1148 | } | |
1149 | ||
1150 | pub fn shifted(&self, amount: u32) -> DebruijnIndex { | |
1151 | DebruijnIndex { depth: self.depth + amount } | |
1152 | } | |
1153 | } | |
1154 | ||
7cac9316 XL |
1155 | /// Region utilities |
1156 | impl RegionKind { | |
1157 | pub fn is_late_bound(&self) -> bool { | |
e9174d1e | 1158 | match *self { |
e9174d1e | 1159 | ty::ReLateBound(..) => true, |
cc61c64b | 1160 | _ => false, |
e9174d1e SL |
1161 | } |
1162 | } | |
1163 | ||
1164 | pub fn needs_infer(&self) -> bool { | |
1165 | match *self { | |
1166 | ty::ReVar(..) | ty::ReSkolemized(..) => true, | |
1167 | _ => false | |
1168 | } | |
1169 | } | |
1170 | ||
1171 | pub fn escapes_depth(&self, depth: u32) -> bool { | |
1172 | match *self { | |
1173 | ty::ReLateBound(debruijn, _) => debruijn.depth > depth, | |
1174 | _ => false, | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | /// Returns the depth of `self` from the (1-based) binding level `depth` | |
7cac9316 | 1179 | pub fn from_depth(&self, depth: u32) -> RegionKind { |
e9174d1e SL |
1180 | match *self { |
1181 | ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex { | |
1182 | depth: debruijn.depth - (depth - 1) | |
1183 | }, r), | |
1184 | r => r | |
1185 | } | |
1186 | } | |
c30ab7b3 SL |
1187 | |
1188 | pub fn type_flags(&self) -> TypeFlags { | |
1189 | let mut flags = TypeFlags::empty(); | |
1190 | ||
1191 | match *self { | |
1192 | ty::ReVar(..) => { | |
ff7c6d11 | 1193 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
c30ab7b3 SL |
1194 | flags = flags | TypeFlags::HAS_RE_INFER; |
1195 | flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; | |
1196 | } | |
1197 | ty::ReSkolemized(..) => { | |
ff7c6d11 | 1198 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
c30ab7b3 SL |
1199 | flags = flags | TypeFlags::HAS_RE_INFER; |
1200 | flags = flags | TypeFlags::HAS_RE_SKOL; | |
1201 | flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; | |
1202 | } | |
1203 | ty::ReLateBound(..) => { } | |
ff7c6d11 XL |
1204 | ty::ReEarlyBound(..) => { |
1205 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1206 | flags = flags | TypeFlags::HAS_RE_EARLY_BOUND; | |
1207 | } | |
1208 | ty::ReEmpty | | |
1209 | ty::ReStatic | | |
1210 | ty::ReFree { .. } | | |
1211 | ty::ReScope { .. } => { | |
1212 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1213 | } | |
1214 | ty::ReErased => { | |
1215 | } | |
1216 | ty::ReClosureBound(..) => { | |
1217 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1218 | } | |
c30ab7b3 SL |
1219 | } |
1220 | ||
1221 | match *self { | |
1222 | ty::ReStatic | ty::ReEmpty | ty::ReErased => (), | |
1223 | _ => flags = flags | TypeFlags::HAS_LOCAL_NAMES, | |
1224 | } | |
1225 | ||
1226 | debug!("type_flags({:?}) = {:?}", self, flags); | |
1227 | ||
1228 | flags | |
1229 | } | |
abe05a73 XL |
1230 | |
1231 | /// Given an early-bound or free region, returns the def-id where it was bound. | |
1232 | /// For example, consider the regions in this snippet of code: | |
1233 | /// | |
1234 | /// ``` | |
1235 | /// impl<'a> Foo { | |
1236 | /// ^^ -- early bound, declared on an impl | |
1237 | /// | |
1238 | /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c | |
1239 | /// ^^ ^^ ^ anonymous, late-bound | |
1240 | /// | early-bound, appears in where-clauses | |
1241 | /// late-bound, appears only in fn args | |
1242 | /// {..} | |
1243 | /// } | |
1244 | /// ``` | |
1245 | /// | |
1246 | /// Here, `free_region_binding_scope('a)` would return the def-id | |
1247 | /// of the impl, and for all the other highlighted regions, it | |
1248 | /// would return the def-id of the function. In other cases (not shown), this | |
1249 | /// function might return the def-id of a closure. | |
1250 | pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_, '_, '_>) -> DefId { | |
1251 | match self { | |
1252 | ty::ReEarlyBound(br) => { | |
1253 | tcx.parent_def_id(br.def_id).unwrap() | |
1254 | } | |
1255 | ty::ReFree(fr) => fr.scope, | |
1256 | _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), | |
1257 | } | |
1258 | } | |
e9174d1e SL |
1259 | } |
1260 | ||
7cac9316 | 1261 | /// Type utilities |
a7813a04 | 1262 | impl<'a, 'gcx, 'tcx> TyS<'tcx> { |
e9174d1e SL |
1263 | pub fn is_nil(&self) -> bool { |
1264 | match self.sty { | |
8bb4bdeb | 1265 | TyTuple(ref tys, _) => tys.is_empty(), |
cc61c64b | 1266 | _ => false, |
e9174d1e SL |
1267 | } |
1268 | } | |
1269 | ||
5bcae85e SL |
1270 | pub fn is_never(&self) -> bool { |
1271 | match self.sty { | |
1272 | TyNever => true, | |
1273 | _ => false, | |
1274 | } | |
1275 | } | |
1276 | ||
7cac9316 XL |
1277 | /// Test whether this is a `()` which was produced by defaulting a |
1278 | /// diverging type variable with feature(never_type) disabled. | |
8bb4bdeb XL |
1279 | pub fn is_defaulted_unit(&self) -> bool { |
1280 | match self.sty { | |
1281 | TyTuple(_, true) => true, | |
1282 | _ => false, | |
1283 | } | |
1284 | } | |
1285 | ||
9cc50fc6 SL |
1286 | pub fn is_primitive(&self) -> bool { |
1287 | match self.sty { | |
1288 | TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true, | |
1289 | _ => false, | |
1290 | } | |
1291 | } | |
1292 | ||
e9174d1e SL |
1293 | pub fn is_ty_var(&self) -> bool { |
1294 | match self.sty { | |
1295 | TyInfer(TyVar(_)) => true, | |
cc61c64b | 1296 | _ => false, |
e9174d1e SL |
1297 | } |
1298 | } | |
1299 | ||
b039eaaf | 1300 | pub fn is_phantom_data(&self) -> bool { |
9e0c209e | 1301 | if let TyAdt(def, _) = self.sty { |
b039eaaf SL |
1302 | def.is_phantom_data() |
1303 | } else { | |
1304 | false | |
1305 | } | |
1306 | } | |
1307 | ||
e9174d1e SL |
1308 | pub fn is_bool(&self) -> bool { self.sty == TyBool } |
1309 | ||
9e0c209e | 1310 | pub fn is_param(&self, index: u32) -> bool { |
e9174d1e | 1311 | match self.sty { |
9e0c209e | 1312 | ty::TyParam(ref data) => data.idx == index, |
e9174d1e SL |
1313 | _ => false, |
1314 | } | |
1315 | } | |
1316 | ||
1317 | pub fn is_self(&self) -> bool { | |
1318 | match self.sty { | |
9e0c209e | 1319 | TyParam(ref p) => p.is_self(), |
cc61c64b | 1320 | _ => false, |
e9174d1e SL |
1321 | } |
1322 | } | |
1323 | ||
54a0048b | 1324 | pub fn is_slice(&self) -> bool { |
e9174d1e SL |
1325 | match self.sty { |
1326 | TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty { | |
1327 | TySlice(_) | TyStr => true, | |
1328 | _ => false, | |
1329 | }, | |
1330 | _ => false | |
1331 | } | |
1332 | } | |
1333 | ||
e9174d1e SL |
1334 | #[inline] |
1335 | pub fn is_simd(&self) -> bool { | |
1336 | match self.sty { | |
cc61c64b XL |
1337 | TyAdt(def, _) => def.repr.simd(), |
1338 | _ => false, | |
e9174d1e SL |
1339 | } |
1340 | } | |
1341 | ||
a7813a04 | 1342 | pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1343 | match self.sty { |
1344 | TyArray(ty, _) | TySlice(ty) => ty, | |
a7813a04 | 1345 | TyStr => tcx.mk_mach_uint(ast::UintTy::U8), |
54a0048b | 1346 | _ => bug!("sequence_element_type called on non-sequence value: {}", self), |
e9174d1e SL |
1347 | } |
1348 | } | |
1349 | ||
a7813a04 | 1350 | pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { |
e9174d1e | 1351 | match self.sty { |
9e0c209e | 1352 | TyAdt(def, substs) => { |
2c00a5a8 | 1353 | def.non_enum_variant().fields[0].ty(tcx, substs) |
e9174d1e | 1354 | } |
54a0048b | 1355 | _ => bug!("simd_type called on invalid type") |
e9174d1e SL |
1356 | } |
1357 | } | |
1358 | ||
a7813a04 | 1359 | pub fn simd_size(&self, _cx: TyCtxt) -> usize { |
e9174d1e | 1360 | match self.sty { |
2c00a5a8 | 1361 | TyAdt(def, _) => def.non_enum_variant().fields.len(), |
54a0048b | 1362 | _ => bug!("simd_size called on invalid type") |
e9174d1e SL |
1363 | } |
1364 | } | |
1365 | ||
1366 | pub fn is_region_ptr(&self) -> bool { | |
1367 | match self.sty { | |
1368 | TyRef(..) => true, | |
cc61c64b | 1369 | _ => false, |
e9174d1e SL |
1370 | } |
1371 | } | |
1372 | ||
32a655c1 SL |
1373 | pub fn is_mutable_pointer(&self) -> bool { |
1374 | match self.sty { | |
1375 | TyRawPtr(tnm) | TyRef(_, tnm) => if let hir::Mutability::MutMutable = tnm.mutbl { | |
1376 | true | |
1377 | } else { | |
1378 | false | |
1379 | }, | |
1380 | _ => false | |
1381 | } | |
1382 | } | |
1383 | ||
e9174d1e SL |
1384 | pub fn is_unsafe_ptr(&self) -> bool { |
1385 | match self.sty { | |
1386 | TyRawPtr(_) => return true, | |
cc61c64b | 1387 | _ => return false, |
e9174d1e SL |
1388 | } |
1389 | } | |
1390 | ||
32a655c1 | 1391 | pub fn is_box(&self) -> bool { |
e9174d1e | 1392 | match self.sty { |
32a655c1 SL |
1393 | TyAdt(def, _) => def.is_box(), |
1394 | _ => false, | |
1395 | } | |
1396 | } | |
1397 | ||
7cac9316 | 1398 | /// panics if called on any type other than `Box<T>` |
32a655c1 SL |
1399 | pub fn boxed_ty(&self) -> Ty<'tcx> { |
1400 | match self.sty { | |
1401 | TyAdt(def, substs) if def.is_box() => substs.type_at(0), | |
1402 | _ => bug!("`boxed_ty` is called on non-box type {:?}", self), | |
e9174d1e SL |
1403 | } |
1404 | } | |
1405 | ||
7cac9316 XL |
1406 | /// A scalar type is one that denotes an atomic datum, with no sub-components. |
1407 | /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its | |
1408 | /// contents are abstract to rustc.) | |
e9174d1e SL |
1409 | pub fn is_scalar(&self) -> bool { |
1410 | match self.sty { | |
1411 | TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | | |
1412 | TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) | | |
54a0048b | 1413 | TyFnDef(..) | TyFnPtr(_) | TyRawPtr(_) => true, |
e9174d1e SL |
1414 | _ => false |
1415 | } | |
1416 | } | |
1417 | ||
1418 | /// Returns true if this type is a floating point type and false otherwise. | |
1419 | pub fn is_floating_point(&self) -> bool { | |
1420 | match self.sty { | |
1421 | TyFloat(_) | | |
1422 | TyInfer(FloatVar(_)) => true, | |
1423 | _ => false, | |
1424 | } | |
1425 | } | |
1426 | ||
1427 | pub fn is_trait(&self) -> bool { | |
1428 | match self.sty { | |
476ff2be | 1429 | TyDynamic(..) => true, |
cc61c64b | 1430 | _ => false, |
e9174d1e SL |
1431 | } |
1432 | } | |
1433 | ||
ff7c6d11 XL |
1434 | pub fn is_enum(&self) -> bool { |
1435 | match self.sty { | |
1436 | TyAdt(adt_def, _) => { | |
1437 | adt_def.is_enum() | |
1438 | } | |
1439 | _ => false, | |
1440 | } | |
1441 | } | |
1442 | ||
7cac9316 XL |
1443 | pub fn is_closure(&self) -> bool { |
1444 | match self.sty { | |
1445 | TyClosure(..) => true, | |
1446 | _ => false, | |
1447 | } | |
1448 | } | |
1449 | ||
ff7c6d11 XL |
1450 | pub fn is_generator(&self) -> bool { |
1451 | match self.sty { | |
1452 | TyGenerator(..) => true, | |
1453 | _ => false, | |
1454 | } | |
1455 | } | |
1456 | ||
e9174d1e SL |
1457 | pub fn is_integral(&self) -> bool { |
1458 | match self.sty { | |
1459 | TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, | |
1460 | _ => false | |
1461 | } | |
1462 | } | |
1463 | ||
ff7c6d11 XL |
1464 | pub fn is_fresh_ty(&self) -> bool { |
1465 | match self.sty { | |
1466 | TyInfer(FreshTy(_)) => true, | |
1467 | _ => false, | |
1468 | } | |
1469 | } | |
1470 | ||
e9174d1e SL |
1471 | pub fn is_fresh(&self) -> bool { |
1472 | match self.sty { | |
1473 | TyInfer(FreshTy(_)) => true, | |
1474 | TyInfer(FreshIntTy(_)) => true, | |
1475 | TyInfer(FreshFloatTy(_)) => true, | |
cc61c64b | 1476 | _ => false, |
e9174d1e SL |
1477 | } |
1478 | } | |
1479 | ||
e9174d1e SL |
1480 | pub fn is_char(&self) -> bool { |
1481 | match self.sty { | |
1482 | TyChar => true, | |
cc61c64b | 1483 | _ => false, |
e9174d1e SL |
1484 | } |
1485 | } | |
1486 | ||
e9174d1e SL |
1487 | pub fn is_fp(&self) -> bool { |
1488 | match self.sty { | |
1489 | TyInfer(FloatVar(_)) | TyFloat(_) => true, | |
1490 | _ => false | |
1491 | } | |
1492 | } | |
1493 | ||
1494 | pub fn is_numeric(&self) -> bool { | |
1495 | self.is_integral() || self.is_fp() | |
1496 | } | |
1497 | ||
1498 | pub fn is_signed(&self) -> bool { | |
1499 | match self.sty { | |
1500 | TyInt(_) => true, | |
cc61c64b | 1501 | _ => false, |
e9174d1e SL |
1502 | } |
1503 | } | |
1504 | ||
1505 | pub fn is_machine(&self) -> bool { | |
1506 | match self.sty { | |
2c00a5a8 | 1507 | TyInt(ast::IntTy::Isize) | TyUint(ast::UintTy::Usize) => false, |
e9174d1e | 1508 | TyInt(..) | TyUint(..) | TyFloat(..) => true, |
cc61c64b | 1509 | _ => false, |
e9174d1e SL |
1510 | } |
1511 | } | |
1512 | ||
54a0048b SL |
1513 | pub fn has_concrete_skeleton(&self) -> bool { |
1514 | match self.sty { | |
1515 | TyParam(_) | TyInfer(_) | TyError => false, | |
1516 | _ => true, | |
1517 | } | |
1518 | } | |
1519 | ||
7cac9316 XL |
1520 | /// Returns the type and mutability of *ty. |
1521 | /// | |
1522 | /// The parameter `explicit` indicates if this is an *explicit* dereference. | |
1523 | /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. | |
2c00a5a8 | 1524 | pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> { |
e9174d1e | 1525 | match self.sty { |
32a655c1 | 1526 | TyAdt(def, _) if def.is_box() => { |
e9174d1e | 1527 | Some(TypeAndMut { |
32a655c1 | 1528 | ty: self.boxed_ty(), |
2c00a5a8 | 1529 | mutbl: hir::MutImmutable, |
e9174d1e SL |
1530 | }) |
1531 | }, | |
1532 | TyRef(_, mt) => Some(mt), | |
1533 | TyRawPtr(mt) if explicit => Some(mt), | |
cc61c64b | 1534 | _ => None, |
e9174d1e SL |
1535 | } |
1536 | } | |
1537 | ||
7cac9316 | 1538 | /// Returns the type of ty[i] |
e9174d1e SL |
1539 | pub fn builtin_index(&self) -> Option<Ty<'tcx>> { |
1540 | match self.sty { | |
1541 | TyArray(ty, _) | TySlice(ty) => Some(ty), | |
cc61c64b | 1542 | _ => None, |
e9174d1e SL |
1543 | } |
1544 | } | |
1545 | ||
041b39d2 | 1546 | pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { |
e9174d1e | 1547 | match self.sty { |
041b39d2 XL |
1548 | TyFnDef(def_id, substs) => { |
1549 | tcx.fn_sig(def_id).subst(tcx, substs) | |
1550 | } | |
1551 | TyFnPtr(f) => f, | |
54a0048b | 1552 | _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) |
e9174d1e SL |
1553 | } |
1554 | } | |
1555 | ||
e9174d1e SL |
1556 | pub fn is_fn(&self) -> bool { |
1557 | match self.sty { | |
54a0048b | 1558 | TyFnDef(..) | TyFnPtr(_) => true, |
cc61c64b | 1559 | _ => false, |
e9174d1e SL |
1560 | } |
1561 | } | |
1562 | ||
1563 | pub fn ty_to_def_id(&self) -> Option<DefId> { | |
1564 | match self.sty { | |
476ff2be | 1565 | TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()), |
9e0c209e | 1566 | TyAdt(def, _) => Some(def.did), |
abe05a73 | 1567 | TyForeign(did) => Some(did), |
e9174d1e | 1568 | TyClosure(id, _) => Some(id), |
ff7c6d11 | 1569 | TyFnDef(id, _) => Some(id), |
cc61c64b | 1570 | _ => None, |
e9174d1e SL |
1571 | } |
1572 | } | |
1573 | ||
476ff2be | 1574 | pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { |
e9174d1e | 1575 | match self.sty { |
9e0c209e | 1576 | TyAdt(adt, _) => Some(adt), |
cc61c64b | 1577 | _ => None, |
e9174d1e SL |
1578 | } |
1579 | } | |
1580 | ||
1581 | /// Returns the regions directly referenced from this type (but | |
1582 | /// not types reachable from this type via `walk_tys`). This | |
1583 | /// ignores late-bound regions binders. | |
7cac9316 | 1584 | pub fn regions(&self) -> Vec<ty::Region<'tcx>> { |
e9174d1e SL |
1585 | match self.sty { |
1586 | TyRef(region, _) => { | |
9e0c209e | 1587 | vec![region] |
e9174d1e | 1588 | } |
476ff2be SL |
1589 | TyDynamic(ref obj, region) => { |
1590 | let mut v = vec![region]; | |
1591 | if let Some(p) = obj.principal() { | |
1592 | v.extend(p.skip_binder().substs.regions()); | |
1593 | } | |
e9174d1e SL |
1594 | v |
1595 | } | |
9e0c209e SL |
1596 | TyAdt(_, substs) | TyAnon(_, substs) => { |
1597 | substs.regions().collect() | |
e9174d1e | 1598 | } |
ea8adc8c | 1599 | TyClosure(_, ref substs) | TyGenerator(_, ref substs, _) => { |
476ff2be | 1600 | substs.substs.regions().collect() |
e9174d1e SL |
1601 | } |
1602 | TyProjection(ref data) => { | |
041b39d2 | 1603 | data.substs.regions().collect() |
e9174d1e | 1604 | } |
54a0048b SL |
1605 | TyFnDef(..) | |
1606 | TyFnPtr(_) | | |
2c00a5a8 | 1607 | TyGeneratorWitness(..) | |
e9174d1e SL |
1608 | TyBool | |
1609 | TyChar | | |
1610 | TyInt(_) | | |
1611 | TyUint(_) | | |
1612 | TyFloat(_) | | |
e9174d1e | 1613 | TyStr | |
9e0c209e | 1614 | TyArray(..) | |
e9174d1e SL |
1615 | TySlice(_) | |
1616 | TyRawPtr(_) | | |
5bcae85e | 1617 | TyNever | |
8bb4bdeb | 1618 | TyTuple(..) | |
abe05a73 | 1619 | TyForeign(..) | |
e9174d1e SL |
1620 | TyParam(_) | |
1621 | TyInfer(_) | | |
1622 | TyError => { | |
1623 | vec![] | |
1624 | } | |
1625 | } | |
1626 | } | |
ff7c6d11 XL |
1627 | |
1628 | /// When we create a closure, we record its kind (i.e., what trait | |
1629 | /// it implements) into its `ClosureSubsts` using a type | |
1630 | /// parameter. This is kind of a phantom type, except that the | |
1631 | /// most convenient thing for us to are the integral types. This | |
1632 | /// function converts such a special type into the closure | |
1633 | /// kind. To go the other way, use | |
1634 | /// `tcx.closure_kind_ty(closure_kind)`. | |
1635 | /// | |
1636 | /// Note that during type checking, we use an inference variable | |
1637 | /// to represent the closure kind, because it has not yet been | |
1638 | /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`) | |
1639 | /// is complete, that type variable will be unified. | |
1640 | pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> { | |
1641 | match self.sty { | |
1642 | TyInt(int_ty) => match int_ty { | |
1643 | ast::IntTy::I8 => Some(ty::ClosureKind::Fn), | |
1644 | ast::IntTy::I16 => Some(ty::ClosureKind::FnMut), | |
1645 | ast::IntTy::I32 => Some(ty::ClosureKind::FnOnce), | |
1646 | _ => bug!("cannot convert type `{:?}` to a closure kind", self), | |
1647 | }, | |
1648 | ||
1649 | TyInfer(_) => None, | |
1650 | ||
1651 | TyError => Some(ty::ClosureKind::Fn), | |
1652 | ||
1653 | _ => bug!("cannot convert type `{:?}` to a closure kind", self), | |
1654 | } | |
1655 | } | |
e9174d1e | 1656 | } |
ea8adc8c XL |
1657 | |
1658 | /// Typed constant value. | |
1659 | #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)] | |
1660 | pub struct Const<'tcx> { | |
1661 | pub ty: Ty<'tcx>, | |
1662 | ||
1663 | // FIXME(eddyb) Replace this with a miri value. | |
1664 | pub val: ConstVal<'tcx>, | |
1665 | } | |
1666 | ||
1667 | impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} |