Adds a dylint library under tooling/lints that flags Zed-specific anti-patterns: * shared_string_from_str_literal, * async_block_without_await, * entity_update_in_render, * notify_in_render, * owned_string_into_shared, * len_in_loop_condition, and * blocking_io_on_foreground. Includes UI tests, a single-lint helper, and workspace.metadata.dylint registration so cargo dylint --all discovers it. The library pins its own nightly toolchain (kept out of the main workspace) and tracks dylint 6. Release Notes: - N/A Self-Review Checklist: - [ ] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [ ] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Closes #ISSUE Release Notes: - N/A or Added/Fixed/Improved ...
3 KiB
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_literal—SharedString::new/frometc whereSharedString::from_staticshould be used instead.async_block_without_await—async { … }blocks whose body contains no.awaitexpression.entity_update_in_render—Entity::update/WeakEntity::updatemutating an entity insideRender::render.notify_in_render—Context::notify()called insideRender::render.owned_string_into_shared—String::from(<lit>).into()/<lit>.to_string().into()/<lit>.to_owned().into()whose target isSharedString,Arc<str>,Rc<str>, orCow<'_, 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-dylintis thecargosubcommand that builds and runs the lints;dylint-linkis 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-warnis required: after-A warningssilences the group, a plain-W <lint>does not reliably re-enable a driver-registered lint.DYLINT_RUSTFLAGSis 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.