Enum rustc_type_ir::RegionKind

source ·
pub enum RegionKind<I: Interner> {
    ReEarlyParam(I::EarlyParamRegion),
    ReBound(DebruijnIndex, I::BoundRegion),
    ReLateParam(I::LateParamRegion),
    ReStatic,
    ReVar(I::InferRegion),
    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 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::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-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(I::InferRegion)

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: Interner> Clone for RegionKind<I>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<I: Interner> Debug for RegionKind<I>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<I: Interner> DebugWithInfcx<I> for RegionKind<I>

source§

fn fmt<Infcx: InferCtxtLike<Interner = I>>( this: WithInfcx<'_, Infcx, &Self>, f: &mut Formatter<'_> ) -> Result

source§

impl<I: Interner, __D: TyDecoder<I = I>> Decodable<__D> for RegionKind<I>

source§

fn decode(__decoder: &mut __D) -> Self

source§

impl<I: Interner, __E: TyEncoder<I = I>> Encodable<__E> for RegionKind<I>

source§

fn encode(&self, __encoder: &mut __E)

source§

impl<I: Interner> Hash for RegionKind<I>

source§

fn hash<__HI>(&self, __state: &mut __HI)
where __HI: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<CTX, I: Interner> HashStable<CTX> for RegionKind<I>

source§

fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher)

source§

impl<I: Interner> PartialEq for RegionKind<I>

source§

fn eq(&self, other: &RegionKind<I>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<I: Interner> Copy for RegionKind<I>

source§

impl<I: Interner> Eq for RegionKind<I>

Auto Trait Implementations§

§

impl<I> Freeze for RegionKind<I>

§

impl<I> RefUnwindSafe for RegionKind<I>

§

impl<I> Send for RegionKind<I>

§

impl<I> Sync for RegionKind<I>

§

impl<I> Unpin for RegionKind<I>

§

impl<I> UnwindSafe for RegionKind<I>

Blanket Implementations§

source§

impl<T> Aligned for T

source§

const ALIGN: Alignment = _

Alignment of Self.
source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, R> CollectAndApply<T, R> for T

source§

fn collect_and_apply<I, F>(iter: I, f: F) -> R
where I: Iterator<Item = T>, F: FnOnce(&[T]) -> R,

Equivalent to f(&iter.collect::<Vec<_>>()).

§

type Output = R

source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<'a, T> Captures<'a> for T
where 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.