]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! This module contains TypeVariants and its major components | |
12 | ||
9cc50fc6 | 13 | use middle::cstore; |
e9174d1e SL |
14 | use middle::def_id::DefId; |
15 | use middle::region; | |
16 | use middle::subst::{self, Substs}; | |
17 | use middle::traits; | |
9cc50fc6 | 18 | use middle::ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyS, TypeFoldable}; |
e9174d1e SL |
19 | use util::common::ErrorReported; |
20 | ||
21 | use collections::enum_set::{self, EnumSet, CLike}; | |
22 | use std::fmt; | |
23 | use std::ops; | |
24 | use std::mem; | |
25 | use syntax::abi; | |
b039eaaf | 26 | use syntax::ast::{self, Name}; |
e9174d1e SL |
27 | use syntax::parse::token::special_idents; |
28 | ||
9cc50fc6 SL |
29 | use serialize::{Decodable, Decoder}; |
30 | ||
e9174d1e SL |
31 | use rustc_front::hir; |
32 | ||
33 | use self::FnOutput::*; | |
34 | use self::InferTy::*; | |
35 | use self::TypeVariants::*; | |
36 | ||
37 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
38 | pub struct TypeAndMut<'tcx> { | |
39 | pub ty: Ty<'tcx>, | |
40 | pub mutbl: hir::Mutability, | |
41 | } | |
42 | ||
43 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, | |
44 | RustcEncodable, RustcDecodable, Copy)] | |
45 | /// A "free" region `fr` can be interpreted as "some region | |
46 | /// at least as big as the scope `fr.scope`". | |
47 | pub struct FreeRegion { | |
48 | pub scope: region::CodeExtent, | |
49 | pub bound_region: BoundRegion | |
50 | } | |
51 | ||
52 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, | |
53 | RustcEncodable, RustcDecodable, Copy)] | |
54 | pub enum BoundRegion { | |
55 | /// An anonymous region parameter for a given fn (&T) | |
56 | BrAnon(u32), | |
57 | ||
58 | /// Named region parameters for functions (a in &'a T) | |
59 | /// | |
60 | /// The def-id is needed to distinguish free regions in | |
61 | /// the event of shadowing. | |
62 | BrNamed(DefId, Name), | |
63 | ||
64 | /// Fresh bound identifiers created during GLB computations. | |
65 | BrFresh(u32), | |
66 | ||
67 | // Anonymous region for the implicit env pointer parameter | |
68 | // to a closure | |
69 | BrEnv | |
70 | } | |
71 | ||
72 | // NB: If you change this, you'll probably want to change the corresponding | |
73 | // AST structure in libsyntax/ast.rs as well. | |
74 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
75 | pub enum TypeVariants<'tcx> { | |
76 | /// The primitive boolean type. Written as `bool`. | |
77 | TyBool, | |
78 | ||
79 | /// The primitive character type; holds a Unicode scalar value | |
80 | /// (a non-surrogate code point). Written as `char`. | |
81 | TyChar, | |
82 | ||
83 | /// A primitive signed integer type. For example, `i32`. | |
b039eaaf | 84 | TyInt(ast::IntTy), |
e9174d1e SL |
85 | |
86 | /// A primitive unsigned integer type. For example, `u32`. | |
b039eaaf | 87 | TyUint(ast::UintTy), |
e9174d1e SL |
88 | |
89 | /// A primitive floating-point type. For example, `f64`. | |
b039eaaf | 90 | TyFloat(ast::FloatTy), |
e9174d1e SL |
91 | |
92 | /// An enumerated type, defined with `enum`. | |
93 | /// | |
94 | /// Substs here, possibly against intuition, *may* contain `TyParam`s. | |
95 | /// That is, even after substitution it is possible that there are type | |
96 | /// variables. This happens when the `TyEnum` corresponds to an enum | |
97 | /// definition and not a concrete use of it. To get the correct `TyEnum` | |
b039eaaf | 98 | /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in |
e9174d1e SL |
99 | /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as |
100 | /// well. | |
101 | TyEnum(AdtDef<'tcx>, &'tcx Substs<'tcx>), | |
102 | ||
103 | /// A structure type, defined with `struct`. | |
104 | /// | |
105 | /// See warning about substitutions for enumerated types. | |
106 | TyStruct(AdtDef<'tcx>, &'tcx Substs<'tcx>), | |
107 | ||
108 | /// `Box<T>`; this is nominally a struct in the documentation, but is | |
109 | /// special-cased internally. For example, it is possible to implicitly | |
110 | /// move the contents of a box out of that box, and methods of any type | |
111 | /// can have type `Box<Self>`. | |
112 | TyBox(Ty<'tcx>), | |
113 | ||
114 | /// The pointee of a string slice. Written as `str`. | |
115 | TyStr, | |
116 | ||
117 | /// An array with the given length. Written as `[T; n]`. | |
118 | TyArray(Ty<'tcx>, usize), | |
119 | ||
120 | /// The pointee of an array slice. Written as `[T]`. | |
121 | TySlice(Ty<'tcx>), | |
122 | ||
123 | /// A raw pointer. Written as `*mut T` or `*const T` | |
124 | TyRawPtr(TypeAndMut<'tcx>), | |
125 | ||
126 | /// A reference; a pointer with an associated lifetime. Written as | |
127 | /// `&a mut T` or `&'a T`. | |
128 | TyRef(&'tcx Region, TypeAndMut<'tcx>), | |
129 | ||
130 | /// If the def-id is Some(_), then this is the type of a specific | |
b039eaaf | 131 | /// fn item. Otherwise, if None(_), it is a fn pointer type. |
e9174d1e SL |
132 | /// |
133 | /// FIXME: Conflating function pointers and the type of a | |
134 | /// function is probably a terrible idea; a function pointer is a | |
135 | /// value with a specific type, but a function can be polymorphic | |
136 | /// or dynamically dispatched. | |
137 | TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>), | |
138 | ||
139 | /// A trait, defined with `trait`. | |
140 | TyTrait(Box<TraitTy<'tcx>>), | |
141 | ||
142 | /// The anonymous type of a closure. Used to represent the type of | |
143 | /// `|a| a`. | |
144 | TyClosure(DefId, Box<ClosureSubsts<'tcx>>), | |
145 | ||
146 | /// A tuple type. For example, `(i32, bool)`. | |
147 | TyTuple(Vec<Ty<'tcx>>), | |
148 | ||
149 | /// The projection of an associated type. For example, | |
150 | /// `<T as Trait<..>>::N`. | |
151 | TyProjection(ProjectionTy<'tcx>), | |
152 | ||
153 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | |
154 | TyParam(ParamTy), | |
155 | ||
156 | /// A type variable used during type-checking. | |
157 | TyInfer(InferTy), | |
158 | ||
159 | /// A placeholder for a type which could not be computed; this is | |
160 | /// propagated to avoid useless error messages. | |
161 | TyError, | |
162 | } | |
163 | ||
164 | /// A closure can be modeled as a struct that looks like: | |
165 | /// | |
166 | /// struct Closure<'l0...'li, T0...Tj, U0...Uk> { | |
167 | /// upvar0: U0, | |
168 | /// ... | |
169 | /// upvark: Uk | |
170 | /// } | |
171 | /// | |
172 | /// where 'l0...'li and T0...Tj are the lifetime and type parameters | |
173 | /// in scope on the function that defined the closure, and U0...Uk are | |
174 | /// type parameters representing the types of its upvars (borrowed, if | |
175 | /// appropriate). | |
176 | /// | |
177 | /// So, for example, given this function: | |
178 | /// | |
179 | /// fn foo<'a, T>(data: &'a mut T) { | |
180 | /// do(|| data.count += 1) | |
181 | /// } | |
182 | /// | |
183 | /// the type of the closure would be something like: | |
184 | /// | |
185 | /// struct Closure<'a, T, U0> { | |
186 | /// data: U0 | |
187 | /// } | |
188 | /// | |
189 | /// Note that the type of the upvar is not specified in the struct. | |
190 | /// You may wonder how the impl would then be able to use the upvar, | |
191 | /// if it doesn't know it's type? The answer is that the impl is | |
192 | /// (conceptually) not fully generic over Closure but rather tied to | |
193 | /// instances with the expected upvar types: | |
194 | /// | |
195 | /// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> { | |
196 | /// ... | |
197 | /// } | |
198 | /// | |
199 | /// You can see that the *impl* fully specified the type of the upvar | |
200 | /// and thus knows full well that `data` has type `&'b mut &'a mut T`. | |
201 | /// (Here, I am assuming that `data` is mut-borrowed.) | |
202 | /// | |
203 | /// Now, the last question you may ask is: Why include the upvar types | |
204 | /// as extra type parameters? The reason for this design is that the | |
205 | /// upvar types can reference lifetimes that are internal to the | |
206 | /// creating function. In my example above, for example, the lifetime | |
207 | /// `'b` represents the extent of the closure itself; this is some | |
208 | /// subset of `foo`, probably just the extent of the call to the to | |
209 | /// `do()`. If we just had the lifetime/type parameters from the | |
210 | /// enclosing function, we couldn't name this lifetime `'b`. Note that | |
211 | /// there can also be lifetimes in the types of the upvars themselves, | |
212 | /// if one of them happens to be a reference to something that the | |
213 | /// creating fn owns. | |
214 | /// | |
215 | /// OK, you say, so why not create a more minimal set of parameters | |
216 | /// that just includes the extra lifetime parameters? The answer is | |
217 | /// primarily that it would be hard --- we don't know at the time when | |
218 | /// we create the closure type what the full types of the upvars are, | |
219 | /// nor do we know which are borrowed and which are not. In this | |
220 | /// design, we can just supply a fresh type parameter and figure that | |
221 | /// out later. | |
222 | /// | |
223 | /// All right, you say, but why include the type parameters from the | |
224 | /// original function then? The answer is that trans may need them | |
225 | /// when monomorphizing, and they may not appear in the upvars. A | |
226 | /// closure could capture no variables but still make use of some | |
227 | /// in-scope type parameter with a bound (e.g., if our example above | |
228 | /// had an extra `U: Default`, and the closure called `U::default()`). | |
229 | /// | |
230 | /// There is another reason. This design (implicitly) prohibits | |
231 | /// closures from capturing themselves (except via a trait | |
232 | /// object). This simplifies closure inference considerably, since it | |
233 | /// means that when we infer the kind of a closure or its upvars, we | |
234 | /// don't have to handle cycles where the decisions we make for | |
235 | /// closure C wind up influencing the decisions we ought to make for | |
236 | /// closure C (which would then require fixed point iteration to | |
237 | /// handle). Plus it fixes an ICE. :P | |
9cc50fc6 | 238 | #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
239 | pub struct ClosureSubsts<'tcx> { |
240 | /// Lifetime and type parameters from the enclosing function. | |
241 | /// These are separated out because trans wants to pass them around | |
242 | /// when monomorphizing. | |
243 | pub func_substs: &'tcx Substs<'tcx>, | |
244 | ||
245 | /// The types of the upvars. The list parallels the freevars and | |
246 | /// `upvar_borrows` lists. These are kept distinct so that we can | |
247 | /// easily index into them. | |
248 | pub upvar_tys: Vec<Ty<'tcx>> | |
249 | } | |
250 | ||
9cc50fc6 SL |
251 | impl<'tcx> Decodable for &'tcx ClosureSubsts<'tcx> { |
252 | fn decode<S: Decoder>(s: &mut S) -> Result<&'tcx ClosureSubsts<'tcx>, S::Error> { | |
253 | let closure_substs = try! { Decodable::decode(s) }; | |
254 | let dummy_def_id: DefId = unsafe { mem::zeroed() }; | |
255 | ||
256 | cstore::tls::with_decoding_context(s, |dcx, _| { | |
257 | // Intern the value | |
258 | let ty = dcx.tcx().mk_closure_from_closure_substs(dummy_def_id, | |
259 | Box::new(closure_substs)); | |
260 | match ty.sty { | |
261 | TyClosure(_, ref closure_substs) => Ok(&**closure_substs), | |
262 | _ => unreachable!() | |
263 | } | |
264 | }) | |
265 | } | |
266 | } | |
267 | ||
e9174d1e SL |
268 | #[derive(Clone, PartialEq, Eq, Hash)] |
269 | pub struct TraitTy<'tcx> { | |
270 | pub principal: ty::PolyTraitRef<'tcx>, | |
271 | pub bounds: ExistentialBounds<'tcx>, | |
272 | } | |
273 | ||
274 | impl<'tcx> TraitTy<'tcx> { | |
275 | pub fn principal_def_id(&self) -> DefId { | |
276 | self.principal.0.def_id | |
277 | } | |
278 | ||
279 | /// Object types don't have a self-type specified. Therefore, when | |
280 | /// we convert the principal trait-ref into a normal trait-ref, | |
281 | /// you must give *some* self-type. A common choice is `mk_err()` | |
282 | /// or some skolemized type. | |
283 | pub fn principal_trait_ref_with_self_ty(&self, | |
284 | tcx: &ty::ctxt<'tcx>, | |
285 | self_ty: Ty<'tcx>) | |
286 | -> ty::PolyTraitRef<'tcx> | |
287 | { | |
288 | // otherwise the escaping regions would be captured by the binder | |
289 | assert!(!self_ty.has_escaping_regions()); | |
290 | ||
291 | ty::Binder(TraitRef { | |
292 | def_id: self.principal.0.def_id, | |
293 | substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), | |
294 | }) | |
295 | } | |
296 | ||
297 | pub fn projection_bounds_with_self_ty(&self, | |
298 | tcx: &ty::ctxt<'tcx>, | |
299 | self_ty: Ty<'tcx>) | |
300 | -> Vec<ty::PolyProjectionPredicate<'tcx>> | |
301 | { | |
302 | // otherwise the escaping regions would be captured by the binders | |
303 | assert!(!self_ty.has_escaping_regions()); | |
304 | ||
305 | self.bounds.projection_bounds.iter() | |
306 | .map(|in_poly_projection_predicate| { | |
307 | let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; | |
308 | let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); | |
309 | let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, | |
310 | substs); | |
311 | let projection_ty = ty::ProjectionTy { | |
312 | trait_ref: trait_ref, | |
313 | item_name: in_projection_ty.item_name | |
314 | }; | |
315 | ty::Binder(ty::ProjectionPredicate { | |
316 | projection_ty: projection_ty, | |
317 | ty: in_poly_projection_predicate.0.ty | |
318 | }) | |
319 | }) | |
320 | .collect() | |
321 | } | |
322 | } | |
323 | ||
324 | /// A complete reference to a trait. These take numerous guises in syntax, | |
325 | /// but perhaps the most recognizable form is in a where clause: | |
326 | /// | |
327 | /// T : Foo<U> | |
328 | /// | |
329 | /// This would be represented by a trait-reference where the def-id is the | |
330 | /// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the | |
331 | /// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`. | |
332 | /// | |
333 | /// Trait references also appear in object types like `Foo<U>`, but in | |
334 | /// that case the `Self` parameter is absent from the substitutions. | |
335 | /// | |
336 | /// Note that a `TraitRef` introduces a level of region binding, to | |
337 | /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a | |
338 | /// U>` or higher-ranked object types. | |
339 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
340 | pub struct TraitRef<'tcx> { | |
341 | pub def_id: DefId, | |
342 | pub substs: &'tcx Substs<'tcx>, | |
343 | } | |
344 | ||
345 | pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>; | |
346 | ||
347 | impl<'tcx> PolyTraitRef<'tcx> { | |
348 | pub fn self_ty(&self) -> Ty<'tcx> { | |
349 | self.0.self_ty() | |
350 | } | |
351 | ||
352 | pub fn def_id(&self) -> DefId { | |
353 | self.0.def_id | |
354 | } | |
355 | ||
356 | pub fn substs(&self) -> &'tcx Substs<'tcx> { | |
357 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
358 | self.0.substs | |
359 | } | |
360 | ||
361 | pub fn input_types(&self) -> &[Ty<'tcx>] { | |
362 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
363 | self.0.input_types() | |
364 | } | |
365 | ||
366 | pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { | |
367 | // Note that we preserve binding levels | |
368 | Binder(ty::TraitPredicate { trait_ref: self.0.clone() }) | |
369 | } | |
370 | } | |
371 | ||
372 | /// Binder is a binder for higher-ranked lifetimes. It is part of the | |
373 | /// compiler's representation for things like `for<'a> Fn(&'a isize)` | |
374 | /// (which would be represented by the type `PolyTraitRef == | |
375 | /// Binder<TraitRef>`). Note that when we skolemize, instantiate, | |
376 | /// erase, or otherwise "discharge" these bound regions, we change the | |
377 | /// type from `Binder<T>` to just `T` (see | |
378 | /// e.g. `liberate_late_bound_regions`). | |
379 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | |
380 | pub struct Binder<T>(pub T); | |
381 | ||
382 | impl<T> Binder<T> { | |
383 | /// Skips the binder and returns the "bound" value. This is a | |
384 | /// risky thing to do because it's easy to get confused about | |
385 | /// debruijn indices and the like. It is usually better to | |
386 | /// discharge the binder using `no_late_bound_regions` or | |
387 | /// `replace_late_bound_regions` or something like | |
388 | /// that. `skip_binder` is only valid when you are either | |
389 | /// extracting data that has nothing to do with bound regions, you | |
390 | /// are doing some sort of test that does not involve bound | |
391 | /// regions, or you are being very careful about your depth | |
392 | /// accounting. | |
393 | /// | |
394 | /// Some examples where `skip_binder` is reasonable: | |
395 | /// - extracting the def-id from a PolyTraitRef; | |
396 | /// - comparing the self type of a PolyTraitRef to see if it is equal to | |
397 | /// a type parameter `X`, since the type `X` does not reference any regions | |
398 | pub fn skip_binder(&self) -> &T { | |
399 | &self.0 | |
400 | } | |
401 | ||
402 | pub fn as_ref(&self) -> Binder<&T> { | |
403 | ty::Binder(&self.0) | |
404 | } | |
405 | ||
406 | pub fn map_bound_ref<F,U>(&self, f: F) -> Binder<U> | |
407 | where F: FnOnce(&T) -> U | |
408 | { | |
409 | self.as_ref().map_bound(f) | |
410 | } | |
411 | ||
412 | pub fn map_bound<F,U>(self, f: F) -> Binder<U> | |
413 | where F: FnOnce(T) -> U | |
414 | { | |
415 | ty::Binder(f(self.0)) | |
416 | } | |
417 | } | |
418 | ||
419 | impl fmt::Debug for TypeFlags { | |
420 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
421 | write!(f, "{}", self.bits) | |
422 | } | |
423 | } | |
424 | ||
425 | /// Represents the projection of an associated type. In explicit UFCS | |
426 | /// form this would be written `<T as Trait<..>>::N`. | |
427 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | |
428 | pub struct ProjectionTy<'tcx> { | |
429 | /// The trait reference `T as Trait<..>`. | |
430 | pub trait_ref: ty::TraitRef<'tcx>, | |
431 | ||
432 | /// The name `N` of the associated type. | |
433 | pub item_name: Name, | |
434 | } | |
435 | ||
436 | impl<'tcx> ProjectionTy<'tcx> { | |
437 | pub fn sort_key(&self) -> (DefId, Name) { | |
438 | (self.trait_ref.def_id, self.item_name) | |
439 | } | |
440 | } | |
441 | ||
442 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
443 | pub struct BareFnTy<'tcx> { | |
444 | pub unsafety: hir::Unsafety, | |
445 | pub abi: abi::Abi, | |
446 | pub sig: PolyFnSig<'tcx>, | |
447 | } | |
448 | ||
449 | #[derive(Clone, PartialEq, Eq, Hash)] | |
450 | pub struct ClosureTy<'tcx> { | |
451 | pub unsafety: hir::Unsafety, | |
452 | pub abi: abi::Abi, | |
453 | pub sig: PolyFnSig<'tcx>, | |
454 | } | |
455 | ||
9cc50fc6 | 456 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
457 | pub enum FnOutput<'tcx> { |
458 | FnConverging(Ty<'tcx>), | |
459 | FnDiverging | |
460 | } | |
461 | ||
462 | impl<'tcx> FnOutput<'tcx> { | |
463 | pub fn diverges(&self) -> bool { | |
464 | *self == FnDiverging | |
465 | } | |
466 | ||
467 | pub fn unwrap(self) -> Ty<'tcx> { | |
468 | match self { | |
469 | ty::FnConverging(t) => t, | |
470 | ty::FnDiverging => unreachable!() | |
471 | } | |
472 | } | |
473 | ||
474 | pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> { | |
475 | match self { | |
476 | ty::FnConverging(t) => t, | |
477 | ty::FnDiverging => def | |
478 | } | |
479 | } | |
480 | } | |
481 | ||
482 | pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>; | |
483 | ||
484 | impl<'tcx> PolyFnOutput<'tcx> { | |
485 | pub fn diverges(&self) -> bool { | |
486 | self.0.diverges() | |
487 | } | |
488 | } | |
489 | ||
490 | /// Signature of a function type, which I have arbitrarily | |
491 | /// decided to use to refer to the input/output types. | |
492 | /// | |
493 | /// - `inputs` is the list of arguments and their modes. | |
494 | /// - `output` is the return type. | |
495 | /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) | |
496 | #[derive(Clone, PartialEq, Eq, Hash)] | |
497 | pub struct FnSig<'tcx> { | |
498 | pub inputs: Vec<Ty<'tcx>>, | |
499 | pub output: FnOutput<'tcx>, | |
500 | pub variadic: bool | |
501 | } | |
502 | ||
503 | pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>; | |
504 | ||
505 | impl<'tcx> PolyFnSig<'tcx> { | |
506 | pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> { | |
507 | self.map_bound_ref(|fn_sig| fn_sig.inputs.clone()) | |
508 | } | |
509 | pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { | |
510 | self.map_bound_ref(|fn_sig| fn_sig.inputs[index]) | |
511 | } | |
512 | pub fn output(&self) -> ty::Binder<FnOutput<'tcx>> { | |
513 | self.map_bound_ref(|fn_sig| fn_sig.output.clone()) | |
514 | } | |
515 | pub fn variadic(&self) -> bool { | |
516 | self.skip_binder().variadic | |
517 | } | |
518 | } | |
519 | ||
520 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | |
521 | pub struct ParamTy { | |
522 | pub space: subst::ParamSpace, | |
523 | pub idx: u32, | |
524 | pub name: Name, | |
525 | } | |
526 | ||
527 | impl ParamTy { | |
528 | pub fn new(space: subst::ParamSpace, | |
529 | index: u32, | |
530 | name: Name) | |
531 | -> ParamTy { | |
532 | ParamTy { space: space, idx: index, name: name } | |
533 | } | |
534 | ||
535 | pub fn for_self() -> ParamTy { | |
536 | ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name) | |
537 | } | |
538 | ||
539 | pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { | |
540 | ParamTy::new(def.space, def.index, def.name) | |
541 | } | |
542 | ||
543 | pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { | |
544 | tcx.mk_param(self.space, self.idx, self.name) | |
545 | } | |
546 | ||
547 | pub fn is_self(&self) -> bool { | |
548 | self.space == subst::SelfSpace && self.idx == 0 | |
549 | } | |
550 | } | |
551 | ||
552 | /// A [De Bruijn index][dbi] is a standard means of representing | |
553 | /// regions (and perhaps later types) in a higher-ranked setting. In | |
554 | /// particular, imagine a type like this: | |
555 | /// | |
556 | /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) | |
557 | /// ^ ^ | | | | |
558 | /// | | | | | | |
559 | /// | +------------+ 1 | | | |
560 | /// | | | | |
561 | /// +--------------------------------+ 2 | | |
562 | /// | | | |
563 | /// +------------------------------------------+ 1 | |
564 | /// | |
565 | /// In this type, there are two binders (the outer fn and the inner | |
566 | /// fn). We need to be able to determine, for any given region, which | |
567 | /// fn type it is bound by, the inner or the outer one. There are | |
568 | /// various ways you can do this, but a De Bruijn index is one of the | |
569 | /// more convenient and has some nice properties. The basic idea is to | |
570 | /// count the number of binders, inside out. Some examples should help | |
571 | /// clarify what I mean. | |
572 | /// | |
573 | /// Let's start with the reference type `&'b isize` that is the first | |
574 | /// argument to the inner function. This region `'b` is assigned a De | |
575 | /// Bruijn index of 1, meaning "the innermost binder" (in this case, a | |
576 | /// fn). The region `'a` that appears in the second argument type (`&'a | |
577 | /// isize`) would then be assigned a De Bruijn index of 2, meaning "the | |
578 | /// second-innermost binder". (These indices are written on the arrays | |
579 | /// in the diagram). | |
580 | /// | |
581 | /// What is interesting is that De Bruijn index attached to a particular | |
582 | /// variable will vary depending on where it appears. For example, | |
583 | /// the final type `&'a char` also refers to the region `'a` declared on | |
584 | /// the outermost fn. But this time, this reference is not nested within | |
585 | /// any other binders (i.e., it is not an argument to the inner fn, but | |
586 | /// rather the outer one). Therefore, in this case, it is assigned a | |
587 | /// De Bruijn index of 1, because the innermost binder in that location | |
588 | /// is the outer fn. | |
589 | /// | |
590 | /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index | |
591 | #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] | |
592 | pub struct DebruijnIndex { | |
593 | // We maintain the invariant that this is never 0. So 1 indicates | |
594 | // the innermost binder. To ensure this, create with `DebruijnIndex::new`. | |
595 | pub depth: u32, | |
596 | } | |
597 | ||
598 | /// Representation of regions. | |
599 | /// | |
600 | /// Unlike types, most region variants are "fictitious", not concrete, | |
601 | /// regions. Among these, `ReStatic`, `ReEmpty` and `ReScope` are the only | |
602 | /// ones representing concrete regions. | |
603 | /// | |
604 | /// ## Bound Regions | |
605 | /// | |
606 | /// These are regions that are stored behind a binder and must be substituted | |
607 | /// with some concrete region before being used. There are 2 kind of | |
608 | /// bound regions: early-bound, which are bound in a TypeScheme/TraitDef, | |
609 | /// and are substituted by a Substs, and late-bound, which are part of | |
610 | /// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by | |
611 | /// the likes of `liberate_late_bound_regions`. The distinction exists | |
612 | /// because higher-ranked lifetimes aren't supported in all places. See [1][2]. | |
613 | /// | |
614 | /// Unlike TyParam-s, bound regions are not supposed to exist "in the wild" | |
615 | /// outside their binder, e.g. in types passed to type inference, and | |
616 | /// should first be substituted (by skolemized regions, free regions, | |
617 | /// or region variables). | |
618 | /// | |
619 | /// ## Skolemized and Free Regions | |
620 | /// | |
621 | /// One often wants to work with bound regions without knowing their precise | |
622 | /// identity. For example, when checking a function, the lifetime of a borrow | |
623 | /// can end up being assigned to some region parameter. In these cases, | |
624 | /// it must be ensured that bounds on the region can't be accidentally | |
625 | /// assumed without being checked. | |
626 | /// | |
627 | /// The process of doing that is called "skolemization". The bound regions | |
628 | /// are replaced by skolemized markers, which don't satisfy any relation | |
629 | /// not explicity provided. | |
630 | /// | |
631 | /// There are 2 kinds of skolemized regions in rustc: `ReFree` and | |
632 | /// `ReSkolemized`. When checking an item's body, `ReFree` is supposed | |
633 | /// to be used. These also support explicit bounds: both the internally-stored | |
634 | /// *scope*, which the region is assumed to outlive, as well as other | |
635 | /// relations stored in the `FreeRegionMap`. Note that these relations | |
636 | /// aren't checked when you `make_subregion` (or `mk_eqty`), only by | |
637 | /// `resolve_regions_and_report_errors`. | |
638 | /// | |
639 | /// When working with higher-ranked types, some region relations aren't | |
640 | /// yet known, so you can't just call `resolve_regions_and_report_errors`. | |
641 | /// `ReSkolemized` is designed for this purpose. In these contexts, | |
642 | /// there's also the risk that some inference variable laying around will | |
643 | /// get unified with your skolemized region: if you want to check whether | |
644 | /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a` | |
645 | /// with a skolemized region `'%a`, the variable `'_` would just be | |
646 | /// instantiated to the skolemized region `'%a`, which is wrong because | |
647 | /// the inference variable is supposed to satisfy the relation | |
648 | /// *for every value of the skolemized region*. To ensure that doesn't | |
649 | /// happen, you can use `leak_check`. This is more clearly explained | |
650 | /// by infer/higher_ranked/README.md. | |
651 | /// | |
652 | /// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ | |
653 | /// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ | |
9cc50fc6 | 654 | #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
655 | pub enum Region { |
656 | // Region bound in a type or fn declaration which will be | |
657 | // substituted 'early' -- that is, at the same time when type | |
658 | // parameters are substituted. | |
659 | ReEarlyBound(EarlyBoundRegion), | |
660 | ||
661 | // Region bound in a function scope, which will be substituted when the | |
662 | // function is called. | |
663 | ReLateBound(DebruijnIndex, BoundRegion), | |
664 | ||
665 | /// When checking a function body, the types of all arguments and so forth | |
666 | /// that refer to bound region parameters are modified to refer to free | |
667 | /// region parameters. | |
668 | ReFree(FreeRegion), | |
669 | ||
670 | /// A concrete region naming some statically determined extent | |
671 | /// (e.g. an expression or sequence of statements) within the | |
672 | /// current function. | |
673 | ReScope(region::CodeExtent), | |
674 | ||
675 | /// Static data that has an "infinite" lifetime. Top in the region lattice. | |
676 | ReStatic, | |
677 | ||
678 | /// A region variable. Should not exist after typeck. | |
679 | ReVar(RegionVid), | |
680 | ||
681 | /// A skolemized region - basically the higher-ranked version of ReFree. | |
682 | /// Should not exist after typeck. | |
683 | ReSkolemized(SkolemizedRegionVid, BoundRegion), | |
684 | ||
685 | /// Empty lifetime is for data that is never accessed. | |
686 | /// Bottom in the region lattice. We treat ReEmpty somewhat | |
687 | /// specially; at least right now, we do not generate instances of | |
688 | /// it during the GLB computations, but rather | |
689 | /// generate an error instead. This is to improve error messages. | |
690 | /// The only way to get an instance of ReEmpty is to have a region | |
691 | /// variable with no constraints. | |
692 | ReEmpty, | |
693 | } | |
694 | ||
695 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] | |
696 | pub struct EarlyBoundRegion { | |
e9174d1e SL |
697 | pub space: subst::ParamSpace, |
698 | pub index: u32, | |
699 | pub name: Name, | |
700 | } | |
701 | ||
702 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | |
703 | pub struct TyVid { | |
704 | pub index: u32 | |
705 | } | |
706 | ||
707 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | |
708 | pub struct IntVid { | |
709 | pub index: u32 | |
710 | } | |
711 | ||
712 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | |
713 | pub struct FloatVid { | |
714 | pub index: u32 | |
715 | } | |
716 | ||
717 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] | |
718 | pub struct RegionVid { | |
719 | pub index: u32 | |
720 | } | |
721 | ||
9cc50fc6 | 722 | #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
723 | pub struct SkolemizedRegionVid { |
724 | pub index: u32 | |
725 | } | |
726 | ||
727 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | |
728 | pub enum InferTy { | |
729 | TyVar(TyVid), | |
730 | IntVar(IntVid), | |
731 | FloatVar(FloatVid), | |
732 | ||
733 | /// A `FreshTy` is one that is generated as a replacement for an | |
734 | /// unbound type variable. This is convenient for caching etc. See | |
735 | /// `middle::infer::freshen` for more details. | |
736 | FreshTy(u32), | |
737 | FreshIntTy(u32), | |
738 | FreshFloatTy(u32) | |
739 | } | |
740 | ||
741 | /// Bounds suitable for an existentially quantified type parameter | |
742 | /// such as those that appear in object types or closure types. | |
743 | #[derive(PartialEq, Eq, Hash, Clone)] | |
744 | pub struct ExistentialBounds<'tcx> { | |
745 | pub region_bound: ty::Region, | |
746 | pub builtin_bounds: BuiltinBounds, | |
747 | pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, | |
748 | } | |
749 | ||
750 | impl<'tcx> ExistentialBounds<'tcx> { | |
751 | pub fn new(region_bound: ty::Region, | |
752 | builtin_bounds: BuiltinBounds, | |
753 | projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>) | |
754 | -> Self { | |
755 | let mut projection_bounds = projection_bounds; | |
756 | projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())); | |
757 | ExistentialBounds { | |
758 | region_bound: region_bound, | |
759 | builtin_bounds: builtin_bounds, | |
760 | projection_bounds: projection_bounds | |
761 | } | |
762 | } | |
763 | } | |
764 | ||
765 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
766 | pub struct BuiltinBounds(EnumSet<BuiltinBound>); | |
767 | ||
768 | impl BuiltinBounds { | |
769 | pub fn empty() -> BuiltinBounds { | |
770 | BuiltinBounds(EnumSet::new()) | |
771 | } | |
772 | ||
773 | pub fn iter(&self) -> enum_set::Iter<BuiltinBound> { | |
774 | self.into_iter() | |
775 | } | |
776 | ||
777 | pub fn to_predicates<'tcx>(&self, | |
778 | tcx: &ty::ctxt<'tcx>, | |
779 | self_ty: Ty<'tcx>) -> Vec<ty::Predicate<'tcx>> { | |
780 | self.iter().filter_map(|builtin_bound| | |
781 | match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) { | |
782 | Ok(trait_ref) => Some(trait_ref.to_predicate()), | |
783 | Err(ErrorReported) => { None } | |
784 | } | |
785 | ).collect() | |
786 | } | |
787 | } | |
788 | ||
789 | impl ops::Deref for BuiltinBounds { | |
790 | type Target = EnumSet<BuiltinBound>; | |
791 | fn deref(&self) -> &Self::Target { &self.0 } | |
792 | } | |
793 | ||
794 | impl ops::DerefMut for BuiltinBounds { | |
795 | fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } | |
796 | } | |
797 | ||
798 | impl<'a> IntoIterator for &'a BuiltinBounds { | |
799 | type Item = BuiltinBound; | |
800 | type IntoIter = enum_set::Iter<BuiltinBound>; | |
801 | fn into_iter(self) -> Self::IntoIter { | |
802 | (**self).into_iter() | |
803 | } | |
804 | } | |
805 | ||
806 | #[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, | |
807 | Debug, Copy)] | |
808 | #[repr(usize)] | |
809 | pub enum BuiltinBound { | |
810 | Send, | |
811 | Sized, | |
812 | Copy, | |
813 | Sync, | |
814 | } | |
815 | ||
816 | impl CLike for BuiltinBound { | |
817 | fn to_usize(&self) -> usize { | |
818 | *self as usize | |
819 | } | |
820 | fn from_usize(v: usize) -> BuiltinBound { | |
821 | unsafe { mem::transmute(v) } | |
822 | } | |
823 | } | |
824 | ||
825 | impl<'tcx> ty::ctxt<'tcx> { | |
826 | pub fn try_add_builtin_trait(&self, | |
827 | trait_def_id: DefId, | |
828 | builtin_bounds: &mut EnumSet<BuiltinBound>) | |
829 | -> bool | |
830 | { | |
831 | //! Checks whether `trait_ref` refers to one of the builtin | |
832 | //! traits, like `Send`, and adds the corresponding | |
833 | //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` | |
834 | //! is a builtin trait. | |
835 | ||
836 | match self.lang_items.to_builtin_kind(trait_def_id) { | |
837 | Some(bound) => { builtin_bounds.insert(bound); true } | |
838 | None => false | |
839 | } | |
840 | } | |
841 | } | |
842 | ||
843 | impl DebruijnIndex { | |
844 | pub fn new(depth: u32) -> DebruijnIndex { | |
845 | assert!(depth > 0); | |
846 | DebruijnIndex { depth: depth } | |
847 | } | |
848 | ||
849 | pub fn shifted(&self, amount: u32) -> DebruijnIndex { | |
850 | DebruijnIndex { depth: self.depth + amount } | |
851 | } | |
852 | } | |
853 | ||
854 | // Region utilities | |
855 | impl Region { | |
856 | pub fn is_bound(&self) -> bool { | |
857 | match *self { | |
858 | ty::ReEarlyBound(..) => true, | |
859 | ty::ReLateBound(..) => true, | |
860 | _ => false | |
861 | } | |
862 | } | |
863 | ||
864 | pub fn needs_infer(&self) -> bool { | |
865 | match *self { | |
866 | ty::ReVar(..) | ty::ReSkolemized(..) => true, | |
867 | _ => false | |
868 | } | |
869 | } | |
870 | ||
871 | pub fn escapes_depth(&self, depth: u32) -> bool { | |
872 | match *self { | |
873 | ty::ReLateBound(debruijn, _) => debruijn.depth > depth, | |
874 | _ => false, | |
875 | } | |
876 | } | |
877 | ||
878 | /// Returns the depth of `self` from the (1-based) binding level `depth` | |
879 | pub fn from_depth(&self, depth: u32) -> Region { | |
880 | match *self { | |
881 | ty::ReLateBound(debruijn, r) => ty::ReLateBound(DebruijnIndex { | |
882 | depth: debruijn.depth - (depth - 1) | |
883 | }, r), | |
884 | r => r | |
885 | } | |
886 | } | |
887 | } | |
888 | ||
889 | // Type utilities | |
890 | impl<'tcx> TyS<'tcx> { | |
891 | pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> { | |
892 | match self.sty { | |
893 | ty::TyParam(ref d) => Some(d.clone()), | |
894 | _ => None, | |
895 | } | |
896 | } | |
897 | ||
898 | pub fn is_nil(&self) -> bool { | |
899 | match self.sty { | |
900 | TyTuple(ref tys) => tys.is_empty(), | |
901 | _ => false | |
902 | } | |
903 | } | |
904 | ||
905 | pub fn is_empty(&self, _cx: &ty::ctxt) -> bool { | |
906 | // FIXME(#24885): be smarter here | |
907 | match self.sty { | |
908 | TyEnum(def, _) | TyStruct(def, _) => def.is_empty(), | |
909 | _ => false | |
910 | } | |
911 | } | |
912 | ||
9cc50fc6 SL |
913 | pub fn is_primitive(&self) -> bool { |
914 | match self.sty { | |
915 | TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true, | |
916 | _ => false, | |
917 | } | |
918 | } | |
919 | ||
e9174d1e SL |
920 | pub fn is_ty_var(&self) -> bool { |
921 | match self.sty { | |
922 | TyInfer(TyVar(_)) => true, | |
923 | _ => false | |
924 | } | |
925 | } | |
926 | ||
b039eaaf SL |
927 | pub fn is_phantom_data(&self) -> bool { |
928 | if let TyStruct(def, _) = self.sty { | |
929 | def.is_phantom_data() | |
930 | } else { | |
931 | false | |
932 | } | |
933 | } | |
934 | ||
e9174d1e SL |
935 | pub fn is_bool(&self) -> bool { self.sty == TyBool } |
936 | ||
937 | pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool { | |
938 | match self.sty { | |
939 | ty::TyParam(ref data) => data.space == space && data.idx == index, | |
940 | _ => false, | |
941 | } | |
942 | } | |
943 | ||
944 | pub fn is_self(&self) -> bool { | |
945 | match self.sty { | |
946 | TyParam(ref p) => p.space == subst::SelfSpace, | |
947 | _ => false | |
948 | } | |
949 | } | |
950 | ||
951 | fn is_slice(&self) -> bool { | |
952 | match self.sty { | |
953 | TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty { | |
954 | TySlice(_) | TyStr => true, | |
955 | _ => false, | |
956 | }, | |
957 | _ => false | |
958 | } | |
959 | } | |
960 | ||
961 | pub fn is_structural(&self) -> bool { | |
962 | match self.sty { | |
963 | TyStruct(..) | TyTuple(_) | TyEnum(..) | | |
964 | TyArray(..) | TyClosure(..) => true, | |
965 | _ => self.is_slice() | self.is_trait() | |
966 | } | |
967 | } | |
968 | ||
969 | #[inline] | |
970 | pub fn is_simd(&self) -> bool { | |
971 | match self.sty { | |
972 | TyStruct(def, _) => def.is_simd(), | |
973 | _ => false | |
974 | } | |
975 | } | |
976 | ||
977 | pub fn sequence_element_type(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> { | |
978 | match self.sty { | |
979 | TyArray(ty, _) | TySlice(ty) => ty, | |
7453a54e | 980 | TyStr => cx.mk_mach_uint(ast::UintTy::U8), |
e9174d1e SL |
981 | _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}", |
982 | self)), | |
983 | } | |
984 | } | |
985 | ||
986 | pub fn simd_type(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> { | |
987 | match self.sty { | |
988 | TyStruct(def, substs) => { | |
989 | def.struct_variant().fields[0].ty(cx, substs) | |
990 | } | |
991 | _ => panic!("simd_type called on invalid type") | |
992 | } | |
993 | } | |
994 | ||
995 | pub fn simd_size(&self, _cx: &ty::ctxt) -> usize { | |
996 | match self.sty { | |
997 | TyStruct(def, _) => def.struct_variant().fields.len(), | |
998 | _ => panic!("simd_size called on invalid type") | |
999 | } | |
1000 | } | |
1001 | ||
1002 | pub fn is_region_ptr(&self) -> bool { | |
1003 | match self.sty { | |
1004 | TyRef(..) => true, | |
1005 | _ => false | |
1006 | } | |
1007 | } | |
1008 | ||
1009 | pub fn is_unsafe_ptr(&self) -> bool { | |
1010 | match self.sty { | |
1011 | TyRawPtr(_) => return true, | |
1012 | _ => return false | |
1013 | } | |
1014 | } | |
1015 | ||
1016 | pub fn is_unique(&self) -> bool { | |
1017 | match self.sty { | |
1018 | TyBox(_) => true, | |
1019 | _ => false | |
1020 | } | |
1021 | } | |
1022 | ||
1023 | /* | |
1024 | A scalar type is one that denotes an atomic datum, with no sub-components. | |
1025 | (A TyRawPtr is scalar because it represents a non-managed pointer, so its | |
1026 | contents are abstract to rustc.) | |
1027 | */ | |
1028 | pub fn is_scalar(&self) -> bool { | |
1029 | match self.sty { | |
1030 | TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | | |
1031 | TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) | | |
1032 | TyBareFn(..) | TyRawPtr(_) => true, | |
1033 | _ => false | |
1034 | } | |
1035 | } | |
1036 | ||
1037 | /// Returns true if this type is a floating point type and false otherwise. | |
1038 | pub fn is_floating_point(&self) -> bool { | |
1039 | match self.sty { | |
1040 | TyFloat(_) | | |
1041 | TyInfer(FloatVar(_)) => true, | |
1042 | _ => false, | |
1043 | } | |
1044 | } | |
1045 | ||
1046 | pub fn is_trait(&self) -> bool { | |
1047 | match self.sty { | |
1048 | TyTrait(..) => true, | |
1049 | _ => false | |
1050 | } | |
1051 | } | |
1052 | ||
1053 | pub fn is_integral(&self) -> bool { | |
1054 | match self.sty { | |
1055 | TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, | |
1056 | _ => false | |
1057 | } | |
1058 | } | |
1059 | ||
1060 | pub fn is_fresh(&self) -> bool { | |
1061 | match self.sty { | |
1062 | TyInfer(FreshTy(_)) => true, | |
1063 | TyInfer(FreshIntTy(_)) => true, | |
1064 | TyInfer(FreshFloatTy(_)) => true, | |
1065 | _ => false | |
1066 | } | |
1067 | } | |
1068 | ||
1069 | pub fn is_uint(&self) -> bool { | |
1070 | match self.sty { | |
7453a54e | 1071 | TyInfer(IntVar(_)) | TyUint(ast::UintTy::Us) => true, |
e9174d1e SL |
1072 | _ => false |
1073 | } | |
1074 | } | |
1075 | ||
1076 | pub fn is_char(&self) -> bool { | |
1077 | match self.sty { | |
1078 | TyChar => true, | |
1079 | _ => false | |
1080 | } | |
1081 | } | |
1082 | ||
1083 | pub fn is_bare_fn(&self) -> bool { | |
1084 | match self.sty { | |
1085 | TyBareFn(..) => true, | |
1086 | _ => false | |
1087 | } | |
1088 | } | |
1089 | ||
1090 | pub fn is_bare_fn_item(&self) -> bool { | |
1091 | match self.sty { | |
1092 | TyBareFn(Some(_), _) => true, | |
1093 | _ => false | |
1094 | } | |
1095 | } | |
1096 | ||
1097 | pub fn is_fp(&self) -> bool { | |
1098 | match self.sty { | |
1099 | TyInfer(FloatVar(_)) | TyFloat(_) => true, | |
1100 | _ => false | |
1101 | } | |
1102 | } | |
1103 | ||
1104 | pub fn is_numeric(&self) -> bool { | |
1105 | self.is_integral() || self.is_fp() | |
1106 | } | |
1107 | ||
1108 | pub fn is_signed(&self) -> bool { | |
1109 | match self.sty { | |
1110 | TyInt(_) => true, | |
1111 | _ => false | |
1112 | } | |
1113 | } | |
1114 | ||
1115 | pub fn is_machine(&self) -> bool { | |
1116 | match self.sty { | |
7453a54e | 1117 | TyInt(ast::IntTy::Is) | TyUint(ast::UintTy::Us) => false, |
e9174d1e SL |
1118 | TyInt(..) | TyUint(..) | TyFloat(..) => true, |
1119 | _ => false | |
1120 | } | |
1121 | } | |
1122 | ||
1123 | // Returns the type and mutability of *ty. | |
1124 | // | |
1125 | // The parameter `explicit` indicates if this is an *explicit* dereference. | |
1126 | // Some types---notably unsafe ptrs---can only be dereferenced explicitly. | |
1127 | pub fn builtin_deref(&self, explicit: bool, pref: ty::LvaluePreference) | |
1128 | -> Option<TypeAndMut<'tcx>> | |
1129 | { | |
1130 | match self.sty { | |
1131 | TyBox(ty) => { | |
1132 | Some(TypeAndMut { | |
1133 | ty: ty, | |
1134 | mutbl: if pref == ty::PreferMutLvalue { | |
1135 | hir::MutMutable | |
1136 | } else { | |
1137 | hir::MutImmutable | |
1138 | }, | |
1139 | }) | |
1140 | }, | |
1141 | TyRef(_, mt) => Some(mt), | |
1142 | TyRawPtr(mt) if explicit => Some(mt), | |
1143 | _ => None | |
1144 | } | |
1145 | } | |
1146 | ||
1147 | // Returns the type of ty[i] | |
1148 | pub fn builtin_index(&self) -> Option<Ty<'tcx>> { | |
1149 | match self.sty { | |
1150 | TyArray(ty, _) | TySlice(ty) => Some(ty), | |
1151 | _ => None | |
1152 | } | |
1153 | } | |
1154 | ||
1155 | pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> { | |
1156 | match self.sty { | |
1157 | TyBareFn(_, ref f) => &f.sig, | |
1158 | _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self) | |
1159 | } | |
1160 | } | |
1161 | ||
1162 | /// Returns the ABI of the given function. | |
1163 | pub fn fn_abi(&self) -> abi::Abi { | |
1164 | match self.sty { | |
1165 | TyBareFn(_, ref f) => f.abi, | |
1166 | _ => panic!("Ty::fn_abi() called on non-fn type"), | |
1167 | } | |
1168 | } | |
1169 | ||
1170 | // Type accessors for substructures of types | |
1171 | pub fn fn_args(&self) -> ty::Binder<Vec<Ty<'tcx>>> { | |
1172 | self.fn_sig().inputs() | |
1173 | } | |
1174 | ||
1175 | pub fn fn_ret(&self) -> Binder<FnOutput<'tcx>> { | |
1176 | self.fn_sig().output() | |
1177 | } | |
1178 | ||
1179 | pub fn is_fn(&self) -> bool { | |
1180 | match self.sty { | |
1181 | TyBareFn(..) => true, | |
1182 | _ => false | |
1183 | } | |
1184 | } | |
1185 | ||
1186 | pub fn ty_to_def_id(&self) -> Option<DefId> { | |
1187 | match self.sty { | |
1188 | TyTrait(ref tt) => Some(tt.principal_def_id()), | |
1189 | TyStruct(def, _) | | |
1190 | TyEnum(def, _) => Some(def.did), | |
1191 | TyClosure(id, _) => Some(id), | |
1192 | _ => None | |
1193 | } | |
1194 | } | |
1195 | ||
1196 | pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> { | |
1197 | match self.sty { | |
1198 | TyStruct(adt, _) | TyEnum(adt, _) => Some(adt), | |
1199 | _ => None | |
1200 | } | |
1201 | } | |
1202 | ||
1203 | /// Returns the regions directly referenced from this type (but | |
1204 | /// not types reachable from this type via `walk_tys`). This | |
1205 | /// ignores late-bound regions binders. | |
1206 | pub fn regions(&self) -> Vec<ty::Region> { | |
1207 | match self.sty { | |
1208 | TyRef(region, _) => { | |
1209 | vec![*region] | |
1210 | } | |
1211 | TyTrait(ref obj) => { | |
1212 | let mut v = vec![obj.bounds.region_bound]; | |
92a42be0 SL |
1213 | v.extend_from_slice(obj.principal.skip_binder() |
1214 | .substs.regions().as_slice()); | |
e9174d1e SL |
1215 | v |
1216 | } | |
1217 | TyEnum(_, substs) | | |
1218 | TyStruct(_, substs) => { | |
1219 | substs.regions().as_slice().to_vec() | |
1220 | } | |
1221 | TyClosure(_, ref substs) => { | |
1222 | substs.func_substs.regions().as_slice().to_vec() | |
1223 | } | |
1224 | TyProjection(ref data) => { | |
1225 | data.trait_ref.substs.regions().as_slice().to_vec() | |
1226 | } | |
1227 | TyBareFn(..) | | |
1228 | TyBool | | |
1229 | TyChar | | |
1230 | TyInt(_) | | |
1231 | TyUint(_) | | |
1232 | TyFloat(_) | | |
1233 | TyBox(_) | | |
1234 | TyStr | | |
1235 | TyArray(_, _) | | |
1236 | TySlice(_) | | |
1237 | TyRawPtr(_) | | |
1238 | TyTuple(_) | | |
1239 | TyParam(_) | | |
1240 | TyInfer(_) | | |
1241 | TyError => { | |
1242 | vec![] | |
1243 | } | |
1244 | } | |
1245 | } | |
1246 | } |