Skip to main content

rustc_type_ir/
infer_ctxt.rs

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