MIR
- Rust course
- Expert
- Lesson 2/46
- 4 min
Learn Mid-level IR (MIR) and its role in borrow checking.
MIR
MIR (Mid-level IR) turns the function into a control-flow graph: basic blocks, the jumps between them and simple statements in each block. The borrow checker, constant evaluation (const fn) and some optimizations run on MIR. Computing lifetimes from actual use points instead of lexical scope (NLL) also becomes possible here:
let mut v = vec![1];
let ilk = &v[0];
println!("{ilk}"); // last use of ilk
v.push(2); // NLL: the borrow is already over here
println!("{:?}", v);MIR can be seen with "Show MIR" on the Playground or with rustc --emit=mir.
Basic blocks
In MIR each function consists of basic blocks like bb0, bb1... Each block starts with straight-line statements and ends with a single terminator: goto, switchInt (branching), call, return, drop. Drop calls are placed explicitly at this stage too; that's why the compiler knows exactly where each value is dropped.
bb0: {
_2 = Len(_1);
_3 = Lt(const 0_usize, _2);
assert(move _3, "index out of bounds") -> bb1;
}Practice NLL example
Write the NLL example above: let mut v = vec![1];, take a reference to the first element and print it, then do v.push(2) and print the vector.
Starter code
fn main() {
// buraya yaz
}Sample solution
fn main() {
let mut v = vec![1];
let ilk = &v[0];
println!("{}", ilk);
v.push(2);
println!("{:?}", v);
}Expected output
1 [1, 2]
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Before NLL (non-lexical lifetimes), why wouldn't the code above compile?
- push didn't exist
- Vec didn't exist
- It would compile
- The borrow by ilk was considered to last until the end of its block Correct answer
Explanation: NLL, which came with the 2018 edition, ends borrows at their last use point in MIR.
2 MIR output
$ rustc --emit=____ main.rs
$ rustc --emit=mir main.rs
Explanation: --emit=mir writes the compiler's MIR output to a file.
3 MIR concept and meaning
| Term | Meaning |
|---|---|
bb0 |
Basic block |
switchInt |
Branching |
drop(_1) |
Explicit drop |
NLL |
Lifetime by use |