]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | #![allow(rustc::usage_of_ty_tykind)] |
2 | ||
9c376795 | 3 | use std::cmp::Ordering; |
923072b8 FG |
4 | use std::{fmt, hash}; |
5 | ||
6 | use crate::DebruijnIndex; | |
7 | use crate::FloatTy; | |
f2b60f7d | 8 | use crate::HashStableContext; |
923072b8 FG |
9 | use crate::IntTy; |
10 | use crate::Interner; | |
11 | use crate::TyDecoder; | |
12 | use crate::TyEncoder; | |
13 | use crate::UintTy; | |
923072b8 FG |
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 | ||
f2b60f7d | 21 | /// Specifies how a trait object is represented. |
9c376795 FG |
22 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
23 | #[derive(Encodable, Decodable, HashStable_Generic)] | |
f2b60f7d FG |
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 ptr-sized value | |
30 | /// (often a pointer to the real object, but not necessarily) and `vtable` is a pointer to | |
31 | /// the vtable for `dyn* Trait`. The representation is essentially the same as `&dyn Trait` | |
32 | /// or similar, but the drop function included in the vtable is responsible for freeing the | |
33 | /// underlying storage if needed. This allows a `dyn*` object to be treated agnostically with | |
34 | /// respect to whether it points to a `Box<T>`, `Rc<T>`, etc. | |
35 | DynStar, | |
36 | } | |
37 | ||
9c376795 FG |
38 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
39 | #[derive(Encodable, Decodable, HashStable_Generic)] | |
40 | pub enum AliasKind { | |
41 | Projection, | |
42 | Opaque, | |
43 | } | |
44 | ||
923072b8 FG |
45 | /// Defines the kinds of types used by the type system. |
46 | /// | |
47 | /// Types written by the user start out as `hir::TyKind` and get | |
48 | /// converted to this representation using `AstConv::ast_ty_to_ty`. | |
49 | #[rustc_diagnostic_item = "IrTyKind"] | |
50 | pub enum TyKind<I: Interner> { | |
51 | /// The primitive boolean type. Written as `bool`. | |
52 | Bool, | |
53 | ||
54 | /// The primitive character type; holds a Unicode scalar value | |
55 | /// (a non-surrogate code point). Written as `char`. | |
56 | Char, | |
57 | ||
58 | /// A primitive signed integer type. For example, `i32`. | |
59 | Int(IntTy), | |
60 | ||
61 | /// A primitive unsigned integer type. For example, `u32`. | |
62 | Uint(UintTy), | |
63 | ||
64 | /// A primitive floating-point type. For example, `f64`. | |
65 | Float(FloatTy), | |
66 | ||
67 | /// Algebraic data types (ADT). For example: structures, enumerations and unions. | |
68 | /// | |
69 | /// For example, the type `List<i32>` would be represented using the `AdtDef` | |
70 | /// for `struct List<T>` and the substs `[i32]`. | |
71 | /// | |
72 | /// Note that generic parameters in fields only get lazily substituted | |
73 | /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`. | |
74 | Adt(I::AdtDef, I::SubstsRef), | |
75 | ||
76 | /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. | |
77 | Foreign(I::DefId), | |
78 | ||
79 | /// The pointee of a string slice. Written as `str`. | |
80 | Str, | |
81 | ||
82 | /// An array with the given length. Written as `[T; N]`. | |
83 | Array(I::Ty, I::Const), | |
84 | ||
85 | /// The pointee of an array slice. Written as `[T]`. | |
86 | Slice(I::Ty), | |
87 | ||
88 | /// A raw pointer. Written as `*mut T` or `*const T` | |
89 | RawPtr(I::TypeAndMut), | |
90 | ||
91 | /// A reference; a pointer with an associated lifetime. Written as | |
92 | /// `&'a mut T` or `&'a T`. | |
93 | Ref(I::Region, I::Ty, I::Mutability), | |
94 | ||
95 | /// The anonymous type of a function declaration/definition. Each | |
96 | /// function has a unique type. | |
97 | /// | |
98 | /// For the function `fn foo() -> i32 { 3 }` this type would be | |
99 | /// shown to the user as `fn() -> i32 {foo}`. | |
100 | /// | |
101 | /// For example the type of `bar` here: | |
102 | /// ```rust | |
103 | /// fn foo() -> i32 { 1 } | |
104 | /// let bar = foo; // bar: fn() -> i32 {foo} | |
105 | /// ``` | |
106 | FnDef(I::DefId, I::SubstsRef), | |
107 | ||
108 | /// A pointer to a function. Written as `fn() -> i32`. | |
109 | /// | |
110 | /// Note that both functions and closures start out as either | |
111 | /// [FnDef] or [Closure] which can be then be coerced to this variant. | |
112 | /// | |
113 | /// For example the type of `bar` here: | |
114 | /// | |
115 | /// ```rust | |
116 | /// fn foo() -> i32 { 1 } | |
117 | /// let bar: fn() -> i32 = foo; | |
118 | /// ``` | |
119 | FnPtr(I::PolyFnSig), | |
120 | ||
121 | /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. | |
f2b60f7d | 122 | Dynamic(I::ListBinderExistentialPredicate, I::Region, DynKind), |
923072b8 FG |
123 | |
124 | /// The anonymous type of a closure. Used to represent the type of `|a| a`. | |
125 | /// | |
126 | /// Closure substs contain both the - potentially substituted - generic parameters | |
127 | /// of its parent and some synthetic parameters. See the documentation for | |
128 | /// `ClosureSubsts` for more details. | |
129 | Closure(I::DefId, I::SubstsRef), | |
130 | ||
131 | /// The anonymous type of a generator. Used to represent the type of | |
132 | /// `|a| yield a`. | |
133 | /// | |
134 | /// For more info about generator substs, visit the documentation for | |
135 | /// `GeneratorSubsts`. | |
136 | Generator(I::DefId, I::SubstsRef, I::Movability), | |
137 | ||
138 | /// A type representing the types stored inside a generator. | |
139 | /// This should only appear as part of the `GeneratorSubsts`. | |
140 | /// | |
141 | /// Note that the captured variables for generators are stored separately | |
142 | /// using a tuple in the same way as for closures. | |
143 | /// | |
144 | /// Unlike upvars, the witness can reference lifetimes from | |
145 | /// inside of the generator itself. To deal with them in | |
146 | /// the type of the generator, we convert them to higher ranked | |
147 | /// lifetimes bound by the witness itself. | |
148 | /// | |
149 | /// Looking at the following example, the witness for this generator | |
150 | /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`: | |
151 | /// | |
152 | /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?) | |
153 | /// #![feature(generators)] | |
154 | /// |a| { | |
155 | /// let x = &vec![3]; | |
156 | /// yield a; | |
157 | /// yield x[0]; | |
158 | /// } | |
159 | /// # ; | |
160 | /// ``` | |
161 | GeneratorWitness(I::BinderListTy), | |
162 | ||
163 | /// The never type `!`. | |
164 | Never, | |
165 | ||
166 | /// A tuple type. For example, `(i32, bool)`. | |
167 | Tuple(I::ListTy), | |
168 | ||
9c376795 FG |
169 | /// A projection or opaque type. Both of these types |
170 | Alias(AliasKind, I::AliasTy), | |
923072b8 FG |
171 | |
172 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`. | |
173 | Param(I::ParamTy), | |
174 | ||
175 | /// Bound type variable, used to represent the `'a` in `for<'a> fn(&'a ())`. | |
176 | /// | |
177 | /// For canonical queries, we replace inference variables with bound variables, | |
178 | /// so e.g. when checking whether `&'_ (): Trait<_>` holds, we canonicalize that to | |
179 | /// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables | |
180 | /// back to inference variables in a new inference context when inside of the query. | |
181 | /// | |
182 | /// See the `rustc-dev-guide` for more details about | |
183 | /// [higher-ranked trait bounds][1] and [canonical queries][2]. | |
184 | /// | |
185 | /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html | |
186 | /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html | |
187 | Bound(DebruijnIndex, I::BoundTy), | |
188 | ||
189 | /// A placeholder type, used during higher ranked subtyping to instantiate | |
190 | /// bound variables. | |
191 | Placeholder(I::PlaceholderType), | |
192 | ||
193 | /// A type variable used during type checking. | |
194 | /// | |
195 | /// Similar to placeholders, inference variables also live in a universe to | |
196 | /// correctly deal with higher ranked types. Though unlike placeholders, | |
197 | /// that universe is stored in the `InferCtxt` instead of directly | |
198 | /// inside of the type. | |
199 | Infer(I::InferTy), | |
200 | ||
201 | /// A placeholder for a type which could not be computed; this is | |
202 | /// propagated to avoid useless error messages. | |
487cf647 | 203 | Error(I::ErrorGuaranteed), |
923072b8 FG |
204 | } |
205 | ||
206 | impl<I: Interner> TyKind<I> { | |
207 | #[inline] | |
208 | pub fn is_primitive(&self) -> bool { | |
209 | matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_)) | |
210 | } | |
211 | } | |
212 | ||
213 | // This is manually implemented for `TyKind` because `std::mem::discriminant` | |
214 | // returns an opaque value that is `PartialEq` but not `PartialOrd` | |
215 | #[inline] | |
216 | const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize { | |
217 | match value { | |
218 | Bool => 0, | |
219 | Char => 1, | |
220 | Int(_) => 2, | |
221 | Uint(_) => 3, | |
222 | Float(_) => 4, | |
223 | Adt(_, _) => 5, | |
224 | Foreign(_) => 6, | |
225 | Str => 7, | |
226 | Array(_, _) => 8, | |
227 | Slice(_) => 9, | |
228 | RawPtr(_) => 10, | |
229 | Ref(_, _, _) => 11, | |
230 | FnDef(_, _) => 12, | |
231 | FnPtr(_) => 13, | |
f2b60f7d | 232 | Dynamic(..) => 14, |
923072b8 FG |
233 | Closure(_, _) => 15, |
234 | Generator(_, _, _) => 16, | |
235 | GeneratorWitness(_) => 17, | |
236 | Never => 18, | |
237 | Tuple(_) => 19, | |
9c376795 FG |
238 | Alias(_, _) => 20, |
239 | Param(_) => 21, | |
240 | Bound(_, _) => 22, | |
241 | Placeholder(_) => 23, | |
242 | Infer(_) => 24, | |
243 | Error(_) => 25, | |
923072b8 FG |
244 | } |
245 | } | |
246 | ||
247 | // This is manually implemented because a derive would require `I: Clone` | |
248 | impl<I: Interner> Clone for TyKind<I> { | |
249 | fn clone(&self) -> Self { | |
250 | match self { | |
251 | Bool => Bool, | |
252 | Char => Char, | |
9c376795 FG |
253 | Int(i) => Int(*i), |
254 | Uint(u) => Uint(*u), | |
255 | Float(f) => Float(*f), | |
923072b8 FG |
256 | Adt(d, s) => Adt(d.clone(), s.clone()), |
257 | Foreign(d) => Foreign(d.clone()), | |
258 | Str => Str, | |
259 | Array(t, c) => Array(t.clone(), c.clone()), | |
260 | Slice(t) => Slice(t.clone()), | |
261 | RawPtr(t) => RawPtr(t.clone()), | |
262 | Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()), | |
263 | FnDef(d, s) => FnDef(d.clone(), s.clone()), | |
264 | FnPtr(s) => FnPtr(s.clone()), | |
9c376795 | 265 | Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr), |
923072b8 FG |
266 | Closure(d, s) => Closure(d.clone(), s.clone()), |
267 | Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()), | |
268 | GeneratorWitness(g) => GeneratorWitness(g.clone()), | |
269 | Never => Never, | |
270 | Tuple(t) => Tuple(t.clone()), | |
9c376795 | 271 | Alias(k, p) => Alias(*k, p.clone()), |
923072b8 | 272 | Param(p) => Param(p.clone()), |
9c376795 | 273 | Bound(d, b) => Bound(*d, b.clone()), |
923072b8 FG |
274 | Placeholder(p) => Placeholder(p.clone()), |
275 | Infer(t) => Infer(t.clone()), | |
276 | Error(e) => Error(e.clone()), | |
277 | } | |
278 | } | |
279 | } | |
280 | ||
281 | // This is manually implemented because a derive would require `I: PartialEq` | |
282 | impl<I: Interner> PartialEq for TyKind<I> { | |
283 | #[inline] | |
284 | fn eq(&self, other: &TyKind<I>) -> bool { | |
487cf647 FG |
285 | tykind_discriminant(self) == tykind_discriminant(other) |
286 | && match (self, other) { | |
287 | (Int(a_i), Int(b_i)) => a_i == b_i, | |
288 | (Uint(a_u), Uint(b_u)) => a_u == b_u, | |
289 | (Float(a_f), Float(b_f)) => a_f == b_f, | |
290 | (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s, | |
291 | (Foreign(a_d), Foreign(b_d)) => a_d == b_d, | |
292 | (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c, | |
293 | (Slice(a_t), Slice(b_t)) => a_t == b_t, | |
294 | (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t, | |
295 | (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, | |
296 | (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s, | |
297 | (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s, | |
298 | (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => { | |
299 | a_p == b_p && a_r == b_r && a_repr == b_repr | |
923072b8 | 300 | } |
487cf647 FG |
301 | (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s, |
302 | (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => { | |
303 | a_d == b_d && a_s == b_s && a_m == b_m | |
923072b8 | 304 | } |
487cf647 FG |
305 | (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g, |
306 | (Tuple(a_t), Tuple(b_t)) => a_t == b_t, | |
9c376795 | 307 | (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p, |
487cf647 FG |
308 | (Param(a_p), Param(b_p)) => a_p == b_p, |
309 | (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b, | |
310 | (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p, | |
311 | (Infer(a_t), Infer(b_t)) => a_t == b_t, | |
312 | (Error(a_e), Error(b_e)) => a_e == b_e, | |
313 | (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true, | |
314 | _ => { | |
315 | debug_assert!( | |
316 | false, | |
317 | "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}" | |
318 | ); | |
319 | true | |
923072b8 | 320 | } |
923072b8 | 321 | } |
923072b8 FG |
322 | } |
323 | } | |
324 | ||
325 | // This is manually implemented because a derive would require `I: Eq` | |
326 | impl<I: Interner> Eq for TyKind<I> {} | |
327 | ||
328 | // This is manually implemented because a derive would require `I: PartialOrd` | |
329 | impl<I: Interner> PartialOrd for TyKind<I> { | |
330 | #[inline] | |
331 | fn partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering> { | |
487cf647 | 332 | Some(self.cmp(other)) |
923072b8 FG |
333 | } |
334 | } | |
335 | ||
336 | // This is manually implemented because a derive would require `I: Ord` | |
337 | impl<I: Interner> Ord for TyKind<I> { | |
338 | #[inline] | |
339 | fn cmp(&self, other: &TyKind<I>) -> Ordering { | |
487cf647 FG |
340 | tykind_discriminant(self).cmp(&tykind_discriminant(other)).then_with(|| { |
341 | match (self, other) { | |
342 | (Int(a_i), Int(b_i)) => a_i.cmp(b_i), | |
343 | (Uint(a_u), Uint(b_u)) => a_u.cmp(b_u), | |
344 | (Float(a_f), Float(b_f)) => a_f.cmp(b_f), | |
345 | (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), | |
346 | (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d), | |
347 | (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)), | |
348 | (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t), | |
349 | (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t), | |
350 | (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => { | |
351 | a_r.cmp(b_r).then_with(|| a_t.cmp(b_t).then_with(|| a_m.cmp(b_m))) | |
923072b8 | 352 | } |
487cf647 FG |
353 | (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), |
354 | (FnPtr(a_s), FnPtr(b_s)) => a_s.cmp(b_s), | |
355 | (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => { | |
356 | a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr))) | |
923072b8 | 357 | } |
487cf647 FG |
358 | (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)), |
359 | (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => { | |
360 | a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m))) | |
923072b8 | 361 | } |
487cf647 FG |
362 | (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g), |
363 | (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t), | |
9c376795 | 364 | (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)), |
487cf647 FG |
365 | (Param(a_p), Param(b_p)) => a_p.cmp(b_p), |
366 | (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)), | |
367 | (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p), | |
368 | (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t), | |
369 | (Error(a_e), Error(b_e)) => a_e.cmp(b_e), | |
370 | (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal, | |
371 | _ => { | |
372 | debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"); | |
373 | Ordering::Equal | |
923072b8 | 374 | } |
923072b8 | 375 | } |
487cf647 | 376 | }) |
923072b8 FG |
377 | } |
378 | } | |
379 | ||
380 | // This is manually implemented because a derive would require `I: Hash` | |
381 | impl<I: Interner> hash::Hash for TyKind<I> { | |
382 | fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () { | |
487cf647 FG |
383 | tykind_discriminant(self).hash(state); |
384 | match self { | |
385 | Int(i) => i.hash(state), | |
386 | Uint(u) => u.hash(state), | |
387 | Float(f) => f.hash(state), | |
388 | Adt(d, s) => { | |
389 | d.hash(state); | |
390 | s.hash(state) | |
391 | } | |
392 | Foreign(d) => d.hash(state), | |
393 | Array(t, c) => { | |
394 | t.hash(state); | |
395 | c.hash(state) | |
923072b8 | 396 | } |
487cf647 FG |
397 | Slice(t) => t.hash(state), |
398 | RawPtr(t) => t.hash(state), | |
399 | Ref(r, t, m) => { | |
400 | r.hash(state); | |
401 | t.hash(state); | |
402 | m.hash(state) | |
403 | } | |
404 | FnDef(d, s) => { | |
405 | d.hash(state); | |
406 | s.hash(state) | |
407 | } | |
408 | FnPtr(s) => s.hash(state), | |
409 | Dynamic(p, r, repr) => { | |
410 | p.hash(state); | |
411 | r.hash(state); | |
412 | repr.hash(state) | |
413 | } | |
414 | Closure(d, s) => { | |
415 | d.hash(state); | |
416 | s.hash(state) | |
417 | } | |
418 | Generator(d, s, m) => { | |
419 | d.hash(state); | |
420 | s.hash(state); | |
421 | m.hash(state) | |
422 | } | |
423 | GeneratorWitness(g) => g.hash(state), | |
424 | Tuple(t) => t.hash(state), | |
9c376795 FG |
425 | Alias(i, p) => { |
426 | i.hash(state); | |
427 | p.hash(state); | |
487cf647 FG |
428 | } |
429 | Param(p) => p.hash(state), | |
430 | Bound(d, b) => { | |
431 | d.hash(state); | |
432 | b.hash(state) | |
923072b8 | 433 | } |
487cf647 FG |
434 | Placeholder(p) => p.hash(state), |
435 | Infer(t) => t.hash(state), | |
436 | Error(e) => e.hash(state), | |
437 | Bool | Char | Str | Never => (), | |
923072b8 FG |
438 | } |
439 | } | |
440 | } | |
441 | ||
442 | // This is manually implemented because a derive would require `I: Debug` | |
443 | impl<I: Interner> fmt::Debug for TyKind<I> { | |
444 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
064997fb | 445 | match self { |
487cf647 FG |
446 | Bool => f.write_str("Bool"), |
447 | Char => f.write_str("Char"), | |
448 | Int(i) => f.debug_tuple_field1_finish("Int", i), | |
449 | Uint(u) => f.debug_tuple_field1_finish("Uint", u), | |
450 | Float(float) => f.debug_tuple_field1_finish("Float", float), | |
451 | Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s), | |
452 | Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), | |
453 | Str => f.write_str("Str"), | |
454 | Array(t, c) => f.debug_tuple_field2_finish("Array", t, c), | |
455 | Slice(t) => f.debug_tuple_field1_finish("Slice", t), | |
456 | RawPtr(t) => f.debug_tuple_field1_finish("RawPtr", t), | |
457 | Ref(r, t, m) => f.debug_tuple_field3_finish("Ref", r, t, m), | |
458 | FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s), | |
459 | FnPtr(s) => f.debug_tuple_field1_finish("FnPtr", s), | |
460 | Dynamic(p, r, repr) => f.debug_tuple_field3_finish("Dynamic", p, r, repr), | |
461 | Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s), | |
462 | Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m), | |
463 | GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g), | |
464 | Never => f.write_str("Never"), | |
465 | Tuple(t) => f.debug_tuple_field1_finish("Tuple", t), | |
9c376795 | 466 | Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a), |
487cf647 FG |
467 | Param(p) => f.debug_tuple_field1_finish("Param", p), |
468 | Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b), | |
469 | Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p), | |
470 | Infer(t) => f.debug_tuple_field1_finish("Infer", t), | |
471 | TyKind::Error(e) => f.debug_tuple_field1_finish("Error", e), | |
923072b8 FG |
472 | } |
473 | } | |
474 | } | |
475 | ||
476 | // This is manually implemented because a derive would require `I: Encodable` | |
477 | impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I> | |
478 | where | |
487cf647 | 479 | I::ErrorGuaranteed: Encodable<E>, |
923072b8 FG |
480 | I::AdtDef: Encodable<E>, |
481 | I::SubstsRef: Encodable<E>, | |
482 | I::DefId: Encodable<E>, | |
483 | I::Ty: Encodable<E>, | |
484 | I::Const: Encodable<E>, | |
485 | I::Region: Encodable<E>, | |
486 | I::TypeAndMut: Encodable<E>, | |
487 | I::Mutability: Encodable<E>, | |
488 | I::Movability: Encodable<E>, | |
489 | I::PolyFnSig: Encodable<E>, | |
490 | I::ListBinderExistentialPredicate: Encodable<E>, | |
491 | I::BinderListTy: Encodable<E>, | |
492 | I::ListTy: Encodable<E>, | |
9c376795 | 493 | I::AliasTy: Encodable<E>, |
923072b8 FG |
494 | I::ParamTy: Encodable<E>, |
495 | I::BoundTy: Encodable<E>, | |
496 | I::PlaceholderType: Encodable<E>, | |
497 | I::InferTy: Encodable<E>, | |
923072b8 FG |
498 | I::PredicateKind: Encodable<E>, |
499 | I::AllocId: Encodable<E>, | |
500 | { | |
501 | fn encode(&self, e: &mut E) { | |
502 | let disc = tykind_discriminant(self); | |
503 | match self { | |
504 | Bool => e.emit_enum_variant(disc, |_| {}), | |
505 | Char => e.emit_enum_variant(disc, |_| {}), | |
506 | Int(i) => e.emit_enum_variant(disc, |e| { | |
507 | i.encode(e); | |
508 | }), | |
509 | Uint(u) => e.emit_enum_variant(disc, |e| { | |
510 | u.encode(e); | |
511 | }), | |
512 | Float(f) => e.emit_enum_variant(disc, |e| { | |
513 | f.encode(e); | |
514 | }), | |
515 | Adt(adt, substs) => e.emit_enum_variant(disc, |e| { | |
516 | adt.encode(e); | |
517 | substs.encode(e); | |
518 | }), | |
519 | Foreign(def_id) => e.emit_enum_variant(disc, |e| { | |
520 | def_id.encode(e); | |
521 | }), | |
522 | Str => e.emit_enum_variant(disc, |_| {}), | |
523 | Array(t, c) => e.emit_enum_variant(disc, |e| { | |
524 | t.encode(e); | |
525 | c.encode(e); | |
526 | }), | |
527 | Slice(t) => e.emit_enum_variant(disc, |e| { | |
528 | t.encode(e); | |
529 | }), | |
530 | RawPtr(tam) => e.emit_enum_variant(disc, |e| { | |
531 | tam.encode(e); | |
532 | }), | |
533 | Ref(r, t, m) => e.emit_enum_variant(disc, |e| { | |
534 | r.encode(e); | |
535 | t.encode(e); | |
536 | m.encode(e); | |
537 | }), | |
538 | FnDef(def_id, substs) => e.emit_enum_variant(disc, |e| { | |
539 | def_id.encode(e); | |
540 | substs.encode(e); | |
541 | }), | |
542 | FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| { | |
543 | polyfnsig.encode(e); | |
544 | }), | |
f2b60f7d | 545 | Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| { |
923072b8 FG |
546 | l.encode(e); |
547 | r.encode(e); | |
f2b60f7d | 548 | repr.encode(e); |
923072b8 FG |
549 | }), |
550 | Closure(def_id, substs) => e.emit_enum_variant(disc, |e| { | |
551 | def_id.encode(e); | |
552 | substs.encode(e); | |
553 | }), | |
554 | Generator(def_id, substs, m) => e.emit_enum_variant(disc, |e| { | |
555 | def_id.encode(e); | |
556 | substs.encode(e); | |
557 | m.encode(e); | |
558 | }), | |
559 | GeneratorWitness(b) => e.emit_enum_variant(disc, |e| { | |
560 | b.encode(e); | |
561 | }), | |
562 | Never => e.emit_enum_variant(disc, |_| {}), | |
563 | Tuple(substs) => e.emit_enum_variant(disc, |e| { | |
564 | substs.encode(e); | |
565 | }), | |
9c376795 FG |
566 | Alias(k, p) => e.emit_enum_variant(disc, |e| { |
567 | k.encode(e); | |
923072b8 FG |
568 | p.encode(e); |
569 | }), | |
923072b8 FG |
570 | Param(p) => e.emit_enum_variant(disc, |e| { |
571 | p.encode(e); | |
572 | }), | |
573 | Bound(d, b) => e.emit_enum_variant(disc, |e| { | |
574 | d.encode(e); | |
575 | b.encode(e); | |
576 | }), | |
577 | Placeholder(p) => e.emit_enum_variant(disc, |e| { | |
578 | p.encode(e); | |
579 | }), | |
580 | Infer(i) => e.emit_enum_variant(disc, |e| { | |
581 | i.encode(e); | |
582 | }), | |
583 | Error(d) => e.emit_enum_variant(disc, |e| { | |
584 | d.encode(e); | |
585 | }), | |
586 | } | |
587 | } | |
588 | } | |
589 | ||
590 | // This is manually implemented because a derive would require `I: Decodable` | |
591 | impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I> | |
592 | where | |
487cf647 | 593 | I::ErrorGuaranteed: Decodable<D>, |
923072b8 FG |
594 | I::AdtDef: Decodable<D>, |
595 | I::SubstsRef: Decodable<D>, | |
596 | I::DefId: Decodable<D>, | |
597 | I::Ty: Decodable<D>, | |
598 | I::Const: Decodable<D>, | |
599 | I::Region: Decodable<D>, | |
600 | I::TypeAndMut: Decodable<D>, | |
601 | I::Mutability: Decodable<D>, | |
602 | I::Movability: Decodable<D>, | |
603 | I::PolyFnSig: Decodable<D>, | |
604 | I::ListBinderExistentialPredicate: Decodable<D>, | |
605 | I::BinderListTy: Decodable<D>, | |
606 | I::ListTy: Decodable<D>, | |
9c376795 | 607 | I::AliasTy: Decodable<D>, |
923072b8 | 608 | I::ParamTy: Decodable<D>, |
9c376795 | 609 | I::AliasTy: Decodable<D>, |
923072b8 FG |
610 | I::BoundTy: Decodable<D>, |
611 | I::PlaceholderType: Decodable<D>, | |
612 | I::InferTy: Decodable<D>, | |
923072b8 FG |
613 | I::PredicateKind: Decodable<D>, |
614 | I::AllocId: Decodable<D>, | |
615 | { | |
616 | fn decode(d: &mut D) -> Self { | |
617 | match Decoder::read_usize(d) { | |
618 | 0 => Bool, | |
619 | 1 => Char, | |
620 | 2 => Int(Decodable::decode(d)), | |
621 | 3 => Uint(Decodable::decode(d)), | |
622 | 4 => Float(Decodable::decode(d)), | |
623 | 5 => Adt(Decodable::decode(d), Decodable::decode(d)), | |
624 | 6 => Foreign(Decodable::decode(d)), | |
625 | 7 => Str, | |
626 | 8 => Array(Decodable::decode(d), Decodable::decode(d)), | |
627 | 9 => Slice(Decodable::decode(d)), | |
628 | 10 => RawPtr(Decodable::decode(d)), | |
629 | 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), | |
630 | 12 => FnDef(Decodable::decode(d), Decodable::decode(d)), | |
631 | 13 => FnPtr(Decodable::decode(d)), | |
f2b60f7d | 632 | 14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), |
923072b8 FG |
633 | 15 => Closure(Decodable::decode(d), Decodable::decode(d)), |
634 | 16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), | |
635 | 17 => GeneratorWitness(Decodable::decode(d)), | |
636 | 18 => Never, | |
637 | 19 => Tuple(Decodable::decode(d)), | |
9c376795 FG |
638 | 20 => Alias(Decodable::decode(d), Decodable::decode(d)), |
639 | 21 => Param(Decodable::decode(d)), | |
640 | 22 => Bound(Decodable::decode(d), Decodable::decode(d)), | |
641 | 23 => Placeholder(Decodable::decode(d)), | |
642 | 24 => Infer(Decodable::decode(d)), | |
643 | 25 => Error(Decodable::decode(d)), | |
923072b8 FG |
644 | _ => panic!( |
645 | "{}", | |
646 | format!( | |
647 | "invalid enum variant tag while decoding `{}`, expected 0..{}", | |
648 | "TyKind", 27, | |
649 | ) | |
650 | ), | |
651 | } | |
652 | } | |
653 | } | |
654 | ||
655 | // This is not a derived impl because a derive would require `I: HashStable` | |
656 | #[allow(rustc::usage_of_ty_tykind)] | |
f2b60f7d | 657 | impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I> |
923072b8 FG |
658 | where |
659 | I::AdtDef: HashStable<CTX>, | |
660 | I::DefId: HashStable<CTX>, | |
661 | I::SubstsRef: HashStable<CTX>, | |
662 | I::Ty: HashStable<CTX>, | |
663 | I::Const: HashStable<CTX>, | |
664 | I::TypeAndMut: HashStable<CTX>, | |
665 | I::PolyFnSig: HashStable<CTX>, | |
666 | I::ListBinderExistentialPredicate: HashStable<CTX>, | |
667 | I::Region: HashStable<CTX>, | |
668 | I::Movability: HashStable<CTX>, | |
669 | I::Mutability: HashStable<CTX>, | |
670 | I::BinderListTy: HashStable<CTX>, | |
671 | I::ListTy: HashStable<CTX>, | |
9c376795 | 672 | I::AliasTy: HashStable<CTX>, |
923072b8 FG |
673 | I::BoundTy: HashStable<CTX>, |
674 | I::ParamTy: HashStable<CTX>, | |
675 | I::PlaceholderType: HashStable<CTX>, | |
676 | I::InferTy: HashStable<CTX>, | |
487cf647 | 677 | I::ErrorGuaranteed: HashStable<CTX>, |
923072b8 FG |
678 | { |
679 | #[inline] | |
680 | fn hash_stable( | |
681 | &self, | |
682 | __hcx: &mut CTX, | |
683 | __hasher: &mut rustc_data_structures::stable_hasher::StableHasher, | |
684 | ) { | |
685 | std::mem::discriminant(self).hash_stable(__hcx, __hasher); | |
686 | match self { | |
687 | Bool => {} | |
688 | Char => {} | |
689 | Int(i) => { | |
690 | i.hash_stable(__hcx, __hasher); | |
691 | } | |
692 | Uint(u) => { | |
693 | u.hash_stable(__hcx, __hasher); | |
694 | } | |
695 | Float(f) => { | |
696 | f.hash_stable(__hcx, __hasher); | |
697 | } | |
698 | Adt(adt, substs) => { | |
699 | adt.hash_stable(__hcx, __hasher); | |
700 | substs.hash_stable(__hcx, __hasher); | |
701 | } | |
702 | Foreign(def_id) => { | |
703 | def_id.hash_stable(__hcx, __hasher); | |
704 | } | |
705 | Str => {} | |
706 | Array(t, c) => { | |
707 | t.hash_stable(__hcx, __hasher); | |
708 | c.hash_stable(__hcx, __hasher); | |
709 | } | |
710 | Slice(t) => { | |
711 | t.hash_stable(__hcx, __hasher); | |
712 | } | |
713 | RawPtr(tam) => { | |
714 | tam.hash_stable(__hcx, __hasher); | |
715 | } | |
716 | Ref(r, t, m) => { | |
717 | r.hash_stable(__hcx, __hasher); | |
718 | t.hash_stable(__hcx, __hasher); | |
719 | m.hash_stable(__hcx, __hasher); | |
720 | } | |
721 | FnDef(def_id, substs) => { | |
722 | def_id.hash_stable(__hcx, __hasher); | |
723 | substs.hash_stable(__hcx, __hasher); | |
724 | } | |
725 | FnPtr(polyfnsig) => { | |
726 | polyfnsig.hash_stable(__hcx, __hasher); | |
727 | } | |
f2b60f7d | 728 | Dynamic(l, r, repr) => { |
923072b8 FG |
729 | l.hash_stable(__hcx, __hasher); |
730 | r.hash_stable(__hcx, __hasher); | |
f2b60f7d | 731 | repr.hash_stable(__hcx, __hasher); |
923072b8 FG |
732 | } |
733 | Closure(def_id, substs) => { | |
734 | def_id.hash_stable(__hcx, __hasher); | |
735 | substs.hash_stable(__hcx, __hasher); | |
736 | } | |
737 | Generator(def_id, substs, m) => { | |
738 | def_id.hash_stable(__hcx, __hasher); | |
739 | substs.hash_stable(__hcx, __hasher); | |
740 | m.hash_stable(__hcx, __hasher); | |
741 | } | |
742 | GeneratorWitness(b) => { | |
743 | b.hash_stable(__hcx, __hasher); | |
744 | } | |
745 | Never => {} | |
746 | Tuple(substs) => { | |
747 | substs.hash_stable(__hcx, __hasher); | |
748 | } | |
9c376795 FG |
749 | Alias(k, p) => { |
750 | k.hash_stable(__hcx, __hasher); | |
923072b8 FG |
751 | p.hash_stable(__hcx, __hasher); |
752 | } | |
923072b8 FG |
753 | Param(p) => { |
754 | p.hash_stable(__hcx, __hasher); | |
755 | } | |
756 | Bound(d, b) => { | |
757 | d.hash_stable(__hcx, __hasher); | |
758 | b.hash_stable(__hcx, __hasher); | |
759 | } | |
760 | Placeholder(p) => { | |
761 | p.hash_stable(__hcx, __hasher); | |
762 | } | |
763 | Infer(i) => { | |
764 | i.hash_stable(__hcx, __hasher); | |
765 | } | |
766 | Error(d) => { | |
767 | d.hash_stable(__hcx, __hasher); | |
768 | } | |
769 | } | |
770 | } | |
771 | } | |
772 | ||
773 | /// Representation of regions. Note that the NLL checker uses a distinct | |
774 | /// representation of regions. For this reason, it internally replaces all the | |
775 | /// regions with inference variables -- the index of the variable is then used | |
776 | /// to index into internal NLL data structures. See `rustc_const_eval::borrow_check` | |
777 | /// module for more information. | |
778 | /// | |
779 | /// Note: operations are on the wrapper `Region` type, which is interned, | |
780 | /// rather than this type. | |
781 | /// | |
782 | /// ## The Region lattice within a given function | |
783 | /// | |
784 | /// In general, the region lattice looks like | |
785 | /// | |
786 | /// ```text | |
787 | /// static ----------+-----...------+ (greatest) | |
788 | /// | | | | |
789 | /// early-bound and | | | |
790 | /// free regions | | | |
791 | /// | | | | |
792 | /// | | | | |
793 | /// empty(root) placeholder(U1) | | |
794 | /// | / | | |
795 | /// | / placeholder(Un) | |
796 | /// empty(U1) -- / | |
797 | /// | / | |
798 | /// ... / | |
799 | /// | / | |
800 | /// empty(Un) -------- (smallest) | |
801 | /// ``` | |
802 | /// | |
803 | /// Early-bound/free regions are the named lifetimes in scope from the | |
804 | /// function declaration. They have relationships to one another | |
805 | /// determined based on the declared relationships from the | |
806 | /// function. | |
807 | /// | |
808 | /// Note that inference variables and bound regions are not included | |
809 | /// in this diagram. In the case of inference variables, they should | |
9c376795 | 810 | /// be inferred to some other region from the diagram. In the case of |
923072b8 FG |
811 | /// bound regions, they are excluded because they don't make sense to |
812 | /// include -- the diagram indicates the relationship between free | |
813 | /// regions. | |
814 | /// | |
815 | /// ## Inference variables | |
816 | /// | |
817 | /// During region inference, we sometimes create inference variables, | |
818 | /// represented as `ReVar`. These will be inferred by the code in | |
819 | /// `infer::lexical_region_resolve` to some free region from the | |
820 | /// lattice above (the minimal region that meets the | |
821 | /// constraints). | |
822 | /// | |
823 | /// During NLL checking, where regions are defined differently, we | |
824 | /// also use `ReVar` -- in that case, the index is used to index into | |
825 | /// the NLL region checker's data structures. The variable may in fact | |
826 | /// represent either a free region or an inference variable, in that | |
827 | /// case. | |
828 | /// | |
829 | /// ## Bound Regions | |
830 | /// | |
831 | /// These are regions that are stored behind a binder and must be substituted | |
832 | /// with some concrete region before being used. There are two kind of | |
833 | /// bound regions: early-bound, which are bound in an item's `Generics`, | |
834 | /// and are substituted by an `InternalSubsts`, and late-bound, which are part of | |
835 | /// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by | |
836 | /// the likes of `liberate_late_bound_regions`. The distinction exists | |
837 | /// because higher-ranked lifetimes aren't supported in all places. See [1][2]. | |
838 | /// | |
839 | /// Unlike `Param`s, bound regions are not supposed to exist "in the wild" | |
840 | /// outside their binder, e.g., in types passed to type inference, and | |
841 | /// should first be substituted (by placeholder regions, free regions, | |
842 | /// or region variables). | |
843 | /// | |
844 | /// ## Placeholder and Free Regions | |
845 | /// | |
846 | /// One often wants to work with bound regions without knowing their precise | |
847 | /// identity. For example, when checking a function, the lifetime of a borrow | |
848 | /// can end up being assigned to some region parameter. In these cases, | |
849 | /// it must be ensured that bounds on the region can't be accidentally | |
850 | /// assumed without being checked. | |
851 | /// | |
852 | /// To do this, we replace the bound regions with placeholder markers, | |
853 | /// which don't satisfy any relation not explicitly provided. | |
854 | /// | |
855 | /// There are two kinds of placeholder regions in rustc: `ReFree` and | |
856 | /// `RePlaceholder`. When checking an item's body, `ReFree` is supposed | |
857 | /// to be used. These also support explicit bounds: both the internally-stored | |
858 | /// *scope*, which the region is assumed to outlive, as well as other | |
859 | /// relations stored in the `FreeRegionMap`. Note that these relations | |
860 | /// aren't checked when you `make_subregion` (or `eq_types`), only by | |
861 | /// `resolve_regions_and_report_errors`. | |
862 | /// | |
863 | /// When working with higher-ranked types, some region relations aren't | |
864 | /// yet known, so you can't just call `resolve_regions_and_report_errors`. | |
865 | /// `RePlaceholder` is designed for this purpose. In these contexts, | |
866 | /// there's also the risk that some inference variable laying around will | |
867 | /// get unified with your placeholder region: if you want to check whether | |
868 | /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a` | |
869 | /// with a placeholder region `'%a`, the variable `'_` would just be | |
870 | /// instantiated to the placeholder region `'%a`, which is wrong because | |
871 | /// the inference variable is supposed to satisfy the relation | |
872 | /// *for every value of the placeholder region*. To ensure that doesn't | |
873 | /// happen, you can use `leak_check`. This is more clearly explained | |
874 | /// by the [rustc dev guide]. | |
875 | /// | |
876 | /// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ | |
877 | /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ | |
878 | /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html | |
879 | pub enum RegionKind<I: Interner> { | |
880 | /// Region bound in a type or fn declaration which will be | |
881 | /// substituted 'early' -- that is, at the same time when type | |
882 | /// parameters are substituted. | |
883 | ReEarlyBound(I::EarlyBoundRegion), | |
884 | ||
885 | /// Region bound in a function scope, which will be substituted when the | |
886 | /// function is called. | |
887 | ReLateBound(DebruijnIndex, I::BoundRegion), | |
888 | ||
889 | /// When checking a function body, the types of all arguments and so forth | |
890 | /// that refer to bound region parameters are modified to refer to free | |
891 | /// region parameters. | |
892 | ReFree(I::FreeRegion), | |
893 | ||
894 | /// Static data that has an "infinite" lifetime. Top in the region lattice. | |
895 | ReStatic, | |
896 | ||
897 | /// A region variable. Should not exist outside of type inference. | |
898 | ReVar(I::RegionVid), | |
899 | ||
900 | /// A placeholder region -- basically, the higher-ranked version of `ReFree`. | |
901 | /// Should not exist outside of type inference. | |
902 | RePlaceholder(I::PlaceholderRegion), | |
903 | ||
923072b8 FG |
904 | /// Erased region, used by trait selection, in MIR and during codegen. |
905 | ReErased, | |
906 | } | |
907 | ||
908 | // This is manually implemented for `RegionKind` because `std::mem::discriminant` | |
909 | // returns an opaque value that is `PartialEq` but not `PartialOrd` | |
910 | #[inline] | |
911 | const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize { | |
912 | match value { | |
913 | ReEarlyBound(_) => 0, | |
914 | ReLateBound(_, _) => 1, | |
915 | ReFree(_) => 2, | |
916 | ReStatic => 3, | |
917 | ReVar(_) => 4, | |
918 | RePlaceholder(_) => 5, | |
f2b60f7d | 919 | ReErased => 6, |
923072b8 FG |
920 | } |
921 | } | |
922 | ||
923 | // This is manually implemented because a derive would require `I: Copy` | |
924 | impl<I: Interner> Copy for RegionKind<I> | |
925 | where | |
926 | I::EarlyBoundRegion: Copy, | |
927 | I::BoundRegion: Copy, | |
928 | I::FreeRegion: Copy, | |
929 | I::RegionVid: Copy, | |
930 | I::PlaceholderRegion: Copy, | |
931 | { | |
932 | } | |
933 | ||
934 | // This is manually implemented because a derive would require `I: Clone` | |
935 | impl<I: Interner> Clone for RegionKind<I> { | |
936 | fn clone(&self) -> Self { | |
937 | match self { | |
487cf647 | 938 | ReEarlyBound(r) => ReEarlyBound(r.clone()), |
9c376795 | 939 | ReLateBound(d, r) => ReLateBound(*d, r.clone()), |
487cf647 | 940 | ReFree(r) => ReFree(r.clone()), |
923072b8 | 941 | ReStatic => ReStatic, |
487cf647 FG |
942 | ReVar(r) => ReVar(r.clone()), |
943 | RePlaceholder(r) => RePlaceholder(r.clone()), | |
923072b8 FG |
944 | ReErased => ReErased, |
945 | } | |
946 | } | |
947 | } | |
948 | ||
949 | // This is manually implemented because a derive would require `I: PartialEq` | |
950 | impl<I: Interner> PartialEq for RegionKind<I> { | |
951 | #[inline] | |
952 | fn eq(&self, other: &RegionKind<I>) -> bool { | |
487cf647 FG |
953 | regionkind_discriminant(self) == regionkind_discriminant(other) |
954 | && match (self, other) { | |
955 | (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r, | |
956 | (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r, | |
957 | (ReFree(a_r), ReFree(b_r)) => a_r == b_r, | |
958 | (ReStatic, ReStatic) => true, | |
959 | (ReVar(a_r), ReVar(b_r)) => a_r == b_r, | |
960 | (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r, | |
961 | (ReErased, ReErased) => true, | |
962 | _ => { | |
963 | debug_assert!( | |
964 | false, | |
965 | "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}" | |
966 | ); | |
967 | true | |
923072b8 | 968 | } |
923072b8 | 969 | } |
923072b8 FG |
970 | } |
971 | } | |
972 | ||
973 | // This is manually implemented because a derive would require `I: Eq` | |
974 | impl<I: Interner> Eq for RegionKind<I> {} | |
975 | ||
976 | // This is manually implemented because a derive would require `I: PartialOrd` | |
977 | impl<I: Interner> PartialOrd for RegionKind<I> { | |
978 | #[inline] | |
979 | fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> { | |
487cf647 | 980 | Some(self.cmp(other)) |
923072b8 FG |
981 | } |
982 | } | |
983 | ||
984 | // This is manually implemented because a derive would require `I: Ord` | |
985 | impl<I: Interner> Ord for RegionKind<I> { | |
986 | #[inline] | |
987 | fn cmp(&self, other: &RegionKind<I>) -> Ordering { | |
487cf647 FG |
988 | regionkind_discriminant(self).cmp(®ionkind_discriminant(other)).then_with(|| { |
989 | match (self, other) { | |
990 | (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r), | |
991 | (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => { | |
992 | a_d.cmp(b_d).then_with(|| a_r.cmp(b_r)) | |
923072b8 | 993 | } |
487cf647 FG |
994 | (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r), |
995 | (ReStatic, ReStatic) => Ordering::Equal, | |
996 | (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r), | |
997 | (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r), | |
998 | (ReErased, ReErased) => Ordering::Equal, | |
999 | _ => { | |
1000 | debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"); | |
1001 | Ordering::Equal | |
923072b8 | 1002 | } |
923072b8 | 1003 | } |
487cf647 | 1004 | }) |
923072b8 FG |
1005 | } |
1006 | } | |
1007 | ||
1008 | // This is manually implemented because a derive would require `I: Hash` | |
1009 | impl<I: Interner> hash::Hash for RegionKind<I> { | |
487cf647 FG |
1010 | fn hash<H: hash::Hasher>(&self, state: &mut H) -> () { |
1011 | regionkind_discriminant(self).hash(state); | |
1012 | match self { | |
1013 | ReEarlyBound(r) => r.hash(state), | |
1014 | ReLateBound(d, r) => { | |
1015 | d.hash(state); | |
1016 | r.hash(state) | |
1017 | } | |
1018 | ReFree(r) => r.hash(state), | |
1019 | ReStatic => (), | |
1020 | ReVar(r) => r.hash(state), | |
1021 | RePlaceholder(r) => r.hash(state), | |
1022 | ReErased => (), | |
923072b8 FG |
1023 | } |
1024 | } | |
1025 | } | |
1026 | ||
1027 | // This is manually implemented because a derive would require `I: Debug` | |
1028 | impl<I: Interner> fmt::Debug for RegionKind<I> { | |
1029 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1030 | match self { | |
9c376795 | 1031 | ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"), |
923072b8 | 1032 | |
487cf647 | 1033 | ReLateBound(binder_id, bound_region) => { |
9c376795 | 1034 | write!(f, "ReLateBound({binder_id:?}, {bound_region:?})") |
923072b8 FG |
1035 | } |
1036 | ||
487cf647 | 1037 | ReFree(fr) => fr.fmt(f), |
923072b8 | 1038 | |
487cf647 | 1039 | ReStatic => f.write_str("ReStatic"), |
923072b8 | 1040 | |
487cf647 | 1041 | ReVar(vid) => vid.fmt(f), |
923072b8 | 1042 | |
9c376795 | 1043 | RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"), |
923072b8 | 1044 | |
487cf647 | 1045 | ReErased => f.write_str("ReErased"), |
923072b8 FG |
1046 | } |
1047 | } | |
1048 | } | |
1049 | ||
1050 | // This is manually implemented because a derive would require `I: Encodable` | |
1051 | impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I> | |
1052 | where | |
1053 | I::EarlyBoundRegion: Encodable<E>, | |
1054 | I::BoundRegion: Encodable<E>, | |
1055 | I::FreeRegion: Encodable<E>, | |
1056 | I::RegionVid: Encodable<E>, | |
1057 | I::PlaceholderRegion: Encodable<E>, | |
1058 | { | |
1059 | fn encode(&self, e: &mut E) { | |
1060 | let disc = regionkind_discriminant(self); | |
1061 | match self { | |
1062 | ReEarlyBound(a) => e.emit_enum_variant(disc, |e| { | |
1063 | a.encode(e); | |
1064 | }), | |
1065 | ReLateBound(a, b) => e.emit_enum_variant(disc, |e| { | |
1066 | a.encode(e); | |
1067 | b.encode(e); | |
1068 | }), | |
1069 | ReFree(a) => e.emit_enum_variant(disc, |e| { | |
1070 | a.encode(e); | |
1071 | }), | |
1072 | ReStatic => e.emit_enum_variant(disc, |_| {}), | |
1073 | ReVar(a) => e.emit_enum_variant(disc, |e| { | |
1074 | a.encode(e); | |
1075 | }), | |
1076 | RePlaceholder(a) => e.emit_enum_variant(disc, |e| { | |
1077 | a.encode(e); | |
1078 | }), | |
923072b8 FG |
1079 | ReErased => e.emit_enum_variant(disc, |_| {}), |
1080 | } | |
1081 | } | |
1082 | } | |
1083 | ||
1084 | // This is manually implemented because a derive would require `I: Decodable` | |
1085 | impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I> | |
1086 | where | |
1087 | I::EarlyBoundRegion: Decodable<D>, | |
1088 | I::BoundRegion: Decodable<D>, | |
1089 | I::FreeRegion: Decodable<D>, | |
1090 | I::RegionVid: Decodable<D>, | |
1091 | I::PlaceholderRegion: Decodable<D>, | |
1092 | { | |
1093 | fn decode(d: &mut D) -> Self { | |
1094 | match Decoder::read_usize(d) { | |
1095 | 0 => ReEarlyBound(Decodable::decode(d)), | |
1096 | 1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)), | |
1097 | 2 => ReFree(Decodable::decode(d)), | |
1098 | 3 => ReStatic, | |
1099 | 4 => ReVar(Decodable::decode(d)), | |
1100 | 5 => RePlaceholder(Decodable::decode(d)), | |
f2b60f7d | 1101 | 6 => ReErased, |
923072b8 FG |
1102 | _ => panic!( |
1103 | "{}", | |
1104 | format!( | |
1105 | "invalid enum variant tag while decoding `{}`, expected 0..{}", | |
1106 | "RegionKind", 8, | |
1107 | ) | |
1108 | ), | |
1109 | } | |
1110 | } | |
1111 | } | |
1112 | ||
1113 | // This is not a derived impl because a derive would require `I: HashStable` | |
f2b60f7d | 1114 | impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I> |
923072b8 FG |
1115 | where |
1116 | I::EarlyBoundRegion: HashStable<CTX>, | |
1117 | I::BoundRegion: HashStable<CTX>, | |
1118 | I::FreeRegion: HashStable<CTX>, | |
1119 | I::RegionVid: HashStable<CTX>, | |
1120 | I::PlaceholderRegion: HashStable<CTX>, | |
1121 | { | |
1122 | #[inline] | |
1123 | fn hash_stable( | |
1124 | &self, | |
1125 | hcx: &mut CTX, | |
1126 | hasher: &mut rustc_data_structures::stable_hasher::StableHasher, | |
1127 | ) { | |
1128 | std::mem::discriminant(self).hash_stable(hcx, hasher); | |
1129 | match self { | |
1130 | ReErased | ReStatic => { | |
1131 | // No variant fields to hash for these ... | |
1132 | } | |
487cf647 FG |
1133 | ReLateBound(d, r) => { |
1134 | d.hash_stable(hcx, hasher); | |
1135 | r.hash_stable(hcx, hasher); | |
923072b8 | 1136 | } |
487cf647 FG |
1137 | ReEarlyBound(r) => { |
1138 | r.hash_stable(hcx, hasher); | |
923072b8 | 1139 | } |
487cf647 FG |
1140 | ReFree(r) => { |
1141 | r.hash_stable(hcx, hasher); | |
923072b8 | 1142 | } |
487cf647 FG |
1143 | RePlaceholder(r) => { |
1144 | r.hash_stable(hcx, hasher); | |
923072b8 | 1145 | } |
2b03887a FG |
1146 | ReVar(_) => { |
1147 | panic!("region variables should not be hashed: {self:?}") | |
923072b8 FG |
1148 | } |
1149 | } | |
1150 | } | |
1151 | } |