Skip to main content

## ProjectionKind

# Type Alias ProjectionKind

Source

    pub type ProjectionKind = ProjectionElem<(), ()>;

Expand description

Alias for projections as they appear in `UserTypeProjection`, where we need neither the `V` parameter for `Index` nor the `T` for `Field`.

## Aliased Type§

    pub enum ProjectionKind {
        Deref,
        Field(FieldIdx, ()),
        Index(()),
        ConstantIndex {
            offset: u64,
            min_length: u64,
            from_end: bool,
        },
        Subslice {
            from: u64,
            to: u64,
            from_end: bool,
        },
        Downcast(Option<Symbol>, VariantIdx),
        OpaqueCast(()),
        UnwrapUnsafeBinder(()),
    }

## Variants§

§

### Deref

§

### Field(FieldIdx, ())

A field (e.g., `f` in `_1.f`) is one variant of `ProjectionElem`. Conceptually, rustc can identify that a field projection refers to either two different regions of memory or the same one between the base and the ‘projection element’. Read more about projections in the rustc-dev-guide

§

### Index(())

Index into a slice/array.

Note that this does not also dereference, and so it does not exactly correspond to slice indexing in Rust. In other words, in the below Rust code:

    let x = &[1, 2, 3, 4];
    let i = 2;
    x[i];

The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same thing is true of the `ConstantIndex` and `Subslice` projections below.

§

### ConstantIndex

These endpoint-relative indices are generated by slice/array patterns.

For array types, `offset` is always relative to the start of the array. For slice types, `from_end` determines whether `offset` is relative to the start or the end of the slice being inspected.

Slice-pattern indices are easiest to explain by the position of `X` in these examples:

ⓘ

    [X, _, .., _, _] => { offset: 0, min_length: 4, from_end: false },
    [_, X, .., _, _] => { offset: 1, min_length: 4, from_end: false },
    [_, _, .., X, _] => { offset: 2, min_length: 4, from_end: true },
    [_, _, .., _, X] => { offset: 1, min_length: 4, from_end: true },

#### Fields

§`offset: u64`

- If `from_end == false`, this is a 0-based offset from the start of the array/slice.
- If `from_end == true`, this is a 1-based offset from the end of the slice.

§`min_length: u64`

The thing being indexed must be at least this long – otherwise, the projection is UB.

For arrays this is always the exact length.

§`from_end: bool`

If `true`, `offset` is a 1-based offset from the end of the slice. Always false when indexing an array.

§

### Subslice

These indices are generated by slice patterns.

If `from_end` is true `slice[from..slice.len() - to]`. Otherwise `array[from..to]`.

This projection cannot have `ConstantIndex` or additional `Subslice` projections after it before runtime MIR.

#### Fields

§`from: u64`
§`to: u64`
§`from_end: bool`

Whether `to` counts from the start or end of the array/slice. For `PlaceElem`s this is `true` if and only if the base is a slice. For `ProjectionKind`, this can also be `true` for arrays.

§

### Downcast(Option<Symbol>, VariantIdx)

“Downcast” to a variant of an enum or a coroutine.

The included Symbol is the name of the variant, used for printing MIR.

This operation itself is never UB, all it does is change the type of the place.

§

### OpaqueCast(())

Like an explicit cast from an opaque type to a concrete type, but without requiring an intermediate variable.

This is unused with `-Znext-solver`.

§

### UnwrapUnsafeBinder(())

A transmute from an unsafe binder to the type that it wraps. This is a projection of a place, so it doesn’t necessarily constitute a move out of the binder.

## 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.