How it works
The explanation, with examples you can run.
Cargo.toml and Cargo.lock
[package]name = "shop"version = "0.1.0"edition = "2024" [dependencies]serde = { version = "1.0", features = ["derive"] }tokio = { version = "1", features = ["full"] } [dev-dependencies]proptest = "1" [profile.release]lto = true- Version requirements are semver ranges.
"1.0"means^1.0: at least 1.0.0 and below 2.0.0. For0.xversions the minor number counts as breaking, so"0.8.3"allows up to, not including, 0.9.0. - Cargo picks the newest version that satisfies everyone (unlike Go's minimal version selection) and writes the exact choice to Cargo.lock. Later builds reuse the lock until you run
cargo update. With the 2024 edition the resolver also prefers versions whose declaredrust-versionyour toolchain supports. - Two incompatible major versions of one crate can both appear in a build. That works, but their types are different types, which is a common source of puzzling "expected
X, foundX" errors. - Features are optional parts of a crate you switch on. Features are additive: if any crate in the graph enables one, every user of that crate gets it.
Profiles
cargo build uses the dev profile: no optimisation, debug assertions and integer overflow checks on. cargo build --release optimises, which can make code many times faster. Iterators, generics and other zero-cost abstractions only become zero-cost once the optimiser runs, so never measure performance in a debug build.
Editions
An edition is a set of language rules chosen per crate with the edition key. New editions come out every few years (2015, 2018, 2021, and 2024 with Rust 1.85) and may change syntax or defaults in ways that would otherwise break code. The rule that makes this work: crates of every edition interoperate, so each crate migrates when it is ready. cargo fix --edition applies most of the mechanical changes.
The 2024 edition, for example, requires unsafe extern blocks and #[unsafe(no_mangle)], changes how long temporaries in if let and at the end of a block live, makes impl Trait return types capture all lifetimes in scope by default, reserves the gen keyword, turns references to static mut into an error by default, and marks std::env::set_var as unsafe. cargo new picks the newest edition.
The rest of the toolbox
cargo fmt (rustfmt) formats code, cargo clippy adds hundreds of lints, cargo doc --open builds documentation for your crate and every dependency, and rustup installs and switches toolchains. A rust-toolchain.toml file pins the toolchain version for a project.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.