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