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.

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
[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
[workspace]
members = ["crates/*"]
resolver = "3"
[workspace.lints.rust]
unsafe_code = "forbid"
[workspace.lints.clippy]
pedantic = { level = "warn", priority = -1 }
unwrap_used = "warn"[package]
name = "core-logic"
version = "0.1.0"
edition = "2024"
[lints]
workspace = trueEvery 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
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:
#[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.


