Skip to main content

rustc_type_ir/
infer_ctxt.rs

1use core::fmt;
2use std::hash::{Hash, Hasher};
3use std::range::RangeInclusive;
4
5use derive_where::derive_where;
6#[cfg(feature = "nightly")]
7use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext};
8
9use crate::data_structures::DelayedMap;
10use crate::inherent::*;
11use crate::relate::RelateResult;
12use crate::relate::combine::PredicateEmittingRelation;
13use crate::solve::{TyOrConstInferVar, VisibleForLeakCheck};
14use crate::{
15    self as ty, Const, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder,
16    TypeSuperFoldable, TypeVisitableExt,
17};
18
19mod private {
20    pub trait Sealed {}
21
22    impl Sealed for super::CantBeErased {}
23    impl Sealed for super::MayBeErased {}
24}
25pub trait TypingModeErasedStatus: private::Sealed + Clone + Copy + Hash + fmt::Debug {}
26
27#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for CantBeErased { }
#[automatically_derived]
impl ::core::clone::Clone for CantBeErased {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CantBeErased { }Copy, #[automatically_derived]
impl ::core::hash::Hash for CantBeErased {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        match *self {}
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CantBeErased {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match *self {}
    }
}Debug)]
28pub enum CantBeErased {}
29#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MayBeErased { }
#[automatically_derived]
impl ::core::clone::Clone for MayBeErased {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MayBeErased { }Copy, #[automatically_derived]
impl ::core::hash::Hash for MayBeErased {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for MayBeErased {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "MayBeErased")
    }
}Debug)]
30#[cfg_attr(
31    feature = "nightly",
32    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for MayBeErased {
            fn encode(&self, __encoder: &mut __E) {}
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for MayBeErased {
            fn decode(__decoder: &mut __D) -> Self { MayBeErased }
        }
    };Decodable_NoContext, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for MayBeErased
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self { MayBeErased => {} }
            }
        }
    };StableHash_NoContext)
33)]
34pub struct MayBeErased;
35
36impl TypingModeErasedStatus for CantBeErased {}
37impl TypingModeErasedStatus for MayBeErased {}
38
39/// The current typing mode of an inference context. We unfortunately have some
40/// slightly different typing rules depending on the current context. See the
41/// doc comment for each variant for how and why they are used.
42///
43/// In most cases you can get the correct typing mode automatically via:
44/// - `mir::Body::typing_mode`
45/// - `rustc_lint::LateContext::typing_mode`
46///
47/// If neither of these functions are available, feel free to reach out to
48/// t-types for help.
49///
50/// Because typing rules get subtly different based on what typing mode we're in,
51/// subtle enough that changing the behavior of typing modes can sometimes cause
52/// changes that we don't even have tests for, we'd like to enforce the rule that
53/// any place where we specialize behavior based on the typing mode, we match
54/// *exhaustively* on the typing mode. That way, it's easy to determine all the
55/// places that must change when anything about typing modes changes.
56///
57/// Hence, `TypingMode` does not implement `Eq`, though [`TypingModeEqWrapper`] is available
58/// in the rare case that you do need this. Most cases where this currently matters is
59/// where we pass typing modes through the query system and want to cache based on it.
60/// See also `#[rustc_must_match_exhaustively]`, which tries to detect non-exhaustive
61/// matches.
62///
63/// Since matching on typing mode to single out `Coherence` is so common, and `Coherence`
64/// is so different from the other modes: see also [`is_coherence`](TypingMode::is_coherence)
65#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::clone::Clone for
    TypingMode<I, S> where I: Interner {
    #[inline]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::marker::Copy for
    TypingMode<I, S> where I: Interner {
}
#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::hash::Hash for
    TypingMode<I, S> where I: Interner {
    fn hash<__H: ::core::hash::Hasher>(&self, __state: &mut __H) {
        match self {
            TypingMode::Coherence => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
            }
            TypingMode::Typeck {
                defining_opaque_types_and_generators: ref __field_defining_opaque_types_and_generators
                } => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
                ::core::hash::Hash::hash(__field_defining_opaque_types_and_generators,
                    __state);
            }
            TypingMode::PostTypeckUntilBorrowck {
                defining_opaque_types: ref __field_defining_opaque_types } =>
                {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
                ::core::hash::Hash::hash(__field_defining_opaque_types,
                    __state);
            }
            TypingMode::PostBorrowck {
                defined_opaque_types: ref __field_defined_opaque_types } => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
                ::core::hash::Hash::hash(__field_defined_opaque_types,
                    __state);
            }
            TypingMode::Reflection => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
            }
            TypingMode::PostAnalysis => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
            }
            TypingMode::Codegen => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
            }
            TypingMode::ErasedNotCoherence(ref __field_0) => {
                ::core::hash::Hash::hash(&::core::mem::discriminant(self),
                    __state);
                ::core::hash::Hash::hash(__field_0, __state);
            }
        }
    }
}
#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::fmt::Debug for
    TypingMode<I, S> where I: Interner {
    fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
        -> ::core::fmt::Result {
        match self {
            TypingMode::Coherence =>
                ::core::fmt::Formatter::write_str(__f, "Coherence"),
            TypingMode::Typeck {
                defining_opaque_types_and_generators: ref __field_defining_opaque_types_and_generators
                } => {
                let mut __builder =
                    ::core::fmt::Formatter::debug_struct(__f, "Typeck");
                ::core::fmt::DebugStruct::field(&mut __builder,
                    "defining_opaque_types_and_generators",
                    __field_defining_opaque_types_and_generators);
                ::core::fmt::DebugStruct::finish(&mut __builder)
            }
            TypingMode::PostTypeckUntilBorrowck {
                defining_opaque_types: ref __field_defining_opaque_types } =>
                {
                let mut __builder =
                    ::core::fmt::Formatter::debug_struct(__f,
                        "PostTypeckUntilBorrowck");
                ::core::fmt::DebugStruct::field(&mut __builder,
                    "defining_opaque_types", __field_defining_opaque_types);
                ::core::fmt::DebugStruct::finish(&mut __builder)
            }
            TypingMode::PostBorrowck {
                defined_opaque_types: ref __field_defined_opaque_types } => {
                let mut __builder =
                    ::core::fmt::Formatter::debug_struct(__f, "PostBorrowck");
                ::core::fmt::DebugStruct::field(&mut __builder,
                    "defined_opaque_types", __field_defined_opaque_types);
                ::core::fmt::DebugStruct::finish(&mut __builder)
            }
            TypingMode::Reflection =>
                ::core::fmt::Formatter::write_str(__f, "Reflection"),
            TypingMode::PostAnalysis =>
                ::core::fmt::Formatter::write_str(__f, "PostAnalysis"),
            TypingMode::Codegen =>
                ::core::fmt::Formatter::write_str(__f, "Codegen"),
            TypingMode::ErasedNotCoherence(ref __field_0) => {
                let mut __builder =
                    ::core::fmt::Formatter::debug_tuple(__f,
                        "ErasedNotCoherence");
                ::core::fmt::DebugTuple::field(&mut __builder, __field_0);
                ::core::fmt::DebugTuple::finish(&mut __builder)
            }
        }
    }
}#[derive_where(Clone, Copy, Hash, Debug; I: Interner)]
66#[cfg_attr(
67    feature = "nightly",
68    derive(const _: () =
    {
        impl<I: Interner, S: TypingModeErasedStatus,
            __E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<__E>
            for TypingMode<I, S> where
            I::LocalDefIds: ::rustc_serialize::Encodable<__E>,
            S: ::rustc_serialize::Encodable<__E> {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        TypingMode::Coherence => { 0usize }
                        TypingMode::Typeck {
                            defining_opaque_types_and_generators: ref __binding_0 } => {
                            1usize
                        }
                        TypingMode::PostTypeckUntilBorrowck {
                            defining_opaque_types: ref __binding_0 } => {
                            2usize
                        }
                        TypingMode::PostBorrowck {
                            defined_opaque_types: ref __binding_0 } => {
                            3usize
                        }
                        TypingMode::Reflection => { 4usize }
                        TypingMode::PostAnalysis => { 5usize }
                        TypingMode::Codegen => { 6usize }
                        TypingMode::ErasedNotCoherence(ref __binding_0) => {
                            7usize
                        }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    TypingMode::Coherence => {}
                    TypingMode::Typeck {
                        defining_opaque_types_and_generators: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    TypingMode::PostTypeckUntilBorrowck {
                        defining_opaque_types: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    TypingMode::PostBorrowck {
                        defined_opaque_types: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    TypingMode::Reflection => {}
                    TypingMode::PostAnalysis => {}
                    TypingMode::Codegen => {}
                    TypingMode::ErasedNotCoherence(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<I: Interner, S: TypingModeErasedStatus,
            __D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<__D>
            for TypingMode<I, S> where
            I::LocalDefIds: ::rustc_serialize::Decodable<__D>,
            S: ::rustc_serialize::Decodable<__D> {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { TypingMode::Coherence }
                    1usize => {
                        TypingMode::Typeck {
                            defining_opaque_types_and_generators: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    2usize => {
                        TypingMode::PostTypeckUntilBorrowck {
                            defining_opaque_types: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    3usize => {
                        TypingMode::PostBorrowck {
                            defined_opaque_types: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    4usize => { TypingMode::Reflection }
                    5usize => { TypingMode::PostAnalysis }
                    6usize => { TypingMode::Codegen }
                    7usize => {
                        TypingMode::ErasedNotCoherence(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `TypingMode`, expected 0..8, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<I: Interner, S: TypingModeErasedStatus>
            ::rustc_data_structures::stable_hash::StableHash for
            TypingMode<I, S> where
            I::LocalDefIds: ::rustc_data_structures::stable_hash::StableHash,
            S: ::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 {
                    TypingMode::Coherence => {}
                    TypingMode::Typeck {
                        defining_opaque_types_and_generators: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    TypingMode::PostTypeckUntilBorrowck {
                        defining_opaque_types: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    TypingMode::PostBorrowck {
                        defined_opaque_types: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    TypingMode::Reflection => {}
                    TypingMode::PostAnalysis => {}
                    TypingMode::Codegen => {}
                    TypingMode::ErasedNotCoherence(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash_NoContext)
69)]
70#[cfg_attr(feature = "nightly", rustc_must_match_exhaustively)]
71pub enum TypingMode<I: Interner, S: TypingModeErasedStatus = MayBeErased> {
72    /// When checking whether impls overlap, we check whether any obligations
73    /// are guaranteed to never hold when unifying the impls. This requires us
74    /// to be complete: we must never fail to prove something which may actually
75    /// hold.
76    ///
77    /// In this typing mode we bail with ambiguity in case its not knowable
78    /// whether a trait goal may hold, e.g. because the trait may get implemented
79    /// in a downstream or sibling crate.
80    ///
81    /// We also have to be careful when generalizing aliases inside of higher-ranked
82    /// types to not unnecessarily constrain any inference variables.
83    Coherence,
84    /// Typeck is the typing mode mainly used in `rustc_hir_typeck` and related crate.
85    /// It includes type inference, checking that items are well-formed, and
86    /// pretty much everything else which may emit proper type errors to the user.
87    ///
88    /// We only normalize opaque types which may get defined by the current body,
89    /// which are stored in `defining_opaque_types`.
90    ///
91    /// We also refuse to project any associated type that is marked `default`.
92    /// Non-`default` ("final") types are always projected. This is necessary in
93    /// general for soundness of specialization. However, we *could* allow projections
94    /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
95    /// to force the type definition to be treated abstractly by any consumers of the
96    /// impl. Concretely, that means that the following example will
97    /// fail to compile:
98    ///
99    /// ```compile_fail,E0308
100    /// #![feature(specialization)]
101    /// trait Assoc {
102    ///     type Output;
103    /// }
104    ///
105    /// impl<T> Assoc for T {
106    ///     default type Output = bool;
107    /// }
108    ///
109    /// fn main() {
110    ///     let x: <() as Assoc>::Output = true;
111    /// }
112    /// ```
113    Typeck { defining_opaque_types_and_generators: I::LocalDefIds },
114    /// `PostTypeckUntilBorrowck` is used after `Typeck` has finished, up to and including borrowck,
115    /// for anything that accesses typeck results. This is the behavior that's used mainly in borrowck,
116    /// but, for example, also in late lints and other analyses while building MIR. The behavior of
117    /// `PostTypeckUntilBorrowck` is identical to `TypingMode::Typeck` except that the initial value for
118    /// opaque types is the type computed during HIR typeck with unique unconstrained region inference variables.
119    ///
120    /// This is currently only used by the new solver as it results in new
121    /// non-universal defining uses of opaque types, which is a breaking change.
122    /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
123    PostTypeckUntilBorrowck { defining_opaque_types: I::LocalDefIds },
124    /// Any analysis after borrowck for a given body should be able to use all the
125    /// hidden types defined by borrowck, without being able to define any new ones.
126    ///
127    /// This is currently only used by the new solver, but should be implemented in
128    /// the old solver as well.
129    PostBorrowck { defined_opaque_types: I::LocalDefIds },
130    /// During the evaluation of reflection logic that ignores lifetimes, we can only
131    /// handle impls that are fully generic over all lifetimes without constraints on
132    /// those lifetimes (other than implied bounds).
133    Reflection,
134    /// After analysis, mostly during MIR optimizations, we're able to
135    /// reveal all opaque types. As the hidden type should *never* be observable
136    /// directly by the user, this should not be used by checks which may expose
137    /// such details to the user.
138    ///
139    /// However, we restrict `layout_of` and const-evaluation from exposing some information like
140    /// coroutine layout which requires optimized MIR.
141    PostAnalysis,
142
143    /// During codegen and MIR optimizations, we're able to reveal all opaque types and compute all
144    /// layouts.
145    Codegen,
146
147    /// The typing modes above (except coherence) only differ in how they handle
148    ///
149    /// - Generators
150    /// - Opaque types
151    /// - Specialization (in `PostAnalysis`)
152    ///
153    /// We replace all of them with this `TypingMode` in the first attempt at canonicalization.
154    /// If, during that attempt, we try to access information about opaques or generators
155    /// we bail out, setting a field on `EvalCtxt` that indicates the canonicalization must be
156    /// rerun in the original typing mode.
157    ///
158    /// Specifically, we always reveal auto traits for rigid aliases and thus we don't allow
159    /// incorrectly marked rigid local opaques. We ensure this by immediately bailing out
160    /// when normalizing local opaques.
161    ///
162    /// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
163    ErasedNotCoherence(S),
164}
165
166/// We want to highly discourage using equality checks on typing modes.
167/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
168/// error. Only use `TypingModeEqWrapper` when you really really really have to.
169/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
170/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
171#[automatically_derived]
impl<I: Interner> ::core::clone::Clone for TypingModeEqWrapper<I> where
    I: Interner {
    #[inline]
    fn clone(&self) -> Self { *self }
}
#[automatically_derived]
impl<I: Interner> ::core::marker::Copy for TypingModeEqWrapper<I> where
    I: Interner {
}
#[automatically_derived]
impl<I: Interner> ::core::fmt::Debug for TypingModeEqWrapper<I> where
    I: Interner {
    fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
        -> ::core::fmt::Result {
        match self {
            TypingModeEqWrapper(ref __field_0) => {
                let mut __builder =
                    ::core::fmt::Formatter::debug_tuple(__f,
                        "TypingModeEqWrapper");
                ::core::fmt::DebugTuple::field(&mut __builder, __field_0);
                ::core::fmt::DebugTuple::finish(&mut __builder)
            }
        }
    }
}#[derive_where(Clone, Copy, Debug; I: Interner)]
172#[cfg_attr(
173    feature = "nightly",
174    derive(const _: () =
    {
        impl<I: Interner, __E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for TypingModeEqWrapper<I> where
            TypingMode<I, MayBeErased>: ::rustc_serialize::Encodable<__E> {
            fn encode(&self, __encoder: &mut __E) {
                let TypingModeEqWrapper(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<I: Interner, __D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for TypingModeEqWrapper<I> where
            TypingMode<I, MayBeErased>: ::rustc_serialize::Decodable<__D> {
            fn decode(__decoder: &mut __D) -> Self {
                TypingModeEqWrapper(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<I: Interner> ::rustc_data_structures::stable_hash::StableHash for
            TypingModeEqWrapper<I> where
            TypingMode<I,
            MayBeErased>: ::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) {
                match *self {
                    TypingModeEqWrapper(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash_NoContext)
175)]
176pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
177
178impl<I: Interner> Hash for TypingModeEqWrapper<I> {
179    fn hash<H: Hasher>(&self, state: &mut H) {
180        self.0.hash(state);
181    }
182}
183
184impl<I: Interner> PartialEq for TypingModeEqWrapper<I> {
185    fn eq(&self, other: &Self) -> bool {
186        match (self.0, other.0) {
187            (TypingMode::Coherence, TypingMode::Coherence) => true,
188            (TypingMode::Reflection, TypingMode::Reflection) => true,
189            (
190                TypingMode::Typeck { defining_opaque_types_and_generators: l },
191                TypingMode::Typeck { defining_opaque_types_and_generators: r },
192            ) => l == r,
193            (
194                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: l },
195                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: r },
196            ) => l == r,
197            (
198                TypingMode::PostBorrowck { defined_opaque_types: l },
199                TypingMode::PostBorrowck { defined_opaque_types: r },
200            ) => l == r,
201            (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
202            (TypingMode::Codegen, TypingMode::Codegen) => true,
203            (
204                TypingMode::ErasedNotCoherence(MayBeErased),
205                TypingMode::ErasedNotCoherence(MayBeErased),
206            ) => true,
207            (
208                TypingMode::Coherence
209                | TypingMode::Reflection
210                | TypingMode::Typeck { .. }
211                | TypingMode::PostTypeckUntilBorrowck { .. }
212                | TypingMode::PostBorrowck { .. }
213                | TypingMode::PostAnalysis
214                | TypingMode::Codegen
215                | TypingMode::ErasedNotCoherence(MayBeErased),
216                _,
217            ) => false,
218        }
219    }
220}
221
222impl<I: Interner> Eq for TypingModeEqWrapper<I> {}
223
224impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
225    /// There are a bunch of places in the compiler where we single out `Coherence`,
226    /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
227    /// but not having this method leads to a bunch of noisy code.
228    ///
229    /// See also the documentation on [`TypingMode`] about exhaustive matching.
230    pub fn is_coherence(&self) -> bool {
231        match self {
232            TypingMode::Coherence => true,
233            TypingMode::Typeck { .. }
234            | TypingMode::PostTypeckUntilBorrowck { .. }
235            | TypingMode::Reflection
236            | TypingMode::PostBorrowck { .. }
237            | TypingMode::PostAnalysis
238            | TypingMode::Codegen
239            | TypingMode::ErasedNotCoherence(_) => false,
240        }
241    }
242
243    /// There are a bunch of places in the compiler where we single out `Reflection`,
244    /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
245    /// but not having this method leads to a bunch of noisy code.
246    ///
247    /// See also the documentation on [`TypingMode`] about exhaustive matching.
248    pub fn is_reflection(&self) -> bool {
249        match self {
250            TypingMode::Reflection => true,
251            TypingMode::Typeck { .. }
252            | TypingMode::PostTypeckUntilBorrowck { .. }
253            | TypingMode::Coherence
254            | TypingMode::PostBorrowck { .. }
255            | TypingMode::PostAnalysis
256            | TypingMode::Codegen
257            | TypingMode::ErasedNotCoherence(_) => false,
258        }
259    }
260
261    /// There are a bunch of places in the trait solver where we single out `Coherence`,
262    /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
263    /// but not having this method leads to a bunch of noisy code.
264    ///
265    /// See also the documentation on [`TypingMode`] about exhaustive matching.
266    pub fn is_erased_not_coherence(&self) -> bool {
267        match self {
268            TypingMode::ErasedNotCoherence(_) => true,
269            TypingMode::Coherence
270            | TypingMode::Typeck { .. }
271            | TypingMode::PostTypeckUntilBorrowck { .. }
272            | TypingMode::Reflection
273            | TypingMode::PostBorrowck { .. }
274            | TypingMode::PostAnalysis
275            | TypingMode::Codegen => false,
276        }
277    }
278}
279
280impl<I: Interner> TypingMode<I, MayBeErased> {
281    /// Only call this when you're sure you're outside the next trait solver!
282    /// That means either not in the trait solver, or in code that is old-solver only.
283    ///
284    /// See the comment on `InferCtxt::typing_mode_raw`
285    pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
286        match self {
287            TypingMode::Coherence => TypingMode::Coherence,
288            TypingMode::Typeck { defining_opaque_types_and_generators } => {
289                TypingMode::Typeck { defining_opaque_types_and_generators }
290            }
291            TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
292                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
293            }
294            TypingMode::PostBorrowck { defined_opaque_types } => {
295                TypingMode::PostBorrowck { defined_opaque_types }
296            }
297            TypingMode::PostAnalysis => TypingMode::PostAnalysis,
298            TypingMode::Codegen => TypingMode::Codegen,
299            TypingMode::Reflection => TypingMode::Reflection,
300            TypingMode::ErasedNotCoherence(MayBeErased) => {
    ::core::panicking::panic_fmt(format_args!("Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible"));
}panic!(
301                "Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible"
302            ),
303        }
304    }
305}
306
307impl<I: Interner> TypingMode<I, CantBeErased> {
308    /// Analysis outside of a body does not define any opaque types.
309    pub fn non_body_analysis() -> TypingMode<I> {
310        TypingMode::Typeck { defining_opaque_types_and_generators: Default::default() }
311    }
312
313    pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
314        TypingMode::Typeck {
315            defining_opaque_types_and_generators: cx
316                .opaque_types_and_coroutines_defined_by(body_def_id),
317        }
318    }
319
320    /// While typechecking a body, we need to be able to define the opaque
321    /// types defined by that body.
322    ///
323    /// FIXME: This will be removed because it's generally not correct to define
324    /// opaques outside of HIR typeck.
325    pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
326        TypingMode::Typeck {
327            defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
328        }
329    }
330
331    pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
332        let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
333        if defining_opaque_types.is_empty() {
334            TypingMode::non_body_analysis()
335        } else {
336            TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
337        }
338    }
339
340    pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
341        let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
342        if defined_opaque_types.is_empty() {
343            TypingMode::non_body_analysis()
344        } else {
345            TypingMode::PostBorrowck { defined_opaque_types }
346        }
347    }
348}
349
350impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
351    fn from(value: TypingMode<I, CantBeErased>) -> Self {
352        match value {
353            TypingMode::Coherence => TypingMode::Coherence,
354            TypingMode::Typeck { defining_opaque_types_and_generators } => {
355                TypingMode::Typeck { defining_opaque_types_and_generators }
356            }
357            TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
358                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
359            }
360            TypingMode::PostBorrowck { defined_opaque_types } => {
361                TypingMode::PostBorrowck { defined_opaque_types }
362            }
363            TypingMode::PostAnalysis => TypingMode::PostAnalysis,
364            TypingMode::Codegen => TypingMode::Codegen,
365            TypingMode::Reflection => TypingMode::Reflection,
366        }
367    }
368}
369
370/// `InferCtxtLike` is one of the two traits abstracting over the [InferCtxt][inferctxt-doc], which
371/// had to be split due to coherence reasons:
372/// - `InferCtxtLike`] contains the parts that have to live in `rustc_infer`, and thus aren't only
373///   about trait-solving. It is implemented [directly on `InferCtxt`][inferctxtlike-impl-doc],
374/// - [SolverDelegate][solverdelegate-doc] contains the parts depending on trait-solving logic, to
375///   provide functionality in `rustc_trait_selection`, and is implemented by a [simple wrapper over
376///   `InferCtxt`][inferctxt-wrapper-doc] there.
377///
378/// More information can also be found in the dedicated chapter in the dev-guide, in [this
379/// section][dev-guide].
380///
381/// [inferctxt-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html
382/// [inferctxtlike-impl-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#impl-InferCtxtLike-for-InferCtxt%3C'tcx%3E
383/// [solverdelegate-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/delegate/trait.SolverDelegate.html
384/// [inferctxt-wrapper-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/delegate/struct.SolverDelegate.html
385/// [dev-guide]: https://rustc-dev-guide.rust-lang.org/solve/sharing-crates-with-rust-analyzer.html#trait-inferctxtlike-and-trait-solverdelegate
386#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
387pub trait InferCtxtLike: Sized {
388    type Interner: Interner;
389    fn cx(&self) -> Self::Interner;
390
391    /// Whether the new trait solver is enabled. This only exists because rustc
392    /// shares code between the new and old trait solvers; for all other users,
393    /// this should always be true. If this is unknowingly false and you try to
394    /// use the new trait solver, things will break badly.
395    fn next_trait_solver(&self) -> bool {
396        true
397    }
398
399    fn enable_next_solver_overflow_fcw(&self) -> bool;
400
401    fn disable_trait_solver_fast_paths(&self) -> bool;
402
403    fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
404
405    fn universe(&self) -> ty::UniverseIndex;
406    fn create_next_universe(&self) -> ty::UniverseIndex;
407
408    fn insert_placeholder_assumptions(
409        &self,
410        u: ty::UniverseIndex,
411        assumptions: crate::region_constraint::Assumptions<Self::Interner>,
412    );
413    fn get_placeholder_assumptions(
414        &self,
415        u: ty::UniverseIndex,
416    ) -> crate::region_constraint::Assumptions<Self::Interner>;
417    fn has_placeholder_assumptions(&self, range: RangeInclusive<ty::UniverseIndex>) -> bool;
418    fn get_solver_region_constraint(
419        &self,
420    ) -> crate::region_constraint::RegionConstraint<Self::Interner>;
421    fn overwrite_solver_region_constraint(
422        &self,
423        constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
424        span: <Self::Interner as Interner>::Span,
425    );
426
427    fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
428    fn universe_of_region(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
429    fn universe_of_const(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
430
431    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
432    fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
433    fn is_sub_unification_table_root_var(&self, var: ty::TyVid) -> bool;
434    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
435
436    fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
437    fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
438    fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> <Self::Interner as Interner>::Ty;
439    fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> Const<Self::Interner>;
440    fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> Region<Self::Interner>;
441
442    fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool;
443
444    fn next_region_infer(&self) -> Region<Self::Interner>;
445    fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
446    fn next_const_infer(&self) -> Const<Self::Interner>;
447    fn fresh_args_for_item(
448        &self,
449        def_id: <Self::Interner as Interner>::DefId,
450    ) -> <Self::Interner as Interner>::GenericArgs;
451
452    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
453        &self,
454        value: ty::Binder<Self::Interner, T>,
455    ) -> T;
456
457    fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
458        &self,
459        value: ty::Binder<Self::Interner, T>,
460        f: impl FnOnce(T) -> U,
461    ) -> U;
462
463    /// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
464    /// and should be replaced in the long term by actually taking assumptions into
465    /// account.
466    fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
467        &self,
468        value: ty::Binder<Self::Interner, T>,
469        f: impl FnOnce(T) -> U,
470    ) -> U;
471
472    fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
473    fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
474    fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
475    fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
476    fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
477
478    /// Use `instantiate_ty_var` instead unless you have reasons to skip
479    /// generalization.
480    fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: <Self::Interner as Interner>::Ty);
481    /// Use `instantiate_const_var` instead unless you have reasons to skip
482    /// generalization.
483    fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: Const<Self::Interner>);
484    fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
485        &self,
486        relation: &mut R,
487        target_is_expected: bool,
488        target_vid: ty::TyVid,
489        instantiation_variance: ty::Variance,
490        source_ty: <Self::Interner as Interner>::Ty,
491    ) -> RelateResult<Self::Interner, ()>;
492    fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
493    fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
494    fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
495        &self,
496        relation: &mut R,
497        target_is_expected: bool,
498        target_vid: ty::ConstVid,
499        source_ct: Const<Self::Interner>,
500    ) -> RelateResult<Self::Interner, ()>;
501
502    fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
503
504    fn shallow_resolve(
505        &self,
506        ty: <Self::Interner as Interner>::Ty,
507    ) -> <Self::Interner as Interner>::Ty;
508    fn shallow_resolve_const(&self, ty: Const<Self::Interner>) -> Const<Self::Interner>;
509
510    fn deeply_resolve_ignoring_regions<T>(&self, value: T) -> T
511    where
512        T: TypeFoldable<Self::Interner>;
513
514    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
515
516    fn commit_if_ok<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E>;
517
518    fn sub_regions(
519        &self,
520        sub: Region<Self::Interner>,
521        sup: Region<Self::Interner>,
522        vis: VisibleForLeakCheck,
523        span: <Self::Interner as Interner>::Span,
524    );
525
526    fn equate_regions(
527        &self,
528        a: Region<Self::Interner>,
529        b: Region<Self::Interner>,
530        vis: VisibleForLeakCheck,
531        span: <Self::Interner as Interner>::Span,
532    );
533
534    fn register_solver_region_constraint(
535        &self,
536        c: crate::region_constraint::RegionConstraint<Self::Interner>,
537        span: <Self::Interner as Interner>::Span,
538    );
539
540    fn register_ty_outlives(
541        &self,
542        ty: <Self::Interner as Interner>::Ty,
543        r: Region<Self::Interner>,
544        span: <Self::Interner as Interner>::Span,
545    );
546
547    type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
548    fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
549    fn clone_opaque_types_lookup_table(
550        &self,
551    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
552    fn clone_duplicate_opaque_types(
553        &self,
554    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
555    fn clone_opaque_types_added_since(
556        &self,
557        prev_entries: Self::OpaqueTypeStorageEntries,
558    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
559    fn opaques_with_sub_unified_hidden_type(
560        &self,
561        ty: TyVid,
562    ) -> Vec<ty::OpaqueAliasTy<Self::Interner>>;
563
564    fn register_hidden_type_in_storage(
565        &self,
566        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
567        hidden_ty: <Self::Interner as Interner>::Ty,
568        span: <Self::Interner as Interner>::Span,
569    ) -> Option<<Self::Interner as Interner>::Ty>;
570    fn add_duplicate_opaque_type(
571        &self,
572        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
573        hidden_ty: <Self::Interner as Interner>::Ty,
574        span: <Self::Interner as Interner>::Span,
575    );
576
577    fn reset_opaque_types(&self);
578
579    /// Where possible, replaces type/const/region variables in `value` with their final value.
580    /// If a type/const/region variable has not (yet) been unified, it is left as is.
581    ///
582    /// This is an idempotent operation that does not affect inference state in any way,
583    /// which means it's safe to call this function at will.
584    fn deeply_resolve_via_unification_table<T: TypeFoldable<Self::Interner>>(&self, value: T) -> T {
585        if value.has_infer() {
586            let mut folder = DeepVariableResolver::new(self);
587            value.fold_with(&mut folder)
588        } else {
589            value
590        }
591    }
592}
593
594pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
595    infcx: &'a Infcx,
596    param_env: I::ParamEnv,
597    symbol: I::Symbol,
598) -> bool
599where
600    Infcx: InferCtxtLike<Interner = I>,
601{
602    // Iterate through all goals in param_env to find the one that has the same symbol.
603    for clause in param_env.caller_bounds() {
604        if let ty::ClauseKind::UnstableFeature(sym) = clause.kind().skip_binder() {
605            if sym == symbol {
606                return true;
607            }
608        }
609    }
610
611    // During codegen we must assume that all feature bounds hold as we may be
612    // monomorphizing a body from an upstream crate which had an unstable feature
613    // enabled that we do not.
614    //
615    // Coherence should already report overlap errors involving unstable impls
616    // as the affected code would otherwise break when stabilizing this feature.
617    // It is also easily possible to accidentally cause unsoundness this way as
618    // we have to always enable unstable impls during codegen.
619    //
620    // Return ambiguity can also prevent people from writing code which depends on inference guidance
621    // that might no longer work after the impl is stabilised,
622    // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
623    //
624    // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
625    // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
626
627    match infcx.typing_mode_raw().assert_not_erased() {
628        TypingMode::Coherence
629        | TypingMode::Typeck { .. }
630        | TypingMode::PostTypeckUntilBorrowck { .. }
631        | TypingMode::Reflection
632        | TypingMode::PostBorrowck { .. }
633        | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol),
634        TypingMode::Codegen => true,
635    }
636}
637
638struct DeepVariableResolver<'a, D, I = <D as InferCtxtLike>::Interner>
639where
640    D: InferCtxtLike<Interner = I>,
641    I: Interner,
642{
643    delegate: &'a D,
644    /// We're able to use a cache here as the folder does not have any
645    /// mutable state.
646    cache: DelayedMap<I::Ty, I::Ty>,
647}
648
649impl<'a, Infcx: InferCtxtLike> DeepVariableResolver<'a, Infcx> {
650    fn new(delegate: &'a Infcx) -> Self {
651        DeepVariableResolver { delegate, cache: Default::default() }
652    }
653}
654
655impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
656    for DeepVariableResolver<'_, Infcx>
657{
658    fn cx(&self) -> I {
659        self.delegate.cx()
660    }
661
662    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
663        match t.kind() {
664            ty::Infer(ty::TyVar(vid)) => {
665                let resolved = self.delegate.shallow_resolve_ty_var(vid);
666                if t != resolved && resolved.has_infer() {
667                    resolved.fold_with(self)
668                } else {
669                    resolved
670                }
671            }
672            ty::Infer(ty::IntVar(vid)) => self.delegate.shallow_resolve_int_var(vid),
673            ty::Infer(ty::FloatVar(vid)) => self.delegate.shallow_resolve_float_var(vid),
674            _ => {
675                if t.has_infer() {
676                    if let Some(&ty) = self.cache.get(&t) {
677                        return ty;
678                    }
679                    let res = t.super_fold_with(self);
680                    if !self.cache.insert(t, res) {
    ::core::panicking::panic("assertion failed: self.cache.insert(t, res)")
};assert!(self.cache.insert(t, res));
681                    res
682                } else {
683                    t
684                }
685            }
686        }
687    }
688
689    fn fold_region(&mut self, r: Region<I>) -> Region<I> {
690        match r.kind() {
691            ty::ReVar(vid) => self.delegate.shallow_resolve_region_var(vid),
692            _ => r,
693        }
694    }
695
696    fn fold_const(&mut self, c: Const<I>) -> Const<I> {
697        match c.kind() {
698            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
699                let resolved = self.delegate.shallow_resolve_const_var(vid);
700                if c != resolved && resolved.has_infer() {
701                    resolved.fold_with(self)
702                } else {
703                    resolved
704                }
705            }
706            _ => {
707                if c.has_infer() {
708                    c.super_fold_with(self)
709                } else {
710                    c
711                }
712            }
713        }
714    }
715
716    fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
717        if p.has_infer() { p.super_fold_with(self) } else { p }
718    }
719
720    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
721        if c.has_infer() { c.super_fold_with(self) } else { c }
722    }
723}