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::data_structures::DelayedMap;
9use crate::inherent::*;
10use crate::relate::RelateResult;
11use crate::relate::combine::PredicateEmittingRelation;
12use crate::solve::VisibleForLeakCheck;
13use crate::{
14selfas ty, Interner, Region, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable,
15TypeVisitableExt,
16};
1718mod private {
19pub trait Sealed {}
2021impl Sealedfor super::CantBeErased {}
22impl Sealedfor super::MayBeErased {}
23}
24pub trait TypingModeErasedStatus: private::Sealed + Clone + Copy + Hash + fmt::Debug {}
2526#[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)]
27pub enum CantBeErased {}
28#[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)]
29#[cfg_attr(
30 feature = "nightly",
31 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)
32)]
33pub struct MayBeErased;
3435impl TypingModeErasedStatusfor CantBeErased {}
36impl TypingModeErasedStatusfor MayBeErased {}
3738/// The current typing mode of an inference context. We unfortunately have some
39/// slightly different typing rules depending on the current context. See the
40/// doc comment for each variant for how and why they are used.
41///
42/// In most cases you can get the correct typing mode automatically via:
43/// - `mir::Body::typing_mode`
44/// - `rustc_lint::LateContext::typing_mode`
45///
46/// If neither of these functions are available, feel free to reach out to
47/// t-types for help.
48///
49/// Because typing rules get subtly different based on what typing mode we're in,
50/// subtle enough that changing the behavior of typing modes can sometimes cause
51/// changes that we don't even have tests for, we'd like to enforce the rule that
52/// any place where we specialize behavior based on the typing mode, we match
53/// *exhaustively* on the typing mode. That way, it's easy to determine all the
54/// places that must change when anything about typing modes changes.
55///
56/// Hence, `TypingMode` does not implement `Eq`, though [`TypingModeEqWrapper`] is available
57/// in the rare case that you do need this. Most cases where this currently matters is
58/// where we pass typing modes through the query system and want to cache based on it.
59/// See also `#[rustc_must_match_exhaustively]`, which tries to detect non-exhaustive
60/// matches.
61///
62/// Since matching on typing mode to single out `Coherence` is so common, and `Coherence`
63/// is so different from the other modes: see also [`is_coherence`](TypingMode::is_coherence)
64#[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::Reflection =>
::core::fmt::Formatter::write_str(__f, "Reflection"),
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)]65#[cfg_attr(
66 feature = "nightly",
67 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::Reflection => { 4usize }
TypingMode::PostAnalysis => { 5usize }
TypingMode::Codegen => { 6usize }
TypingMode::ErasedNotCoherence(ref __binding_0) => {
7usize
}
};
::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::Reflection => {}
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::Reflection }
5usize => { TypingMode::PostAnalysis }
6usize => { TypingMode::Codegen }
7usize => {
TypingMode::ErasedNotCoherence(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `TypingMode`, expected 0..8, 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::Reflection => {}
TypingMode::PostAnalysis => {}
TypingMode::Codegen => {}
TypingMode::ErasedNotCoherence(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash_NoContext)
68)]
69#[cfg_attr(feature = "nightly", rustc_must_match_exhaustively)]
70pub enum TypingMode<I: Interner, S: TypingModeErasedStatus = MayBeErased> {
71/// When checking whether impls overlap, we check whether any obligations
72 /// are guaranteed to never hold when unifying the impls. This requires us
73 /// to be complete: we must never fail to prove something which may actually
74 /// hold.
75 ///
76 /// In this typing mode we bail with ambiguity in case its not knowable
77 /// whether a trait goal may hold, e.g. because the trait may get implemented
78 /// in a downstream or sibling crate.
79 ///
80 /// We also have to be careful when generalizing aliases inside of higher-ranked
81 /// types to not unnecessarily constrain any inference variables.
82Coherence,
83/// Typeck is the typing mode mainly used in `rustc_hir_typeck` and related crate.
84 /// It includes type inference, checking that items are well-formed, and
85 /// pretty much everything else which may emit proper type errors to the user.
86 ///
87 /// We only normalize opaque types which may get defined by the current body,
88 /// which are stored in `defining_opaque_types`.
89 ///
90 /// We also refuse to project any associated type that is marked `default`.
91 /// Non-`default` ("final") types are always projected. This is necessary in
92 /// general for soundness of specialization. However, we *could* allow projections
93 /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
94 /// to force the type definition to be treated abstractly by any consumers of the
95 /// impl. Concretely, that means that the following example will
96 /// fail to compile:
97 ///
98 /// ```compile_fail,E0308
99 /// #![feature(specialization)]
100 /// trait Assoc {
101 /// type Output;
102 /// }
103 ///
104 /// impl<T> Assoc for T {
105 /// default type Output = bool;
106 /// }
107 ///
108 /// fn main() {
109 /// let x: <() as Assoc>::Output = true;
110 /// }
111 /// ```
112Typeck { defining_opaque_types_and_generators: I::LocalDefIds },
113/// `PostTypeckUntilBorrowck` is used after `Typeck` has finished, up to and including borrowck,
114 /// for anything that accesses typeck results. This is the behavior that's used mainly in borrowck,
115 /// but, for example, also in late lints and other analyses while building MIR. The behavior of
116 /// `PostTypeckUntilBorrowck` is identical to `TypingMode::Typeck` except that the initial value for
117 /// opaque types is the type computed during HIR typeck with unique unconstrained region inference variables.
118 ///
119 /// This is currently only used by the new solver as it results in new
120 /// non-universal defining uses of opaque types, which is a breaking change.
121 /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
122PostTypeckUntilBorrowck { defining_opaque_types: I::LocalDefIds },
123/// Any analysis after borrowck for a given body should be able to use all the
124 /// hidden types defined by borrowck, without being able to define any new ones.
125 ///
126 /// This is currently only used by the new solver, but should be implemented in
127 /// the old solver as well.
128PostBorrowck { defined_opaque_types: I::LocalDefIds },
129/// During the evaluation of reflection logic that ignores lifetimes, we can only
130 /// handle impls that are fully generic over all lifetimes without constraints on
131 /// those lifetimes (other than implied bounds).
132Reflection,
133/// After analysis, mostly during MIR optimizations, we're able to
134 /// reveal all opaque types. As the hidden type should *never* be observable
135 /// directly by the user, this should not be used by checks which may expose
136 /// such details to the user.
137 ///
138 /// However, we restrict `layout_of` and const-evaluation from exposing some information like
139 /// coroutine layout which requires optimized MIR.
140PostAnalysis,
141142/// During codegen and MIR optimizations, we're able to reveal all opaque types and compute all
143 /// layouts.
144Codegen,
145146/// The typing modes above (except coherence) only differ in how they handle
147 ///
148 /// - Generators
149 /// - Opaque types
150 /// - Specialization (in `PostAnalysis`)
151 ///
152 /// We replace all of them with this `TypingMode` in the first attempt at canonicalization.
153 /// If, during that attempt, we try to access information about opaques or generators
154 /// we bail out, setting a field on `EvalCtxt` that indicates the canonicalization must be
155 /// rerun in the original typing mode.
156 ///
157 /// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
158ErasedNotCoherence(S),
159}
160161/// We want to highly discourage using equality checks on typing modes.
162/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
163/// error. Only use `TypingModeEqWrapper` when you really really really have to.
164/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
165/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
166#[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)]167#[cfg_attr(
168 feature = "nightly",
169 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)
170)]
171pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
172173impl<I: Interner> Hashfor TypingModeEqWrapper<I> {
174fn hash<H: Hasher>(&self, state: &mut H) {
175self.0.hash(state);
176 }
177}
178179impl<I: Interner> PartialEqfor TypingModeEqWrapper<I> {
180fn eq(&self, other: &Self) -> bool {
181match (self.0, other.0) {
182 (TypingMode::Coherence, TypingMode::Coherence) => true,
183 (TypingMode::Reflection, TypingMode::Reflection) => true,
184 (
185 TypingMode::Typeck { defining_opaque_types_and_generators: l },
186 TypingMode::Typeck { defining_opaque_types_and_generators: r },
187 ) => l == r,
188 (
189 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: l },
190 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: r },
191 ) => l == r,
192 (
193 TypingMode::PostBorrowck { defined_opaque_types: l },
194 TypingMode::PostBorrowck { defined_opaque_types: r },
195 ) => l == r,
196 (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
197 (TypingMode::Codegen, TypingMode::Codegen) => true,
198 (
199 TypingMode::ErasedNotCoherence(MayBeErased),
200 TypingMode::ErasedNotCoherence(MayBeErased),
201 ) => true,
202 (
203 TypingMode::Coherence204 | TypingMode::Reflection205 | TypingMode::Typeck { .. }
206 | TypingMode::PostTypeckUntilBorrowck { .. }
207 | TypingMode::PostBorrowck { .. }
208 | TypingMode::PostAnalysis209 | TypingMode::Codegen210 | TypingMode::ErasedNotCoherence(MayBeErased),
211_,
212 ) => false,
213 }
214 }
215}
216217impl<I: Interner> Eqfor TypingModeEqWrapper<I> {}
218219impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
220/// There are a bunch of places in the compiler where we single out `Coherence`,
221 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
222 /// but not having this method leads to a bunch of noisy code.
223 ///
224 /// See also the documentation on [`TypingMode`] about exhaustive matching.
225pub fn is_coherence(&self) -> bool {
226match self {
227 TypingMode::Coherence => true,
228 TypingMode::Typeck { .. }
229 | TypingMode::PostTypeckUntilBorrowck { .. }
230 | TypingMode::Reflection231 | TypingMode::PostBorrowck { .. }
232 | TypingMode::PostAnalysis233 | TypingMode::Codegen234 | TypingMode::ErasedNotCoherence(_) => false,
235 }
236 }
237238/// There are a bunch of places in the compiler where we single out `Reflection`,
239 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
240 /// but not having this method leads to a bunch of noisy code.
241 ///
242 /// See also the documentation on [`TypingMode`] about exhaustive matching.
243pub fn is_reflection(&self) -> bool {
244match self {
245 TypingMode::Reflection => true,
246 TypingMode::Typeck { .. }
247 | TypingMode::PostTypeckUntilBorrowck { .. }
248 | TypingMode::Coherence249 | TypingMode::PostBorrowck { .. }
250 | TypingMode::PostAnalysis251 | TypingMode::Codegen252 | TypingMode::ErasedNotCoherence(_) => false,
253 }
254 }
255256/// There are a bunch of places in the trait solver where we single out `Coherence`,
257 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
258 /// but not having this method leads to a bunch of noisy code.
259 ///
260 /// See also the documentation on [`TypingMode`] about exhaustive matching.
261pub fn is_erased_not_coherence(&self) -> bool {
262match self {
263 TypingMode::ErasedNotCoherence(_) => true,
264 TypingMode::Coherence265 | TypingMode::Typeck { .. }
266 | TypingMode::PostTypeckUntilBorrowck { .. }
267 | TypingMode::Reflection268 | TypingMode::PostBorrowck { .. }
269 | TypingMode::PostAnalysis270 | TypingMode::Codegen => false,
271 }
272 }
273}
274275impl<I: Interner> TypingMode<I, MayBeErased> {
276/// Only call this when you're sure you're outside the next trait solver!
277 /// That means either not in the trait solver, or in code that is old-solver only.
278 ///
279 /// See the comment on `InferCtxt::typing_mode_raw`
280pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
281match self {
282 TypingMode::Coherence => TypingMode::Coherence,
283 TypingMode::Typeck { defining_opaque_types_and_generators } => {
284 TypingMode::Typeck { defining_opaque_types_and_generators }
285 }
286 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
287 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
288 }
289 TypingMode::PostBorrowck { defined_opaque_types } => {
290 TypingMode::PostBorrowck { defined_opaque_types }
291 }
292 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
293 TypingMode::Codegen => TypingMode::Codegen,
294 TypingMode::Reflection => TypingMode::Reflection,
295 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!(
296"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"
297),
298 }
299 }
300}
301302impl<I: Interner> TypingMode<I, CantBeErased> {
303/// Analysis outside of a body does not define any opaque types.
304pub fn non_body_analysis() -> TypingMode<I> {
305 TypingMode::Typeck { defining_opaque_types_and_generators: Default::default() }
306 }
307308pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
309 TypingMode::Typeck {
310 defining_opaque_types_and_generators: cx311 .opaque_types_and_coroutines_defined_by(body_def_id),
312 }
313 }
314315/// While typechecking a body, we need to be able to define the opaque
316 /// types defined by that body.
317 ///
318 /// FIXME: This will be removed because it's generally not correct to define
319 /// opaques outside of HIR typeck.
320pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
321 TypingMode::Typeck {
322 defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
323 }
324 }
325326pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
327let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
328if defining_opaque_types.is_empty() {
329TypingMode::non_body_analysis()
330 } else {
331 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
332 }
333 }
334335pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
336let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
337if defined_opaque_types.is_empty() {
338TypingMode::non_body_analysis()
339 } else {
340 TypingMode::PostBorrowck { defined_opaque_types }
341 }
342 }
343}
344345impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
346fn from(value: TypingMode<I, CantBeErased>) -> Self {
347match value {
348 TypingMode::Coherence => TypingMode::Coherence,
349 TypingMode::Typeck { defining_opaque_types_and_generators } => {
350 TypingMode::Typeck { defining_opaque_types_and_generators }
351 }
352 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
353 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
354 }
355 TypingMode::PostBorrowck { defined_opaque_types } => {
356 TypingMode::PostBorrowck { defined_opaque_types }
357 }
358 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
359 TypingMode::Codegen => TypingMode::Codegen,
360 TypingMode::Reflection => TypingMode::Reflection,
361 }
362 }
363}
364365#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
366pub trait InferCtxtLike: Sized {
367type Interner: Interner;
368fn cx(&self) -> Self::Interner;
369370/// Whether the new trait solver is enabled. This only exists because rustc
371 /// shares code between the new and old trait solvers; for all other users,
372 /// this should always be true. If this is unknowingly false and you try to
373 /// use the new trait solver, things will break badly.
374fn next_trait_solver(&self) -> bool {
375true
376}
377378fn enable_next_solver_overflow_fcw(&self) -> bool;
379380fn disable_trait_solver_fast_paths(&self) -> bool;
381382fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
383384fn universe(&self) -> ty::UniverseIndex;
385fn create_next_universe(&self) -> ty::UniverseIndex;
386387fn insert_placeholder_assumptions(
388&self,
389 u: ty::UniverseIndex,
390 assumptions: Option<crate::region_constraint::Assumptions<Self::Interner>>,
391 );
392fn get_placeholder_assumptions(
393&self,
394 u: ty::UniverseIndex,
395 ) -> Option<crate::region_constraint::Assumptions<Self::Interner>>;
396fn get_solver_region_constraint(
397&self,
398 ) -> crate::region_constraint::RegionConstraint<Self::Interner>;
399fn overwrite_solver_region_constraint(
400&self,
401 constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
402 );
403404fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
405fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
406fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
407408fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
409fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
410fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
411412fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
413fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
414fn opportunistic_resolve_float_var(
415&self,
416 vid: ty::FloatVid,
417 ) -> <Self::Interner as Interner>::Ty;
418fn opportunistic_resolve_ct_var(
419&self,
420 vid: ty::ConstVid,
421 ) -> <Self::Interner as Interner>::Const;
422fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> Region<Self::Interner>;
423424fn is_changed_arg(&self, arg: <Self::Interner as Interner>::GenericArg) -> bool;
425426fn next_region_infer(&self) -> Region<Self::Interner>;
427fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
428fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
429fn fresh_args_for_item(
430&self,
431 def_id: <Self::Interner as Interner>::DefId,
432 ) -> <Self::Interner as Interner>::GenericArgs;
433434fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
435&self,
436 value: ty::Binder<Self::Interner, T>,
437 ) -> T;
438439fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
440&self,
441 value: ty::Binder<Self::Interner, T>,
442 f: impl FnOnce(T) -> U,
443 ) -> U;
444445/// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
446 /// and should be replaced in the long term by actually taking assumptions into
447 /// account.
448fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
449&self,
450 value: ty::Binder<Self::Interner, T>,
451 f: impl FnOnce(T) -> U,
452 ) -> U;
453454fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
455fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
456fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
457fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
458fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
459460/// Use `instantiate_ty_var` instead unless you have reasons to skip
461 /// generalization.
462fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: <Self::Interner as Interner>::Ty);
463/// Use `instantiate_const_var` instead unless you have reasons to skip
464 /// generalization.
465fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: <Self::Interner as Interner>::Const);
466fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
467&self,
468 relation: &mut R,
469 target_is_expected: bool,
470 target_vid: ty::TyVid,
471 instantiation_variance: ty::Variance,
472 source_ty: <Self::Interner as Interner>::Ty,
473 ) -> RelateResult<Self::Interner, ()>;
474fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
475fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
476fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
477&self,
478 relation: &mut R,
479 target_is_expected: bool,
480 target_vid: ty::ConstVid,
481 source_ct: <Self::Interner as Interner>::Const,
482 ) -> RelateResult<Self::Interner, ()>;
483484fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
485486fn shallow_resolve(
487&self,
488 ty: <Self::Interner as Interner>::Ty,
489 ) -> <Self::Interner as Interner>::Ty;
490fn shallow_resolve_const(
491&self,
492 ty: <Self::Interner as Interner>::Const,
493 ) -> <Self::Interner as Interner>::Const;
494495fn resolve_vars_if_possible<T>(&self, value: T) -> T
496where
497T: TypeFoldable<Self::Interner>;
498499fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
500501fn commit_if_ok<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E>;
502503fn sub_regions(
504&self,
505 sub: Region<Self::Interner>,
506 sup: Region<Self::Interner>,
507 vis: VisibleForLeakCheck,
508 span: <Self::Interner as Interner>::Span,
509 );
510511fn equate_regions(
512&self,
513 a: Region<Self::Interner>,
514 b: Region<Self::Interner>,
515 vis: VisibleForLeakCheck,
516 span: <Self::Interner as Interner>::Span,
517 );
518519fn register_solver_region_constraint(
520&self,
521 c: crate::region_constraint::RegionConstraint<Self::Interner>,
522 );
523524fn register_ty_outlives(
525&self,
526 ty: <Self::Interner as Interner>::Ty,
527 r: Region<Self::Interner>,
528 span: <Self::Interner as Interner>::Span,
529 );
530531type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
532fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
533fn clone_opaque_types_lookup_table(
534&self,
535 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
536fn clone_duplicate_opaque_types(
537&self,
538 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
539fn clone_opaque_types_added_since(
540&self,
541 prev_entries: Self::OpaqueTypeStorageEntries,
542 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
543fn opaques_with_sub_unified_hidden_type(
544&self,
545 ty: TyVid,
546 ) -> Vec<ty::OpaqueAliasTy<Self::Interner>>;
547548fn register_hidden_type_in_storage(
549&self,
550 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
551 hidden_ty: <Self::Interner as Interner>::Ty,
552 span: <Self::Interner as Interner>::Span,
553 ) -> Option<<Self::Interner as Interner>::Ty>;
554fn add_duplicate_opaque_type(
555&self,
556 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
557 hidden_ty: <Self::Interner as Interner>::Ty,
558 span: <Self::Interner as Interner>::Span,
559 );
560561fn reset_opaque_types(&self);
562}
563564pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
565 infcx: &'a Infcx,
566 param_env: I::ParamEnv,
567 symbol: I::Symbol,
568) -> bool569where
570Infcx: InferCtxtLike<Interner = I>,
571{
572// Iterate through all goals in param_env to find the one that has the same symbol.
573for clause in param_env.caller_bounds().iter() {
574if let ty::ClauseKind::UnstableFeature(sym) = clause.kind().skip_binder() {
575if sym == symbol {
576return true;
577 }
578 }
579 }
580581// During codegen we must assume that all feature bounds hold as we may be
582 // monomorphizing a body from an upstream crate which had an unstable feature
583 // enabled that we do not.
584 //
585 // Coherence should already report overlap errors involving unstable impls
586 // as the affected code would otherwise break when stabilizing this feature.
587 // It is also easily possible to accidentally cause unsoundness this way as
588 // we have to always enable unstable impls during codegen.
589 //
590 // Return ambiguity can also prevent people from writing code which depends on inference guidance
591 // that might no longer work after the impl is stabilised,
592 // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
593 //
594 // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
595 // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
596597match infcx.typing_mode_raw().assert_not_erased() {
598 TypingMode::Coherence599 | TypingMode::Typeck { .. }
600 | TypingMode::PostTypeckUntilBorrowck { .. }
601 | TypingMode::Reflection602 | TypingMode::PostBorrowck { .. }
603 | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol),
604 TypingMode::Codegen => true,
605 }
606}
607608/// Resolves ty, region, and const vars to their inferred values or their root vars.
609pub fn eager_resolve_vars<Infcx: InferCtxtLike, T: TypeFoldable<Infcx::Interner>>(
610 infcx: &Infcx,
611 value: T,
612) -> T {
613if value.has_infer() {
614let mut folder = EagerResolver::new(infcx);
615value.fold_with(&mut folder)
616 } else {
617value618 }
619}
620621struct EagerResolver<'a, D, I = <D as InferCtxtLike>::Interner>
622where
623D: InferCtxtLike<Interner = I>,
624 I: Interner,
625{
626 delegate: &'a D,
627/// We're able to use a cache here as the folder does not have any
628 /// mutable state.
629cache: DelayedMap<I::Ty, I::Ty>,
630}
631632impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> {
633fn new(delegate: &'a Infcx) -> Self {
634EagerResolver { delegate, cache: Default::default() }
635 }
636}
637638impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerResolver<'_, Infcx> {
639fn cx(&self) -> I {
640self.delegate.cx()
641 }
642643fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
644match t.kind() {
645 ty::Infer(ty::TyVar(vid)) => {
646let resolved = self.delegate.opportunistic_resolve_ty_var(vid);
647if t != resolved && resolved.has_infer() {
648resolved.fold_with(self)
649 } else {
650resolved651 }
652 }
653 ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid),
654 ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid),
655_ => {
656if t.has_infer() {
657if let Some(&ty) = self.cache.get(&t) {
658return ty;
659 }
660let res = t.super_fold_with(self);
661if !self.cache.insert(t, res) {
::core::panicking::panic("assertion failed: self.cache.insert(t, res)")
};assert!(self.cache.insert(t, res));
662res663 } else {
664t665 }
666 }
667 }
668 }
669670fn fold_region(&mut self, r: Region<I>) -> Region<I> {
671match r.kind() {
672 ty::ReVar(vid) => self.delegate.opportunistic_resolve_lt_var(vid),
673_ => r,
674 }
675 }
676677fn fold_const(&mut self, c: I::Const) -> I::Const {
678match c.kind() {
679 ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
680let resolved = self.delegate.opportunistic_resolve_ct_var(vid);
681if c != resolved && resolved.has_infer() {
682resolved.fold_with(self)
683 } else {
684resolved685 }
686 }
687_ => {
688if c.has_infer() {
689c.super_fold_with(self)
690 } else {
691c692 }
693 }
694 }
695 }
696697fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
698if p.has_infer() { p.super_fold_with(self) } else { p }
699 }
700701fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
702if c.has_infer() { c.super_fold_with(self) } else { c }
703 }
704}