Skip to content
rusthacks.dev
Tooling

Configuring Lints in Cargo Toml for the Whole Workspace

Set rustc and Clippy lint levels in the [lints] table of Cargo.toml, inherit them across a workspace with workspace.lints and handle priority for groups.

2 min read
Summarize in AI
Flat illustration for the post “Configuring Lints in Cargo Toml for the Whole Workspace”, composed around tooling.

Lint configuration used to live in three places: #![warn(...)] at the top of each crate, RUSTFLAGS in CI, and a clippy.toml. A fourth place, the [lints] table in Cargo.toml, replaces the first two and makes workspaces consistent. This post shows the table, the workspace form and the priority detail that causes the only common mistake. It builds on Clippy explained.

Cargo 1.90.

A single crate

Cargo.tomlTOML
[package]
name = "demo"
version = "0.1.0"
edition = "2024"

[lints.rust]
unsafe_code = "forbid"
missing_docs = "warn"

[lints.clippy]
pedantic = { level = "warn", priority = -1 }
unwrap_used = "warn"
module_name_repetitions = "allow"

unsafe_code = "forbid" makes any unsafe block an error that cannot be overridden by allow. unwrap_used is a restriction lint, not enabled by default. The line with pedantic turns on the whole group at warn level.

Why priority

Cargo passes lint flags to the compiler in an order. Without a priority, a group and a single lint may be applied in the wrong order, and the group wins. priority = -1 on the group (lower runs first) means the specific lines after it override. Clippy warns when you forget with its lint_groups_priority lint.

A workspace

Cargo.tomlTOML
[workspace]
members = ["crates/*"]
resolver = "3"

[workspace.lints.rust]
unsafe_code = "forbid"

[workspace.lints.clippy]
pedantic = { level = "warn", priority = -1 }
unwrap_used = "warn"
crates/core/Cargo.tomlTOML
[package]
name = "core-logic"
version = "0.1.0"
edition = "2024"

[lints]
workspace = true

Every member picks up the same rules. A member that needs an exception cannot add a local [lints.clippy] entry beside workspace = true; it uses an attribute in code, or you move that crate's policy out of the workspace table. The dependency half of workspace inheritance is in workspace dependencies.

Warnings in CI

Shell
cargo clippy --all-targets --all-features -- -D warnings

-D warnings turns every warning into an error in that run. Keep it in CI. If you put deny in Cargo.toml, a new compiler release that adds a lint will break local builds for everyone on upgrade.

Tests

Test code uses unwrap() and expect() freely. Allow the lint in test modules:

rust
#[cfg(test)]
mod tests {
    #![allow(clippy::unwrap_used)]
}

or enable allow-unwrap-in-tests = true in clippy.toml.

Rolling out on an old codebase

Allow the existing violations in a baseline, deny new ones, and tighten over time. A first step is unused_must_use and unsafe_code, because they are cheap to fix. The technical debt angle is in technical debt in Rust codebases.

Limits

Lints specific to a tool, such as rustdoc::broken_intra_doc_links, use their own table keys ([lints.rustdoc]). Unknown lint names produce a warning that is easy to miss after a toolchain change. The format is described in the Cargo book's section on the lints section.

Taggedlints
Share

Keep reading

Flat illustration for the post “Incident Response for Rust Services a Short Runbook”, composed around deploy.
DevOps

Incident Response for Rust Services a Short Runbook

A one-page runbook for when a Rust service misbehaves: stabilize first, check recent changes, read the four golden signals, find the failing dependency, and use the Rust-specific evidence: panics, memory, executor stalls.

4 min read
Flat illustration for the post “Debugging Async Backtraces and Task Dumps in Tokio”, composed around async.
Tooling

Debugging Async Backtraces and Task Dumps in Tokio

A hung async service has no useful thread backtrace. Tokio task dumps capture the await stack of every task. Enable tokio_unstable and taskdump, trigger a dump from a signal or endpoint, and read where each task is parked.

4 min read

Get new posts by email

We send one email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.