_3 = &mut _1;
_2 = const <std::vec::Vec<T>>::push(move _3, const 1i32) -> [return: bb3, unwind: bb4];
}
```
Here there are two statements: another `StorageLive`, introducing the `_3`
temporary, and then an assignment:
```mir
_3 = &mut _1;
```
Assignments in general have the form:
```text
<Place> = <Rvalue>
```
A place is an expression like `_3`, `_3.f` or `*_3` – it denotes a
location in memory. An **Rvalue** is an expression that creates a
value: in this case, the rvalue is a mutable borrow expression, which
looks like `&mut <Place>`. So we can kind of define a grammar for
rvalues like so:
```text
<Rvalue> = & (mut)? <Place>
| <Operand> + <Operand>
| <Operand> - <Operand>
| ...
<Operand> = Constant
| copy Place
| move Place
```
As you can see from this grammar, rvalues cannot be nested – they can
only reference places and constants. Moreover, when you use a place,
we indicate whether we are **copying it** (which requires that the
place have a type `T` where `T: Copy`) or **moving it** (which works
for a place of any type). So, for example, if we had the expression `x
= a + b + c` in Rust, that would get compiled to two statements and a
temporary:
```mir
TMP1 = a + b
x = TMP1 + c
```
([Try it and see][play-abc], though you may want to do release mode to skip
over the overflow checks.)
## MIR data types
The MIR data types are defined in the [`compiler/rustc_middle/src/mir/`][mir]
module. Each of the key concepts mentioned in the previous section
maps in a fairly straightforward way to a Rust type.
The main MIR data type is [`Body`]. It contains the data for a single
function (along with sub-instances of Mir for "promoted constants",
but [you can read about those below](#promoted)).
- **Basic blocks**: The basic blocks are stored in the field
[`Body::basic_blocks`][basicblocks]; this is a vector
of [`BasicBlockData`] structures. Nobody ever references a
basic block directly: instead, we pass around [`BasicBlock`]
values, which are [newtype'd] indices into this vector.
- **Statements** are represented by the type [`Statement`].
- **Terminators** are represented by the [`Terminator`].
- **Locals** are represented by a [newtype'd] index type [`Local`].
The data for a local variable is found in the
[`Body::local_decls`][localdecls] vector. There is also a special constant
[`RETURN_PLACE`] identifying the special "local" representing the return value.
- **Places** are identified by the struct [`Place`]. There are a few
fields:
- Local variables like `_1`
- **Projections**, which are fields or other things that "project
out" from a base place. These are represented by the [newtype'd] type
[`ProjectionElem`]. So e.g. the place `_1.f` is a projection,
with `f` being the "projection element" and `_1` being the base
path. `*_1` is also a projection, with the `*` being represented
by the [`ProjectionElem::Deref`] element.
- **Rvalues** are represented by the enum [`Rvalue`].
- **Operands** are represented by the enum [`Operand`].
## Representing constants
When code has reached the MIR stage, constants can generally come in two forms:
*MIR constants* ([`mir::Constant`]) and *type system constants* ([`ty::Const`]).
MIR constants are used as operands: in `x + CONST`, `CONST` is a MIR constant;
similarly, in `x + 2`, `2` is a MIR constant. Type system constants are used in
the type system, in particular for array lengths but also for const generics.
Generally, both kinds of constants can be "unevaluated" or "already evaluated".