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