4 releases (breaking)
Uses new Rust 2024
| 0.4.0 | Feb 13, 2026 |
|---|---|
| 0.3.0 | Feb 13, 2026 |
| 0.2.0 | Feb 12, 2026 |
| 0.1.0 | Feb 12, 2026 |
#87 in Cargo plugins
57KB
1.5K
SLoC
cargo-unused-allow
Detect unused #[allow(...)] attributes in Rust projects.
How it works
- Temporarily replaces every
#[allow(...)]/#![allow(...)]with#[expect(...)]/#![expect(...)]in your source files. - Runs
cargo clippy --message-format=json -- -Wunfulfilled-lint-expectationsonce. - Parses
unfulfilled_lint_expectationsdiagnostics — each one corresponds to an#[allow]that was suppressing nothing. - Restores all original files (even on failure or panic).
Why?
Rust 1.81 stabilized #[expect(...)], which warns you when the suppressed lint no longer fires — but many projects still carry #[allow] attributes added before #[expect] existed, or out of habit. Over time, some of these become stale: the guarded code is refactored away, the lint rule changes, or the attribute was copy-pasted without thought. This is especially common in larger codebases. Stale #[allow]s silently hide real warnings and mask code-quality regressions, yet finding them manually is tedious.
cargo-unused-allow automates this. It detects every #[allow] that suppresses nothing — useful as a one-time cleanup, a CI gate, or a stepping stone toward migrating to #[expect].
Requirements
- Rust toolchain 1.81 or later (for
#[expect]support) clippy(rustup component add clippy)
Installation
From local source
cargo install --path .
From crates.io
cargo install cargo-unused-allow
From GitHub
cargo install --git https://github.com/lapla-cogito/cargo-unused-allow
Usage
# Run in any Rust project directory
cd /path/to/your/rust/project
# Basic detection
cargo-unused-allow
# Also check tests, examples, and benches
cargo-unused-allow --all-targets
# Automatically remove unused #[allow] attributes
cargo-unused-allow --fix
# Exclude specific lints from detection
cargo-unused-allow --exclude dead_code --exclude unused_imports
# Combine options
cargo-unused-allow --all-targets --fix --exclude dead_code
# Pass extra arguments to cargo clippy (after --)
cargo-unused-allow -- --workspace
cargo-unused-allow -- --package my-crate
cargo-unused-allow -- --workspace --features serde
cargo-unused-allow --all-targets -- --workspace
When installed via cargo install, you can also invoke it as a cargo subcommand:
cargo unused-allow --all-targets
Options
$ cargo unused-allow --help
Detect unused #[allow(...)] attributes in Rust projects
Usage: cargo-unused-allow [OPTIONS] [-- <CLIPPY_ARGS>...]
Arguments:
[CLIPPY_ARGS]... Extra arguments passed through to `cargo clippy` (specify after --)
Options:
--all-targets Check all targets (tests, examples, etc...)
--fix Automatically remove unused #[allow(...)] attributes from source files
--exclude <LINT> Lint names to exclude from detection (can be specified multiple times)
-h, --help Print help
-V, --version Print version
Exit codes
| Code | Meaning |
|---|---|
0 |
No unused #[allow] found |
1 |
Unused #[allow] attributes found |
2 |
Internal error |
Example output
See the examples directory for sample output.
*.rs files are the original sources, *.rs.output files contain the tool's output, and *.rs.fixed files are generated with --fix.
--fix behavior
When --fix is specified, the tool modifies source files directly:
- Single-lint attributes like
#[allow(dead_code)]are removed entirely (including the line). - Multi-lint attributes like
#[allow(dead_code, unused_variables)]are rewritten to keep only the lints that are still needed (e.g.,#[allow(unused_variables)]). - Inner attributes like
#![allow(...)]are handled the same way. cfg_attr-wrapped attributes like#[cfg_attr(feature = "foo", allow(dead_code))]are removed entirely when all lints are unused, or rewritten to keep remaining lints (e.g.,#[cfg_attr(feature = "foo", allow(unused_imports))]).- Indentation and surrounding code are preserved.
--exclude behavior
You can exclude specific lint names from detection. This is useful when you intentionally keep certain #[allow] attributes (e.g., for forward compatibility):
# Ignore unused dead_code and unused_imports allows
cargo-unused-allow --exclude dead_code --exclude unused_imports
The --exclude flag can be specified multiple times. Clippy lints use their full path:
cargo-unused-allow --exclude clippy::needless_return
Try with included examples
The repository includes example files in examples/ that demonstrate detection:
# From the repository root — detect only
cargo-unused-allow --all-targets
# Detect and auto-fix
cargo-unused-allow --all-targets --fix
License
MIT
Dependencies
~3.5–7.5MB
~132K SLoC