Enum rustc_type_ir::region_kind::RegionKind
source · pub enum RegionKind<I: Interner> {
ReEarlyParam(I::EarlyParamRegion),
ReBound(DebruijnIndex, I::BoundRegion),
ReLateParam(I::LateParamRegion),
ReStatic,
ReVar(RegionVid),
RePlaceholder(I::PlaceholderRegion),
ReErased,
ReError(I::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
static ----------+-----...------+ (greatest)
| | |
param regions | |
| | |
| | |
| | |
empty(root) placeholder(U1) |
| / |
| / placeholder(Un)
empty(U1) -- /
| /
... /
| /
empty(Un) -------- (smallest)
Early-bound/free regions are the named lifetimes in scope from the function declaration. They have relationships to one another determined 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.
§Inference variables
During region inference, we sometimes create inference variables,
represented as 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 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. There are two kind of
bound regions: early-bound, which are bound in an item’s Generics
,
and are instantiated by an GenericArgs
, and late-bound, which are part of
higher-ranked types (e.g., for<'a> fn(&'a ())
), and are instantiated by
the likes of liberate_late_bound_regions
. The distinction exists
because higher-ranked lifetimes aren’t supported in all places. See 1.
Unlike Param
s, 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::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(DebruijnIndex, I::BoundRegion)
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::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-bound-params/early-late-bound-summary.html for more info about early and late bound lifetime parameters.
ReStatic
Static data that has an “infinite” lifetime. Top in the region lattice.
ReVar(RegionVid)
A region variable. Should not exist outside of type inference.
RePlaceholder(I::PlaceholderRegion)
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::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§impl<I: Interner> Debug for RegionKind<I>
impl<I: Interner> Debug for RegionKind<I>
source§impl<I: Interner, __D: TyDecoder<I = I>> Decodable<__D> for RegionKind<I>where
I::EarlyParamRegion: Decodable<__D>,
I::BoundRegion: Decodable<__D>,
I::LateParamRegion: Decodable<__D>,
I::PlaceholderRegion: Decodable<__D>,
I::ErrorGuaranteed: Decodable<__D>,
impl<I: Interner, __D: TyDecoder<I = I>> Decodable<__D> for RegionKind<I>where
I::EarlyParamRegion: Decodable<__D>,
I::BoundRegion: Decodable<__D>,
I::LateParamRegion: Decodable<__D>,
I::PlaceholderRegion: Decodable<__D>,
I::ErrorGuaranteed: Decodable<__D>,
source§impl<I: Interner, __E: TyEncoder<I = I>> Encodable<__E> for RegionKind<I>where
I::EarlyParamRegion: Encodable<__E>,
I::BoundRegion: Encodable<__E>,
I::LateParamRegion: Encodable<__E>,
I::PlaceholderRegion: Encodable<__E>,
I::ErrorGuaranteed: Encodable<__E>,
impl<I: Interner, __E: TyEncoder<I = I>> Encodable<__E> for RegionKind<I>where
I::EarlyParamRegion: Encodable<__E>,
I::BoundRegion: Encodable<__E>,
I::LateParamRegion: Encodable<__E>,
I::PlaceholderRegion: Encodable<__E>,
I::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: Interner> HashStable<CTX> for RegionKind<I>where
I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>,
I::LateParamRegion: HashStable<CTX>,
I::PlaceholderRegion: HashStable<CTX>,
impl<CTX, I: Interner> HashStable<CTX> for RegionKind<I>where
I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>,
I::LateParamRegion: HashStable<CTX>,
I::PlaceholderRegion: HashStable<CTX>,
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher)
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>::BoundRegion: DynSend,
<I as Interner>::LateParamRegion: DynSend,
<I as Interner>::PlaceholderRegion: DynSend,
<I as Interner>::ErrorGuaranteed: DynSend,
impl<I> DynSync for RegionKind<I>where
<I as Interner>::EarlyParamRegion: DynSync,
<I as Interner>::BoundRegion: DynSync,
<I as Interner>::LateParamRegion: DynSync,
<I as Interner>::PlaceholderRegion: DynSync,
<I as Interner>::ErrorGuaranteed: DynSync,
impl<I> Freeze for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Freeze,
<I as Interner>::BoundRegion: Freeze,
<I as Interner>::LateParamRegion: Freeze,
<I as Interner>::PlaceholderRegion: Freeze,
<I as Interner>::ErrorGuaranteed: Freeze,
impl<I> RefUnwindSafe for RegionKind<I>where
<I as Interner>::EarlyParamRegion: RefUnwindSafe,
<I as Interner>::BoundRegion: RefUnwindSafe,
<I as Interner>::LateParamRegion: RefUnwindSafe,
<I as Interner>::PlaceholderRegion: RefUnwindSafe,
<I as Interner>::ErrorGuaranteed: RefUnwindSafe,
impl<I> Send for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Send,
<I as Interner>::BoundRegion: Send,
<I as Interner>::LateParamRegion: Send,
<I as Interner>::PlaceholderRegion: Send,
<I as Interner>::ErrorGuaranteed: Send,
impl<I> Sync for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Sync,
<I as Interner>::BoundRegion: Sync,
<I as Interner>::LateParamRegion: Sync,
<I as Interner>::PlaceholderRegion: Sync,
<I as Interner>::ErrorGuaranteed: Sync,
impl<I> Unpin for RegionKind<I>where
<I as Interner>::EarlyParamRegion: Unpin,
<I as Interner>::BoundRegion: Unpin,
<I as Interner>::LateParamRegion: Unpin,
<I as Interner>::PlaceholderRegion: Unpin,
<I as Interner>::ErrorGuaranteed: Unpin,
impl<I> UnwindSafe for RegionKind<I>where
<I as Interner>::EarlyParamRegion: UnwindSafe,
<I as Interner>::BoundRegion: UnwindSafe,
<I as Interner>::LateParamRegion: UnwindSafe,
<I as Interner>::PlaceholderRegion: UnwindSafe,
<I as Interner>::ErrorGuaranteed: UnwindSafe,
Blanket Implementations§
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§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T> CloneToUninit for Twhere
T: Copy,
impl<T> CloneToUninit for Twhere
T: Copy,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
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<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<'a, T> Captures<'a> for Twhere
T: ?Sized,
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.