Why these choices
This page explains the configuration decisions that are not obvious from the lint name. For the full map of rules to lints, see coverage.md. For what was deliberately left out, see why-not.md.
Principles
Section titled “Principles”- Enforce what the guide says, not more. A lint gets in only when it maps to a sentence in the guide. Popular lints that the guide does not ask for (
mod_module_files,module_name_repetitions, the wholepedanticgroup) stay off, so a warning always points back to a rule. - One layer per rule. A rule lives in tooling or in AGENTS.md, never both. Duplicated rules drift, and agents waste context re-reading what clippy will tell them anyway.
- Exceptions are data. The guide grants many exceptions. Rather than weakening a lint to accept them, the lint stays strict and the exception is written down as
#[expect(lint, reason = "...")]at the exact site where a reviewer can judge it. - The config must prove itself. Every lint is exercised by a fixture in CI, so “we enforce X” is a tested claim rather than a hope.
Global settings
Section titled “Global settings”all = { level = "warn", priority = -1 }
Section titled “all = { level = "warn", priority = -1 }”This keeps clippy’s default groups (correctness, suspicious, style, complexity, perf) on. They encode the official Rust style and API conventions, which the guide’s first rule says to follow. priority = -1 lets the individual entries below override the group.
warn in the config, -D warnings in CI
Section titled “warn in the config, -D warnings in CI”Every guide lint is warn, and CI promotes warnings to errors. Locally you can keep compiling and testing while a warning is outstanding, but nothing merges with one. Only two lints are deny everywhere, because there is never a reason to iterate with them present:
unstable_features: the guide forbids unstable features outright.clippy::invisible_characters: an invisible character in a literal is never intentional enough to keep.
avoid-breaking-exported-api = false
Section titled “avoid-breaking-exported-api = false”By default clippy skips several API lints (wrong_self_convention, ref_option, needless_pass_by_value and others) on public items, to avoid suggesting breaking changes. The guide’s API rules matter most at public boundaries, so this kit turns that protection off. An established library that cannot ship breaking changes can set it back to true. See adopting.md.
allow_attributes_without_reason
Section titled “allow_attributes_without_reason”The guide is a document of rules plus exceptions, and every exception should be reviewable. Requiring reason = "..." on every suppression means the reviewer sees the author’s justification rather than having to reconstruct it. AGENTS.md asks for #[expect] rather than #[allow] because an #[expect] fails once it is no longer needed.
Code organization
Section titled “Code organization”wildcard_imports
Section titled “wildcard_imports”It matches the guide’s exceptions closely without configuration. It does not flag use Enum::* inside a function body, pub use submodule::* re-exports, or use super::* in #[cfg(test)] modules. The guide also allows use super::* in non-test inline modules; those need an #[expect], which is rare enough to be acceptable.
absolute_paths with a two-segment limit
Section titled “absolute_paths with a two-segment limit”The guide wants functions called as module::function() and types used bare after a use. absolute_paths with absolute-paths-max-segments = 2 accepts fs::read() and Regex::new() but rejects std::fs::read(), crate::shelf::add() and regex::Regex::new() written inline, which pushes code toward exactly the import style the guide describes. It cannot catch the opposite mistake (use std::mem::swap; swap(..)), so AGENTS.md covers that.
Formatting
Section titled “Formatting”Nightly-only rustfmt options
Section titled “Nightly-only rustfmt options”The guide names imports_granularity = Module, hex_literal_case = Lower and format_macro_matchers = true, all unstable in rustfmt. The guide also says a codebase that wants to stay on stable may drop them. This kit keeps them in rustfmt.toml because stable rustfmt only warns about them and otherwise formats normally. Teams that run cargo +nightly fmt get the full guide, and teams that do not still get max_width = 100.
invisible_characters
Section titled “invisible_characters”The guide asks for escapes such as \u{200D} instead of literal invisible characters. That lives with rustfmt in the guide’s formatting section, but rustfmt cannot enforce it and clippy can.
Ownership
Section titled “Ownership”Rc and Arc as disallowed_types
Section titled “Rc and Arc as disallowed_types”The guide says to prefer unique ownership and to allow Rc/Arc only when the alternative would be unreasonably complex, “a judgment call to be discussed during code review.” A lint cannot make that call, but it can make sure the call happens: every use needs #[expect(clippy::disallowed_types, reason = "...")]. Put it at module level (#![expect(...)]) when a module is built around shared ownership, so the reason is stated once.
redundant_clone from the nursery
Section titled “redundant_clone from the nursery”The guide’s rule is “use .clone() when you genuinely need a deep copy”. redundant_clone is the only lint that directly detects a clone whose original is never used again. It lives in the nursery group because of rare false positives in complex control flow; when one happens, #[expect] with a reason is cheap. implicit_clone and needless_pass_by_value cover the related patterns: hidden clones through to_owned()/to_string(), and owned parameters that are only read.
Function inputs
Section titled “Function inputs”ref_option alongside ptr_arg and borrowed_box
Section titled “ref_option alongside ptr_arg and borrowed_box”The guide’s table has four rows: &T over &Box<T>, &[T] over &Vec<T>, &str over &String, and Option<&T> over &Option<T>. It cites borrowed_box and ptr_arg, which cover the first three. ref_option covers the fourth.
Bool thresholds of one
Section titled “Bool thresholds of one”fn_params_excessive_bools and struct_excessive_bools default to flagging at four bools. The guide wants an enum whenever a bool’s purpose is not obvious, which no threshold captures. A threshold of one (flag at two or more) catches the worst cases, render(true, false), without forcing enums on a single obvious flag like set_visible(bool).
Traits and naming
Section titled “Traits and naming”should_implement_trait, wrong_self_convention, new_without_default and len_without_is_empty are named by the guide itself and are on by default. They are listed explicitly in Cargo.toml anyway, so the file reads as a complete map and so a future change to clippy’s defaults cannot silently drop them. inherent_to_string and from_over_into extend the same “implement the standard trait” rule to Display and From. new_ret_no_self backs the constructor naming rule: a function called new returns Self.
Documentation
Section titled “Documentation”missing_docs is what the guide names. missing_panics_doc, missing_errors_doc and missing_safety_doc back its instructions to document panic cases and unsafe invariants, plus the Rust API Guidelines’ requirement to document errors (the guide says to follow the API Guidelines). doc_markdown catches identifiers written without backticks, since the guide asks for Markdown.
Other features
Section titled “Other features”exhaustive_enums and exhaustive_structs
Section titled “exhaustive_enums and exhaustive_structs”Both are restriction lints, and the guide names exhaustive_enums itself. exhaustive_structs fires only on structs whose fields are all public, which is exactly the guide’s condition. Both have well-defined exceptions in the guide (fixed ontologies, two-state enums, options structs using struct update syntax), which become #[expect] with a reason. The example crate shows both.
must_use_candidate
Section titled “must_use_candidate”The guide wants #[must_use] on functions whose result the caller cannot ignore, “including pure functions such as HashMap::get()”. must_use_candidate flags exactly public functions with no side effects that return a value. It is the noisiest lint in the set, but every warning it raises is a case the guide covers.
Poison and catch_unwind as disallowed methods
Section titled “Poison and catch_unwind as disallowed methods”“Never reach inside a poisoned mutex” means never calling PoisonError::into_inner, get_ref or get_mut, so those three are disallowed. panic::catch_unwind is prohibited apart from a defense-in-depth exception, which takes an #[expect] with a reason.
cargo-deny for code before main()
Section titled “cargo-deny for code before main()”The guide cites the ctor crate. Running code before main() is a property of dependencies, not of your own source, so it is checked at the dependency graph: ctor, plus inventory and static_init, which provide the same capability.
Implementation concerns
Section titled “Implementation concerns”unwrap_usedturns “preferexpectoverunwrap” into a check.allow-unwrap-in-testsfollows the guide’s “tests may use panics.”unnecessary_unwrapis the guide’s check-then-unwrap example, almost line for line.missing_assert_messageenforces that a message exists. Clippy skips test functions, which matches the guide’s focus on assertions in production code.needless_for_eachmatches “avoidIterator::for_each” exactly.format_push_stringcatchess += &format!(..)andpush_str(&format!(..)), wherewrite!avoids the temporary allocation.
Unofficial community project, not affiliated with or endorsed by Google. TheGoogle Rust Style Guide is published by Google under CC-BY 3.0. This kit is Apache-2.0.