]> git.proxmox.com Git - rustc.git/blob - src/librustc/ty/sty.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / librustc / ty / sty.rs
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
13 use hir::def_id::DefId;
14
15 use middle::region;
16 use ty::subst::{Substs, Subst};
17 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
18 use ty::{Slice, TyS};
19 use ty::subst::Kind;
20
21 use std::fmt;
22 use std::iter;
23 use std::cmp::Ordering;
24 use syntax::abi;
25 use syntax::ast::{self, Name};
26 use syntax::symbol::keywords;
27 use util::nodemap::FxHashMap;
28
29 use serialize;
30
31 use hir;
32
33 use self::InferTy::*;
34 use self::TypeVariants::*;
35
36 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
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: DefId,
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.
61 BrNamed(DefId, Name),
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
71 impl BoundRegion {
72 pub fn is_named(&self) -> bool {
73 match *self {
74 BoundRegion::BrNamed(..) => true,
75 _ => false,
76 }
77 }
78 }
79
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.
83 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash,
84 RustcEncodable, RustcDecodable)]
85 pub struct Issue32330 {
86 /// fn where is region declared
87 pub fn_def_id: DefId,
88
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,
92 }
93
94 /// NB: If you change this, you'll probably want to change the corresponding
95 /// AST structure in libsyntax/ast.rs as well.
96 #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
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`.
106 TyInt(ast::IntTy),
107
108 /// A primitive unsigned integer type. For example, `u32`.
109 TyUint(ast::UintTy),
110
111 /// A primitive floating-point type. For example, `f64`.
112 TyFloat(ast::FloatTy),
113
114 /// Structures, enumerations and unions.
115 ///
116 /// Substs here, possibly against intuition, *may* contain `TyParam`s.
117 /// That is, even after substitution it is possible that there are type
118 /// variables. This happens when the `TyAdt` corresponds to an ADT
119 /// definition and not a concrete use of it.
120 TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>),
121
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
135 /// `&'a mut T` or `&'a T`.
136 TyRef(Region<'tcx>, TypeAndMut<'tcx>),
137
138 /// The anonymous type of a function declaration/definition. Each
139 /// function has a unique type.
140 TyFnDef(DefId, &'tcx Substs<'tcx>),
141
142 /// A pointer to a function. Written as `fn() -> i32`.
143 TyFnPtr(PolyFnSig<'tcx>),
144
145 /// A trait, defined with `trait`.
146 TyDynamic(Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
147
148 /// The anonymous type of a closure. Used to represent the type of
149 /// `|a| a`.
150 TyClosure(DefId, ClosureSubsts<'tcx>),
151
152 /// The never type `!`
153 TyNever,
154
155 /// A tuple type. For example, `(i32, bool)`.
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),
161
162 /// The projection of an associated type. For example,
163 /// `<T as Trait<..>>::N`.
164 TyProjection(ProjectionTy<'tcx>),
165
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.
169 /// After typeck, the concrete type can be found in the `types` map.
170 TyAnon(DefId, &'tcx Substs<'tcx>),
171
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
257 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
258 pub struct ClosureSubsts<'tcx> {
259 /// Lifetime and type parameters from the enclosing function,
260 /// concatenated with the types of the upvars.
261 ///
262 /// These are separated out because trans wants to pass them around
263 /// when monomorphizing.
264 pub substs: &'tcx Substs<'tcx>,
265 }
266
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 {
272 let generics = tcx.generics_of(def_id);
273 self.substs[self.substs.len()-generics.own_count()..].iter().map(
274 |t| t.as_type().expect("unexpected region in upvars"))
275 }
276 }
277
278 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
279 pub enum ExistentialPredicate<'tcx> {
280 /// e.g. Iterator
281 Trait(ExistentialTraitRef<'tcx>),
282 /// e.g. Iterator::Item = T
283 Projection(ExistentialProjection<'tcx>),
284 /// e.g. Send
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,
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)),
295 (AutoTrait(ref a), AutoTrait(ref b)) =>
296 tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash),
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),
331 _ => None,
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 }
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
385 /// def-id for the trait `Foo` and the substs define `T` as parameter 0,
386 /// and `U` as parameter 1.
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.
394 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
395 pub struct TraitRef<'tcx> {
396 pub def_id: DefId,
397 pub substs: &'tcx Substs<'tcx>,
398 }
399
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
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
434 pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
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
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
458 impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
459 pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'b {
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 }
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 }
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
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`).
504 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
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
531 pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U>
532 where F: FnOnce(&T) -> U
533 {
534 self.as_ref().map_bound(f)
535 }
536
537 pub fn map_bound<F, U>(self, f: F) -> Binder<U>
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 {
546 write!(f, "{:x}", self.bits)
547 }
548 }
549
550 /// Represents the projection of an associated type. In explicit UFCS
551 /// form this would be written `<T as Trait<..>>::N`.
552 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
553 pub struct ProjectionTy<'tcx> {
554 /// The parameters of the associated item.
555 pub substs: &'tcx Substs<'tcx>,
556
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,
562 }
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(
571 |item| item.name == item_name && item.kind == ty::AssociatedKind::Type
572 ).unwrap().def_id;
573
574 ProjectionTy {
575 substs: trait_ref.substs,
576 item_def_id,
577 }
578 }
579
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,
587 substs: self.substs,
588 }
589 }
590
591 pub fn self_ty(&self) -> Ty<'tcx> {
592 self.substs.type_at(0)
593 }
594 }
595
596
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)
603 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
604 pub struct FnSig<'tcx> {
605 pub inputs_and_output: &'tcx Slice<Ty<'tcx>>,
606 pub variadic: bool,
607 pub unsafety: hir::Unsafety,
608 pub abi: abi::Abi,
609 }
610
611 impl<'tcx> FnSig<'tcx> {
612 pub fn inputs(&self) -> &'tcx [Ty<'tcx>] {
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
621 pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
622
623 impl<'tcx> PolyFnSig<'tcx> {
624 pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> {
625 Binder(self.skip_binder().inputs())
626 }
627 pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
628 self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
629 }
630 pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
631 self.map_bound_ref(|fn_sig| fn_sig.output().clone())
632 }
633 pub fn variadic(&self) -> bool {
634 self.skip_binder().variadic
635 }
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 }
642 }
643
644 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
645 pub struct ParamTy {
646 pub idx: u32,
647 pub name: Name,
648 }
649
650 impl<'a, 'gcx, 'tcx> ParamTy {
651 pub fn new(index: u32, name: Name) -> ParamTy {
652 ParamTy { idx: index, name: name }
653 }
654
655 pub fn for_self() -> ParamTy {
656 ParamTy::new(0, keywords::SelfType.name())
657 }
658
659 pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
660 ParamTy::new(def.index, def.name)
661 }
662
663 pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
664 tcx.mk_param(self.idx, self.name)
665 }
666
667 pub fn is_self(&self) -> bool {
668 if self.name == keywords::SelfType.name() {
669 assert_eq!(self.idx, 0);
670 true
671 } else {
672 false
673 }
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 {
718 /// We maintain the invariant that this is never 0. So 1 indicates
719 /// the innermost binder. To ensure this, create with `DebruijnIndex::new`.
720 pub depth: u32,
721 }
722
723 pub type Region<'tcx> = &'tcx RegionKind;
724
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
735 /// bound regions: early-bound, which are bound in an item's Generics,
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 explicitly 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
763 /// aren't checked when you `make_subregion` (or `eq_types`), only by
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/
781 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)]
782 pub enum RegionKind {
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,
820
821 /// Erased region, used by trait selection, in MIR and during trans.
822 ReErased,
823 }
824
825 impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
826
827 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
828 pub struct EarlyBoundRegion {
829 pub def_id: DefId,
830 pub index: u32,
831 pub name: Name,
832 }
833
834 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
835 pub struct TyVid {
836 pub index: u32,
837 }
838
839 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
840 pub struct IntVid {
841 pub index: u32,
842 }
843
844 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
845 pub struct FloatVid {
846 pub index: u32,
847 }
848
849 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
850 pub struct RegionVid {
851 pub index: u32,
852 }
853
854 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
855 pub struct SkolemizedRegionVid {
856 pub index: u32,
857 }
858
859 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
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
867 /// `infer::freshen` for more details.
868 FreshTy(u32),
869 FreshIntTy(u32),
870 FreshFloatTy(u32),
871 }
872
873 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
874 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
875 pub struct ExistentialProjection<'tcx> {
876 pub item_def_id: DefId,
877 pub substs: &'tcx Substs<'tcx>,
878 pub ty: Ty<'tcx>,
879 }
880
881 pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
882
883 impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
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,
892 substs: self.substs,
893 }
894 }
895
896 pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
897 self_ty: Ty<'tcx>)
898 -> ty::ProjectionPredicate<'tcx>
899 {
900 // otherwise the escaping regions would be captured by the binders
901 assert!(!self_ty.has_escaping_regions());
902
903 ty::ProjectionPredicate {
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 },
909 ty: self.ty,
910 }
911 }
912 }
913
914 impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
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))
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
932 /// Region utilities
933 impl RegionKind {
934 pub fn is_late_bound(&self) -> bool {
935 match *self {
936 ty::ReLateBound(..) => true,
937 _ => false,
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`
956 pub fn from_depth(&self, depth: u32) -> RegionKind {
957 match *self {
958 ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex {
959 depth: debruijn.depth - (depth - 1)
960 }, r),
961 r => r
962 }
963 }
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 }
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 }
1006 }
1007
1008 /// Type utilities
1009 impl<'a, 'gcx, 'tcx> TyS<'tcx> {
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 {
1019 TyTuple(ref tys, _) => tys.is_empty(),
1020 _ => false,
1021 }
1022 }
1023
1024 pub fn is_never(&self) -> bool {
1025 match self.sty {
1026 TyNever => true,
1027 _ => false,
1028 }
1029 }
1030
1031 /// Test whether this is a `()` which was produced by defaulting a
1032 /// diverging type variable with feature(never_type) disabled.
1033 pub fn is_defaulted_unit(&self) -> bool {
1034 match self.sty {
1035 TyTuple(_, true) => true,
1036 _ => false,
1037 }
1038 }
1039
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 {
1077 let mut visited = FxHashMap::default();
1078 let forest = self.uninhabited_from(&mut visited, tcx);
1079
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)
1086 }
1087
1088 pub fn is_primitive(&self) -> bool {
1089 match self.sty {
1090 TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,
1091 _ => false,
1092 }
1093 }
1094
1095 pub fn is_ty_var(&self) -> bool {
1096 match self.sty {
1097 TyInfer(TyVar(_)) => true,
1098 _ => false,
1099 }
1100 }
1101
1102 pub fn is_phantom_data(&self) -> bool {
1103 if let TyAdt(def, _) = self.sty {
1104 def.is_phantom_data()
1105 } else {
1106 false
1107 }
1108 }
1109
1110 pub fn is_bool(&self) -> bool { self.sty == TyBool }
1111
1112 pub fn is_param(&self, index: u32) -> bool {
1113 match self.sty {
1114 ty::TyParam(ref data) => data.idx == index,
1115 _ => false,
1116 }
1117 }
1118
1119 pub fn is_self(&self) -> bool {
1120 match self.sty {
1121 TyParam(ref p) => p.is_self(),
1122 _ => false,
1123 }
1124 }
1125
1126 pub fn is_slice(&self) -> bool {
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 {
1138 TyAdt(..) | TyTuple(..) | TyArray(..) | TyClosure(..) => true,
1139 _ => self.is_slice() | self.is_trait(),
1140 }
1141 }
1142
1143 #[inline]
1144 pub fn is_simd(&self) -> bool {
1145 match self.sty {
1146 TyAdt(def, _) => def.repr.simd(),
1147 _ => false,
1148 }
1149 }
1150
1151 pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1152 match self.sty {
1153 TyArray(ty, _) | TySlice(ty) => ty,
1154 TyStr => tcx.mk_mach_uint(ast::UintTy::U8),
1155 _ => bug!("sequence_element_type called on non-sequence value: {}", self),
1156 }
1157 }
1158
1159 pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1160 match self.sty {
1161 TyAdt(def, substs) => {
1162 def.struct_variant().fields[0].ty(tcx, substs)
1163 }
1164 _ => bug!("simd_type called on invalid type")
1165 }
1166 }
1167
1168 pub fn simd_size(&self, _cx: TyCtxt) -> usize {
1169 match self.sty {
1170 TyAdt(def, _) => def.struct_variant().fields.len(),
1171 _ => bug!("simd_size called on invalid type")
1172 }
1173 }
1174
1175 pub fn is_region_ptr(&self) -> bool {
1176 match self.sty {
1177 TyRef(..) => true,
1178 _ => false,
1179 }
1180 }
1181
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
1193 pub fn is_unsafe_ptr(&self) -> bool {
1194 match self.sty {
1195 TyRawPtr(_) => return true,
1196 _ => return false,
1197 }
1198 }
1199
1200 pub fn is_box(&self) -> bool {
1201 match self.sty {
1202 TyAdt(def, _) => def.is_box(),
1203 _ => false,
1204 }
1205 }
1206
1207 /// panics if called on any type other than `Box<T>`
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),
1212 }
1213 }
1214
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.)
1218 pub fn is_scalar(&self) -> bool {
1219 match self.sty {
1220 TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
1221 TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
1222 TyFnDef(..) | TyFnPtr(_) | TyRawPtr(_) => true,
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 {
1238 TyDynamic(..) => true,
1239 _ => false,
1240 }
1241 }
1242
1243 pub fn is_closure(&self) -> bool {
1244 match self.sty {
1245 TyClosure(..) => true,
1246 _ => false,
1247 }
1248 }
1249
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,
1262 _ => false,
1263 }
1264 }
1265
1266 pub fn is_uint(&self) -> bool {
1267 match self.sty {
1268 TyInfer(IntVar(_)) | TyUint(ast::UintTy::Us) => true,
1269 _ => false
1270 }
1271 }
1272
1273 pub fn is_char(&self) -> bool {
1274 match self.sty {
1275 TyChar => true,
1276 _ => false,
1277 }
1278 }
1279
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,
1294 _ => false,
1295 }
1296 }
1297
1298 pub fn is_machine(&self) -> bool {
1299 match self.sty {
1300 TyInt(ast::IntTy::Is) | TyUint(ast::UintTy::Us) => false,
1301 TyInt(..) | TyUint(..) | TyFloat(..) => true,
1302 _ => false,
1303 }
1304 }
1305
1306 pub fn has_concrete_skeleton(&self) -> bool {
1307 match self.sty {
1308 TyParam(_) | TyInfer(_) | TyError => false,
1309 _ => true,
1310 }
1311 }
1312
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.
1317 pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference)
1318 -> Option<TypeAndMut<'tcx>>
1319 {
1320 match self.sty {
1321 TyAdt(def, _) if def.is_box() => {
1322 Some(TypeAndMut {
1323 ty: self.boxed_ty(),
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),
1333 _ => None,
1334 }
1335 }
1336
1337 /// Returns the type of ty[i]
1338 pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
1339 match self.sty {
1340 TyArray(ty, _) | TySlice(ty) => Some(ty),
1341 _ => None,
1342 }
1343 }
1344
1345 pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> {
1346 match self.sty {
1347 TyFnDef(def_id, substs) => {
1348 tcx.fn_sig(def_id).subst(tcx, substs)
1349 }
1350 TyFnPtr(f) => f,
1351 _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
1352 }
1353 }
1354
1355 pub fn is_fn(&self) -> bool {
1356 match self.sty {
1357 TyFnDef(..) | TyFnPtr(_) => true,
1358 _ => false,
1359 }
1360 }
1361
1362 pub fn ty_to_def_id(&self) -> Option<DefId> {
1363 match self.sty {
1364 TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()),
1365 TyAdt(def, _) => Some(def.did),
1366 TyClosure(id, _) => Some(id),
1367 _ => None,
1368 }
1369 }
1370
1371 pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
1372 match self.sty {
1373 TyAdt(adt, _) => Some(adt),
1374 _ => None,
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.
1381 pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
1382 match self.sty {
1383 TyRef(region, _) => {
1384 vec![region]
1385 }
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 }
1391 v
1392 }
1393 TyAdt(_, substs) | TyAnon(_, substs) => {
1394 substs.regions().collect()
1395 }
1396 TyClosure(_, ref substs) => {
1397 substs.substs.regions().collect()
1398 }
1399 TyProjection(ref data) => {
1400 data.substs.regions().collect()
1401 }
1402 TyFnDef(..) |
1403 TyFnPtr(_) |
1404 TyBool |
1405 TyChar |
1406 TyInt(_) |
1407 TyUint(_) |
1408 TyFloat(_) |
1409 TyStr |
1410 TyArray(..) |
1411 TySlice(_) |
1412 TyRawPtr(_) |
1413 TyNever |
1414 TyTuple(..) |
1415 TyParam(_) |
1416 TyInfer(_) |
1417 TyError => {
1418 vec![]
1419 }
1420 }
1421 }
1422 }