tezvyn:

What is the difference between Cargo.toml and Cargo.lock?

AI-drafted, machine-checkedSource: doc.rust-lang.orgbeginner
WHAT IT TESTS

Understanding reproducible builds and Cargo's dependency model.

ANSWER OUTLINE

Cargo.toml declares broad requirements; Cargo.lock pins exact resolved versions.

RED FLAG

Saying lockfiles are optional for apps or that both files are hand edited.

WHAT THIS TESTS: This question tests whether you understand reproducible builds and the division of labor between human intent and machine precision in Cargo. It reveals if you know that dependency resolution is a two-phase process: you express loose requirements, and Cargo computes a deterministic graph. It also checks whether you grasp the downstream impact of that choice on applications versus libraries.

A GOOD ANSWER COVERS: A strong answer explains that Cargo.toml is the manifest file you write by hand to specify metadata and broad dependency requirements, such as version ranges or git repository URLs without exact commits. It then explains that Cargo.lock is the lockfile generated and maintained by Cargo that records the exact resolved versions, including precise git revision hashes and transitive dependencies, ensuring that two builds at different times produce identical artifacts. Next, it covers the version control policy: commit Cargo.lock for applications because reproducible builds matter for deployable artifacts, but do not commit it for libraries because libraries need to remain compatible with a range of dependency versions chosen by the consuming application; a committed lockfile in a library would hide integration conflicts and force downstream users into an overly rigid graph. Finally, mention that cargo update is the tool to refresh the lockfile when you intentionally want to pull in newer compatible versions.

COMMON WRONG ANSWERS: A red flag is saying that both files are meant to be edited manually. Another is claiming that Cargo.lock is unnecessary for applications because semantic versioning guarantees safety; in practice, even patch releases can introduce regressions. Conversely, insisting that libraries must always commit their lockfile shows a misunderstanding of composability and the resolver's role in downstream projects. Some candidates also confuse the two files by describing Cargo.toml as containing exact versions, which misses the point of the manifest versus lockfile separation.

LIKELY FOLLOW-UPS: An interviewer might ask what happens if two libraries in the same application depend on different major versions of the same crate, or how the resolver handles yanked crates. They might also ask about the Package ID Specification used with cargo update, or how workspaces interact with lockfiles. You could also be asked to compare this model to npm's package.json and package-lock.json or Python's requirements.txt and poetry.lock.

ONE CONCRETE EXAMPLE: Imagine your Cargo.toml depends on regex with a git URL but no revision hash. On your first build, Cargo fetches the latest commit and writes the exact SHA into Cargo.lock. When a teammate clones the repo tomorrow, Cargo reads that SHA from the lockfile and builds the same code even if the upstream repository has new commits. If you were shipping a library instead, omitting the lockfile lets the application using your library resolve its own compatible version of regex, avoiding conflicts with other crates in the application's dependency tree.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.