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