Skip to main content

rustc_type_ir/
infer_ctxt.rs

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