Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Cargo.toml is your project's contract with the rest of the Rust world: name, version, edition, dependencies, dev-dependencies, build-dependencies, features, and profile overrides. A real project's Cargo.toml is dense — knowing every field by heart is the difference between 'I copy from a template' and 'I can audit a repo before contributing'. This is also where features (Rust's conditional-compilation flags) live, which become important the moment you depend on tokio or serde.
Cargo.toml is the contract between your project and the Rust toolchain: it declares the package identity, edition, all dependencies with their version requirements, and optional feature flags that gate conditional compilation. The [dependencies], [dev-dependencies], and [build-dependencies] sections exist because code you need at test-time or at build-time should never end up in your production binary. Learning to read and write this file fluently is a prerequisite for every other Rust skill.
cargo add serde --features derive. Open Cargo.toml and see what changed.cargo tree. Note the depth of even small dep trees (tokio pulls in ~30 crates).[profile.release] block with lto = "thin" and strip = true. Rebuild with --release and compare binary size.cargo update -p serde. See how the lockfile changes; understand that Cargo.toml says 'compatible with', Cargo.lock says 'exactly this'.Use these three in order. Each builds on the one before.
In one paragraph, explain the difference between `Cargo.toml` and `Cargo.lock` — and which one I commit for a binary vs a library.
Walk me through how cargo resolves features: what does `default-features = false` mean, what's the unification rule when two crates ask for different features?
I'm shipping a library and want to be a good citizen. What's the right way to design features (additive, no mutually exclusive features), and what are the common pitfalls?
[package]
name = "myapp"
version = "0.1.0"
edition = "2021"
rust-version = "1.75"
license = "MIT OR Apache-2.0"
description = "A sample app"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1"
[dev-dependencies]
proptest = "1"
[features]
default = ["tls"]
tls = ["dep:rustls"]
[profile.release]
lto = "thin" # link-time optimization → smaller, faster binaries
codegen-units = 1 # better optimization, slower compile
strip = true # strip symbols
# install:
$ cargo add anyhow tokio --features tokio/full
$ cargo tree | head -10 # see the resolved graphcargo run