]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! This module contains TypeVariants and its major components | |
12 | ||
54a0048b | 13 | use hir::def_id::DefId; |
476ff2be | 14 | |
ea8adc8c | 15 | use middle::const_val::ConstVal; |
e9174d1e | 16 | use middle::region; |
94b46f34 | 17 | use polonius_engine::Atom; |
abe05a73 | 18 | use rustc_data_structures::indexed_vec::Idx; |
0531ce1d | 19 | use ty::subst::{Substs, Subst, Kind, UnpackedKind}; |
476ff2be | 20 | use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; |
94b46f34 | 21 | use ty::{Slice, TyS, ParamEnvAnd, ParamEnv}; |
0531ce1d | 22 | use util::captures::Captures; |
94b46f34 | 23 | use mir::interpret::{Scalar, Pointer, Value, ConstValue}; |
e9174d1e | 24 | |
476ff2be SL |
25 | use std::iter; |
26 | use std::cmp::Ordering; | |
83c7162d | 27 | use rustc_target::spec::abi; |
32a655c1 | 28 | use syntax::ast::{self, Name}; |
0531ce1d | 29 | use syntax::symbol::{keywords, InternedString}; |
e9174d1e | 30 | |
9e0c209e | 31 | use serialize; |
9cc50fc6 | 32 | |
54a0048b | 33 | use hir; |
e9174d1e | 34 | |
e9174d1e SL |
35 | use self::InferTy::*; |
36 | use self::TypeVariants::*; | |
37 | ||
94b46f34 | 38 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
39 | pub struct TypeAndMut<'tcx> { |
40 | pub ty: Ty<'tcx>, | |
41 | pub mutbl: hir::Mutability, | |
42 | } | |
43 | ||
44 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, | |
45 | RustcEncodable, RustcDecodable, Copy)] | |
46 | /// A "free" region `fr` can be interpreted as "some region | |
47 | /// at least as big as the scope `fr.scope`". | |
48 | pub struct FreeRegion { | |
7cac9316 | 49 | pub scope: DefId, |
cc61c64b | 50 | pub bound_region: BoundRegion, |
e9174d1e SL |
51 | } |
52 | ||
53 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, | |
54 | RustcEncodable, RustcDecodable, Copy)] | |
55 | pub enum BoundRegion { | |
56 | /// An anonymous region parameter for a given fn (&T) | |
57 | BrAnon(u32), | |
58 | ||
59 | /// Named region parameters for functions (a in &'a T) | |
60 | /// | |
61 | /// The def-id is needed to distinguish free regions in | |
62 | /// the event of shadowing. | |
83c7162d | 63 | BrNamed(DefId, InternedString), |
e9174d1e SL |
64 | |
65 | /// Fresh bound identifiers created during GLB computations. | |
66 | BrFresh(u32), | |
67 | ||
7cac9316 XL |
68 | /// Anonymous region for the implicit env pointer parameter |
69 | /// to a closure | |
cc61c64b | 70 | BrEnv, |
e9174d1e SL |
71 | } |
72 | ||
7cac9316 XL |
73 | impl BoundRegion { |
74 | pub fn is_named(&self) -> bool { | |
75 | match *self { | |
76 | BoundRegion::BrNamed(..) => true, | |
77 | _ => false, | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
7cac9316 XL |
82 | /// NB: If you change this, you'll probably want to change the corresponding |
83 | /// AST structure in libsyntax/ast.rs as well. | |
94b46f34 | 84 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
85 | pub enum TypeVariants<'tcx> { |
86 | /// The primitive boolean type. Written as `bool`. | |
87 | TyBool, | |
88 | ||
89 | /// The primitive character type; holds a Unicode scalar value | |
90 | /// (a non-surrogate code point). Written as `char`. | |
91 | TyChar, | |
92 | ||
93 | /// A primitive signed integer type. For example, `i32`. | |
b039eaaf | 94 | TyInt(ast::IntTy), |
e9174d1e SL |
95 | |
96 | /// A primitive unsigned integer type. For example, `u32`. | |
b039eaaf | 97 | TyUint(ast::UintTy), |
e9174d1e SL |
98 | |
99 | /// A primitive floating-point type. For example, `f64`. | |
b039eaaf | 100 | TyFloat(ast::FloatTy), |
e9174d1e | 101 | |
9e0c209e | 102 | /// Structures, enumerations and unions. |
e9174d1e SL |
103 | /// |
104 | /// Substs here, possibly against intuition, *may* contain `TyParam`s. | |
105 | /// That is, even after substitution it is possible that there are type | |
9e0c209e SL |
106 | /// variables. This happens when the `TyAdt` corresponds to an ADT |
107 | /// definition and not a concrete use of it. | |
476ff2be | 108 | TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>), |
e9174d1e | 109 | |
abe05a73 XL |
110 | TyForeign(DefId), |
111 | ||
e9174d1e SL |
112 | /// The pointee of a string slice. Written as `str`. |
113 | TyStr, | |
114 | ||
115 | /// An array with the given length. Written as `[T; n]`. | |
ea8adc8c | 116 | TyArray(Ty<'tcx>, &'tcx ty::Const<'tcx>), |
e9174d1e SL |
117 | |
118 | /// The pointee of an array slice. Written as `[T]`. | |
119 | TySlice(Ty<'tcx>), | |
120 | ||
121 | /// A raw pointer. Written as `*mut T` or `*const T` | |
122 | TyRawPtr(TypeAndMut<'tcx>), | |
123 | ||
124 | /// A reference; a pointer with an associated lifetime. Written as | |
32a655c1 | 125 | /// `&'a mut T` or `&'a T`. |
94b46f34 | 126 | TyRef(Region<'tcx>, Ty<'tcx>, hir::Mutability), |
e9174d1e | 127 | |
54a0048b SL |
128 | /// The anonymous type of a function declaration/definition. Each |
129 | /// function has a unique type. | |
041b39d2 | 130 | TyFnDef(DefId, &'tcx Substs<'tcx>), |
54a0048b SL |
131 | |
132 | /// A pointer to a function. Written as `fn() -> i32`. | |
8bb4bdeb | 133 | TyFnPtr(PolyFnSig<'tcx>), |
e9174d1e SL |
134 | |
135 | /// A trait, defined with `trait`. | |
7cac9316 | 136 | TyDynamic(Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>), |
e9174d1e SL |
137 | |
138 | /// The anonymous type of a closure. Used to represent the type of | |
139 | /// `|a| a`. | |
a7813a04 | 140 | TyClosure(DefId, ClosureSubsts<'tcx>), |
e9174d1e | 141 | |
ea8adc8c XL |
142 | /// The anonymous type of a generator. Used to represent the type of |
143 | /// `|a| yield a`. | |
94b46f34 | 144 | TyGenerator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), |
ea8adc8c | 145 | |
2c00a5a8 XL |
146 | /// A type representin the types stored inside a generator. |
147 | /// This should only appear in GeneratorInteriors. | |
148 | TyGeneratorWitness(Binder<&'tcx Slice<Ty<'tcx>>>), | |
149 | ||
5bcae85e SL |
150 | /// The never type `!` |
151 | TyNever, | |
152 | ||
e9174d1e | 153 | /// A tuple type. For example, `(i32, bool)`. |
0531ce1d | 154 | TyTuple(&'tcx Slice<Ty<'tcx>>), |
e9174d1e SL |
155 | |
156 | /// The projection of an associated type. For example, | |
157 | /// `<T as Trait<..>>::N`. | |
158 | TyProjection(ProjectionTy<'tcx>), | |
159 | ||
5bcae85e SL |
160 | /// Anonymized (`impl Trait`) type found in a return type. |
161 | /// The DefId comes from the `impl Trait` ast::Ty node, and the | |
162 | /// substitutions are for the generics of the function in question. | |
476ff2be | 163 | /// After typeck, the concrete type can be found in the `types` map. |
5bcae85e SL |
164 | TyAnon(DefId, &'tcx Substs<'tcx>), |
165 | ||
e9174d1e SL |
166 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} |
167 | TyParam(ParamTy), | |
168 | ||
169 | /// A type variable used during type-checking. | |
170 | TyInfer(InferTy), | |
171 | ||
172 | /// A placeholder for a type which could not be computed; this is | |
173 | /// propagated to avoid useless error messages. | |
174 | TyError, | |
175 | } | |
176 | ||
177 | /// A closure can be modeled as a struct that looks like: | |
178 | /// | |
ff7c6d11 | 179 | /// struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> { |
e9174d1e SL |
180 | /// upvar0: U0, |
181 | /// ... | |
182 | /// upvark: Uk | |
183 | /// } | |
184 | /// | |
ff7c6d11 XL |
185 | /// where: |
186 | /// | |
187 | /// - 'l0...'li and T0...Tj are the lifetime and type parameters | |
188 | /// in scope on the function that defined the closure, | |
189 | /// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This | |
190 | /// is rather hackily encoded via a scalar type. See | |
191 | /// `TyS::to_opt_closure_kind` for details. | |
192 | /// - CS represents the *closure signature*, representing as a `fn()` | |
193 | /// type. For example, `fn(u32, u32) -> u32` would mean that the closure | |
194 | /// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait | |
195 | /// specified above. | |
196 | /// - U0...Uk are type parameters representing the types of its upvars | |
197 | /// (borrowed, if appropriate; that is, if Ui represents a by-ref upvar, | |
198 | /// and the up-var has the type `Foo`, then `Ui = &Foo`). | |
e9174d1e SL |
199 | /// |
200 | /// So, for example, given this function: | |
201 | /// | |
202 | /// fn foo<'a, T>(data: &'a mut T) { | |
203 | /// do(|| data.count += 1) | |
204 | /// } | |
205 | /// | |
206 | /// the type of the closure would be something like: | |
207 | /// | |
208 | /// struct Closure<'a, T, U0> { | |
209 | /// data: U0 | |
210 | /// } | |
211 | /// | |
212 | /// Note that the type of the upvar is not specified in the struct. | |
213 | /// You may wonder how the impl would then be able to use the upvar, | |
214 | /// if it doesn't know it's type? The answer is that the impl is | |
215 | /// (conceptually) not fully generic over Closure but rather tied to | |
216 | /// instances with the expected upvar types: | |
217 | /// | |
218 | /// impl<'b, 'a, T> FnMut() for Closure<'a, T, &'b mut &'a mut T> { | |
219 | /// ... | |
220 | /// } | |
221 | /// | |
222 | /// You can see that the *impl* fully specified the type of the upvar | |
223 | /// and thus knows full well that `data` has type `&'b mut &'a mut T`. | |
224 | /// (Here, I am assuming that `data` is mut-borrowed.) | |
225 | /// | |
226 | /// Now, the last question you may ask is: Why include the upvar types | |
227 | /// as extra type parameters? The reason for this design is that the | |
228 | /// upvar types can reference lifetimes that are internal to the | |
229 | /// creating function. In my example above, for example, the lifetime | |
ea8adc8c XL |
230 | /// `'b` represents the scope of the closure itself; this is some |
231 | /// subset of `foo`, probably just the scope of the call to the to | |
e9174d1e SL |
232 | /// `do()`. If we just had the lifetime/type parameters from the |
233 | /// enclosing function, we couldn't name this lifetime `'b`. Note that | |
234 | /// there can also be lifetimes in the types of the upvars themselves, | |
235 | /// if one of them happens to be a reference to something that the | |
236 | /// creating fn owns. | |
237 | /// | |
238 | /// OK, you say, so why not create a more minimal set of parameters | |
239 | /// that just includes the extra lifetime parameters? The answer is | |
240 | /// primarily that it would be hard --- we don't know at the time when | |
241 | /// we create the closure type what the full types of the upvars are, | |
242 | /// nor do we know which are borrowed and which are not. In this | |
243 | /// design, we can just supply a fresh type parameter and figure that | |
244 | /// out later. | |
245 | /// | |
246 | /// All right, you say, but why include the type parameters from the | |
94b46f34 | 247 | /// original function then? The answer is that codegen may need them |
e9174d1e SL |
248 | /// when monomorphizing, and they may not appear in the upvars. A |
249 | /// closure could capture no variables but still make use of some | |
250 | /// in-scope type parameter with a bound (e.g., if our example above | |
251 | /// had an extra `U: Default`, and the closure called `U::default()`). | |
252 | /// | |
253 | /// There is another reason. This design (implicitly) prohibits | |
254 | /// closures from capturing themselves (except via a trait | |
255 | /// object). This simplifies closure inference considerably, since it | |
256 | /// means that when we infer the kind of a closure or its upvars, we | |
257 | /// don't have to handle cycles where the decisions we make for | |
258 | /// closure C wind up influencing the decisions we ought to make for | |
259 | /// closure C (which would then require fixed point iteration to | |
260 | /// handle). Plus it fixes an ICE. :P | |
ff7c6d11 XL |
261 | /// |
262 | /// ## Generators | |
263 | /// | |
264 | /// Perhaps surprisingly, `ClosureSubsts` are also used for | |
265 | /// generators. In that case, what is written above is only half-true | |
266 | /// -- the set of type parameters is similar, but the role of CK and | |
267 | /// CS are different. CK represents the "yield type" and CS | |
268 | /// represents the "return type" of the generator. | |
269 | /// | |
270 | /// It'd be nice to split this struct into ClosureSubsts and | |
271 | /// GeneratorSubsts, I believe. -nmatsakis | |
94b46f34 | 272 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e | 273 | pub struct ClosureSubsts<'tcx> { |
476ff2be SL |
274 | /// Lifetime and type parameters from the enclosing function, |
275 | /// concatenated with the types of the upvars. | |
276 | /// | |
94b46f34 | 277 | /// These are separated out because codegen wants to pass them around |
e9174d1e | 278 | /// when monomorphizing. |
476ff2be SL |
279 | pub substs: &'tcx Substs<'tcx>, |
280 | } | |
e9174d1e | 281 | |
ff7c6d11 XL |
282 | /// Struct returned by `split()`. Note that these are subslices of the |
283 | /// parent slice and not canonical substs themselves. | |
284 | struct SplitClosureSubsts<'tcx> { | |
285 | closure_kind_ty: Ty<'tcx>, | |
286 | closure_sig_ty: Ty<'tcx>, | |
287 | upvar_kinds: &'tcx [Kind<'tcx>], | |
288 | } | |
289 | ||
290 | impl<'tcx> ClosureSubsts<'tcx> { | |
291 | /// Divides the closure substs into their respective | |
292 | /// components. Single source of truth with respect to the | |
293 | /// ordering. | |
294 | fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitClosureSubsts<'tcx> { | |
295 | let generics = tcx.generics_of(def_id); | |
94b46f34 | 296 | let parent_len = generics.parent_count; |
ff7c6d11 | 297 | SplitClosureSubsts { |
0531ce1d XL |
298 | closure_kind_ty: self.substs.type_at(parent_len), |
299 | closure_sig_ty: self.substs.type_at(parent_len + 1), | |
ff7c6d11 XL |
300 | upvar_kinds: &self.substs[parent_len + 2..], |
301 | } | |
302 | } | |
303 | ||
476ff2be | 304 | #[inline] |
ff7c6d11 | 305 | pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> |
476ff2be SL |
306 | impl Iterator<Item=Ty<'tcx>> + 'tcx |
307 | { | |
ff7c6d11 | 308 | let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx); |
0531ce1d XL |
309 | upvar_kinds.iter().map(|t| { |
310 | if let UnpackedKind::Type(ty) = t.unpack() { | |
311 | ty | |
312 | } else { | |
313 | bug!("upvar should be type") | |
314 | } | |
315 | }) | |
ff7c6d11 XL |
316 | } |
317 | ||
318 | /// Returns the closure kind for this closure; may return a type | |
319 | /// variable during inference. To get the closure kind during | |
320 | /// inference, use `infcx.closure_kind(def_id, substs)`. | |
321 | pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
322 | self.split(def_id, tcx).closure_kind_ty | |
323 | } | |
324 | ||
325 | /// Returns the type representing the closure signature for this | |
326 | /// closure; may contain type variables during inference. To get | |
327 | /// the closure signature during inference, use | |
328 | /// `infcx.fn_sig(def_id)`. | |
329 | pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
330 | self.split(def_id, tcx).closure_sig_ty | |
331 | } | |
332 | ||
ff7c6d11 XL |
333 | /// Returns the closure kind for this closure; only usable outside |
334 | /// of an inference context, because in that context we know that | |
335 | /// there are no type variables. | |
336 | /// | |
337 | /// If you have an inference context, use `infcx.closure_kind()`. | |
338 | pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::ClosureKind { | |
339 | self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap() | |
340 | } | |
341 | ||
342 | /// Extracts the signature from the closure; only usable outside | |
343 | /// of an inference context, because in that context we know that | |
344 | /// there are no type variables. | |
345 | /// | |
346 | /// If you have an inference context, use `infcx.closure_sig()`. | |
347 | pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { | |
348 | match self.closure_sig_ty(def_id, tcx).sty { | |
349 | ty::TyFnPtr(sig) => sig, | |
350 | ref t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t), | |
351 | } | |
476ff2be | 352 | } |
a7813a04 | 353 | } |
9cc50fc6 | 354 | |
94b46f34 XL |
355 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
356 | pub struct GeneratorSubsts<'tcx> { | |
357 | pub substs: &'tcx Substs<'tcx>, | |
358 | } | |
359 | ||
360 | struct SplitGeneratorSubsts<'tcx> { | |
361 | yield_ty: Ty<'tcx>, | |
362 | return_ty: Ty<'tcx>, | |
363 | witness: Ty<'tcx>, | |
364 | upvar_kinds: &'tcx [Kind<'tcx>], | |
365 | } | |
366 | ||
367 | impl<'tcx> GeneratorSubsts<'tcx> { | |
368 | fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitGeneratorSubsts<'tcx> { | |
369 | let generics = tcx.generics_of(def_id); | |
370 | let parent_len = generics.parent_count; | |
371 | SplitGeneratorSubsts { | |
372 | yield_ty: self.substs.type_at(parent_len), | |
373 | return_ty: self.substs.type_at(parent_len + 1), | |
374 | witness: self.substs.type_at(parent_len + 2), | |
375 | upvar_kinds: &self.substs[parent_len + 3..], | |
376 | } | |
377 | } | |
378 | ||
379 | /// This describes the types that can be contained in a generator. | |
380 | /// It will be a type variable initially and unified in the last stages of typeck of a body. | |
381 | /// It contains a tuple of all the types that could end up on a generator frame. | |
382 | /// The state transformation MIR pass may only produce layouts which mention types | |
383 | /// in this tuple. Upvars are not counted here. | |
384 | pub fn witness(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
385 | self.split(def_id, tcx).witness | |
386 | } | |
387 | ||
388 | #[inline] | |
389 | pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> | |
390 | impl Iterator<Item=Ty<'tcx>> + 'tcx | |
391 | { | |
392 | let SplitGeneratorSubsts { upvar_kinds, .. } = self.split(def_id, tcx); | |
393 | upvar_kinds.iter().map(|t| { | |
394 | if let UnpackedKind::Type(ty) = t.unpack() { | |
395 | ty | |
396 | } else { | |
397 | bug!("upvar should be type") | |
398 | } | |
399 | }) | |
400 | } | |
401 | ||
402 | /// Returns the type representing the yield type of the generator. | |
403 | pub fn yield_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
404 | self.split(def_id, tcx).yield_ty | |
405 | } | |
406 | ||
407 | /// Returns the type representing the return type of the generator. | |
408 | pub fn return_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> { | |
409 | self.split(def_id, tcx).return_ty | |
410 | } | |
411 | ||
412 | /// Return the "generator signature", which consists of its yield | |
413 | /// and return types. | |
414 | /// | |
415 | /// NB. Some bits of the code prefers to see this wrapped in a | |
416 | /// binder, but it never contains bound regions. Probably this | |
417 | /// function should be removed. | |
418 | pub fn poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> { | |
419 | ty::Binder::dummy(self.sig(def_id, tcx)) | |
420 | } | |
421 | ||
422 | /// Return the "generator signature", which consists of its yield | |
423 | /// and return types. | |
424 | pub fn sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> GenSig<'tcx> { | |
425 | ty::GenSig { | |
426 | yield_ty: self.yield_ty(def_id, tcx), | |
427 | return_ty: self.return_ty(def_id, tcx), | |
428 | } | |
429 | } | |
430 | } | |
431 | ||
432 | impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> { | |
ea8adc8c XL |
433 | /// This returns the types of the MIR locals which had to be stored across suspension points. |
434 | /// It is calculated in rustc_mir::transform::generator::StateTransform. | |
435 | /// All the types here must be in the tuple in GeneratorInterior. | |
0531ce1d XL |
436 | pub fn state_tys( |
437 | self, | |
438 | def_id: DefId, | |
439 | tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
440 | ) -> impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a { | |
ea8adc8c XL |
441 | let state = tcx.generator_layout(def_id).fields.iter(); |
442 | state.map(move |d| d.ty.subst(tcx, self.substs)) | |
443 | } | |
444 | ||
2c00a5a8 XL |
445 | /// This is the types of the fields of a generate which |
446 | /// is available before the generator transformation. | |
447 | /// It includes the upvars and the state discriminant which is u32. | |
448 | pub fn pre_transforms_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> | |
449 | impl Iterator<Item=Ty<'tcx>> + 'a | |
450 | { | |
451 | self.upvar_tys(def_id, tcx).chain(iter::once(tcx.types.u32)) | |
452 | } | |
453 | ||
ea8adc8c XL |
454 | /// This is the types of all the fields stored in a generator. |
455 | /// It includes the upvars, state types and the state discriminant which is u32. | |
456 | pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> | |
0531ce1d | 457 | impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a |
ea8adc8c | 458 | { |
2c00a5a8 | 459 | self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx)) |
ea8adc8c XL |
460 | } |
461 | } | |
462 | ||
94b46f34 XL |
463 | #[derive(Debug, Copy, Clone)] |
464 | pub enum UpvarSubsts<'tcx> { | |
465 | Closure(ClosureSubsts<'tcx>), | |
466 | Generator(GeneratorSubsts<'tcx>), | |
467 | } | |
468 | ||
469 | impl<'tcx> UpvarSubsts<'tcx> { | |
470 | #[inline] | |
471 | pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> | |
472 | impl Iterator<Item=Ty<'tcx>> + 'tcx | |
473 | { | |
474 | let upvar_kinds = match self { | |
475 | UpvarSubsts::Closure(substs) => substs.split(def_id, tcx).upvar_kinds, | |
476 | UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds, | |
477 | }; | |
478 | upvar_kinds.iter().map(|t| { | |
479 | if let UnpackedKind::Type(ty) = t.unpack() { | |
480 | ty | |
481 | } else { | |
482 | bug!("upvar should be type") | |
483 | } | |
484 | }) | |
485 | } | |
ea8adc8c XL |
486 | } |
487 | ||
94b46f34 | 488 | #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, RustcEncodable, RustcDecodable)] |
476ff2be | 489 | pub enum ExistentialPredicate<'tcx> { |
7cac9316 | 490 | /// e.g. Iterator |
476ff2be | 491 | Trait(ExistentialTraitRef<'tcx>), |
7cac9316 | 492 | /// e.g. Iterator::Item = T |
476ff2be | 493 | Projection(ExistentialProjection<'tcx>), |
7cac9316 | 494 | /// e.g. Send |
476ff2be SL |
495 | AutoTrait(DefId), |
496 | } | |
497 | ||
498 | impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> { | |
94b46f34 XL |
499 | /// Compares via an ordering that will not change if modules are reordered or other changes are |
500 | /// made to the tree. In particular, this ordering is preserved across incremental compilations. | |
501 | pub fn stable_cmp(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, other: &Self) -> Ordering { | |
476ff2be SL |
502 | use self::ExistentialPredicate::*; |
503 | match (*self, *other) { | |
504 | (Trait(_), Trait(_)) => Ordering::Equal, | |
041b39d2 XL |
505 | (Projection(ref a), Projection(ref b)) => |
506 | tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)), | |
476ff2be | 507 | (AutoTrait(ref a), AutoTrait(ref b)) => |
7cac9316 | 508 | tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash), |
476ff2be SL |
509 | (Trait(_), _) => Ordering::Less, |
510 | (Projection(_), Trait(_)) => Ordering::Greater, | |
511 | (Projection(_), _) => Ordering::Less, | |
512 | (AutoTrait(_), _) => Ordering::Greater, | |
513 | } | |
514 | } | |
515 | ||
516 | } | |
517 | ||
518 | impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> { | |
519 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) | |
520 | -> ty::Predicate<'tcx> { | |
521 | use ty::ToPredicate; | |
522 | match *self.skip_binder() { | |
523 | ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(), | |
524 | ExistentialPredicate::Projection(p) => | |
525 | ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))), | |
526 | ExistentialPredicate::AutoTrait(did) => { | |
527 | let trait_ref = Binder(ty::TraitRef { | |
528 | def_id: did, | |
529 | substs: tcx.mk_substs_trait(self_ty, &[]), | |
530 | }); | |
531 | trait_ref.to_predicate() | |
532 | } | |
533 | } | |
534 | } | |
535 | } | |
536 | ||
537 | impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<ExistentialPredicate<'tcx>> {} | |
538 | ||
539 | impl<'tcx> Slice<ExistentialPredicate<'tcx>> { | |
540 | pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> { | |
541 | match self.get(0) { | |
542 | Some(&ExistentialPredicate::Trait(tr)) => Some(tr), | |
cc61c64b | 543 | _ => None, |
476ff2be SL |
544 | } |
545 | } | |
546 | ||
547 | #[inline] | |
548 | pub fn projection_bounds<'a>(&'a self) -> | |
549 | impl Iterator<Item=ExistentialProjection<'tcx>> + 'a { | |
550 | self.iter().filter_map(|predicate| { | |
551 | match *predicate { | |
552 | ExistentialPredicate::Projection(p) => Some(p), | |
553 | _ => None, | |
554 | } | |
555 | }) | |
556 | } | |
557 | ||
558 | #[inline] | |
559 | pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a { | |
560 | self.iter().filter_map(|predicate| { | |
561 | match *predicate { | |
562 | ExistentialPredicate::AutoTrait(d) => Some(d), | |
563 | _ => None | |
564 | } | |
565 | }) | |
566 | } | |
567 | } | |
568 | ||
569 | impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> { | |
570 | pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> { | |
83c7162d | 571 | self.skip_binder().principal().map(Binder::bind) |
476ff2be SL |
572 | } |
573 | ||
574 | #[inline] | |
575 | pub fn projection_bounds<'a>(&'a self) -> | |
576 | impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a { | |
83c7162d | 577 | self.skip_binder().projection_bounds().map(Binder::bind) |
476ff2be SL |
578 | } |
579 | ||
580 | #[inline] | |
581 | pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a { | |
582 | self.skip_binder().auto_traits() | |
583 | } | |
584 | ||
585 | pub fn iter<'a>(&'a self) | |
586 | -> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx { | |
83c7162d | 587 | self.skip_binder().iter().cloned().map(Binder::bind) |
476ff2be | 588 | } |
e9174d1e SL |
589 | } |
590 | ||
591 | /// A complete reference to a trait. These take numerous guises in syntax, | |
592 | /// but perhaps the most recognizable form is in a where clause: | |
593 | /// | |
594 | /// T : Foo<U> | |
595 | /// | |
596 | /// This would be represented by a trait-reference where the def-id is the | |
9e0c209e SL |
597 | /// def-id for the trait `Foo` and the substs define `T` as parameter 0, |
598 | /// and `U` as parameter 1. | |
e9174d1e SL |
599 | /// |
600 | /// Trait references also appear in object types like `Foo<U>`, but in | |
601 | /// that case the `Self` parameter is absent from the substitutions. | |
602 | /// | |
603 | /// Note that a `TraitRef` introduces a level of region binding, to | |
604 | /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a | |
605 | /// U>` or higher-ranked object types. | |
9e0c209e | 606 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e SL |
607 | pub struct TraitRef<'tcx> { |
608 | pub def_id: DefId, | |
609 | pub substs: &'tcx Substs<'tcx>, | |
610 | } | |
611 | ||
8bb4bdeb XL |
612 | impl<'tcx> TraitRef<'tcx> { |
613 | pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { | |
614 | TraitRef { def_id: def_id, substs: substs } | |
615 | } | |
616 | ||
617 | pub fn self_ty(&self) -> Ty<'tcx> { | |
618 | self.substs.type_at(0) | |
619 | } | |
620 | ||
621 | pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { | |
622 | // Select only the "input types" from a trait-reference. For | |
623 | // now this is all the types that appear in the | |
624 | // trait-reference, but it should eventually exclude | |
625 | // associated types. | |
626 | self.substs.types() | |
627 | } | |
94b46f34 XL |
628 | |
629 | pub fn from_method(tcx: TyCtxt<'_, '_, 'tcx>, | |
630 | trait_id: DefId, | |
631 | substs: &Substs<'tcx>) | |
632 | -> ty::TraitRef<'tcx> { | |
633 | let defs = tcx.generics_of(trait_id); | |
634 | ||
635 | ty::TraitRef { | |
636 | def_id: trait_id, | |
637 | substs: tcx.intern_substs(&substs[..defs.params.len()]) | |
638 | } | |
639 | } | |
8bb4bdeb XL |
640 | } |
641 | ||
e9174d1e SL |
642 | pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>; |
643 | ||
644 | impl<'tcx> PolyTraitRef<'tcx> { | |
645 | pub fn self_ty(&self) -> Ty<'tcx> { | |
83c7162d | 646 | self.skip_binder().self_ty() |
e9174d1e SL |
647 | } |
648 | ||
649 | pub fn def_id(&self) -> DefId { | |
83c7162d | 650 | self.skip_binder().def_id |
e9174d1e SL |
651 | } |
652 | ||
653 | pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { | |
654 | // Note that we preserve binding levels | |
83c7162d | 655 | Binder(ty::TraitPredicate { trait_ref: self.skip_binder().clone() }) |
e9174d1e SL |
656 | } |
657 | } | |
658 | ||
9e0c209e SL |
659 | /// An existential reference to a trait, where `Self` is erased. |
660 | /// For example, the trait object `Trait<'a, 'b, X, Y>` is: | |
661 | /// | |
662 | /// exists T. T: Trait<'a, 'b, X, Y> | |
663 | /// | |
664 | /// The substitutions don't include the erased `Self`, only trait | |
665 | /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). | |
94b46f34 | 666 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
9e0c209e SL |
667 | pub struct ExistentialTraitRef<'tcx> { |
668 | pub def_id: DefId, | |
669 | pub substs: &'tcx Substs<'tcx>, | |
670 | } | |
671 | ||
476ff2be SL |
672 | impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { |
673 | pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'b { | |
9e0c209e SL |
674 | // Select only the "input types" from a trait-reference. For |
675 | // now this is all the types that appear in the | |
676 | // trait-reference, but it should eventually exclude | |
677 | // associated types. | |
678 | self.substs.types() | |
679 | } | |
476ff2be | 680 | |
94b46f34 XL |
681 | pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>, |
682 | trait_ref: ty::TraitRef<'tcx>) | |
683 | -> ty::ExistentialTraitRef<'tcx> { | |
684 | // Assert there is a Self. | |
685 | trait_ref.substs.type_at(0); | |
686 | ||
687 | ty::ExistentialTraitRef { | |
688 | def_id: trait_ref.def_id, | |
689 | substs: tcx.intern_substs(&trait_ref.substs[1..]) | |
690 | } | |
691 | } | |
692 | ||
476ff2be SL |
693 | /// Object types don't have a self-type specified. Therefore, when |
694 | /// we convert the principal trait-ref into a normal trait-ref, | |
695 | /// you must give *some* self-type. A common choice is `mk_err()` | |
696 | /// or some skolemized type. | |
697 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) | |
698 | -> ty::TraitRef<'tcx> { | |
699 | // otherwise the escaping regions would be captured by the binder | |
700 | assert!(!self_ty.has_escaping_regions()); | |
701 | ||
702 | ty::TraitRef { | |
703 | def_id: self.def_id, | |
94b46f34 | 704 | substs: tcx.mk_substs_trait(self_ty, self.substs) |
476ff2be SL |
705 | } |
706 | } | |
9e0c209e SL |
707 | } |
708 | ||
709 | pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>; | |
710 | ||
711 | impl<'tcx> PolyExistentialTraitRef<'tcx> { | |
712 | pub fn def_id(&self) -> DefId { | |
83c7162d | 713 | self.skip_binder().def_id |
9e0c209e | 714 | } |
94b46f34 XL |
715 | |
716 | /// Object types don't have a self-type specified. Therefore, when | |
717 | /// we convert the principal trait-ref into a normal trait-ref, | |
718 | /// you must give *some* self-type. A common choice is `mk_err()` | |
719 | /// or some skolemized type. | |
720 | pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>, | |
721 | self_ty: Ty<'tcx>) | |
722 | -> ty::PolyTraitRef<'tcx> { | |
723 | self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty)) | |
724 | } | |
9e0c209e SL |
725 | } |
726 | ||
e9174d1e SL |
727 | /// Binder is a binder for higher-ranked lifetimes. It is part of the |
728 | /// compiler's representation for things like `for<'a> Fn(&'a isize)` | |
729 | /// (which would be represented by the type `PolyTraitRef == | |
730 | /// Binder<TraitRef>`). Note that when we skolemize, instantiate, | |
731 | /// erase, or otherwise "discharge" these bound regions, we change the | |
732 | /// type from `Binder<T>` to just `T` (see | |
733 | /// e.g. `liberate_late_bound_regions`). | |
94b46f34 | 734 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
83c7162d | 735 | pub struct Binder<T>(T); |
e9174d1e SL |
736 | |
737 | impl<T> Binder<T> { | |
ff7c6d11 XL |
738 | /// Wraps `value` in a binder, asserting that `value` does not |
739 | /// contain any bound regions that would be bound by the | |
740 | /// binder. This is commonly used to 'inject' a value T into a | |
741 | /// different binding level. | |
742 | pub fn dummy<'tcx>(value: T) -> Binder<T> | |
743 | where T: TypeFoldable<'tcx> | |
744 | { | |
745 | assert!(!value.has_escaping_regions()); | |
746 | Binder(value) | |
747 | } | |
748 | ||
83c7162d XL |
749 | /// Wraps `value` in a binder, binding late-bound regions (if any). |
750 | pub fn bind<'tcx>(value: T) -> Binder<T> | |
751 | { | |
752 | Binder(value) | |
753 | } | |
754 | ||
e9174d1e SL |
755 | /// Skips the binder and returns the "bound" value. This is a |
756 | /// risky thing to do because it's easy to get confused about | |
757 | /// debruijn indices and the like. It is usually better to | |
758 | /// discharge the binder using `no_late_bound_regions` or | |
759 | /// `replace_late_bound_regions` or something like | |
760 | /// that. `skip_binder` is only valid when you are either | |
761 | /// extracting data that has nothing to do with bound regions, you | |
762 | /// are doing some sort of test that does not involve bound | |
763 | /// regions, or you are being very careful about your depth | |
764 | /// accounting. | |
765 | /// | |
766 | /// Some examples where `skip_binder` is reasonable: | |
ff7c6d11 | 767 | /// |
e9174d1e SL |
768 | /// - extracting the def-id from a PolyTraitRef; |
769 | /// - comparing the self type of a PolyTraitRef to see if it is equal to | |
770 | /// a type parameter `X`, since the type `X` does not reference any regions | |
771 | pub fn skip_binder(&self) -> &T { | |
772 | &self.0 | |
773 | } | |
774 | ||
775 | pub fn as_ref(&self) -> Binder<&T> { | |
83c7162d | 776 | Binder(&self.0) |
e9174d1e SL |
777 | } |
778 | ||
cc61c64b | 779 | pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U> |
e9174d1e SL |
780 | where F: FnOnce(&T) -> U |
781 | { | |
782 | self.as_ref().map_bound(f) | |
783 | } | |
784 | ||
cc61c64b | 785 | pub fn map_bound<F, U>(self, f: F) -> Binder<U> |
e9174d1e SL |
786 | where F: FnOnce(T) -> U |
787 | { | |
83c7162d | 788 | Binder(f(self.0)) |
e9174d1e | 789 | } |
ff7c6d11 XL |
790 | |
791 | /// Unwraps and returns the value within, but only if it contains | |
792 | /// no bound regions at all. (In other words, if this binder -- | |
793 | /// and indeed any enclosing binder -- doesn't bind anything at | |
794 | /// all.) Otherwise, returns `None`. | |
795 | /// | |
796 | /// (One could imagine having a method that just unwraps a single | |
797 | /// binder, but permits late-bound regions bound by enclosing | |
798 | /// binders, but that would require adjusting the debruijn | |
799 | /// indices, and given the shallow binding structure we often use, | |
800 | /// would not be that useful.) | |
801 | pub fn no_late_bound_regions<'tcx>(self) -> Option<T> | |
802 | where T : TypeFoldable<'tcx> | |
803 | { | |
804 | if self.skip_binder().has_escaping_regions() { | |
805 | None | |
806 | } else { | |
807 | Some(self.skip_binder().clone()) | |
808 | } | |
809 | } | |
810 | ||
811 | /// Given two things that have the same binder level, | |
812 | /// and an operation that wraps on their contents, execute the operation | |
813 | /// and then wrap its result. | |
814 | /// | |
815 | /// `f` should consider bound regions at depth 1 to be free, and | |
816 | /// anything it produces with bound regions at depth 1 will be | |
817 | /// bound in the resulting return value. | |
818 | pub fn fuse<U,F,R>(self, u: Binder<U>, f: F) -> Binder<R> | |
819 | where F: FnOnce(T, U) -> R | |
820 | { | |
83c7162d | 821 | Binder(f(self.0, u.0)) |
ff7c6d11 XL |
822 | } |
823 | ||
824 | /// Split the contents into two things that share the same binder | |
825 | /// level as the original, returning two distinct binders. | |
826 | /// | |
827 | /// `f` should consider bound regions at depth 1 to be free, and | |
828 | /// anything it produces with bound regions at depth 1 will be | |
829 | /// bound in the resulting return values. | |
830 | pub fn split<U,V,F>(self, f: F) -> (Binder<U>, Binder<V>) | |
831 | where F: FnOnce(T) -> (U, V) | |
832 | { | |
833 | let (u, v) = f(self.0); | |
83c7162d | 834 | (Binder(u), Binder(v)) |
ff7c6d11 | 835 | } |
e9174d1e SL |
836 | } |
837 | ||
e9174d1e SL |
838 | /// Represents the projection of an associated type. In explicit UFCS |
839 | /// form this would be written `<T as Trait<..>>::N`. | |
94b46f34 | 840 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
e9174d1e | 841 | pub struct ProjectionTy<'tcx> { |
041b39d2 XL |
842 | /// The parameters of the associated item. |
843 | pub substs: &'tcx Substs<'tcx>, | |
e9174d1e | 844 | |
7cac9316 XL |
845 | /// The DefId of the TraitItem for the associated type N. |
846 | /// | |
847 | /// Note that this is not the DefId of the TraitRef containing this | |
848 | /// associated type, which is in tcx.associated_item(item_def_id).container. | |
849 | pub item_def_id: DefId, | |
e9174d1e | 850 | } |
7cac9316 XL |
851 | |
852 | impl<'a, 'tcx> ProjectionTy<'tcx> { | |
853 | /// Construct a ProjectionTy by searching the trait from trait_ref for the | |
854 | /// associated item named item_name. | |
855 | pub fn from_ref_and_name( | |
856 | tcx: TyCtxt, trait_ref: ty::TraitRef<'tcx>, item_name: Name | |
857 | ) -> ProjectionTy<'tcx> { | |
ea8adc8c XL |
858 | let item_def_id = tcx.associated_items(trait_ref.def_id).find(|item| { |
859 | item.kind == ty::AssociatedKind::Type && | |
860 | tcx.hygienic_eq(item_name, item.name, trait_ref.def_id) | |
861 | }).unwrap().def_id; | |
7cac9316 XL |
862 | |
863 | ProjectionTy { | |
041b39d2 XL |
864 | substs: trait_ref.substs, |
865 | item_def_id, | |
7cac9316 XL |
866 | } |
867 | } | |
868 | ||
041b39d2 XL |
869 | /// Extracts the underlying trait reference from this projection. |
870 | /// For example, if this is a projection of `<T as Iterator>::Item`, | |
871 | /// then this function would return a `T: Iterator` trait reference. | |
872 | pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> { | |
873 | let def_id = tcx.associated_item(self.item_def_id).container.id(); | |
874 | ty::TraitRef { | |
3b2f2976 | 875 | def_id, |
041b39d2 XL |
876 | substs: self.substs, |
877 | } | |
878 | } | |
879 | ||
880 | pub fn self_ty(&self) -> Ty<'tcx> { | |
881 | self.substs.type_at(0) | |
7cac9316 XL |
882 | } |
883 | } | |
884 | ||
ea8adc8c XL |
885 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] |
886 | pub struct GenSig<'tcx> { | |
887 | pub yield_ty: Ty<'tcx>, | |
888 | pub return_ty: Ty<'tcx>, | |
889 | } | |
890 | ||
891 | pub type PolyGenSig<'tcx> = Binder<GenSig<'tcx>>; | |
892 | ||
893 | impl<'tcx> PolyGenSig<'tcx> { | |
894 | pub fn yield_ty(&self) -> ty::Binder<Ty<'tcx>> { | |
895 | self.map_bound_ref(|sig| sig.yield_ty) | |
896 | } | |
897 | pub fn return_ty(&self) -> ty::Binder<Ty<'tcx>> { | |
898 | self.map_bound_ref(|sig| sig.return_ty) | |
899 | } | |
900 | } | |
7cac9316 | 901 | |
e9174d1e SL |
902 | /// Signature of a function type, which I have arbitrarily |
903 | /// decided to use to refer to the input/output types. | |
904 | /// | |
905 | /// - `inputs` is the list of arguments and their modes. | |
906 | /// - `output` is the return type. | |
907 | /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) | |
94b46f34 | 908 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 909 | pub struct FnSig<'tcx> { |
476ff2be | 910 | pub inputs_and_output: &'tcx Slice<Ty<'tcx>>, |
8bb4bdeb XL |
911 | pub variadic: bool, |
912 | pub unsafety: hir::Unsafety, | |
913 | pub abi: abi::Abi, | |
e9174d1e SL |
914 | } |
915 | ||
476ff2be | 916 | impl<'tcx> FnSig<'tcx> { |
8bb4bdeb | 917 | pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { |
476ff2be SL |
918 | &self.inputs_and_output[..self.inputs_and_output.len() - 1] |
919 | } | |
920 | ||
921 | pub fn output(&self) -> Ty<'tcx> { | |
922 | self.inputs_and_output[self.inputs_and_output.len() - 1] | |
923 | } | |
924 | } | |
925 | ||
e9174d1e SL |
926 | pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>; |
927 | ||
928 | impl<'tcx> PolyFnSig<'tcx> { | |
8bb4bdeb | 929 | pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { |
83c7162d | 930 | self.map_bound_ref(|fn_sig| fn_sig.inputs()) |
e9174d1e SL |
931 | } |
932 | pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { | |
476ff2be | 933 | self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) |
e9174d1e | 934 | } |
ff7c6d11 XL |
935 | pub fn inputs_and_output(&self) -> ty::Binder<&'tcx Slice<Ty<'tcx>>> { |
936 | self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) | |
937 | } | |
5bcae85e | 938 | pub fn output(&self) -> ty::Binder<Ty<'tcx>> { |
476ff2be | 939 | self.map_bound_ref(|fn_sig| fn_sig.output().clone()) |
e9174d1e SL |
940 | } |
941 | pub fn variadic(&self) -> bool { | |
942 | self.skip_binder().variadic | |
943 | } | |
8bb4bdeb XL |
944 | pub fn unsafety(&self) -> hir::Unsafety { |
945 | self.skip_binder().unsafety | |
946 | } | |
947 | pub fn abi(&self) -> abi::Abi { | |
948 | self.skip_binder().abi | |
949 | } | |
e9174d1e SL |
950 | } |
951 | ||
94b46f34 | 952 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 953 | pub struct ParamTy { |
e9174d1e | 954 | pub idx: u32, |
0531ce1d | 955 | pub name: InternedString, |
e9174d1e SL |
956 | } |
957 | ||
a7813a04 | 958 | impl<'a, 'gcx, 'tcx> ParamTy { |
0531ce1d | 959 | pub fn new(index: u32, name: InternedString) -> ParamTy { |
9e0c209e | 960 | ParamTy { idx: index, name: name } |
e9174d1e SL |
961 | } |
962 | ||
963 | pub fn for_self() -> ParamTy { | |
83c7162d | 964 | ParamTy::new(0, keywords::SelfType.name().as_interned_str()) |
e9174d1e SL |
965 | } |
966 | ||
94b46f34 | 967 | pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { |
9e0c209e | 968 | ParamTy::new(def.index, def.name) |
e9174d1e SL |
969 | } |
970 | ||
a7813a04 | 971 | pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { |
94b46f34 | 972 | tcx.mk_ty_param(self.idx, self.name) |
e9174d1e SL |
973 | } |
974 | ||
975 | pub fn is_self(&self) -> bool { | |
0531ce1d XL |
976 | // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere, |
977 | // but this should only be possible when using `-Z continue-parse-after-error` like | |
978 | // `compile-fail/issue-36638.rs`. | |
979 | if self.name == keywords::SelfType.name().as_str() && self.idx == 0 { | |
9e0c209e SL |
980 | true |
981 | } else { | |
982 | false | |
983 | } | |
e9174d1e SL |
984 | } |
985 | } | |
986 | ||
987 | /// A [De Bruijn index][dbi] is a standard means of representing | |
988 | /// regions (and perhaps later types) in a higher-ranked setting. In | |
989 | /// particular, imagine a type like this: | |
990 | /// | |
991 | /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) | |
992 | /// ^ ^ | | | | |
993 | /// | | | | | | |
94b46f34 | 994 | /// | +------------+ 0 | | |
e9174d1e | 995 | /// | | | |
94b46f34 | 996 | /// +--------------------------------+ 1 | |
e9174d1e | 997 | /// | | |
94b46f34 | 998 | /// +------------------------------------------+ 0 |
e9174d1e SL |
999 | /// |
1000 | /// In this type, there are two binders (the outer fn and the inner | |
1001 | /// fn). We need to be able to determine, for any given region, which | |
1002 | /// fn type it is bound by, the inner or the outer one. There are | |
1003 | /// various ways you can do this, but a De Bruijn index is one of the | |
1004 | /// more convenient and has some nice properties. The basic idea is to | |
1005 | /// count the number of binders, inside out. Some examples should help | |
1006 | /// clarify what I mean. | |
1007 | /// | |
1008 | /// Let's start with the reference type `&'b isize` that is the first | |
1009 | /// argument to the inner function. This region `'b` is assigned a De | |
94b46f34 | 1010 | /// Bruijn index of 0, meaning "the innermost binder" (in this case, a |
e9174d1e | 1011 | /// fn). The region `'a` that appears in the second argument type (`&'a |
94b46f34 | 1012 | /// isize`) would then be assigned a De Bruijn index of 1, meaning "the |
e9174d1e SL |
1013 | /// second-innermost binder". (These indices are written on the arrays |
1014 | /// in the diagram). | |
1015 | /// | |
1016 | /// What is interesting is that De Bruijn index attached to a particular | |
1017 | /// variable will vary depending on where it appears. For example, | |
1018 | /// the final type `&'a char` also refers to the region `'a` declared on | |
1019 | /// the outermost fn. But this time, this reference is not nested within | |
1020 | /// any other binders (i.e., it is not an argument to the inner fn, but | |
1021 | /// rather the outer one). Therefore, in this case, it is assigned a | |
94b46f34 | 1022 | /// De Bruijn index of 0, because the innermost binder in that location |
e9174d1e SL |
1023 | /// is the outer fn. |
1024 | /// | |
1025 | /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index | |
94b46f34 XL |
1026 | newtype_index!(DebruijnIndex |
1027 | { | |
1028 | DEBUG_FORMAT = "DebruijnIndex({})", | |
1029 | const INNERMOST = 0, | |
1030 | }); | |
e9174d1e | 1031 | |
7cac9316 XL |
1032 | pub type Region<'tcx> = &'tcx RegionKind; |
1033 | ||
e9174d1e SL |
1034 | /// Representation of regions. |
1035 | /// | |
1036 | /// Unlike types, most region variants are "fictitious", not concrete, | |
1037 | /// regions. Among these, `ReStatic`, `ReEmpty` and `ReScope` are the only | |
1038 | /// ones representing concrete regions. | |
1039 | /// | |
1040 | /// ## Bound Regions | |
1041 | /// | |
1042 | /// These are regions that are stored behind a binder and must be substituted | |
1043 | /// with some concrete region before being used. There are 2 kind of | |
476ff2be | 1044 | /// bound regions: early-bound, which are bound in an item's Generics, |
e9174d1e SL |
1045 | /// and are substituted by a Substs, and late-bound, which are part of |
1046 | /// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by | |
1047 | /// the likes of `liberate_late_bound_regions`. The distinction exists | |
1048 | /// because higher-ranked lifetimes aren't supported in all places. See [1][2]. | |
1049 | /// | |
1050 | /// Unlike TyParam-s, bound regions are not supposed to exist "in the wild" | |
1051 | /// outside their binder, e.g. in types passed to type inference, and | |
1052 | /// should first be substituted (by skolemized regions, free regions, | |
1053 | /// or region variables). | |
1054 | /// | |
1055 | /// ## Skolemized and Free Regions | |
1056 | /// | |
1057 | /// One often wants to work with bound regions without knowing their precise | |
1058 | /// identity. For example, when checking a function, the lifetime of a borrow | |
1059 | /// can end up being assigned to some region parameter. In these cases, | |
1060 | /// it must be ensured that bounds on the region can't be accidentally | |
1061 | /// assumed without being checked. | |
1062 | /// | |
1063 | /// The process of doing that is called "skolemization". The bound regions | |
1064 | /// are replaced by skolemized markers, which don't satisfy any relation | |
3b2f2976 | 1065 | /// not explicitly provided. |
e9174d1e SL |
1066 | /// |
1067 | /// There are 2 kinds of skolemized regions in rustc: `ReFree` and | |
1068 | /// `ReSkolemized`. When checking an item's body, `ReFree` is supposed | |
1069 | /// to be used. These also support explicit bounds: both the internally-stored | |
1070 | /// *scope*, which the region is assumed to outlive, as well as other | |
1071 | /// relations stored in the `FreeRegionMap`. Note that these relations | |
a7813a04 | 1072 | /// aren't checked when you `make_subregion` (or `eq_types`), only by |
e9174d1e SL |
1073 | /// `resolve_regions_and_report_errors`. |
1074 | /// | |
1075 | /// When working with higher-ranked types, some region relations aren't | |
1076 | /// yet known, so you can't just call `resolve_regions_and_report_errors`. | |
1077 | /// `ReSkolemized` is designed for this purpose. In these contexts, | |
1078 | /// there's also the risk that some inference variable laying around will | |
1079 | /// get unified with your skolemized region: if you want to check whether | |
1080 | /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a` | |
1081 | /// with a skolemized region `'%a`, the variable `'_` would just be | |
1082 | /// instantiated to the skolemized region `'%a`, which is wrong because | |
1083 | /// the inference variable is supposed to satisfy the relation | |
1084 | /// *for every value of the skolemized region*. To ensure that doesn't | |
1085 | /// happen, you can use `leak_check`. This is more clearly explained | |
0531ce1d | 1086 | /// by the [rustc guide]. |
e9174d1e | 1087 | /// |
ff7c6d11 XL |
1088 | /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ |
1089 | /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ | |
0531ce1d | 1090 | /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html |
abe05a73 | 1091 | #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)] |
7cac9316 | 1092 | pub enum RegionKind { |
e9174d1e SL |
1093 | // Region bound in a type or fn declaration which will be |
1094 | // substituted 'early' -- that is, at the same time when type | |
1095 | // parameters are substituted. | |
1096 | ReEarlyBound(EarlyBoundRegion), | |
1097 | ||
1098 | // Region bound in a function scope, which will be substituted when the | |
1099 | // function is called. | |
1100 | ReLateBound(DebruijnIndex, BoundRegion), | |
1101 | ||
1102 | /// When checking a function body, the types of all arguments and so forth | |
1103 | /// that refer to bound region parameters are modified to refer to free | |
1104 | /// region parameters. | |
1105 | ReFree(FreeRegion), | |
1106 | ||
ea8adc8c | 1107 | /// A concrete region naming some statically determined scope |
e9174d1e SL |
1108 | /// (e.g. an expression or sequence of statements) within the |
1109 | /// current function. | |
ea8adc8c | 1110 | ReScope(region::Scope), |
e9174d1e SL |
1111 | |
1112 | /// Static data that has an "infinite" lifetime. Top in the region lattice. | |
1113 | ReStatic, | |
1114 | ||
1115 | /// A region variable. Should not exist after typeck. | |
1116 | ReVar(RegionVid), | |
1117 | ||
1118 | /// A skolemized region - basically the higher-ranked version of ReFree. | |
1119 | /// Should not exist after typeck. | |
83c7162d | 1120 | ReSkolemized(ty::UniverseIndex, BoundRegion), |
e9174d1e SL |
1121 | |
1122 | /// Empty lifetime is for data that is never accessed. | |
1123 | /// Bottom in the region lattice. We treat ReEmpty somewhat | |
1124 | /// specially; at least right now, we do not generate instances of | |
1125 | /// it during the GLB computations, but rather | |
1126 | /// generate an error instead. This is to improve error messages. | |
1127 | /// The only way to get an instance of ReEmpty is to have a region | |
1128 | /// variable with no constraints. | |
1129 | ReEmpty, | |
3157f602 | 1130 | |
94b46f34 | 1131 | /// Erased region, used by trait selection, in MIR and during codegen. |
3157f602 | 1132 | ReErased, |
ff7c6d11 XL |
1133 | |
1134 | /// These are regions bound in the "defining type" for a | |
1135 | /// closure. They are used ONLY as part of the | |
1136 | /// `ClosureRegionRequirements` that are produced by MIR borrowck. | |
1137 | /// See `ClosureRegionRequirements` for more details. | |
1138 | ReClosureBound(RegionVid), | |
0531ce1d XL |
1139 | |
1140 | /// Canonicalized region, used only when preparing a trait query. | |
1141 | ReCanonical(CanonicalVar), | |
e9174d1e SL |
1142 | } |
1143 | ||
7cac9316 | 1144 | impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {} |
9e0c209e | 1145 | |
abe05a73 | 1146 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, PartialOrd, Ord)] |
e9174d1e | 1147 | pub struct EarlyBoundRegion { |
7cac9316 | 1148 | pub def_id: DefId, |
e9174d1e | 1149 | pub index: u32, |
83c7162d | 1150 | pub name: InternedString, |
e9174d1e SL |
1151 | } |
1152 | ||
94b46f34 | 1153 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 1154 | pub struct TyVid { |
3157f602 | 1155 | pub index: u32, |
e9174d1e SL |
1156 | } |
1157 | ||
94b46f34 | 1158 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 1159 | pub struct IntVid { |
cc61c64b | 1160 | pub index: u32, |
e9174d1e SL |
1161 | } |
1162 | ||
94b46f34 | 1163 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] |
e9174d1e | 1164 | pub struct FloatVid { |
cc61c64b | 1165 | pub index: u32, |
e9174d1e SL |
1166 | } |
1167 | ||
ff7c6d11 XL |
1168 | newtype_index!(RegionVid |
1169 | { | |
1170 | pub idx | |
1171 | DEBUG_FORMAT = custom, | |
1172 | }); | |
abe05a73 | 1173 | |
94b46f34 XL |
1174 | impl Atom for RegionVid { |
1175 | fn index(self) -> usize { | |
1176 | Idx::index(self) | |
1177 | } | |
1178 | } | |
1179 | ||
1180 | impl From<usize> for RegionVid { | |
1181 | fn from(i: usize) -> RegionVid { | |
1182 | RegionVid::new(i) | |
1183 | } | |
1184 | } | |
1185 | ||
1186 | impl From<RegionVid> for usize { | |
1187 | fn from(vid: RegionVid) -> usize { | |
1188 | Idx::index(vid) | |
1189 | } | |
1190 | } | |
1191 | ||
1192 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] | |
e9174d1e SL |
1193 | pub enum InferTy { |
1194 | TyVar(TyVid), | |
1195 | IntVar(IntVid), | |
1196 | FloatVar(FloatVid), | |
1197 | ||
1198 | /// A `FreshTy` is one that is generated as a replacement for an | |
1199 | /// unbound type variable. This is convenient for caching etc. See | |
54a0048b | 1200 | /// `infer::freshen` for more details. |
e9174d1e SL |
1201 | FreshTy(u32), |
1202 | FreshIntTy(u32), | |
cc61c64b | 1203 | FreshFloatTy(u32), |
0531ce1d XL |
1204 | |
1205 | /// Canonicalized type variable, used only when preparing a trait query. | |
1206 | CanonicalTy(CanonicalVar), | |
e9174d1e SL |
1207 | } |
1208 | ||
0531ce1d XL |
1209 | newtype_index!(CanonicalVar); |
1210 | ||
9e0c209e | 1211 | /// A `ProjectionPredicate` for an `ExistentialTraitRef`. |
94b46f34 | 1212 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] |
9e0c209e | 1213 | pub struct ExistentialProjection<'tcx> { |
041b39d2 XL |
1214 | pub item_def_id: DefId, |
1215 | pub substs: &'tcx Substs<'tcx>, | |
cc61c64b | 1216 | pub ty: Ty<'tcx>, |
e9174d1e SL |
1217 | } |
1218 | ||
9e0c209e SL |
1219 | pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>; |
1220 | ||
476ff2be | 1221 | impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { |
041b39d2 XL |
1222 | /// Extracts the underlying existential trait reference from this projection. |
1223 | /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`, | |
1224 | /// then this function would return a `exists T. T: Iterator` existential trait | |
1225 | /// reference. | |
1226 | pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> { | |
1227 | let def_id = tcx.associated_item(self.item_def_id).container.id(); | |
1228 | ty::ExistentialTraitRef{ | |
3b2f2976 | 1229 | def_id, |
041b39d2 XL |
1230 | substs: self.substs, |
1231 | } | |
9e0c209e SL |
1232 | } |
1233 | ||
1234 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, | |
1235 | self_ty: Ty<'tcx>) | |
476ff2be | 1236 | -> ty::ProjectionPredicate<'tcx> |
9e0c209e SL |
1237 | { |
1238 | // otherwise the escaping regions would be captured by the binders | |
1239 | assert!(!self_ty.has_escaping_regions()); | |
1240 | ||
476ff2be | 1241 | ty::ProjectionPredicate { |
041b39d2 XL |
1242 | projection_ty: ty::ProjectionTy { |
1243 | item_def_id: self.item_def_id, | |
94b46f34 | 1244 | substs: tcx.mk_substs_trait(self_ty, self.substs), |
041b39d2 | 1245 | }, |
cc61c64b | 1246 | ty: self.ty, |
476ff2be | 1247 | } |
e9174d1e SL |
1248 | } |
1249 | } | |
1250 | ||
476ff2be | 1251 | impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { |
476ff2be SL |
1252 | pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) |
1253 | -> ty::PolyProjectionPredicate<'tcx> { | |
1254 | self.map_bound(|p| p.with_self_ty(tcx, self_ty)) | |
e9174d1e | 1255 | } |
83c7162d XL |
1256 | |
1257 | pub fn item_def_id(&self) -> DefId { | |
1258 | return self.skip_binder().item_def_id; | |
1259 | } | |
e9174d1e SL |
1260 | } |
1261 | ||
1262 | impl DebruijnIndex { | |
94b46f34 XL |
1263 | /// Returns the resulting index when this value is moved into |
1264 | /// `amount` number of new binders. So e.g. if you had | |
1265 | /// | |
1266 | /// for<'a> fn(&'a x) | |
1267 | /// | |
1268 | /// and you wanted to change to | |
1269 | /// | |
1270 | /// for<'a> fn(for<'b> fn(&'a x)) | |
1271 | /// | |
1272 | /// you would need to shift the index for `'a` into 1 new binder. | |
1273 | #[must_use] | |
1274 | pub const fn shifted_in(self, amount: u32) -> DebruijnIndex { | |
1275 | DebruijnIndex(self.0 + amount) | |
1276 | } | |
1277 | ||
1278 | /// Update this index in place by shifting it "in" through | |
1279 | /// `amount` number of binders. | |
1280 | pub fn shift_in(&mut self, amount: u32) { | |
1281 | *self = self.shifted_in(amount); | |
e9174d1e SL |
1282 | } |
1283 | ||
94b46f34 XL |
1284 | /// Returns the resulting index when this value is moved out from |
1285 | /// `amount` number of new binders. | |
1286 | #[must_use] | |
1287 | pub const fn shifted_out(self, amount: u32) -> DebruijnIndex { | |
1288 | DebruijnIndex(self.0 - amount) | |
1289 | } | |
1290 | ||
1291 | /// Update in place by shifting out from `amount` binders. | |
1292 | pub fn shift_out(&mut self, amount: u32) { | |
1293 | *self = self.shifted_out(amount); | |
1294 | } | |
1295 | ||
1296 | /// Adjusts any Debruijn Indices so as to make `to_binder` the | |
1297 | /// innermost binder. That is, if we have something bound at `to_binder`, | |
1298 | /// it will now be bound at INNERMOST. This is an appropriate thing to do | |
1299 | /// when moving a region out from inside binders: | |
1300 | /// | |
1301 | /// ``` | |
1302 | /// for<'a> fn(for<'b> for<'c> fn(&'a u32), _) | |
1303 | /// // Binder: D3 D2 D1 ^^ | |
1304 | /// ``` | |
1305 | /// | |
1306 | /// Here, the region `'a` would have the debruijn index D3, | |
1307 | /// because it is the bound 3 binders out. However, if we wanted | |
1308 | /// to refer to that region `'a` in the second argument (the `_`), | |
1309 | /// those two binders would not be in scope. In that case, we | |
1310 | /// might invoke `shift_out_to_binder(D3)`. This would adjust the | |
1311 | /// debruijn index of `'a` to D1 (the innermost binder). | |
1312 | /// | |
1313 | /// If we invoke `shift_out_to_binder` and the region is in fact | |
1314 | /// bound by one of the binders we are shifting out of, that is an | |
1315 | /// error (and should fail an assertion failure). | |
1316 | pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self { | |
1317 | self.shifted_out((to_binder.0 - INNERMOST.0) as u32) | |
e9174d1e SL |
1318 | } |
1319 | } | |
1320 | ||
94b46f34 XL |
1321 | impl_stable_hash_for!(tuple_struct DebruijnIndex { index }); |
1322 | ||
7cac9316 XL |
1323 | /// Region utilities |
1324 | impl RegionKind { | |
1325 | pub fn is_late_bound(&self) -> bool { | |
e9174d1e | 1326 | match *self { |
e9174d1e | 1327 | ty::ReLateBound(..) => true, |
cc61c64b | 1328 | _ => false, |
e9174d1e SL |
1329 | } |
1330 | } | |
1331 | ||
94b46f34 | 1332 | pub fn bound_at_or_above_binder(&self, index: DebruijnIndex) -> bool { |
e9174d1e | 1333 | match *self { |
94b46f34 | 1334 | ty::ReLateBound(debruijn, _) => debruijn >= index, |
e9174d1e SL |
1335 | _ => false, |
1336 | } | |
1337 | } | |
1338 | ||
94b46f34 XL |
1339 | /// Adjusts any Debruijn Indices so as to make `to_binder` the |
1340 | /// innermost binder. That is, if we have something bound at `to_binder`, | |
1341 | /// it will now be bound at INNERMOST. This is an appropriate thing to do | |
1342 | /// when moving a region out from inside binders: | |
1343 | /// | |
1344 | /// ``` | |
1345 | /// for<'a> fn(for<'b> for<'c> fn(&'a u32), _) | |
1346 | /// // Binder: D3 D2 D1 ^^ | |
1347 | /// ``` | |
1348 | /// | |
1349 | /// Here, the region `'a` would have the debruijn index D3, | |
1350 | /// because it is the bound 3 binders out. However, if we wanted | |
1351 | /// to refer to that region `'a` in the second argument (the `_`), | |
1352 | /// those two binders would not be in scope. In that case, we | |
1353 | /// might invoke `shift_out_to_binder(D3)`. This would adjust the | |
1354 | /// debruijn index of `'a` to D1 (the innermost binder). | |
1355 | /// | |
1356 | /// If we invoke `shift_out_to_binder` and the region is in fact | |
1357 | /// bound by one of the binders we are shifting out of, that is an | |
1358 | /// error (and should fail an assertion failure). | |
1359 | pub fn shifted_out_to_binder(&self, to_binder: ty::DebruijnIndex) -> RegionKind { | |
e9174d1e | 1360 | match *self { |
94b46f34 XL |
1361 | ty::ReLateBound(debruijn, r) => ty::ReLateBound( |
1362 | debruijn.shifted_out_to_binder(to_binder), | |
1363 | r, | |
1364 | ), | |
e9174d1e SL |
1365 | r => r |
1366 | } | |
1367 | } | |
c30ab7b3 | 1368 | |
83c7162d XL |
1369 | pub fn keep_in_local_tcx(&self) -> bool { |
1370 | if let ty::ReVar(..) = self { | |
1371 | true | |
1372 | } else { | |
1373 | false | |
1374 | } | |
1375 | } | |
1376 | ||
c30ab7b3 SL |
1377 | pub fn type_flags(&self) -> TypeFlags { |
1378 | let mut flags = TypeFlags::empty(); | |
1379 | ||
83c7162d XL |
1380 | if self.keep_in_local_tcx() { |
1381 | flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; | |
1382 | } | |
1383 | ||
c30ab7b3 SL |
1384 | match *self { |
1385 | ty::ReVar(..) => { | |
ff7c6d11 | 1386 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
c30ab7b3 | 1387 | flags = flags | TypeFlags::HAS_RE_INFER; |
c30ab7b3 SL |
1388 | } |
1389 | ty::ReSkolemized(..) => { | |
ff7c6d11 | 1390 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
c30ab7b3 | 1391 | flags = flags | TypeFlags::HAS_RE_SKOL; |
c30ab7b3 | 1392 | } |
94b46f34 XL |
1393 | ty::ReLateBound(..) => { |
1394 | flags = flags | TypeFlags::HAS_RE_LATE_BOUND; | |
1395 | } | |
ff7c6d11 XL |
1396 | ty::ReEarlyBound(..) => { |
1397 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1398 | flags = flags | TypeFlags::HAS_RE_EARLY_BOUND; | |
1399 | } | |
1400 | ty::ReEmpty | | |
1401 | ty::ReStatic | | |
1402 | ty::ReFree { .. } | | |
1403 | ty::ReScope { .. } => { | |
1404 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1405 | } | |
1406 | ty::ReErased => { | |
1407 | } | |
0531ce1d XL |
1408 | ty::ReCanonical(..) => { |
1409 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1410 | flags = flags | TypeFlags::HAS_CANONICAL_VARS; | |
1411 | } | |
ff7c6d11 XL |
1412 | ty::ReClosureBound(..) => { |
1413 | flags = flags | TypeFlags::HAS_FREE_REGIONS; | |
1414 | } | |
c30ab7b3 SL |
1415 | } |
1416 | ||
1417 | match *self { | |
94b46f34 XL |
1418 | ty::ReStatic | ty::ReEmpty | ty::ReErased | ty::ReLateBound(..) => (), |
1419 | _ => flags = flags | TypeFlags::HAS_FREE_LOCAL_NAMES, | |
c30ab7b3 SL |
1420 | } |
1421 | ||
1422 | debug!("type_flags({:?}) = {:?}", self, flags); | |
1423 | ||
1424 | flags | |
1425 | } | |
abe05a73 XL |
1426 | |
1427 | /// Given an early-bound or free region, returns the def-id where it was bound. | |
1428 | /// For example, consider the regions in this snippet of code: | |
1429 | /// | |
1430 | /// ``` | |
1431 | /// impl<'a> Foo { | |
1432 | /// ^^ -- early bound, declared on an impl | |
1433 | /// | |
1434 | /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c | |
1435 | /// ^^ ^^ ^ anonymous, late-bound | |
1436 | /// | early-bound, appears in where-clauses | |
1437 | /// late-bound, appears only in fn args | |
1438 | /// {..} | |
1439 | /// } | |
1440 | /// ``` | |
1441 | /// | |
1442 | /// Here, `free_region_binding_scope('a)` would return the def-id | |
1443 | /// of the impl, and for all the other highlighted regions, it | |
1444 | /// would return the def-id of the function. In other cases (not shown), this | |
1445 | /// function might return the def-id of a closure. | |
1446 | pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_, '_, '_>) -> DefId { | |
1447 | match self { | |
1448 | ty::ReEarlyBound(br) => { | |
1449 | tcx.parent_def_id(br.def_id).unwrap() | |
1450 | } | |
1451 | ty::ReFree(fr) => fr.scope, | |
1452 | _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), | |
1453 | } | |
1454 | } | |
e9174d1e SL |
1455 | } |
1456 | ||
7cac9316 | 1457 | /// Type utilities |
a7813a04 | 1458 | impl<'a, 'gcx, 'tcx> TyS<'tcx> { |
e9174d1e SL |
1459 | pub fn is_nil(&self) -> bool { |
1460 | match self.sty { | |
0531ce1d | 1461 | TyTuple(ref tys) => tys.is_empty(), |
cc61c64b | 1462 | _ => false, |
e9174d1e SL |
1463 | } |
1464 | } | |
1465 | ||
5bcae85e SL |
1466 | pub fn is_never(&self) -> bool { |
1467 | match self.sty { | |
1468 | TyNever => true, | |
1469 | _ => false, | |
1470 | } | |
1471 | } | |
1472 | ||
0531ce1d | 1473 | pub fn is_primitive(&self) -> bool { |
8bb4bdeb | 1474 | match self.sty { |
0531ce1d | 1475 | TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true, |
8bb4bdeb XL |
1476 | _ => false, |
1477 | } | |
1478 | } | |
1479 | ||
0531ce1d | 1480 | pub fn is_ty_var(&self) -> bool { |
9cc50fc6 | 1481 | match self.sty { |
0531ce1d | 1482 | TyInfer(TyVar(_)) => true, |
9cc50fc6 SL |
1483 | _ => false, |
1484 | } | |
1485 | } | |
1486 | ||
0531ce1d | 1487 | pub fn is_ty_infer(&self) -> bool { |
e9174d1e | 1488 | match self.sty { |
0531ce1d | 1489 | TyInfer(_) => true, |
cc61c64b | 1490 | _ => false, |
e9174d1e SL |
1491 | } |
1492 | } | |
1493 | ||
b039eaaf | 1494 | pub fn is_phantom_data(&self) -> bool { |
9e0c209e | 1495 | if let TyAdt(def, _) = self.sty { |
b039eaaf SL |
1496 | def.is_phantom_data() |
1497 | } else { | |
1498 | false | |
1499 | } | |
1500 | } | |
1501 | ||
e9174d1e SL |
1502 | pub fn is_bool(&self) -> bool { self.sty == TyBool } |
1503 | ||
9e0c209e | 1504 | pub fn is_param(&self, index: u32) -> bool { |
e9174d1e | 1505 | match self.sty { |
9e0c209e | 1506 | ty::TyParam(ref data) => data.idx == index, |
e9174d1e SL |
1507 | _ => false, |
1508 | } | |
1509 | } | |
1510 | ||
1511 | pub fn is_self(&self) -> bool { | |
1512 | match self.sty { | |
9e0c209e | 1513 | TyParam(ref p) => p.is_self(), |
cc61c64b | 1514 | _ => false, |
e9174d1e SL |
1515 | } |
1516 | } | |
1517 | ||
54a0048b | 1518 | pub fn is_slice(&self) -> bool { |
e9174d1e | 1519 | match self.sty { |
94b46f34 | 1520 | TyRawPtr(TypeAndMut { ty, .. }) | TyRef(_, ty, _) => match ty.sty { |
e9174d1e SL |
1521 | TySlice(_) | TyStr => true, |
1522 | _ => false, | |
1523 | }, | |
1524 | _ => false | |
1525 | } | |
1526 | } | |
1527 | ||
e9174d1e SL |
1528 | #[inline] |
1529 | pub fn is_simd(&self) -> bool { | |
1530 | match self.sty { | |
cc61c64b XL |
1531 | TyAdt(def, _) => def.repr.simd(), |
1532 | _ => false, | |
e9174d1e SL |
1533 | } |
1534 | } | |
1535 | ||
a7813a04 | 1536 | pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { |
e9174d1e SL |
1537 | match self.sty { |
1538 | TyArray(ty, _) | TySlice(ty) => ty, | |
a7813a04 | 1539 | TyStr => tcx.mk_mach_uint(ast::UintTy::U8), |
54a0048b | 1540 | _ => bug!("sequence_element_type called on non-sequence value: {}", self), |
e9174d1e SL |
1541 | } |
1542 | } | |
1543 | ||
a7813a04 | 1544 | pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { |
e9174d1e | 1545 | match self.sty { |
9e0c209e | 1546 | TyAdt(def, substs) => { |
2c00a5a8 | 1547 | def.non_enum_variant().fields[0].ty(tcx, substs) |
e9174d1e | 1548 | } |
54a0048b | 1549 | _ => bug!("simd_type called on invalid type") |
e9174d1e SL |
1550 | } |
1551 | } | |
1552 | ||
a7813a04 | 1553 | pub fn simd_size(&self, _cx: TyCtxt) -> usize { |
e9174d1e | 1554 | match self.sty { |
2c00a5a8 | 1555 | TyAdt(def, _) => def.non_enum_variant().fields.len(), |
54a0048b | 1556 | _ => bug!("simd_size called on invalid type") |
e9174d1e SL |
1557 | } |
1558 | } | |
1559 | ||
1560 | pub fn is_region_ptr(&self) -> bool { | |
1561 | match self.sty { | |
1562 | TyRef(..) => true, | |
cc61c64b | 1563 | _ => false, |
e9174d1e SL |
1564 | } |
1565 | } | |
1566 | ||
32a655c1 SL |
1567 | pub fn is_mutable_pointer(&self) -> bool { |
1568 | match self.sty { | |
94b46f34 XL |
1569 | TyRawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) | |
1570 | TyRef(_, _, hir::Mutability::MutMutable) => true, | |
32a655c1 SL |
1571 | _ => false |
1572 | } | |
1573 | } | |
1574 | ||
e9174d1e SL |
1575 | pub fn is_unsafe_ptr(&self) -> bool { |
1576 | match self.sty { | |
1577 | TyRawPtr(_) => return true, | |
cc61c64b | 1578 | _ => return false, |
e9174d1e SL |
1579 | } |
1580 | } | |
1581 | ||
32a655c1 | 1582 | pub fn is_box(&self) -> bool { |
e9174d1e | 1583 | match self.sty { |
32a655c1 SL |
1584 | TyAdt(def, _) => def.is_box(), |
1585 | _ => false, | |
1586 | } | |
1587 | } | |
1588 | ||
7cac9316 | 1589 | /// panics if called on any type other than `Box<T>` |
32a655c1 SL |
1590 | pub fn boxed_ty(&self) -> Ty<'tcx> { |
1591 | match self.sty { | |
1592 | TyAdt(def, substs) if def.is_box() => substs.type_at(0), | |
1593 | _ => bug!("`boxed_ty` is called on non-box type {:?}", self), | |
e9174d1e SL |
1594 | } |
1595 | } | |
1596 | ||
7cac9316 XL |
1597 | /// A scalar type is one that denotes an atomic datum, with no sub-components. |
1598 | /// (A TyRawPtr is scalar because it represents a non-managed pointer, so its | |
1599 | /// contents are abstract to rustc.) | |
e9174d1e SL |
1600 | pub fn is_scalar(&self) -> bool { |
1601 | match self.sty { | |
1602 | TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | | |
1603 | TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) | | |
54a0048b | 1604 | TyFnDef(..) | TyFnPtr(_) | TyRawPtr(_) => true, |
e9174d1e SL |
1605 | _ => false |
1606 | } | |
1607 | } | |
1608 | ||
1609 | /// Returns true if this type is a floating point type and false otherwise. | |
1610 | pub fn is_floating_point(&self) -> bool { | |
1611 | match self.sty { | |
1612 | TyFloat(_) | | |
1613 | TyInfer(FloatVar(_)) => true, | |
1614 | _ => false, | |
1615 | } | |
1616 | } | |
1617 | ||
1618 | pub fn is_trait(&self) -> bool { | |
1619 | match self.sty { | |
476ff2be | 1620 | TyDynamic(..) => true, |
cc61c64b | 1621 | _ => false, |
e9174d1e SL |
1622 | } |
1623 | } | |
1624 | ||
ff7c6d11 XL |
1625 | pub fn is_enum(&self) -> bool { |
1626 | match self.sty { | |
1627 | TyAdt(adt_def, _) => { | |
1628 | adt_def.is_enum() | |
1629 | } | |
1630 | _ => false, | |
1631 | } | |
1632 | } | |
1633 | ||
7cac9316 XL |
1634 | pub fn is_closure(&self) -> bool { |
1635 | match self.sty { | |
1636 | TyClosure(..) => true, | |
1637 | _ => false, | |
1638 | } | |
1639 | } | |
1640 | ||
ff7c6d11 XL |
1641 | pub fn is_generator(&self) -> bool { |
1642 | match self.sty { | |
1643 | TyGenerator(..) => true, | |
1644 | _ => false, | |
1645 | } | |
1646 | } | |
1647 | ||
e9174d1e SL |
1648 | pub fn is_integral(&self) -> bool { |
1649 | match self.sty { | |
1650 | TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, | |
1651 | _ => false | |
1652 | } | |
1653 | } | |
1654 | ||
ff7c6d11 XL |
1655 | pub fn is_fresh_ty(&self) -> bool { |
1656 | match self.sty { | |
1657 | TyInfer(FreshTy(_)) => true, | |
1658 | _ => false, | |
1659 | } | |
1660 | } | |
1661 | ||
e9174d1e SL |
1662 | pub fn is_fresh(&self) -> bool { |
1663 | match self.sty { | |
1664 | TyInfer(FreshTy(_)) => true, | |
1665 | TyInfer(FreshIntTy(_)) => true, | |
1666 | TyInfer(FreshFloatTy(_)) => true, | |
cc61c64b | 1667 | _ => false, |
e9174d1e SL |
1668 | } |
1669 | } | |
1670 | ||
e9174d1e SL |
1671 | pub fn is_char(&self) -> bool { |
1672 | match self.sty { | |
1673 | TyChar => true, | |
cc61c64b | 1674 | _ => false, |
e9174d1e SL |
1675 | } |
1676 | } | |
1677 | ||
e9174d1e SL |
1678 | pub fn is_fp(&self) -> bool { |
1679 | match self.sty { | |
1680 | TyInfer(FloatVar(_)) | TyFloat(_) => true, | |
1681 | _ => false | |
1682 | } | |
1683 | } | |
1684 | ||
1685 | pub fn is_numeric(&self) -> bool { | |
1686 | self.is_integral() || self.is_fp() | |
1687 | } | |
1688 | ||
1689 | pub fn is_signed(&self) -> bool { | |
1690 | match self.sty { | |
1691 | TyInt(_) => true, | |
cc61c64b | 1692 | _ => false, |
e9174d1e SL |
1693 | } |
1694 | } | |
1695 | ||
1696 | pub fn is_machine(&self) -> bool { | |
1697 | match self.sty { | |
2c00a5a8 | 1698 | TyInt(ast::IntTy::Isize) | TyUint(ast::UintTy::Usize) => false, |
e9174d1e | 1699 | TyInt(..) | TyUint(..) | TyFloat(..) => true, |
cc61c64b | 1700 | _ => false, |
e9174d1e SL |
1701 | } |
1702 | } | |
1703 | ||
54a0048b SL |
1704 | pub fn has_concrete_skeleton(&self) -> bool { |
1705 | match self.sty { | |
1706 | TyParam(_) | TyInfer(_) | TyError => false, | |
1707 | _ => true, | |
1708 | } | |
1709 | } | |
1710 | ||
7cac9316 XL |
1711 | /// Returns the type and mutability of *ty. |
1712 | /// | |
1713 | /// The parameter `explicit` indicates if this is an *explicit* dereference. | |
1714 | /// Some types---notably unsafe ptrs---can only be dereferenced explicitly. | |
2c00a5a8 | 1715 | pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> { |
e9174d1e | 1716 | match self.sty { |
32a655c1 | 1717 | TyAdt(def, _) if def.is_box() => { |
e9174d1e | 1718 | Some(TypeAndMut { |
32a655c1 | 1719 | ty: self.boxed_ty(), |
2c00a5a8 | 1720 | mutbl: hir::MutImmutable, |
e9174d1e SL |
1721 | }) |
1722 | }, | |
94b46f34 | 1723 | TyRef(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }), |
e9174d1e | 1724 | TyRawPtr(mt) if explicit => Some(mt), |
cc61c64b | 1725 | _ => None, |
e9174d1e SL |
1726 | } |
1727 | } | |
1728 | ||
83c7162d | 1729 | /// Returns the type of `ty[i]`. |
e9174d1e SL |
1730 | pub fn builtin_index(&self) -> Option<Ty<'tcx>> { |
1731 | match self.sty { | |
1732 | TyArray(ty, _) | TySlice(ty) => Some(ty), | |
cc61c64b | 1733 | _ => None, |
e9174d1e SL |
1734 | } |
1735 | } | |
1736 | ||
041b39d2 | 1737 | pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> { |
e9174d1e | 1738 | match self.sty { |
041b39d2 XL |
1739 | TyFnDef(def_id, substs) => { |
1740 | tcx.fn_sig(def_id).subst(tcx, substs) | |
1741 | } | |
1742 | TyFnPtr(f) => f, | |
54a0048b | 1743 | _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) |
e9174d1e SL |
1744 | } |
1745 | } | |
1746 | ||
e9174d1e SL |
1747 | pub fn is_fn(&self) -> bool { |
1748 | match self.sty { | |
54a0048b | 1749 | TyFnDef(..) | TyFnPtr(_) => true, |
cc61c64b | 1750 | _ => false, |
e9174d1e SL |
1751 | } |
1752 | } | |
1753 | ||
1754 | pub fn ty_to_def_id(&self) -> Option<DefId> { | |
1755 | match self.sty { | |
476ff2be | 1756 | TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()), |
9e0c209e | 1757 | TyAdt(def, _) => Some(def.did), |
abe05a73 | 1758 | TyForeign(did) => Some(did), |
e9174d1e | 1759 | TyClosure(id, _) => Some(id), |
ff7c6d11 | 1760 | TyFnDef(id, _) => Some(id), |
cc61c64b | 1761 | _ => None, |
e9174d1e SL |
1762 | } |
1763 | } | |
1764 | ||
476ff2be | 1765 | pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { |
e9174d1e | 1766 | match self.sty { |
9e0c209e | 1767 | TyAdt(adt, _) => Some(adt), |
cc61c64b | 1768 | _ => None, |
e9174d1e SL |
1769 | } |
1770 | } | |
1771 | ||
1772 | /// Returns the regions directly referenced from this type (but | |
1773 | /// not types reachable from this type via `walk_tys`). This | |
1774 | /// ignores late-bound regions binders. | |
7cac9316 | 1775 | pub fn regions(&self) -> Vec<ty::Region<'tcx>> { |
e9174d1e | 1776 | match self.sty { |
94b46f34 | 1777 | TyRef(region, _, _) => { |
9e0c209e | 1778 | vec![region] |
e9174d1e | 1779 | } |
476ff2be SL |
1780 | TyDynamic(ref obj, region) => { |
1781 | let mut v = vec![region]; | |
1782 | if let Some(p) = obj.principal() { | |
1783 | v.extend(p.skip_binder().substs.regions()); | |
1784 | } | |
e9174d1e SL |
1785 | v |
1786 | } | |
9e0c209e SL |
1787 | TyAdt(_, substs) | TyAnon(_, substs) => { |
1788 | substs.regions().collect() | |
e9174d1e | 1789 | } |
94b46f34 XL |
1790 | TyClosure(_, ClosureSubsts { ref substs }) | |
1791 | TyGenerator(_, GeneratorSubsts { ref substs }, _) => { | |
1792 | substs.regions().collect() | |
e9174d1e SL |
1793 | } |
1794 | TyProjection(ref data) => { | |
041b39d2 | 1795 | data.substs.regions().collect() |
e9174d1e | 1796 | } |
54a0048b SL |
1797 | TyFnDef(..) | |
1798 | TyFnPtr(_) | | |
2c00a5a8 | 1799 | TyGeneratorWitness(..) | |
e9174d1e SL |
1800 | TyBool | |
1801 | TyChar | | |
1802 | TyInt(_) | | |
1803 | TyUint(_) | | |
1804 | TyFloat(_) | | |
e9174d1e | 1805 | TyStr | |
9e0c209e | 1806 | TyArray(..) | |
e9174d1e SL |
1807 | TySlice(_) | |
1808 | TyRawPtr(_) | | |
5bcae85e | 1809 | TyNever | |
8bb4bdeb | 1810 | TyTuple(..) | |
abe05a73 | 1811 | TyForeign(..) | |
e9174d1e SL |
1812 | TyParam(_) | |
1813 | TyInfer(_) | | |
1814 | TyError => { | |
1815 | vec![] | |
1816 | } | |
1817 | } | |
1818 | } | |
ff7c6d11 XL |
1819 | |
1820 | /// When we create a closure, we record its kind (i.e., what trait | |
1821 | /// it implements) into its `ClosureSubsts` using a type | |
1822 | /// parameter. This is kind of a phantom type, except that the | |
1823 | /// most convenient thing for us to are the integral types. This | |
1824 | /// function converts such a special type into the closure | |
1825 | /// kind. To go the other way, use | |
1826 | /// `tcx.closure_kind_ty(closure_kind)`. | |
1827 | /// | |
1828 | /// Note that during type checking, we use an inference variable | |
1829 | /// to represent the closure kind, because it has not yet been | |
1830 | /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`) | |
1831 | /// is complete, that type variable will be unified. | |
1832 | pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> { | |
1833 | match self.sty { | |
1834 | TyInt(int_ty) => match int_ty { | |
1835 | ast::IntTy::I8 => Some(ty::ClosureKind::Fn), | |
1836 | ast::IntTy::I16 => Some(ty::ClosureKind::FnMut), | |
1837 | ast::IntTy::I32 => Some(ty::ClosureKind::FnOnce), | |
1838 | _ => bug!("cannot convert type `{:?}` to a closure kind", self), | |
1839 | }, | |
1840 | ||
1841 | TyInfer(_) => None, | |
1842 | ||
1843 | TyError => Some(ty::ClosureKind::Fn), | |
1844 | ||
1845 | _ => bug!("cannot convert type `{:?}` to a closure kind", self), | |
1846 | } | |
1847 | } | |
e9174d1e | 1848 | } |
ea8adc8c XL |
1849 | |
1850 | /// Typed constant value. | |
94b46f34 | 1851 | #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] |
ea8adc8c XL |
1852 | pub struct Const<'tcx> { |
1853 | pub ty: Ty<'tcx>, | |
1854 | ||
ea8adc8c XL |
1855 | pub val: ConstVal<'tcx>, |
1856 | } | |
1857 | ||
94b46f34 XL |
1858 | impl<'tcx> Const<'tcx> { |
1859 | pub fn unevaluated( | |
1860 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1861 | def_id: DefId, | |
1862 | substs: &'tcx Substs<'tcx>, | |
1863 | ty: Ty<'tcx>, | |
1864 | ) -> &'tcx Self { | |
1865 | tcx.mk_const(Const { | |
1866 | val: ConstVal::Unevaluated(def_id, substs), | |
1867 | ty, | |
1868 | }) | |
1869 | } | |
1870 | ||
1871 | #[inline] | |
1872 | pub fn from_const_val( | |
1873 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1874 | val: ConstVal<'tcx>, | |
1875 | ty: Ty<'tcx>, | |
1876 | ) -> &'tcx Self { | |
1877 | tcx.mk_const(Const { | |
1878 | val, | |
1879 | ty, | |
1880 | }) | |
1881 | } | |
1882 | ||
1883 | #[inline] | |
1884 | pub fn from_const_value( | |
1885 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1886 | val: ConstValue<'tcx>, | |
1887 | ty: Ty<'tcx>, | |
1888 | ) -> &'tcx Self { | |
1889 | Self::from_const_val(tcx, ConstVal::Value(val), ty) | |
1890 | } | |
1891 | ||
1892 | #[inline] | |
1893 | pub fn from_byval_value( | |
1894 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1895 | val: Value, | |
1896 | ty: Ty<'tcx>, | |
1897 | ) -> &'tcx Self { | |
1898 | Self::from_const_value(tcx, ConstValue::from_byval_value(val), ty) | |
1899 | } | |
1900 | ||
1901 | #[inline] | |
1902 | pub fn from_scalar( | |
1903 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1904 | val: Scalar, | |
1905 | ty: Ty<'tcx>, | |
1906 | ) -> &'tcx Self { | |
1907 | Self::from_const_value(tcx, ConstValue::from_scalar(val), ty) | |
1908 | } | |
1909 | ||
1910 | #[inline] | |
1911 | pub fn from_bits( | |
1912 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1913 | bits: u128, | |
1914 | ty: ParamEnvAnd<'tcx, Ty<'tcx>>, | |
1915 | ) -> &'tcx Self { | |
1916 | let ty = tcx.lift_to_global(&ty).unwrap(); | |
1917 | let size = tcx.layout_of(ty).unwrap_or_else(|e| { | |
1918 | panic!("could not compute layout for {:?}: {:?}", ty, e) | |
1919 | }).size; | |
1920 | let shift = 128 - size.bits(); | |
1921 | let truncated = (bits << shift) >> shift; | |
1922 | assert_eq!(truncated, bits, "from_bits called with untruncated value"); | |
1923 | Self::from_scalar(tcx, Scalar::Bits { bits, defined: size.bits() as u8 }, ty.value) | |
1924 | } | |
1925 | ||
1926 | #[inline] | |
1927 | pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self { | |
1928 | Self::from_scalar(tcx, Scalar::undef(), ty) | |
1929 | } | |
1930 | ||
1931 | #[inline] | |
1932 | pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> &'tcx Self { | |
1933 | Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) | |
1934 | } | |
1935 | ||
1936 | #[inline] | |
1937 | pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self { | |
1938 | Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) | |
1939 | } | |
1940 | ||
1941 | #[inline] | |
1942 | pub fn to_bits( | |
1943 | &self, | |
1944 | tcx: TyCtxt<'_, '_, 'tcx>, | |
1945 | ty: ParamEnvAnd<'tcx, Ty<'tcx>>, | |
1946 | ) -> Option<u128> { | |
1947 | if self.ty != ty.value { | |
1948 | return None; | |
1949 | } | |
1950 | let ty = tcx.lift_to_global(&ty).unwrap(); | |
1951 | let size = tcx.layout_of(ty).ok()?.size; | |
1952 | match self.val { | |
1953 | ConstVal::Value(val) => val.to_bits(size), | |
1954 | _ => None, | |
1955 | } | |
1956 | } | |
1957 | ||
1958 | #[inline] | |
1959 | pub fn to_ptr(&self) -> Option<Pointer> { | |
1960 | match self.val { | |
1961 | ConstVal::Value(val) => val.to_ptr(), | |
1962 | _ => None, | |
1963 | } | |
1964 | } | |
1965 | ||
1966 | #[inline] | |
1967 | pub fn to_byval_value(&self) -> Option<Value> { | |
1968 | match self.val { | |
1969 | ConstVal::Value(val) => val.to_byval_value(), | |
1970 | _ => None, | |
1971 | } | |
1972 | } | |
1973 | ||
1974 | #[inline] | |
1975 | pub fn to_scalar(&self) -> Option<Scalar> { | |
1976 | match self.val { | |
1977 | ConstVal::Value(val) => val.to_scalar(), | |
1978 | _ => None, | |
1979 | } | |
1980 | } | |
1981 | ||
1982 | #[inline] | |
1983 | pub fn assert_bits( | |
1984 | &self, | |
1985 | tcx: TyCtxt<'_, '_, '_>, | |
1986 | ty: ParamEnvAnd<'tcx, Ty<'tcx>>, | |
1987 | ) -> Option<u128> { | |
1988 | assert_eq!(self.ty, ty.value); | |
1989 | let ty = tcx.lift_to_global(&ty).unwrap(); | |
1990 | let size = tcx.layout_of(ty).ok()?.size; | |
1991 | match self.val { | |
1992 | ConstVal::Value(val) => val.to_bits(size), | |
1993 | _ => None, | |
1994 | } | |
1995 | } | |
1996 | ||
1997 | #[inline] | |
1998 | pub fn assert_bool(&self, tcx: TyCtxt<'_, '_, '_>) -> Option<bool> { | |
1999 | self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.bool)).and_then(|v| match v { | |
2000 | 0 => Some(false), | |
2001 | 1 => Some(true), | |
2002 | _ => None, | |
2003 | }) | |
2004 | } | |
2005 | ||
2006 | #[inline] | |
2007 | pub fn assert_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> Option<u64> { | |
2008 | self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.usize)).map(|v| v as u64) | |
2009 | } | |
2010 | ||
2011 | #[inline] | |
2012 | pub fn unwrap_bits( | |
2013 | &self, | |
2014 | tcx: TyCtxt<'_, '_, '_>, | |
2015 | ty: ParamEnvAnd<'tcx, Ty<'tcx>>, | |
2016 | ) -> u128 { | |
2017 | match self.assert_bits(tcx, ty) { | |
2018 | Some(val) => val, | |
2019 | None => bug!("expected bits of {}, got {:#?}", ty.value, self), | |
2020 | } | |
2021 | } | |
2022 | ||
2023 | #[inline] | |
2024 | pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 { | |
2025 | match self.assert_usize(tcx) { | |
2026 | Some(val) => val, | |
2027 | None => bug!("expected constant usize, got {:#?}", self), | |
2028 | } | |
2029 | } | |
2030 | } | |
2031 | ||
ea8adc8c | 2032 | impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} |