1use core::fmt;
2use std::hash::{Hash, Hasher};
3use std::range::RangeInclusive;
45use derive_where::derive_where;
6#[cfg(feature = "nightly")]
7use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext};
89use crate::data_structures::DelayedMap;
10use crate::inherent::*;
11use crate::relate::RelateResult;
12use crate::relate::combine::PredicateEmittingRelation;
13use crate::solve::{TyOrConstInferVar, VisibleForLeakCheck};
14use crate::{
15selfas ty, Const, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder,
16TypeSuperFoldable, TypeVisitableExt,
17};
1819mod private {
20pub trait Sealed {}
2122impl Sealedfor super::CantBeErased {}
23impl Sealedfor super::MayBeErased {}
24}
25pub trait TypingModeErasedStatus: private::Sealed + Clone + Copy + Hash + fmt::Debug {}
2627#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for CantBeErased { }
#[automatically_derived]
impl ::core::clone::Clone for CantBeErased {
#[inline]
fn clone(&self) -> Self { *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)]
28pub enum CantBeErased {}
29#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MayBeErased { }
#[automatically_derived]
impl ::core::clone::Clone for MayBeErased {
#[inline]
fn clone(&self) -> Self { *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)]
30#[cfg_attr(
31 feature = "nightly",
32 derive(const _: () =
{
impl<__E: ::rustc_serialize::Encoder>
::rustc_serialize::Encodable<__E> for MayBeErased {
fn encode(&self, __encoder: &mut __E) {}
}
};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)
33)]
34pub struct MayBeErased;
3536impl TypingModeErasedStatusfor CantBeErased {}
37impl TypingModeErasedStatusfor MayBeErased {}
3839/// The current typing mode of an inference context. We unfortunately have some
40/// slightly different typing rules depending on the current context. See the
41/// doc comment for each variant for how and why they are used.
42///
43/// In most cases you can get the correct typing mode automatically via:
44/// - `mir::Body::typing_mode`
45/// - `rustc_lint::LateContext::typing_mode`
46///
47/// If neither of these functions are available, feel free to reach out to
48/// t-types for help.
49///
50/// Because typing rules get subtly different based on what typing mode we're in,
51/// subtle enough that changing the behavior of typing modes can sometimes cause
52/// changes that we don't even have tests for, we'd like to enforce the rule that
53/// any place where we specialize behavior based on the typing mode, we match
54/// *exhaustively* on the typing mode. That way, it's easy to determine all the
55/// places that must change when anything about typing modes changes.
56///
57/// Hence, `TypingMode` does not implement `Eq`, though [`TypingModeEqWrapper`] is available
58/// in the rare case that you do need this. Most cases where this currently matters is
59/// where we pass typing modes through the query system and want to cache based on it.
60/// See also `#[rustc_must_match_exhaustively]`, which tries to detect non-exhaustive
61/// matches.
62///
63/// Since matching on typing mode to single out `Coherence` is so common, and `Coherence`
64/// is so different from the other modes: see also [`is_coherence`](TypingMode::is_coherence)
65#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::clone::Clone for
TypingMode<I, S> where I: Interner {
#[inline]
fn clone(&self) -> Self { *self }
}
#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::marker::Copy for
TypingMode<I, S> where I: Interner {
}
#[automatically_derived]
impl<I: Interner, S: TypingModeErasedStatus> ::core::hash::Hash for
TypingMode<I, S> where I: Interner {
fn hash<__H: ::core::hash::Hasher>(&self, __state: &mut __H) {
match self {
TypingMode::Coherence => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
}
TypingMode::Typeck {
defining_opaque_types_and_generators: ref __field_defining_opaque_types_and_generators
} => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
::core::hash::Hash::hash(__field_defining_opaque_types_and_generators,
__state);
}
TypingMode::PostTypeckUntilBorrowck {
defining_opaque_types: ref __field_defining_opaque_types } =>
{
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
::core::hash::Hash::hash(__field_defining_opaque_types,
__state);
}
TypingMode::PostBorrowck {
defined_opaque_types: ref __field_defined_opaque_types } => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
::core::hash::Hash::hash(__field_defined_opaque_types,
__state);
}
TypingMode::Reflection => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
}
TypingMode::PostAnalysis => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
}
TypingMode::Codegen => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
}
TypingMode::ErasedNotCoherence(ref __field_0) => {
::core::hash::Hash::hash(&::core::mem::discriminant(self),
__state);
::core::hash::Hash::hash(__field_0, __state);
}
}
}
}
#[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)]66#[cfg_attr(
67 feature = "nightly",
68 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)
69)]
70#[cfg_attr(feature = "nightly", rustc_must_match_exhaustively)]
71pub enum TypingMode<I: Interner, S: TypingModeErasedStatus = MayBeErased> {
72/// When checking whether impls overlap, we check whether any obligations
73 /// are guaranteed to never hold when unifying the impls. This requires us
74 /// to be complete: we must never fail to prove something which may actually
75 /// hold.
76 ///
77 /// In this typing mode we bail with ambiguity in case its not knowable
78 /// whether a trait goal may hold, e.g. because the trait may get implemented
79 /// in a downstream or sibling crate.
80 ///
81 /// We also have to be careful when generalizing aliases inside of higher-ranked
82 /// types to not unnecessarily constrain any inference variables.
83Coherence,
84/// Typeck is the typing mode mainly used in `rustc_hir_typeck` and related crate.
85 /// It includes type inference, checking that items are well-formed, and
86 /// pretty much everything else which may emit proper type errors to the user.
87 ///
88 /// We only normalize opaque types which may get defined by the current body,
89 /// which are stored in `defining_opaque_types`.
90 ///
91 /// We also refuse to project any associated type that is marked `default`.
92 /// Non-`default` ("final") types are always projected. This is necessary in
93 /// general for soundness of specialization. However, we *could* allow projections
94 /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
95 /// to force the type definition to be treated abstractly by any consumers of the
96 /// impl. Concretely, that means that the following example will
97 /// fail to compile:
98 ///
99 /// ```compile_fail,E0308
100 /// #![feature(specialization)]
101 /// trait Assoc {
102 /// type Output;
103 /// }
104 ///
105 /// impl<T> Assoc for T {
106 /// default type Output = bool;
107 /// }
108 ///
109 /// fn main() {
110 /// let x: <() as Assoc>::Output = true;
111 /// }
112 /// ```
113Typeck { defining_opaque_types_and_generators: I::LocalDefIds },
114/// `PostTypeckUntilBorrowck` is used after `Typeck` has finished, up to and including borrowck,
115 /// for anything that accesses typeck results. This is the behavior that's used mainly in borrowck,
116 /// but, for example, also in late lints and other analyses while building MIR. The behavior of
117 /// `PostTypeckUntilBorrowck` is identical to `TypingMode::Typeck` except that the initial value for
118 /// opaque types is the type computed during HIR typeck with unique unconstrained region inference variables.
119 ///
120 /// This is currently only used by the new solver as it results in new
121 /// non-universal defining uses of opaque types, which is a breaking change.
122 /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
123PostTypeckUntilBorrowck { defining_opaque_types: I::LocalDefIds },
124/// Any analysis after borrowck for a given body should be able to use all the
125 /// hidden types defined by borrowck, without being able to define any new ones.
126 ///
127 /// This is currently only used by the new solver, but should be implemented in
128 /// the old solver as well.
129PostBorrowck { defined_opaque_types: I::LocalDefIds },
130/// During the evaluation of reflection logic that ignores lifetimes, we can only
131 /// handle impls that are fully generic over all lifetimes without constraints on
132 /// those lifetimes (other than implied bounds).
133Reflection,
134/// After analysis, mostly during MIR optimizations, we're able to
135 /// reveal all opaque types. As the hidden type should *never* be observable
136 /// directly by the user, this should not be used by checks which may expose
137 /// such details to the user.
138 ///
139 /// However, we restrict `layout_of` and const-evaluation from exposing some information like
140 /// coroutine layout which requires optimized MIR.
141PostAnalysis,
142143/// During codegen and MIR optimizations, we're able to reveal all opaque types and compute all
144 /// layouts.
145Codegen,
146147/// The typing modes above (except coherence) only differ in how they handle
148 ///
149 /// - Generators
150 /// - Opaque types
151 /// - Specialization (in `PostAnalysis`)
152 ///
153 /// We replace all of them with this `TypingMode` in the first attempt at canonicalization.
154 /// If, during that attempt, we try to access information about opaques or generators
155 /// we bail out, setting a field on `EvalCtxt` that indicates the canonicalization must be
156 /// rerun in the original typing mode.
157 ///
158 /// Specifically, we always reveal auto traits for rigid aliases and thus we don't allow
159 /// incorrectly marked rigid local opaques. We ensure this by immediately bailing out
160 /// when normalizing local opaques.
161 ///
162 /// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
163ErasedNotCoherence(S),
164}
165166/// We want to highly discourage using equality checks on typing modes.
167/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
168/// error. Only use `TypingModeEqWrapper` when you really really really have to.
169/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
170/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
171#[automatically_derived]
impl<I: Interner> ::core::clone::Clone for TypingModeEqWrapper<I> where
I: Interner {
#[inline]
fn clone(&self) -> Self { *self }
}
#[automatically_derived]
impl<I: Interner> ::core::marker::Copy for TypingModeEqWrapper<I> where
I: Interner {
}
#[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)]172#[cfg_attr(
173 feature = "nightly",
174 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) {
let TypingModeEqWrapper(ref __binding_0) = *self;
::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)
175)]
176pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
177178impl<I: Interner> Hashfor TypingModeEqWrapper<I> {
179fn hash<H: Hasher>(&self, state: &mut H) {
180self.0.hash(state);
181 }
182}
183184impl<I: Interner> PartialEqfor TypingModeEqWrapper<I> {
185fn eq(&self, other: &Self) -> bool {
186match (self.0, other.0) {
187 (TypingMode::Coherence, TypingMode::Coherence) => true,
188 (TypingMode::Reflection, TypingMode::Reflection) => true,
189 (
190 TypingMode::Typeck { defining_opaque_types_and_generators: l },
191 TypingMode::Typeck { defining_opaque_types_and_generators: r },
192 ) => l == r,
193 (
194 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: l },
195 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: r },
196 ) => l == r,
197 (
198 TypingMode::PostBorrowck { defined_opaque_types: l },
199 TypingMode::PostBorrowck { defined_opaque_types: r },
200 ) => l == r,
201 (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
202 (TypingMode::Codegen, TypingMode::Codegen) => true,
203 (
204 TypingMode::ErasedNotCoherence(MayBeErased),
205 TypingMode::ErasedNotCoherence(MayBeErased),
206 ) => true,
207 (
208 TypingMode::Coherence209 | TypingMode::Reflection210 | TypingMode::Typeck { .. }
211 | TypingMode::PostTypeckUntilBorrowck { .. }
212 | TypingMode::PostBorrowck { .. }
213 | TypingMode::PostAnalysis214 | TypingMode::Codegen215 | TypingMode::ErasedNotCoherence(MayBeErased),
216_,
217 ) => false,
218 }
219 }
220}
221222impl<I: Interner> Eqfor TypingModeEqWrapper<I> {}
223224impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
225/// There are a bunch of places in the compiler where we single out `Coherence`,
226 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
227 /// but not having this method leads to a bunch of noisy code.
228 ///
229 /// See also the documentation on [`TypingMode`] about exhaustive matching.
230pub fn is_coherence(&self) -> bool {
231match self {
232 TypingMode::Coherence => true,
233 TypingMode::Typeck { .. }
234 | TypingMode::PostTypeckUntilBorrowck { .. }
235 | TypingMode::Reflection236 | TypingMode::PostBorrowck { .. }
237 | TypingMode::PostAnalysis238 | TypingMode::Codegen239 | TypingMode::ErasedNotCoherence(_) => false,
240 }
241 }
242243/// There are a bunch of places in the compiler where we single out `Reflection`,
244 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
245 /// but not having this method leads to a bunch of noisy code.
246 ///
247 /// See also the documentation on [`TypingMode`] about exhaustive matching.
248pub fn is_reflection(&self) -> bool {
249match self {
250 TypingMode::Reflection => true,
251 TypingMode::Typeck { .. }
252 | TypingMode::PostTypeckUntilBorrowck { .. }
253 | TypingMode::Coherence254 | TypingMode::PostBorrowck { .. }
255 | TypingMode::PostAnalysis256 | TypingMode::Codegen257 | TypingMode::ErasedNotCoherence(_) => false,
258 }
259 }
260261/// There are a bunch of places in the trait solver where we single out `Coherence`,
262 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
263 /// but not having this method leads to a bunch of noisy code.
264 ///
265 /// See also the documentation on [`TypingMode`] about exhaustive matching.
266pub fn is_erased_not_coherence(&self) -> bool {
267match self {
268 TypingMode::ErasedNotCoherence(_) => true,
269 TypingMode::Coherence270 | TypingMode::Typeck { .. }
271 | TypingMode::PostTypeckUntilBorrowck { .. }
272 | TypingMode::Reflection273 | TypingMode::PostBorrowck { .. }
274 | TypingMode::PostAnalysis275 | TypingMode::Codegen => false,
276 }
277 }
278}
279280impl<I: Interner> TypingMode<I, MayBeErased> {
281/// Only call this when you're sure you're outside the next trait solver!
282 /// That means either not in the trait solver, or in code that is old-solver only.
283 ///
284 /// See the comment on `InferCtxt::typing_mode_raw`
285pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
286match self {
287 TypingMode::Coherence => TypingMode::Coherence,
288 TypingMode::Typeck { defining_opaque_types_and_generators } => {
289 TypingMode::Typeck { defining_opaque_types_and_generators }
290 }
291 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
292 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
293 }
294 TypingMode::PostBorrowck { defined_opaque_types } => {
295 TypingMode::PostBorrowck { defined_opaque_types }
296 }
297 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
298 TypingMode::Codegen => TypingMode::Codegen,
299 TypingMode::Reflection => TypingMode::Reflection,
300 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!(
301"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"
302),
303 }
304 }
305}
306307impl<I: Interner> TypingMode<I, CantBeErased> {
308/// Analysis outside of a body does not define any opaque types.
309pub fn non_body_analysis() -> TypingMode<I> {
310 TypingMode::Typeck { defining_opaque_types_and_generators: Default::default() }
311 }
312313pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
314 TypingMode::Typeck {
315 defining_opaque_types_and_generators: cx316 .opaque_types_and_coroutines_defined_by(body_def_id),
317 }
318 }
319320/// While typechecking a body, we need to be able to define the opaque
321 /// types defined by that body.
322 ///
323 /// FIXME: This will be removed because it's generally not correct to define
324 /// opaques outside of HIR typeck.
325pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
326 TypingMode::Typeck {
327 defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
328 }
329 }
330331pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
332let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
333if defining_opaque_types.is_empty() {
334TypingMode::non_body_analysis()
335 } else {
336 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
337 }
338 }
339340pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
341let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
342if defined_opaque_types.is_empty() {
343TypingMode::non_body_analysis()
344 } else {
345 TypingMode::PostBorrowck { defined_opaque_types }
346 }
347 }
348}
349350impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
351fn from(value: TypingMode<I, CantBeErased>) -> Self {
352match value {
353 TypingMode::Coherence => TypingMode::Coherence,
354 TypingMode::Typeck { defining_opaque_types_and_generators } => {
355 TypingMode::Typeck { defining_opaque_types_and_generators }
356 }
357 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
358 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
359 }
360 TypingMode::PostBorrowck { defined_opaque_types } => {
361 TypingMode::PostBorrowck { defined_opaque_types }
362 }
363 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
364 TypingMode::Codegen => TypingMode::Codegen,
365 TypingMode::Reflection => TypingMode::Reflection,
366 }
367 }
368}
369370/// `InferCtxtLike` is one of the two traits abstracting over the [InferCtxt][inferctxt-doc], which
371/// had to be split due to coherence reasons:
372/// - `InferCtxtLike`] contains the parts that have to live in `rustc_infer`, and thus aren't only
373/// about trait-solving. It is implemented [directly on `InferCtxt`][inferctxtlike-impl-doc],
374/// - [SolverDelegate][solverdelegate-doc] contains the parts depending on trait-solving logic, to
375/// provide functionality in `rustc_trait_selection`, and is implemented by a [simple wrapper over
376/// `InferCtxt`][inferctxt-wrapper-doc] there.
377///
378/// More information can also be found in the dedicated chapter in the dev-guide, in [this
379/// section][dev-guide].
380///
381/// [inferctxt-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html
382/// [inferctxtlike-impl-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#impl-InferCtxtLike-for-InferCtxt%3C'tcx%3E
383/// [solverdelegate-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/delegate/trait.SolverDelegate.html
384/// [inferctxt-wrapper-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/delegate/struct.SolverDelegate.html
385/// [dev-guide]: https://rustc-dev-guide.rust-lang.org/solve/sharing-crates-with-rust-analyzer.html#trait-inferctxtlike-and-trait-solverdelegate
386#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
387pub trait InferCtxtLike: Sized {
388type Interner: Interner;
389fn cx(&self) -> Self::Interner;
390391/// Whether the new trait solver is enabled. This only exists because rustc
392 /// shares code between the new and old trait solvers; for all other users,
393 /// this should always be true. If this is unknowingly false and you try to
394 /// use the new trait solver, things will break badly.
395fn next_trait_solver(&self) -> bool {
396true
397}
398399fn enable_next_solver_overflow_fcw(&self) -> bool;
400401fn disable_trait_solver_fast_paths(&self) -> bool;
402403fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
404405fn universe(&self) -> ty::UniverseIndex;
406fn create_next_universe(&self) -> ty::UniverseIndex;
407408fn insert_placeholder_assumptions(
409&self,
410 u: ty::UniverseIndex,
411 assumptions: crate::region_constraint::Assumptions<Self::Interner>,
412 );
413fn get_placeholder_assumptions(
414&self,
415 u: ty::UniverseIndex,
416 ) -> crate::region_constraint::Assumptions<Self::Interner>;
417fn has_placeholder_assumptions(&self, range: RangeInclusive<ty::UniverseIndex>) -> bool;
418fn get_solver_region_constraint(
419&self,
420 ) -> crate::region_constraint::RegionConstraint<Self::Interner>;
421fn overwrite_solver_region_constraint(
422&self,
423 constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
424 span: <Self::Interner as Interner>::Span,
425 );
426427fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
428fn universe_of_region(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
429fn universe_of_const(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
430431fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
432fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
433fn is_sub_unification_table_root_var(&self, var: ty::TyVid) -> bool;
434fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
435436fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
437fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
438fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> <Self::Interner as Interner>::Ty;
439fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> Const<Self::Interner>;
440fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> Region<Self::Interner>;
441442fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool;
443444fn next_region_infer(&self) -> Region<Self::Interner>;
445fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
446fn next_const_infer(&self) -> Const<Self::Interner>;
447fn fresh_args_for_item(
448&self,
449 def_id: <Self::Interner as Interner>::DefId,
450 ) -> <Self::Interner as Interner>::GenericArgs;
451452fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
453&self,
454 value: ty::Binder<Self::Interner, T>,
455 ) -> T;
456457fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
458&self,
459 value: ty::Binder<Self::Interner, T>,
460 f: impl FnOnce(T) -> U,
461 ) -> U;
462463/// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
464 /// and should be replaced in the long term by actually taking assumptions into
465 /// account.
466fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
467&self,
468 value: ty::Binder<Self::Interner, T>,
469 f: impl FnOnce(T) -> U,
470 ) -> U;
471472fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
473fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
474fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
475fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
476fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
477478/// Use `instantiate_ty_var` instead unless you have reasons to skip
479 /// generalization.
480fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: <Self::Interner as Interner>::Ty);
481/// Use `instantiate_const_var` instead unless you have reasons to skip
482 /// generalization.
483fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: Const<Self::Interner>);
484fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
485&self,
486 relation: &mut R,
487 target_is_expected: bool,
488 target_vid: ty::TyVid,
489 instantiation_variance: ty::Variance,
490 source_ty: <Self::Interner as Interner>::Ty,
491 ) -> RelateResult<Self::Interner, ()>;
492fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
493fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
494fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
495&self,
496 relation: &mut R,
497 target_is_expected: bool,
498 target_vid: ty::ConstVid,
499 source_ct: Const<Self::Interner>,
500 ) -> RelateResult<Self::Interner, ()>;
501502fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
503504fn shallow_resolve(
505&self,
506 ty: <Self::Interner as Interner>::Ty,
507 ) -> <Self::Interner as Interner>::Ty;
508fn shallow_resolve_const(&self, ty: Const<Self::Interner>) -> Const<Self::Interner>;
509510fn deeply_resolve_ignoring_regions<T>(&self, value: T) -> T
511where
512T: TypeFoldable<Self::Interner>;
513514fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
515516fn commit_if_ok<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E>;
517518fn sub_regions(
519&self,
520 sub: Region<Self::Interner>,
521 sup: Region<Self::Interner>,
522 vis: VisibleForLeakCheck,
523 span: <Self::Interner as Interner>::Span,
524 );
525526fn equate_regions(
527&self,
528 a: Region<Self::Interner>,
529 b: Region<Self::Interner>,
530 vis: VisibleForLeakCheck,
531 span: <Self::Interner as Interner>::Span,
532 );
533534fn register_solver_region_constraint(
535&self,
536 c: crate::region_constraint::RegionConstraint<Self::Interner>,
537 span: <Self::Interner as Interner>::Span,
538 );
539540fn register_ty_outlives(
541&self,
542 ty: <Self::Interner as Interner>::Ty,
543 r: Region<Self::Interner>,
544 span: <Self::Interner as Interner>::Span,
545 );
546547type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
548fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
549fn clone_opaque_types_lookup_table(
550&self,
551 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
552fn clone_duplicate_opaque_types(
553&self,
554 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
555fn clone_opaque_types_added_since(
556&self,
557 prev_entries: Self::OpaqueTypeStorageEntries,
558 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
559fn opaques_with_sub_unified_hidden_type(
560&self,
561 ty: TyVid,
562 ) -> Vec<ty::OpaqueAliasTy<Self::Interner>>;
563564fn register_hidden_type_in_storage(
565&self,
566 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
567 hidden_ty: <Self::Interner as Interner>::Ty,
568 span: <Self::Interner as Interner>::Span,
569 ) -> Option<<Self::Interner as Interner>::Ty>;
570fn add_duplicate_opaque_type(
571&self,
572 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
573 hidden_ty: <Self::Interner as Interner>::Ty,
574 span: <Self::Interner as Interner>::Span,
575 );
576577fn reset_opaque_types(&self);
578579/// Where possible, replaces type/const/region variables in `value` with their final value.
580 /// If a type/const/region variable has not (yet) been unified, it is left as is.
581 ///
582 /// This is an idempotent operation that does not affect inference state in any way,
583 /// which means it's safe to call this function at will.
584fn deeply_resolve_via_unification_table<T: TypeFoldable<Self::Interner>>(&self, value: T) -> T {
585if value.has_infer() {
586let mut folder = DeepVariableResolver::new(self);
587value.fold_with(&mut folder)
588 } else {
589value590 }
591 }
592}
593594pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
595 infcx: &'a Infcx,
596 param_env: I::ParamEnv,
597 symbol: I::Symbol,
598) -> bool599where
600Infcx: InferCtxtLike<Interner = I>,
601{
602// Iterate through all goals in param_env to find the one that has the same symbol.
603for clause in param_env.caller_bounds() {
604if let ty::ClauseKind::UnstableFeature(sym) = clause.kind().skip_binder() {
605if sym == symbol {
606return true;
607 }
608 }
609 }
610611// During codegen we must assume that all feature bounds hold as we may be
612 // monomorphizing a body from an upstream crate which had an unstable feature
613 // enabled that we do not.
614 //
615 // Coherence should already report overlap errors involving unstable impls
616 // as the affected code would otherwise break when stabilizing this feature.
617 // It is also easily possible to accidentally cause unsoundness this way as
618 // we have to always enable unstable impls during codegen.
619 //
620 // Return ambiguity can also prevent people from writing code which depends on inference guidance
621 // that might no longer work after the impl is stabilised,
622 // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
623 //
624 // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
625 // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
626627match infcx.typing_mode_raw().assert_not_erased() {
628 TypingMode::Coherence629 | TypingMode::Typeck { .. }
630 | TypingMode::PostTypeckUntilBorrowck { .. }
631 | TypingMode::Reflection632 | TypingMode::PostBorrowck { .. }
633 | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol),
634 TypingMode::Codegen => true,
635 }
636}
637638struct DeepVariableResolver<'a, D, I = <D as InferCtxtLike>::Interner>
639where
640D: InferCtxtLike<Interner = I>,
641 I: Interner,
642{
643 delegate: &'a D,
644/// We're able to use a cache here as the folder does not have any
645 /// mutable state.
646cache: DelayedMap<I::Ty, I::Ty>,
647}
648649impl<'a, Infcx: InferCtxtLike> DeepVariableResolver<'a, Infcx> {
650fn new(delegate: &'a Infcx) -> Self {
651DeepVariableResolver { delegate, cache: Default::default() }
652 }
653}
654655impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
656for DeepVariableResolver<'_, Infcx>
657{
658fn cx(&self) -> I {
659self.delegate.cx()
660 }
661662fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
663match t.kind() {
664 ty::Infer(ty::TyVar(vid)) => {
665let resolved = self.delegate.shallow_resolve_ty_var(vid);
666if t != resolved && resolved.has_infer() {
667resolved.fold_with(self)
668 } else {
669resolved670 }
671 }
672 ty::Infer(ty::IntVar(vid)) => self.delegate.shallow_resolve_int_var(vid),
673 ty::Infer(ty::FloatVar(vid)) => self.delegate.shallow_resolve_float_var(vid),
674_ => {
675if t.has_infer() {
676if let Some(&ty) = self.cache.get(&t) {
677return ty;
678 }
679let res = t.super_fold_with(self);
680if !self.cache.insert(t, res) {
::core::panicking::panic("assertion failed: self.cache.insert(t, res)")
};assert!(self.cache.insert(t, res));
681res682 } else {
683t684 }
685 }
686 }
687 }
688689fn fold_region(&mut self, r: Region<I>) -> Region<I> {
690match r.kind() {
691 ty::ReVar(vid) => self.delegate.shallow_resolve_region_var(vid),
692_ => r,
693 }
694 }
695696fn fold_const(&mut self, c: Const<I>) -> Const<I> {
697match c.kind() {
698 ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
699let resolved = self.delegate.shallow_resolve_const_var(vid);
700if c != resolved && resolved.has_infer() {
701resolved.fold_with(self)
702 } else {
703resolved704 }
705 }
706_ => {
707if c.has_infer() {
708c.super_fold_with(self)
709 } else {
710c711 }
712 }
713 }
714 }
715716fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
717if p.has_infer() { p.super_fold_with(self) } else { p }
718 }
719720fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
721if c.has_infer() { c.super_fold_with(self) } else { c }
722 }
723}