zed/tooling/lints
Richard Feldman 872ca8fef5
Some checks are pending
Congratsbot / check-author (push) Waiting to run
Congratsbot / congrats (push) Blocked by required conditions
deploy_nightly_docs / deploy_docs (push) Waiting to run
run_tests / orchestrate (push) Waiting to run
run_tests / check_style (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
Add license symlinks to lint test fixture crates (#60505)
Stacked on #60502 and targets it — #60502 must land first (its
orchestrator fix is what lets this `tooling/lints/`-touching PR go green
rather than tripping the `rdeps(lints)` nextest filter). Re-creates the
symlinks from #60504, which was accidentally merged into #60502's branch
and reverted.

Follow-up to #60468, which added a `LICENSE-APACHE` symlink to the
`tooling/lints` crate but not to the `test_fixture` sub-crates. Those
five sub-crates each carry a `Cargo.toml`, so `script/check-licenses`
requires a `LICENSE-GPL`/`LICENSE-APACHE` symlink in each, and
`check_licenses` fails on any PR that changes `Cargo.lock`. This adds
`LICENSE-APACHE` symlinks to the five fixture crates, matching #60468;
`script/check-licenses` passes locally afterward.

Release Notes:

- N/A
2026-07-07 01:35:06 +00:00
..
.cargo
src
test_fixture Add license symlinks to lint test fixture crates (#60505) 2026-07-07 01:35:06 +00:00
ui
.gitignore
Cargo.toml
LICENSE-APACHE Add license to tooling/lints crate (#60468) 2026-07-06 16:10:48 +00:00
README.md
rust-toolchain.toml
single-lint

lints

A dylint library that flags various bad patterns in our codebase.

Install dylint, a pinned nightly toolchain and the necessary tools with

cargo install cargo-dylint dylint-link
cd tooling/lints
rustup toolchain install

The channel and its components (rustc-dev, rust-src, llvm-tools-preview) are declared in tooling/lints/rust-toolchain.toml, so rustup toolchain install picks them up automatically when run from that directory.

Demo

./single-lint blocking_io_on_foreground

Current lints

  • shared_string_from_str_literalSharedString::new/from etc where SharedString::from_static should be used instead.
  • async_block_without_awaitasync { … } blocks whose body contains no .await expression.
  • entity_update_in_renderEntity::update/WeakEntity::update mutating an entity inside Render::render.
  • notify_in_renderContext::notify() called inside Render::render.
  • owned_string_into_sharedString::from(<lit>).into() / <lit>.to_string().into() / <lit>.to_owned().into() whose target is SharedString, Arc<str>, Rc<str>, or Cow<'_, str>.
  • blocking_io_on_foreground - Catch blocking IO calls that are called on the main thread (but not on closures or background threads)

How to run

Ideally you run this as part of the clippy script in the zed/scripts directory since this will also run our other linters.

Prerequisites

Install both tools (version 6 or later):

cargo install cargo-dylint dylint-link
  • cargo-dylint is the cargo subcommand that builds and runs the lints; dylint-link is the linker used to build the lint library.

The workspace registers this library under [workspace.metadata.dylint] in the root Cargo.toml, so Dylint discovers it automatically — you do not pass a --path. The first run builds the library against its pinned nightly (see rust-toolchain.toml) and is slow; later runs are cached.

Run all lints against the whole repo

cargo dylint --all -- --workspace

Run all lints against a single crate

cargo dylint --all -- -p project_panel

Run a single lint

The library loads every lint at once. To run just one, use the single-lint helper, which silences the rest and force-enables the one you name:

tooling/lints/single-lint blocking_io_on_foreground -p project_panel

The first argument is the lint name (one of the snake_case identifiers under Current lints); everything after it is passed to cargo check and defaults to --workspace. Under the hood the script runs:

DYLINT_RUSTFLAGS="-A warnings --force-warn <lint>" cargo dylint --all -- <args>

It also handles two non-obvious gotchas:

  • --force-warn is required: after -A warnings silences the group, a plain -W <lint> does not reliably re-enable a driver-registered lint.
  • DYLINT_RUSTFLAGS is not part of Cargo's fingerprint, so the script cleans the targeted package(s) first; otherwise Cargo replays a stale cache and the filter appears to do nothing.