rustc_type_ir/
ty_kind.rs

1use std::fmt;
2use std::ops::Deref;
3
4use derive_where::derive_where;
5use rustc_ast_ir::Mutability;
6#[cfg(feature = "nightly")]
7use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
8#[cfg(feature = "nightly")]
9use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
10#[cfg(feature = "nightly")]
11use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
12use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
13
14use self::TyKind::*;
15pub use self::closure::*;
16use crate::inherent::*;
17use crate::visit::TypeVisitable;
18use crate::{self as ty, DebruijnIndex, Interner};
19
20mod closure;
21
22/// Specifies how a trait object is represented.
23#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
24#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
25pub enum DynKind {
26    /// An unsized `dyn Trait` object
27    Dyn,
28    /// A sized `dyn* Trait` object
29    ///
30    /// These objects are represented as a `(data, vtable)` pair where `data` is a value of some
31    /// ptr-sized and ptr-aligned dynamically determined type `T` and `vtable` is a pointer to the
32    /// vtable of `impl T for Trait`. This allows a `dyn*` object to be treated agnostically with
33    /// respect to whether it points to a `Box<T>`, `Rc<T>`, etc.
34    DynStar,
35}
36
37#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
38#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
39pub enum AliasTyKind {
40    /// A projection `<Type as Trait>::AssocType`.
41    /// Can get normalized away if monomorphic enough.
42    Projection,
43    /// An associated type in an inherent `impl`
44    Inherent,
45    /// An opaque type (usually from `impl Trait` in type aliases or function return types)
46    /// Can only be normalized away in PostAnalysis mode or its defining scope.
47    Opaque,
48    /// A type alias that actually checks its trait bounds.
49    /// Currently only used if the type alias references opaque types.
50    /// Can always be normalized away.
51    Weak,
52}
53
54impl AliasTyKind {
55    pub fn descr(self) -> &'static str {
56        match self {
57            AliasTyKind::Projection => "associated type",
58            AliasTyKind::Inherent => "inherent associated type",
59            AliasTyKind::Opaque => "opaque type",
60            AliasTyKind::Weak => "type alias",
61        }
62    }
63}
64
65/// Defines the kinds of types used by the type system.
66///
67/// Types written by the user start out as `hir::TyKind` and get
68/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
69#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
70#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
71#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
72pub enum TyKind<I: Interner> {
73    /// The primitive boolean type. Written as `bool`.
74    Bool,
75
76    /// The primitive character type; holds a Unicode scalar value
77    /// (a non-surrogate code point). Written as `char`.
78    Char,
79
80    /// A primitive signed integer type. For example, `i32`.
81    Int(IntTy),
82
83    /// A primitive unsigned integer type. For example, `u32`.
84    Uint(UintTy),
85
86    /// A primitive floating-point type. For example, `f64`.
87    Float(FloatTy),
88
89    /// Algebraic data types (ADT). For example: structures, enumerations and unions.
90    ///
91    /// For example, the type `List<i32>` would be represented using the `AdtDef`
92    /// for `struct List<T>` and the args `[i32]`.
93    ///
94    /// Note that generic parameters in fields only get lazily instantiated
95    /// by using something like `adt_def.all_fields().map(|field| field.ty(interner, args))`.
96    Adt(I::AdtDef, I::GenericArgs),
97
98    /// An unsized FFI type that is opaque to Rust. Written as `extern type T`.
99    Foreign(I::DefId),
100
101    /// The pointee of a string slice. Written as `str`.
102    Str,
103
104    /// An array with the given length. Written as `[T; N]`.
105    Array(I::Ty, I::Const),
106
107    /// A pattern newtype. Takes any type and restricts its valid values to its pattern.
108    /// This will also change the layout to take advantage of this restriction.
109    /// Only `Copy` and `Clone` will automatically get implemented for pattern types.
110    /// Auto-traits treat this as if it were an aggregate with a single nested type.
111    /// Only supports integer range patterns for now.
112    Pat(I::Ty, I::Pat),
113
114    /// The pointee of an array slice. Written as `[T]`.
115    Slice(I::Ty),
116
117    /// A raw pointer. Written as `*mut T` or `*const T`
118    RawPtr(I::Ty, Mutability),
119
120    /// A reference; a pointer with an associated lifetime. Written as
121    /// `&'a mut T` or `&'a T`.
122    Ref(I::Region, I::Ty, Mutability),
123
124    /// The anonymous type of a function declaration/definition. Each
125    /// function has a unique type.
126    ///
127    /// For the function `fn foo() -> i32 { 3 }` this type would be
128    /// shown to the user as `fn() -> i32 {foo}`.
129    ///
130    /// For example the type of `bar` here:
131    /// ```rust
132    /// fn foo() -> i32 { 1 }
133    /// let bar = foo; // bar: fn() -> i32 {foo}
134    /// ```
135    FnDef(I::DefId, I::GenericArgs),
136
137    /// A pointer to a function. Written as `fn() -> i32`.
138    ///
139    /// Note that both functions and closures start out as either
140    /// [FnDef] or [Closure] which can be then be coerced to this variant.
141    ///
142    /// For example the type of `bar` here:
143    ///
144    /// ```rust
145    /// fn foo() -> i32 { 1 }
146    /// let bar: fn() -> i32 = foo;
147    /// ```
148    ///
149    /// These two fields are equivalent to a `ty::Binder<I, FnSig<I>>`. But by
150    /// splitting that into two pieces, we get a more compact data layout that
151    /// reduces the size of `TyKind` by 8 bytes. It is a very hot type, so it's
152    /// worth the mild inconvenience.
153    FnPtr(ty::Binder<I, FnSigTys<I>>, FnHeader<I>),
154
155    /// An unsafe binder type.
156    ///
157    /// A higher-ranked type used to represent a type which has had some of its
158    /// lifetimes erased. This can be used to represent types in positions where
159    /// a lifetime is literally inexpressible, such as self-referential types.
160    UnsafeBinder(UnsafeBinderInner<I>),
161
162    /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
163    Dynamic(I::BoundExistentialPredicates, I::Region, DynKind),
164
165    /// The anonymous type of a closure. Used to represent the type of `|a| a`.
166    ///
167    /// Closure args contain both the - potentially instantiated - generic parameters
168    /// of its parent and some synthetic parameters. See the documentation for
169    /// `ClosureArgs` for more details.
170    Closure(I::DefId, I::GenericArgs),
171
172    /// The anonymous type of a closure. Used to represent the type of `async |a| a`.
173    ///
174    /// Coroutine-closure args contain both the - potentially instantiated - generic
175    /// parameters of its parent and some synthetic parameters. See the documentation
176    /// for `CoroutineClosureArgs` for more details.
177    CoroutineClosure(I::DefId, I::GenericArgs),
178
179    /// The anonymous type of a coroutine. Used to represent the type of
180    /// `|a| yield a`.
181    ///
182    /// For more info about coroutine args, visit the documentation for
183    /// `CoroutineArgs`.
184    Coroutine(I::DefId, I::GenericArgs),
185
186    /// A type representing the types stored inside a coroutine.
187    /// This should only appear as part of the `CoroutineArgs`.
188    ///
189    /// Unlike upvars, the witness can reference lifetimes from
190    /// inside of the coroutine itself. To deal with them in
191    /// the type of the coroutine, we convert them to higher ranked
192    /// lifetimes bound by the witness itself.
193    ///
194    /// This contains the `DefId` and the `GenericArgsRef` of the coroutine.
195    /// The actual witness types are computed on MIR by the `mir_coroutine_witnesses` query.
196    ///
197    /// Looking at the following example, the witness for this coroutine
198    /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
199    ///
200    /// ```
201    /// #![feature(coroutines)]
202    /// #[coroutine] static |a| {
203    ///     let x = &vec![3];
204    ///     yield a;
205    ///     yield x[0];
206    /// }
207    /// # ;
208    /// ```
209    CoroutineWitness(I::DefId, I::GenericArgs),
210
211    /// The never type `!`.
212    Never,
213
214    /// A tuple type. For example, `(i32, bool)`.
215    Tuple(I::Tys),
216
217    /// A projection, opaque type, weak type alias, or inherent associated type.
218    /// All of these types are represented as pairs of def-id and args, and can
219    /// be normalized, so they are grouped conceptually.
220    Alias(AliasTyKind, AliasTy<I>),
221
222    /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
223    Param(I::ParamTy),
224
225    /// Bound type variable, used to represent the `'a` in `for<'a> fn(&'a ())`.
226    ///
227    /// For canonical queries, we replace inference variables with bound variables,
228    /// so e.g. when checking whether `&'_ (): Trait<_>` holds, we canonicalize that to
229    /// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables
230    /// back to inference variables in a new inference context when inside of the query.
231    ///
232    /// It is conventional to render anonymous bound types like `^N` or `^D_N`,
233    /// where `N` is the bound variable's anonymous index into the binder, and
234    /// `D` is the debruijn index, or totally omitted if the debruijn index is zero.
235    ///
236    /// See the `rustc-dev-guide` for more details about
237    /// [higher-ranked trait bounds][1] and [canonical queries][2].
238    ///
239    /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
240    /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html
241    Bound(DebruijnIndex, I::BoundTy),
242
243    /// A placeholder type, used during higher ranked subtyping to instantiate
244    /// bound variables.
245    ///
246    /// It is conventional to render anonymous placeholder types like `!N` or `!U_N`,
247    /// where `N` is the placeholder variable's anonymous index (which corresponds
248    /// to the bound variable's index from the binder from which it was instantiated),
249    /// and `U` is the universe index in which it is instantiated, or totally omitted
250    /// if the universe index is zero.
251    Placeholder(I::PlaceholderTy),
252
253    /// A type variable used during type checking.
254    ///
255    /// Similar to placeholders, inference variables also live in a universe to
256    /// correctly deal with higher ranked types. Though unlike placeholders,
257    /// that universe is stored in the `InferCtxt` instead of directly
258    /// inside of the type.
259    Infer(InferTy),
260
261    /// A placeholder for a type which could not be computed; this is
262    /// propagated to avoid useless error messages.
263    Error(I::ErrorGuaranteed),
264}
265
266// This is manually implemented because a derive would require `I: Debug`
267impl<I: Interner> fmt::Debug for TyKind<I> {
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        match self {
270            Bool => write!(f, "bool"),
271            Char => write!(f, "char"),
272            Int(i) => write!(f, "{i:?}"),
273            Uint(u) => write!(f, "{u:?}"),
274            Float(float) => write!(f, "{float:?}"),
275            Adt(d, s) => {
276                write!(f, "{d:?}")?;
277                let mut s = s.iter();
278                let first = s.next();
279                match first {
280                    Some(first) => write!(f, "<{:?}", first)?,
281                    None => return Ok(()),
282                };
283
284                for arg in s {
285                    write!(f, ", {:?}", arg)?;
286                }
287
288                write!(f, ">")
289            }
290            Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
291            Str => write!(f, "str"),
292            Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
293            Pat(t, p) => write!(f, "pattern_type!({t:?} is {p:?})"),
294            Slice(t) => write!(f, "[{:?}]", &t),
295            RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), ty),
296            Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t),
297            FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(),
298            FnPtr(sig_tys, hdr) => write!(f, "{:?}", sig_tys.with(*hdr)),
299            // FIXME(unsafe_binder): print this like `unsafe<'a> T<'a>`.
300            UnsafeBinder(binder) => write!(f, "{:?}", binder),
301            Dynamic(p, r, repr) => match repr {
302                DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
303                DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
304            },
305            Closure(d, s) => f.debug_tuple("Closure").field(d).field(&s).finish(),
306            CoroutineClosure(d, s) => f.debug_tuple("CoroutineClosure").field(d).field(&s).finish(),
307            Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&s).finish(),
308            CoroutineWitness(d, s) => f.debug_tuple("CoroutineWitness").field(d).field(&s).finish(),
309            Never => write!(f, "!"),
310            Tuple(t) => {
311                write!(f, "(")?;
312                let mut count = 0;
313                for ty in t.iter() {
314                    if count > 0 {
315                        write!(f, ", ")?;
316                    }
317                    write!(f, "{ty:?}")?;
318                    count += 1;
319                }
320                // unary tuples need a trailing comma
321                if count == 1 {
322                    write!(f, ",")?;
323                }
324                write!(f, ")")
325            }
326            Alias(i, a) => f.debug_tuple("Alias").field(i).field(&a).finish(),
327            Param(p) => write!(f, "{p:?}"),
328            Bound(d, b) => crate::debug_bound_var(f, *d, b),
329            Placeholder(p) => write!(f, "{p:?}"),
330            Infer(t) => write!(f, "{:?}", t),
331            TyKind::Error(_) => write!(f, "{{type error}}"),
332        }
333    }
334}
335
336/// Represents the projection of an associated, opaque, or lazy-type-alias type.
337///
338/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
339/// * For an inherent projection, this would be `Ty::N<...>`.
340/// * For an opaque type, there is no explicit syntax.
341#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
342#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
343#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
344pub struct AliasTy<I: Interner> {
345    /// The parameters of the associated or opaque type.
346    ///
347    /// For a projection, these are the generic parameters for the trait and the
348    /// GAT parameters, if there are any.
349    ///
350    /// For an inherent projection, they consist of the self type and the GAT parameters,
351    /// if there are any.
352    ///
353    /// For RPIT the generic parameters are for the generics of the function,
354    /// while for TAIT it is used for the generic parameters of the alias.
355    pub args: I::GenericArgs,
356
357    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
358    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
359    /// this is an opaque.
360    ///
361    /// During codegen, `interner.type_of(def_id)` can be used to get the type of the
362    /// underlying type if the type is an opaque.
363    ///
364    /// Note that if this is an associated type, this is not the `DefId` of the
365    /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
366    /// aka. `interner.parent(def_id)`.
367    pub def_id: I::DefId,
368
369    /// This field exists to prevent the creation of `AliasTy` without using [`AliasTy::new_from_args`].
370    #[derive_where(skip(Debug))]
371    pub(crate) _use_alias_ty_new_instead: (),
372}
373
374impl<I: Interner> AliasTy<I> {
375    pub fn new_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTy<I> {
376        interner.debug_assert_args_compatible(def_id, args);
377        AliasTy { def_id, args, _use_alias_ty_new_instead: () }
378    }
379
380    pub fn new(
381        interner: I,
382        def_id: I::DefId,
383        args: impl IntoIterator<Item: Into<I::GenericArg>>,
384    ) -> AliasTy<I> {
385        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
386        Self::new_from_args(interner, def_id, args)
387    }
388
389    pub fn kind(self, interner: I) -> AliasTyKind {
390        interner.alias_ty_kind(self)
391    }
392
393    /// Whether this alias type is an opaque.
394    pub fn is_opaque(self, interner: I) -> bool {
395        matches!(self.kind(interner), AliasTyKind::Opaque)
396    }
397
398    pub fn to_ty(self, interner: I) -> I::Ty {
399        Ty::new_alias(interner, self.kind(interner), self)
400    }
401}
402
403/// The following methods work only with (trait) associated type projections.
404impl<I: Interner> AliasTy<I> {
405    pub fn self_ty(self) -> I::Ty {
406        self.args.type_at(0)
407    }
408
409    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
410        AliasTy::new(
411            interner,
412            self.def_id,
413            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
414        )
415    }
416
417    pub fn trait_def_id(self, interner: I) -> I::DefId {
418        assert_eq!(self.kind(interner), AliasTyKind::Projection, "expected a projection");
419        interner.parent(self.def_id)
420    }
421
422    /// Extracts the underlying trait reference and own args from this projection.
423    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
424    /// then this function would return a `T: StreamingIterator` trait reference and
425    /// `['a]` as the own args.
426    pub fn trait_ref_and_own_args(self, interner: I) -> (ty::TraitRef<I>, I::GenericArgsSlice) {
427        debug_assert_eq!(self.kind(interner), AliasTyKind::Projection);
428        interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
429    }
430
431    /// Extracts the underlying trait reference from this projection.
432    /// For example, if this is a projection of `<T as Iterator>::Item`,
433    /// then this function would return a `T: Iterator` trait reference.
434    ///
435    /// WARNING: This will drop the args for generic associated types
436    /// consider calling [Self::trait_ref_and_own_args] to get those
437    /// as well.
438    pub fn trait_ref(self, interner: I) -> ty::TraitRef<I> {
439        self.trait_ref_and_own_args(interner).0
440    }
441}
442
443/// The following methods work only with inherent associated type projections.
444impl<I: Interner> AliasTy<I> {
445    /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that.
446    ///
447    /// Does the following transformation:
448    ///
449    /// ```text
450    /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
451    ///
452    ///     I_i impl args
453    ///     P_j GAT args
454    /// ```
455    pub fn rebase_inherent_args_onto_impl(
456        self,
457        impl_args: I::GenericArgs,
458        interner: I,
459    ) -> I::GenericArgs {
460        debug_assert_eq!(self.kind(interner), AliasTyKind::Inherent);
461        interner.mk_args_from_iter(impl_args.iter().chain(self.args.iter().skip(1)))
462    }
463}
464
465#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
466#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
467pub enum IntTy {
468    Isize,
469    I8,
470    I16,
471    I32,
472    I64,
473    I128,
474}
475
476impl IntTy {
477    pub fn name_str(&self) -> &'static str {
478        match *self {
479            IntTy::Isize => "isize",
480            IntTy::I8 => "i8",
481            IntTy::I16 => "i16",
482            IntTy::I32 => "i32",
483            IntTy::I64 => "i64",
484            IntTy::I128 => "i128",
485        }
486    }
487
488    pub fn bit_width(&self) -> Option<u64> {
489        Some(match *self {
490            IntTy::Isize => return None,
491            IntTy::I8 => 8,
492            IntTy::I16 => 16,
493            IntTy::I32 => 32,
494            IntTy::I64 => 64,
495            IntTy::I128 => 128,
496        })
497    }
498
499    pub fn normalize(&self, target_width: u32) -> Self {
500        match self {
501            IntTy::Isize => match target_width {
502                16 => IntTy::I16,
503                32 => IntTy::I32,
504                64 => IntTy::I64,
505                _ => unreachable!(),
506            },
507            _ => *self,
508        }
509    }
510
511    pub fn to_unsigned(self) -> UintTy {
512        match self {
513            IntTy::Isize => UintTy::Usize,
514            IntTy::I8 => UintTy::U8,
515            IntTy::I16 => UintTy::U16,
516            IntTy::I32 => UintTy::U32,
517            IntTy::I64 => UintTy::U64,
518            IntTy::I128 => UintTy::U128,
519        }
520    }
521}
522
523#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
524#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
525pub enum UintTy {
526    Usize,
527    U8,
528    U16,
529    U32,
530    U64,
531    U128,
532}
533
534impl UintTy {
535    pub fn name_str(&self) -> &'static str {
536        match *self {
537            UintTy::Usize => "usize",
538            UintTy::U8 => "u8",
539            UintTy::U16 => "u16",
540            UintTy::U32 => "u32",
541            UintTy::U64 => "u64",
542            UintTy::U128 => "u128",
543        }
544    }
545
546    pub fn bit_width(&self) -> Option<u64> {
547        Some(match *self {
548            UintTy::Usize => return None,
549            UintTy::U8 => 8,
550            UintTy::U16 => 16,
551            UintTy::U32 => 32,
552            UintTy::U64 => 64,
553            UintTy::U128 => 128,
554        })
555    }
556
557    pub fn normalize(&self, target_width: u32) -> Self {
558        match self {
559            UintTy::Usize => match target_width {
560                16 => UintTy::U16,
561                32 => UintTy::U32,
562                64 => UintTy::U64,
563                _ => unreachable!(),
564            },
565            _ => *self,
566        }
567    }
568
569    pub fn to_signed(self) -> IntTy {
570        match self {
571            UintTy::Usize => IntTy::Isize,
572            UintTy::U8 => IntTy::I8,
573            UintTy::U16 => IntTy::I16,
574            UintTy::U32 => IntTy::I32,
575            UintTy::U64 => IntTy::I64,
576            UintTy::U128 => IntTy::I128,
577        }
578    }
579}
580
581#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
582#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
583pub enum FloatTy {
584    F16,
585    F32,
586    F64,
587    F128,
588}
589
590impl FloatTy {
591    pub fn name_str(self) -> &'static str {
592        match self {
593            FloatTy::F16 => "f16",
594            FloatTy::F32 => "f32",
595            FloatTy::F64 => "f64",
596            FloatTy::F128 => "f128",
597        }
598    }
599
600    pub fn bit_width(self) -> u64 {
601        match self {
602            FloatTy::F16 => 16,
603            FloatTy::F32 => 32,
604            FloatTy::F64 => 64,
605            FloatTy::F128 => 128,
606        }
607    }
608}
609
610#[derive(Clone, Copy, PartialEq, Eq, Debug)]
611pub enum IntVarValue {
612    Unknown,
613    IntType(IntTy),
614    UintType(UintTy),
615}
616
617impl IntVarValue {
618    pub fn is_known(self) -> bool {
619        match self {
620            IntVarValue::IntType(_) | IntVarValue::UintType(_) => true,
621            IntVarValue::Unknown => false,
622        }
623    }
624
625    pub fn is_unknown(self) -> bool {
626        !self.is_known()
627    }
628}
629
630#[derive(Clone, Copy, PartialEq, Eq, Debug)]
631pub enum FloatVarValue {
632    Unknown,
633    Known(FloatTy),
634}
635
636impl FloatVarValue {
637    pub fn is_known(self) -> bool {
638        match self {
639            FloatVarValue::Known(_) => true,
640            FloatVarValue::Unknown => false,
641        }
642    }
643
644    pub fn is_unknown(self) -> bool {
645        !self.is_known()
646    }
647}
648
649rustc_index::newtype_index! {
650    /// A **ty**pe **v**ariable **ID**.
651    #[encodable]
652    #[orderable]
653    #[debug_format = "?{}t"]
654    #[gate_rustc_only]
655    pub struct TyVid {}
656}
657
658rustc_index::newtype_index! {
659    /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
660    #[encodable]
661    #[orderable]
662    #[debug_format = "?{}i"]
663    #[gate_rustc_only]
664    pub struct IntVid {}
665}
666
667rustc_index::newtype_index! {
668    /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
669    #[encodable]
670    #[orderable]
671    #[debug_format = "?{}f"]
672    #[gate_rustc_only]
673    pub struct FloatVid {}
674}
675
676/// A placeholder for a type that hasn't been inferred yet.
677///
678/// E.g., if we have an empty array (`[]`), then we create a fresh
679/// type variable for the element type since we won't know until it's
680/// used what the element type is supposed to be.
681#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
682#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))]
683pub enum InferTy {
684    /// A type variable.
685    TyVar(TyVid),
686    /// An integral type variable (`{integer}`).
687    ///
688    /// These are created when the compiler sees an integer literal like
689    /// `1` that could be several different types (`u8`, `i32`, `u32`, etc.).
690    /// We don't know until it's used what type it's supposed to be, so
691    /// we create a fresh type variable.
692    IntVar(IntVid),
693    /// A floating-point type variable (`{float}`).
694    ///
695    /// These are created when the compiler sees an float literal like
696    /// `1.0` that could be either an `f32` or an `f64`.
697    /// We don't know until it's used what type it's supposed to be, so
698    /// we create a fresh type variable.
699    FloatVar(FloatVid),
700
701    /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement
702    /// for an unbound type variable. This is convenient for caching etc. See
703    /// `rustc_infer::infer::freshen` for more details.
704    ///
705    /// Compare with [`TyVar`][Self::TyVar].
706    FreshTy(u32),
707    /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`IntVar`][Self::IntVar].
708    FreshIntTy(u32),
709    /// Like [`FreshTy`][Self::FreshTy], but as a replacement for [`FloatVar`][Self::FloatVar].
710    FreshFloatTy(u32),
711}
712
713/// Raw `TyVid` are used as the unification key for `sub_relations`;
714/// they carry no values.
715#[cfg(feature = "nightly")]
716impl UnifyKey for TyVid {
717    type Value = ();
718    #[inline]
719    fn index(&self) -> u32 {
720        self.as_u32()
721    }
722    #[inline]
723    fn from_index(i: u32) -> TyVid {
724        TyVid::from_u32(i)
725    }
726    fn tag() -> &'static str {
727        "TyVid"
728    }
729}
730
731#[cfg(feature = "nightly")]
732impl UnifyValue for IntVarValue {
733    type Error = NoError;
734
735    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
736        match (*value1, *value2) {
737            (IntVarValue::Unknown, IntVarValue::Unknown) => Ok(IntVarValue::Unknown),
738            (
739                IntVarValue::Unknown,
740                known @ (IntVarValue::UintType(_) | IntVarValue::IntType(_)),
741            )
742            | (
743                known @ (IntVarValue::UintType(_) | IntVarValue::IntType(_)),
744                IntVarValue::Unknown,
745            ) => Ok(known),
746            _ => panic!("differing ints should have been resolved first"),
747        }
748    }
749}
750
751#[cfg(feature = "nightly")]
752impl UnifyKey for IntVid {
753    type Value = IntVarValue;
754    #[inline] // make this function eligible for inlining - it is quite hot.
755    fn index(&self) -> u32 {
756        self.as_u32()
757    }
758    #[inline]
759    fn from_index(i: u32) -> IntVid {
760        IntVid::from_u32(i)
761    }
762    fn tag() -> &'static str {
763        "IntVid"
764    }
765}
766
767#[cfg(feature = "nightly")]
768impl UnifyValue for FloatVarValue {
769    type Error = NoError;
770
771    fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
772        match (*value1, *value2) {
773            (FloatVarValue::Unknown, FloatVarValue::Unknown) => Ok(FloatVarValue::Unknown),
774            (FloatVarValue::Unknown, FloatVarValue::Known(known))
775            | (FloatVarValue::Known(known), FloatVarValue::Unknown) => {
776                Ok(FloatVarValue::Known(known))
777            }
778            (FloatVarValue::Known(_), FloatVarValue::Known(_)) => {
779                panic!("differing floats should have been resolved first")
780            }
781        }
782    }
783}
784
785#[cfg(feature = "nightly")]
786impl UnifyKey for FloatVid {
787    type Value = FloatVarValue;
788    #[inline]
789    fn index(&self) -> u32 {
790        self.as_u32()
791    }
792    #[inline]
793    fn from_index(i: u32) -> FloatVid {
794        FloatVid::from_u32(i)
795    }
796    fn tag() -> &'static str {
797        "FloatVid"
798    }
799}
800
801#[cfg(feature = "nightly")]
802impl<CTX> HashStable<CTX> for InferTy {
803    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
804        use InferTy::*;
805        std::mem::discriminant(self).hash_stable(ctx, hasher);
806        match self {
807            TyVar(_) | IntVar(_) | FloatVar(_) => {
808                panic!("type variables should not be hashed: {self:?}")
809            }
810            FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher),
811        }
812    }
813}
814
815impl fmt::Display for InferTy {
816    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817        use InferTy::*;
818        match *self {
819            TyVar(_) => write!(f, "_"),
820            IntVar(_) => write!(f, "{}", "{integer}"),
821            FloatVar(_) => write!(f, "{}", "{float}"),
822            FreshTy(v) => write!(f, "FreshTy({v})"),
823            FreshIntTy(v) => write!(f, "FreshIntTy({v})"),
824            FreshFloatTy(v) => write!(f, "FreshFloatTy({v})"),
825        }
826    }
827}
828
829impl fmt::Debug for IntTy {
830    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
831        write!(f, "{}", self.name_str())
832    }
833}
834
835impl fmt::Debug for UintTy {
836    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
837        write!(f, "{}", self.name_str())
838    }
839}
840
841impl fmt::Debug for FloatTy {
842    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
843        write!(f, "{}", self.name_str())
844    }
845}
846
847impl fmt::Debug for InferTy {
848    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
849        use InferTy::*;
850        match *self {
851            TyVar(ref v) => v.fmt(f),
852            IntVar(ref v) => v.fmt(f),
853            FloatVar(ref v) => v.fmt(f),
854            FreshTy(v) => write!(f, "FreshTy({v:?})"),
855            FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
856            FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
857        }
858    }
859}
860
861#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
862#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
863#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
864pub struct TypeAndMut<I: Interner> {
865    pub ty: I::Ty,
866    pub mutbl: Mutability,
867}
868
869#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
870#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
871#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
872pub struct FnSig<I: Interner> {
873    pub inputs_and_output: I::Tys,
874    pub c_variadic: bool,
875    #[type_visitable(ignore)]
876    #[type_foldable(identity)]
877    pub safety: I::Safety,
878    #[type_visitable(ignore)]
879    #[type_foldable(identity)]
880    pub abi: I::Abi,
881}
882
883impl<I: Interner> FnSig<I> {
884    pub fn inputs(self) -> I::FnInputTys {
885        self.inputs_and_output.inputs()
886    }
887
888    pub fn output(self) -> I::Ty {
889        self.inputs_and_output.output()
890    }
891
892    pub fn is_fn_trait_compatible(self) -> bool {
893        let FnSig { safety, abi, c_variadic, .. } = self;
894        !c_variadic && safety.is_safe() && abi.is_rust()
895    }
896}
897
898impl<I: Interner> ty::Binder<I, FnSig<I>> {
899    #[inline]
900    pub fn inputs(self) -> ty::Binder<I, I::FnInputTys> {
901        self.map_bound(|fn_sig| fn_sig.inputs())
902    }
903
904    #[inline]
905    #[track_caller]
906    pub fn input(self, index: usize) -> ty::Binder<I, I::Ty> {
907        self.map_bound(|fn_sig| fn_sig.inputs().get(index).unwrap())
908    }
909
910    pub fn inputs_and_output(self) -> ty::Binder<I, I::Tys> {
911        self.map_bound(|fn_sig| fn_sig.inputs_and_output)
912    }
913
914    #[inline]
915    pub fn output(self) -> ty::Binder<I, I::Ty> {
916        self.map_bound(|fn_sig| fn_sig.output())
917    }
918
919    pub fn c_variadic(self) -> bool {
920        self.skip_binder().c_variadic
921    }
922
923    pub fn safety(self) -> I::Safety {
924        self.skip_binder().safety
925    }
926
927    pub fn abi(self) -> I::Abi {
928        self.skip_binder().abi
929    }
930
931    pub fn is_fn_trait_compatible(&self) -> bool {
932        self.skip_binder().is_fn_trait_compatible()
933    }
934
935    // Used to split a single value into the two fields in `TyKind::FnPtr`.
936    pub fn split(self) -> (ty::Binder<I, FnSigTys<I>>, FnHeader<I>) {
937        let hdr =
938            FnHeader { c_variadic: self.c_variadic(), safety: self.safety(), abi: self.abi() };
939        (self.map_bound(|sig| FnSigTys { inputs_and_output: sig.inputs_and_output }), hdr)
940    }
941}
942
943impl<I: Interner> fmt::Debug for FnSig<I> {
944    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945        let sig = self;
946        let FnSig { inputs_and_output: _, c_variadic, safety, abi } = sig;
947
948        write!(f, "{}", safety.prefix_str())?;
949        if !abi.is_rust() {
950            write!(f, "extern \"{abi:?}\" ")?;
951        }
952
953        write!(f, "fn(")?;
954        let inputs = sig.inputs();
955        for (i, ty) in inputs.iter().enumerate() {
956            if i > 0 {
957                write!(f, ", ")?;
958            }
959            write!(f, "{ty:?}")?;
960        }
961        if *c_variadic {
962            if inputs.is_empty() {
963                write!(f, "...")?;
964            } else {
965                write!(f, ", ...")?;
966            }
967        }
968        write!(f, ")")?;
969
970        let output = sig.output();
971        match output.kind() {
972            Tuple(list) if list.is_empty() => Ok(()),
973            _ => write!(f, " -> {:?}", sig.output()),
974        }
975    }
976}
977
978// FIXME: this is a distinct type because we need to define `Encode`/`Decode`
979// impls in this crate for `Binder<I, I::Ty>`.
980#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
981#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
982#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
983pub struct UnsafeBinderInner<I: Interner>(ty::Binder<I, I::Ty>);
984
985impl<I: Interner> From<ty::Binder<I, I::Ty>> for UnsafeBinderInner<I> {
986    fn from(value: ty::Binder<I, I::Ty>) -> Self {
987        UnsafeBinderInner(value)
988    }
989}
990
991impl<I: Interner> From<UnsafeBinderInner<I>> for ty::Binder<I, I::Ty> {
992    fn from(value: UnsafeBinderInner<I>) -> Self {
993        value.0
994    }
995}
996
997impl<I: Interner> fmt::Debug for UnsafeBinderInner<I> {
998    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
999        self.0.fmt(f)
1000    }
1001}
1002
1003impl<I: Interner> Deref for UnsafeBinderInner<I> {
1004    type Target = ty::Binder<I, I::Ty>;
1005
1006    fn deref(&self) -> &Self::Target {
1007        &self.0
1008    }
1009}
1010
1011#[cfg(feature = "nightly")]
1012impl<I: Interner, E: crate::TyEncoder<I = I>> rustc_serialize::Encodable<E> for UnsafeBinderInner<I>
1013where
1014    I::Ty: rustc_serialize::Encodable<E>,
1015    I::BoundVarKinds: rustc_serialize::Encodable<E>,
1016{
1017    fn encode(&self, e: &mut E) {
1018        self.bound_vars().encode(e);
1019        self.as_ref().skip_binder().encode(e);
1020    }
1021}
1022
1023#[cfg(feature = "nightly")]
1024impl<I: Interner, D: crate::TyDecoder<I = I>> rustc_serialize::Decodable<D> for UnsafeBinderInner<I>
1025where
1026    I::Ty: TypeVisitable<I> + rustc_serialize::Decodable<D>,
1027    I::BoundVarKinds: rustc_serialize::Decodable<D>,
1028{
1029    fn decode(decoder: &mut D) -> Self {
1030        let bound_vars = rustc_serialize::Decodable::decode(decoder);
1031        UnsafeBinderInner(ty::Binder::bind_with_vars(
1032            rustc_serialize::Decodable::decode(decoder),
1033            bound_vars,
1034        ))
1035    }
1036}
1037
1038// This is just a `FnSig` without the `FnHeader` fields.
1039#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
1040#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
1041#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
1042pub struct FnSigTys<I: Interner> {
1043    pub inputs_and_output: I::Tys,
1044}
1045
1046impl<I: Interner> FnSigTys<I> {
1047    pub fn inputs(self) -> I::FnInputTys {
1048        self.inputs_and_output.inputs()
1049    }
1050
1051    pub fn output(self) -> I::Ty {
1052        self.inputs_and_output.output()
1053    }
1054}
1055
1056impl<I: Interner> ty::Binder<I, FnSigTys<I>> {
1057    // Used to combine the two fields in `TyKind::FnPtr` into a single value.
1058    pub fn with(self, hdr: FnHeader<I>) -> ty::Binder<I, FnSig<I>> {
1059        self.map_bound(|sig_tys| FnSig {
1060            inputs_and_output: sig_tys.inputs_and_output,
1061            c_variadic: hdr.c_variadic,
1062            safety: hdr.safety,
1063            abi: hdr.abi,
1064        })
1065    }
1066
1067    #[inline]
1068    pub fn inputs(self) -> ty::Binder<I, I::FnInputTys> {
1069        self.map_bound(|sig_tys| sig_tys.inputs())
1070    }
1071
1072    #[inline]
1073    #[track_caller]
1074    pub fn input(self, index: usize) -> ty::Binder<I, I::Ty> {
1075        self.map_bound(|sig_tys| sig_tys.inputs().get(index).unwrap())
1076    }
1077
1078    pub fn inputs_and_output(self) -> ty::Binder<I, I::Tys> {
1079        self.map_bound(|sig_tys| sig_tys.inputs_and_output)
1080    }
1081
1082    #[inline]
1083    pub fn output(self) -> ty::Binder<I, I::Ty> {
1084        self.map_bound(|sig_tys| sig_tys.output())
1085    }
1086}
1087
1088#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
1089#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
1090#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
1091pub struct FnHeader<I: Interner> {
1092    pub c_variadic: bool,
1093    pub safety: I::Safety,
1094    pub abi: I::Abi,
1095}