# Type Alias rustc_middle::mir::statement::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§

    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(()),
        Subtype(()),
    }

## 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 indices are generated by slice patterns. Easiest to explain by example:

ⓘ

    [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`

index or -index (in Python terms), depending on from_end

§`min_length: u64`

The thing being indexed must be at least this long. For arrays this is always the exact length.

§`from_end: bool`

Counting backwards from end? This is 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]`.

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

§

### Subtype(())

A `Subtype(T)` projection is applied to any `StatementKind::Assign` where type of lvalue doesn’t match the type of rvalue, the primary goal is making subtyping explicit during optimizations and codegen.

This projection doesn’t impact the runtime behavior of the program except for potentially changing some type metadata of the interpreter or codegen backend.

This goal is achieved with mir_transform pass `Subtyper`, which runs right after borrowchecker, as we only care about subtyping that can affect trait selection and `TypeId`.

## 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: 24 bytes

Size for each variant:

- `Deref`: 0 bytes
- `Field`: 7 bytes
- `Index`: 0 bytes
- `ConstantIndex`: 23 bytes
- `Subslice`: 23 bytes
- `Downcast`: 11 bytes
- `OpaqueCast`: 0 bytes
- `Subtype`: 0 bytes