CodeBlanks Logo Icon CodeBlanks

MIR

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

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
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

Question
$ rustc --emit=____ main.rs
Answer
$ 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

All lessons in Expert