rustc_type_ir/
infer_ctxt.rs

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