pub enum RegionKind {
    ReEarlyBound(EarlyBoundRegion),
    ReLateBound(DebruijnIndexBoundRegion),
    ReFree(FreeRegion),
    ReStatic,
    ReVar(RegionVid),
    RePlaceholder(PlaceholderRegion),
    ReEmpty(UniverseIndex),
    ReErased,
}
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)
|                |              |
early-bound and  |              |
free 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 substituted 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 substituted by an InternalSubsts, and late-bound, which are part of higher-ranked types (e.g., for<'a> fn(&'a ())), and are substituted 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 substituted (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: ReFree and RePlaceholder. When checking an item’s body, ReFree 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 substitute 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

ReEarlyBound(EarlyBoundRegion)

Region bound in a type or fn declaration which will be substituted ‘early’ – that is, at the same time when type parameters are substituted.

ReLateBound(DebruijnIndexBoundRegion)

Region bound in a function scope, which will be substituted when the function is called.

ReFree(FreeRegion)

When checking a function body, the types of all arguments and so forth that refer to bound region parameters are modified to refer to free region 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(PlaceholderRegion)

A placeholder region – basically, the higher-ranked version of ReFree. Should not exist outside of type inference.

ReEmpty(UniverseIndex)

Empty lifetime is for data that is never accessed. We tag the empty lifetime with a universe – the idea is that we don’t want exists<'a> { forall<'b> { 'b: 'a } } to be satisfiable. Therefore, the 'empty in a universe U is less than all regions visible from U, but not less than regions not visible from U.

ReErased

Erased region, used by trait selection, in MIR and during codegen.

Trait Implementations

Immutably borrows from an owned value. Read more

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Feeds this value into the given Hasher. Read more

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

This method returns an Ordering between self and other. Read more

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method returns an ordering between self and other values if one exists. Read more

This method tests less than (for self and other) and is used by the < operator. Read more

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

This method tests greater than (for self and other) and is used by the > operator. Read more

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

This method turns the parameters of a DepNodeConstructor into an opaque Fingerprint to be used in DepNode. Not all DepNodeParams support being turned into a Fingerprint (they don’t need to if the corresponding DepNode is anonymous). Read more

This method tries to recover the query key from the given 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. Read more

Returns the argument unchanged.

Calls U::from(self).

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

The resulting type after obtaining ownership.

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

🔬 This is a nightly-only experimental API. (toowned_clone_into)

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

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

Layout

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference’s “Type Layout” chapter for details on type layout guarantees.

Size: 28 bytes

Size for each variant:

  • ReEarlyBound: 16 bytes
  • ReLateBound: 24 bytes
  • ReFree: 24 bytes
  • ReStatic: 0 bytes
  • ReVar: 4 bytes
  • RePlaceholder: 20 bytes
  • ReEmpty: 4 bytes
  • ReErased: 0 bytes