--- id: SMH-RESEARCH-JTJLLCMH type: research title: "Cargo and Clippy Lint Scoping" --- # Cargo and Clippy Lint Scoping Idiomatic ways to scope lint levels by target (production, tests, guests), verified against current docs and this repository. ## Mechanisms, verified | mechanism | scope unit | idiomatic for | verified | |---|---|---|---| | `[workspace.lints]` + `[lints] workspace = true` | package (all its targets) | stable levels owned in Cargo.toml; cargo-native since 1.74 | [cargo workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html) | | `[lints.clippy]` per package | package | per-crate exceptions without attrs | [clippy configuration](https://doc.rust-lang.org/clippy/configuration.html) | | attributes `#[deny]` / `#[expect]` | item, module, file | visible, reasoned, local exceptions | clippy docs | | rustc args after `--` (`-A clippy::x`) | invocation | phase splits (`--tests`, `--lib`) and one-shot overrides; last level wins over earlier flags | rustc lint levels | | `.cargo/config.toml` rustflags | every rustc invocation | workspace-wide zero-warning policy incl. builds | current smith setup | | `clippy.toml` / `.clippy.toml` | whole run | VALUES only (thresholds), never levels | clippy docs | Nightly-only: `cargo`'s own lint group (`unused_dependencies` etc.) — not usable on stable. ## Facts discovered in this repository - `CLIPPY_CONF_DIR` is real and documented: priority CLIPPY_CONF_DIR → CARGO_MANIFEST_DIR → cwd, then parent walk. - Empirically: without the env var, `clippy.toml` under `.config/` is NOT discovered — raw `cargo clippy` and rust-analyzer silently lose threshold configuration. With the env var (xtask gate), it parses. - Clippy levels cannot be scoped by target type (`--tests`) through any cargo-native table; that gap is what invocation splitting covers. - `#[expect]` on items coexists with command-line `-A`: expectations stay fulfilled when the lint would fire without the allowance. File-level `#![expect]` headers on lints the phase allows become redundant but were not observed to error; either way, phase-covered expectations should be deleted. ## Idiomatic shape for smith ```text policy levels .cargo/config.toml rustflags (unchanged) — the zero-warning law applies to every compilation thresholds .config/clippy.toml + CLIPPY_CONF_DIR in xtask per-crate levels [lints] tables when a crate needs a standing exception (none today) local exceptions #[expect(..., reason)] attributes (status quo) target phases xtask clippy split: --lib/--bins strict, --tests with assertion allowances, guests with pedantic+missing_docs allowances ``` Phase allowances after `--` are idiomatic for CI orchestration; they live in one auditable place and cannot leak into source. ## Unresolved questions - Raw-run configuration loss: developers and rust-analyzer invoke clippy without CLIPPY_CONF_DIR and get default thresholds. Options: symlink `.clippy.toml` at root into `.config/` (root file, law tension), law exception for clippy discovery, or accept gate-only configuration and document it. - Precedence between `[lints]` table levels and config rustflags is undocumented; if both are adopted, test empirically before mixing. - Whether test allowances should eventually move into a `[lints]`-based scheme if cargo grows per-target lint tables. ## Sources - Cargo lints inheritance — - Clippy configuration discovery — - Cargo's own (nightly) lint groups —