1 #![allow(rustc::usage_of_ty_tykind)]
2
3 use std::cmp::Ordering;
4 use std::{fmt, hash};
5
6 use crate::DebruijnIndex;
7 use crate::FloatTy;
8 use crate::HashStableContext;
9 use crate::IntTy;
10 use crate::Interner;
11 use crate::TyDecoder;
12 use crate::TyEncoder;
13 use crate::UintTy;
14
15 use self::RegionKind::*;
16 use self::TyKind::*;
17
18 use rustc_data_structures::stable_hasher::HashStable;
19 use rustc_serialize::{Decodable, Decoder, Encodable};
20
21 /// Specifies how a trait object is represented.
22 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
23 #[derive(Encodable, Decodable, HashStable_Generic)]
24 pub enum DynKind {
25 /// An unsized `dyn Trait` object
26 Dyn,
27 /// A sized `dyn* Trait` object
28 ///
29 /// These objects are represented as a `(data, vtable)` pair where `data` is a value of some
30 /// ptr-sized and ptr-aligned dynamically determined type `T` and `vtable` is a pointer to the
31 /// vtable of `impl T for Trait`. This allows a `dyn*` object to be treated agnostically with
32 /// respect to whether it points to a `Box<T>`, `Rc<T>`, etc.
33 DynStar,
34 }
35
36 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
37 #[derive(Encodable, Decodable, HashStable_Generic)]
38 pub enum AliasKind {
39 /// A projection `<Type as Trait>::AssocType`.
40 /// Can get normalized away if monomorphic enough.
41 Projection,
42 Inherent,
43 /// An opaque type (usually from `impl Trait` in type aliases or function return types)
44 /// Can only be normalized away in RevealAll mode
45 Opaque,
46 /// A type alias that actually checks its trait bounds.
47 /// Currently only used if the type alias references opaque types.
48 /// Can always be normalized away.
49 Weak,
50 }
51
52 /// Defines the kinds of types used by the type system.
53 ///
54 /// Types written by the user start out as `hir::TyKind` and get
55 /// converted to this representation using `AstConv::ast_ty_to_ty`.
56 #[rustc_diagnostic_item = "IrTyKind"]
57 pub enum TyKind<I: Interner> {
58 /// The primitive boolean type. Written as `bool`.
59 Bool,
60
61 /// The primitive character type; holds a Unicode scalar value
62 /// (a non-surrogate code point). Written as `char`.
63 Char,
64
65 /// A primitive signed integer type. For example, `i32`.
66 Int(IntTy),
67
68 /// A primitive unsigned integer type. For example, `u32`.
69 Uint(UintTy),
70
71 /// A primitive floating-point type. For example, `f64`.
72 Float(FloatTy),
73
74 /// Algebraic data types (ADT). For example: structures, enumerations and unions.
75 ///
76 /// For example, the type `List<i32>` would be represented using the `AdtDef`
77 /// for `struct List<T>` and the substs `[i32]`.
78 ///
79 /// Note that generic parameters in fields only get lazily substituted
80 /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`.
81 Adt(I::AdtDef, I::SubstsRef),
82
83 /// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
84 Foreign(I::DefId),
85
86 /// The pointee of a string slice. Written as `str`.
87 Str,
88
89 /// An array with the given length. Written as `[T; N]`.
90 Array(I::Ty, I::Const),
91
92 /// The pointee of an array slice. Written as `[T]`.
93 Slice(I::Ty),
94
95 /// A raw pointer. Written as `*mut T` or `*const T`
96 RawPtr(I::TypeAndMut),
97
98 /// A reference; a pointer with an associated lifetime. Written as
99 /// `&'a mut T` or `&'a T`.
100 Ref(I::Region, I::Ty, I::Mutability),
101
102 /// The anonymous type of a function declaration/definition. Each
103 /// function has a unique type.
104 ///
105 /// For the function `fn foo() -> i32 { 3 }` this type would be
106 /// shown to the user as `fn() -> i32 {foo}`.
107 ///
108 /// For example the type of `bar` here:
109 /// ```rust
110 /// fn foo() -> i32 { 1 }
111 /// let bar = foo; // bar: fn() -> i32 {foo}
112 /// ```
113 FnDef(I::DefId, I::SubstsRef),
114
115 /// A pointer to a function. Written as `fn() -> i32`.
116 ///
117 /// Note that both functions and closures start out as either
118 /// [FnDef] or [Closure] which can be then be coerced to this variant.
119 ///
120 /// For example the type of `bar` here:
121 ///
122 /// ```rust
123 /// fn foo() -> i32 { 1 }
124 /// let bar: fn() -> i32 = foo;
125 /// ```
126 FnPtr(I::PolyFnSig),
127
128 /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
129 Dynamic(I::ListBinderExistentialPredicate, I::Region, DynKind),
130
131 /// The anonymous type of a closure. Used to represent the type of `|a| a`.
132 ///
133 /// Closure substs contain both the - potentially substituted - generic parameters
134 /// of its parent and some synthetic parameters. See the documentation for
135 /// `ClosureSubsts` for more details.
136 Closure(I::DefId, I::SubstsRef),
137
138 /// The anonymous type of a generator. Used to represent the type of
139 /// `|a| yield a`.
140 ///
141 /// For more info about generator substs, visit the documentation for
142 /// `GeneratorSubsts`.
143 Generator(I::DefId, I::SubstsRef, I::Movability),
144
145 /// A type representing the types stored inside a generator.
146 /// This should only appear as part of the `GeneratorSubsts`.
147 ///
148 /// Note that the captured variables for generators are stored separately
149 /// using a tuple in the same way as for closures.
150 ///
151 /// Unlike upvars, the witness can reference lifetimes from
152 /// inside of the generator itself. To deal with them in
153 /// the type of the generator, we convert them to higher ranked
154 /// lifetimes bound by the witness itself.
155 ///
156 /// Looking at the following example, the witness for this generator
157 /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
158 ///
159 /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
160 /// #![feature(generators)]
161 /// |a| {
162 /// let x = &vec![3];
163 /// yield a;
164 /// yield x[0];
165 /// }
166 /// # ;
167 /// ```
168 GeneratorWitness(I::BinderListTy),
169
170 /// A type representing the types stored inside a generator.
171 /// This should only appear as part of the `GeneratorSubsts`.
172 ///
173 /// Unlike upvars, the witness can reference lifetimes from
174 /// inside of the generator itself. To deal with them in
175 /// the type of the generator, we convert them to higher ranked
176 /// lifetimes bound by the witness itself.
177 ///
178 /// This variant is only using when `drop_tracking_mir` is set.
179 /// This contains the `DefId` and the `SubstsRef` of the generator.
180 /// The actual witness types are computed on MIR by the `mir_generator_witnesses` query.
181 ///
182 /// Looking at the following example, the witness for this generator
183 /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
184 ///
185 /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
186 /// #![feature(generators)]
187 /// |a| {
188 /// let x = &vec![3];
189 /// yield a;
190 /// yield x[0];
191 /// }
192 /// # ;
193 /// ```
194 GeneratorWitnessMIR(I::DefId, I::SubstsRef),
195
196 /// The never type `!`.
197 Never,
198
199 /// A tuple type. For example, `(i32, bool)`.
200 Tuple(I::ListTy),
201
202 /// A projection or opaque type. Both of these types
203 Alias(AliasKind, I::AliasTy),
204
205 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
206 Param(I::ParamTy),
207
208 /// Bound type variable, used to represent the `'a` in `for<'a> fn(&'a ())`.
209 ///
210 /// For canonical queries, we replace inference variables with bound variables,
211 /// so e.g. when checking whether `&'_ (): Trait<_>` holds, we canonicalize that to
212 /// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables
213 /// back to inference variables in a new inference context when inside of the query.
214 ///
215 /// It is conventional to render anonymous bound types like `^N` or `^D_N`,
216 /// where `N` is the bound variable's anonymous index into the binder, and
217 /// `D` is the debruijn index, or totally omitted if the debruijn index is zero.
218 ///
219 /// See the `rustc-dev-guide` for more details about
220 /// [higher-ranked trait bounds][1] and [canonical queries][2].
221 ///
222 /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
223 /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html
224 Bound(DebruijnIndex, I::BoundTy),
225
226 /// A placeholder type, used during higher ranked subtyping to instantiate
227 /// bound variables.
228 ///
229 /// It is conventional to render anonymous placeholer types like `!N` or `!U_N`,
230 /// where `N` is the placeholder variable's anonymous index (which corresponds
231 /// to the bound variable's index from the binder from which it was instantiated),
232 /// and `U` is the universe index in which it is instantiated, or totally omitted
233 /// if the universe index is zero.
234 Placeholder(I::PlaceholderType),
235
236 /// A type variable used during type checking.
237 ///
238 /// Similar to placeholders, inference variables also live in a universe to
239 /// correctly deal with higher ranked types. Though unlike placeholders,
240 /// that universe is stored in the `InferCtxt` instead of directly
241 /// inside of the type.
242 Infer(I::InferTy),
243
244 /// A placeholder for a type which could not be computed; this is
245 /// propagated to avoid useless error messages.
246 Error(I::ErrorGuaranteed),
247 }
248
249 impl<I: Interner> TyKind<I> {
250 #[inline]
is_primitive(&self) -> bool251 pub fn is_primitive(&self) -> bool {
252 matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_))
253 }
254 }
255
256 // This is manually implemented for `TyKind` because `std::mem::discriminant`
257 // returns an opaque value that is `PartialEq` but not `PartialOrd`
258 #[inline]
tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize259 const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
260 match value {
261 Bool => 0,
262 Char => 1,
263 Int(_) => 2,
264 Uint(_) => 3,
265 Float(_) => 4,
266 Adt(_, _) => 5,
267 Foreign(_) => 6,
268 Str => 7,
269 Array(_, _) => 8,
270 Slice(_) => 9,
271 RawPtr(_) => 10,
272 Ref(_, _, _) => 11,
273 FnDef(_, _) => 12,
274 FnPtr(_) => 13,
275 Dynamic(..) => 14,
276 Closure(_, _) => 15,
277 Generator(_, _, _) => 16,
278 GeneratorWitness(_) => 17,
279 Never => 18,
280 Tuple(_) => 19,
281 Alias(_, _) => 20,
282 Param(_) => 21,
283 Bound(_, _) => 22,
284 Placeholder(_) => 23,
285 Infer(_) => 24,
286 Error(_) => 25,
287 GeneratorWitnessMIR(_, _) => 26,
288 }
289 }
290
291 // This is manually implemented because a derive would require `I: Clone`
292 impl<I: Interner> Clone for TyKind<I> {
clone(&self) -> Self293 fn clone(&self) -> Self {
294 match self {
295 Bool => Bool,
296 Char => Char,
297 Int(i) => Int(*i),
298 Uint(u) => Uint(*u),
299 Float(f) => Float(*f),
300 Adt(d, s) => Adt(d.clone(), s.clone()),
301 Foreign(d) => Foreign(d.clone()),
302 Str => Str,
303 Array(t, c) => Array(t.clone(), c.clone()),
304 Slice(t) => Slice(t.clone()),
305 RawPtr(p) => RawPtr(p.clone()),
306 Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
307 FnDef(d, s) => FnDef(d.clone(), s.clone()),
308 FnPtr(s) => FnPtr(s.clone()),
309 Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr),
310 Closure(d, s) => Closure(d.clone(), s.clone()),
311 Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
312 GeneratorWitness(g) => GeneratorWitness(g.clone()),
313 GeneratorWitnessMIR(d, s) => GeneratorWitnessMIR(d.clone(), s.clone()),
314 Never => Never,
315 Tuple(t) => Tuple(t.clone()),
316 Alias(k, p) => Alias(*k, p.clone()),
317 Param(p) => Param(p.clone()),
318 Bound(d, b) => Bound(*d, b.clone()),
319 Placeholder(p) => Placeholder(p.clone()),
320 Infer(t) => Infer(t.clone()),
321 Error(e) => Error(e.clone()),
322 }
323 }
324 }
325
326 // This is manually implemented because a derive would require `I: PartialEq`
327 impl<I: Interner> PartialEq for TyKind<I> {
328 #[inline]
eq(&self, other: &TyKind<I>) -> bool329 fn eq(&self, other: &TyKind<I>) -> bool {
330 // You might expect this `match` to be preceded with this:
331 //
332 // tykind_discriminant(self) == tykind_discriminant(other) &&
333 //
334 // but the data patterns in practice are such that a comparison
335 // succeeds 99%+ of the time, and it's faster to omit it.
336 match (self, other) {
337 (Int(a_i), Int(b_i)) => a_i == b_i,
338 (Uint(a_u), Uint(b_u)) => a_u == b_u,
339 (Float(a_f), Float(b_f)) => a_f == b_f,
340 (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
341 (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
342 (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
343 (Slice(a_t), Slice(b_t)) => a_t == b_t,
344 (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t,
345 (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
346 (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
347 (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
348 (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
349 a_p == b_p && a_r == b_r && a_repr == b_repr
350 }
351 (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
352 (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
353 a_d == b_d && a_s == b_s && a_m == b_m
354 }
355 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
356 (GeneratorWitnessMIR(a_d, a_s), GeneratorWitnessMIR(b_d, b_s)) => {
357 a_d == b_d && a_s == b_s
358 }
359 (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
360 (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
361 (Param(a_p), Param(b_p)) => a_p == b_p,
362 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
363 (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
364 (Infer(a_t), Infer(b_t)) => a_t == b_t,
365 (Error(a_e), Error(b_e)) => a_e == b_e,
366 (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
367 _ => {
368 debug_assert!(
369 tykind_discriminant(self) != tykind_discriminant(other),
370 "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
371 );
372 false
373 }
374 }
375 }
376 }
377
378 // This is manually implemented because a derive would require `I: Eq`
379 impl<I: Interner> Eq for TyKind<I> {}
380
381 // This is manually implemented because a derive would require `I: PartialOrd`
382 impl<I: Interner> PartialOrd for TyKind<I> {
383 #[inline]
partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering>384 fn partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering> {
385 Some(self.cmp(other))
386 }
387 }
388
389 // This is manually implemented because a derive would require `I: Ord`
390 impl<I: Interner> Ord for TyKind<I> {
391 #[inline]
cmp(&self, other: &TyKind<I>) -> Ordering392 fn cmp(&self, other: &TyKind<I>) -> Ordering {
393 tykind_discriminant(self).cmp(&tykind_discriminant(other)).then_with(|| {
394 match (self, other) {
395 (Int(a_i), Int(b_i)) => a_i.cmp(b_i),
396 (Uint(a_u), Uint(b_u)) => a_u.cmp(b_u),
397 (Float(a_f), Float(b_f)) => a_f.cmp(b_f),
398 (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
399 (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d),
400 (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)),
401 (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t),
402 (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t),
403 (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => {
404 a_r.cmp(b_r).then_with(|| a_t.cmp(b_t).then_with(|| a_m.cmp(b_m)))
405 }
406 (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
407 (FnPtr(a_s), FnPtr(b_s)) => a_s.cmp(b_s),
408 (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
409 a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr)))
410 }
411 (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)),
412 (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
413 a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m)))
414 }
415 (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
416 (
417 GeneratorWitnessMIR(a_d, a_s),
418 GeneratorWitnessMIR(b_d, b_s),
419 ) => match Ord::cmp(a_d, b_d) {
420 Ordering::Equal => Ord::cmp(a_s, b_s),
421 cmp => cmp,
422 },
423 (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
424 (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)),
425 (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
426 (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
427 (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
428 (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t),
429 (Error(a_e), Error(b_e)) => a_e.cmp(b_e),
430 (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal,
431 _ => {
432 debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
433 Ordering::Equal
434 }
435 }
436 })
437 }
438 }
439
440 // This is manually implemented because a derive would require `I: Hash`
441 impl<I: Interner> hash::Hash for TyKind<I> {
hash<__H: hash::Hasher>(&self, state: &mut __H) -> ()442 fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
443 tykind_discriminant(self).hash(state);
444 match self {
445 Int(i) => i.hash(state),
446 Uint(u) => u.hash(state),
447 Float(f) => f.hash(state),
448 Adt(d, s) => {
449 d.hash(state);
450 s.hash(state)
451 }
452 Foreign(d) => d.hash(state),
453 Array(t, c) => {
454 t.hash(state);
455 c.hash(state)
456 }
457 Slice(t) => t.hash(state),
458 RawPtr(t) => t.hash(state),
459 Ref(r, t, m) => {
460 r.hash(state);
461 t.hash(state);
462 m.hash(state)
463 }
464 FnDef(d, s) => {
465 d.hash(state);
466 s.hash(state)
467 }
468 FnPtr(s) => s.hash(state),
469 Dynamic(p, r, repr) => {
470 p.hash(state);
471 r.hash(state);
472 repr.hash(state)
473 }
474 Closure(d, s) => {
475 d.hash(state);
476 s.hash(state)
477 }
478 Generator(d, s, m) => {
479 d.hash(state);
480 s.hash(state);
481 m.hash(state)
482 }
483 GeneratorWitness(g) => g.hash(state),
484 GeneratorWitnessMIR(d, s) => {
485 d.hash(state);
486 s.hash(state);
487 }
488 Tuple(t) => t.hash(state),
489 Alias(i, p) => {
490 i.hash(state);
491 p.hash(state);
492 }
493 Param(p) => p.hash(state),
494 Bound(d, b) => {
495 d.hash(state);
496 b.hash(state)
497 }
498 Placeholder(p) => p.hash(state),
499 Infer(t) => t.hash(state),
500 Error(e) => e.hash(state),
501 Bool | Char | Str | Never => (),
502 }
503 }
504 }
505
506 // This is manually implemented because a derive would require `I: Debug`
507 impl<I: Interner> fmt::Debug for TyKind<I> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 match self {
510 Bool => write!(f, "bool"),
511 Char => write!(f, "char"),
512 Int(i) => write!(f, "{i:?}"),
513 Uint(u) => write!(f, "{u:?}"),
514 Float(float) => write!(f, "{float:?}"),
515 Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
516 Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
517 Str => write!(f, "str"),
518 Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
519 Slice(t) => write!(f, "[{t:?}]"),
520 RawPtr(p) => {
521 let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
522 match I::mutability_is_mut(mutbl) {
523 true => write!(f, "*mut "),
524 false => write!(f, "*const "),
525 }?;
526 write!(f, "{ty:?}")
527 }
528 Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
529 true => write!(f, "&{r:?} mut {t:?}"),
530 false => write!(f, "&{r:?} {t:?}"),
531 },
532 FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
533 FnPtr(s) => write!(f, "{s:?}"),
534 Dynamic(p, r, repr) => match repr {
535 DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
536 DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
537 },
538 Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
539 Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
540 GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
541 GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s),
542 Never => write!(f, "!"),
543 Tuple(t) => {
544 let mut iter = t.clone().into_iter();
545
546 write!(f, "(")?;
547
548 match iter.next() {
549 None => return write!(f, ")"),
550 Some(ty) => write!(f, "{ty:?}")?,
551 };
552
553 match iter.next() {
554 None => return write!(f, ",)"),
555 Some(ty) => write!(f, "{ty:?})")?,
556 }
557
558 for ty in iter {
559 write!(f, ", {ty:?}")?;
560 }
561 write!(f, ")")
562 }
563 Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
564 Param(p) => write!(f, "{p:?}"),
565 Bound(d, b) => crate::debug_bound_var(f, *d, b),
566 Placeholder(p) => write!(f, "{p:?}"),
567 Infer(t) => write!(f, "{t:?}"),
568 TyKind::Error(_) => write!(f, "{{type error}}"),
569 }
570 }
571 }
572
573 // This is manually implemented because a derive would require `I: Encodable`
574 impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
575 where
576 I::ErrorGuaranteed: Encodable<E>,
577 I::AdtDef: Encodable<E>,
578 I::SubstsRef: Encodable<E>,
579 I::DefId: Encodable<E>,
580 I::Ty: Encodable<E>,
581 I::Const: Encodable<E>,
582 I::Region: Encodable<E>,
583 I::TypeAndMut: Encodable<E>,
584 I::Mutability: Encodable<E>,
585 I::Movability: Encodable<E>,
586 I::PolyFnSig: Encodable<E>,
587 I::ListBinderExistentialPredicate: Encodable<E>,
588 I::BinderListTy: Encodable<E>,
589 I::ListTy: Encodable<E>,
590 I::AliasTy: Encodable<E>,
591 I::ParamTy: Encodable<E>,
592 I::BoundTy: Encodable<E>,
593 I::PlaceholderType: Encodable<E>,
594 I::InferTy: Encodable<E>,
595 I::PredicateKind: Encodable<E>,
596 I::AllocId: Encodable<E>,
597 {
encode(&self, e: &mut E)598 fn encode(&self, e: &mut E) {
599 let disc = tykind_discriminant(self);
600 match self {
601 Bool => e.emit_enum_variant(disc, |_| {}),
602 Char => e.emit_enum_variant(disc, |_| {}),
603 Int(i) => e.emit_enum_variant(disc, |e| {
604 i.encode(e);
605 }),
606 Uint(u) => e.emit_enum_variant(disc, |e| {
607 u.encode(e);
608 }),
609 Float(f) => e.emit_enum_variant(disc, |e| {
610 f.encode(e);
611 }),
612 Adt(adt, substs) => e.emit_enum_variant(disc, |e| {
613 adt.encode(e);
614 substs.encode(e);
615 }),
616 Foreign(def_id) => e.emit_enum_variant(disc, |e| {
617 def_id.encode(e);
618 }),
619 Str => e.emit_enum_variant(disc, |_| {}),
620 Array(t, c) => e.emit_enum_variant(disc, |e| {
621 t.encode(e);
622 c.encode(e);
623 }),
624 Slice(t) => e.emit_enum_variant(disc, |e| {
625 t.encode(e);
626 }),
627 RawPtr(tam) => e.emit_enum_variant(disc, |e| {
628 tam.encode(e);
629 }),
630 Ref(r, t, m) => e.emit_enum_variant(disc, |e| {
631 r.encode(e);
632 t.encode(e);
633 m.encode(e);
634 }),
635 FnDef(def_id, substs) => e.emit_enum_variant(disc, |e| {
636 def_id.encode(e);
637 substs.encode(e);
638 }),
639 FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| {
640 polyfnsig.encode(e);
641 }),
642 Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| {
643 l.encode(e);
644 r.encode(e);
645 repr.encode(e);
646 }),
647 Closure(def_id, substs) => e.emit_enum_variant(disc, |e| {
648 def_id.encode(e);
649 substs.encode(e);
650 }),
651 Generator(def_id, substs, m) => e.emit_enum_variant(disc, |e| {
652 def_id.encode(e);
653 substs.encode(e);
654 m.encode(e);
655 }),
656 GeneratorWitness(b) => e.emit_enum_variant(disc, |e| {
657 b.encode(e);
658 }),
659 GeneratorWitnessMIR(def_id, substs) => e.emit_enum_variant(disc, |e| {
660 def_id.encode(e);
661 substs.encode(e);
662 }),
663 Never => e.emit_enum_variant(disc, |_| {}),
664 Tuple(substs) => e.emit_enum_variant(disc, |e| {
665 substs.encode(e);
666 }),
667 Alias(k, p) => e.emit_enum_variant(disc, |e| {
668 k.encode(e);
669 p.encode(e);
670 }),
671 Param(p) => e.emit_enum_variant(disc, |e| {
672 p.encode(e);
673 }),
674 Bound(d, b) => e.emit_enum_variant(disc, |e| {
675 d.encode(e);
676 b.encode(e);
677 }),
678 Placeholder(p) => e.emit_enum_variant(disc, |e| {
679 p.encode(e);
680 }),
681 Infer(i) => e.emit_enum_variant(disc, |e| {
682 i.encode(e);
683 }),
684 Error(d) => e.emit_enum_variant(disc, |e| {
685 d.encode(e);
686 }),
687 }
688 }
689 }
690
691 // This is manually implemented because a derive would require `I: Decodable`
692 impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I>
693 where
694 I::ErrorGuaranteed: Decodable<D>,
695 I::AdtDef: Decodable<D>,
696 I::SubstsRef: Decodable<D>,
697 I::DefId: Decodable<D>,
698 I::Ty: Decodable<D>,
699 I::Const: Decodable<D>,
700 I::Region: Decodable<D>,
701 I::TypeAndMut: Decodable<D>,
702 I::Mutability: Decodable<D>,
703 I::Movability: Decodable<D>,
704 I::PolyFnSig: Decodable<D>,
705 I::ListBinderExistentialPredicate: Decodable<D>,
706 I::BinderListTy: Decodable<D>,
707 I::ListTy: Decodable<D>,
708 I::AliasTy: Decodable<D>,
709 I::ParamTy: Decodable<D>,
710 I::AliasTy: Decodable<D>,
711 I::BoundTy: Decodable<D>,
712 I::PlaceholderType: Decodable<D>,
713 I::InferTy: Decodable<D>,
714 I::PredicateKind: Decodable<D>,
715 I::AllocId: Decodable<D>,
716 {
decode(d: &mut D) -> Self717 fn decode(d: &mut D) -> Self {
718 match Decoder::read_usize(d) {
719 0 => Bool,
720 1 => Char,
721 2 => Int(Decodable::decode(d)),
722 3 => Uint(Decodable::decode(d)),
723 4 => Float(Decodable::decode(d)),
724 5 => Adt(Decodable::decode(d), Decodable::decode(d)),
725 6 => Foreign(Decodable::decode(d)),
726 7 => Str,
727 8 => Array(Decodable::decode(d), Decodable::decode(d)),
728 9 => Slice(Decodable::decode(d)),
729 10 => RawPtr(Decodable::decode(d)),
730 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
731 12 => FnDef(Decodable::decode(d), Decodable::decode(d)),
732 13 => FnPtr(Decodable::decode(d)),
733 14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
734 15 => Closure(Decodable::decode(d), Decodable::decode(d)),
735 16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)),
736 17 => GeneratorWitness(Decodable::decode(d)),
737 18 => Never,
738 19 => Tuple(Decodable::decode(d)),
739 20 => Alias(Decodable::decode(d), Decodable::decode(d)),
740 21 => Param(Decodable::decode(d)),
741 22 => Bound(Decodable::decode(d), Decodable::decode(d)),
742 23 => Placeholder(Decodable::decode(d)),
743 24 => Infer(Decodable::decode(d)),
744 25 => Error(Decodable::decode(d)),
745 26 => GeneratorWitnessMIR(Decodable::decode(d), Decodable::decode(d)),
746 _ => panic!(
747 "{}",
748 format!(
749 "invalid enum variant tag while decoding `{}`, expected 0..{}",
750 "TyKind", 27,
751 )
752 ),
753 }
754 }
755 }
756
757 // This is not a derived impl because a derive would require `I: HashStable`
758 #[allow(rustc::usage_of_ty_tykind)]
759 impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
760 where
761 I::AdtDef: HashStable<CTX>,
762 I::DefId: HashStable<CTX>,
763 I::SubstsRef: HashStable<CTX>,
764 I::Ty: HashStable<CTX>,
765 I::Const: HashStable<CTX>,
766 I::TypeAndMut: HashStable<CTX>,
767 I::PolyFnSig: HashStable<CTX>,
768 I::ListBinderExistentialPredicate: HashStable<CTX>,
769 I::Region: HashStable<CTX>,
770 I::Movability: HashStable<CTX>,
771 I::Mutability: HashStable<CTX>,
772 I::BinderListTy: HashStable<CTX>,
773 I::ListTy: HashStable<CTX>,
774 I::AliasTy: HashStable<CTX>,
775 I::BoundTy: HashStable<CTX>,
776 I::ParamTy: HashStable<CTX>,
777 I::PlaceholderType: HashStable<CTX>,
778 I::InferTy: HashStable<CTX>,
779 I::ErrorGuaranteed: HashStable<CTX>,
780 {
781 #[inline]
hash_stable( &self, __hcx: &mut CTX, __hasher: &mut rustc_data_structures::stable_hasher::StableHasher, )782 fn hash_stable(
783 &self,
784 __hcx: &mut CTX,
785 __hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
786 ) {
787 std::mem::discriminant(self).hash_stable(__hcx, __hasher);
788 match self {
789 Bool => {}
790 Char => {}
791 Int(i) => {
792 i.hash_stable(__hcx, __hasher);
793 }
794 Uint(u) => {
795 u.hash_stable(__hcx, __hasher);
796 }
797 Float(f) => {
798 f.hash_stable(__hcx, __hasher);
799 }
800 Adt(adt, substs) => {
801 adt.hash_stable(__hcx, __hasher);
802 substs.hash_stable(__hcx, __hasher);
803 }
804 Foreign(def_id) => {
805 def_id.hash_stable(__hcx, __hasher);
806 }
807 Str => {}
808 Array(t, c) => {
809 t.hash_stable(__hcx, __hasher);
810 c.hash_stable(__hcx, __hasher);
811 }
812 Slice(t) => {
813 t.hash_stable(__hcx, __hasher);
814 }
815 RawPtr(tam) => {
816 tam.hash_stable(__hcx, __hasher);
817 }
818 Ref(r, t, m) => {
819 r.hash_stable(__hcx, __hasher);
820 t.hash_stable(__hcx, __hasher);
821 m.hash_stable(__hcx, __hasher);
822 }
823 FnDef(def_id, substs) => {
824 def_id.hash_stable(__hcx, __hasher);
825 substs.hash_stable(__hcx, __hasher);
826 }
827 FnPtr(polyfnsig) => {
828 polyfnsig.hash_stable(__hcx, __hasher);
829 }
830 Dynamic(l, r, repr) => {
831 l.hash_stable(__hcx, __hasher);
832 r.hash_stable(__hcx, __hasher);
833 repr.hash_stable(__hcx, __hasher);
834 }
835 Closure(def_id, substs) => {
836 def_id.hash_stable(__hcx, __hasher);
837 substs.hash_stable(__hcx, __hasher);
838 }
839 Generator(def_id, substs, m) => {
840 def_id.hash_stable(__hcx, __hasher);
841 substs.hash_stable(__hcx, __hasher);
842 m.hash_stable(__hcx, __hasher);
843 }
844 GeneratorWitness(b) => {
845 b.hash_stable(__hcx, __hasher);
846 }
847 GeneratorWitnessMIR(def_id, substs) => {
848 def_id.hash_stable(__hcx, __hasher);
849 substs.hash_stable(__hcx, __hasher);
850 }
851 Never => {}
852 Tuple(substs) => {
853 substs.hash_stable(__hcx, __hasher);
854 }
855 Alias(k, p) => {
856 k.hash_stable(__hcx, __hasher);
857 p.hash_stable(__hcx, __hasher);
858 }
859 Param(p) => {
860 p.hash_stable(__hcx, __hasher);
861 }
862 Bound(d, b) => {
863 d.hash_stable(__hcx, __hasher);
864 b.hash_stable(__hcx, __hasher);
865 }
866 Placeholder(p) => {
867 p.hash_stable(__hcx, __hasher);
868 }
869 Infer(i) => {
870 i.hash_stable(__hcx, __hasher);
871 }
872 Error(d) => {
873 d.hash_stable(__hcx, __hasher);
874 }
875 }
876 }
877 }
878
879 /// Represents a constant in Rust.
880 // #[derive(derive_more::From)]
881 pub enum ConstKind<I: Interner> {
882 /// A const generic parameter.
883 Param(I::ParamConst),
884
885 /// Infer the value of the const.
886 Infer(I::InferConst),
887
888 /// Bound const variable, used only when preparing a trait query.
889 Bound(DebruijnIndex, I::BoundConst),
890
891 /// A placeholder const - universally quantified higher-ranked const.
892 Placeholder(I::PlaceholderConst),
893
894 /// An unnormalized const item such as an anon const or assoc const or free const item.
895 /// Right now anything other than anon consts does not actually work properly but this
896 /// should
897 Unevaluated(I::AliasConst),
898
899 /// Used to hold computed value.
900 Value(I::ValueConst),
901
902 /// A placeholder for a const which could not be computed; this is
903 /// propagated to avoid useless error messages.
904 Error(I::ErrorGuaranteed),
905
906 /// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
907 /// const arguments such as `N + 1` or `foo(N)`
908 Expr(I::ExprConst),
909 }
910
const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize911 const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
912 match value {
913 ConstKind::Param(_) => 0,
914 ConstKind::Infer(_) => 1,
915 ConstKind::Bound(_, _) => 2,
916 ConstKind::Placeholder(_) => 3,
917 ConstKind::Unevaluated(_) => 4,
918 ConstKind::Value(_) => 5,
919 ConstKind::Error(_) => 6,
920 ConstKind::Expr(_) => 7,
921 }
922 }
923
924 impl<I: Interner> hash::Hash for ConstKind<I> {
hash<H: hash::Hasher>(&self, state: &mut H)925 fn hash<H: hash::Hasher>(&self, state: &mut H) {
926 const_kind_discriminant(self).hash(state);
927 match self {
928 ConstKind::Param(p) => p.hash(state),
929 ConstKind::Infer(i) => i.hash(state),
930 ConstKind::Bound(d, b) => {
931 d.hash(state);
932 b.hash(state);
933 }
934 ConstKind::Placeholder(p) => p.hash(state),
935 ConstKind::Unevaluated(u) => u.hash(state),
936 ConstKind::Value(v) => v.hash(state),
937 ConstKind::Error(e) => e.hash(state),
938 ConstKind::Expr(e) => e.hash(state),
939 }
940 }
941 }
942
943 impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
944 where
945 I::ParamConst: HashStable<CTX>,
946 I::InferConst: HashStable<CTX>,
947 I::BoundConst: HashStable<CTX>,
948 I::PlaceholderConst: HashStable<CTX>,
949 I::AliasConst: HashStable<CTX>,
950 I::ValueConst: HashStable<CTX>,
951 I::ErrorGuaranteed: HashStable<CTX>,
952 I::ExprConst: HashStable<CTX>,
953 {
hash_stable( &self, hcx: &mut CTX, hasher: &mut rustc_data_structures::stable_hasher::StableHasher, )954 fn hash_stable(
955 &self,
956 hcx: &mut CTX,
957 hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
958 ) {
959 const_kind_discriminant(self).hash_stable(hcx, hasher);
960 match self {
961 ConstKind::Param(p) => p.hash_stable(hcx, hasher),
962 ConstKind::Infer(i) => i.hash_stable(hcx, hasher),
963 ConstKind::Bound(d, b) => {
964 d.hash_stable(hcx, hasher);
965 b.hash_stable(hcx, hasher);
966 }
967 ConstKind::Placeholder(p) => p.hash_stable(hcx, hasher),
968 ConstKind::Unevaluated(u) => u.hash_stable(hcx, hasher),
969 ConstKind::Value(v) => v.hash_stable(hcx, hasher),
970 ConstKind::Error(e) => e.hash_stable(hcx, hasher),
971 ConstKind::Expr(e) => e.hash_stable(hcx, hasher),
972 }
973 }
974 }
975
976 impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
977 where
978 I::ParamConst: Decodable<D>,
979 I::InferConst: Decodable<D>,
980 I::BoundConst: Decodable<D>,
981 I::PlaceholderConst: Decodable<D>,
982 I::AliasConst: Decodable<D>,
983 I::ValueConst: Decodable<D>,
984 I::ErrorGuaranteed: Decodable<D>,
985 I::ExprConst: Decodable<D>,
986 {
decode(d: &mut D) -> Self987 fn decode(d: &mut D) -> Self {
988 match Decoder::read_usize(d) {
989 0 => ConstKind::Param(Decodable::decode(d)),
990 1 => ConstKind::Infer(Decodable::decode(d)),
991 2 => ConstKind::Bound(Decodable::decode(d), Decodable::decode(d)),
992 3 => ConstKind::Placeholder(Decodable::decode(d)),
993 4 => ConstKind::Unevaluated(Decodable::decode(d)),
994 5 => ConstKind::Value(Decodable::decode(d)),
995 6 => ConstKind::Error(Decodable::decode(d)),
996 7 => ConstKind::Expr(Decodable::decode(d)),
997 _ => panic!(
998 "{}",
999 format!(
1000 "invalid enum variant tag while decoding `{}`, expected 0..{}",
1001 "ConstKind", 8,
1002 )
1003 ),
1004 }
1005 }
1006 }
1007
1008 impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
1009 where
1010 I::ParamConst: Encodable<E>,
1011 I::InferConst: Encodable<E>,
1012 I::BoundConst: Encodable<E>,
1013 I::PlaceholderConst: Encodable<E>,
1014 I::AliasConst: Encodable<E>,
1015 I::ValueConst: Encodable<E>,
1016 I::ErrorGuaranteed: Encodable<E>,
1017 I::ExprConst: Encodable<E>,
1018 {
encode(&self, e: &mut E)1019 fn encode(&self, e: &mut E) {
1020 let disc = const_kind_discriminant(self);
1021 match self {
1022 ConstKind::Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
1023 ConstKind::Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
1024 ConstKind::Bound(d, b) => e.emit_enum_variant(disc, |e| {
1025 d.encode(e);
1026 b.encode(e);
1027 }),
1028 ConstKind::Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
1029 ConstKind::Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
1030 ConstKind::Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
1031 ConstKind::Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
1032 ConstKind::Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
1033 }
1034 }
1035 }
1036
1037 impl<I: Interner> PartialOrd for ConstKind<I> {
partial_cmp(&self, other: &Self) -> Option<Ordering>1038 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1039 Some(self.cmp(other))
1040 }
1041 }
1042
1043 impl<I: Interner> Ord for ConstKind<I> {
cmp(&self, other: &Self) -> Ordering1044 fn cmp(&self, other: &Self) -> Ordering {
1045 const_kind_discriminant(self)
1046 .cmp(&const_kind_discriminant(other))
1047 .then_with(|| match (self, other) {
1048 (ConstKind::Param(p1), ConstKind::Param(p2)) => p1.cmp(p2),
1049 (ConstKind::Infer(i1), ConstKind::Infer(i2)) => i1.cmp(i2),
1050 (ConstKind::Bound(d1, b1), ConstKind::Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)),
1051 (ConstKind::Placeholder(p1), ConstKind::Placeholder(p2)) => p1.cmp(p2),
1052 (ConstKind::Unevaluated(u1), ConstKind::Unevaluated(u2)) => u1.cmp(u2),
1053 (ConstKind::Value(v1), ConstKind::Value(v2)) => v1.cmp(v2),
1054 (ConstKind::Error(e1), ConstKind::Error(e2)) => e1.cmp(e2),
1055 (ConstKind::Expr(e1), ConstKind::Expr(e2)) => e1.cmp(e2),
1056 _ => {
1057 debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
1058 Ordering::Equal
1059 }
1060 })
1061 }
1062 }
1063
1064 impl<I: Interner> PartialEq for ConstKind<I> {
eq(&self, other: &Self) -> bool1065 fn eq(&self, other: &Self) -> bool {
1066 match (self, other) {
1067 (Self::Param(l0), Self::Param(r0)) => l0 == r0,
1068 (Self::Infer(l0), Self::Infer(r0)) => l0 == r0,
1069 (Self::Bound(l0, l1), Self::Bound(r0, r1)) => l0 == r0 && l1 == r1,
1070 (Self::Placeholder(l0), Self::Placeholder(r0)) => l0 == r0,
1071 (Self::Unevaluated(l0), Self::Unevaluated(r0)) => l0 == r0,
1072 (Self::Value(l0), Self::Value(r0)) => l0 == r0,
1073 (Self::Error(l0), Self::Error(r0)) => l0 == r0,
1074 (Self::Expr(l0), Self::Expr(r0)) => l0 == r0,
1075 _ => false,
1076 }
1077 }
1078 }
1079
1080 impl<I: Interner> Eq for ConstKind<I> {}
1081
1082 impl<I: Interner> Clone for ConstKind<I> {
clone(&self) -> Self1083 fn clone(&self) -> Self {
1084 match self {
1085 Self::Param(arg0) => Self::Param(arg0.clone()),
1086 Self::Infer(arg0) => Self::Infer(arg0.clone()),
1087 Self::Bound(arg0, arg1) => Self::Bound(arg0.clone(), arg1.clone()),
1088 Self::Placeholder(arg0) => Self::Placeholder(arg0.clone()),
1089 Self::Unevaluated(arg0) => Self::Unevaluated(arg0.clone()),
1090 Self::Value(arg0) => Self::Value(arg0.clone()),
1091 Self::Error(arg0) => Self::Error(arg0.clone()),
1092 Self::Expr(arg0) => Self::Expr(arg0.clone()),
1093 }
1094 }
1095 }
1096
1097 /// Representation of regions. Note that the NLL checker uses a distinct
1098 /// representation of regions. For this reason, it internally replaces all the
1099 /// regions with inference variables -- the index of the variable is then used
1100 /// to index into internal NLL data structures. See `rustc_const_eval::borrow_check`
1101 /// module for more information.
1102 ///
1103 /// Note: operations are on the wrapper `Region` type, which is interned,
1104 /// rather than this type.
1105 ///
1106 /// ## The Region lattice within a given function
1107 ///
1108 /// In general, the region lattice looks like
1109 ///
1110 /// ```text
1111 /// static ----------+-----...------+ (greatest)
1112 /// | | |
1113 /// early-bound and | |
1114 /// free regions | |
1115 /// | | |
1116 /// | | |
1117 /// empty(root) placeholder(U1) |
1118 /// | / |
1119 /// | / placeholder(Un)
1120 /// empty(U1) -- /
1121 /// | /
1122 /// ... /
1123 /// | /
1124 /// empty(Un) -------- (smallest)
1125 /// ```
1126 ///
1127 /// Early-bound/free regions are the named lifetimes in scope from the
1128 /// function declaration. They have relationships to one another
1129 /// determined based on the declared relationships from the
1130 /// function.
1131 ///
1132 /// Note that inference variables and bound regions are not included
1133 /// in this diagram. In the case of inference variables, they should
1134 /// be inferred to some other region from the diagram. In the case of
1135 /// bound regions, they are excluded because they don't make sense to
1136 /// include -- the diagram indicates the relationship between free
1137 /// regions.
1138 ///
1139 /// ## Inference variables
1140 ///
1141 /// During region inference, we sometimes create inference variables,
1142 /// represented as `ReVar`. These will be inferred by the code in
1143 /// `infer::lexical_region_resolve` to some free region from the
1144 /// lattice above (the minimal region that meets the
1145 /// constraints).
1146 ///
1147 /// During NLL checking, where regions are defined differently, we
1148 /// also use `ReVar` -- in that case, the index is used to index into
1149 /// the NLL region checker's data structures. The variable may in fact
1150 /// represent either a free region or an inference variable, in that
1151 /// case.
1152 ///
1153 /// ## Bound Regions
1154 ///
1155 /// These are regions that are stored behind a binder and must be substituted
1156 /// with some concrete region before being used. There are two kind of
1157 /// bound regions: early-bound, which are bound in an item's `Generics`,
1158 /// and are substituted by an `InternalSubsts`, and late-bound, which are part of
1159 /// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by
1160 /// the likes of `liberate_late_bound_regions`. The distinction exists
1161 /// because higher-ranked lifetimes aren't supported in all places. See [1][2].
1162 ///
1163 /// Unlike `Param`s, bound regions are not supposed to exist "in the wild"
1164 /// outside their binder, e.g., in types passed to type inference, and
1165 /// should first be substituted (by placeholder regions, free regions,
1166 /// or region variables).
1167 ///
1168 /// ## Placeholder and Free Regions
1169 ///
1170 /// One often wants to work with bound regions without knowing their precise
1171 /// identity. For example, when checking a function, the lifetime of a borrow
1172 /// can end up being assigned to some region parameter. In these cases,
1173 /// it must be ensured that bounds on the region can't be accidentally
1174 /// assumed without being checked.
1175 ///
1176 /// To do this, we replace the bound regions with placeholder markers,
1177 /// which don't satisfy any relation not explicitly provided.
1178 ///
1179 /// There are two kinds of placeholder regions in rustc: `ReFree` and
1180 /// `RePlaceholder`. When checking an item's body, `ReFree` is supposed
1181 /// to be used. These also support explicit bounds: both the internally-stored
1182 /// *scope*, which the region is assumed to outlive, as well as other
1183 /// relations stored in the `FreeRegionMap`. Note that these relations
1184 /// aren't checked when you `make_subregion` (or `eq_types`), only by
1185 /// `resolve_regions_and_report_errors`.
1186 ///
1187 /// When working with higher-ranked types, some region relations aren't
1188 /// yet known, so you can't just call `resolve_regions_and_report_errors`.
1189 /// `RePlaceholder` is designed for this purpose. In these contexts,
1190 /// there's also the risk that some inference variable laying around will
1191 /// get unified with your placeholder region: if you want to check whether
1192 /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
1193 /// with a placeholder region `'%a`, the variable `'_` would just be
1194 /// instantiated to the placeholder region `'%a`, which is wrong because
1195 /// the inference variable is supposed to satisfy the relation
1196 /// *for every value of the placeholder region*. To ensure that doesn't
1197 /// happen, you can use `leak_check`. This is more clearly explained
1198 /// by the [rustc dev guide].
1199 ///
1200 /// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
1201 /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
1202 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
1203 pub enum RegionKind<I: Interner> {
1204 /// Region bound in a type or fn declaration which will be
1205 /// substituted 'early' -- that is, at the same time when type
1206 /// parameters are substituted.
1207 ReEarlyBound(I::EarlyBoundRegion),
1208
1209 /// Region bound in a function scope, which will be substituted when the
1210 /// function is called.
1211 ReLateBound(DebruijnIndex, I::BoundRegion),
1212
1213 /// When checking a function body, the types of all arguments and so forth
1214 /// that refer to bound region parameters are modified to refer to free
1215 /// region parameters.
1216 ReFree(I::FreeRegion),
1217
1218 /// Static data that has an "infinite" lifetime. Top in the region lattice.
1219 ReStatic,
1220
1221 /// A region variable. Should not exist outside of type inference.
1222 ReVar(I::RegionVid),
1223
1224 /// A placeholder region -- basically, the higher-ranked version of `ReFree`.
1225 /// Should not exist outside of type inference.
1226 RePlaceholder(I::PlaceholderRegion),
1227
1228 /// Erased region, used by trait selection, in MIR and during codegen.
1229 ReErased,
1230
1231 /// A region that resulted from some other error. Used exclusively for diagnostics.
1232 ReError(I::ErrorGuaranteed),
1233 }
1234
1235 // This is manually implemented for `RegionKind` because `std::mem::discriminant`
1236 // returns an opaque value that is `PartialEq` but not `PartialOrd`
1237 #[inline]
regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize1238 const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
1239 match value {
1240 ReEarlyBound(_) => 0,
1241 ReLateBound(_, _) => 1,
1242 ReFree(_) => 2,
1243 ReStatic => 3,
1244 ReVar(_) => 4,
1245 RePlaceholder(_) => 5,
1246 ReErased => 6,
1247 ReError(_) => 7,
1248 }
1249 }
1250
1251 // This is manually implemented because a derive would require `I: Copy`
1252 impl<I: Interner> Copy for RegionKind<I>
1253 where
1254 I::EarlyBoundRegion: Copy,
1255 I::BoundRegion: Copy,
1256 I::FreeRegion: Copy,
1257 I::RegionVid: Copy,
1258 I::PlaceholderRegion: Copy,
1259 I::ErrorGuaranteed: Copy,
1260 {
1261 }
1262
1263 // This is manually implemented because a derive would require `I: Clone`
1264 impl<I: Interner> Clone for RegionKind<I> {
clone(&self) -> Self1265 fn clone(&self) -> Self {
1266 match self {
1267 ReEarlyBound(r) => ReEarlyBound(r.clone()),
1268 ReLateBound(d, r) => ReLateBound(*d, r.clone()),
1269 ReFree(r) => ReFree(r.clone()),
1270 ReStatic => ReStatic,
1271 ReVar(r) => ReVar(r.clone()),
1272 RePlaceholder(r) => RePlaceholder(r.clone()),
1273 ReErased => ReErased,
1274 ReError(r) => ReError(r.clone()),
1275 }
1276 }
1277 }
1278
1279 // This is manually implemented because a derive would require `I: PartialEq`
1280 impl<I: Interner> PartialEq for RegionKind<I> {
1281 #[inline]
eq(&self, other: &RegionKind<I>) -> bool1282 fn eq(&self, other: &RegionKind<I>) -> bool {
1283 regionkind_discriminant(self) == regionkind_discriminant(other)
1284 && match (self, other) {
1285 (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
1286 (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
1287 (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
1288 (ReStatic, ReStatic) => true,
1289 (ReVar(a_r), ReVar(b_r)) => a_r == b_r,
1290 (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
1291 (ReErased, ReErased) => true,
1292 (ReError(_), ReError(_)) => true,
1293 _ => {
1294 debug_assert!(
1295 false,
1296 "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
1297 );
1298 true
1299 }
1300 }
1301 }
1302 }
1303
1304 // This is manually implemented because a derive would require `I: Eq`
1305 impl<I: Interner> Eq for RegionKind<I> {}
1306
1307 // This is manually implemented because a derive would require `I: PartialOrd`
1308 impl<I: Interner> PartialOrd for RegionKind<I> {
1309 #[inline]
partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering>1310 fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> {
1311 Some(self.cmp(other))
1312 }
1313 }
1314
1315 // This is manually implemented because a derive would require `I: Ord`
1316 impl<I: Interner> Ord for RegionKind<I> {
1317 #[inline]
cmp(&self, other: &RegionKind<I>) -> Ordering1318 fn cmp(&self, other: &RegionKind<I>) -> Ordering {
1319 regionkind_discriminant(self).cmp(®ionkind_discriminant(other)).then_with(|| {
1320 match (self, other) {
1321 (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r),
1322 (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => {
1323 a_d.cmp(b_d).then_with(|| a_r.cmp(b_r))
1324 }
1325 (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r),
1326 (ReStatic, ReStatic) => Ordering::Equal,
1327 (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r),
1328 (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r),
1329 (ReErased, ReErased) => Ordering::Equal,
1330 _ => {
1331 debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
1332 Ordering::Equal
1333 }
1334 }
1335 })
1336 }
1337 }
1338
1339 // This is manually implemented because a derive would require `I: Hash`
1340 impl<I: Interner> hash::Hash for RegionKind<I> {
hash<H: hash::Hasher>(&self, state: &mut H) -> ()1341 fn hash<H: hash::Hasher>(&self, state: &mut H) -> () {
1342 regionkind_discriminant(self).hash(state);
1343 match self {
1344 ReEarlyBound(r) => r.hash(state),
1345 ReLateBound(d, r) => {
1346 d.hash(state);
1347 r.hash(state)
1348 }
1349 ReFree(r) => r.hash(state),
1350 ReStatic => (),
1351 ReVar(r) => r.hash(state),
1352 RePlaceholder(r) => r.hash(state),
1353 ReErased => (),
1354 ReError(_) => (),
1355 }
1356 }
1357 }
1358
1359 // This is manually implemented because a derive would require `I: Debug`
1360 impl<I: Interner> fmt::Debug for RegionKind<I> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1362 match self {
1363 ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
1364
1365 ReLateBound(binder_id, bound_region) => {
1366 write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
1367 }
1368
1369 ReFree(fr) => fr.fmt(f),
1370
1371 ReStatic => f.write_str("ReStatic"),
1372
1373 ReVar(vid) => vid.fmt(f),
1374
1375 RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
1376
1377 ReErased => f.write_str("ReErased"),
1378
1379 ReError(_) => f.write_str("ReError"),
1380 }
1381 }
1382 }
1383
1384 // This is manually implemented because a derive would require `I: Encodable`
1385 impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
1386 where
1387 I::EarlyBoundRegion: Encodable<E>,
1388 I::BoundRegion: Encodable<E>,
1389 I::FreeRegion: Encodable<E>,
1390 I::RegionVid: Encodable<E>,
1391 I::PlaceholderRegion: Encodable<E>,
1392 {
encode(&self, e: &mut E)1393 fn encode(&self, e: &mut E) {
1394 let disc = regionkind_discriminant(self);
1395 match self {
1396 ReEarlyBound(a) => e.emit_enum_variant(disc, |e| {
1397 a.encode(e);
1398 }),
1399 ReLateBound(a, b) => e.emit_enum_variant(disc, |e| {
1400 a.encode(e);
1401 b.encode(e);
1402 }),
1403 ReFree(a) => e.emit_enum_variant(disc, |e| {
1404 a.encode(e);
1405 }),
1406 ReStatic => e.emit_enum_variant(disc, |_| {}),
1407 ReVar(a) => e.emit_enum_variant(disc, |e| {
1408 a.encode(e);
1409 }),
1410 RePlaceholder(a) => e.emit_enum_variant(disc, |e| {
1411 a.encode(e);
1412 }),
1413 ReErased => e.emit_enum_variant(disc, |_| {}),
1414 ReError(_) => e.emit_enum_variant(disc, |_| {}),
1415 }
1416 }
1417 }
1418
1419 // This is manually implemented because a derive would require `I: Decodable`
1420 impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I>
1421 where
1422 I::EarlyBoundRegion: Decodable<D>,
1423 I::BoundRegion: Decodable<D>,
1424 I::FreeRegion: Decodable<D>,
1425 I::RegionVid: Decodable<D>,
1426 I::PlaceholderRegion: Decodable<D>,
1427 I::ErrorGuaranteed: Decodable<D>,
1428 {
decode(d: &mut D) -> Self1429 fn decode(d: &mut D) -> Self {
1430 match Decoder::read_usize(d) {
1431 0 => ReEarlyBound(Decodable::decode(d)),
1432 1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)),
1433 2 => ReFree(Decodable::decode(d)),
1434 3 => ReStatic,
1435 4 => ReVar(Decodable::decode(d)),
1436 5 => RePlaceholder(Decodable::decode(d)),
1437 6 => ReErased,
1438 7 => ReError(Decodable::decode(d)),
1439 _ => panic!(
1440 "{}",
1441 format!(
1442 "invalid enum variant tag while decoding `{}`, expected 0..{}",
1443 "RegionKind", 8,
1444 )
1445 ),
1446 }
1447 }
1448 }
1449
1450 // This is not a derived impl because a derive would require `I: HashStable`
1451 impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
1452 where
1453 I::EarlyBoundRegion: HashStable<CTX>,
1454 I::BoundRegion: HashStable<CTX>,
1455 I::FreeRegion: HashStable<CTX>,
1456 I::RegionVid: HashStable<CTX>,
1457 I::PlaceholderRegion: HashStable<CTX>,
1458 {
1459 #[inline]
hash_stable( &self, hcx: &mut CTX, hasher: &mut rustc_data_structures::stable_hasher::StableHasher, )1460 fn hash_stable(
1461 &self,
1462 hcx: &mut CTX,
1463 hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
1464 ) {
1465 std::mem::discriminant(self).hash_stable(hcx, hasher);
1466 match self {
1467 ReErased | ReStatic | ReError(_) => {
1468 // No variant fields to hash for these ...
1469 }
1470 ReLateBound(d, r) => {
1471 d.hash_stable(hcx, hasher);
1472 r.hash_stable(hcx, hasher);
1473 }
1474 ReEarlyBound(r) => {
1475 r.hash_stable(hcx, hasher);
1476 }
1477 ReFree(r) => {
1478 r.hash_stable(hcx, hasher);
1479 }
1480 RePlaceholder(r) => {
1481 r.hash_stable(hcx, hasher);
1482 }
1483 ReVar(_) => {
1484 panic!("region variables should not be hashed: {self:?}")
1485 }
1486 }
1487 }
1488 }
1489