Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Rust’s Mid-level Intermediate Representation (MIR) makes a function easier to inspect as a control-flow graph: basic blocks show where execution can go, while locals, places and rvalues show where values live and how they are produced. Learning to read those pieces helps explain how rustc reasons about moves, initialization and borrows—and gives you a view between Rust source and generated code.
What MIR represents
The Rust Compiler Development Guide calls MIR “Rust’s Mid-level Intermediate Representation.” rustc constructs it from HIR, an earlier representation of the program, in a form that is simpler than Rust’s source syntax. MIR has three especially useful characteristics: it is organized around control flow, it does not use nested expressions in the same way source code does, and types are explicit.
As an Amazon Associate I earn from qualifying purchases.
That simplification is deliberate. Compiler analyses and transformations can work with explicit operations and paths through a function instead of having to reason directly about every surface feature of Rust syntax. MIR is an implementation view of rustc, not a stable language contract; its details and debugging output can change between compiler releases.
Start with the control-flow graph
Basic blocks and terminators
A MIR function is divided into basic blocks. Each block contains statements followed by a terminator. A statement performs an action and continues to the next statement in that block; the terminator ends the block and determines what happens next. A terminator may transfer control to one successor or choose among several, making branches and other control transfers explicit.
#1 Best Overall
When you inspect a block, find its terminator first. It tells you which block or blocks can follow. Then read the statements above it to see what the current path changes before control moves on. This avoids treating the listing as a flat sequence when it actually describes a graph.
Locals, places and rvalues
MIR uses indexed locals as storage locations. Names such as _1 refer to locals, and _0 is used for a function’s return value. A place identifies a location that can be read or written. It can include a projection into a value, such as _1.f, which refers to a field of the local _1.
An rvalue is an expression that produces a value. In a MIR assignment, the place on the left identifies where the result goes; the rvalue on the right describes what produces it. Keeping those roles distinct is key: a place answers “where?”, while an rvalue answers “what value?” The terminology is MIR vocabulary, not a claim that the notation is ordinary Rust expression syntax.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
Trace a function one block at a time
For a small MIR function, use the same questions in each block:
- Where can control go next? Read the block’s terminator and note its successor or possible successors.
- What storage location changes? Find statements that assign to a local or projected place, such as a field.
- What value is produced? Read the right-hand rvalue separately from the destination place.
- What does the next block inherit? Follow each possible edge and continue tracking the locals and places that matter to your question.
This method is useful whether you are trying to understand a branch, locate where a value is moved, or see why a borrow remains relevant along one path but not another. If a block has multiple successors, follow each path rather than assuming that every later statement executes.
Why MIR matters to borrow checking
rustc’s borrow checker operates on MIR. The compiler guide’s borrow-checking overview describes checks such as ensuring that variables are initialized before use, preventing a value from being moved twice, and rejecting a move while the value is borrowed. It also describes restrictions on accessing a place while it is mutably borrowed, other than through the reference, and on mutating a place while it is immutably borrowed.
Rank #3
Because MIR exposes control flow, borrow checking can reason about where a value is used or borrowed along paths through the function. The guide connects MIR-based checking to non-lexical lifetimes (NLL): lifetime regions are derived from the control-flow graph rather than being determined only by the enclosing lexical scope.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesThe guide’s high-level borrow-check sequence
The guide presents the implementation in broad stages. It is a useful mental model, not an exhaustive or permanent specification of rustc’s algorithm:
- Prepare a local copy of MIR and replace regions with inference variables.
- Run dataflow analyses to determine what has been moved and when.
- Type-check the MIR to collect region constraints.
- Infer region values over control-flow locations.
- Determine which borrows are in scope.
- Walk MIR again to report violations.
The important reading insight is that borrow checking combines information about values and types with information about where execution can travel. A diagnostic is not merely a textual scan of the source; the compiler’s reasoning depends on operations and paths represented in MIR.
Dataflow: tracking facts across paths
Dataflow analysis propagates facts through a control-flow graph. At a basic level, an analysis has a rule for how a block changes its incoming facts and a way to combine information arriving from different predecessors. Repeating those rules until the facts stop changing is called reaching a fixpoint. A lattice is the mathematical structure used to represent and combine such facts; a transfer function describes how an operation changes them.
The MIR dataflow chapter gives examples of rustc using dataflow to find uninitialized variables, determine which variables are live across generator yield statements, and compute which places are borrowed at a point in the control-flow graph. You do not need the formal terminology to begin reading MIR, but it helps explain how a local operation in one block can affect what the compiler knows in another.
Where MIR sits in rustc
MIR is one stage in rustc’s broader compilation process, not a single isolated conversion from source directly to machine code. The compiler overview describes parsing and successive lowering and checking stages, including lowering through THIR, followed by MIR building. MIR is then used in borrow checking and later compiler work such as optimization and code generation.
This is a useful orientation rather than a rigid one-way pipeline diagram: rustc is organized around queries and dependencies between stages. For a brief representation-level contrast, HIR is earlier and closer to source structure, MIR is simplified and explicit about control flow, and LLVM IR is a later representation involved in code generation. The exact details of each representation go beyond what that contrast establishes.
Inspect MIR with rustc debugging flags
The compiler’s MIR debugging guide documents flags for inspecting textual MIR and dataflow output. These are compiler debugging options, so check the current guide for the toolchain and channel requirements before relying on them; they are not stable interfaces guaranteed across releases.
-Z dump-mirwrites textual MIR dumps.-Z dump-mir-dataflowproduces a.dotgraph showing dataflow state at control-flow points.
Use a textual dump when you want to connect assignments and terminators to the function’s structure. Use the dataflow graph when your question is specifically about how an analysis’ state changes at control-flow points. In either case, begin with the basic blocks and follow successor edges before trying to interpret every detail in the output.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




