rustc_type_ir/
infer_ctxt.rs

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