pub(crate) type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
Aliased Type§
enum AbstractElem {
Deref,
Field(FieldIdx, AbstractType),
Index(AbstractOperand),
ConstantIndex {
offset: u64,
min_length: u64,
from_end: bool,
},
Subslice {
from: u64,
to: u64,
from_end: bool,
},
Downcast(Option<Symbol>, VariantIdx),
OpaqueCast(AbstractType),
Subtype(AbstractType),
}
Variants§
Deref
Field(FieldIdx, AbstractType)
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(AbstractOperand)
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
Subslice
These indices are generated by slice patterns.
If from_end
is true slice[from..slice.len() - to]
.
Otherwise array[from..to]
.
Fields
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(AbstractType)
Like an explicit cast from an opaque type to a concrete type, but without requiring an intermediate variable.
Subtype(AbstractType)
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 bytesField
: 7 bytesIndex
: 0 bytesConstantIndex
: 23 bytesSubslice
: 23 bytesDowncast
: 11 bytesOpaqueCast
: 0 bytesSubtype
: 0 bytes