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