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::{TyOrConstInferVar, VisibleForLeakCheck};
13use crate::{
14selfas ty, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder,
15TypeSuperFoldable, TypeVisitableExt,
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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for CantBeErased { }
#[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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MayBeErased { }
#[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) {}
}
};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::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)]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 /// Specifically, we always reveal auto traits for rigid aliases and thus we don't allow
158 /// incorrectly marked rigid local opaques. We ensure this by immediately bailing out
159 /// when normalizing local opaques.
160 ///
161 /// `TypingMode::Coherence` is not replaced by this and is always kept as-is.
162ErasedNotCoherence(S),
163}
164165/// We want to highly discourage using equality checks on typing modes.
166/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
167/// error. Only use `TypingModeEqWrapper` when you really really really have to.
168/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
169/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
170#[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)]171#[cfg_attr(
172 feature = "nightly",
173 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)
174)]
175pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I, MayBeErased>);
176177impl<I: Interner> Hashfor TypingModeEqWrapper<I> {
178fn hash<H: Hasher>(&self, state: &mut H) {
179self.0.hash(state);
180 }
181}
182183impl<I: Interner> PartialEqfor TypingModeEqWrapper<I> {
184fn eq(&self, other: &Self) -> bool {
185match (self.0, other.0) {
186 (TypingMode::Coherence, TypingMode::Coherence) => true,
187 (TypingMode::Reflection, TypingMode::Reflection) => true,
188 (
189 TypingMode::Typeck { defining_opaque_types_and_generators: l },
190 TypingMode::Typeck { defining_opaque_types_and_generators: r },
191 ) => l == r,
192 (
193 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: l },
194 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: r },
195 ) => l == r,
196 (
197 TypingMode::PostBorrowck { defined_opaque_types: l },
198 TypingMode::PostBorrowck { defined_opaque_types: r },
199 ) => l == r,
200 (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
201 (TypingMode::Codegen, TypingMode::Codegen) => true,
202 (
203 TypingMode::ErasedNotCoherence(MayBeErased),
204 TypingMode::ErasedNotCoherence(MayBeErased),
205 ) => true,
206 (
207 TypingMode::Coherence208 | TypingMode::Reflection209 | TypingMode::Typeck { .. }
210 | TypingMode::PostTypeckUntilBorrowck { .. }
211 | TypingMode::PostBorrowck { .. }
212 | TypingMode::PostAnalysis213 | TypingMode::Codegen214 | TypingMode::ErasedNotCoherence(MayBeErased),
215_,
216 ) => false,
217 }
218 }
219}
220221impl<I: Interner> Eqfor TypingModeEqWrapper<I> {}
222223impl<I: Interner, S: TypingModeErasedStatus> TypingMode<I, S> {
224/// There are a bunch of places in the compiler where we single out `Coherence`,
225 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
226 /// but not having this method leads to a bunch of noisy code.
227 ///
228 /// See also the documentation on [`TypingMode`] about exhaustive matching.
229pub fn is_coherence(&self) -> bool {
230match self {
231 TypingMode::Coherence => true,
232 TypingMode::Typeck { .. }
233 | TypingMode::PostTypeckUntilBorrowck { .. }
234 | TypingMode::Reflection235 | TypingMode::PostBorrowck { .. }
236 | TypingMode::PostAnalysis237 | TypingMode::Codegen238 | TypingMode::ErasedNotCoherence(_) => false,
239 }
240 }
241242/// There are a bunch of places in the compiler where we single out `Reflection`,
243 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
244 /// but not having this method leads to a bunch of noisy code.
245 ///
246 /// See also the documentation on [`TypingMode`] about exhaustive matching.
247pub fn is_reflection(&self) -> bool {
248match self {
249 TypingMode::Reflection => true,
250 TypingMode::Typeck { .. }
251 | TypingMode::PostTypeckUntilBorrowck { .. }
252 | TypingMode::Coherence253 | TypingMode::PostBorrowck { .. }
254 | TypingMode::PostAnalysis255 | TypingMode::Codegen256 | TypingMode::ErasedNotCoherence(_) => false,
257 }
258 }
259260/// There are a bunch of places in the trait solver where we single out `Coherence`,
261 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
262 /// but not having this method leads to a bunch of noisy code.
263 ///
264 /// See also the documentation on [`TypingMode`] about exhaustive matching.
265pub fn is_erased_not_coherence(&self) -> bool {
266match self {
267 TypingMode::ErasedNotCoherence(_) => true,
268 TypingMode::Coherence269 | TypingMode::Typeck { .. }
270 | TypingMode::PostTypeckUntilBorrowck { .. }
271 | TypingMode::Reflection272 | TypingMode::PostBorrowck { .. }
273 | TypingMode::PostAnalysis274 | TypingMode::Codegen => false,
275 }
276 }
277}
278279impl<I: Interner> TypingMode<I, MayBeErased> {
280/// Only call this when you're sure you're outside the next trait solver!
281 /// That means either not in the trait solver, or in code that is old-solver only.
282 ///
283 /// See the comment on `InferCtxt::typing_mode_raw`
284pub fn assert_not_erased(self) -> TypingMode<I, CantBeErased> {
285match self {
286 TypingMode::Coherence => TypingMode::Coherence,
287 TypingMode::Typeck { defining_opaque_types_and_generators } => {
288 TypingMode::Typeck { defining_opaque_types_and_generators }
289 }
290 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
291 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
292 }
293 TypingMode::PostBorrowck { defined_opaque_types } => {
294 TypingMode::PostBorrowck { defined_opaque_types }
295 }
296 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
297 TypingMode::Codegen => TypingMode::Codegen,
298 TypingMode::Reflection => TypingMode::Reflection,
299 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!(
300"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"
301),
302 }
303 }
304}
305306impl<I: Interner> TypingMode<I, CantBeErased> {
307/// Analysis outside of a body does not define any opaque types.
308pub fn non_body_analysis() -> TypingMode<I> {
309 TypingMode::Typeck { defining_opaque_types_and_generators: Default::default() }
310 }
311312pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
313 TypingMode::Typeck {
314 defining_opaque_types_and_generators: cx315 .opaque_types_and_coroutines_defined_by(body_def_id),
316 }
317 }
318319/// While typechecking a body, we need to be able to define the opaque
320 /// types defined by that body.
321 ///
322 /// FIXME: This will be removed because it's generally not correct to define
323 /// opaques outside of HIR typeck.
324pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
325 TypingMode::Typeck {
326 defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
327 }
328 }
329330pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
331let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
332if defining_opaque_types.is_empty() {
333TypingMode::non_body_analysis()
334 } else {
335 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
336 }
337 }
338339pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
340let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
341if defined_opaque_types.is_empty() {
342TypingMode::non_body_analysis()
343 } else {
344 TypingMode::PostBorrowck { defined_opaque_types }
345 }
346 }
347}
348349impl<I: Interner> From<TypingMode<I, CantBeErased>> for TypingMode<I, MayBeErased> {
350fn from(value: TypingMode<I, CantBeErased>) -> Self {
351match value {
352 TypingMode::Coherence => TypingMode::Coherence,
353 TypingMode::Typeck { defining_opaque_types_and_generators } => {
354 TypingMode::Typeck { defining_opaque_types_and_generators }
355 }
356 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {
357 TypingMode::PostTypeckUntilBorrowck { defining_opaque_types }
358 }
359 TypingMode::PostBorrowck { defined_opaque_types } => {
360 TypingMode::PostBorrowck { defined_opaque_types }
361 }
362 TypingMode::PostAnalysis => TypingMode::PostAnalysis,
363 TypingMode::Codegen => TypingMode::Codegen,
364 TypingMode::Reflection => TypingMode::Reflection,
365 }
366 }
367}
368369/// `InferCtxtLike` is one of the two traits abstracting over the [InferCtxt][inferctxt-doc], which
370/// had to be split due to coherence reasons:
371/// - `InferCtxtLike`] contains the parts that have to live in `rustc_infer`, and thus aren't only
372/// about trait-solving. It is implemented [directly on `InferCtxt`][inferctxtlike-impl-doc],
373/// - [SolverDelegate][solverdelegate-doc] contains the parts depending on trait-solving logic, to
374/// provide functionality in `rustc_trait_selection`, and is implemented by a [simple wrapper over
375/// `InferCtxt`][inferctxt-wrapper-doc] there.
376///
377/// More information can also be found in the dedicated chapter in the dev-guide, in [this
378/// section][dev-guide].
379///
380/// [inferctxt-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html
381/// [inferctxtlike-impl-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#impl-InferCtxtLike-for-InferCtxt%3C'tcx%3E
382/// [solverdelegate-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/delegate/trait.SolverDelegate.html
383/// [inferctxt-wrapper-doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/delegate/struct.SolverDelegate.html
384/// [dev-guide]: https://rustc-dev-guide.rust-lang.org/solve/sharing-crates-with-rust-analyzer.html#trait-inferctxtlike-and-trait-solverdelegate
385#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
386pub trait InferCtxtLike: Sized {
387type Interner: Interner;
388fn cx(&self) -> Self::Interner;
389390/// Whether the new trait solver is enabled. This only exists because rustc
391 /// shares code between the new and old trait solvers; for all other users,
392 /// this should always be true. If this is unknowingly false and you try to
393 /// use the new trait solver, things will break badly.
394fn next_trait_solver(&self) -> bool {
395true
396}
397398fn enable_next_solver_overflow_fcw(&self) -> bool;
399400fn disable_trait_solver_fast_paths(&self) -> bool;
401402fn typing_mode_raw(&self) -> TypingMode<Self::Interner>;
403404fn universe(&self) -> ty::UniverseIndex;
405fn create_next_universe(&self) -> ty::UniverseIndex;
406407fn insert_placeholder_assumptions(
408&self,
409 u: ty::UniverseIndex,
410 assumptions: Option<crate::region_constraint::Assumptions<Self::Interner>>,
411 );
412fn get_placeholder_assumptions(
413&self,
414 u: ty::UniverseIndex,
415 ) -> Option<crate::region_constraint::Assumptions<Self::Interner>>;
416fn get_solver_region_constraint(
417&self,
418 ) -> crate::region_constraint::RegionConstraint<Self::Interner>;
419fn overwrite_solver_region_constraint(
420&self,
421 constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
422 span: <Self::Interner as Interner>::Span,
423 );
424425fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
426fn universe_of_region(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
427fn universe_of_const(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
428429fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
430fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
431fn is_sub_unification_table_root_var(&self, var: ty::TyVid) -> bool;
432fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
433434fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
435fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
436fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> <Self::Interner as Interner>::Ty;
437fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> <Self::Interner as Interner>::Const;
438fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> Region<Self::Interner>;
439440fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool;
441442fn next_region_infer(&self) -> Region<Self::Interner>;
443fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
444fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
445fn fresh_args_for_item(
446&self,
447 def_id: <Self::Interner as Interner>::DefId,
448 ) -> <Self::Interner as Interner>::GenericArgs;
449450fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
451&self,
452 value: ty::Binder<Self::Interner, T>,
453 ) -> T;
454455fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
456&self,
457 value: ty::Binder<Self::Interner, T>,
458 f: impl FnOnce(T) -> U,
459 ) -> U;
460461/// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
462 /// and should be replaced in the long term by actually taking assumptions into
463 /// account.
464fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
465&self,
466 value: ty::Binder<Self::Interner, T>,
467 f: impl FnOnce(T) -> U,
468 ) -> U;
469470fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
471fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
472fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
473fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
474fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
475476/// Use `instantiate_ty_var` instead unless you have reasons to skip
477 /// generalization.
478fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: <Self::Interner as Interner>::Ty);
479/// Use `instantiate_const_var` instead unless you have reasons to skip
480 /// generalization.
481fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: <Self::Interner as Interner>::Const);
482fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
483&self,
484 relation: &mut R,
485 target_is_expected: bool,
486 target_vid: ty::TyVid,
487 instantiation_variance: ty::Variance,
488 source_ty: <Self::Interner as Interner>::Ty,
489 ) -> RelateResult<Self::Interner, ()>;
490fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
491fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
492fn instantiate_const_var<R: PredicateEmittingRelation<Self>>(
493&self,
494 relation: &mut R,
495 target_is_expected: bool,
496 target_vid: ty::ConstVid,
497 source_ct: <Self::Interner as Interner>::Const,
498 ) -> RelateResult<Self::Interner, ()>;
499500fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
501502fn shallow_resolve(
503&self,
504 ty: <Self::Interner as Interner>::Ty,
505 ) -> <Self::Interner as Interner>::Ty;
506fn shallow_resolve_const(
507&self,
508 ty: <Self::Interner as Interner>::Const,
509 ) -> <Self::Interner as Interner>::Const;
510511fn deeply_resolve_ignoring_regions<T>(&self, value: T) -> T
512where
513T: TypeFoldable<Self::Interner>;
514515fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
516517fn commit_if_ok<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E>;
518519fn sub_regions(
520&self,
521 sub: Region<Self::Interner>,
522 sup: Region<Self::Interner>,
523 vis: VisibleForLeakCheck,
524 span: <Self::Interner as Interner>::Span,
525 );
526527fn equate_regions(
528&self,
529 a: Region<Self::Interner>,
530 b: Region<Self::Interner>,
531 vis: VisibleForLeakCheck,
532 span: <Self::Interner as Interner>::Span,
533 );
534535fn register_solver_region_constraint(
536&self,
537 c: crate::region_constraint::RegionConstraint<Self::Interner>,
538 span: <Self::Interner as Interner>::Span,
539 );
540541fn register_ty_outlives(
542&self,
543 ty: <Self::Interner as Interner>::Ty,
544 r: Region<Self::Interner>,
545 span: <Self::Interner as Interner>::Span,
546 );
547548type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
549fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
550fn clone_opaque_types_lookup_table(
551&self,
552 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
553fn clone_duplicate_opaque_types(
554&self,
555 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
556fn clone_opaque_types_added_since(
557&self,
558 prev_entries: Self::OpaqueTypeStorageEntries,
559 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
560fn opaques_with_sub_unified_hidden_type(
561&self,
562 ty: TyVid,
563 ) -> Vec<ty::OpaqueAliasTy<Self::Interner>>;
564565fn register_hidden_type_in_storage(
566&self,
567 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
568 hidden_ty: <Self::Interner as Interner>::Ty,
569 span: <Self::Interner as Interner>::Span,
570 ) -> Option<<Self::Interner as Interner>::Ty>;
571fn add_duplicate_opaque_type(
572&self,
573 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
574 hidden_ty: <Self::Interner as Interner>::Ty,
575 span: <Self::Interner as Interner>::Span,
576 );
577578fn reset_opaque_types(&self);
579580/// Where possible, replaces type/const/region variables in `value` with their final value.
581 /// If a type/const/region variable has not (yet) been unified, it is left as is.
582 ///
583 /// This is an idempotent operation that does not affect inference state in any way,
584 /// which means it's safe to call this function at will.
585fn deeply_resolve_via_unification_table<T: TypeFoldable<Self::Interner>>(&self, value: T) -> T {
586if value.has_infer() {
587let mut folder = DeepVariableResolver::new(self);
588value.fold_with(&mut folder)
589 } else {
590value591 }
592 }
593}
594595pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
596 infcx: &'a Infcx,
597 param_env: I::ParamEnv,
598 symbol: I::Symbol,
599) -> bool600where
601Infcx: InferCtxtLike<Interner = I>,
602{
603// Iterate through all goals in param_env to find the one that has the same symbol.
604for clause in param_env.caller_bounds() {
605if let ty::ClauseKind::UnstableFeature(sym) = clause.kind().skip_binder() {
606if sym == symbol {
607return true;
608 }
609 }
610 }
611612// During codegen we must assume that all feature bounds hold as we may be
613 // monomorphizing a body from an upstream crate which had an unstable feature
614 // enabled that we do not.
615 //
616 // Coherence should already report overlap errors involving unstable impls
617 // as the affected code would otherwise break when stabilizing this feature.
618 // It is also easily possible to accidentally cause unsoundness this way as
619 // we have to always enable unstable impls during codegen.
620 //
621 // Return ambiguity can also prevent people from writing code which depends on inference guidance
622 // that might no longer work after the impl is stabilised,
623 // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
624 //
625 // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
626 // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
627628match infcx.typing_mode_raw().assert_not_erased() {
629 TypingMode::Coherence630 | TypingMode::Typeck { .. }
631 | TypingMode::PostTypeckUntilBorrowck { .. }
632 | TypingMode::Reflection633 | TypingMode::PostBorrowck { .. }
634 | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol),
635 TypingMode::Codegen => true,
636 }
637}
638639struct DeepVariableResolver<'a, D, I = <D as InferCtxtLike>::Interner>
640where
641D: InferCtxtLike<Interner = I>,
642 I: Interner,
643{
644 delegate: &'a D,
645/// We're able to use a cache here as the folder does not have any
646 /// mutable state.
647cache: DelayedMap<I::Ty, I::Ty>,
648}
649650impl<'a, Infcx: InferCtxtLike> DeepVariableResolver<'a, Infcx> {
651fn new(delegate: &'a Infcx) -> Self {
652DeepVariableResolver { delegate, cache: Default::default() }
653 }
654}
655656impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
657for DeepVariableResolver<'_, Infcx>
658{
659fn cx(&self) -> I {
660self.delegate.cx()
661 }
662663fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
664match t.kind() {
665 ty::Infer(ty::TyVar(vid)) => {
666let resolved = self.delegate.shallow_resolve_ty_var(vid);
667if t != resolved && resolved.has_infer() {
668resolved.fold_with(self)
669 } else {
670resolved671 }
672 }
673 ty::Infer(ty::IntVar(vid)) => self.delegate.shallow_resolve_int_var(vid),
674 ty::Infer(ty::FloatVar(vid)) => self.delegate.shallow_resolve_float_var(vid),
675_ => {
676if t.has_infer() {
677if let Some(&ty) = self.cache.get(&t) {
678return ty;
679 }
680let res = t.super_fold_with(self);
681if !self.cache.insert(t, res) {
::core::panicking::panic("assertion failed: self.cache.insert(t, res)")
};assert!(self.cache.insert(t, res));
682res683 } else {
684t685 }
686 }
687 }
688 }
689690fn fold_region(&mut self, r: Region<I>) -> Region<I> {
691match r.kind() {
692 ty::ReVar(vid) => self.delegate.shallow_resolve_region_var(vid),
693_ => r,
694 }
695 }
696697fn fold_const(&mut self, c: I::Const) -> I::Const {
698match c.kind() {
699 ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
700let resolved = self.delegate.shallow_resolve_const_var(vid);
701if c != resolved && resolved.has_infer() {
702resolved.fold_with(self)
703 } else {
704resolved705 }
706 }
707_ => {
708if c.has_infer() {
709c.super_fold_with(self)
710 } else {
711c712 }
713 }
714 }
715 }
716717fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
718if p.has_infer() { p.super_fold_with(self) } else { p }
719 }
720721fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
722if c.has_infer() { c.super_fold_with(self) } else { c }
723 }
724}