rust-lang / rust-lang/rust-analyzer

Pass `cfg`s to `cargo metadata` to discover correct subset of `target.cfg(...)` dependencies

Open
#19,846 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-cargo C-feature
Dominant language
Rust
Stars
16.9k
Forks
2.2k
Avg merge
1d 12h
Merged PRs (30d)
72

Description

(This is somewhere between a bug report and a feature request)

At work we've got a setup where various cfgs are being set depending on outside configuration. For rust-analyzer, we set these via the rust-analyzer.cargo.cfgs setting:

{
  "rust-analyzer.cargo.cfgs": ["my_custom_cfg=foobar"],
}

This works fine as long as all cfg checks remain only in Rust code. We did start, however, to use target dependencies based on these cfgs as well:

[target.'cfg(my_custom_cfg = "foobar")'.dependencies]
bar = { workspace = true }

Sadly, rust-analyzer doesn't recognize and load these dependencies, and the relevant imports and code lose all LSP benefits.

A minimal reproduction repository can be found here: https://github.com/seritools/cfg-dependencies-repro

I've looked into what's happening and traced it back to the cargo metadata call in CargoWorkspace::fetch_metadata_: Generally, rust-analyzer passes the --filter-platform argument to cargo metadata, to filter out dependencies for other targets. It seems that --filter-platform causes cargo metadata to evaluate all target.'cfg(...)' configurations, including those using custom cfgs.

Finally, the problem is that cfgs set via the rust-analyzer.cargo.cfgs setting are not passed to cargo metadata, meaning that the returned metadata becomes out of sync with the expected config.

To confirm that that is the problem (and as a hacky proof-of-concept solution) I patched rust-analyzer to inject the specified cfgs via CARGO_ENCODED_RUSTFLAGS: https://github.com/rust-lang/rust-analyzer/compare/master...seritools:rust-analyzer:extra-cfgs-for-cargo-metadata

I've confirmed that this allows cargo metadata to return the correct dependency tree. This proof of concept solution is of course not sane for general use (because of how it breaks RUSTFLAGS usage), but I hope it shows the issue and and idea for resolution.

Personally, I couldn't think of a way to implement this sanely that doesn't also involve extending cargo metadata -- something akin to --filter-cfg to pass in extra cfgs. What do you think? If that seems reasonable, I'll also create an issue in the cargo repository and link it to this one. Created the respective cargo issue: https://github.com/rust-lang/cargo/issues/15576

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at CargoWorkspace::fetch_metadata_ and trace how rust-analyzer's rust-analyzer.cargo.cfgs setting is used when invoking cargo metadata. Read the linked Cargo issue about passing extra cfgs, then determine an integration approach that preserves existing RUSTFLAGS behavior. Done means cargo metadata returns dependencies selected by the configured custom cfgs and the relevant imports regain LSP support.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.