pub enum RegionKind<I>where
I: Interner,{
ReEarlyParam(<I as Interner>::EarlyParamRegion),
ReBound(BoundVarIndexKind, BoundRegion<I>),
ReLateParam(<I as Interner>::LateParamRegion),
ReStatic,
ReVar(RegionVid),
RePlaceholder(Placeholder<I, BoundRegion<I>>),
ReErased,
ReError(<I as Interner>::ErrorGuaranteed),
}Expand description
Representation of regions. Note that the NLL checker uses a distinct
representation of regions. For this reason, it internally replaces all the
regions with inference variables – the index of the variable is then used
to index into internal NLL data structures. See rustc_const_eval::borrow_check
module for more information.
Note: operations are on the wrapper Region type, which is interned,
rather than this type.
§The Region lattice within a given function
In general, the region lattice looks like
empty(Un) -------- (smallest)
| \
... \
| \
empty(U1) -- \
| \ placeholder(Un)
| \ |
empty(root) placeholder(U1) |
| | |
| | |
| | |
param regions | |
| | |
static ----------+-----...------+ (greatest)Lifetimes in scope from a function declaration are represented via
RegionKind::ReEarlyParam/RegionKind::ReLateParam. They
have relationships to one another and 'static based on the
declared relationships from the function.
Note that inference variables and bound regions are not included in this diagram. In the case of inference variables, they should be inferred to some other region from the diagram. In the case of bound regions, they are excluded because they don’t make sense to include – the diagram indicates the relationship between free regions.
You can read more about the distinction between early and late bound parameters in the rustc dev guide: Early vs Late bound parameters.
A note on subtyping: If we assume that references take their region
covariantly, and use that to define the subtyping relationship of regions,
it may be somewhat surprising that 'empty is Top and 'static is Bottom,
and that “'a is a subtype of 'b” is defined as “'a is bigger than
'b” - good to keep in mind.
§Inference variables
During region inference, we sometimes create inference variables,
represented as RegionKind::ReVar. These will be inferred by
the code in infer::lexical_region_resolve to some free region
from the lattice above (the minimal region that meets the
constraints).
During NLL checking, where regions are defined differently, we
also use RegionKind::ReVar – in that case, the index is used
to index into the NLL region checker’s data structures. The
variable may in fact represent either a free region or an
inference variable, in that case.
§Bound Regions
These are regions that are stored behind a binder and must be instantiated
with some concrete region before being used. A type can be wrapped in a
Binder, which introduces new type/const/lifetime variables (e.g., for<'a> fn(&'a ())). These parameters are referred to via RegionKind::ReBound.
You can instantiate them by the likes of liberate_late_bound_regions.
Unlike Params, bound regions are not supposed to exist “in the wild”
outside their binder, e.g., in types passed to type inference, and
should first be instantiated (by placeholder regions, free regions,
or region variables).
§Placeholder and Free Regions
One often wants to work with bound regions without knowing their precise identity. For example, when checking a function, the lifetime of a borrow can end up being assigned to some region parameter. In these cases, it must be ensured that bounds on the region can’t be accidentally assumed without being checked.
To do this, we replace the bound regions with placeholder markers, which don’t satisfy any relation not explicitly provided.
There are two kinds of placeholder regions in rustc: ReLateParam and
RePlaceholder. When checking an item’s body, ReLateParam is supposed
to be used. These also support explicit bounds: both the internally-stored
scope, which the region is assumed to outlive, as well as other
relations stored in the FreeRegionMap. Note that these relations
aren’t checked when you make_subregion (or eq_types), only by
resolve_regions_and_report_errors.
When working with higher-ranked types, some region relations aren’t
yet known, so you can’t just call resolve_regions_and_report_errors.
RePlaceholder is designed for this purpose. In these contexts,
there’s also the risk that some inference variable laying around will
get unified with your placeholder region: if you want to check whether
for<'a> Foo<'_>: 'a, and you instantiate your bound region 'a
with a placeholder region '%a, the variable '_ would just be
instantiated to the placeholder region '%a, which is wrong because
the inference variable is supposed to satisfy the relation
for every value of the placeholder region. To ensure that doesn’t
happen, you can use leak_check. This is more clearly explained
by the rustc dev guide.
Variants§
ReEarlyParam(<I as Interner>::EarlyParamRegion)
A region parameter; for example 'a in impl<'a> Trait for &'a ().
There are some important differences between region and type parameters.
Not all region parameters in the source are represented via ReEarlyParam:
late-bound function parameters are instead lowered to a ReBound. Late-bound
regions get eagerly replaced with ReLateParam which behaves in the same way as
ReEarlyParam. Region parameters are also sometimes implicit,
e.g. in impl Trait for &().
ReBound(BoundVarIndexKind, BoundRegion<I>)
A higher-ranked region. These represent either late-bound function parameters
or bound variables from a for<'a>-binder.
While inside of a function, e.g. during typeck, the late-bound function parameters
can be converted to ReLateParam by calling tcx.liberate_late_bound_regions.
Bound regions inside of types must not be erased, as they impact trait
selection and the TypeId of that type. for<'a> fn(&'a ()) and
fn(&'static ()) are different types and have to be treated as such.
ReLateParam(<I as Interner>::LateParamRegion)
Late-bound function parameters are represented using a ReBound. When
inside of a function, we convert these bound variables to placeholder
parameters via tcx.liberate_late_bound_regions. They are then treated
the same way as ReEarlyParam while inside of the function.
See https://rustc-dev-guide.rust-lang.org/early_late_parameters.html for more info about early and late bound lifetime parameters.
ReStatic
Static data that has an “infinite” lifetime. Bottom in the region lattice.
ReVar(RegionVid)
A region variable. Should not exist outside of type inference.
RePlaceholder(Placeholder<I, BoundRegion<I>>)
A placeholder region – the higher-ranked version of ReLateParam.
Should not exist outside of type inference.
Used when instantiating a forall binder via infcx.enter_forall.
ReErased
Erased region, used by trait selection, in MIR and during codegen.
ReError(<I as Interner>::ErrorGuaranteed)
A region that resulted from some other error. Used exclusively for diagnostics.
Trait Implementations§
Source§impl<I> Clone for RegionKind<I>where
I: Interner,
impl<I> Clone for RegionKind<I>where
I: Interner,
Source§fn clone(&self) -> RegionKind<I>
fn clone(&self) -> RegionKind<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 RegionKind<I>where
I: Interner,
impl<I> Debug for RegionKind<I>where
I: Interner,
Source§impl<I, __D> Decodable<__D> for RegionKind<I>where
I: Interner,
__D: Decoder,
<I as Interner>::EarlyParamRegion: Decodable<__D>,
BoundRegion<I>: Decodable<__D>,
<I as Interner>::LateParamRegion: Decodable<__D>,
Placeholder<I, BoundRegion<I>>: Decodable<__D>,
<I as Interner>::ErrorGuaranteed: Decodable<__D>,
impl<I, __D> Decodable<__D> for RegionKind<I>where
I: Interner,
__D: Decoder,
<I as Interner>::EarlyParamRegion: Decodable<__D>,
BoundRegion<I>: Decodable<__D>,
<I as Interner>::LateParamRegion: Decodable<__D>,
Placeholder<I, BoundRegion<I>>: Decodable<__D>,
<I as Interner>::ErrorGuaranteed: Decodable<__D>,
fn decode(__decoder: &mut __D) -> RegionKind<I>
Source§impl<I, __E> Encodable<__E> for RegionKind<I>where
I: Interner,
__E: Encoder,
<I as Interner>::EarlyParamRegion: Encodable<__E>,
BoundRegion<I>: Encodable<__E>,
<I as Interner>::LateParamRegion: Encodable<__E>,
Placeholder<I, BoundRegion<I>>: Encodable<__E>,
<I as Interner>::ErrorGuaranteed: Encodable<__E>,
impl<I, __E> Encodable<__E> for RegionKind<I>where
I: Interner,
__E: Encoder,
<I as Interner>::EarlyParamRegion: Encodable<__E>,
BoundRegion<I>: Encodable<__E>,
<I as Interner>::LateParamRegion: Encodable<__E>,
Placeholder<I, BoundRegion<I>>: Encodable<__E>,
<I as Interner>::ErrorGuaranteed: Encodable<__E>,
Source§impl<I> Hash for RegionKind<I>where
I: Interner,
impl<I> Hash for RegionKind<I>where
I: Interner,
Source§impl<CTX, I> HashStable<CTX> for RegionKind<I>where
I: Interner,
<I as Interner>::EarlyParamRegion: HashStable<CTX>,
<I as Interner>::LateParamRegion: HashStable<CTX>,
<I as Interner>::DefId: HashStable<CTX>,
<I as Interner>::Symbol: HashStable<CTX>,
Available on crate feature nightly only.
impl<CTX, I> HashStable<CTX> for RegionKind<I>where
I: Interner,
<I as Interner>::EarlyParamRegion: HashStable<CTX>,
<I as Interner>::LateParamRegion: HashStable<CTX>,
<I as Interner>::DefId: HashStable<CTX>,
<I as Interner>::Symbol: HashStable<CTX>,
nightly only.fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher<SipHasher128>)
Source§impl<I> PartialEq for RegionKind<I>where
I: Interner,
impl<I> PartialEq for RegionKind<I>where
I: Interner,
impl<I> Copy for RegionKind<I>where
I: Interner,
impl<I> Eq for RegionKind<I>where
I: Interner,
Auto Trait Implementations§
impl<I> DynSend for RegionKind<I>where
<I as Interner>::EarlyParamRegion: DynSend,
<I as Interner>::LateParamRegion: DynSend,
<I as Interner>::ErrorGuaranteed: DynSend,
<I as Interner>::Symbol: DynSend,
<I as Interner>::DefId: DynSend,
impl<I> DynSync for RegionKind<I>where
<I as Interner>::EarlyParamRegion: DynSync,
<I as Interner>::LateParamRegion: DynSync,
<I as Interner>::ErrorGuaranteed: DynSync,
<I as Interner>::Symbol: DynSync,
<I as Interner>::DefId: DynSync,
impl<I> Freeze for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Freeze,
<I as Interner>::LateParamRegion: Freeze,
<I as Interner>::ErrorGuaranteed: Freeze,
<I as Interner>::Symbol: Freeze,
<I as Interner>::DefId: Freeze,
impl<I> RefUnwindSafe for RegionKind<I>where
<I as Interner>::EarlyParamRegion: RefUnwindSafe,
<I as Interner>::LateParamRegion: RefUnwindSafe,
<I as Interner>::ErrorGuaranteed: RefUnwindSafe,
<I as Interner>::Symbol: RefUnwindSafe,
<I as Interner>::DefId: RefUnwindSafe,
impl<I> Send for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Send,
<I as Interner>::LateParamRegion: Send,
<I as Interner>::ErrorGuaranteed: Send,
<I as Interner>::Symbol: Send,
<I as Interner>::DefId: Send,
impl<I> Sync for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Sync,
<I as Interner>::LateParamRegion: Sync,
<I as Interner>::ErrorGuaranteed: Sync,
<I as Interner>::Symbol: Sync,
<I as Interner>::DefId: Sync,
impl<I> Unpin for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Unpin,
<I as Interner>::LateParamRegion: Unpin,
<I as Interner>::ErrorGuaranteed: Unpin,
<I as Interner>::Symbol: Unpin,
<I as Interner>::DefId: Unpin,
impl<I> UnsafeUnpin for RegionKind<I>where
<I as Interner>::EarlyParamRegion: UnsafeUnpin,
<I as Interner>::LateParamRegion: UnsafeUnpin,
<I as Interner>::ErrorGuaranteed: UnsafeUnpin,
<I as Interner>::Symbol: UnsafeUnpin,
<I as Interner>::DefId: UnsafeUnpin,
impl<I> UnwindSafe for RegionKind<I>where
<I as Interner>::EarlyParamRegion: UnwindSafe,
<I as Interner>::LateParamRegion: UnwindSafe,
<I as Interner>::ErrorGuaranteed: UnwindSafe,
<I as Interner>::Symbol: UnwindSafe,
<I as Interner>::DefId: UnwindSafe,
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.default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String
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<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.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.