Dylint

A tool for running Rust lints from dynamic libraries

sh cargo install cargo-dylint dylint-link

Dylint 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.

Contents

Documentation is also available on [how Dylint works].

Quick start

Running Dylint

The next three steps install Dylint and run all of this repository's [general-purpose, example lints] on a workspace:

  1. Install cargo-dylint and dylint-link:

    sh cargo install cargo-dylint dylint-link

  2. Add the following to the workspace's Cargo.toml file:

    toml [workspace.metadata.dylint] libraries = [ { git = "https://github.com/trailofbits/dylint", pattern = "examples/general/*" }, ]

  3. Run cargo-dylint: sh cargo dylint --all --workspace

In the above example, the libraries are found via [workspace metadata], which is the recommended way. For additional ways of finding libraries, see [How Dylint works].

Writing lints

You 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:

sh cargo dylint new new_lint_name cd new_lint_name cargo build DYLINT_LIBRARY_PATH=$PWD/target/debug cargo dylint list --lib new_lint_name

All you have to do is implement the [LateLintPass] trait and accommodate the symbols asking to be filled in.

Helpful [resources] for writing lints appear below.

Features

Workspace metadata

A workspace can name the libraries it should be linted with in its Cargo.toml file. Specifically, a workspace's manifest can contain a TOML list under workspace.metadata.dylint.libraries. Each list entry must have the form of a Cargo git or path dependency, with the following differences:

Dylint 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]).

As an example, if you include the following in your workspace's Cargo.toml file and run cargo dylint --all --workspace, Dylint will run on your workspace all of this repository's [example general-purpose lints], as well as the example restriction lint [try_io_result].

toml [workspace.metadata.dylint] libraries = [ { git = "https://github.com/trailofbits/dylint", pattern = "examples/general/*" }, { git = "https://github.com/trailofbits/dylint", pattern = "examples/restriction/try_io_result" }, ]

Configurable libraries

Libraries 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.

As 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:

toml [non_local_effect_before_error_return] work_limit = 1_000_000

For instructions on creating a configurable library, see the [dylint_linting] documentation.

Conditional compilation

For each library that Dylint uses to check a crate, Dylint passes the following to the Rust compiler:

sh --cfg=dylint_lib="LIBRARY_NAME"

You 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:

```rust

[cfgattr(dylintlib = "LIBRARYNAME", allow(LINTNAME))]

```

Note 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.

Also note that the just described approach does not work for pre-expansion lints. The only known workaround for pre-expansion lints is allow the compiler's built-in [unknown_lints] lint. Specifically, you can do the following:

```rust

[allow(unknown_lints)]

[allow(PREEXPANSIONLINT_NAME)]

```

For an example involving [env_cargo_path], see [internal/src/examples.rs] in this repository.

VS Code integration

Dylint results can be viewed in VS Code using [rust-analyzer]. To do so, add the following to your VS Code settings.json file:

json "rust-analyzer.checkOnSave.overrideCommand": [ "cargo", "dylint", "--all", "--workspace", "--", "--all-targets", "--message-format=json" ]

If you want to use rust-analyzer inside a lint library, you need to add the following to your VS Code settings.json file:

json "rust-analyzer.rustc.source": "discover",

And add the following to the library's Cargo.toml file:

toml [package.metadata.rust-analyzer] rustc_private = true

Utilities

The following utilities can be helpful for writing Dylint libraries:

Resources

Helpful resources for writing lints include the following: