rustc_type_ir/
infer_ctxt.rs

1use derive_where::derive_where;
2#[cfg(feature = "nightly")]
3use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
4
5use crate::fold::TypeFoldable;
6use crate::inherent::*;
7use crate::relate::RelateResult;
8use crate::relate::combine::PredicateEmittingRelation;
9use crate::{self as ty, Interner};
10
11/// The current typing mode of an inference context. We unfortunately have some
12/// slightly different typing rules depending on the current context. See the
13/// doc comment for each variant for how and why they are used.
14///
15/// In most cases you can get the correct typing mode automatically via:
16/// - `mir::Body::typing_mode`
17/// - `rustc_lint::LateContext::typing_mode`
18///
19/// If neither of these functions are available, feel free to reach out to
20/// t-types for help.
21#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
22#[cfg_attr(
23    feature = "nightly",
24    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
25)]
26pub enum TypingMode<I: Interner> {
27    /// When checking whether impls overlap, we check whether any obligations
28    /// are guaranteed to never hold when unifying the impls. This requires us
29    /// to be complete: we must never fail to prove something which may actually
30    /// hold.
31    ///
32    /// In this typing mode we bail with ambiguity in case its not knowable
33    /// whether a trait goal may hold, e.g. because the trait may get implemented
34    /// in a downstream or sibling crate.
35    ///
36    /// We also have to be careful when generalizing aliases inside of higher-ranked
37    /// types to not unnecessarily constrain any inference variables.
38    Coherence,
39    /// Analysis includes type inference, checking that items are well-formed, and
40    /// pretty much everything else which may emit proper type errors to the user.
41    ///
42    /// We only normalize opaque types which may get defined by the current body,
43    /// which are stored in `defining_opaque_types`.
44    ///
45    /// We also refuse to project any associated type that is marked `default`.
46    /// Non-`default` ("final") types are always projected. This is necessary in
47    /// general for soundness of specialization. However, we *could* allow projections
48    /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
49    /// to force the type definition to be treated abstractly by any consumers of the
50    /// impl. Concretely, that means that the following example will
51    /// fail to compile:
52    ///
53    /// ```compile_fail,E0308
54    /// #![feature(specialization)]
55    /// trait Assoc {
56    ///     type Output;
57    /// }
58    ///
59    /// impl<T> Assoc for T {
60    ///     default type Output = bool;
61    /// }
62    ///
63    /// fn main() {
64    ///     let x: <() as Assoc>::Output = true;
65    /// }
66    /// ```
67    Analysis { defining_opaque_types_and_generators: I::LocalDefIds },
68    /// The behavior during MIR borrowck is identical to `TypingMode::Analysis`
69    /// except that the initial value for opaque types is the type computed during
70    /// HIR typeck with unique unconstrained region inference variables.
71    ///
72    /// This is currently only used with by the new solver as it results in new
73    /// non-universal defining uses of opaque types, which is a breaking change.
74    /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
75    Borrowck { defining_opaque_types: I::LocalDefIds },
76    /// Any analysis after borrowck for a given body should be able to use all the
77    /// hidden types defined by borrowck, without being able to define any new ones.
78    ///
79    /// This is currently only used by the new solver, but should be implemented in
80    /// the old solver as well.
81    PostBorrowckAnalysis { defined_opaque_types: I::LocalDefIds },
82    /// After analysis, mostly during codegen and MIR optimizations, we're able to
83    /// reveal all opaque types. As the concrete type should *never* be observable
84    /// directly by the user, this should not be used by checks which may expose
85    /// such details to the user.
86    ///
87    /// There are some exceptions to this as for example `layout_of` and const-evaluation
88    /// always run in `PostAnalysis` mode, even when used during analysis. This exposes
89    /// some information about the underlying type to users, but not the type itself.
90    PostAnalysis,
91}
92
93impl<I: Interner> Eq for TypingMode<I> {}
94
95impl<I: Interner> TypingMode<I> {
96    /// Analysis outside of a body does not define any opaque types.
97    pub fn non_body_analysis() -> TypingMode<I> {
98        TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
99    }
100
101    pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
102        TypingMode::Analysis {
103            defining_opaque_types_and_generators: cx
104                .opaque_types_and_coroutines_defined_by(body_def_id),
105        }
106    }
107
108    /// While typechecking a body, we need to be able to define the opaque
109    /// types defined by that body.
110    ///
111    /// FIXME: This will be removed because it's generally not correct to define
112    /// opaques outside of HIR typeck.
113    pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
114        TypingMode::Analysis {
115            defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
116        }
117    }
118
119    pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
120        let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
121        if defining_opaque_types.is_empty() {
122            TypingMode::non_body_analysis()
123        } else {
124            TypingMode::Borrowck { defining_opaque_types }
125        }
126    }
127
128    pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
129        let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
130        if defined_opaque_types.is_empty() {
131            TypingMode::non_body_analysis()
132        } else {
133            TypingMode::PostBorrowckAnalysis { defined_opaque_types }
134        }
135    }
136}
137
138#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
139pub trait InferCtxtLike: Sized {
140    type Interner: Interner;
141    fn cx(&self) -> Self::Interner;
142
143    /// Whether the new trait solver is enabled. This only exists because rustc
144    /// shares code between the new and old trait solvers; for all other users,
145    /// this should always be true. If this is unknowingly false and you try to
146    /// use the new trait solver, things will break badly.
147    fn next_trait_solver(&self) -> bool {
148        true
149    }
150
151    fn typing_mode(&self) -> TypingMode<Self::Interner>;
152
153    fn universe(&self) -> ty::UniverseIndex;
154    fn create_next_universe(&self) -> ty::UniverseIndex;
155
156    fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
157    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
158    fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
159
160    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
161    fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
162    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
163
164    fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
165    fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
166    fn opportunistic_resolve_float_var(
167        &self,
168        vid: ty::FloatVid,
169    ) -> <Self::Interner as Interner>::Ty;
170    fn opportunistic_resolve_ct_var(
171        &self,
172        vid: ty::ConstVid,
173    ) -> <Self::Interner as Interner>::Const;
174    fn opportunistic_resolve_lt_var(
175        &self,
176        vid: ty::RegionVid,
177    ) -> <Self::Interner as Interner>::Region;
178
179    fn is_changed_arg(&self, arg: <Self::Interner as Interner>::GenericArg) -> bool;
180
181    fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
182    fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
183    fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
184    fn fresh_args_for_item(
185        &self,
186        def_id: <Self::Interner as Interner>::DefId,
187    ) -> <Self::Interner as Interner>::GenericArgs;
188
189    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
190        &self,
191        value: ty::Binder<Self::Interner, T>,
192    ) -> T;
193
194    fn enter_forall<T: TypeFoldable<Self::Interner>, U>(
195        &self,
196        value: ty::Binder<Self::Interner, T>,
197        f: impl FnOnce(T) -> U,
198    ) -> U;
199
200    fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
201    fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
202    fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
203    fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
204    fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
205
206    fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
207        &self,
208        relation: &mut R,
209        target_is_expected: bool,
210        target_vid: ty::TyVid,
211        instantiation_variance: ty::Variance,
212        source_ty: <Self::Interner as Interner>::Ty,
213    ) -> RelateResult<Self::Interner, ()>;
214    fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
215    fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
216    fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
217        &self,
218        relation: &mut R,
219        target_is_expected: bool,
220        target_vid: ty::ConstVid,
221        source_ct: <Self::Interner as Interner>::Const,
222    ) -> RelateResult<Self::Interner, ()>;
223
224    fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
225
226    fn shallow_resolve(
227        &self,
228        ty: <Self::Interner as Interner>::Ty,
229    ) -> <Self::Interner as Interner>::Ty;
230    fn shallow_resolve_const(
231        &self,
232        ty: <Self::Interner as Interner>::Const,
233    ) -> <Self::Interner as Interner>::Const;
234
235    fn resolve_vars_if_possible<T>(&self, value: T) -> T
236    where
237        T: TypeFoldable<Self::Interner>;
238
239    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
240
241    fn sub_regions(
242        &self,
243        sub: <Self::Interner as Interner>::Region,
244        sup: <Self::Interner as Interner>::Region,
245        span: <Self::Interner as Interner>::Span,
246    );
247
248    fn equate_regions(
249        &self,
250        a: <Self::Interner as Interner>::Region,
251        b: <Self::Interner as Interner>::Region,
252        span: <Self::Interner as Interner>::Span,
253    );
254
255    fn register_ty_outlives(
256        &self,
257        ty: <Self::Interner as Interner>::Ty,
258        r: <Self::Interner as Interner>::Region,
259        span: <Self::Interner as Interner>::Span,
260    );
261
262    type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
263    fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
264    fn clone_opaque_types_lookup_table(
265        &self,
266    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
267    fn clone_duplicate_opaque_types(
268        &self,
269    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
270    fn clone_opaque_types_added_since(
271        &self,
272        prev_entries: Self::OpaqueTypeStorageEntries,
273    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
274
275    fn register_hidden_type_in_storage(
276        &self,
277        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
278        hidden_ty: <Self::Interner as Interner>::Ty,
279        span: <Self::Interner as Interner>::Span,
280    ) -> Option<<Self::Interner as Interner>::Ty>;
281    fn add_duplicate_opaque_type(
282        &self,
283        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
284        hidden_ty: <Self::Interner as Interner>::Ty,
285        span: <Self::Interner as Interner>::Span,
286    );
287
288    fn reset_opaque_types(&self);
289}
290
291pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
292    infcx: &'a Infcx,
293    param_env: I::ParamEnv,
294    symbol: I::Symbol,
295) -> bool
296where
297    Infcx: InferCtxtLike<Interner = I>,
298{
299    // Iterate through all goals in param_env to find the one that has the same symbol.
300    for pred in param_env.caller_bounds().iter() {
301        if let ty::ClauseKind::UnstableFeature(sym) = pred.kind().skip_binder() {
302            if sym == symbol {
303                return true;
304            }
305        }
306    }
307
308    // During codegen we must assume that all feature bounds hold as we may be
309    // monomorphizing a body from an upstream crate which had an unstable feature
310    // enabled that we do not.
311    //
312    // Coherence should already report overlap errors involving unstable impls
313    // as the affected code would otherwise break when stabilizing this feature.
314    // It is also easily possible to accidentally cause unsoundness this way as
315    // we have to always enable unstable impls during codegen.
316    //
317    // Return ambiguity can also prevent people from writing code which depends on inference guidance
318    // that might no longer work after the impl is stabilised,
319    // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
320    //
321    // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
322    // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
323
324    (infcx.typing_mode() == TypingMode::PostAnalysis)
325        || infcx.cx().features().feature_bound_holds_in_crate(symbol)
326}