pub enum TypingMode<I>where
I: Interner,{
Coherence,
Analysis {
defining_opaque_types_and_generators: <I as Interner>::LocalDefIds,
},
Borrowck {
defining_opaque_types: <I as Interner>::LocalDefIds,
},
PostBorrowckAnalysis {
defined_opaque_types: <I as Interner>::LocalDefIds,
},
PostAnalysis,
}Expand description
The current typing mode of an inference context. We unfortunately have some slightly different typing rules depending on the current context. See the doc comment for each variant for how and why they are used.
In most cases you can get the correct typing mode automatically via:
mir::Body::typing_moderustc_lint::LateContext::typing_mode
If neither of these functions are available, feel free to reach out to t-types for help.
Because typing rules get subtly different based on what typing mode we’re in, subtle enough that changing the behavior of typing modes can sometimes cause changes that we don’t even have tests for, we’d like to enforce the rule that any place where we specialize behavior based on the typing mode, we match exhaustively on the typing mode. That way, it’s easy to determine all the places that must change when anything about typing modes changes.
Hence, TypingMode does not implement Eq, though TypingModeEqWrapper is available
in the rare case that you do need this. Most cases where this currently matters is
where we pass typing modes through the query system and want to cache based on it.
See also #[rustc_must_match_exhaustively], which tries to detect non-exhaustive
matches.
Since matching on typing mode to single out Coherence is so common, and Coherence
is so different from the other modes: see also is_coherence
Variants§
Coherence
When checking whether impls overlap, we check whether any obligations are guaranteed to never hold when unifying the impls. This requires us to be complete: we must never fail to prove something which may actually hold.
In this typing mode we bail with ambiguity in case its not knowable whether a trait goal may hold, e.g. because the trait may get implemented in a downstream or sibling crate.
We also have to be careful when generalizing aliases inside of higher-ranked types to not unnecessarily constrain any inference variables.
Analysis
Analysis includes type inference, checking that items are well-formed, and pretty much everything else which may emit proper type errors to the user.
We only normalize opaque types which may get defined by the current body,
which are stored in defining_opaque_types.
We also refuse to project any associated type that is marked default.
Non-default (“final”) types are always projected. This is necessary in
general for soundness of specialization. However, we could allow projections
in fully-monomorphic cases. We choose not to, because we prefer for default type
to force the type definition to be treated abstractly by any consumers of the
impl. Concretely, that means that the following example will
fail to compile:
#![feature(specialization)]
trait Assoc {
type Output;
}
impl<T> Assoc for T {
default type Output = bool;
}
fn main() {
let x: <() as Assoc>::Output = true;
}Fields
defining_opaque_types_and_generators: <I as Interner>::LocalDefIdsBorrowck
The behavior during MIR borrowck is identical to TypingMode::Analysis
except that the initial value for opaque types is the type computed during
HIR typeck with unique unconstrained region inference variables.
This is currently only used with by the new solver as it results in new non-universal defining uses of opaque types, which is a breaking change. See tests/ui/impl-trait/non-defining-use/as-projection-term.rs.
Fields
defining_opaque_types: <I as Interner>::LocalDefIdsPostBorrowckAnalysis
Any analysis after borrowck for a given body should be able to use all the hidden types defined by borrowck, without being able to define any new ones.
This is currently only used by the new solver, but should be implemented in the old solver as well.
Fields
defined_opaque_types: <I as Interner>::LocalDefIdsPostAnalysis
After analysis, mostly during codegen and MIR optimizations, we’re able to reveal all opaque types. As the hidden type should never be observable directly by the user, this should not be used by checks which may expose such details to the user.
There are some exceptions to this as for example layout_of and const-evaluation
always run in PostAnalysis mode, even when used during analysis. This exposes
some information about the underlying type to users, but not the type itself.
Implementations§
Source§impl<I> TypingMode<I>where
I: Interner,
impl<I> TypingMode<I>where
I: Interner,
Sourcepub fn is_coherence(&self) -> bool
pub fn is_coherence(&self) -> bool
There are a bunch of places in the compiler where we single out Coherence,
and alter behavior. We’d like to always match on TypingMode exhaustively,
but not having this method leads to a bunch of noisy code.
See also the documentation on TypingMode about exhaustive matching.
Sourcepub fn non_body_analysis() -> TypingMode<I>
pub fn non_body_analysis() -> TypingMode<I>
Analysis outside of a body does not define any opaque types.
pub fn typeck_for_body( cx: I, body_def_id: <I as Interner>::LocalDefId, ) -> TypingMode<I>
Sourcepub fn analysis_in_body(
cx: I,
body_def_id: <I as Interner>::LocalDefId,
) -> TypingMode<I>
pub fn analysis_in_body( cx: I, body_def_id: <I as Interner>::LocalDefId, ) -> TypingMode<I>
While typechecking a body, we need to be able to define the opaque types defined by that body.
FIXME: This will be removed because it’s generally not correct to define opaques outside of HIR typeck.
pub fn borrowck( cx: I, body_def_id: <I as Interner>::LocalDefId, ) -> TypingMode<I>
pub fn post_borrowck_analysis( cx: I, body_def_id: <I as Interner>::LocalDefId, ) -> TypingMode<I>
Trait Implementations§
Source§impl<I> Clone for TypingMode<I>where
I: Interner,
impl<I> Clone for TypingMode<I>where
I: Interner,
Source§fn clone(&self) -> TypingMode<I>
fn clone(&self) -> TypingMode<I>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<I> Debug for TypingMode<I>where
I: Interner,
impl<I> Debug for TypingMode<I>where
I: Interner,
Source§impl<I, __D> Decodable<__D> for TypingMode<I>
impl<I, __D> Decodable<__D> for TypingMode<I>
fn decode(__decoder: &mut __D) -> TypingMode<I>
Source§impl<I, __E> Encodable<__E> for TypingMode<I>
impl<I, __E> Encodable<__E> for TypingMode<I>
Source§impl<I> Hash for TypingMode<I>where
I: Interner,
impl<I> Hash for TypingMode<I>where
I: Interner,
Source§impl<I, __CTX> HashStable<__CTX> for TypingMode<I>
impl<I, __CTX> HashStable<__CTX> for TypingMode<I>
fn hash_stable( &self, __hcx: &mut __CTX, __hasher: &mut StableHasher<SipHasher128>, )
impl<I> Copy for TypingMode<I>where
I: Interner,
Auto Trait Implementations§
impl<I> DynSend for TypingMode<I>
impl<I> DynSync for TypingMode<I>
impl<I> Freeze for TypingMode<I>
impl<I> RefUnwindSafe for TypingMode<I>
impl<I> Send for TypingMode<I>
impl<I> Sync for TypingMode<I>
impl<I> Unpin for TypingMode<I>
impl<I> UnsafeUnpin for TypingMode<I>
impl<I> UnwindSafe for TypingMode<I>
Blanket Implementations§
Source§impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut T
fn allocate_from_iter( arena: &'tcx Arena<'tcx>, iter: impl IntoIterator<Item = T>, ) -> &'tcx mut [T]
Source§impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
impl<'tcx, T> ArenaAllocatable<'tcx, IsCopy> for Twhere
T: Copy,
fn allocate_on(self, arena: &'tcx Arena<'tcx>) -> &'tcx mut T
fn allocate_from_iter( arena: &'tcx Arena<'tcx>, iter: impl IntoIterator<Item = T>, ) -> &'tcx mut [T]
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
Source§impl<'tcx, T> DepNodeKey<'tcx> for T
impl<'tcx, T> DepNodeKey<'tcx> for T
default fn key_fingerprint_style() -> KeyFingerprintStyle
Source§default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint
default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint
Fingerprint to be used
in DepNode.Source§default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<T>
default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<T>
DepNode,
something which is needed when forcing DepNodes during red-green
evaluation. The query system will only call this method if
fingerprint_style() is not FingerprintStyle::Opaque.
It is always valid to return None here, in which case incremental
compilation will treat the query as having changed instead of forcing it.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<K> IntoQueryKey<K> for K
impl<K> IntoQueryKey<K> for K
Source§fn into_query_key(self) -> K
fn into_query_key(self) -> K
Self to K.
This should always be a very cheap conversion, e.g. LocalDefId::to_def_id.Source§impl<T> MaybeResult<T> for T
impl<T> MaybeResult<T> for T
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
Source§impl<I, T> UpcastFrom<I, T> for T
impl<I, T> UpcastFrom<I, T> for T
fn upcast_from(from: T, _tcx: I) -> T
Source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
Source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
Source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<T> ErasedDestructor for Twhere
T: 'static,
Layout§
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.