Rust Tooling and Code Quality

cargo check

The cargo check command runs the front-end and middle-end passes of rustc—parsing, macro expansion, name resolution, type checking, trait solving, and borrow checking—while skipping machine-code generation (LLVM codegen) and binary linking. Because LLVM code generation and linking typically account for 50–80% of total compilation time, cargo check validates your code in a fraction of the time of cargo build.

`rustc` Compilation Pipeline:

  [ Lex / Parse / Expand Macros ]
                 |
                 v
  [ Name Resolution & Type Inference (HIR) ]
                 |
                 v
  [ Borrow Checker & Lints (MIR) ]   <=== `cargo check` STOPS HERE!
                 |                        (Emits `.rmeta` metadata file only)
                 v
  [ LLVM Optimization & Codegen ]
                 |
                 v
  [ Native Linker (`ld` / `lld`) ]   <=== `cargo build` runs all the way here

Comparing cargo check and cargo build

Aspect cargo check (cargo c) cargo build (cargo b)
Syntax & Macro Checking Yes Yes
Type & Trait Checking Yes Yes
Borrow & Lifetime Checking Yes Yes
Compiler Warnings & Lints Yes Yes
LLVM Machine Code Generation No (Skipped) Yes
Executable Binary / .rlib Output No (Writes .rmeta type metadata only) Yes (Writes .rlib and executables)
Typical Incremental Speed 2x–5x faster Baseline

Useful cargo check Flags for Comprehensive Validation

By default, cargo check only checks the package's library and binary targets (src/lib.rs and src/main.rs). If you refactor a public function signature, a compile error sitting inside tests/integration.rs or examples/demo.rs will not be checked unless you pass --all-targets (or --tests):

# 1. Check library, binaries, unit tests, integration tests, examples, and benches:
cargo check --all-targets

# 2. Check across every crate in a workspace with all Cargo features enabled:
cargo check --workspace --all-targets --all-features

# 3. Check whether code compiles cleanly for a different target OS without linking:
cargo check --target x86_64-pc-windows-gnu

What cargo check Cannot Catch

Because cargo check stops before LLVM codegen and linking, there are two rare error classes that only appear during cargo build or cargo test:

  1. Linker errors: Missing native C libraries (-l foo) or unresolved extern "C" symbols.
  2. Post-monomorphization errors: Compile-time const { assert!(...) } failures inside generic functions that are only instantiated during monomorphization in codegen.
pub fn validate_frame_bounds(offset: usize, len: usize, total: usize) -> Option<usize> {
    let end = offset.checked_add(len)?;
    (end <= total).then_some(end)
}

fn main() {
    println!("Validated end offset: {:?}", validate_frame_bounds(10, 20, 50));
}
Validated end offset: Some(30)