Repository: rust-lang/cargo (rust)

Issue:
Activation of features of non-optional dependencies breaks manifest for 2024 edition
## Problem

Activation of an `foo/bar` feature dependency where `foo` is not an optional dependency results causes a manifest error in edition 2024:

```toml
[dependencies]
foo = "..."
bar = { version = "...", optional = true }

[features]
bar = ["dep:bar", "foo/bar"] # -> ["dep:bar", "foo/bar", "dep:foo"]
```

...results in...

```
feature `bar` includes `dep:foo`, but `foo` is not an optional dependency
```

### Explanation

#14221 introduces implicit activation of `dep:` for non-weak dependencies when parsing/updating the manifest in edition 2024. This issue appears to be to due to a missing check for whether or not the dependency of the activated feature is marked as optional.

This issue was also brought up in [a comment](https://github.com/rust-lang/cargo/pull/14221#discussion_r1686496418) post-merge, and in [a Zulip discussion](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Edition.202024.3A.20dep.20feature.20breakage.20with.20non-optional.20dep).

### Reproducible example

```toml
cargo-features = ["edition2024"]

[package]
name = "foobar"
edition = "2024"
version = "0.1.0"

[dependencies]
chrono = "0.4.38"
serde = { version = "1.0.204", optional = true }

[features]
serde = ["dep:serde", "chrono/serde"] # -> ["dep:serde", "chrono/serde", "dep:chrono"]
```

### Version

`cargo --version`:
```
cargo 1.82.0-nightly (5f6b9a922 2024-07-19)
release: 1.82.0-nightly
commit-hash: 5f6b9a92201d78af75dc24f14662c3e2dacbbbe1
commit-date: 2024-07-19
```


Pull request:
Revert "fix: Ensure dep/feature activates the dependency on 2024"
### What does this PR try to resolve?

Fixes #14283 by re-opening #14016 so we don't block people testing other Edition 2024 changes.


### How should we test and review this PR?

This reverts commit 99fae9187ac0bae12a03585083169e34dc7a197d.

I initially held off on reverting in case we quickly had a clear direction to go.  Since we're still doing some investigation, I decided to move forward with this.

### Additional information



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 48c68995b..2fec28b78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,44 +1,7 @@
 # Changelog
 
-## Cargo 1.82 (2024-10-17)
-[a2b58c3d...HEAD](https://github.com/rust-lang/cargo/compare/a2b58c3d...HEAD)
-
-### Added
-
-### Changed
-
-- Improved error message for missing both `[package]` and `[workspace]` in Cargo.toml.
-  [#14261](https://github.com/rust-lang/cargo/pull/14261)
-
-### Fixed
-
-### Nightly only
-
-- `-Ztarget-applies-to-host`: Fixed passing of links-overrides with
-  target-applies-to-host and an implicit target
-  [#14205](https://github.com/rust-lang/cargo/pull/14205)
-
-### Documentation
-
-### Internal
-
-- cargo-util-schemas: Added `TomlPackage::new`, `Default` for `TomlWorkspace`
-  [#14271](https://github.com/rust-lang/cargo/pull/14271)
-- Enhanced `cargo-test-support` usability and documentation.
-  [#14266](https://github.com/rust-lang/cargo/pull/14266)
-  [#14268](https://github.com/rust-lang/cargo/pull/14268)
-  [#14269](https://github.com/rust-lang/cargo/pull/14269)
-  [#14270](https://github.com/rust-lang/cargo/pull/14270)
-  [#14272](https://github.com/rust-lang/cargo/pull/14272)
-- Made summary sync by using Arc instead of Rc
-  [#14260](https://github.com/rust-lang/cargo/pull/14260)
-- Used `Rc` instead of `Arc` for storing rustflags
-  [#14273](https://github.com/rust-lang/cargo/pull/14273)
-- test: Migrated `global_cache_tracker` snapbox
-  [#14244](https://github.com/rust-lang/cargo/pull/14244)
-
 ## Cargo 1.81 (2024-09-05)
-[34a6a87d...rust-1.81.0](https://github.com/rust-lang/cargo/compare/34a6a87d...rust-1.81.0)
+[34a6a87d...HEAD](https://github.com/rust-lang/cargo/compare/34a6a87d...HEAD)
 
 ### Added
 
@@ -46,9 +9,6 @@
 
 - ❗️ cargo-package: Disallow `package.license-file` and `package.readme` pointing
   to non-existent files during packaging.
-- ❗️ cargo-package: generated `.cargo_vcs_info.json` is always incluced,
-  even when `--allow-dirty` is passed.
-  [#13960](https://github.com/rust-lang/cargo/pull/13960)
 - ❗️ Disallow passing `--release`/`--debug` flag along with the `--profile` flag.
   [#13971](https://github.com/rust-lang/cargo/pull/13971)
   [#13921](https://github.com/rust-lang/cargo/pull/13921)
@@ -56,21 +16,11 @@
   Rust plugin support has been deprecated for four years and was removed in 1.75.0.
   [#13902](https://github.com/rust-lang/cargo/pull/13902)
   [#14038](https://github.com/rust-lang/cargo/pull/14038)
-- Make the calculation of `-Cmetadata` for rustc consistent across platforms.
-  [#14107](https://github.com/rust-lang/cargo/pull/14107)
-- Emit a warning when `edition` is unset, even when MSRV is unset.
-  [#14110](https://github.com/rust-lang/cargo/pull/14110)
 
 ### Fixed
 
 - Fix a proc-macro example from a dependency affecting feature resolution.
   [#13892](https://github.com/rust-lang/cargo/pull/13892)
-- Don't warn on duplicate packages from using '..'.
-  [#14234](https://github.com/rust-lang/cargo/pull/14234)
-- Don't `du` on every git source load.
-  [#14252](https://github.com/rust-lang/cargo/pull/14252)
-- Don't warn about unreferenced duplicate packages 
-  [#14239](https://github.com/rust-lang/cargo/pull/14239)
 
 ### Nightly only
 
@@ -78,106 +28,34 @@
   allowing upgrading dependencies to breaking versions.
   [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#update-breaking)
   [#13979](https://github.com/rust-lang/cargo/pull/13979)
-  [#14047](https://github.com/rust-lang/cargo/pull/14047)
-  [#14049](https://github.com/rust-lang/cargo/pull/14049)
 - `--artifact-dir`: Rename `--out-dir` to `--artifact-dir`.
   The `--out-dir` flag is kept for compatibility
   and may be removed when the feature gets stabilized.
   [#13809](https://github.com/rust-lang/cargo/pull/13809)
 - `edition2024`: Ensure unused optional dependencies fire for shadowed dependencies.
   [#14028](https://github.com/rust-lang/cargo/pull/14028)
-- `edition2024`: Address problems with implicit -> explicit feature migration 
-  [#14018](https://github.com/rust-lang/cargo/pull/14018)
-- `edition2024`: Ensure `dep/feature` feature syntax activates the dependency
-  [#14221](https://github.com/rust-lang/cargo/pull/14221)
 - `-Zcargo-lints`: Add `unknown_lints` to lints list.
   [#14024](https://github.com/rust-lang/cargo/pull/14024)
 - `-Zcargo-lints`: Add tooling to document lints.
   [#14025](https://github.com/rust-lang/cargo/pull/14025)
 - `-Zcargo-lints`: Keep lints updated and sorted.
   [#14030](https://github.com/rust-lang/cargo/pull/14030)
-- `-Zconfig-include`: Allow enabling `config-include` feature in config.
-  [#14196](https://github.com/rust-lang/cargo/pull/14196)
-- `-Zpublic-dependency`: remove some legacy public dependency code from the resolver
-  [#14090](https://github.com/rust-lang/cargo/pull/14090)
-- `-Ztarget-applies-to-host`: Pass rustflags to artifacts built with implicit targets when using target-applies-to-host
-  [#13900](https://github.com/rust-lang/cargo/pull/13900)
-  [#14201](https://github.com/rust-lang/cargo/pull/14201)
 - cargo-update: Track the behavior of `--precise <prerelease>`.
   [#14013](https://github.com/rust-lang/cargo/pull/14013)
 
 ### Documentation
 
-- Clarify `CARGO_CFG_TARGET_FAMILY` is multi-valued.
-  [#14165](https://github.com/rust-lang/cargo/pull/14165)
-- Document `CARGO_CFG_TARGET_ABI`
-  [#14164](https://github.com/rust-lang/cargo/pull/14164)
-- Document MSRV for each manifest field and build script invocations.
-  [#14224](https://github.com/rust-lang/cargo/pull/14224)
-- Remove duplicate `strip` section. 
-  [#14146](https://github.com/rust-lang/cargo/pull/14146)
-- Update summary of Cargo configuration to include missing keys. 
-  [#14145](https://github.com/rust-lang/cargo/pull/14145)
-- Update index of Cargo documentation.
-  [#14228](https://github.com/rust-lang/cargo/pull/14228)
-- Don't mention non-existent `workspace.badges` field.
-  [#14042](https://github.com/rust-lang/cargo/pull/14042)
 - contrib: Suggest atomic commits with separate test commits.
   [#14014](https://github.com/rust-lang/cargo/pull/14014)
-- contrib: Document how to write an RFC for Cargo.
-  [#14222](https://github.com/rust-lang/cargo/pull/14222)
-- contrib: Improve triage instructions 
-  [#14052](https://github.com/rust-lang/cargo/pull/14052)
 
 ### Internal
 
-- cargo-package: Change verification order during packaging. 
-  [#14074](https://github.com/rust-lang/cargo/pull/14074)
-- ci: Add workflow to publish Cargo automatically 
-  [#14202](https://github.com/rust-lang/cargo/pull/14202)
-- ci: bump CI tools 
-  [#14062](https://github.com/rust-lang/cargo/pull/14062)
-  [#14257](https://github.com/rust-lang/cargo/pull/14257)
-- registry: Add local registry overlays.
-  [#13926](https://github.com/rust-lang/cargo/pull/13926)
-- registry: move `get_source_id` out of registry
-  [#14218](https://github.com/rust-lang/cargo/pull/14218)
-- resolver: Simplify checking for dependency cycles 
-  [#14089](https://github.com/rust-lang/cargo/pull/14089)
-- rustfix: Add `CodeFix::apply_solution` and impl `Clone` 
-  [#14092](https://github.com/rust-lang/cargo/pull/14092)
-- source: Clean up after `PathSource`/`RecursivePathSource` split
-  [#14169](https://github.com/rust-lang/cargo/pull/14169)
-  [#14231](https://github.com/rust-lang/cargo/pull/14231)
 - Remove the temporary `__CARGO_GITOXIDE_DISABLE_LIST_FILES` environment variable.
   [#14036](https://github.com/rust-lang/cargo/pull/14036)
-- Simplify checking feature syntax 
-  [#14106](https://github.com/rust-lang/cargo/pull/14106)
-- Dont make new constant `InternedString` in hot path 
-  [#14211](https://github.com/rust-lang/cargo/pull/14211)
-- Use `std::fs::absolute` instead of reimplementing it 
-  [#14075](https://github.com/rust-lang/cargo/pull/14075)
-- Remove unecessary feature activations from cargo.
-  [#14122](https://github.com/rust-lang/cargo/pull/14122)
-  [#14160](https://github.com/rust-lang/cargo/pull/14160)
-- Revert #13630 as rustc ignores `-C strip` on MSVC.
-  [#14061](https://github.com/rust-lang/cargo/pull/14061)
-- test: Allow `unexpected_builtin_cfgs` lint in `user_specific_cfgs` test 
-  [#14153](https://github.com/rust-lang/cargo/pull/14153)
-- test: Add cargo_test to test-support prelude 
-  [#14243](https://github.com/rust-lang/cargo/pull/14243)
-- test: migrate Cargo testsuite to `snapbox`.
-  For the complete list of migration pull requests,
-  see [#14039](https://github.com/rust-lang/cargo/issues/14039#issuecomment-2158974033)
 - Update dependencies.
   [#13995](https://github.com/rust-lang/cargo/pull/13995)
   [#13998](https://github.com/rust-lang/cargo/pull/13998)
   [#14037](https://github.com/rust-lang/cargo/pull/14037)
-  [#14063](https://github.com/rust-lang/cargo/pull/14063)
-  [#14067](https://github.com/rust-lang/cargo/pull/14067)
-  [#14174](https://github.com/rust-lang/cargo/pull/14174)
-  [#14186](https://github.com/rust-lang/cargo/pull/14186)
-  [#14254](https://github.com/rust-lang/cargo/pull/14254)
 
 ## Cargo 1.80 (2024-07-25)
 [b60a1555...rust-1.80.0](https://github.com/rust-lang/cargo/compare/b60a1555...rust-1.80.0)
diff --git a/Cargo.lock b/Cargo.lock
index faa5794dd..6fca15b18 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -266,7 +266,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.83.0"
+version = "0.82.0"
 dependencies = [
  "annotate-snippets",
  "anstream",
@@ -412,7 +412,7 @@ version = "0.3.0"
 
 [[package]]
 name = "cargo-test-support"
-version = "0.4.0"
+version = "0.3.0"
 dependencies = [
  "anstream",
  "anstyle",
diff --git a/Cargo.toml b/Cargo.toml
index 0b5888287..9b7f314e5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,7 +31,7 @@ cargo-credential-macos-keychain = { version = "0.4.7", path = "credential/cargo-
 cargo-credential-wincred = { version = "0.4.7", path = "credential/cargo-credential-wincred" }
 cargo-platform = { path = "crates/cargo-platform", version = "0.1.5" }
 cargo-test-macro = { version = "0.3.0", path = "crates/cargo-test-macro" }
-cargo-test-support = { version = "0.4.0", path = "crates/cargo-test-support" }
+cargo-test-support = { version = "0.3.0", path = "crates/cargo-test-support" }
 cargo-util = { version = "0.2.14", path = "crates/cargo-util" }
 cargo-util-schemas = { version = "0.5.0", path = "crates/cargo-util-schemas" }
 cargo_metadata = "0.18.1"
@@ -125,7 +125,7 @@ self_named_module_files = "warn"
 
 [package]
 name = "cargo"
-version = "0.83.0"
+version = "0.82.0"
 edition.workspace = true
 license.workspace = true
 rust-version = "1.79"  # MSRV:1
diff --git a/src/cargo/ops/cargo_update.rs b/src/cargo/ops/cargo_update.rs
index ab78988e5..c3d367311 100644
--- a/src/cargo/ops/cargo_update.rs
+++ b/src/cargo/ops/cargo_update.rs
@@ -14,7 +14,6 @@ use crate::util::toml_mut::manifest::LocalManifest;
 use crate::util::toml_mut::upgrade::upgrade_requirement;
 use crate::util::{style, OptVersionReq};
 use crate::util::{CargoResult, VersionExt};
-use anyhow::Context as _;
 use itertools::Itertools;
 use semver::{Op, Version, VersionReq};
 use std::cmp::Ordering;
@@ -225,10 +224,7 @@ pub fn upgrade_manifests(
 
     let to_update = to_update
         .iter()
-        .map(|spec| {
-            PackageIdSpec::parse(spec)
-                .with_context(|| format!("invalid package ID specification: `{spec}`"))
-        })
+        .map(|s| PackageIdSpec::parse(s))
         .collect::<Result<Vec<_>, _>>()?;
 
     // Updates often require a lot of modifications to the registry, so ensure
diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs
index e29a7ea66..2fa704a8b 100644
--- a/src/cargo/util/toml/mod.rs
+++ b/src/cargo/util/toml/mod.rs
@@ -324,7 +324,7 @@ fn resolve_toml(
             });
         resolved_toml.package = Some(resolved_package);
 
-        resolved_toml.features = resolve_features(original_toml.features.as_ref(), edition)?;
+        resolved_toml.features = resolve_features(original_toml.features.as_ref())?;
 
         resolved_toml.lib = targets::resolve_lib(
             original_toml.lib.as_ref(),
@@ -693,34 +693,11 @@ fn default_readme_from_package_root(package_root: &Path) -> Option<String> {
 #[tracing::instrument(skip_all)]
 fn resolve_features(
     original_features: Option<&BTreeMap<manifest::FeatureName, Vec<String>>>,
-    edition: Edition,
 ) -> CargoResult<Option<BTreeMap<manifest::FeatureName, Vec<String>>>> {
-    let Some(mut resolved_features) = original_features.cloned() else {
+    let Some(resolved_features) = original_features.cloned() else {
         return Ok(None);
     };
 
-    if Edition::Edition2024 <= edition {
-        for activations in resolved_features.values_mut() {
-            let mut deps = Vec::new();
-            for feature_value in activations.iter() {
-                let feature_value = FeatureValue::new(InternedString::new(feature_value));
-                let FeatureValue::DepFeature {
-                    dep_name,
-                    dep_feature: _,
-                    weak: false,
-                } = feature_value
-                else {
-                    continue;
-                };
-                let dep = FeatureValue::Dep { dep_name }.to_string();
-                if !activations.contains(&dep) {
-                    deps.push(dep);
-                }
-            }
-            activations.extend(deps);
-        }
-    }
-
     Ok(Some(resolved_features))
 }
 


Test patch:
diff --git a/crates/cargo-test-support/Cargo.toml b/crates/cargo-test-support/Cargo.toml
index f0daa08f2..42e0d6465 100644
--- a/crates/cargo-test-support/Cargo.toml
+++ b/crates/cargo-test-support/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cargo-test-support"
-version = "0.4.0"
+version = "0.3.0"
 edition.workspace = true
 rust-version = "1.79"  # MSRV:1
 license.workspace = true
diff --git a/tests/testsuite/features.rs b/tests/testsuite/features.rs
index f821395e3..7962f18f1 100644
--- a/tests/testsuite/features.rs
+++ b/tests/testsuite/features.rs
@@ -1889,27 +1889,17 @@ fn strong_dep_feature_edition2024() {
 
     p.cargo("metadata")
         .masquerade_as_nightly_cargo(&["edition2024"])
-        .with_stdout_data(
-            str![[r#"
-{
-  "metadata": null,
-  "packages": [
-    {
-      "features": {
-        "optional_dep": [
-          "optional_dep/foo",
-          "dep:optional_dep"
-        ]
-      },
-      "name": "foo",
-      "...": "{...}"
-    }
-  ],
-  "...": "{...}"
-}
-"#]]
-            .json(),
-        )
+        .with_status(101)
+        .with_stderr_data(str![[r#"
+[ERROR] feature `optional_dep` includes `optional_dep/foo`, but `optional_dep` is not a dependency
+ --> Cargo.toml:9:32
+  |
+9 |                 optional_dep = ["optional_dep/foo"]
+  |                                ^^^^^^^^^^^^^^^^^^^^
+  |
+[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
+
+"#]])
         .run();
 }
 
diff --git a/tests/testsuite/update.rs b/tests/testsuite/update.rs
index f27fd6888..1e74e32f9 100644
--- a/tests/testsuite/update.rs
+++ b/tests/testsuite/update.rs
@@ -2263,10 +2263,7 @@ fn update_breaking_spec_version() {
         .masquerade_as_nightly_cargo(&["update-breaking"])
         .with_status(101)
         .with_stderr_data(str![[r#"
-[ERROR] invalid package ID specification: `incompatible@foo`
-
-Caused by:
-  expected a version like "1.32"
+[ERROR] expected a version like "1.32"
 
 "#]])
         .run();