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