lints 0.3.1

Writes [lints.rust] to stdout such that all lints are denied or allowed.
CLI app for `rustc` lints
=========================

[<img alt="git" src="https://git.philomathiclife.com/badges/lints.svg" height="20">](https://git.philomathiclife.com/lints/log.html)
[<img alt="crates.io" src="https://img.shields.io/crates/v/lints.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/lints)

`lints` is a CLI application that parses the output of [`rustc -Whelp`](https://doc.rust-lang.org/stable/rustc/)
before writing the lints to `stdout` in a format that can be added to a TOML table, `lints.rust`, in `Cargo.toml`.

## Why is this useful?

Unlike [Clippy](https://doc.rust-lang.org/stable/clippy/index.html), many `rustc` lints are not members of at
least one lint group which makes it easy for one to not enjoy the benefit of a lint they didn't know about it.
`rustc` lints and lint groups change rather frequently, so it can be "annoying" to maintain a list of up-to-date
lints.

## Usage

`lints [COMMAND] [OPTIONS]`

## Commands

* `allow`: Allows all lints.
* `deny`: Denies all lints.
* `help`: This message.
* `version`: Prints version info.

## Options

* `--all`: Writes all individual lints even if they're already part of a lint group.
* `--allow-undefined-lints`: Lint groups that contain undefined lints are allowed.
* `-`: If the last argument, `stdin` is read instead of getting the output from `rustc`.

When nothing or `deny` is passed, all lint groups and `allow`-by-default lints that are not part of a group
are set to `deny`.
When `allow` is passed, `"warnings"` and all `deny`-by-default lints are set to `allow`.
`stdout` is written to in the format of the TOML table, `lints.rust`, which can be added to `Cargo.toml`.

`--allow-undefined-lints` should rarely be necessary since the lints defined in a lint group per `rustc -Whelp`
are almost always one of the lints listed. There have been exceptions though (e.g., `rustc 1.48.0` lists the
lint group `"rustdoc"` containing the lint `"private-intra-doc-links"` despite that lint not being in the table
of lints).

## `lints` in action

```bash
[zack@laptop ~]$ rustc -V
rustc 1.93.0 (254b59607 2026-01-19)
[zack@laptop ~]$ lints version
lints 0.3.0
[zack@laptop ~]$ lints
deprecated-safe = { level = "deny", priority = -1 }
future-incompatible = { level = "deny", priority = -1 }
keyword-idents = { level = "deny", priority = -1 }
let-underscore = { level = "deny", priority = -1 }
nonstandard-style = { level = "deny", priority = -1 }
refining-impl-trait = { level = "deny", priority = -1 }
rust-2018-compatibility = { level = "deny", priority = -1 }
rust-2018-idioms = { level = "deny", priority = -1 }
rust-2021-compatibility = { level = "deny", priority = -1 }
rust-2024-compatibility = { level = "deny", priority = -1 }
unknown-or-malformed-diagnostic-attributes = { level = "deny", priority = -1 }
unused = { level = "deny", priority = -1 }
warnings = { level = "deny", priority = -1 }
ambiguous-negative-literals = { level = "deny", priority = -1 }
closure-returning-async-block = { level = "deny", priority = -1 }
deprecated-in-future = { level = "deny", priority = -1 }
deref-into-dyn-supertrait = { level = "deny", priority = -1 }
ffi-unwind-calls = { level = "deny", priority = -1 }
fuzzy-provenance-casts = { level = "deny", priority = -1 }
impl-trait-redundant-captures = { level = "deny", priority = -1 }
linker-messages = { level = "deny", priority = -1 }
lossy-provenance-casts = { level = "deny", priority = -1 }
macro-use-extern-crate = { level = "deny", priority = -1 }
meta-variable-misuse = { level = "deny", priority = -1 }
missing-copy-implementations = { level = "deny", priority = -1 }
missing-debug-implementations = { level = "deny", priority = -1 }
missing-docs = { level = "deny", priority = -1 }
multiple-supertrait-upcastable = { level = "deny", priority = -1 }
must-not-suspend = { level = "deny", priority = -1 }
non-ascii-idents = { level = "deny", priority = -1 }
non-exhaustive-omitted-patterns = { level = "deny", priority = -1 }
redundant-imports = { level = "deny", priority = -1 }
redundant-lifetimes = { level = "deny", priority = -1 }
resolving-to-items-shadowing-supertrait-items = { level = "deny", priority = -1 }
shadowing-supertrait-items = { level = "deny", priority = -1 }
single-use-lifetimes = { level = "deny", priority = -1 }
trivial-casts = { level = "deny", priority = -1 }
trivial-numeric-casts = { level = "deny", priority = -1 }
unit-bindings = { level = "deny", priority = -1 }
unnameable-types = { level = "deny", priority = -1 }
unqualified-local-imports = { level = "deny", priority = -1 }
unreachable-pub = { level = "deny", priority = -1 }
unsafe-code = { level = "deny", priority = -1 }
unstable-features = { level = "deny", priority = -1 }
unused-crate-dependencies = { level = "deny", priority = -1 }
unused-import-braces = { level = "deny", priority = -1 }
unused-lifetimes = { level = "deny", priority = -1 }
unused-qualifications = { level = "deny", priority = -1 }
unused-results = { level = "deny", priority = -1 }
variant-size-differences = { level = "deny", priority = -1 }
```

## Minimum Supported Rust Version (MSRV)

This will frequently be updated to be the same as stable. Specifically, any time stable is updated and that
update has "useful" features or compilation no longer succeeds (e.g., due to new compiler lints), then MSRV
will be updated.

MSRV changes will correspond to a SemVer patch version bump pre-`1.0.0`; otherwise a minor version bump.

## SemVer Policy

* All on-by-default features of this library are covered by SemVer
* MSRV is considered exempt from SemVer as noted above

## License

Licensed under either of

* Apache License, Version 2.0 ([LICENSE-APACHE]https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT]https://opensource.org/licenses/MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Before any PR is sent, `cargo clippy --all-targets` and `cargo test --all-targets` should be run using the stable
and MSRV toolchains. One easy way to achieve this is by invoking [`ci-cargo`](https://crates.io/crates/ci-cargo)
as `ci-cargo clippy --all-targets test --benches --bins --examples --tests` in the `lints` directory.

Last, `cargo +nightly doc` should be run to ensure documentation can be built.

### Status

The crate is only tested on the `x86_64-unknown-linux-gnu`, `x86_64-unknown-openbsd`, and `aarch64-apple-darwin`
targets; but it should work on most platforms.