cargo icon indicating copy to clipboard operation
cargo copied to clipboard

cargo add cannot enable features if version="*" in Cargo.toml

Open georgmu opened this issue 1 year ago • 3 comments

Problem

When trying to run cargo add crate -F feature with crate = "*" or crate = { version="*" } in Cargo.toml, an error is returned.

Steps

  1. Add time = "*" to Cargo.toml
  2. Run the following command:
$ cargo +nightly add time -F serde
    Updating crates.io index
      Adding time * to dependencies
error: unrecognized feature for crate time: serde
no features available for crate time
  1. Change time = "*" to time = "0.3"
  2. Run the command again:
$ cargo +nightly add time -F serde
    Updating crates.io index
      Adding time v0.3 to dependencies
             Features as of v0.3.0:
             + alloc
             + serde
             + std
             - formatting
             - itoa
             - large-dates
             - local-offset
             - macros
             - parsing
             - quickcheck
             - quickcheck-dep
             - rand
             - serde-human-readable
             - time-macros

List of features changes when using the last concrete version (0.3.36).

Possible Solution(s)

For version="*", I would expect that it uses the feature list of the used root dependency (as in Cargo.lock) or of the latest version available.

Notes

No response

Version

cargo 1.83.0-nightly (80d82ca22 2024-09-27) release: 1.83.0-nightly commit-hash: 80d82ca22abbee5fb7b51fa1abeb1ae34e99e88a commit-date: 2024-09-27 host: x86_64-unknown-linux-gnu libgit2: 1.8.1 (sys:0.19.0 vendored) libcurl: 8.9.0-DEV (sys:0.4.74+curl-8.9.0 vendored ssl:OpenSSL/1.1.1w) ssl: OpenSSL 1.1.1w 11 Sep 2023 os: Fedora 41.0.0 (FortyOne) [64-bit]

georgmu avatar Oct 06 '24 11:10 georgmu

When cargo add looks for available features to display and validate against, it looks to the oldest version compatible with your version requirement, assuming

  1. You set the minimum supported version in your version requirement
  2. The dependency doesn't remove features, making this the lowest common denominator for your version requirement. Granted, this gets fuzzy with multi-major version requirements.

In your case, its picking time = "0.1.0" and only allowing features from that version.

epage avatar Oct 07 '24 16:10 epage

@Kelvin-1013 please don't post LLM responses without reading and reformatting.

weihanglo avatar Oct 08 '24 16:10 weihanglo

The behavior is written down here in code: https://github.com/rust-lang/cargo/blob/d8cb5fb7f8f66fc9b4ba3d80b089474164a8a83d/src/cargo/ops/cargo_add/mod.rs?plain=1#L1040-L1054

It seems pretty like an implementation detail relying on the assumption in the comment. I don't think this should be documented, and picking up the latest version isn't better either. I would propose we close this as the behavior is intended.

weihanglo avatar Nov 09 '24 18:11 weihanglo

imo if we did anything, it would likely to be lint against wildcard dependencies, see #5340

epage avatar Nov 11 '24 16:11 epage

It seems odd that cargo, which has a ton of code about resolving versions of crates, doesn't reuse this for determining which version's features are in play here? Especially in this case where the actual version is already known in Cargo.lock?

A diagnostic sounds good to me -- the current behaviour is surprising.

ctz avatar Nov 18 '24 09:11 ctz

The current version is in Cargo.lock but your dependency specification says any version in existence could be used instead. We are trying to pick features that work for your dependency specification. However, as I said earlier

Granted, this gets fuzzy with multi-major version requirements.

epage avatar Nov 18 '24 15:11 epage