2026-04-28
Discoveries
Rust Things
Quick Tip - Force types in error output:
let x = some_complex_expression();
let _: () = x;
- Dev Guide Reference
- Rust Playground - Includes ASM, LLVM IR, MIR, HIR as outputs.
- Overview of Compilation Process
rustcCommand Line Parsing- Lexical Analysis (i.e. tokenization)
- Parsing into AST: Macro Expansion, Name Resolution, Entry Points, Feature Gate Checking, Early Linting
- High Level Intermediate Representation (HIR)
- Type Inference - process of automatic detection of the type of an expression
- Mid-Level Intermediate Representation (MIR) - simplified Rust IR used for borrow checker.
- Basic Blocks: statements, terminators, control-flow graphs
- Locals: stack vars, arguments, local vars, temps.
- Places: memory address expressions
- Rvalues: expressions producing a value
- Operands
- Borrow Checker - Operates on MIR
- That all variables are initialized before they are used.
- That you can’t move the same value twice.
- That you can’t move a value while it is borrowed.
- That you can’t access a place while it is mutably borrowed (except through the reference).
- That you can’t mutate a place while it is immutably borrowed.
- MIR Optimizations - Pre-LLVM optimizations.
- Code Generation - LLVM process to generate binary.
There is a large list of "undocumented" flags you can use to drive rustc (nightly) outputs by running:
rustc +nightly -Z help
Run the following to see the rustc commands that cargo is running to build each crate.
cargo +nightly build -v
For me, one of them looked like:
/home/user/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc --crate-name reftests --edition=2021 src/main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=116 --crate-type bin --emit=dep-info,link -C panic=abort -C embed-bitcode=no -C debuginfo=2 --check-cfg 'cfg(docsrs,test)' --check-cfg 'cfg(feature, values())' -C metadata=224fb19d0a7d9e0e -C extra-filename=-06c49fae36f5f61c --out-dir /opt/labs/rust/refs/target/debug/deps -C incremental=/opt/labs/rust/refs/target/debug/incremental -L dependency=/opt/labs/rust/refs/target/debug/deps --extern libc=/opt/labs/rust/refs/target/debug/deps/liblibc-48f66f96bb8290dc.rlib
If you add a -Zunpretty= flag to the command, you can get different phases of the your rust code compilation. As seen from -Z help:
-Z unpretty=val -- present the input source, unstable (and less-pretty) variants;
`normal`, `identified`,
`expanded`, `expanded,identified`,
`expanded,hygiene` (with internal representations),
`ast-tree` (raw AST before expansion),
`ast-tree,expanded` (raw AST after expansion),
`hir` (the HIR), `hir,identified`,
`hir,typed` (HIR with types for each node),
`hir-tree` (dump the raw HIR),
`thir-tree`, `thir-flat`,
`mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)
Changing the generated outputs from a stable rustc is accomplished with the --emit argument.
Formats:
--emit=type=-- emissions can be sent to STDOUT--emit=type=/path/to/file- emissions can specify a dump file--emit=type1=arg,type=arg- emissions types can be comma separated
Options:
--emit <TYPE>[=<FILE>]
Comma separated list of types of output for the
compiler to emit.
Each TYPE has the default FILE name:
* asm - CRATE_NAME.s
* llvm-bc - CRATE_NAME.bc
* dep-info - CRATE_NAME.d
* link - (platform and crate-type dependent)
* llvm-ir - CRATE_NAME.ll
* metadata - libCRATE_NAME.rmeta
* mir - CRATE_NAME.mir
* obj - CRATE_NAME.o
* thin-link-bitcode - CRATE_NAME.indexing.o
Trait Resolution:
RUSTC_LOG=rustc_trait_selection=info cargo build
RUSTC_LOG=rustc_trait_selection=debug cargo build