]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/sty.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc / ty / sty.rs
CommitLineData
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 13use hir::def_id::DefId;
476ff2be 14
e9174d1e 15use middle::region;
9e0c209e 16use ty::subst::Substs;
476ff2be 17use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
9e0c209e 18use ty::{Slice, TyS};
476ff2be 19use ty::subst::Kind;
e9174d1e 20
e9174d1e 21use std::fmt;
476ff2be
SL
22use std::iter;
23use std::cmp::Ordering;
e9174d1e 24use syntax::abi;
32a655c1 25use syntax::ast::{self, Name};
476ff2be 26use syntax::symbol::{keywords, InternedString};
8bb4bdeb 27use util::nodemap::FxHashMap;
e9174d1e 28
9e0c209e 29use serialize;
9cc50fc6 30
54a0048b 31use hir;
e9174d1e 32
e9174d1e
SL
33use self::InferTy::*;
34use self::TypeVariants::*;
35
9e0c209e 36#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
e9174d1e
SL
37pub 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`".
46pub 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)]
53pub 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
76pub 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
88pub 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 251pub 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
260impl<'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)]
272pub 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
281impl<'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
298impl<'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
317impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<ExistentialPredicate<'tcx>> {}
318
319impl<'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
349impl<'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
387pub struct TraitRef<'tcx> {
388 pub def_id: DefId,
389 pub substs: &'tcx Substs<'tcx>,
390}
391
8bb4bdeb
XL
392impl<'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
410pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
411
412impl<'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)]
445pub struct ExistentialTraitRef<'tcx> {
446 pub def_id: DefId,
447 pub substs: &'tcx Substs<'tcx>,
448}
449
476ff2be
SL
450impl<'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
476pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
477
478impl<'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
497pub struct Binder<T>(pub T);
498
499impl<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
536impl 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
545pub 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 559pub 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 566impl<'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
576pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
577
578impl<'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 600pub struct ParamTy {
e9174d1e
SL
601 pub idx: u32,
602 pub name: Name,
603}
604
a7813a04 605impl<'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)]
672pub 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
735pub 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
778impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Region {}
779
e9174d1e
SL
780#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
781pub 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 787pub struct TyVid {
3157f602 788 pub index: u32,
e9174d1e
SL
789}
790
9e0c209e 791#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
e9174d1e
SL
792pub struct IntVid {
793 pub index: u32
794}
795
9e0c209e 796#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
e9174d1e
SL
797pub struct FloatVid {
798 pub index: u32
799}
800
801#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
802pub struct RegionVid {
803 pub index: u32
804}
805
9cc50fc6 806#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
e9174d1e
SL
807pub struct SkolemizedRegionVid {
808 pub index: u32
809}
810
9e0c209e 811#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
e9174d1e
SL
812pub 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)]
827pub 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
833pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
834
476ff2be 835impl<'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
870impl<'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
885impl 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
897impl 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 961impl<'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}