1use core::fmt;
2use std::hash::{Hash, Hasher};
34use derive_where::derive_where;
5#[cfg(feature = "nightly")]
6use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext};
78use crate::fold::TypeFoldable;
9use crate::inherent::*;
10use crate::relate::RelateResult;
11use crate::relate::combine::PredicateEmittingRelation;
12use crate::solve::VisibleForLeakCheck;
13use crate::{selfas ty, Interner, TyVid};
1415mod private {
16pub trait Sealed {}
1718impl Sealedfor super::CantBeErased {}
19impl Sealedfor super::MayBeErased {}
20}
21pub trait TypingModeErasedStatus: private::Sealed + Clone + Copy + Hash + fmt::Debug {}
2223#[derive(#[automatically_derived]
impl ::core::clone::Clone for CantBeErased {
#[inline]
fn clone(&self) -> CantBeErased { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CantBeErased { }Copy, #[automatically_derived]
impl ::core::hash::Hash for CantBeErased {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
match *self {}
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CantBeErased {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {}
}
}Debug)]
24pub enum CantBeErased {}
25#[derive(#[automatically_derived]
impl ::core::clone::Clone for MayBeErased {
#[inline]
fn clone(&self) -> MayBeErased { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MayBeErased { }Copy, #[automatically_derived]
impl ::core::hash::Hash for MayBeErased {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for MayBeErased {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "MayBeErased")
}
}Debug)]
26#[cfg_attr(
27 feature = "nightly",
28 derive(const _: () =
{
impl<__E: ::rustc_serialize::Encoder>
::rustc_serialize::Encodable<__E> for MayBeErased {
fn encode(&self, __encoder: &mut __E) {
match *self { MayBeErased => {} }
}
}
};Encodable_NoContext, const _: () =
{
impl<__D: ::rustc_serialize::Decoder>
::rustc_serialize::Decodable<__D> for MayBeErased {
fn decode(__decoder: &mut __D) -> Self { MayBeErased }
}
};Decodable_NoContext, const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for MayBeErased
{
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self { MayBeErased => {} }
}
}
};StableHash_NoContext)
29)]
30pub struct MayBeErased;
3132impl TypingModeErasedStatusfor CantBeErased {}
33impl TypingModeErasedStatusfor MayBeErased {}
3435/// The current typing mode of an inference context. We unfortunately have some
36/// slightly different typing rules depending on the current context. See the
37/// doc comment for each variant for how and why they are used.
38///
39/// In most cases you can get the correct typing mode automatically via:
40/// - `mir::Body::typing_mode`
41/// - `rustc_lint::LateContext::typing_mode`
42///
43/// If neither of these functions are available, feel free to reach out to
44/// t-types for help.
45///
46/// Because typing rules get subtly different based on what typing mode we're in,
47/// subtle enough that changing the behavior of typing modes can sometimes cause
48/// changes that we don't even have tests for, we'd like to enforce the rule that
49/// any place where we specialize behavior based on the typing mode, we match
50/// *exhaustively* on the typing mode. That way, it's easy to determine all the
51/// places that must change when anything about typing modes changes.
52///
53/// Hence, `TypingMode` does not implement `Eq`, though [`TypingModeEqWrapper`] is available
54/// in the rare case that you do need this. Most cases where this currently matters is
55/// where we pass typing modes through the query system and want to cache based on it.
56/// See also `#[rustc_must_match_exhaustively]`, which tries to detect non-exhaustive
57/// matches.
58///
59/// Since matching on typing mode to single out `Coherence` is so common, and `Coherence`
60/// is so different from the other modes: see also [`is_coherence`](TypingMode::is_coherence)
61#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::fmt::Debug for
TypingMode<I, S> 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::Typeck {
defining_opaque_types_and_generators: ref __field_defining_opaque_types_and_generators
} => {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f, "Typeck");
::core::fmt::DebugStruct::field(&mut __builder,
"defining_opaque_types_and_generators",
__field_defining_opaque_types_and_generators);
::core::fmt::DebugStruct::finish(&mut __builder)
}
TypingMode::PostTypeckUntilBorrowck {
defining_opaque_types: ref __field_defining_opaque_types } =>
{
let mut __builder =
::core::fmt::Formatter::debug_struct(__f,
"PostTypeckUntilBorrowck");
::core::fmt::DebugStruct::field(&mut __builder,
"defining_opaque_types", __field_defining_opaque_types);
::core::fmt::DebugStruct::finish(&mut __builder)
}
TypingMode::PostBorrowck {
defined_opaque_types: ref __field_defined_opaque_types } => {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f, "PostBorrowck");
::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"),
TypingMode::Codegen =>
::core::fmt::Formatter::write_str(__f, "Codegen"),
TypingMode::ErasedNotCoherence(ref __field_0) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f,
"ErasedNotCoherence");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::finish(&mut __builder)
}
}
}
}#[derive_where(Clone, Copy, Hash, Debug; I: Interner)]62#[cfg_attr(
63 feature = "nightly",
64 derive(const _: () =
{
impl<I: Interner, S: TypingModeErasedStatus,
__E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<__E>
for TypingMode<I, S> where
I::LocalDefIds: ::rustc_serialize::Encodable<__E>,
S: ::rustc_serialize::Encodable<__E> {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
TypingMode::Coherence => { 0usize }
TypingMode::Typeck {
defining_opaque_types_and_generators: ref __binding_0 } => {
1usize
}
TypingMode::PostTypeckUntilBorrowck {
defining_opaque_types: ref __binding_0 } => {
2usize
}
TypingMode::PostBorrowck {
defined_opaque_types: ref __binding_0 } => {
3usize
}
TypingMode::PostAnalysis => { 4usize }
TypingMode::Codegen => { 5usize }
TypingMode::ErasedNotCoherence(ref __binding_0) => {
6usize
}
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
TypingMode::Coherence => {}
TypingMode::Typeck {
defining_opaque_types_and_generators: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
TypingMode::PostTypeckUntilBorrowck {
defining_opaque_types: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
TypingMode::PostBorrowck {
defined_opaque_types: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
TypingMode::PostAnalysis => {}
TypingMode::Codegen => {}
TypingMode::ErasedNotCoherence(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable_NoContext, const _: () =
{
impl<I: Interner, S: TypingModeErasedStatus,
__D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<__D>
for TypingMode<I, S> where
I::LocalDefIds: ::rustc_serialize::Decodable<__D>,
S: ::rustc_serialize::Decodable<__D> {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { TypingMode::Coherence }
1usize => {
TypingMode::Typeck {
defining_opaque_types_and_generators: ::rustc_serialize::Decodable::decode(__decoder),
}
}
2usize => {
TypingMode::PostTypeckUntilBorrowck {
defining_opaque_types: ::rustc_serialize::Decodable::decode(__decoder),
}
}
3usize => {
TypingMode::PostBorrowck {
defined_opaque_types: ::rustc_serialize::Decodable::decode(__decoder),
}
}
4usize => { TypingMode::PostAnalysis }
5usize => { TypingMode::Codegen }
6usize => {
TypingMode::ErasedNotCoherence(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `TypingMode`, expected 0..7, actual {0}",
n));
}
}
}
}
};Decodable_NoContext, const _: () =
{
impl<I: Interner, S: TypingModeErasedStatus>
::rustc_data_structures::stable_hash::StableHash for
TypingMode<I, S> where
I::LocalDefIds: ::rustc_data_structures::stable_hash::StableHash,
S: ::rustc_data_structures::stable_hash::StableHash {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
TypingMode::Coherence => {}
TypingMode::Typeck {
defining_opaque_types_and_generators: ref __binding_0 } => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
TypingMode::PostTypeckUntilBorrowck {
defining_opaque_types: ref __binding_0 } => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
TypingMode::PostBorrowck {
defined_opaque_types: ref __binding_0 } => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
TypingMode::PostAnalysis => {}
TypingMode::Codegen => {}
TypingMode::ErasedNotCoherence(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash_NoContext)
65)]
66#[cfg_attr(feature = "nightly", rustc_must_match_exhaustively)]
67pub enum TypingMode<I: Interner, S: TypingModeErasedStatus = MayBeErased> {
68/// When checking whether impls overlap, we check whether any obligations
69 /// are guaranteed to never hold when unifying the impls. This requires us
70 /// to be complete: we must never fail to prove something which may actually
71 /// hold.
72 ///
73 /// In this typing mode we bail with ambiguity in case its not knowable
74 /// whether a trait goal may hold, e.g. because the trait may get implemented
75 /// in a downstream or sibling crate.
76 ///
77 /// We also have to be careful when generalizing aliases inside of higher-ranked
78 /// types to not unnecessarily constrain any inference variables.
79Coherence,
80/// Typeck is the typing mode mainly used in `rustc_hir_typeck` and related crate.
81 /// It includes type inference, checking that items are well-formed, and
82 /// pretty much everything else which may emit proper type errors to the user.
83 ///
84 /// We only normalize opaque types which may get defined by the current body,
85 /// which are stored in `defining_opaque_types`.
86 ///
87 /// We also refuse to project any associated type that is marked `default`.
88 /// Non-`default` ("final") types are always projected. This is necessary in
89 /// general for soundness of specialization. However, we *could* allow projections
90 /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
91 /// to force the type definition to be treated abstractly by any consumers of the
92 /// impl. Concretely, that means that the following example will
93 /// fail to compile:
94 ///
95 /// ```compile_fail,E0308
96 /// #![feature(specialization)]
97 /// trait Assoc {
98 /// type Output;
99 /// }
100 ///
101 /// impl<T> Assoc for T {
102 /// default type Output = bool;
103 /// }
104 ///
105 /// fn main() {
106 /// let x: <() as Assoc>::Output = true;
107 /// }
108 /// ```
109Typeck { defining_opaque_types_and_generators: I::LocalDefIds },
110/// `PostTypeckUntilBorrowck` is used after `Typeck` has finished, up to and including borrowck,
111 /// for anything that accesses typeck results. This is the behavior that's used mainly in borrowck,
112 /// but, for example, also in late lints and other analyses while building MIR. The behavior of
113 /// `PostTypeckUntilBorrowck` is identical to `TypingMode::Typeck` except that the initial value for
114 /// opaque types is the type computed during HIR typeck with unique unconstrained region inference variables.
115 ///
116 /// This is currently only used by the new solver as it results in new
117 /// non-universal defining uses of opaque types, which is a breaking change.
118 /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
119PostTypeckUntilBorrowck { defining_opaque_types: I::LocalDefIds },
120/// Any analysis after borrowck for a given body should be able to use all the
121 /// hidden types defined by borrowck, without being able to define any new ones.
122 ///
123 /// This is currently only used by the new solver, but should be implemented in
124 /// the old solver as well.
125PostBorrowck { defined_opaque_types: I::LocalDefIds },
126/// After analysis, mostly during MIR optimizations, we're able to
127 /// reveal all opaque types. As the hidden type should *never* be observable
128 /// directly by the user, this should not be used by checks which may expose
129 /// such details to the user.
130 ///
131 /// However, we restrict `layout_of` and const-evaluation from exposing some information like
132 /// coroutine layout which requires optimized MIR.
133PostAnalysis,
134135/// During codegen and MIR optimizations, we're able to reveal all opaque types and compute all
136 /// layouts.
137Codegen,
138139/// The typing modes above (except coherence) only differ in how they handle
140 ///
141 /// - Generators
142 /// - Opaque types
143 /// - Specialization (in `PostAnalysis`)
144 ///
145 /// We replace all of them with this `TypingMode` in the first attempt at canonicalization.
146 /// If, during that attempt, we try to access information about opaques or generators
147 /// we bail out, setting a field on `EvalCtxt` that indicates the canonicalization must be
148 /// rerun in the original typing mode.
149 ///
150 /// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
151ErasedNotCoherence(S),
152}
153154/// We want to highly discourage using equality checks on typing modes.
155/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
156/// error. Only use `TypingModeEqWrapper` when you really really really have to.
157/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
158/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
159#[automatically_derived]
impl<I: Interner> ::core::fmt::Debug for TypingModeEqWrapper<I> where
I: Interner {
fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
match self {
TypingModeEqWrapper(ref __field_0) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f,
"TypingModeEqWrapper");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::finish(&mut __builder)
}
}
}
}#[derive_where(Clone, Copy, Debug; I: Interner)]160#[cfg_attr(
161 feature = "nightly",
162 derive(const _: () =
{
impl<I: Interner, __E: ::rustc_serialize::Encoder>
::rustc_serialize::Encodable<__E> for TypingModeEqWrapper<I> where
TypingMode<I, MayBeErased>: ::rustc_serialize::Encodable<__E> {
fn encode(&self, __encoder: &mut __E) {
match *self {
TypingModeEqWrapper(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};Encodable_NoContext, const _: () =
{
impl<I: Interner, __D: ::rustc_serialize::Decoder>
::rustc_serialize::Decodable<__D> for TypingModeEqWrapper<I> where
TypingMode<I, MayBeErased>: ::rustc_serialize::Decodable<__D> {
fn decode(__decoder: &mut __D) -> Self {
TypingModeEqWrapper(::rustc_serialize::Decodable::decode(__decoder))
}
}
};Decodable_NoContext, const _: () =
{
impl<I: Interner> ::rustc_data_structures::stable_hash::StableHash for
TypingModeEqWrapper<I> where
TypingMode<I,
MayBeErased>: ::rustc_data_structures::stable_hash::StableHash {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
TypingModeEqWrapper(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash_NoContext)
163)]
164pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
165166impl<I: Interner> Hashfor TypingModeEqWrapper<I> {
167fn hash<H: Hasher>(&self, state: &mut H) {
168self.0.hash(state);
169 }
170}
171172impl<I: Interner> PartialEqfor TypingModeEqWrapper<I> {
173fn eq(&self, other: &Self) -> bool {
174match (self.0, other.0) {
175 (TypingMode::Coherence, TypingMode::Coherence) => true,
176 (
177 TypingMode::Typeck { defining_opaque_types_and_generators: l },
178 TypingMode::Typeck { defining_opaque_types_and_generators: r },
179 ) => l == r,
180 (
181 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: l },
182 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: r },
183 ) => l == r,
184 (
185 TypingMode::PostBorrowck { defined_opaque_types: l },
186 TypingMode::PostBorrowck { defined_opaque_types: r },
187 ) => l == r,
188 (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
189 (TypingMode::Codegen, TypingMode::Codegen) => true,
190 (
191 TypingMode::ErasedNotCoherence(MayBeErased),
192 TypingMode::ErasedNotCoherence(MayBeErased),
193 ) => true,
194 (
195 TypingMode::Coherence196 | TypingMode::Typeck { .. }
197 | TypingMode::PostTypeckUntilBorrowck { .. }
198 | TypingMode::PostBorrowck { .. }
199 | TypingMode::PostAnalysis200 | TypingMode::Codegen201 | TypingMode::ErasedNotCoherence(MayBeErased),
202_,
203 ) => false,
204 }
205 }
206}
207208impl<I: Interner> Eqfor TypingModeEqWrapper<I> {}
209210impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
211/// There are a bunch of places in the compiler where we single out `Coherence`,
212 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
213 /// but not having this method leads to a bunch of noisy code.
214 ///
215 /// See also the documentation on [`TypingMode`] about exhaustive matching.
216pub fn is_coherence(&self) -> bool {
217match self {
218 TypingMode::Coherence => true,
219 TypingMode::Typeck { .. }
220 | TypingMode::PostTypeckUntilBorrowck { .. }
221 | TypingMode::PostBorrowck { .. }
222 | TypingMode::PostAnalysis223 | TypingMode::Codegen224 | TypingMode::ErasedNotCoherence(_) => false,
225 }
226 }
227228/// There are a bunch of places in the trait solver where we single out `Coherence`,
229 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
230 /// but not having this method leads to a bunch of noisy code.
231 ///
232 /// See also the documentation on [`TypingMode`] about exhaustive matching.
233pub fn is_erased_not_coherence(&self) -> bool {
234match self {
235 TypingMode::ErasedNotCoherence(_) => true,
236 TypingMode::Coherence237 | TypingMode::Typeck { .. }
238 | TypingMode::PostTypeckUntilBorrowck { .. }
239 | TypingMode::PostBorrowck { .. }
240 | TypingMode::PostAnalysis241 | TypingMode::Codegen => false,
242 }
243 }
244}
245246impl<I: Interner> TypingMode<I, MayBeErased> {
247/// Only call this when you're sure you're outside the next trait solver!
248 /// That means either not in the trait solver, or in code that is old-solver only.
249 ///
250 /// See the comment on `InferCtxt::typing_mode_raw`
251pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
252match self {
253 TypingMode::Coherence => TypingMode::Coherence,
254 TypingMode::Typeck { defining_opaque_types_and_generators } => {
255 TypingMode::Typeck { defining_opaque_types_and_generators }
256 }
257 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
258 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
259 }
260 TypingMode::PostBorrowck { defined_opaque_types } => {
261 TypingMode::PostBorrowck { defined_opaque_types }
262 }
263 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
264 TypingMode::Codegen => TypingMode::Codegen,
265 TypingMode::ErasedNotCoherence(MayBeErased) => {
::core::panicking::panic_fmt(format_args!("Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible"));
}panic!(
266"Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible"
267),
268 }
269 }
270}
271272impl<I: Interner> TypingMode<I, CantBeErased> {
273/// Analysis outside of a body does not define any opaque types.
274pub fn non_body_analysis() -> TypingMode<I> {
275 TypingMode::Typeck { defining_opaque_types_and_generators: Default::default() }
276 }
277278pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
279 TypingMode::Typeck {
280 defining_opaque_types_and_generators: cx281 .opaque_types_and_coroutines_defined_by(body_def_id),
282 }
283 }
284285/// While typechecking a body, we need to be able to define the opaque
286 /// types defined by that body.
287 ///
288 /// FIXME: This will be removed because it's generally not correct to define
289 /// opaques outside of HIR typeck.
290pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
291 TypingMode::Typeck {
292 defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
293 }
294 }
295296pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
297let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
298if defining_opaque_types.is_empty() {
299TypingMode::non_body_analysis()
300 } else {
301 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
302 }
303 }
304305pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
306let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
307if defined_opaque_types.is_empty() {
308TypingMode::non_body_analysis()
309 } else {
310 TypingMode::PostBorrowck { defined_opaque_types }
311 }
312 }
313}
314315impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
316fn from(value: TypingMode<I, CantBeErased>) -> Self {
317match value {
318 TypingMode::Coherence => TypingMode::Coherence,
319 TypingMode::Typeck { defining_opaque_types_and_generators } => {
320 TypingMode::Typeck { defining_opaque_types_and_generators }
321 }
322 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
323 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
324 }
325 TypingMode::PostBorrowck { defined_opaque_types } => {
326 TypingMode::PostBorrowck { defined_opaque_types }
327 }
328 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
329 TypingMode::Codegen => TypingMode::Codegen,
330 }
331 }
332}
333334#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
335pub trait InferCtxtLike: Sized {
336type Interner: Interner;
337fn cx(&self) -> Self::Interner;
338339/// Whether the new trait solver is enabled. This only exists because rustc
340 /// shares code between the new and old trait solvers; for all other users,
341 /// this should always be true. If this is unknowingly false and you try to
342 /// use the new trait solver, things will break badly.
343fn next_trait_solver(&self) -> bool {
344true
345}
346347fn disable_trait_solver_fast_paths(&self) -> bool;
348349fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
350351fn universe(&self) -> ty::UniverseIndex;
352fn create_next_universe(&self) -> ty::UniverseIndex;
353354fn insert_placeholder_assumptions(
355&self,
356 u: ty::UniverseIndex,
357 assumptions: Option<crate::region_constraint::Assumptions<Self::Interner>>,
358 );
359fn get_placeholder_assumptions(
360&self,
361 u: ty::UniverseIndex,
362 ) -> Option<crate::region_constraint::Assumptions<Self::Interner>>;
363fn get_solver_region_constraint(
364&self,
365 ) -> crate::region_constraint::RegionConstraint<Self::Interner>;
366fn overwrite_solver_region_constraint(
367&self,
368 constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
369 );
370371fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
372fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
373fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
374375fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
376fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
377fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
378379fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
380fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
381fn opportunistic_resolve_float_var(
382&self,
383 vid: ty::FloatVid,
384 ) -> <Self::Interner as Interner>::Ty;
385fn opportunistic_resolve_ct_var(
386&self,
387 vid: ty::ConstVid,
388 ) -> <Self::Interner as Interner>::Const;
389fn opportunistic_resolve_lt_var(
390&self,
391 vid: ty::RegionVid,
392 ) -> <Self::Interner as Interner>::Region;
393394fn is_changed_arg(&self, arg: <Self::Interner as Interner>::GenericArg) -> bool;
395396fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
397fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
398fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
399fn fresh_args_for_item(
400&self,
401 def_id: <Self::Interner as Interner>::DefId,
402 ) -> <Self::Interner as Interner>::GenericArgs;
403404fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
405&self,
406 value: ty::Binder<Self::Interner, T>,
407 ) -> T;
408409fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
410&self,
411 value: ty::Binder<Self::Interner, T>,
412 f: impl FnOnce(T) -> U,
413 ) -> U;
414415/// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
416 /// and should be replaced in the long term by actually taking assumptions into
417 /// account.
418fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
419&self,
420 value: ty::Binder<Self::Interner, T>,
421 f: impl FnOnce(T) -> U,
422 ) -> U;
423424fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
425fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
426fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
427fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
428fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
429430fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
431&self,
432 relation: &mut R,
433 target_is_expected: bool,
434 target_vid: ty::TyVid,
435 instantiation_variance: ty::Variance,
436 source_ty: <Self::Interner as Interner>::Ty,
437 ) -> RelateResult<Self::Interner, ()>;
438fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
439fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
440fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
441&self,
442 relation: &mut R,
443 target_is_expected: bool,
444 target_vid: ty::ConstVid,
445 source_ct: <Self::Interner as Interner>::Const,
446 ) -> RelateResult<Self::Interner, ()>;
447448fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
449450fn shallow_resolve(
451&self,
452 ty: <Self::Interner as Interner>::Ty,
453 ) -> <Self::Interner as Interner>::Ty;
454fn shallow_resolve_const(
455&self,
456 ty: <Self::Interner as Interner>::Const,
457 ) -> <Self::Interner as Interner>::Const;
458459fn resolve_vars_if_possible<T>(&self, value: T) -> T
460where
461T: TypeFoldable<Self::Interner>;
462463fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
464465fn sub_regions(
466&self,
467 sub: <Self::Interner as Interner>::Region,
468 sup: <Self::Interner as Interner>::Region,
469 vis: VisibleForLeakCheck,
470 span: <Self::Interner as Interner>::Span,
471 );
472473fn equate_regions(
474&self,
475 a: <Self::Interner as Interner>::Region,
476 b: <Self::Interner as Interner>::Region,
477 vis: VisibleForLeakCheck,
478 span: <Self::Interner as Interner>::Span,
479 );
480481fn register_solver_region_constraint(
482&self,
483 c: crate::region_constraint::RegionConstraint<Self::Interner>,
484 );
485486fn register_ty_outlives(
487&self,
488 ty: <Self::Interner as Interner>::Ty,
489 r: <Self::Interner as Interner>::Region,
490 span: <Self::Interner as Interner>::Span,
491 );
492493type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
494fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
495fn clone_opaque_types_lookup_table(
496&self,
497 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
498fn clone_duplicate_opaque_types(
499&self,
500 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
501fn clone_opaque_types_added_since(
502&self,
503 prev_entries: Self::OpaqueTypeStorageEntries,
504 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
505fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec<ty::AliasTy<Self::Interner>>;
506507fn register_hidden_type_in_storage(
508&self,
509 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
510 hidden_ty: <Self::Interner as Interner>::Ty,
511 span: <Self::Interner as Interner>::Span,
512 ) -> Option<<Self::Interner as Interner>::Ty>;
513fn add_duplicate_opaque_type(
514&self,
515 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
516 hidden_ty: <Self::Interner as Interner>::Ty,
517 span: <Self::Interner as Interner>::Span,
518 );
519520fn reset_opaque_types(&self);
521}
522523pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
524 infcx: &'a Infcx,
525 param_env: I::ParamEnv,
526 symbol: I::Symbol,
527) -> bool528where
529Infcx: InferCtxtLike<Interner = I>,
530{
531// Iterate through all goals in param_env to find the one that has the same symbol.
532for pred in param_env.caller_bounds().iter() {
533if let ty::ClauseKind::UnstableFeature(sym) = pred.kind().skip_binder() {
534if sym == symbol {
535return true;
536 }
537 }
538 }
539540// During codegen we must assume that all feature bounds hold as we may be
541 // monomorphizing a body from an upstream crate which had an unstable feature
542 // enabled that we do not.
543 //
544 // Coherence should already report overlap errors involving unstable impls
545 // as the affected code would otherwise break when stabilizing this feature.
546 // It is also easily possible to accidentally cause unsoundness this way as
547 // we have to always enable unstable impls during codegen.
548 //
549 // Return ambiguity can also prevent people from writing code which depends on inference guidance
550 // that might no longer work after the impl is stabilised,
551 // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
552 //
553 // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
554 // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
555556match infcx.typing_mode_raw().assert_not_erased() {
557 TypingMode::Coherence558 | TypingMode::Typeck { .. }
559 | TypingMode::PostTypeckUntilBorrowck { .. }
560 | TypingMode::PostBorrowck { .. }
561 | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol),
562 TypingMode::Codegen => true,
563 }
564}