1use derive_where::derive_where;
2#[cfg(feature = "nightly")]
3use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
45use crate::fold::TypeFoldable;
6use crate::inherent::*;
7use crate::relate::RelateResult;
8use crate::relate::combine::PredicateEmittingRelation;
9use crate::{selfas ty, Interner, TyVid};
1011/// 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#[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, PartialEq, Debug; I: Interner)]22#[cfg_attr(
23 feature = "nightly",
24 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, __CTX>
::rustc_data_structures::stable_hasher::HashStable<__CTX> for
TypingMode<I> where
I::LocalDefIds: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
{
#[inline]
fn hash_stable(&self, __hcx: &mut __CTX,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
match *self {
TypingMode::Coherence => {}
TypingMode::Analysis {
defining_opaque_types_and_generators: ref __binding_0 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
TypingMode::Borrowck {
defining_opaque_types: ref __binding_0 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: ref __binding_0 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
TypingMode::PostAnalysis => {}
}
}
}
};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.
38Coherence,
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 /// ```
67Analysis { 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.
75Borrowck { 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.
81PostBorrowckAnalysis { 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 hidden 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.
90PostAnalysis,
91}
9293impl<I: Interner> Eqfor TypingMode<I> {}
9495impl<I: Interner> TypingMode<I> {
96/// Analysis outside of a body does not define any opaque types.
97pub fn non_body_analysis() -> TypingMode<I> {
98 TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
99 }
100101pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
102 TypingMode::Analysis {
103 defining_opaque_types_and_generators: cx104 .opaque_types_and_coroutines_defined_by(body_def_id),
105 }
106 }
107108/// 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.
113pub 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 }
118119pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
120let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
121if defining_opaque_types.is_empty() {
122TypingMode::non_body_analysis()
123 } else {
124 TypingMode::Borrowck { defining_opaque_types }
125 }
126 }
127128pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
129let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
130if defined_opaque_types.is_empty() {
131TypingMode::non_body_analysis()
132 } else {
133 TypingMode::PostBorrowckAnalysis { defined_opaque_types }
134 }
135 }
136}
137138#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
139pub trait InferCtxtLike: Sized {
140type Interner: Interner;
141fn cx(&self) -> Self::Interner;
142143/// 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.
147fn next_trait_solver(&self) -> bool {
148true
149}
150151fn typing_mode(&self) -> TypingMode<Self::Interner>;
152153fn universe(&self) -> ty::UniverseIndex;
154fn create_next_universe(&self) -> ty::UniverseIndex;
155156fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
157fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
158fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
159160fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
161fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
162fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
163164fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
165fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
166fn opportunistic_resolve_float_var(
167&self,
168 vid: ty::FloatVid,
169 ) -> <Self::Interner as Interner>::Ty;
170fn opportunistic_resolve_ct_var(
171&self,
172 vid: ty::ConstVid,
173 ) -> <Self::Interner as Interner>::Const;
174fn opportunistic_resolve_lt_var(
175&self,
176 vid: ty::RegionVid,
177 ) -> <Self::Interner as Interner>::Region;
178179fn is_changed_arg(&self, arg: <Self::Interner as Interner>::GenericArg) -> bool;
180181fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
182fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
183fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
184fn fresh_args_for_item(
185&self,
186 def_id: <Self::Interner as Interner>::DefId,
187 ) -> <Self::Interner as Interner>::GenericArgs;
188189fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
190&self,
191 value: ty::Binder<Self::Interner, T>,
192 ) -> T;
193194fn enter_forall<T: TypeFoldable<Self::Interner>, U>(
195&self,
196 value: ty::Binder<Self::Interner, T>,
197 f: impl FnOnce(T) -> U,
198 ) -> U;
199200fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
201fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
202fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
203fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
204fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
205206fn 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, ()>;
214fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
215fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
216fn 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, ()>;
223224fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
225226fn shallow_resolve(
227&self,
228 ty: <Self::Interner as Interner>::Ty,
229 ) -> <Self::Interner as Interner>::Ty;
230fn shallow_resolve_const(
231&self,
232 ty: <Self::Interner as Interner>::Const,
233 ) -> <Self::Interner as Interner>::Const;
234235fn resolve_vars_if_possible<T>(&self, value: T) -> T
236where
237T: TypeFoldable<Self::Interner>;
238239fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
240241fn 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 );
247248fn 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 );
254255fn 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 );
261262type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
263fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
264fn clone_opaque_types_lookup_table(
265&self,
266 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
267fn clone_duplicate_opaque_types(
268&self,
269 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
270fn clone_opaque_types_added_since(
271&self,
272 prev_entries: Self::OpaqueTypeStorageEntries,
273 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
274fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec<ty::AliasTy<Self::Interner>>;
275276fn register_hidden_type_in_storage(
277&self,
278 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
279 hidden_ty: <Self::Interner as Interner>::Ty,
280 span: <Self::Interner as Interner>::Span,
281 ) -> Option<<Self::Interner as Interner>::Ty>;
282fn add_duplicate_opaque_type(
283&self,
284 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
285 hidden_ty: <Self::Interner as Interner>::Ty,
286 span: <Self::Interner as Interner>::Span,
287 );
288289fn reset_opaque_types(&self);
290}
291292pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
293 infcx: &'a Infcx,
294 param_env: I::ParamEnv,
295 symbol: I::Symbol,
296) -> bool297where
298Infcx: InferCtxtLike<Interner = I>,
299{
300// Iterate through all goals in param_env to find the one that has the same symbol.
301for pred in param_env.caller_bounds().iter() {
302if let ty::ClauseKind::UnstableFeature(sym) = pred.kind().skip_binder() {
303if sym == symbol {
304return true;
305 }
306 }
307 }
308309// During codegen we must assume that all feature bounds hold as we may be
310 // monomorphizing a body from an upstream crate which had an unstable feature
311 // enabled that we do not.
312 //
313 // Coherence should already report overlap errors involving unstable impls
314 // as the affected code would otherwise break when stabilizing this feature.
315 // It is also easily possible to accidentally cause unsoundness this way as
316 // we have to always enable unstable impls during codegen.
317 //
318 // Return ambiguity can also prevent people from writing code which depends on inference guidance
319 // that might no longer work after the impl is stabilised,
320 // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
321 //
322 // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
323 // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
324325(infcx.typing_mode() == TypingMode::PostAnalysis)
326 || infcx.cx().features().feature_bound_holds_in_crate(symbol)
327}