Rust Development Environment

cargo check

cargo check (aliased as cargo c) runs all of the Rust compiler's validation passes—syntax parsing, macro expansion, type inference, trait resolution, and borrow checking—without spending time generating LLVM machine code or linking an executable binary.

Why cargo check Is Much Faster Than cargo build

In a typical Rust build, generating and optimizing native machine instructions in LLVM and running the system linker (ld / cc) accounts for the majority of total compilation time.

cargo check tells rustc to stop immediately after Mid-Level IR (MIR) borrow checking and emit only lightweight type metadata (.rmeta files) instead of object files (.o) and binaries:

Full `cargo build` Pipeline:
  [Parse & Expand] -> [Type Check (HIR)] -> [Borrow Check (MIR)] -> [LLVM Codegen & Opt] -> [System Linker]
  |______________________ ~30% of build time __________________|    |_________ ~70% of build time _________|

Fast `cargo check` Pipeline:
  [Parse & Expand] -> [Type Check (HIR)] -> [Borrow Check (MIR)] -> Writes `.rmeta` (Done!)

Because it skips LLVM codegen and linking completely, cargo check is often 2× to 5× faster than cargo build while catching the exact same syntax, type, trait, and borrow-checker errors!

Basic Usage and Output

While editing code and refactoring types or lifetimes, run cargo check in a tight loop to verify that your project compiles cleanly:

cargo check
    Checking my_project v0.1.0 (/Users/username/my_project)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s

Notice that Cargo prints Checking my_project rather than Compiling my_project, and no executable binary is created in target/debug/my_project.

Useful cargo check Flags

By default, cargo check checks only your library (src/lib.rs) and binary (src/main.rs, src/bin/*.rs) targets—it does not check #[test] functions or integration tests in tests/ unless you pass --tests or --all-targets:

Command What It Checks
cargo check (or cargo c) Library (src/lib.rs) and binary (src/main.rs, src/bin/) targets
cargo check --tests Also checks unit tests (#[cfg(test)]) and integration tests (tests/*.rs)
cargo check --examples Checks standalone example programs in examples/*.rs
cargo check --all-targets Checks libraries, binaries, unit tests, integration tests, and examples together
cargo check --workspace Checks every package in a multi-crate Cargo workspace
cargo check --target <triple> Type-checks platform-specific #[cfg(target_os = "...")] code for another OS/architecture
# Verify that both application code AND all unit/integration tests type-check cleanly:
cargo check --all-targets

Rare Errors Caught Only by cargo build, Not cargo check

Because cargo check stops before final monomorphization codegen and linking, a small handful of late-stage errors only surface during cargo build, cargo test, or cargo run:

Late-Stage Issue Detected by cargo check? Detected by cargo build?
Syntax, type (E0308), trait (E0277), and borrow (E0502) errors Yes Yes
Const evaluation panics in const items and array lengths (E0080) Yes Yes
Post-monomorphization const { ... } block errors inside generic functions Only when instantiated & codegen'd Yes
Missing external C library or unresolved extern "C" linker symbol No (linker is skipped) Yes (linking with cc failed)
Inline assembly (asm!) register allocation constraints Partially Yes

Typical Development Loop

In day-to-day Rust development:

  1. Run cargo check --all-targets (or let rust-analyzer run cargo check automatically in the background on every file save) while iterating on code structure and fixing compiler errors.
  2. Run cargo test or cargo run once cargo check succeeds with zero errors and you are ready to execute the program.