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