1use std::hash::{Hash, Hasher};
23use derive_where::derive_where;
4#[cfg(feature = "nightly")]
5use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
67use crate::fold::TypeFoldable;
8use crate::inherent::*;
9use crate::relate::RelateResult;
10use crate::relate::combine::PredicateEmittingRelation;
11use crate::{selfas ty, Interner, TyVid};
1213/// The current typing mode of an inference context. We unfortunately have some
14/// slightly different typing rules depending on the current context. See the
15/// doc comment for each variant for how and why they are used.
16///
17/// In most cases you can get the correct typing mode automatically via:
18/// - `mir::Body::typing_mode`
19/// - `rustc_lint::LateContext::typing_mode`
20///
21/// If neither of these functions are available, feel free to reach out to
22/// t-types for help.
23///
24/// Because typing rules get subtly different based on what typing mode we're in,
25/// subtle enough that changing the behavior of typing modes can sometimes cause
26/// changes that we don't even have tests for, we'd like to enforce the rule that
27/// any place where we specialize behavior based on the typing mode, we match
28/// *exhaustively* on the typing mode. That way, it's easy to determine all the
29/// places that must change when anything about typing modes changes.
30///
31/// Hence, `TypingMode` does not implement `Eq`, though [`TypingModeEqWrapper`] is available
32/// in the rare case that you do need this. Most cases where this currently matters is
33/// where we pass typing modes through the query system and want to cache based on it.
34/// See also `#[rustc_must_match_exhaustively]`, which tries to detect non-exhaustive
35/// matches.
36///
37/// Since matching on typing mode to single out `Coherence` is so common, and `Coherence`
38/// is so different from the other modes: see also [`is_coherence`](TypingMode::is_coherence)
39#[automatically_derived]
impl<I: Interner> ::core::fmt::Debug for TypingMode<I> where I: Interner {
fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
match self {
TypingMode::Coherence =>
::core::fmt::Formatter::write_str(__f, "Coherence"),
TypingMode::Analysis {
defining_opaque_types_and_generators: ref __field_defining_opaque_types_and_generators
} => {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f, "Analysis");
::core::fmt::DebugStruct::field(&mut __builder,
"defining_opaque_types_and_generators",
__field_defining_opaque_types_and_generators);
::core::fmt::DebugStruct::finish(&mut __builder)
}
TypingMode::Borrowck {
defining_opaque_types: ref __field_defining_opaque_types } =>
{
let mut __builder =
::core::fmt::Formatter::debug_struct(__f, "Borrowck");
::core::fmt::DebugStruct::field(&mut __builder,
"defining_opaque_types", __field_defining_opaque_types);
::core::fmt::DebugStruct::finish(&mut __builder)
}
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: ref __field_defined_opaque_types } => {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f,
"PostBorrowckAnalysis");
::core::fmt::DebugStruct::field(&mut __builder,
"defined_opaque_types", __field_defined_opaque_types);
::core::fmt::DebugStruct::finish(&mut __builder)
}
TypingMode::PostAnalysis =>
::core::fmt::Formatter::write_str(__f, "PostAnalysis"),
}
}
}#[derive_where(Clone, Copy, Hash, Debug; I: Interner)]40#[cfg_attr(
41 feature = "nightly",
42 derive(const _: () =
{
impl<I: Interner, __E: ::rustc_serialize::Encoder>
::rustc_serialize::Encodable<__E> for TypingMode<I> where
I::LocalDefIds: ::rustc_serialize::Encodable<__E> {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
TypingMode::Coherence => { 0usize }
TypingMode::Analysis {
defining_opaque_types_and_generators: ref __binding_0 } => {
1usize
}
TypingMode::Borrowck {
defining_opaque_types: ref __binding_0 } => {
2usize
}
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: ref __binding_0 } => {
3usize
}
TypingMode::PostAnalysis => { 4usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
TypingMode::Coherence => {}
TypingMode::Analysis {
defining_opaque_types_and_generators: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
TypingMode::Borrowck {
defining_opaque_types: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: ref __binding_0 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
TypingMode::PostAnalysis => {}
}
}
}
};Encodable_NoContext, const _: () =
{
impl<I: Interner, __D: ::rustc_serialize::Decoder>
::rustc_serialize::Decodable<__D> for TypingMode<I> where
I::LocalDefIds: ::rustc_serialize::Decodable<__D> {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => { TypingMode::Coherence }
1usize => {
TypingMode::Analysis {
defining_opaque_types_and_generators: ::rustc_serialize::Decodable::decode(__decoder),
}
}
2usize => {
TypingMode::Borrowck {
defining_opaque_types: ::rustc_serialize::Decodable::decode(__decoder),
}
}
3usize => {
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: ::rustc_serialize::Decodable::decode(__decoder),
}
}
4usize => { TypingMode::PostAnalysis }
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `TypingMode`, expected 0..5, actual {0}",
n));
}
}
}
}
};Decodable_NoContext, const _: () =
{
impl<I: Interner, __CTX>
::rustc_data_structures::stable_hasher::HashStable<__CTX> for
TypingMode<I> where
I::LocalDefIds: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
{
#[inline]
fn hash_stable(&self, __hcx: &mut __CTX,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
match *self {
TypingMode::Coherence => {}
TypingMode::Analysis {
defining_opaque_types_and_generators: ref __binding_0 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
TypingMode::Borrowck {
defining_opaque_types: ref __binding_0 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
TypingMode::PostBorrowckAnalysis {
defined_opaque_types: ref __binding_0 } => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
TypingMode::PostAnalysis => {}
}
}
}
};HashStable_NoContext)
43)]
44#[cfg_attr(feature = "nightly", rustc_must_match_exhaustively)]
45pub enum TypingMode<I: Interner> {
46/// When checking whether impls overlap, we check whether any obligations
47 /// are guaranteed to never hold when unifying the impls. This requires us
48 /// to be complete: we must never fail to prove something which may actually
49 /// hold.
50 ///
51 /// In this typing mode we bail with ambiguity in case its not knowable
52 /// whether a trait goal may hold, e.g. because the trait may get implemented
53 /// in a downstream or sibling crate.
54 ///
55 /// We also have to be careful when generalizing aliases inside of higher-ranked
56 /// types to not unnecessarily constrain any inference variables.
57Coherence,
58/// Analysis includes type inference, checking that items are well-formed, and
59 /// pretty much everything else which may emit proper type errors to the user.
60 ///
61 /// We only normalize opaque types which may get defined by the current body,
62 /// which are stored in `defining_opaque_types`.
63 ///
64 /// We also refuse to project any associated type that is marked `default`.
65 /// Non-`default` ("final") types are always projected. This is necessary in
66 /// general for soundness of specialization. However, we *could* allow projections
67 /// in fully-monomorphic cases. We choose not to, because we prefer for `default type`
68 /// to force the type definition to be treated abstractly by any consumers of the
69 /// impl. Concretely, that means that the following example will
70 /// fail to compile:
71 ///
72 /// ```compile_fail,E0308
73 /// #![feature(specialization)]
74 /// trait Assoc {
75 /// type Output;
76 /// }
77 ///
78 /// impl<T> Assoc for T {
79 /// default type Output = bool;
80 /// }
81 ///
82 /// fn main() {
83 /// let x: <() as Assoc>::Output = true;
84 /// }
85 /// ```
86Analysis { defining_opaque_types_and_generators: I::LocalDefIds },
87/// The behavior during MIR borrowck is identical to `TypingMode::Analysis`
88 /// except that the initial value for opaque types is the type computed during
89 /// HIR typeck with unique unconstrained region inference variables.
90 ///
91 /// This is currently only used with by the new solver as it results in new
92 /// non-universal defining uses of opaque types, which is a breaking change.
93 /// See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
94Borrowck { defining_opaque_types: I::LocalDefIds },
95/// Any analysis after borrowck for a given body should be able to use all the
96 /// hidden types defined by borrowck, without being able to define any new ones.
97 ///
98 /// This is currently only used by the new solver, but should be implemented in
99 /// the old solver as well.
100PostBorrowckAnalysis { defined_opaque_types: I::LocalDefIds },
101/// After analysis, mostly during codegen and MIR optimizations, we're able to
102 /// reveal all opaque types. As the hidden type should *never* be observable
103 /// directly by the user, this should not be used by checks which may expose
104 /// such details to the user.
105 ///
106 /// There are some exceptions to this as for example `layout_of` and const-evaluation
107 /// always run in `PostAnalysis` mode, even when used during analysis. This exposes
108 /// some information about the underlying type to users, but not the type itself.
109PostAnalysis,
110}
111112/// We want to highly discourage using equality checks on typing modes.
113/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
114/// error. Only use `TypingModeEqWrapper` when you really really really have to.
115/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
116/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
117#[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)]118#[cfg_attr(
119 feature = "nightly",
120 derive(const _: () =
{
impl<I: Interner, __E: ::rustc_serialize::Encoder>
::rustc_serialize::Encodable<__E> for TypingModeEqWrapper<I> where
TypingMode<I>: ::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>: ::rustc_serialize::Decodable<__D> {
fn decode(__decoder: &mut __D) -> Self {
TypingModeEqWrapper(::rustc_serialize::Decodable::decode(__decoder))
}
}
};Decodable_NoContext, const _: () =
{
impl<I: Interner, __CTX>
::rustc_data_structures::stable_hasher::HashStable<__CTX> for
TypingModeEqWrapper<I> where
TypingMode<I>: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
{
#[inline]
fn hash_stable(&self, __hcx: &mut __CTX,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
TypingModeEqWrapper(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable_NoContext)
121)]
122pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I>);
123124impl<I: Interner> Hashfor TypingModeEqWrapper<I> {
125fn hash<H: Hasher>(&self, state: &mut H) {
126self.0.hash(state);
127 }
128}
129130impl<I: Interner> PartialEqfor TypingModeEqWrapper<I> {
131fn eq(&self, other: &Self) -> bool {
132match (self.0, other.0) {
133 (TypingMode::Coherence, TypingMode::Coherence) => true,
134 (
135 TypingMode::Analysis { defining_opaque_types_and_generators: l },
136 TypingMode::Analysis { defining_opaque_types_and_generators: r },
137 ) => l == r,
138 (
139 TypingMode::Borrowck { defining_opaque_types: l },
140 TypingMode::Borrowck { defining_opaque_types: r },
141 ) => l == r,
142 (
143 TypingMode::PostBorrowckAnalysis { defined_opaque_types: l },
144 TypingMode::PostBorrowckAnalysis { defined_opaque_types: r },
145 ) => l == r,
146 (TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
147 (
148 TypingMode::Coherence149 | TypingMode::Analysis { .. }
150 | TypingMode::Borrowck { .. }
151 | TypingMode::PostBorrowckAnalysis { .. }
152 | TypingMode::PostAnalysis,
153_,
154 ) => false,
155 }
156 }
157}
158159impl<I: Interner> Eqfor TypingModeEqWrapper<I> {}
160161impl<I: Interner> TypingMode<I> {
162/// There are a bunch of places in the compiler where we single out `Coherence`,
163 /// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
164 /// but not having this method leads to a bunch of noisy code.
165 ///
166 /// See also the documentation on [`TypingMode`] about exhaustive matching.
167pub fn is_coherence(&self) -> bool {
168match self {
169 TypingMode::Coherence => true,
170 TypingMode::Analysis { .. }
171 | TypingMode::Borrowck { .. }
172 | TypingMode::PostBorrowckAnalysis { .. }
173 | TypingMode::PostAnalysis => false,
174 }
175 }
176177/// Analysis outside of a body does not define any opaque types.
178pub fn non_body_analysis() -> TypingMode<I> {
179 TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
180 }
181182pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
183 TypingMode::Analysis {
184 defining_opaque_types_and_generators: cx185 .opaque_types_and_coroutines_defined_by(body_def_id),
186 }
187 }
188189/// While typechecking a body, we need to be able to define the opaque
190 /// types defined by that body.
191 ///
192 /// FIXME: This will be removed because it's generally not correct to define
193 /// opaques outside of HIR typeck.
194pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
195 TypingMode::Analysis {
196 defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
197 }
198 }
199200pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
201let defining_opaque_types = cx.opaque_types_defined_by(body_def_id);
202if defining_opaque_types.is_empty() {
203TypingMode::non_body_analysis()
204 } else {
205 TypingMode::Borrowck { defining_opaque_types }
206 }
207 }
208209pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
210let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
211if defined_opaque_types.is_empty() {
212TypingMode::non_body_analysis()
213 } else {
214 TypingMode::PostBorrowckAnalysis { defined_opaque_types }
215 }
216 }
217}
218219#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_infer_ctxt_like")]
220pub trait InferCtxtLike: Sized {
221type Interner: Interner;
222fn cx(&self) -> Self::Interner;
223224/// Whether the new trait solver is enabled. This only exists because rustc
225 /// shares code between the new and old trait solvers; for all other users,
226 /// this should always be true. If this is unknowingly false and you try to
227 /// use the new trait solver, things will break badly.
228fn next_trait_solver(&self) -> bool {
229true
230}
231232fn typing_mode(&self) -> TypingMode<Self::Interner>;
233234fn universe(&self) -> ty::UniverseIndex;
235fn create_next_universe(&self) -> ty::UniverseIndex;
236237fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
238fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex>;
239fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
240241fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
242fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
243fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
244245fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
246fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> <Self::Interner as Interner>::Ty;
247fn opportunistic_resolve_float_var(
248&self,
249 vid: ty::FloatVid,
250 ) -> <Self::Interner as Interner>::Ty;
251fn opportunistic_resolve_ct_var(
252&self,
253 vid: ty::ConstVid,
254 ) -> <Self::Interner as Interner>::Const;
255fn opportunistic_resolve_lt_var(
256&self,
257 vid: ty::RegionVid,
258 ) -> <Self::Interner as Interner>::Region;
259260fn is_changed_arg(&self, arg: <Self::Interner as Interner>::GenericArg) -> bool;
261262fn next_region_infer(&self) -> <Self::Interner as Interner>::Region;
263fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
264fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
265fn fresh_args_for_item(
266&self,
267 def_id: <Self::Interner as Interner>::DefId,
268 ) -> <Self::Interner as Interner>::GenericArgs;
269270fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
271&self,
272 value: ty::Binder<Self::Interner, T>,
273 ) -> T;
274275fn enter_forall<T: TypeFoldable<Self::Interner>, U>(
276&self,
277 value: ty::Binder<Self::Interner, T>,
278 f: impl FnOnce(T) -> U,
279 ) -> U;
280281fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
282fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
283fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
284fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
285fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
286287fn instantiate_ty_var_raw<R: PredicateEmittingRelation<Self>>(
288&self,
289 relation: &mut R,
290 target_is_expected: bool,
291 target_vid: ty::TyVid,
292 instantiation_variance: ty::Variance,
293 source_ty: <Self::Interner as Interner>::Ty,
294 ) -> RelateResult<Self::Interner, ()>;
295fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue);
296fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue);
297fn instantiate_const_var_raw<R: PredicateEmittingRelation<Self>>(
298&self,
299 relation: &mut R,
300 target_is_expected: bool,
301 target_vid: ty::ConstVid,
302 source_ct: <Self::Interner as Interner>::Const,
303 ) -> RelateResult<Self::Interner, ()>;
304305fn set_tainted_by_errors(&self, e: <Self::Interner as Interner>::ErrorGuaranteed);
306307fn shallow_resolve(
308&self,
309 ty: <Self::Interner as Interner>::Ty,
310 ) -> <Self::Interner as Interner>::Ty;
311fn shallow_resolve_const(
312&self,
313 ty: <Self::Interner as Interner>::Const,
314 ) -> <Self::Interner as Interner>::Const;
315316fn resolve_vars_if_possible<T>(&self, value: T) -> T
317where
318T: TypeFoldable<Self::Interner>;
319320fn probe<T>(&self, probe: impl FnOnce() -> T) -> T;
321322fn sub_regions(
323&self,
324 sub: <Self::Interner as Interner>::Region,
325 sup: <Self::Interner as Interner>::Region,
326 span: <Self::Interner as Interner>::Span,
327 );
328329fn equate_regions(
330&self,
331 a: <Self::Interner as Interner>::Region,
332 b: <Self::Interner as Interner>::Region,
333 span: <Self::Interner as Interner>::Span,
334 );
335336fn register_ty_outlives(
337&self,
338 ty: <Self::Interner as Interner>::Ty,
339 r: <Self::Interner as Interner>::Region,
340 span: <Self::Interner as Interner>::Span,
341 );
342343type OpaqueTypeStorageEntries: OpaqueTypeStorageEntries;
344fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries;
345fn clone_opaque_types_lookup_table(
346&self,
347 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
348fn clone_duplicate_opaque_types(
349&self,
350 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
351fn clone_opaque_types_added_since(
352&self,
353 prev_entries: Self::OpaqueTypeStorageEntries,
354 ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
355fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec<ty::AliasTy<Self::Interner>>;
356357fn register_hidden_type_in_storage(
358&self,
359 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
360 hidden_ty: <Self::Interner as Interner>::Ty,
361 span: <Self::Interner as Interner>::Span,
362 ) -> Option<<Self::Interner as Interner>::Ty>;
363fn add_duplicate_opaque_type(
364&self,
365 opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
366 hidden_ty: <Self::Interner as Interner>::Ty,
367 span: <Self::Interner as Interner>::Span,
368 );
369370fn reset_opaque_types(&self);
371}
372373pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
374 infcx: &'a Infcx,
375 param_env: I::ParamEnv,
376 symbol: I::Symbol,
377) -> bool378where
379Infcx: InferCtxtLike<Interner = I>,
380{
381// Iterate through all goals in param_env to find the one that has the same symbol.
382for pred in param_env.caller_bounds().iter() {
383if let ty::ClauseKind::UnstableFeature(sym) = pred.kind().skip_binder() {
384if sym == symbol {
385return true;
386 }
387 }
388 }
389390// During codegen we must assume that all feature bounds hold as we may be
391 // monomorphizing a body from an upstream crate which had an unstable feature
392 // enabled that we do not.
393 //
394 // Coherence should already report overlap errors involving unstable impls
395 // as the affected code would otherwise break when stabilizing this feature.
396 // It is also easily possible to accidentally cause unsoundness this way as
397 // we have to always enable unstable impls during codegen.
398 //
399 // Return ambiguity can also prevent people from writing code which depends on inference guidance
400 // that might no longer work after the impl is stabilised,
401 // tests/ui/unstable-feature-bound/unstable_impl_method_selection.rs is one of the example.
402 //
403 // Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
404 // if we are in std/core even if there is a corresponding `feature` attribute on the crate.
405406match infcx.typing_mode() {
407 TypingMode::Coherence408 | TypingMode::Analysis { .. }
409 | TypingMode::Borrowck { .. }
410 | TypingMode::PostBorrowckAnalysis { .. } => {
411infcx.cx().features().feature_bound_holds_in_crate(symbol)
412 }
413 TypingMode::PostAnalysis => true,
414 }
415}