Make `cargo.features` a crate-level config
workspace
|-crate1
|-crate2
|-crate3
|_crate4
crate 2 and 4 have a feature called "example_feature" that i want to enable for RA, so using a workspace setting is a no go, because RA will complain that crates 1 and 3 don't have this feature creating
rust-analyzer.tomlin crate 2 and 4's root and addingcargo.features = ["example_feature"]has no effect, however if i replace it withrust-analyzer.cargo.features = ["example_feature"], RA will complain that this is an invalid key that doesn't exist. So it reads the file but when it reads a correct key it doesn't apply that? I have no machine-wide or workspace or user overrides (using VSC right now but same happens in Vim).
Originally posted by @vaqxai in https://github.com/rust-lang/rust-analyzer/issues/13529#issuecomment-2345668435
What the title indicates is just a way to resolve this issue although making such a change is not wanted. This issue is just to discuss and shed a light on what we can do
crate 2 and 4 have a feature called "example_feature" that i want to enable for RA, so using a workspace setting is a no go,
@vaqxai I cannot reproduce any errors when I use cargo {build,check,metadata} --features example_feature. These are the three subcommands we use in rust-analyzer. Would you mind sharing your whole workspace ( I mean to say a minimal example where the said error is to be seen)?
I will try to give you a minimal example soon. Please note that I have experienced this error in VSCode and in Vim (both running rust-analyzer themselves), i haven't done a check without an IDE/Editor.
I think this error will manifest specifically when the workspace uses resolver = 2 and you pass a -p crate {1|3} to the build command, as either of those lack the features
I have compiled a reproducible repo, the full command that is being ran/error returned (by vscode?) is:
Failed to read Cargo metadata with dependencies for `/home/vaqxai/Documents/example_ra_cratefeatures/test2/Cargo.toml`:
Failed to run `cd "/home/vaqxai/Documents/example_ra_cratefeatures/test2"
&& RUSTUP_TOOLCHAIN="/home/vaqxai/.rustup/toolchains/stable-x86_64-unknown-linux-gnu"
"/home/vaqxai/.cargo/bin/cargo" "metadata"
"--format-version" "1"
"--features" "test_feat"
"--manifest-path" "/home/vaqxai/Documents/example_ra_cratefeatures/test2/Cargo.toml"
"--filter-platform" "x86_64-unknown-linux-gnu"`
: `cargo metadata` exited with an error: error: none of the selected packages contains these features: test_feat
Edit: It seems that VSCode runs cargo metadata for all workspace crates adding the features parameter, when it is set in .vscode/settings.json for that workspace, which causes the error. I can open up another issue with vscode for not having per-folder (crate) settings.json, but a rust-analyzer.toml that has a working, crate-level cargo.features seems more elegant and universal to have.
Edit no. 2: It seems sometime between my original issue and now there was a feature added that allows per folder .vscode/settings.json and they support rust-analyzer.cargo.features. So my error is kinda-solved for now (as long as I'm using VSCode only), but I do remember vim having similar issues, so a per-crate cargo.features in rust-analyzer.toml would still be "nice to have" (no longer a development-breaking issue though)
Edit no. 3: My bad, that setting is just ignored and I get code is inactive due to #[cfg] directives in the crate with the feature instead of the error.
So after some thorough investigation I can finally say a few things about this.
First things first : I believe #18197 has resolved resolved this issue in some ways : Your cargo check should consider features that you want to activate if you use the check.features = [ "test_feat" ]. As to cargo.features this is very tricky at the moment because there are tons of things missing in our codebase that should be propagating a cargo.features value all the way to cargo metadata command we run.
This is where things get more interesting :
Comically if you use VSCode's settings.json and use cargo.features I believe it will work ( the reasoning of which I will omit because it is not related).
It would be good to know the intention with setting cargo.features : Do you want cargo metadatas output to reflect the features/ are you trying to use our Run Test/Debug.
Finally, your repro is flawed in that you don't have proper workspace, due to which cargo metadata's manifest path points to /home/vaqxai/Documents/example_ra_cratefeatures/test2/Cargo.toml where it should have actually been pointing to /home/vaqxai/Documents/example_ra_cratefeatures/Cargo.toml
I am sorry if this is not the answer you were expecting. I would be happy to help if you can provide more context. 👋
First things first : I believe https://github.com/rust-lang/rust-analyzer/pull/18197 has resolved resolved this issue in some ways : Your cargo check should consider features that you want to activate if you use the check.features = [ "test_feat" ]. As to cargo.features this is very tricky at the moment because there are tons of things missing in our codebase that should be propagating a cargo.features value all the way to cargo metadata command we run.
Not sure if I omitted an update somewhere, AFAIK I'm using the latest nightly for everything, but it still won't work for me (i.e. nothing really changes, all cargo commands and VSC/VIM/ZED still act as if the feat was disabled)
Comically if you use VSCode's settings.json and use cargo.features I believe it will work ( the reasoning of which I will omit because it is not related).
It actually does, wow. That's very interesting.
Edit:
In Zed, which is curious, adding a .zed/settings.json with this:
{
"lsp": {
"rust-analyzer": {
"initialization_options": {
"cargo": {
"features": ["feat1"]
}
}
}
}
}
Works fine, ig zed runs RA per-folder/project
It would be good to know the intention with setting cargo.features : Do you want cargo metadatas output to reflect the features/ are you trying to use our Run Test/Debug.
Primarily, I want syntax highlighting, diagnostics, inlay hints and all other LSP features to work correctly, considering the feature tags I have currently enabled/disabled. The error I was getting earlier (with the metadata command) "crashes" RA for a given folder and makes it not generate/show any LSP things at all.
Finally, your repro is flawed in that you don't have proper workspace, due to which cargo metadata's manifest path points to /home/vaqxai/Documents/example_ra_cratefeatures/test2/Cargo.toml where it should have actually been pointing to /home/vaqxai/Documents/example_ra_cratefeatures/Cargo.toml
Yeah, that's the point, actually, I was trying to be able to attach many ad-hoc random directories to a vscode window / vim window / zed window and not create any actual cargo workspaces. Perhaps my usage of the word "workspace" is what threw it off. I basically wanted for RA to only consider crate-level feature toggles, treating them all as separate things. But, with the changes you consider for RA itself (i.e. to have a crate-level cargo.features) i don't think this is wrong reasoning.
P.S.
Currently, a good-enough, for-the-time-being solution would be to just have RA/cargo ignore the feature for a crate if it doesn't exist. So instead of having the error "features could not be enabled because they could not be found" it could be just a soft warning "features which do not exist have been requested, ignoring" and just run the rest of the command like nothing happened. Then I could enable as many features as I want (even in my global, "User" settings), and unless I have two crates with features named the same way, of which I only intended to enable one (which is an odd case even for me), there would be no problem. Could this be something we'd need to suggest to the cargo people (as the error I think originates in cargo-metadata and not rust-analyzer?)
I also encountered this issue today while using rust analyzer.
I have a workspace with one crate named add and another crate named xtask. The add crate has a feature named feat.
After setting "rust-analyzer.cargo.features": ["feat"] in settings.json, Rust Analyzer stopped working for the crate xtask, and prints
ERROR Flycheck failed to run the following command: CommandHandle { program: "/home/usamoi/.cargo/bin/cargo", arguments: ["check", "-p", "xtask", "--bin", "xtask", "--message-format=json-diagnostic-rendered-ansi", "--manifest-path", "/usamoi/usamoi/example/Cargo.toml", "--keep-going", "--all-targets", "--features", "feat"], current_dir: Some("/usamoi/usamoi/example") }, error=Cargo watcher failed, the command produced no valid metadata (exit code: ExitStatus(unix_wait_status(25856))):
error: the package 'xtask' does not contain this feature: feat
help: package with the missing feature: add
I have found one workaround for this.
If you define a dummy root package within the workspace toml file which lists all of the workspace crates that have features as dependancies, then you can control the features using "rust-analyzer.cargo.features": ["crate/feat"].
Eg. Suppose I have a workspace containing crates foo with feature red, bar with feature blue, and baz with no features. I would create a dummy root crate with dependancies:
[package]
name = "dummy"
version = "0.1.0"
authors = ["nobody@nowhere"]
edition = "2024"
[dependancies]
foo = { path = "foo" }
bar = { path = "bar" }
Then I could enable feature red of foo like this:
"rust-analyzer.cargo.features": [ "foo/baz" ],
and it somehow does not stop RA from checking files in baz.
EDIT: Actually, ignore this. It does allow RA to check the whole project (eg. if you restart RA) but if you trigger a check on a file that is part of a crate that does not have the feature, it will fail (for example, saving one of those files).