Skip to content

Pass cfgs to cargo metadata to discover correct subset of target.cfg(...) dependencies #19846

@seritools

Description

@seritools

(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: 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: rust-lang/cargo#15576

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-cargocargo related issuesC-featureCategory: feature request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions