{"id":13671697,"url":"https://github.com/trailofbits/dylint","last_synced_at":"2025-05-14T10:10:55.714Z","repository":{"id":36978584,"uuid":"349570194","full_name":"trailofbits/dylint","owner":"trailofbits","description":"Run Rust lints from dynamic libraries","archived":false,"fork":false,"pushed_at":"2025-05-06T17:56:58.000Z","size":10498,"stargazers_count":446,"open_issues_count":51,"forks_count":37,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-05-06T18:24:42.020Z","etag":null,"topics":["linting","rust"],"latest_commit_sha":null,"homepage":"https://blog.trailofbits.com/2021/11/09/write-rust-lints-without-forking-clippy/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trailofbits.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-03-19T22:27:48.000Z","updated_at":"2025-05-06T17:57:01.000Z","dependencies_parsed_at":"2023-12-17T14:29:31.355Z","dependency_job_id":"6c4d1144-c18e-42f5-8893-40174b8efc53","html_url":"https://github.com/trailofbits/dylint","commit_stats":{"total_commits":999,"total_committers":10,"mean_commits":99.9,"dds":0.8028028028028028,"last_synced_commit":"e4c8c0d45dc25e72b4c13e2c6dcb4846aca3e02c"},"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fdylint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fdylint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fdylint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fdylint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trailofbits","download_url":"https://codeload.github.com/trailofbits/dylint/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254120170,"owners_count":22017953,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linting","rust"],"created_at":"2024-08-02T09:01:16.560Z","updated_at":"2025-05-14T10:10:55.705Z","avatar_url":"https://github.com/trailofbits.png","language":"Rust","funding_links":[],"categories":["Rust","Linters"],"sub_categories":[],"readme":"# Dylint\n\nRun Rust lints from dynamic libraries (EuroRust 2024 [slides] and [video])\n\n```sh\ncargo install cargo-dylint dylint-link\n```\n\nDylint is a Rust linting tool, similar to Clippy. But whereas Clippy runs a predetermined, static set of lints, Dylint runs lints from user-specified, dynamic libraries. Thus, Dylint allows developers to maintain their own personal lint collections.\n\n**Contents**\n\n- [Quick start]\n  - [Running Dylint]\n  - [Writing lints]\n- [Features]\n  - [Workspace metadata]\n  - [Configurable libraries]\n  - [Conditional compilation]\n  - [VS Code integration]\n- [Utilities]\n- [Resources]\n- [MSRV policy]\n\nDocumentation is also available on [how Dylint works].\n\n## Quick start\n\n### Running Dylint\n\nThe next two steps install Dylint and run all of this repository's [general-purpose, example lints] on a workspace:\n\n1. Install `cargo-dylint` and `dylint-link`:\n\n   ```sh\n   cargo install cargo-dylint dylint-link\n   ```\n\n2. Run `cargo-dylint`:\n   ```sh\n   cargo dylint --git https://github.com/trailofbits/dylint --pattern examples/general\n   ```\n\nIn the above example, the libraries are found via the command line. If you plan to run Dylint regularly, then consider using [workspace metadata]. For additional ways of finding libraries, see [How Dylint works].\n\n### Writing lints\n\nYou can start writing your own Dylint library by running `cargo dylint new new_lint_name`. Doing so will produce a loadable library right out of the box. You can verify this as follows:\n\n```sh\ncargo dylint new new_lint_name\ncd new_lint_name\ncargo build\ncargo dylint list --path .\n```\n\nAll you have to do is implement the [`LateLintPass`] trait and accommodate the symbols asking to be filled in.\n\nHelpful [resources] for writing lints appear below.\n\n## Features\n\n### Workspace metadata\n\nA workspace can name the libraries it should be linted with in its `Cargo.toml` or `dylint.toml` file. Specifically, either file can contain a TOML array under `workspace.metadata.dylint.libraries`. Each array entry must have the form of a Cargo `git` or `path` dependency, with the following differences:\n\n- There is no leading package name, i.e., no `package =`.\n- `path` entries can contain [glob] patterns, e.g., `*`.\n- Any entry can contain a `pattern` field whose value is a [glob] pattern. The `pattern` field indicates the subdirectories that contain Dylint libraries.\n\nDylint downloads and builds each entry, similar to how Cargo downloads and builds a dependency. The resulting `target/release` directories are searched for files with names of the form that Dylint recognizes (see [Library requirements] under [How Dylint works]).\n\nAs an example, if you include the following in your workspace's `Cargo.toml` or `dylint.toml` file and run `cargo dylint --all`, Dylint will run all of this repository's [example general-purpose lints], as well as the example restriction lint [`try_io_result`].\n\n```toml\n[workspace.metadata.dylint]\nlibraries = [\n    { git = \"https://github.com/trailofbits/dylint\", pattern = \"examples/general\" },\n    { git = \"https://github.com/trailofbits/dylint\", pattern = \"examples/restriction/try_io_result\" },\n]\n```\n\nFor convenience, the `pattern` field can contain an array, in which case the pattern is considered to be the union of the array elements. Thus, the just given `workspace.metadata.dylint.libraries` example could alternatively be written as:\n\n```toml\n[workspace.metadata.dylint]\nlibraries = [\n    { git = \"https://github.com/trailofbits/dylint\", pattern = [\n        \"examples/general\",\n        \"examples/restriction/try_io_result\",\n    ] },\n]\n```\n\n### Configurable libraries\n\nLibraries can be configured by including a `dylint.toml` file in a linted workspace's root directory. The file should encode a [toml table] whose keys are library names. A library determines how its value in the table (if any) is interpreted.\n\nAs an example, a `dylint.toml` file with the following contents sets the [`non_local_effect_before_error_return`] library's `work_limit` configuration to `1_000_000`:\n\n```toml\n[non_local_effect_before_error_return]\nwork_limit = 1_000_000\n```\n\nFor instructions on creating a configurable library, see the [`dylint_linting`] documentation.\n\n### Conditional compilation\n\nFor each library that Dylint uses to check a crate, Dylint passes the following to the Rust compiler:\n\n```sh\n--cfg=dylint_lib=\"LIBRARY_NAME\"\n```\n\nYou can use this feature to allow a lint when Dylint is used, but also avoid an \"unknown lint\" warning when Dylint is not used. Specifically, you can do the following:\n\n```rust\n#[cfg_attr(dylint_lib = \"LIBRARY_NAME\", allow(LINT_NAME))]\n```\n\nNote that `LIBRARY_NAME` and `LINT_NAME` may be the same. For an example involving [`non_thread_safe_call_in_test`], see [dylint/src/lib.rs] in this repository.\n\nAlso note that the just described approach does not work for pre-expansion lints. The only known workaround for pre-expansion lints is to allow the compiler's built-in [`unknown_lints`] lint. Specifically, you can do the following:\n\n```rust\n#[allow(unknown_lints)]\n#[allow(PRE_EXPANSION_LINT_NAME)]\n```\n\nFor an example involving [`abs_home_path`], see [internal/src/examples.rs] in this repository.\n\n#### Rustc's `unexpected_cfg` lint\n\nAs of nightly-2024-05-05, the names and values of every reachable `#[cfg]` [are checked]. This causes the compiler to produce warnings for `cfg_attr` attributes as described above.\n\nTo suppress such warnings, add the following to your packages' Cargo.toml files:\n\n```toml\n[lints.rust.unexpected_cfgs]\nlevel = \"warn\"\ncheck-cfg = [\"cfg(dylint_lib, values(any()))\"]\n```\n\nOr, if you're using a Cargo workspace, add the following the workspace's Cargo.toml file:\n\n```toml\n[workspace.lints.rust.unexpected_cfgs]\nlevel = \"warn\"\ncheck-cfg = [\"cfg(dylint_lib, values(any()))\"]\n```\n\nThen, add the following to the Cargo.toml file of each package in the workspace:\n\n```toml\n[lints]\nworkspace = true\n```\n\nFor an example, see commit [`c8fabc5`] in this repository.\n\n### VS Code integration\n\nDylint results can be viewed in VS Code using [rust-analyzer]. To do so, add the following to your VS Code `settings.json` file:\n\n```json\n    \"rust-analyzer.checkOnSave.overrideCommand\": [\n        \"cargo\",\n        \"dylint\",\n        \"--all\",\n        \"--\",\n        \"--all-targets\",\n        \"--message-format=json\"\n    ]\n```\n\nIf you want to use rust-analyzer inside a lint library, you need to add the following to your VS Code `settings.json` file:\n\n```json\n    \"rust-analyzer.rustc.source\": \"discover\",\n```\n\nAnd add the following to the library's `Cargo.toml` file:\n\n```toml\n[package.metadata.rust-analyzer]\nrustc_private = true\n```\n\n## Utilities\n\nThe following utilities can be helpful for writing Dylint libraries:\n\n- [`dylint-link`] is a wrapper around Rust's default linker (`cc`) that creates a copy of your library with a filename that Dylint recognizes.\n- [`dylint_library!`] is a macro that automatically defines the `dylint_version` function and adds the `extern crate rustc_driver` declaration.\n- [`ui_test`] is a function that can be used to test Dylint libraries. It provides convenient access to the [`compiletest_rs`] package.\n- [`clippy_utils`] is a collection of utilities to make writing lints easier. It is generously made public by the Rust Clippy Developers. Note that, like `rustc`, `clippy_utils` provides no stability guarantees for its APIs.\n\n## Resources\n\nHelpful resources for writing lints include the following:\n\n- [Adding a new lint] (targeted at Clippy but still useful)\n- [Author lint]\n- [Common tools for writing lints]\n- [Guide to Rustc Development]\n- [Crate `rustc_hir`]\n- [Crate `rustc_middle`]\n- [Struct `rustc_lint::LateContext`]\n  - [Method `typeck_results`]\n  - [Field `tcx`]\n    - [Method `hir`]\n\n## MSRV policy\n\nA bump of the Dylint library's MSRV will be accompanied by a bump of at least Dylint's minor version.\n\nPut another way, we strive to preserve Dylint's MSRV when releasing bug fixes, and to change it only when releasing new features.\n\n[Test coverage]\n\n[Adding a new lint]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md\n[Author lint]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md#author-lint\n[Common tools for writing lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/common_tools_writing_lints.md\n[Conditional compilation]: #conditional-compilation\n[Configurable libraries]: #configurable-libraries\n[Crate `rustc_hir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/index.html\n[Crate `rustc_middle`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/index.html\n[Features]: #features\n[Field `tcx`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html#structfield.tcx\n[Guide to Rustc Development]: https://rustc-dev-guide.rust-lang.org/\n[How Dylint works]: ./docs/how_dylint_works.md\n[Library requirements]: ./docs/how_dylint_works.md#library-requirements\n[MSRV policy]: #msrv-policy\n[Method `hir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.hir\n[Method `typeck_results`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html#method.typeck_results\n[Quick start]: #quick-start\n[Resources]: #resources\n[Running Dylint]: #running-dylint\n[Struct `rustc_lint::LateContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html\n[Test coverage]: https://trailofbits.github.io/dylint/coverage/index.html\n[Utilities]: #utilities\n[VS Code integration]: #vs-code-integration\n[Workspace metadata]: #workspace-metadata\n[Writing lints]: #writing-lints\n[`LateLintPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html\n[`abs_home_path`]: ./examples/general/abs_home_path\n[`c8fabc5`]: https://github.com/trailofbits/dylint/pull/1240/commits/c8fabc59dff5564333d4b6d4108e5f09108a0b4a\n[`clippy_utils`]: https://github.com/rust-lang/rust-clippy/tree/master/clippy_utils\n[`compiletest_rs`]: https://github.com/Manishearth/compiletest-rs\n[`dylint-link`]: ./dylint-link\n[`dylint_library!`]: ./utils/linting\n[`dylint_linting`]: ./utils/linting\n[`non_local_effect_before_error_return`]: ./examples/general/non_local_effect_before_error_return\n[`non_thread_safe_call_in_test`]: ./examples/general/non_thread_safe_call_in_test\n[`try_io_result`]: ./examples/restriction/try_io_result\n[`ui_test`]: ./utils/testing\n[`unknown_lints`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unknown-lints\n[are checked]: https://blog.rust-lang.org/2024/05/06/check-cfg.html\n[dylint/src/lib.rs]: ./dylint/src/lib.rs\n[example general-purpose lints]: ./examples/general\n[general-purpose, example lints]: ./examples/README.md#general\n[glob]: https://docs.rs/glob/0.3.0/glob/struct.Pattern.html\n[how Dylint works]: ./docs/how_dylint_works.md\n[internal/src/examples.rs]: ./internal/src/examples.rs\n[resources]: #resources\n[rust-analyzer]: https://github.com/rust-analyzer/rust-analyzer\n[slides]: ./docs/2024-10-11%20Linting%20with%20Dylint%20(EuroRust).pdf\n[toml table]: https://toml.io/en/v1.0.0#table\n[video]: https://www.youtube.com/watch?v=MjlPUA7sAmA\n[workspace metadata]: #workspace-metadata\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fdylint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrailofbits%2Fdylint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fdylint/lists"}