Learn Rust With Entirely Too Many Linked Lists
31

Miri

Miri is a Rust interpreter for MIR — the compiler's mid-level IR. It runs your program's tests one MIR statement at a time, with full provenance tracking, and screams the moment you violate the abstract machine. It's the only tool that will catch the bug from the previous section.

  1. Miri ships as a rustup component on the nightly toolchain. Install once, then cargo +nightly miri test runs your test suite under Miri. It is slow — expect 50–500x slowdown — but it is exhaustive.
    $ rustup toolchain install nightly
    $ rustup +nightly component add miri
    $ cargo +nightly miri test
  2. Run it against the previous section's queue. Miri flags the first deref of self.tail after the box has been moved, with a stacked-borrows trace pointing at the offending tag.
    error: Undefined Behavior: trying to retag from <1234> for SharedReadWrite
      permission, but that tag does not exist in the borrow stack for this location
      --> src/lib.rs:23:13
       |
    23 |   unsafe { (*self.tail).next = Some(new_node); }
       |            ^^^^^^^^^^^^^^^^
       |            |
       |            trying to retag from <1234> for SharedReadWrite permission
       |            <1234> was created by a SharedReadWrite retag at offsets [0..24]
       = help: this indicates a potential bug in the program: it performed an
               invalid operation, but the rules it violated are still experimental
  3. Miri does not just run on tests — it runs on any binary or example. Use MIRIFLAGS="-Zmiri-tree-borrows" to switch from stacked borrows to the newer tree-borrows model; some programs that fail under stacked borrows pass under tree borrows and vice versa. The lesson: write code that satisfies both.
    $ cargo +nightly miri test                            # stacked borrows (default)
    $ MIRIFLAGS="-Zmiri-tree-borrows" cargo +nightly miri test  # tree borrows