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::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 automically 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, Eq, Debug; I: Interner)]
22#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
23#[cfg_attr(
24    feature = "nightly",
25    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
26)]
27pub enum TypingMode<I: Interner> {
28    /// When checking whether impls overlap, we check whether any obligations
29    /// are guaranteed to never hold when unifying the impls. This requires us
30    /// to be complete: we must never fail to prove something which may actually
31    /// hold.
32    ///
33    /// In this typing mode we bail with ambiguity in case its not knowable
34    /// whether a trait goal may hold, e.g. because the trait may get implemented
35    /// in a downstream or sibling crate.
36    ///
37    /// We also have to be careful when generalizing aliases inside of higher-ranked
38    /// types to not unnecessarily constrain any inference variables.
39    Coherence,
40    /// Analysis includes type inference, checking that items are well-formed, and
41    /// pretty much everything else which may emit proper type errors to the user.
42    ///
43    /// We only normalize opaque types which may get defined by the current body,
44    /// which are stored in `defining_opaque_types`.
45    ///
46    /// We also refuse to project any associated type that is marked `default`.
47    /// Non-`default` ("final") types are always projected. This is necessary in
48    /// general for soundness of specialization. However, we *could* allow projections
49    /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
50    /// to force the type definition to be treated abstractly by any consumers of the
51    /// impl. Concretely, that means that the following example will
52    /// fail to compile:
53    ///
54    /// ```compile_fail,E0308
55    /// #![feature(specialization)]
56    /// trait Assoc {
57    ///     type Output;
58    /// }
59    ///
60    /// impl<T> Assoc for T {
61    ///     default type Output = bool;
62    /// }
63    ///
64    /// fn main() {
65    ///     let x: <() as Assoc>::Output = true;
66    /// }
67    /// ```
68    Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
69    /// Any analysis after borrowck for a given body should be able to use all the
70    /// hidden types defined by borrowck, without being able to define any new ones.
71    ///
72    /// This is currently only used by the new solver, but should be implemented in
73    /// the old solver as well.
74    PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes },
75    /// After analysis, mostly during codegen and MIR optimizations, we're able to
76    /// reveal all opaque types. As the concrete type should *never* be observable
77    /// directly by the user, this should not be used by checks which may expose
78    /// such details to the user.
79    ///
80    /// There are some exceptions to this as for example `layout_of` and const-evaluation
81    /// always run in `PostAnalysis` mode, even when used during analysis. This exposes
82    /// some information about the underlying type to users, but not the type itself.
83    PostAnalysis,
84}
85
86impl<I: Interner> TypingMode<I> {
87    /// Analysis outside of a body does not define any opaque types.
88    pub fn non_body_analysis() -> TypingMode<I> {
89        TypingMode::Analysis { defining_opaque_types: Default::default() }
90    }
91
92    /// While typechecking a body, we need to be able to define the opaque
93    /// types defined by that body.
94    pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
95        TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
96    }
97
98    pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
99        TypingMode::PostBorrowckAnalysis {
100            defined_opaque_types: cx.opaque_types_defined_by(body_def_id),
101        }
102    }
103}
104
105pub trait InferCtxtLike: Sized {
106    type Interner: Interner;
107    fn cx(&self) -> Self::Interner;
108
109    /// Whether the new trait solver is enabled. This only exists because rustc
110    /// shares code between the new and old trait solvers; for all other users,
111    /// this should always be true. If this is unknowingly false and you try to
112    /// use the new trait solver, things will break badly.
113    fn next_trait_solver(&self) -> bool {
114        true
115    }
116
117    fn typing_mode(&self) -> TypingMode<Self::Interner>;
118
119    fn universe(&self) -> ty::UniverseIndex;
120    fn create_next_universe(&self) -> ty::UniverseIndex;
121
122    fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
123    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
124    fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
125
126    fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
127    fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
128
129    fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
130    fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
131    fn opportunistic_resolve_float_var(
132        &self,
133        vid: ty::FloatVid,
134    ) -> <Self::Interner as Interner>::Ty;
135    fn opportunistic_resolve_ct_var(
136        &self,
137        vid: ty::ConstVid,
138    ) -> <Self::Interner as Interner>::Const;
139    fn opportunistic_resolve_lt_var(
140        &self,
141        vid: ty::RegionVid,
142    ) -> <Self::Interner as Interner>::Region;
143
144    fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
145    fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
146    fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
147    fn fresh_args_for_item(
148        &self,
149        def_id: <Self::Interner as Interner>::DefId,
150    ) -> <Self::Interner as Interner>::GenericArgs;
151
152    fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
153        &self,
154        value: ty::Binder<Self::Interner, T>,
155    ) -> T;
156
157    fn enter_forall<T: TypeFoldable<Self::Interner>, U>(
158        &self,
159        value: ty::Binder<Self::Interner, T>,
160        f: impl FnOnce(T) -> U,
161    ) -> U;
162
163    fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
164    fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
165    fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
166    fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
167
168    fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
169        &self,
170        relation: &mut R,
171        target_is_expected: bool,
172        target_vid: ty::TyVid,
173        instantiation_variance: ty::Variance,
174        source_ty: <Self::Interner as Interner>::Ty,
175    ) -> RelateResult<Self::Interner, ()>;
176    fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
177    fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
178    fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
179        &self,
180        relation: &mut R,
181        target_is_expected: bool,
182        target_vid: ty::ConstVid,
183        source_ct: <Self::Interner as Interner>::Const,
184    ) -> RelateResult<Self::Interner, ()>;
185
186    fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
187
188    fn shallow_resolve(
189        &self,
190        ty: <Self::Interner as Interner>::Ty,
191    ) -> <Self::Interner as Interner>::Ty;
192    fn shallow_resolve_const(
193        &self,
194        ty: <Self::Interner as Interner>::Const,
195    ) -> <Self::Interner as Interner>::Const;
196
197    fn resolve_vars_if_possible<T>(&self, value: T) -> T
198    where
199        T: TypeFoldable<Self::Interner>;
200
201    fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
202
203    fn sub_regions(
204        &self,
205        sub: <Self::Interner as Interner>::Region,
206        sup: <Self::Interner as Interner>::Region,
207        span: <Self::Interner as Interner>::Span,
208    );
209
210    fn equate_regions(
211        &self,
212        a: <Self::Interner as Interner>::Region,
213        b: <Self::Interner as Interner>::Region,
214        span: <Self::Interner as Interner>::Span,
215    );
216
217    fn register_ty_outlives(
218        &self,
219        ty: <Self::Interner as Interner>::Ty,
220        r: <Self::Interner as Interner>::Region,
221        span: <Self::Interner as Interner>::Span,
222    );
223}