Configure flycheck using workspace.discoverConfig#18043
Configure flycheck using workspace.discoverConfig#18043Veykril merged 18 commits intorust-lang:masterfrom
Conversation
f1dbc97 to
52354dc
Compare
5bf5e0d to
09ef79a
Compare
davidbarsky
left a comment
There was a problem hiding this comment.
some assorted comments. I'll do another pass later.
| // Trigger flychecks for the only crate which the target belongs to | ||
| Some((_, krate)) => vec![krate], | ||
| None => { | ||
| tracing::debug!("flycheck scope: {:?}", scope); |
There was a problem hiding this comment.
| tracing::debug!("flycheck scope: {:?}", scope); | |
| tracing::debug!(?scope); |
| PackageToRestart::Package(PackageSpecifier::BuildInfo { label: _ }) => { | ||
| // No way to flycheck this single package. All we have is a build label. | ||
| // There's no way to really say whether this build label happens to be | ||
| // a cargo canonical name, so we won't try. | ||
| return None; | ||
| } |
There was a problem hiding this comment.
not a review comment, but more resignation: it's unfortunate that it is possible to have a PackageSpecifier::BuildInfo in FlycheckConfig::CargoCommand branch.
There was a problem hiding this comment.
We can rename it FlycheckConfig::Automatic. Because it is! In cargo workspaces it does cargo stuff; in json workspaces it does JSON stuff.
There was a problem hiding this comment.
Renamed to Automatic, it is a bit clearer.
| } | ||
|
|
||
| pub(crate) const SAVED_FILE_PLACEHOLDER: &str = "$saved_file"; | ||
| /// This is stable behaviour. Don't change. |
There was a problem hiding this comment.
fwiw, we can remove $saved_file with a bit of notice.
There was a problem hiding this comment.
actually, no, I lied we need to keep this for while. the main user of this is Fuchsia and until they're using Bazel, I don't think it's feasible to remove $saved_file.
There was a problem hiding this comment.
thanks for the ping. We'd actually be ok with removing $saved_file if we could use {label} in the flycheck override. Today we actually do that mapping ourselves (wrapper script checks a global file list to find all labels that include the saved file and runs a check build/clippy on all those in the build system).
I'd be happy to migrate us over to label replacement when this lands.
There was a problem hiding this comment.
I'm keeping it because I think it's still useful -- a build system might know that there are multiple crates that use a particular file and compile both. $saved_file is still there but prefer {saved_file} to match all other command interpolations.
|
Just to confirm my understanding: when you say:
The code changes here seem to imply that it'd be relying on the runnables in a |
|
Correct. However now that I think about it, the runnable templating would be a useful thing to expose to end users to override. They can then have custom test commands, debug commands, etc. (Noting that Meta's internal test harness has different flags to the OSS one. Would we want to have another configuration layer for rust-project to pick up and change its output? I would hope not!) |
Sorry, I realized I phrased my question ambiguously: are you planning on adding another field to
I agree! I think it's be nice to expose that via the standard rust-analyzer configuration mechanism.
Oi, I didn't realize that fact, but good to know. Lemme see if I can try and unify the two.
We should probably move this discussion over to the buck2 repo, but I've wanted a |
|
☔ The latest upstream changes (presumably #18123) made this pull request unmergeable. Please resolve the merge conflicts. |
|
What is the status of this? (Looking into cleaning up our PR backlog again but I haven't been following this PR) |
|
Well, I've been using it with my team pretty comfortably for 8 months. Will soon be upgrading a bunch of systems and will have to rebase this anyway. I will keep this PR updated when I do. |
09ef79a to
b6e93b8
Compare
|
@Veykril this is rebased onto master. I actually found during rebasing that a number of the things I did have been done independently in other PRs, just slightly differently. So the diff is a little smaller. To remind you:
This lets your 3rd party build tool configure how RA will flycheck. |
|
I'll try to take a look this week. |
e484bfc to
978412c
Compare
|
I also added a pretty big docs overhaul for non-cargo build systems. I recommend reviewing this commit-by-commit, as there is a bit of diff noise now due to some renames etc. |
978412c to
721eb04
Compare
|
Just gotta make clippy happy now and then I am fine with merging this 👍 |
This comment has been minimized.
This comment has been minimized.
…roject.json runnable For JSON / override users, pretty-print the custom flycheck command with fewer quote characters Better debug logging in flycheck
Because (1) it is what we use when there is no relevant config
(2) we automatically use either rust-project.json's flycheck, or cargo
This also puts check_command config into CargoOptions. It's a cargo option, after all.
It was pretty useless without this.
Previously:
Parsing target pattern `{label}`
Caused by:
Invalid target name `{label}`. (...)
Build ID: 6dab5942-d81c-4430-83b0-5ba523999050
Network: Up: 0B Down: 0B
Command: run.
Time elapsed: 0.3s
BUILD FAILED
* The terminal process "buck2 'run', '{label}'" terminated with exit code: 3.
rust-project requires {arg} these days. No good giving people bad information
even if it's not crucial to documenting this.
I am not familiar with this code at allso just doing what I can to unblock.
3c8ba82 to
96f0185
Compare
|
Clippy issues were in hir-ty, done. |
|
Ripper, thanks a ton mate |
|
Nice work! I particularly appreciate the docs polish too :) We should look at updating rust-project to use this new interpolation syntax too. |
After rust-lang#18043 introduced per-package flycheck for JSON projects, the code assumed that `world.flycheck` indices matched `world.workspaces` indices. However, not all workspaces have flycheck enabled (e.g., JSON projects without a flycheck template configured), so the flycheck vector can be shorter than the workspaces vector. This caused an index-out-of-bounds panic when saving a file in a JSON project without flycheck configured: thread 'Worker' panicked at notification.rs: index out of bounds: the len is 0 but the index is 0 Fix by looking up the flycheck handle by its ID (which is the workspace index set during spawn) rather than using the workspace index directly as a vector index.
PR rust-lang#18043 changed flycheck to be scoped to the relevant package. This broke projects using check commands that invoke rustc directly, because diagnostic JSON from rustc doesn't contain the package ID. This was visible in the rust-analyzer logs when RA_LOG is set to `rust_analyzer::flycheck=trace`. Before: 2026-02-02T07:03:48.020184937-08:00 TRACE diagnostic received flycheck_id=0 mismatched types package_id=None scope=Workspace ... 2026-02-02T07:03:55.082046488-08:00 TRACE clearing diagnostics flycheck_id=0 scope=Workspace After: 2026-02-02T07:14:32.760707785-08:00 TRACE diagnostic received flycheck_id=0 mismatched types package_id=None scope=Package { package: BuildInfo { label: "fbcode//rust_devx/rust-guess-deps:rust-guess-deps" }, workspace_deps: Some({}) } ... 2026-02-02T07:14:48.355981415-08:00 TRACE clearing diagnostics flycheck_id=0 scope=Package { package: BuildInfo { label: "fbcode//rust_devx/rust-guess-deps:rust-guess-deps" }, workspace_deps: Some({}) } Previously r-a assumed that a diagnostic without a package ID applied to the whole workspace. We would insert the diagnostic at the workspace level, but then only clear diagnostics for the package. As a result, red squiggles would get 'stuck'. Users who had fixed compilation issues would still see the old red squiggles until they introduced a new compilation error. Instead, always apply diagnostics to the current package if flycheck is scoped to a package and the diagnostic doesn't specify a package. This makes CargoCheckEvent(None) and CargoCheckEvent(Some(_)) more consistent, as they now both match on scope.
PR rust-lang#18043 changed flycheck to be scoped to the relevant package. This broke projects using check commands that invoke rustc directly, because diagnostic JSON from rustc doesn't contain the package ID. This was visible in the rust-analyzer logs when RA_LOG is set to `rust_analyzer::flycheck=trace`. Before: 2026-02-02T07:03:48.020184937-08:00 TRACE diagnostic received flycheck_id=0 mismatched types package_id=None scope=Workspace ... 2026-02-02T07:03:55.082046488-08:00 TRACE clearing diagnostics flycheck_id=0 scope=Workspace After: 2026-02-02T07:14:32.760707785-08:00 TRACE diagnostic received flycheck_id=0 mismatched types package_id=None scope=Package { package: BuildInfo { label: "fbcode//rust_devx/rust-guess-deps:rust-guess-deps" }, workspace_deps: Some({}) } ... 2026-02-02T07:14:48.355981415-08:00 TRACE clearing diagnostics flycheck_id=0 scope=Package { package: BuildInfo { label: "fbcode//rust_devx/rust-guess-deps:rust-guess-deps" }, workspace_deps: Some({}) } Previously r-a assumed that a diagnostic without a package ID applied to the whole workspace. We would insert the diagnostic at the workspace level, but then only clear diagnostics for the package. As a result, red squiggles would get 'stuck'. Users who had fixed compilation issues would still see the old red squiggles until they introduced a new compilation error. Instead, always apply diagnostics to the current package if flycheck is scoped to a package and the diagnostic doesn't specify a package. This makes CargoCheckEvent(None) and CargoCheckEvent(Some(_)) more consistent, as they now both match on scope.
See rust-lang#18043, and specifically commit 8d8cc93.
See rust-lang#18043, and specifically commit 8d8cc93.
See rust-lang#18043, and specifically commit 8d8cc93.
See rust-lang#18043, and specifically commit 8d8cc93.
See rust-lang#18043, and specifically commit 8d8cc93, which this partially reverts.
Recap of recent developments with non-Cargo build systems
rust-project.jsonon stdout and treats it like you put arust-project.jsonfile on disk.RunnableKind { Check, Run, TestOne, }. You cannot have the JSON project configure its own flychecks. Which means that configuring a non-Cargo build system is a complicated dance ofworkspace.discoverConfig+check.overrideCommand+"check.workspace": false.{label}substitution (available for runnables) was not usable for the flycheck command. I think because the only users of discoverConfig have been content with$saved_fileso far. So we currently have build labels in the JSON project that can't even be used for flychecking.What this does
This PR adds this functionality:
{label}. If you are not using discoverConfig / rust-project.json and therefore don't have build labels attached to crates, then{label}means the cargo canonical name. Previously we only supported$saved_filehere.And fixes:
Flychecks were being run on random downstream crates instead of the crate containing the file you saved, which would randomly result inThis was fixed in fix: Fix flycheck getting confused which package to check #18845 it seems, although it also appears to have completely disabled flycheck for rust-project.json. I certainly noticed there was no flycheck at all when I tried mainline RA on 2025-12-02. I guess if you don't add tests for behaviour, the behaviour slowly fades away!cargo check-ing a bigger downstream dependency, leading to unnecessarily slow flychecks and wasted CPU cycles. See the comments in notification.rs. I noticed this because the buck2rust-project checkcommand does not give diagnostics for dependencies of the target you ask for.Notes for users
For people actually using this, it works well in VSCode if you configure
rust-analyzer.workspace.discoverConfigin your settings.json, as per the manual. However, becauserust-analyzer.tomlsupport is still in its infancy, to get this going in Neovim, you will need my PR torustaceanvimto get the settings into the initialization request, and I advise having rustaceanvim autoload settings from a file calledrust-analyzer.json.Tagging: @alibektas @davidbarsky