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::{TyOrConstInferVar, VisibleForLeakCheck};
13use crate::{
14    self as ty, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder,
15    TypeSuperFoldable, 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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for CantBeErased { }
#[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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MayBeErased { }
#[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) {}
        }
    };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::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)]
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    /// Specifically, we always reveal auto traits for rigid aliases and thus we don't allow
158    /// incorrectly marked rigid local opaques. We ensure this by immediately bailing out
159    /// when normalizing local opaques.
160    ///
161    /// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
162    ErasedNotCoherence(S),
163}
164
165/// We want to highly discourage using equality checks on typing modes.
166/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
167/// error. Only use `TypingModeEqWrapper` when you really really really have to.
168/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
169/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
170#[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)]
171#[cfg_attr(
172    feature = "nightly",
173    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)
174)]
175pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
176
177impl<I: Interner> Hash for TypingModeEqWrapper<I> {
178    fn hash<H: Hasher>(&self, state: &mut H) {
179        self.0.hash(state);
180    }
181}
182
183impl<I: Interner> PartialEq for TypingModeEqWrapper<I> {
184    fn eq(&self, other: &Self) -> bool {
185        match (self.0, other.0) {
186            (TypingMode::Coherence, TypingMode::Coherence) => true,
187            (TypingMode::Reflection, TypingMode::Reflection) => true,
188            (
189                TypingMode::Typeck { defining_opaque_types_and_generators: l },
190                TypingMode::Typeck { defining_opaque_types_and_generators: r },
191            ) => l == r,
192            (
193                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: l },
194                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: r },
195            ) => l == r,
196            (
197                TypingMode::PostBorrowck { defined_opaque_types: l },
198                TypingMode::PostBorrowck { defined_opaque_types: r },
199            ) => l == r,
200            (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
201            (TypingMode::Codegen, TypingMode::Codegen) => true,
202            (
203                TypingMode::ErasedNotCoherence(MayBeErased),
204                TypingMode::ErasedNotCoherence(MayBeErased),
205            ) => true,
206            (
207                TypingMode::Coherence
208                | TypingMode::Reflection
209                | TypingMode::Typeck { .. }
210                | TypingMode::PostTypeckUntilBorrowck { .. }
211                | TypingMode::PostBorrowck { .. }
212                | TypingMode::PostAnalysis
213                | TypingMode::Codegen
214                | TypingMode::ErasedNotCoherence(MayBeErased),
215                _,
216            ) => false,
217        }
218    }
219}
220
221impl<I: Interner> Eq for TypingModeEqWrapper<I> {}
222
223impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
224    /// There are a bunch of places in the compiler where we single out `Coherence`,
225    /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
226    /// but not having this method leads to a bunch of noisy code.
227    ///
228    /// See also the documentation on [`TypingMode`] about exhaustive matching.
229    pub fn is_coherence(&self) -> bool {
230        match self {
231            TypingMode::Coherence => true,
232            TypingMode::Typeck { .. }
233            | TypingMode::PostTypeckUntilBorrowck { .. }
234            | TypingMode::Reflection
235            | TypingMode::PostBorrowck { .. }
236            | TypingMode::PostAnalysis
237            | TypingMode::Codegen
238            | TypingMode::ErasedNotCoherence(_) => false,
239        }
240    }
241
242    /// There are a bunch of places in the compiler where we single out `Reflection`,
243    /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
244    /// but not having this method leads to a bunch of noisy code.
245    ///
246    /// See also the documentation on [`TypingMode`] about exhaustive matching.
247    pub fn is_reflection(&self) -> bool {
248        match self {
249            TypingMode::Reflection => true,
250            TypingMode::Typeck { .. }
251            | TypingMode::PostTypeckUntilBorrowck { .. }
252            | TypingMode::Coherence
253            | TypingMode::PostBorrowck { .. }
254            | TypingMode::PostAnalysis
255            | TypingMode::Codegen
256            | TypingMode::ErasedNotCoherence(_) => false,
257        }
258    }
259
260    /// There are a bunch of places in the trait solver where we single out `Coherence`,
261    /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
262    /// but not having this method leads to a bunch of noisy code.
263    ///
264    /// See also the documentation on [`TypingMode`] about exhaustive matching.
265    pub fn is_erased_not_coherence(&self) -> bool {
266        match self {
267            TypingMode::ErasedNotCoherence(_) => true,
268            TypingMode::Coherence
269            | TypingMode::Typeck { .. }
270            | TypingMode::PostTypeckUntilBorrowck { .. }
271            | TypingMode::Reflection
272            | TypingMode::PostBorrowck { .. }
273            | TypingMode::PostAnalysis
274            | TypingMode::Codegen => false,
275        }
276    }
277}
278
279impl<I: Interner> TypingMode<I, MayBeErased> {
280    /// Only call this when you're sure you're outside the next trait solver!
281    /// That means either not in the trait solver, or in code that is old-solver only.
282    ///
283    /// See the comment on `InferCtxt::typing_mode_raw`
284    pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
285        match self {
286            TypingMode::Coherence => TypingMode::Coherence,
287            TypingMode::Typeck { defining_opaque_types_and_generators } => {
288                TypingMode::Typeck { defining_opaque_types_and_generators }
289            }
290            TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
291                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
292            }
293            TypingMode::PostBorrowck { defined_opaque_types } => {
294                TypingMode::PostBorrowck { defined_opaque_types }
295            }
296            TypingMode::PostAnalysis => TypingMode::PostAnalysis,
297            TypingMode::Codegen => TypingMode::Codegen,
298            TypingMode::Reflection => TypingMode::Reflection,
299            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!(
300                "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"
301            ),
302        }
303    }
304}
305
306impl<I: Interner> TypingMode<I, CantBeErased> {
307    /// Analysis outside of a body does not define any opaque types.
308    pub fn non_body_analysis() -> TypingMode<I> {
309        TypingMode::Typeck { defining_opaque_types_and_generators: Default::default() }
310    }
311
312    pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
313        TypingMode::Typeck {
314            defining_opaque_types_and_generators: cx
315                .opaque_types_and_coroutines_defined_by(body_def_id),
316        }
317    }
318
319    /// While typechecking a body, we need to be able to define the opaque
320    /// types defined by that body.
321    ///
322    /// FIXME: This will be removed because it's generally not correct to define
323    /// opaques outside of HIR typeck.
324    pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
325        TypingMode::Typeck {
326            defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
327        }
328    }
329
330    pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
331        let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
332        if defining_opaque_types.is_empty() {
333            TypingMode::non_body_analysis()
334        } else {
335            TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
336        }
337    }
338
339    pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
340        let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
341        if defined_opaque_types.is_empty() {
342            TypingMode::non_body_analysis()
343        } else {
344            TypingMode::PostBorrowck { defined_opaque_types }
345        }
346    }
347}
348
349impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
350    fn from(value: TypingMode<I, CantBeErased>) -> Self {
351        match value {
352            TypingMode::Coherence => TypingMode::Coherence,
353            TypingMode::Typeck { defining_opaque_types_and_generators } => {
354                TypingMode::Typeck { defining_opaque_types_and_generators }
355            }
356            TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
357                TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
358            }
359            TypingMode::PostBorrowck { defined_opaque_types } => {
360                TypingMode::PostBorrowck { defined_opaque_types }
361            }
362            TypingMode::PostAnalysis => TypingMode::PostAnalysis,
363            TypingMode::Codegen => TypingMode::Codegen,
364            TypingMode::Reflection => TypingMode::Reflection,
365        }
366    }
367}
368
369/// `InferCtxtLike` is one of the two traits abstracting over the [InferCtxt][inferctxt-doc], which
370/// had to be split due to coherence reasons:
371/// - `InferCtxtLike`] contains the parts that have to live in `rustc_infer`, and thus aren't only
372///   about trait-solving. It is implemented [directly on `InferCtxt`][inferctxtlike-impl-doc],
373/// - [SolverDelegate][solverdelegate-doc] contains the parts depending on trait-solving logic, to
374///   provide functionality in `rustc_trait_selection`, and is implemented by a [simple wrapper over
375///   `InferCtxt`][inferctxt-wrapper-doc] there.
376///
377/// More information can also be found in the dedicated chapter in the dev-guide, in [this
378/// section][dev-guide].
379///
380/// [inferctxt-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html
381/// [inferctxtlike-impl-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#impl-InferCtxtLike-for-InferCtxt%3C'tcx%3E
382/// [solverdelegate-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/delegate/trait.SolverDelegate.html
383/// [inferctxt-wrapper-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/delegate/struct.SolverDelegate.html
384/// [dev-guide]: https://rustc-dev-guide.rust-lang.org/solve/sharing-crates-with-rust-analyzer.html#trait-inferctxtlike-and-trait-solverdelegate
385#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
386pub trait InferCtxtLike: Sized {
387    type Interner: Interner;
388    fn cx(&self) -> Self::Interner;
389
390    /// Whether the new trait solver is enabled. This only exists because rustc
391    /// shares code between the new and old trait solvers; for all other users,
392    /// this should always be true. If this is unknowingly false and you try to
393    /// use the new trait solver, things will break badly.
394    fn next_trait_solver(&self) -> bool {
395        true
396    }
397
398    fn enable_next_solver_overflow_fcw(&self) -> bool;
399
400    fn disable_trait_solver_fast_paths(&self) -> bool;
401
402    fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
403
404    fn universe(&self) -> ty::UniverseIndex;
405    fn create_next_universe(&self) -> ty::UniverseIndex;
406
407    fn insert_placeholder_assumptions(
408        &self,
409        u: ty::UniverseIndex,
410        assumptions: Option<crate::region_constraint::Assumptions<Self::Interner>>,
411    );
412    fn get_placeholder_assumptions(
413        &self,
414        u: ty::UniverseIndex,
415    ) -> Option<crate::region_constraint::Assumptions<Self::Interner>>;
416    fn get_solver_region_constraint(
417        &self,
418    ) -> crate::region_constraint::RegionConstraint<Self::Interner>;
419    fn overwrite_solver_region_constraint(
420        &self,
421        constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
422        span: <Self::Interner as Interner>::Span,
423    );
424
425    fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
426    fn universe_of_region(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
427    fn universe_of_const(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
428
429    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
430    fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
431    fn is_sub_unification_table_root_var(&self, var: ty::TyVid) -> bool;
432    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
433
434    fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
435    fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
436    fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> <Self::Interner as Interner>::Ty;
437    fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> <Self::Interner as Interner>::Const;
438    fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> Region<Self::Interner>;
439
440    fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool;
441
442    fn next_region_infer(&self) -> Region<Self::Interner>;
443    fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
444    fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
445    fn fresh_args_for_item(
446        &self,
447        def_id: <Self::Interner as Interner>::DefId,
448    ) -> <Self::Interner as Interner>::GenericArgs;
449
450    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
451        &self,
452        value: ty::Binder<Self::Interner, T>,
453    ) -> T;
454
455    fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
456        &self,
457        value: ty::Binder<Self::Interner, T>,
458        f: impl FnOnce(T) -> U,
459    ) -> U;
460
461    /// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
462    /// and should be replaced in the long term by actually taking assumptions into
463    /// account.
464    fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
465        &self,
466        value: ty::Binder<Self::Interner, T>,
467        f: impl FnOnce(T) -> U,
468    ) -> U;
469
470    fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
471    fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
472    fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
473    fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
474    fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
475
476    /// Use `instantiate_ty_var` instead unless you have reasons to skip
477    /// generalization.
478    fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: <Self::Interner as Interner>::Ty);
479    /// Use `instantiate_const_var` instead unless you have reasons to skip
480    /// generalization.
481    fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: <Self::Interner as Interner>::Const);
482    fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
483        &self,
484        relation: &mut R,
485        target_is_expected: bool,
486        target_vid: ty::TyVid,
487        instantiation_variance: ty::Variance,
488        source_ty: <Self::Interner as Interner>::Ty,
489    ) -> RelateResult<Self::Interner, ()>;
490    fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
491    fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
492    fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
493        &self,
494        relation: &mut R,
495        target_is_expected: bool,
496        target_vid: ty::ConstVid,
497        source_ct: <Self::Interner as Interner>::Const,
498    ) -> RelateResult<Self::Interner, ()>;
499
500    fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
501
502    fn shallow_resolve(
503        &self,
504        ty: <Self::Interner as Interner>::Ty,
505    ) -> <Self::Interner as Interner>::Ty;
506    fn shallow_resolve_const(
507        &self,
508        ty: <Self::Interner as Interner>::Const,
509    ) -> <Self::Interner as Interner>::Const;
510
511    fn deeply_resolve_ignoring_regions<T>(&self, value: T) -> T
512    where
513        T: TypeFoldable<Self::Interner>;
514
515    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
516
517    fn commit_if_ok<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E>;
518
519    fn sub_regions(
520        &self,
521        sub: Region<Self::Interner>,
522        sup: Region<Self::Interner>,
523        vis: VisibleForLeakCheck,
524        span: <Self::Interner as Interner>::Span,
525    );
526
527    fn equate_regions(
528        &self,
529        a: Region<Self::Interner>,
530        b: Region<Self::Interner>,
531        vis: VisibleForLeakCheck,
532        span: <Self::Interner as Interner>::Span,
533    );
534
535    fn register_solver_region_constraint(
536        &self,
537        c: crate::region_constraint::RegionConstraint<Self::Interner>,
538        span: <Self::Interner as Interner>::Span,
539    );
540
541    fn register_ty_outlives(
542        &self,
543        ty: <Self::Interner as Interner>::Ty,
544        r: Region<Self::Interner>,
545        span: <Self::Interner as Interner>::Span,
546    );
547
548    type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
549    fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
550    fn clone_opaque_types_lookup_table(
551        &self,
552    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
553    fn clone_duplicate_opaque_types(
554        &self,
555    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
556    fn clone_opaque_types_added_since(
557        &self,
558        prev_entries: Self::OpaqueTypeStorageEntries,
559    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
560    fn opaques_with_sub_unified_hidden_type(
561        &self,
562        ty: TyVid,
563    ) -> Vec<ty::OpaqueAliasTy<Self::Interner>>;
564
565    fn register_hidden_type_in_storage(
566        &self,
567        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
568        hidden_ty: <Self::Interner as Interner>::Ty,
569        span: <Self::Interner as Interner>::Span,
570    ) -> Option<<Self::Interner as Interner>::Ty>;
571    fn add_duplicate_opaque_type(
572        &self,
573        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
574        hidden_ty: <Self::Interner as Interner>::Ty,
575        span: <Self::Interner as Interner>::Span,
576    );
577
578    fn reset_opaque_types(&self);
579
580    /// Where possible, replaces type/const/region variables in `value` with their final value.
581    /// If a type/const/region variable has not (yet) been unified, it is left as is.
582    ///
583    /// This is an idempotent operation that does not affect inference state in any way,
584    /// which means it's safe to call this function at will.
585    fn deeply_resolve_via_unification_table<T: TypeFoldable<Self::Interner>>(&self, value: T) -> T {
586        if value.has_infer() {
587            let mut folder = DeepVariableResolver::new(self);
588            value.fold_with(&mut folder)
589        } else {
590            value
591        }
592    }
593}
594
595pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
596    infcx: &'a Infcx,
597    param_env: I::ParamEnv,
598    symbol: I::Symbol,
599) -> bool
600where
601    Infcx: InferCtxtLike<Interner = I>,
602{
603    // Iterate through all goals in param_env to find the one that has the same symbol.
604    for clause in param_env.caller_bounds() {
605        if let ty::ClauseKind::UnstableFeature(sym) = clause.kind().skip_binder() {
606            if sym == symbol {
607                return true;
608            }
609        }
610    }
611
612    // During codegen we must assume that all feature bounds hold as we may be
613    // monomorphizing a body from an upstream crate which had an unstable feature
614    // enabled that we do not.
615    //
616    // Coherence should already report overlap errors involving unstable impls
617    // as the affected code would otherwise break when stabilizing this feature.
618    // It is also easily possible to accidentally cause unsoundness this way as
619    // we have to always enable unstable impls during codegen.
620    //
621    // Return ambiguity can also prevent people from writing code which depends on inference guidance
622    // that might no longer work after the impl is stabilised,
623    // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
624    //
625    // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
626    // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
627
628    match infcx.typing_mode_raw().assert_not_erased() {
629        TypingMode::Coherence
630        | TypingMode::Typeck { .. }
631        | TypingMode::PostTypeckUntilBorrowck { .. }
632        | TypingMode::Reflection
633        | TypingMode::PostBorrowck { .. }
634        | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol),
635        TypingMode::Codegen => true,
636    }
637}
638
639struct DeepVariableResolver<'a, D, I = <D as InferCtxtLike>::Interner>
640where
641    D: InferCtxtLike<Interner = I>,
642    I: Interner,
643{
644    delegate: &'a D,
645    /// We're able to use a cache here as the folder does not have any
646    /// mutable state.
647    cache: DelayedMap<I::Ty, I::Ty>,
648}
649
650impl<'a, Infcx: InferCtxtLike> DeepVariableResolver<'a, Infcx> {
651    fn new(delegate: &'a Infcx) -> Self {
652        DeepVariableResolver { delegate, cache: Default::default() }
653    }
654}
655
656impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
657    for DeepVariableResolver<'_, Infcx>
658{
659    fn cx(&self) -> I {
660        self.delegate.cx()
661    }
662
663    fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
664        match t.kind() {
665            ty::Infer(ty::TyVar(vid)) => {
666                let resolved = self.delegate.shallow_resolve_ty_var(vid);
667                if t != resolved && resolved.has_infer() {
668                    resolved.fold_with(self)
669                } else {
670                    resolved
671                }
672            }
673            ty::Infer(ty::IntVar(vid)) => self.delegate.shallow_resolve_int_var(vid),
674            ty::Infer(ty::FloatVar(vid)) => self.delegate.shallow_resolve_float_var(vid),
675            _ => {
676                if t.has_infer() {
677                    if let Some(&ty) = self.cache.get(&t) {
678                        return ty;
679                    }
680                    let res = t.super_fold_with(self);
681                    if !self.cache.insert(t, res) {
    ::core::panicking::panic("assertion failed: self.cache.insert(t, res)")
};assert!(self.cache.insert(t, res));
682                    res
683                } else {
684                    t
685                }
686            }
687        }
688    }
689
690    fn fold_region(&mut self, r: Region<I>) -> Region<I> {
691        match r.kind() {
692            ty::ReVar(vid) => self.delegate.shallow_resolve_region_var(vid),
693            _ => r,
694        }
695    }
696
697    fn fold_const(&mut self, c: I::Const) -> I::Const {
698        match c.kind() {
699            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
700                let resolved = self.delegate.shallow_resolve_const_var(vid);
701                if c != resolved && resolved.has_infer() {
702                    resolved.fold_with(self)
703                } else {
704                    resolved
705                }
706            }
707            _ => {
708                if c.has_infer() {
709                    c.super_fold_with(self)
710                } else {
711                    c
712                }
713            }
714        }
715    }
716
717    fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
718        if p.has_infer() { p.super_fold_with(self) } else { p }
719    }
720
721    fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
722        if c.has_infer() { c.super_fold_with(self) } else { c }
723    }
724}