Skip to main content

rustc_type_ir/
fast_reject.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3use std::iter;
4use std::marker::PhantomData;
5
6use rustc_ast_ir::Mutability;
7#[cfg(feature = "nightly")]
8use rustc_data_structures::fingerprint::Fingerprint;
9#[cfg(feature = "nightly")]
10use rustc_data_structures::stable_hasher::{
11    HashStable, HashStableContext, StableHasher, ToStableHashKey,
12};
13#[cfg(feature = "nightly")]
14use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable};
15
16use crate::inherent::*;
17use crate::visit::TypeVisitableExt as _;
18use crate::{self as ty, Interner};
19
20/// See `simplify_type`.
21#[derive(#[automatically_derived]
impl<DefId: ::core::clone::Clone> ::core::clone::Clone for
    SimplifiedType<DefId> {
    #[inline]
    fn clone(&self) -> SimplifiedType<DefId> {
        match self {
            SimplifiedType::Bool => SimplifiedType::Bool,
            SimplifiedType::Char => SimplifiedType::Char,
            SimplifiedType::Int(__self_0) =>
                SimplifiedType::Int(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Uint(__self_0) =>
                SimplifiedType::Uint(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Float(__self_0) =>
                SimplifiedType::Float(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Adt(__self_0) =>
                SimplifiedType::Adt(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Foreign(__self_0) =>
                SimplifiedType::Foreign(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Str => SimplifiedType::Str,
            SimplifiedType::Array => SimplifiedType::Array,
            SimplifiedType::Slice => SimplifiedType::Slice,
            SimplifiedType::Ref(__self_0) =>
                SimplifiedType::Ref(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Ptr(__self_0) =>
                SimplifiedType::Ptr(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Never => SimplifiedType::Never,
            SimplifiedType::Tuple(__self_0) =>
                SimplifiedType::Tuple(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::MarkerTraitObject =>
                SimplifiedType::MarkerTraitObject,
            SimplifiedType::Trait(__self_0) =>
                SimplifiedType::Trait(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Closure(__self_0) =>
                SimplifiedType::Closure(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Coroutine(__self_0) =>
                SimplifiedType::Coroutine(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::CoroutineWitness(__self_0) =>
                SimplifiedType::CoroutineWitness(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::Function(__self_0) =>
                SimplifiedType::Function(::core::clone::Clone::clone(__self_0)),
            SimplifiedType::UnsafeBinder => SimplifiedType::UnsafeBinder,
            SimplifiedType::Placeholder => SimplifiedType::Placeholder,
            SimplifiedType::Error => SimplifiedType::Error,
        }
    }
}Clone, #[automatically_derived]
impl<DefId: ::core::marker::Copy> ::core::marker::Copy for
    SimplifiedType<DefId> {
}Copy, #[automatically_derived]
impl<DefId: ::core::fmt::Debug> ::core::fmt::Debug for SimplifiedType<DefId> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            SimplifiedType::Bool =>
                ::core::fmt::Formatter::write_str(f, "Bool"),
            SimplifiedType::Char =>
                ::core::fmt::Formatter::write_str(f, "Char"),
            SimplifiedType::Int(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Int",
                    &__self_0),
            SimplifiedType::Uint(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Uint",
                    &__self_0),
            SimplifiedType::Float(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Float",
                    &__self_0),
            SimplifiedType::Adt(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Adt",
                    &__self_0),
            SimplifiedType::Foreign(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Foreign", &__self_0),
            SimplifiedType::Str =>
                ::core::fmt::Formatter::write_str(f, "Str"),
            SimplifiedType::Array =>
                ::core::fmt::Formatter::write_str(f, "Array"),
            SimplifiedType::Slice =>
                ::core::fmt::Formatter::write_str(f, "Slice"),
            SimplifiedType::Ref(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ref",
                    &__self_0),
            SimplifiedType::Ptr(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ptr",
                    &__self_0),
            SimplifiedType::Never =>
                ::core::fmt::Formatter::write_str(f, "Never"),
            SimplifiedType::Tuple(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Tuple",
                    &__self_0),
            SimplifiedType::MarkerTraitObject =>
                ::core::fmt::Formatter::write_str(f, "MarkerTraitObject"),
            SimplifiedType::Trait(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Trait",
                    &__self_0),
            SimplifiedType::Closure(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Closure", &__self_0),
            SimplifiedType::Coroutine(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Coroutine", &__self_0),
            SimplifiedType::CoroutineWitness(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "CoroutineWitness", &__self_0),
            SimplifiedType::Function(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Function", &__self_0),
            SimplifiedType::UnsafeBinder =>
                ::core::fmt::Formatter::write_str(f, "UnsafeBinder"),
            SimplifiedType::Placeholder =>
                ::core::fmt::Formatter::write_str(f, "Placeholder"),
            SimplifiedType::Error =>
                ::core::fmt::Formatter::write_str(f, "Error"),
        }
    }
}Debug, #[automatically_derived]
impl<DefId: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
    SimplifiedType<DefId> {
    #[inline]
    fn eq(&self, other: &SimplifiedType<DefId>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (SimplifiedType::Int(__self_0), SimplifiedType::Int(__arg1_0))
                    => __self_0 == __arg1_0,
                (SimplifiedType::Uint(__self_0),
                    SimplifiedType::Uint(__arg1_0)) => __self_0 == __arg1_0,
                (SimplifiedType::Float(__self_0),
                    SimplifiedType::Float(__arg1_0)) => __self_0 == __arg1_0,
                (SimplifiedType::Adt(__self_0), SimplifiedType::Adt(__arg1_0))
                    => __self_0 == __arg1_0,
                (SimplifiedType::Foreign(__self_0),
                    SimplifiedType::Foreign(__arg1_0)) => __self_0 == __arg1_0,
                (SimplifiedType::Ref(__self_0), SimplifiedType::Ref(__arg1_0))
                    => __self_0 == __arg1_0,
                (SimplifiedType::Ptr(__self_0), SimplifiedType::Ptr(__arg1_0))
                    => __self_0 == __arg1_0,
                (SimplifiedType::Tuple(__self_0),
                    SimplifiedType::Tuple(__arg1_0)) => __self_0 == __arg1_0,
                (SimplifiedType::Trait(__self_0),
                    SimplifiedType::Trait(__arg1_0)) => __self_0 == __arg1_0,
                (SimplifiedType::Closure(__self_0),
                    SimplifiedType::Closure(__arg1_0)) => __self_0 == __arg1_0,
                (SimplifiedType::Coroutine(__self_0),
                    SimplifiedType::Coroutine(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (SimplifiedType::CoroutineWitness(__self_0),
                    SimplifiedType::CoroutineWitness(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (SimplifiedType::Function(__self_0),
                    SimplifiedType::Function(__arg1_0)) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<DefId: ::core::cmp::Eq> ::core::cmp::Eq for SimplifiedType<DefId> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::IntTy>;
        let _: ::core::cmp::AssertParamIsEq<ty::UintTy>;
        let _: ::core::cmp::AssertParamIsEq<ty::FloatTy>;
        let _: ::core::cmp::AssertParamIsEq<DefId>;
        let _: ::core::cmp::AssertParamIsEq<Mutability>;
        let _: ::core::cmp::AssertParamIsEq<usize>;
    }
}Eq, #[automatically_derived]
impl<DefId: ::core::hash::Hash> ::core::hash::Hash for SimplifiedType<DefId> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            SimplifiedType::Int(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Uint(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Float(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Adt(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Foreign(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Ref(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Ptr(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Tuple(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Trait(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Closure(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Coroutine(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::CoroutineWitness(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            SimplifiedType::Function(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash)]
22#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<DefId, __E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for SimplifiedType<DefId> where
            DefId: ::rustc_serialize::Encodable<__E> {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SimplifiedType::Bool => { 0usize }
                        SimplifiedType::Char => { 1usize }
                        SimplifiedType::Int(ref __binding_0) => { 2usize }
                        SimplifiedType::Uint(ref __binding_0) => { 3usize }
                        SimplifiedType::Float(ref __binding_0) => { 4usize }
                        SimplifiedType::Adt(ref __binding_0) => { 5usize }
                        SimplifiedType::Foreign(ref __binding_0) => { 6usize }
                        SimplifiedType::Str => { 7usize }
                        SimplifiedType::Array => { 8usize }
                        SimplifiedType::Slice => { 9usize }
                        SimplifiedType::Ref(ref __binding_0) => { 10usize }
                        SimplifiedType::Ptr(ref __binding_0) => { 11usize }
                        SimplifiedType::Never => { 12usize }
                        SimplifiedType::Tuple(ref __binding_0) => { 13usize }
                        SimplifiedType::MarkerTraitObject => { 14usize }
                        SimplifiedType::Trait(ref __binding_0) => { 15usize }
                        SimplifiedType::Closure(ref __binding_0) => { 16usize }
                        SimplifiedType::Coroutine(ref __binding_0) => { 17usize }
                        SimplifiedType::CoroutineWitness(ref __binding_0) => {
                            18usize
                        }
                        SimplifiedType::Function(ref __binding_0) => { 19usize }
                        SimplifiedType::UnsafeBinder => { 20usize }
                        SimplifiedType::Placeholder => { 21usize }
                        SimplifiedType::Error => { 22usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SimplifiedType::Bool => {}
                    SimplifiedType::Char => {}
                    SimplifiedType::Int(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Uint(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Float(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Adt(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Foreign(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Str => {}
                    SimplifiedType::Array => {}
                    SimplifiedType::Slice => {}
                    SimplifiedType::Ref(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Ptr(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Never => {}
                    SimplifiedType::Tuple(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::MarkerTraitObject => {}
                    SimplifiedType::Trait(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Closure(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Coroutine(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::CoroutineWitness(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::Function(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SimplifiedType::UnsafeBinder => {}
                    SimplifiedType::Placeholder => {}
                    SimplifiedType::Error => {}
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<DefId, __D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for SimplifiedType<DefId> where
            DefId: ::rustc_serialize::Decodable<__D> {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { SimplifiedType::Bool }
                    1usize => { SimplifiedType::Char }
                    2usize => {
                        SimplifiedType::Int(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => {
                        SimplifiedType::Uint(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    4usize => {
                        SimplifiedType::Float(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    5usize => {
                        SimplifiedType::Adt(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    6usize => {
                        SimplifiedType::Foreign(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    7usize => { SimplifiedType::Str }
                    8usize => { SimplifiedType::Array }
                    9usize => { SimplifiedType::Slice }
                    10usize => {
                        SimplifiedType::Ref(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    11usize => {
                        SimplifiedType::Ptr(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    12usize => { SimplifiedType::Never }
                    13usize => {
                        SimplifiedType::Tuple(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    14usize => { SimplifiedType::MarkerTraitObject }
                    15usize => {
                        SimplifiedType::Trait(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    16usize => {
                        SimplifiedType::Closure(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    17usize => {
                        SimplifiedType::Coroutine(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    18usize => {
                        SimplifiedType::CoroutineWitness(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    19usize => {
                        SimplifiedType::Function(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    20usize => { SimplifiedType::UnsafeBinder }
                    21usize => { SimplifiedType::Placeholder }
                    22usize => { SimplifiedType::Error }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SimplifiedType`, expected 0..23, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<DefId> ::rustc_data_structures::stable_hasher::HashStable for
            SimplifiedType<DefId> where
            DefId: ::rustc_data_structures::stable_hasher::HashStable {
            #[inline]
            fn hash_stable<__Hcx: ::rustc_data_structures::stable_hasher::HashStableContext>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    SimplifiedType::Bool => {}
                    SimplifiedType::Char => {}
                    SimplifiedType::Int(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Uint(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Float(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Adt(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Foreign(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Str => {}
                    SimplifiedType::Array => {}
                    SimplifiedType::Slice => {}
                    SimplifiedType::Ref(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Ptr(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Never => {}
                    SimplifiedType::Tuple(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::MarkerTraitObject => {}
                    SimplifiedType::Trait(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Closure(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Coroutine(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::CoroutineWitness(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::Function(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    SimplifiedType::UnsafeBinder => {}
                    SimplifiedType::Placeholder => {}
                    SimplifiedType::Error => {}
                }
            }
        }
    };HashStable))]
23pub enum SimplifiedType<DefId> {
24    Bool,
25    Char,
26    Int(ty::IntTy),
27    Uint(ty::UintTy),
28    Float(ty::FloatTy),
29    Adt(DefId),
30    Foreign(DefId),
31    Str,
32    Array,
33    Slice,
34    Ref(Mutability),
35    Ptr(Mutability),
36    Never,
37    Tuple(usize),
38    /// A trait object, all of whose components are markers
39    /// (e.g., `dyn Send + Sync`).
40    MarkerTraitObject,
41    Trait(DefId),
42    Closure(DefId),
43    Coroutine(DefId),
44    CoroutineWitness(DefId),
45    Function(usize),
46    UnsafeBinder,
47    Placeholder,
48    Error,
49}
50
51#[cfg(feature = "nightly")]
52impl<DefId: HashStable> ToStableHashKey for SimplifiedType<DefId> {
53    type KeyType = Fingerprint;
54
55    #[inline]
56    fn to_stable_hash_key<Hcx: HashStableContext>(&self, hcx: &mut Hcx) -> Fingerprint {
57        let mut hasher = StableHasher::new();
58        self.hash_stable(hcx, &mut hasher);
59        hasher.finish()
60    }
61}
62
63/// Generic parameters are pretty much just bound variables, e.g.
64/// the type of `fn foo<'a, T>(x: &'a T) -> u32 { ... }` can be thought of as
65/// `for<'a, T> fn(&'a T) -> u32`.
66///
67/// Typecheck of `foo` has to succeed for all possible generic arguments, so
68/// during typeck, we have to treat its generic parameters as if they
69/// were placeholders.
70///
71/// But when calling `foo` we only have to provide a specific generic argument.
72/// In that case the generic parameters are instantiated with inference variables.
73/// As we use `simplify_type` before that instantiation happens, we just treat
74/// generic parameters as if they were inference variables in that case.
75#[derive(#[automatically_derived]
impl ::core::cmp::PartialEq for TreatParams {
    #[inline]
    fn eq(&self, other: &TreatParams) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TreatParams {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for TreatParams {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                TreatParams::InstantiateWithInfer => "InstantiateWithInfer",
                TreatParams::AsRigid => "AsRigid",
            })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for TreatParams {
    #[inline]
    fn clone(&self) -> TreatParams { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TreatParams { }Copy)]
76pub enum TreatParams {
77    /// Treat parameters as infer vars. This is the correct mode for caching
78    /// an impl's type for lookup.
79    InstantiateWithInfer,
80    /// Treat parameters as placeholders in the given environment. This is the
81    /// correct mode for *lookup*, as during candidate selection.
82    ///
83    /// This also treats projections with inference variables as infer vars
84    /// since they could be further normalized.
85    // FIXME(@lcnr): This treats aliases as rigid. This is only correct if the
86    // type has been structurally normalized. We should reflect this requirement
87    // in the variant name. It is currently incorrectly used in diagnostics.
88    AsRigid,
89}
90
91/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
92///
93/// **This function should only be used if you need to store or retrieve the type from some
94/// hashmap. If you want to quickly decide whether two types may unify, use the [DeepRejectCtxt]
95/// instead.**
96///
97/// The idea is to get something simple that we can use to quickly decide if two types could unify,
98/// for example during method lookup. If this function returns `Some(x)` it can only unify with
99/// types for which this method returns either `Some(x)` as well or `None`.
100///
101/// A special case here are parameters and projections, which are only injective
102/// if they are treated as placeholders.
103///
104/// For example when storing impls based on their simplified self type, we treat
105/// generic parameters as if they were inference variables. We must not simplify them here,
106/// as they can unify with any other type.
107///
108/// With projections we have to be even more careful, as treating them as placeholders
109/// is only correct if they are fully normalized.
110///
111/// ¹ meaning that if the outermost layers are different, then the whole types are also different.
112pub fn simplify_type<I: Interner>(
113    cx: I,
114    ty: I::Ty,
115    treat_params: TreatParams,
116) -> Option<SimplifiedType<I::DefId>> {
117    match ty.kind() {
118        ty::Bool => Some(SimplifiedType::Bool),
119        ty::Char => Some(SimplifiedType::Char),
120        ty::Int(int_type) => Some(SimplifiedType::Int(int_type)),
121        ty::Uint(uint_type) => Some(SimplifiedType::Uint(uint_type)),
122        ty::Float(float_type) => Some(SimplifiedType::Float(float_type)),
123        ty::Adt(def, _) => Some(SimplifiedType::Adt(def.def_id().into())),
124        ty::Str => Some(SimplifiedType::Str),
125        ty::Array(..) => Some(SimplifiedType::Array),
126        ty::Slice(..) => Some(SimplifiedType::Slice),
127        ty::Pat(ty, ..) => simplify_type(cx, ty, treat_params),
128        ty::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(mutbl)),
129        ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() {
130            Some(principal_def_id) if !cx.trait_is_auto(principal_def_id) => {
131                Some(SimplifiedType::Trait(principal_def_id.into()))
132            }
133            _ => Some(SimplifiedType::MarkerTraitObject),
134        },
135        ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)),
136        ty::FnDef(def_id, _) => Some(SimplifiedType::Closure(def_id.into())),
137        ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id.into())),
138        ty::CoroutineClosure(def_id, _) => Some(SimplifiedType::Closure(def_id.into())),
139        ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id.into())),
140        ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id.into())),
141        ty::Never => Some(SimplifiedType::Never),
142        ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
143        ty::FnPtr(sig_tys, _hdr) => {
144            Some(SimplifiedType::Function(sig_tys.skip_binder().inputs().len()))
145        }
146        ty::UnsafeBinder(_) => Some(SimplifiedType::UnsafeBinder),
147        ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
148        ty::Param(_) => match treat_params {
149            TreatParams::AsRigid => Some(SimplifiedType::Placeholder),
150            TreatParams::InstantiateWithInfer => None,
151        },
152        ty::Alias(..) => match treat_params {
153            // When treating `ty::Param` as a placeholder, projections also
154            // don't unify with anything else as long as they are fully normalized.
155            TreatParams::AsRigid
156                if !ty.has_non_region_infer() || cx.next_trait_solver_globally() =>
157            {
158                Some(SimplifiedType::Placeholder)
159            }
160            TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None,
161        },
162        ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id.into())),
163        ty::Error(_) => Some(SimplifiedType::Error),
164        ty::Bound(..) | ty::Infer(_) => None,
165    }
166}
167
168impl<DefId> SimplifiedType<DefId> {
169    pub fn def(self) -> Option<DefId> {
170        match self {
171            SimplifiedType::Adt(d)
172            | SimplifiedType::Foreign(d)
173            | SimplifiedType::Trait(d)
174            | SimplifiedType::Closure(d)
175            | SimplifiedType::Coroutine(d)
176            | SimplifiedType::CoroutineWitness(d) => Some(d),
177            _ => None,
178        }
179    }
180}
181
182/// Given generic arguments, could they be unified after
183/// replacing parameters with inference variables or placeholders.
184/// This behavior is toggled using the const generics.
185///
186/// We use this to quickly reject impl/wc candidates without needing
187/// to instantiate generic arguments/having to enter a probe.
188///
189/// We also use this function during coherence. For coherence the
190/// impls only have to overlap for some value, so we treat parameters
191/// on both sides like inference variables.
192#[derive(#[automatically_derived]
impl<I: ::core::fmt::Debug + Interner, const INSTANTIATE_LHS_WITH_INFER :
    bool, const INSTANTIATE_RHS_WITH_INFER : bool> ::core::fmt::Debug for
    DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
    {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "DeepRejectCtxt", "_interner", &&self._interner)
    }
}Debug, #[automatically_derived]
impl<I: ::core::clone::Clone + Interner, const INSTANTIATE_LHS_WITH_INFER :
    bool, const INSTANTIATE_RHS_WITH_INFER : bool> ::core::clone::Clone for
    DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
    {
    #[inline]
    fn clone(&self)
        ->
            DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER,
            INSTANTIATE_RHS_WITH_INFER> {
        DeepRejectCtxt {
            _interner: ::core::clone::Clone::clone(&self._interner),
        }
    }
}Clone, #[automatically_derived]
impl<I: ::core::marker::Copy + Interner, const INSTANTIATE_LHS_WITH_INFER :
    bool, const INSTANTIATE_RHS_WITH_INFER : bool> ::core::marker::Copy for
    DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
    {
}Copy)]
193pub struct DeepRejectCtxt<
194    I: Interner,
195    const INSTANTIATE_LHS_WITH_INFER: bool,
196    const INSTANTIATE_RHS_WITH_INFER: bool,
197> {
198    _interner: PhantomData<I>,
199}
200
201impl<I: Interner> DeepRejectCtxt<I, false, false> {
202    /// Treat parameters in both the lhs and the rhs as rigid.
203    pub fn relate_rigid_rigid(_interner: I) -> DeepRejectCtxt<I, false, false> {
204        DeepRejectCtxt { _interner: PhantomData }
205    }
206}
207
208impl<I: Interner> DeepRejectCtxt<I, true, true> {
209    /// Treat parameters in both the lhs and the rhs as infer vars.
210    pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt<I, true, true> {
211        DeepRejectCtxt { _interner: PhantomData }
212    }
213}
214
215impl<I: Interner> DeepRejectCtxt<I, false, true> {
216    /// Treat parameters in the lhs as rigid, and in rhs as infer vars.
217    pub fn relate_rigid_infer(_interner: I) -> DeepRejectCtxt<I, false, true> {
218        DeepRejectCtxt { _interner: PhantomData }
219    }
220}
221
222impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_WITH_INFER: bool>
223    DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
224{
225    // Quite arbitrary. Large enough to only affect a very tiny amount of impls/crates
226    // and small enough to prevent hangs.
227    const STARTING_DEPTH: usize = 8;
228
229    pub fn args_may_unify(
230        self,
231        obligation_args: I::GenericArgs,
232        impl_args: I::GenericArgs,
233    ) -> bool {
234        self.args_may_unify_inner(obligation_args, impl_args, Self::STARTING_DEPTH)
235    }
236
237    pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
238        self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH)
239    }
240
241    pub fn types_may_unify_with_depth(self, lhs: I::Ty, rhs: I::Ty, depth_limit: usize) -> bool {
242        self.types_may_unify_inner(lhs, rhs, depth_limit)
243    }
244
245    fn args_may_unify_inner(
246        self,
247        obligation_args: I::GenericArgs,
248        impl_args: I::GenericArgs,
249        depth: usize,
250    ) -> bool {
251        // No need to decrement the depth here as this function is only
252        // recursively reachable via `types_may_unify_inner` which already
253        // increments the depth for us.
254        iter::zip(obligation_args.iter(), impl_args.iter()).all(|(obl, imp)| {
255            match (obl.kind(), imp.kind()) {
256                // We don't fast reject based on regions.
257                (ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_)) => true,
258                (ty::GenericArgKind::Type(obl), ty::GenericArgKind::Type(imp)) => {
259                    self.types_may_unify_inner(obl, imp, depth)
260                }
261                (ty::GenericArgKind::Const(obl), ty::GenericArgKind::Const(imp)) => {
262                    self.consts_may_unify_inner(obl, imp)
263                }
264                _ => {
    ::core::panicking::panic_fmt(format_args!("kind mismatch: {0:?} {1:?}",
            obl, imp));
}panic!("kind mismatch: {obl:?} {imp:?}"),
265            }
266        })
267    }
268
269    fn types_may_unify_inner(self, lhs: I::Ty, rhs: I::Ty, depth: usize) -> bool {
270        if lhs == rhs {
271            return true;
272        }
273
274        match rhs.kind() {
275            // Start by checking whether the `rhs` type may unify with
276            // pretty much everything. Just return `true` in that case.
277            ty::Param(_) => {
278                if INSTANTIATE_RHS_WITH_INFER {
279                    return true;
280                }
281            }
282            ty::Error(_) | ty::Alias(..) | ty::Bound(..) => return true,
283            ty::Infer(var) => return self.var_and_ty_may_unify(var, lhs),
284
285            // These types only unify with inference variables or their own
286            // variant.
287            ty::Bool
288            | ty::Char
289            | ty::Int(_)
290            | ty::Uint(_)
291            | ty::Float(_)
292            | ty::Adt(..)
293            | ty::Str
294            | ty::Array(..)
295            | ty::Slice(..)
296            | ty::RawPtr(..)
297            | ty::Dynamic(..)
298            | ty::Pat(..)
299            | ty::Ref(..)
300            | ty::Never
301            | ty::Tuple(..)
302            | ty::FnDef(..)
303            | ty::FnPtr(..)
304            | ty::Closure(..)
305            | ty::CoroutineClosure(..)
306            | ty::Coroutine(..)
307            | ty::CoroutineWitness(..)
308            | ty::Foreign(_)
309            | ty::Placeholder(_)
310            | ty::UnsafeBinder(_) => {}
311        };
312
313        // The type system needs to support exponentially large types
314        // as long as they are self-similar. While most other folders
315        // use caching to handle them, this folder exists purely as a
316        // perf optimization and is incredibly hot. In pretty much all
317        // uses checking the cache is slower than simply recursing, so
318        // we instead just add an arbitrary depth cutoff.
319        //
320        // We only decrement the depth here as the match on `rhs`
321        // does not recurse.
322        let Some(depth) = depth.checked_sub(1) else {
323            return true;
324        };
325
326        // For purely rigid types, use structural equivalence.
327        match lhs.kind() {
328            ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() {
329                ty::Ref(_, rhs_ty, rhs_mutbl) => {
330                    lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth)
331                }
332                _ => false,
333            },
334
335            ty::Adt(lhs_def, lhs_args) => match rhs.kind() {
336                ty::Adt(rhs_def, rhs_args) => {
337                    lhs_def == rhs_def && self.args_may_unify_inner(lhs_args, rhs_args, depth)
338                }
339                _ => false,
340            },
341
342            // Depending on the value of const generics, we either treat generic parameters
343            // like placeholders or like inference variables.
344            ty::Param(lhs) => {
345                INSTANTIATE_LHS_WITH_INFER
346                    || match rhs.kind() {
347                        ty::Param(rhs) => lhs == rhs,
348                        _ => false,
349                    }
350            }
351
352            // Placeholder types don't unify with anything on their own.
353            ty::Placeholder(lhs) => {
354                #[allow(non_exhaustive_omitted_patterns)] match rhs.kind() {
    ty::Placeholder(rhs) if lhs == rhs => true,
    _ => false,
}matches!(rhs.kind(), ty::Placeholder(rhs) if lhs == rhs)
355            }
356
357            ty::Infer(var) => self.var_and_ty_may_unify(var, rhs),
358
359            // As we're walking the whole type, it may encounter projections
360            // inside of binders and what not, so we're just going to assume that
361            // projections can unify with other stuff.
362            //
363            // Looking forward to lazy normalization this is the safer strategy anyways.
364            ty::Alias(..) => true,
365
366            ty::Int(_)
367            | ty::Uint(_)
368            | ty::Float(_)
369            | ty::Str
370            | ty::Bool
371            | ty::Char
372            | ty::Never
373            | ty::Foreign(_) => lhs == rhs,
374
375            ty::Tuple(lhs) => match rhs.kind() {
376                ty::Tuple(rhs) => {
377                    lhs.len() == rhs.len()
378                        && iter::zip(lhs.iter(), rhs.iter())
379                            .all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth))
380                }
381                _ => false,
382            },
383
384            ty::Array(lhs_ty, lhs_len) => match rhs.kind() {
385                ty::Array(rhs_ty, rhs_len) => {
386                    self.types_may_unify_inner(lhs_ty, rhs_ty, depth)
387                        && self.consts_may_unify_inner(lhs_len, rhs_len)
388                }
389                _ => false,
390            },
391
392            ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() {
393                ty::RawPtr(rhs_ty, rhs_mutbl) => {
394                    lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth)
395                }
396                _ => false,
397            },
398
399            ty::Slice(lhs_ty) => {
400                #[allow(non_exhaustive_omitted_patterns)] match rhs.kind() {
    ty::Slice(rhs_ty) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth) =>
        true,
    _ => false,
}matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth))
401            }
402
403            ty::Dynamic(lhs_preds, ..) => {
404                // Ideally we would walk the existential predicates here or at least
405                // compare their length. But considering that the relevant `Relate` impl
406                // actually sorts and deduplicates these, that doesn't work.
407                #[allow(non_exhaustive_omitted_patterns)] match rhs.kind() {
    ty::Dynamic(rhs_preds, ..) if
        lhs_preds.principal_def_id() == rhs_preds.principal_def_id() => true,
    _ => false,
}matches!(rhs.kind(), ty::Dynamic(rhs_preds, ..) if
408                    lhs_preds.principal_def_id() == rhs_preds.principal_def_id()
409                )
410            }
411
412            ty::FnPtr(lhs_sig_tys, lhs_hdr) => match rhs.kind() {
413                ty::FnPtr(rhs_sig_tys, rhs_hdr) => {
414                    let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output;
415                    let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output;
416
417                    lhs_hdr == rhs_hdr
418                        && lhs_sig_tys.len() == rhs_sig_tys.len()
419                        && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter())
420                            .all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth))
421                }
422                _ => false,
423            },
424
425            ty::Bound(..) => true,
426
427            ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() {
428                ty::FnDef(rhs_def_id, rhs_args) => {
429                    lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
430                }
431                _ => false,
432            },
433
434            ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() {
435                ty::Closure(rhs_def_id, rhs_args) => {
436                    lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
437                }
438                _ => false,
439            },
440
441            ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() {
442                ty::CoroutineClosure(rhs_def_id, rhs_args) => {
443                    lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
444                }
445                _ => false,
446            },
447
448            ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() {
449                ty::Coroutine(rhs_def_id, rhs_args) => {
450                    lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
451                }
452                _ => false,
453            },
454
455            ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() {
456                ty::CoroutineWitness(rhs_def_id, rhs_args) => {
457                    lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
458                }
459                _ => false,
460            },
461
462            ty::Pat(lhs_ty, _) => {
463                // FIXME(pattern_types): take pattern into account
464                #[allow(non_exhaustive_omitted_patterns)] match rhs.kind() {
    ty::Pat(rhs_ty, _) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth) =>
        true,
    _ => false,
}matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth))
465            }
466
467            ty::UnsafeBinder(lhs_ty) => match rhs.kind() {
468                ty::UnsafeBinder(rhs_ty) => {
469                    self.types_may_unify(lhs_ty.skip_binder(), rhs_ty.skip_binder())
470                }
471                _ => false,
472            },
473
474            ty::Error(..) => true,
475        }
476    }
477
478    // Unlike `types_may_unify_inner`, this does not take a depth as
479    // we never recurse from this function.
480    fn consts_may_unify_inner(self, lhs: I::Const, rhs: I::Const) -> bool {
481        match rhs.kind() {
482            ty::ConstKind::Param(_) => {
483                if INSTANTIATE_RHS_WITH_INFER {
484                    return true;
485                }
486            }
487
488            ty::ConstKind::Expr(_)
489            | ty::ConstKind::Unevaluated(_)
490            | ty::ConstKind::Error(_)
491            | ty::ConstKind::Infer(_)
492            | ty::ConstKind::Bound(..) => {
493                return true;
494            }
495
496            ty::ConstKind::Value(..) | ty::ConstKind::Placeholder(_) => {}
497        };
498
499        match lhs.kind() {
500            ty::ConstKind::Value(lhs_val) => match rhs.kind() {
501                ty::ConstKind::Value(rhs_val) => lhs_val.valtree() == rhs_val.valtree(),
502                _ => false,
503            },
504
505            ty::ConstKind::Param(lhs) => {
506                INSTANTIATE_LHS_WITH_INFER
507                    || match rhs.kind() {
508                        ty::ConstKind::Param(rhs) => lhs == rhs,
509                        _ => false,
510                    }
511            }
512
513            // Placeholder consts don't unify with anything on their own
514            ty::ConstKind::Placeholder(lhs) => {
515                #[allow(non_exhaustive_omitted_patterns)] match rhs.kind() {
    ty::ConstKind::Placeholder(rhs) if lhs == rhs => true,
    _ => false,
}matches!(rhs.kind(), ty::ConstKind::Placeholder(rhs) if lhs == rhs)
516            }
517
518            // As we don't necessarily eagerly evaluate constants,
519            // they might unify with any value.
520            ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
521                true
522            }
523
524            ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) => true,
525        }
526    }
527
528    fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool {
529        if !ty.is_known_rigid() {
530            return true;
531        }
532
533        match var {
534            ty::IntVar(_) => ty.is_integral(),
535            ty::FloatVar(_) => ty.is_floating_point(),
536            _ => true,
537        }
538    }
539}