]>
Commit | Line | Data |
---|---|---|
1 | #![feature(min_specialization)] | |
2 | ||
3 | #[macro_use] | |
4 | extern crate bitflags; | |
5 | #[macro_use] | |
6 | extern crate rustc_macros; | |
7 | ||
8 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; | |
9 | use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; | |
10 | use std::fmt; | |
11 | use std::mem::discriminant; | |
12 | ||
13 | bitflags! { | |
14 | /// Flags that we track on types. These flags are propagated upwards | |
15 | /// through the type during type construction, so that we can quickly check | |
16 | /// whether the type has various kinds of types in it without recursing | |
17 | /// over the type itself. | |
18 | pub struct TypeFlags: u32 { | |
19 | // Does this have parameters? Used to determine whether substitution is | |
20 | // required. | |
21 | /// Does this have `Param`? | |
22 | const HAS_KNOWN_TY_PARAM = 1 << 0; | |
23 | /// Does this have `ReEarlyBound`? | |
24 | const HAS_KNOWN_RE_PARAM = 1 << 1; | |
25 | /// Does this have `ConstKind::Param`? | |
26 | const HAS_KNOWN_CT_PARAM = 1 << 2; | |
27 | ||
28 | const KNOWN_NEEDS_SUBST = TypeFlags::HAS_KNOWN_TY_PARAM.bits | |
29 | | TypeFlags::HAS_KNOWN_RE_PARAM.bits | |
30 | | TypeFlags::HAS_KNOWN_CT_PARAM.bits; | |
31 | ||
32 | /// Does this have `Infer`? | |
33 | const HAS_TY_INFER = 1 << 3; | |
34 | /// Does this have `ReVar`? | |
35 | const HAS_RE_INFER = 1 << 4; | |
36 | /// Does this have `ConstKind::Infer`? | |
37 | const HAS_CT_INFER = 1 << 5; | |
38 | ||
39 | /// Does this have inference variables? Used to determine whether | |
40 | /// inference is required. | |
41 | const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits | |
42 | | TypeFlags::HAS_RE_INFER.bits | |
43 | | TypeFlags::HAS_CT_INFER.bits; | |
44 | ||
45 | /// Does this have `Placeholder`? | |
46 | const HAS_TY_PLACEHOLDER = 1 << 6; | |
47 | /// Does this have `RePlaceholder`? | |
48 | const HAS_RE_PLACEHOLDER = 1 << 7; | |
49 | /// Does this have `ConstKind::Placeholder`? | |
50 | const HAS_CT_PLACEHOLDER = 1 << 8; | |
51 | ||
52 | /// `true` if there are "names" of regions and so forth | |
53 | /// that are local to a particular fn/inferctxt | |
54 | const HAS_KNOWN_FREE_LOCAL_REGIONS = 1 << 9; | |
55 | ||
56 | /// `true` if there are "names" of types and regions and so forth | |
57 | /// that are local to a particular fn | |
58 | const HAS_KNOWN_FREE_LOCAL_NAMES = TypeFlags::HAS_KNOWN_TY_PARAM.bits | |
59 | | TypeFlags::HAS_KNOWN_CT_PARAM.bits | |
60 | | TypeFlags::HAS_TY_INFER.bits | |
61 | | TypeFlags::HAS_CT_INFER.bits | |
62 | | TypeFlags::HAS_TY_PLACEHOLDER.bits | |
63 | | TypeFlags::HAS_CT_PLACEHOLDER.bits | |
64 | // We consider 'freshened' types and constants | |
65 | // to depend on a particular fn. | |
66 | // The freshening process throws away information, | |
67 | // which can make things unsuitable for use in a global | |
68 | // cache. Note that there is no 'fresh lifetime' flag - | |
69 | // freshening replaces all lifetimes with `ReErased`, | |
70 | // which is different from how types/const are freshened. | |
71 | | TypeFlags::HAS_TY_FRESH.bits | |
72 | | TypeFlags::HAS_CT_FRESH.bits | |
73 | | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits; | |
74 | ||
75 | const HAS_POTENTIAL_FREE_LOCAL_NAMES = TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES.bits | |
76 | | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits; | |
77 | ||
78 | /// Does this have `Projection`? | |
79 | const HAS_TY_PROJECTION = 1 << 10; | |
80 | /// Does this have `Opaque`? | |
81 | const HAS_TY_OPAQUE = 1 << 11; | |
82 | /// Does this have `ConstKind::Unevaluated`? | |
83 | const HAS_CT_PROJECTION = 1 << 12; | |
84 | ||
85 | /// Could this type be normalized further? | |
86 | const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits | |
87 | | TypeFlags::HAS_TY_OPAQUE.bits | |
88 | | TypeFlags::HAS_CT_PROJECTION.bits; | |
89 | ||
90 | /// Is an error type/const reachable? | |
91 | const HAS_ERROR = 1 << 13; | |
92 | ||
93 | /// Does this have any region that "appears free" in the type? | |
94 | /// Basically anything but `ReLateBound` and `ReErased`. | |
95 | const HAS_KNOWN_FREE_REGIONS = 1 << 14; | |
96 | ||
97 | const HAS_POTENTIAL_FREE_REGIONS = TypeFlags::HAS_KNOWN_FREE_REGIONS.bits | |
98 | | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits; | |
99 | ||
100 | /// Does this have any `ReLateBound` regions? Used to check | |
101 | /// if a global bound is safe to evaluate. | |
102 | const HAS_RE_LATE_BOUND = 1 << 15; | |
103 | ||
104 | /// Does this have any `ReErased` regions? | |
105 | const HAS_RE_ERASED = 1 << 16; | |
106 | ||
107 | /// Does this value have parameters/placeholders/inference variables which could be | |
108 | /// replaced later, in a way that would change the results of `impl` specialization? | |
109 | /// | |
110 | /// Note that this flag being set is not a guarantee, as it is also | |
111 | /// set if there are any anon consts with unknown default substs. | |
112 | const STILL_FURTHER_SPECIALIZABLE = 1 << 17; | |
113 | ||
114 | /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? | |
115 | const HAS_TY_FRESH = 1 << 18; | |
116 | ||
117 | /// Does this value have `InferConst::Fresh`? | |
118 | const HAS_CT_FRESH = 1 << 19; | |
119 | ||
120 | /// Does this value have unknown default anon const substs. | |
121 | /// | |
122 | /// For more details refer to... | |
123 | /// FIXME(@lcnr): ask me for now, still have to write all of this. | |
124 | const HAS_UNKNOWN_DEFAULT_CONST_SUBSTS = 1 << 20; | |
125 | /// Flags which can be influenced by default anon const substs. | |
126 | const MAY_NEED_DEFAULT_CONST_SUBSTS = TypeFlags::HAS_KNOWN_RE_PARAM.bits | |
127 | | TypeFlags::HAS_KNOWN_TY_PARAM.bits | |
128 | | TypeFlags::HAS_KNOWN_CT_PARAM.bits | |
129 | | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits | |
130 | | TypeFlags::HAS_KNOWN_FREE_REGIONS.bits; | |
131 | ||
132 | } | |
133 | } | |
134 | ||
135 | rustc_index::newtype_index! { | |
136 | /// A [De Bruijn index][dbi] is a standard means of representing | |
137 | /// regions (and perhaps later types) in a higher-ranked setting. In | |
138 | /// particular, imagine a type like this: | |
139 | /// | |
140 | /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) | |
141 | /// ^ ^ | | | | |
142 | /// | | | | | | |
143 | /// | +------------+ 0 | | | |
144 | /// | | | | |
145 | /// +----------------------------------+ 1 | | |
146 | /// | | | |
147 | /// +----------------------------------------------+ 0 | |
148 | /// | |
149 | /// In this type, there are two binders (the outer fn and the inner | |
150 | /// fn). We need to be able to determine, for any given region, which | |
151 | /// fn type it is bound by, the inner or the outer one. There are | |
152 | /// various ways you can do this, but a De Bruijn index is one of the | |
153 | /// more convenient and has some nice properties. The basic idea is to | |
154 | /// count the number of binders, inside out. Some examples should help | |
155 | /// clarify what I mean. | |
156 | /// | |
157 | /// Let's start with the reference type `&'b isize` that is the first | |
158 | /// argument to the inner function. This region `'b` is assigned a De | |
159 | /// Bruijn index of 0, meaning "the innermost binder" (in this case, a | |
160 | /// fn). The region `'a` that appears in the second argument type (`&'a | |
161 | /// isize`) would then be assigned a De Bruijn index of 1, meaning "the | |
162 | /// second-innermost binder". (These indices are written on the arrows | |
163 | /// in the diagram). | |
164 | /// | |
165 | /// What is interesting is that De Bruijn index attached to a particular | |
166 | /// variable will vary depending on where it appears. For example, | |
167 | /// the final type `&'a char` also refers to the region `'a` declared on | |
168 | /// the outermost fn. But this time, this reference is not nested within | |
169 | /// any other binders (i.e., it is not an argument to the inner fn, but | |
170 | /// rather the outer one). Therefore, in this case, it is assigned a | |
171 | /// De Bruijn index of 0, because the innermost binder in that location | |
172 | /// is the outer fn. | |
173 | /// | |
174 | /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index | |
175 | pub struct DebruijnIndex { | |
176 | DEBUG_FORMAT = "DebruijnIndex({})", | |
177 | const INNERMOST = 0, | |
178 | } | |
179 | } | |
180 | ||
181 | impl DebruijnIndex { | |
182 | /// Returns the resulting index when this value is moved into | |
183 | /// `amount` number of new binders. So, e.g., if you had | |
184 | /// | |
185 | /// for<'a> fn(&'a x) | |
186 | /// | |
187 | /// and you wanted to change it to | |
188 | /// | |
189 | /// for<'a> fn(for<'b> fn(&'a x)) | |
190 | /// | |
191 | /// you would need to shift the index for `'a` into a new binder. | |
192 | #[must_use] | |
193 | pub fn shifted_in(self, amount: u32) -> DebruijnIndex { | |
194 | DebruijnIndex::from_u32(self.as_u32() + amount) | |
195 | } | |
196 | ||
197 | /// Update this index in place by shifting it "in" through | |
198 | /// `amount` number of binders. | |
199 | pub fn shift_in(&mut self, amount: u32) { | |
200 | *self = self.shifted_in(amount); | |
201 | } | |
202 | ||
203 | /// Returns the resulting index when this value is moved out from | |
204 | /// `amount` number of new binders. | |
205 | #[must_use] | |
206 | pub fn shifted_out(self, amount: u32) -> DebruijnIndex { | |
207 | DebruijnIndex::from_u32(self.as_u32() - amount) | |
208 | } | |
209 | ||
210 | /// Update in place by shifting out from `amount` binders. | |
211 | pub fn shift_out(&mut self, amount: u32) { | |
212 | *self = self.shifted_out(amount); | |
213 | } | |
214 | ||
215 | /// Adjusts any De Bruijn indices so as to make `to_binder` the | |
216 | /// innermost binder. That is, if we have something bound at `to_binder`, | |
217 | /// it will now be bound at INNERMOST. This is an appropriate thing to do | |
218 | /// when moving a region out from inside binders: | |
219 | /// | |
220 | /// ``` | |
221 | /// for<'a> fn(for<'b> for<'c> fn(&'a u32), _) | |
222 | /// // Binder: D3 D2 D1 ^^ | |
223 | /// ``` | |
224 | /// | |
225 | /// Here, the region `'a` would have the De Bruijn index D3, | |
226 | /// because it is the bound 3 binders out. However, if we wanted | |
227 | /// to refer to that region `'a` in the second argument (the `_`), | |
228 | /// those two binders would not be in scope. In that case, we | |
229 | /// might invoke `shift_out_to_binder(D3)`. This would adjust the | |
230 | /// De Bruijn index of `'a` to D1 (the innermost binder). | |
231 | /// | |
232 | /// If we invoke `shift_out_to_binder` and the region is in fact | |
233 | /// bound by one of the binders we are shifting out of, that is an | |
234 | /// error (and should fail an assertion failure). | |
235 | pub fn shifted_out_to_binder(self, to_binder: DebruijnIndex) -> Self { | |
236 | self.shifted_out(to_binder.as_u32() - INNERMOST.as_u32()) | |
237 | } | |
238 | } | |
239 | ||
240 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | |
241 | #[derive(Encodable, Decodable)] | |
242 | pub enum IntTy { | |
243 | Isize, | |
244 | I8, | |
245 | I16, | |
246 | I32, | |
247 | I64, | |
248 | I128, | |
249 | } | |
250 | ||
251 | impl IntTy { | |
252 | pub fn name_str(&self) -> &'static str { | |
253 | match *self { | |
254 | IntTy::Isize => "isize", | |
255 | IntTy::I8 => "i8", | |
256 | IntTy::I16 => "i16", | |
257 | IntTy::I32 => "i32", | |
258 | IntTy::I64 => "i64", | |
259 | IntTy::I128 => "i128", | |
260 | } | |
261 | } | |
262 | ||
263 | pub fn bit_width(&self) -> Option<u64> { | |
264 | Some(match *self { | |
265 | IntTy::Isize => return None, | |
266 | IntTy::I8 => 8, | |
267 | IntTy::I16 => 16, | |
268 | IntTy::I32 => 32, | |
269 | IntTy::I64 => 64, | |
270 | IntTy::I128 => 128, | |
271 | }) | |
272 | } | |
273 | ||
274 | pub fn normalize(&self, target_width: u32) -> Self { | |
275 | match self { | |
276 | IntTy::Isize => match target_width { | |
277 | 16 => IntTy::I16, | |
278 | 32 => IntTy::I32, | |
279 | 64 => IntTy::I64, | |
280 | _ => unreachable!(), | |
281 | }, | |
282 | _ => *self, | |
283 | } | |
284 | } | |
285 | } | |
286 | ||
287 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)] | |
288 | #[derive(Encodable, Decodable)] | |
289 | pub enum UintTy { | |
290 | Usize, | |
291 | U8, | |
292 | U16, | |
293 | U32, | |
294 | U64, | |
295 | U128, | |
296 | } | |
297 | ||
298 | impl UintTy { | |
299 | pub fn name_str(&self) -> &'static str { | |
300 | match *self { | |
301 | UintTy::Usize => "usize", | |
302 | UintTy::U8 => "u8", | |
303 | UintTy::U16 => "u16", | |
304 | UintTy::U32 => "u32", | |
305 | UintTy::U64 => "u64", | |
306 | UintTy::U128 => "u128", | |
307 | } | |
308 | } | |
309 | ||
310 | pub fn bit_width(&self) -> Option<u64> { | |
311 | Some(match *self { | |
312 | UintTy::Usize => return None, | |
313 | UintTy::U8 => 8, | |
314 | UintTy::U16 => 16, | |
315 | UintTy::U32 => 32, | |
316 | UintTy::U64 => 64, | |
317 | UintTy::U128 => 128, | |
318 | }) | |
319 | } | |
320 | ||
321 | pub fn normalize(&self, target_width: u32) -> Self { | |
322 | match self { | |
323 | UintTy::Usize => match target_width { | |
324 | 16 => UintTy::U16, | |
325 | 32 => UintTy::U32, | |
326 | 64 => UintTy::U64, | |
327 | _ => unreachable!(), | |
328 | }, | |
329 | _ => *self, | |
330 | } | |
331 | } | |
332 | } | |
333 | ||
334 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | |
335 | #[derive(Encodable, Decodable)] | |
336 | pub enum FloatTy { | |
337 | F32, | |
338 | F64, | |
339 | } | |
340 | ||
341 | impl FloatTy { | |
342 | pub fn name_str(self) -> &'static str { | |
343 | match self { | |
344 | FloatTy::F32 => "f32", | |
345 | FloatTy::F64 => "f64", | |
346 | } | |
347 | } | |
348 | ||
349 | pub fn bit_width(self) -> u64 { | |
350 | match self { | |
351 | FloatTy::F32 => 32, | |
352 | FloatTy::F64 => 64, | |
353 | } | |
354 | } | |
355 | } | |
356 | ||
357 | #[derive(Clone, Copy, PartialEq, Eq)] | |
358 | pub enum IntVarValue { | |
359 | IntType(IntTy), | |
360 | UintType(UintTy), | |
361 | } | |
362 | ||
363 | #[derive(Clone, Copy, PartialEq, Eq)] | |
364 | pub struct FloatVarValue(pub FloatTy); | |
365 | ||
366 | rustc_index::newtype_index! { | |
367 | /// A **ty**pe **v**ariable **ID**. | |
368 | pub struct TyVid { | |
369 | DEBUG_FORMAT = "_#{}t" | |
370 | } | |
371 | } | |
372 | ||
373 | /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. | |
374 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] | |
375 | pub struct IntVid { | |
376 | pub index: u32, | |
377 | } | |
378 | ||
379 | /// An **float**ing-point (`f32` or `f64`) type **v**ariable **ID**. | |
380 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] | |
381 | pub struct FloatVid { | |
382 | pub index: u32, | |
383 | } | |
384 | ||
385 | /// A placeholder for a type that hasn't been inferred yet. | |
386 | /// | |
387 | /// E.g., if we have an empty array (`[]`), then we create a fresh | |
388 | /// type variable for the element type since we won't know until it's | |
389 | /// used what the element type is supposed to be. | |
390 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] | |
391 | pub enum InferTy { | |
392 | /// A type variable. | |
393 | TyVar(TyVid), | |
394 | /// An integral type variable (`{integer}`). | |
395 | /// | |
396 | /// These are created when the compiler sees an integer literal like | |
397 | /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.). | |
398 | /// We don't know until it's used what type it's supposed to be, so | |
399 | /// we create a fresh type variable. | |
400 | IntVar(IntVid), | |
401 | /// A floating-point type variable (`{float}`). | |
402 | /// | |
403 | /// These are created when the compiler sees an float literal like | |
404 | /// `1.0` that could be either an `f32` or an `f64`. | |
405 | /// We don't know until it's used what type it's supposed to be, so | |
406 | /// we create a fresh type variable. | |
407 | FloatVar(FloatVid), | |
408 | ||
409 | /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement | |
410 | /// for an unbound type variable. This is convenient for caching etc. See | |
411 | /// `rustc_infer::infer::freshen` for more details. | |
412 | /// | |
413 | /// Compare with [`TyVar`][Self::TyVar]. | |
414 | FreshTy(u32), | |
415 | /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar]. | |
416 | FreshIntTy(u32), | |
417 | /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar]. | |
418 | FreshFloatTy(u32), | |
419 | } | |
420 | ||
421 | /// Raw `TyVid` are used as the unification key for `sub_relations`; | |
422 | /// they carry no values. | |
423 | impl UnifyKey for TyVid { | |
424 | type Value = (); | |
425 | fn index(&self) -> u32 { | |
426 | self.as_u32() | |
427 | } | |
428 | fn from_index(i: u32) -> TyVid { | |
429 | TyVid::from_u32(i) | |
430 | } | |
431 | fn tag() -> &'static str { | |
432 | "TyVid" | |
433 | } | |
434 | } | |
435 | ||
436 | impl EqUnifyValue for IntVarValue {} | |
437 | ||
438 | impl UnifyKey for IntVid { | |
439 | type Value = Option<IntVarValue>; | |
440 | #[inline] // make this function eligible for inlining - it is quite hot. | |
441 | fn index(&self) -> u32 { | |
442 | self.index | |
443 | } | |
444 | fn from_index(i: u32) -> IntVid { | |
445 | IntVid { index: i } | |
446 | } | |
447 | fn tag() -> &'static str { | |
448 | "IntVid" | |
449 | } | |
450 | } | |
451 | ||
452 | impl EqUnifyValue for FloatVarValue {} | |
453 | ||
454 | impl UnifyKey for FloatVid { | |
455 | type Value = Option<FloatVarValue>; | |
456 | fn index(&self) -> u32 { | |
457 | self.index | |
458 | } | |
459 | fn from_index(i: u32) -> FloatVid { | |
460 | FloatVid { index: i } | |
461 | } | |
462 | fn tag() -> &'static str { | |
463 | "FloatVid" | |
464 | } | |
465 | } | |
466 | ||
467 | #[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash)] | |
468 | pub enum Variance { | |
469 | Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type | |
470 | Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell | |
471 | Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type | |
472 | Bivariant, // T<A> <: T<B> -- e.g., unused type parameter | |
473 | } | |
474 | ||
475 | impl Variance { | |
476 | /// `a.xform(b)` combines the variance of a context with the | |
477 | /// variance of a type with the following meaning. If we are in a | |
478 | /// context with variance `a`, and we encounter a type argument in | |
479 | /// a position with variance `b`, then `a.xform(b)` is the new | |
480 | /// variance with which the argument appears. | |
481 | /// | |
482 | /// Example 1: | |
483 | /// | |
484 | /// *mut Vec<i32> | |
485 | /// | |
486 | /// Here, the "ambient" variance starts as covariant. `*mut T` is | |
487 | /// invariant with respect to `T`, so the variance in which the | |
488 | /// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which | |
489 | /// yields `Invariant`. Now, the type `Vec<T>` is covariant with | |
490 | /// respect to its type argument `T`, and hence the variance of | |
491 | /// the `i32` here is `Invariant.xform(Covariant)`, which results | |
492 | /// (again) in `Invariant`. | |
493 | /// | |
494 | /// Example 2: | |
495 | /// | |
496 | /// fn(*const Vec<i32>, *mut Vec<i32) | |
497 | /// | |
498 | /// The ambient variance is covariant. A `fn` type is | |
499 | /// contravariant with respect to its parameters, so the variance | |
500 | /// within which both pointer types appear is | |
501 | /// `Covariant.xform(Contravariant)`, or `Contravariant`. `*const | |
502 | /// T` is covariant with respect to `T`, so the variance within | |
503 | /// which the first `Vec<i32>` appears is | |
504 | /// `Contravariant.xform(Covariant)` or `Contravariant`. The same | |
505 | /// is true for its `i32` argument. In the `*mut T` case, the | |
506 | /// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`, | |
507 | /// and hence the outermost type is `Invariant` with respect to | |
508 | /// `Vec<i32>` (and its `i32` argument). | |
509 | /// | |
510 | /// Source: Figure 1 of "Taming the Wildcards: | |
511 | /// Combining Definition- and Use-Site Variance" published in PLDI'11. | |
512 | pub fn xform(self, v: Variance) -> Variance { | |
513 | match (self, v) { | |
514 | // Figure 1, column 1. | |
515 | (Variance::Covariant, Variance::Covariant) => Variance::Covariant, | |
516 | (Variance::Covariant, Variance::Contravariant) => Variance::Contravariant, | |
517 | (Variance::Covariant, Variance::Invariant) => Variance::Invariant, | |
518 | (Variance::Covariant, Variance::Bivariant) => Variance::Bivariant, | |
519 | ||
520 | // Figure 1, column 2. | |
521 | (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant, | |
522 | (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant, | |
523 | (Variance::Contravariant, Variance::Invariant) => Variance::Invariant, | |
524 | (Variance::Contravariant, Variance::Bivariant) => Variance::Bivariant, | |
525 | ||
526 | // Figure 1, column 3. | |
527 | (Variance::Invariant, _) => Variance::Invariant, | |
528 | ||
529 | // Figure 1, column 4. | |
530 | (Variance::Bivariant, _) => Variance::Bivariant, | |
531 | } | |
532 | } | |
533 | } | |
534 | ||
535 | impl<CTX> HashStable<CTX> for DebruijnIndex { | |
536 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
537 | self.as_u32().hash_stable(ctx, hasher); | |
538 | } | |
539 | } | |
540 | ||
541 | impl<CTX> HashStable<CTX> for IntTy { | |
542 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
543 | discriminant(self).hash_stable(ctx, hasher); | |
544 | } | |
545 | } | |
546 | ||
547 | impl<CTX> HashStable<CTX> for UintTy { | |
548 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
549 | discriminant(self).hash_stable(ctx, hasher); | |
550 | } | |
551 | } | |
552 | ||
553 | impl<CTX> HashStable<CTX> for FloatTy { | |
554 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
555 | discriminant(self).hash_stable(ctx, hasher); | |
556 | } | |
557 | } | |
558 | ||
559 | impl<CTX> HashStable<CTX> for InferTy { | |
560 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
561 | use InferTy::*; | |
562 | match self { | |
563 | TyVar(v) => v.as_u32().hash_stable(ctx, hasher), | |
564 | IntVar(v) => v.index.hash_stable(ctx, hasher), | |
565 | FloatVar(v) => v.index.hash_stable(ctx, hasher), | |
566 | FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher), | |
567 | } | |
568 | } | |
569 | } | |
570 | ||
571 | impl<CTX> HashStable<CTX> for Variance { | |
572 | fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { | |
573 | discriminant(self).hash_stable(ctx, hasher); | |
574 | } | |
575 | } | |
576 | ||
577 | impl fmt::Debug for IntVarValue { | |
578 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
579 | match *self { | |
580 | IntVarValue::IntType(ref v) => v.fmt(f), | |
581 | IntVarValue::UintType(ref v) => v.fmt(f), | |
582 | } | |
583 | } | |
584 | } | |
585 | ||
586 | impl fmt::Debug for FloatVarValue { | |
587 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
588 | self.0.fmt(f) | |
589 | } | |
590 | } | |
591 | ||
592 | impl fmt::Debug for IntVid { | |
593 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
594 | write!(f, "_#{}i", self.index) | |
595 | } | |
596 | } | |
597 | ||
598 | impl fmt::Debug for FloatVid { | |
599 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
600 | write!(f, "_#{}f", self.index) | |
601 | } | |
602 | } | |
603 | ||
604 | impl fmt::Debug for InferTy { | |
605 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
606 | use InferTy::*; | |
607 | match *self { | |
608 | TyVar(ref v) => v.fmt(f), | |
609 | IntVar(ref v) => v.fmt(f), | |
610 | FloatVar(ref v) => v.fmt(f), | |
611 | FreshTy(v) => write!(f, "FreshTy({:?})", v), | |
612 | FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), | |
613 | FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v), | |
614 | } | |
615 | } | |
616 | } | |
617 | ||
618 | impl fmt::Debug for Variance { | |
619 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
620 | f.write_str(match *self { | |
621 | Variance::Covariant => "+", | |
622 | Variance::Contravariant => "-", | |
623 | Variance::Invariant => "o", | |
624 | Variance::Bivariant => "*", | |
625 | }) | |
626 | } | |
627 | } | |
628 | ||
629 | impl fmt::Display for InferTy { | |
630 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
631 | use InferTy::*; | |
632 | match *self { | |
633 | TyVar(_) => write!(f, "_"), | |
634 | IntVar(_) => write!(f, "{}", "{integer}"), | |
635 | FloatVar(_) => write!(f, "{}", "{float}"), | |
636 | FreshTy(v) => write!(f, "FreshTy({})", v), | |
637 | FreshIntTy(v) => write!(f, "FreshIntTy({})", v), | |
638 | FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v), | |
639 | } | |
640 | } | |
641 | } |