git: ca25a32921ed - main - devel/cargo-c: backport dep: syntax support

From: Jan Beich <jbeich_at_FreeBSD.org>
Date: Sat, 05 Nov 2022 02:20:46 UTC
The branch main has been updated by jbeich:

URL: https://cgit.FreeBSD.org/ports/commit/?id=ca25a32921eda996ce79e41b0edf763e97b0b5d6

commit ca25a32921eda996ce79e41b0edf763e97b0b5d6
Author:     Jan Beich <jbeich@FreeBSD.org>
AuthorDate: 2022-11-05 01:20:54 +0000
Commit:     Jan Beich <jbeich@FreeBSD.org>
CommitDate: 2022-11-05 02:18:25 +0000

    devel/cargo-c: backport dep: syntax support
---
 devel/cargo-c/Makefile              |    2 +-
 devel/cargo-c/Makefile.crates       |    2 +-
 devel/cargo-c/distinfo              |    4 +-
 devel/cargo-c/files/patch-cargo-dep | 1602 +++++++++++++++++++++++++++++++++++
 graphics/libimagequant/Makefile     |    4 -
 5 files changed, 1606 insertions(+), 8 deletions(-)

diff --git a/devel/cargo-c/Makefile b/devel/cargo-c/Makefile
index b7f46933296d..e13be476cbfc 100644
--- a/devel/cargo-c/Makefile
+++ b/devel/cargo-c/Makefile
@@ -1,7 +1,7 @@
 PORTNAME=	cargo-c
 DISTVERSION=	0.9.8
 DISTVERSIONSUFFIX=	+cargo-0.60
-PORTREVISION=	6
+PORTREVISION=	7
 CATEGORIES=	devel
 MASTER_SITES=	CRATESIO
 # XXX Teach USES=cargo to have proper default
diff --git a/devel/cargo-c/Makefile.crates b/devel/cargo-c/Makefile.crates
index 6c17ec1c7551..f00ed94ac8bf 100644
--- a/devel/cargo-c/Makefile.crates
+++ b/devel/cargo-c/Makefile.crates
@@ -20,7 +20,7 @@ CARGO_CRATES=	adler-1.0.2 \
 		commoncrypto-sys-0.2.0 \
 		core-foundation-0.9.3 \
 		core-foundation-sys-0.8.3 \
-		crates-io-0.33.1 \
+		crates-io-0.34.0 \
 		crc32fast-1.3.2 \
 		crossbeam-utils-0.8.7 \
 		crypto-hash-0.3.4 \
diff --git a/devel/cargo-c/distinfo b/devel/cargo-c/distinfo
index bf272d89b486..cfbd081cd542 100644
--- a/devel/cargo-c/distinfo
+++ b/devel/cargo-c/distinfo
@@ -45,8 +45,8 @@ SHA256 (rust/crates/core-foundation-0.9.3.crate) = 194a7a9e6de53fa55116934067c84
 SIZE (rust/crates/core-foundation-0.9.3.crate) = 27059
 SHA256 (rust/crates/core-foundation-sys-0.8.3.crate) = 5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc
 SIZE (rust/crates/core-foundation-sys-0.8.3.crate) = 17519
-SHA256 (rust/crates/crates-io-0.33.1.crate) = b2d7714dc2b336c5a579a1a2aa2d41c7cd7a31ccb25e2ea908dba8934cfeb75a
-SIZE (rust/crates/crates-io-0.33.1.crate) = 9435
+SHA256 (rust/crates/crates-io-0.34.0.crate) = 6b4a87459133b2e708195eaab34be55039bc30e0d120658bd40794bb00b6328d
+SIZE (rust/crates/crates-io-0.34.0.crate) = 9543
 SHA256 (rust/crates/crc32fast-1.3.2.crate) = b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d
 SIZE (rust/crates/crc32fast-1.3.2.crate) = 38661
 SHA256 (rust/crates/crossbeam-utils-0.8.7.crate) = b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6
diff --git a/devel/cargo-c/files/patch-cargo-dep b/devel/cargo-c/files/patch-cargo-dep
new file mode 100644
index 000000000000..c042f3ba0986
--- /dev/null
+++ b/devel/cargo-c/files/patch-cargo-dep
@@ -0,0 +1,1602 @@
+https://github.com/rust-lang/cargo/commit/43a063c80a53
+
+--- cargo-crates/cargo-0.60.0/Cargo.toml.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/Cargo.toml
+@@ -50,7 +50,7 @@ version = "2.34.0"
+ version = "2.34.0"
+ 
+ [dependencies.crates-io]
+-version = "0.33.1"
++version = "0.34.0"
+ 
+ [dependencies.crossbeam-utils]
+ version = "0.8"
+--- cargo-crates/cargo-0.60.0/src/bin/cargo/commands/read_manifest.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/bin/cargo/commands/read_manifest.rs
+@@ -15,8 +15,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>
+ 
+ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
+     let ws = args.workspace(config)?;
+-    config
+-        .shell()
+-        .print_json(&ws.current()?.serialized(config))?;
++    config.shell().print_json(&ws.current()?.serialized())?;
+     Ok(())
+ }
+--- cargo-crates/cargo-0.60.0/src/cargo/core/features.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/core/features.rs
+@@ -642,7 +642,6 @@ unstable_cli_options!(
+     minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum"),
+     mtime_on_use: bool = ("Configure Cargo to update the mtime of used files"),
+     multitarget: bool = ("Allow passing multiple `--target` flags to the cargo subcommand selected"),
+-    namespaced_features: bool = ("Allow features with `dep:` prefix"),
+     no_index_update: bool = ("Do not update the registry index even if the cache is outdated"),
+     panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
+     host_config: bool = ("Enable the [host] section in the .cargo/config.toml file"),
+@@ -652,7 +651,6 @@ unstable_cli_options!(
+     terminal_width: Option<Option<usize>>  = ("Provide a terminal width to rustc for error truncation"),
+     timings: Option<Vec<String>>  = ("Display concurrency information"),
+     unstable_options: bool = ("Allow the usage of unstable options"),
+-    weak_dep_features: bool = ("Allow `dep_name?/feature` feature syntax"),
+     // TODO(wcrichto): move scrape example configuration into Cargo.toml before stabilization
+     // See: https://github.com/rust-lang/cargo/pull/9525#discussion_r728470927
+     rustdoc_scrape_examples: Option<String> = ("Allow rustdoc to scrape examples from reverse-dependencies for documentation"),
+@@ -707,6 +705,10 @@ const STABILIZED_FUTURE_INCOMPAT_REPORT: &str =
+ const STABILIZED_FUTURE_INCOMPAT_REPORT: &str =
+     "The future-incompat-report feature is now always enabled.";
+ 
++const STABILIZED_WEAK_DEP_FEATURES: &str = "Weak dependency features are now always available.";
++
++const STABILISED_NAMESPACED_FEATURES: &str = "Namespaced features are now always available.";
++
+ fn deserialize_build_std<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
+ where
+     D: serde::Deserializer<'de>,
+@@ -873,8 +875,8 @@ impl CliUnstable {
+             "multitarget" => self.multitarget = parse_empty(k, v)?,
+             "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
+             "terminal-width" => self.terminal_width = Some(parse_usize_opt(v)?),
+-            "namespaced-features" => self.namespaced_features = parse_empty(k, v)?,
+-            "weak-dep-features" => self.weak_dep_features = parse_empty(k, v)?,
++            "namespaced-features" => stabilized_warn(k, "1.60", STABILISED_NAMESPACED_FEATURES),
++            "weak-dep-features" => stabilized_warn(k, "1.60", STABILIZED_WEAK_DEP_FEATURES),
+             "credential-process" => self.credential_process = parse_empty(k, v)?,
+             "rustdoc-scrape-examples" => {
+                 if let Some(s) = v {
+--- cargo-crates/cargo-0.60.0/src/cargo/core/package.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/core/package.rs
+@@ -208,7 +208,7 @@ impl Package {
+         self.targets().iter().any(|t| t.is_example() || t.is_bin())
+     }
+ 
+-    pub fn serialized(&self, config: &Config) -> SerializedPackage {
++    pub fn serialized(&self) -> SerializedPackage {
+         let summary = self.manifest().summary();
+         let package_id = summary.package_id();
+         let manmeta = self.manifest().metadata();
+@@ -222,27 +222,19 @@ impl Package {
+             .filter(|t| t.src_path().is_path())
+             .cloned()
+             .collect();
+-        let features = if config.cli_unstable().namespaced_features {
+-            // Convert Vec<FeatureValue> to Vec<InternedString>
+-            summary
+-                .features()
+-                .iter()
+-                .map(|(k, v)| {
+-                    (
+-                        *k,
+-                        v.iter()
+-                            .map(|fv| InternedString::new(&fv.to_string()))
+-                            .collect(),
+-                    )
+-                })
+-                .collect()
+-        } else {
+-            self.manifest()
+-                .original()
+-                .features()
+-                .cloned()
+-                .unwrap_or_default()
+-        };
++        // Convert Vec<FeatureValue> to Vec<InternedString>
++        let features = summary
++            .features()
++            .iter()
++            .map(|(k, v)| {
++                (
++                    *k,
++                    v.iter()
++                        .map(|fv| InternedString::new(&fv.to_string()))
++                        .collect(),
++                )
++            })
++            .collect();
+ 
+         SerializedPackage {
+             name: package_id.name(),
+--- cargo-crates/cargo-0.60.0/src/cargo/core/resolver/features.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/core/resolver/features.rs
+@@ -1,19 +1,14 @@
+ //! Feature resolver.
+ //!
+ //! This is a new feature resolver that runs independently of the main
+-//! dependency resolver. It is enabled when the user specifies `resolver =
+-//! "2"` in `Cargo.toml`.
++//! dependency resolver. It has several options which can enable new feature
++//! resolution behavior.
+ //!
+ //! One of its key characteristics is that it can avoid unifying features for
+ //! shared dependencies in some situations. See `FeatureOpts` for the
+ //! different behaviors that can be enabled. If no extra options are enabled,
+ //! then it should behave exactly the same as the dependency resolver's
+-//! feature resolution. This can be verified by setting the
+-//! `__CARGO_FORCE_NEW_FEATURES=compare` environment variable and running
+-//! Cargo's test suite (or building other projects), and checking if it
+-//! panics. Note: the `features2` tests will fail because they intentionally
+-//! compare the old vs new behavior, so forcing the old behavior will
+-//! naturally fail the tests.
++//! feature resolution.
+ //!
+ //! The preferred way to engage this new resolver is via
+ //! `resolve_ws_with_opts`.
+@@ -59,22 +54,12 @@ pub struct ResolvedFeatures {
+     ///
+     /// The value is the `name_in_toml` of the dependencies.
+     activated_dependencies: ActivateMap,
+-    /// This is only here for legacy support when the new resolver is not enabled.
+-    ///
+-    /// This is the set of features enabled for each package.
+-    legacy_features: Option<HashMap<PackageId, Vec<InternedString>>>,
+-    /// This is only here for legacy support when the new resolver is not enabled.
+-    ///
+-    /// This is the set of optional dependencies enabled for each package.
+-    legacy_dependencies: Option<HashMap<PackageId, HashSet<InternedString>>>,
+     opts: FeatureOpts,
+ }
+ 
+ /// Options for how the feature resolver works.
+ #[derive(Default)]
+ pub struct FeatureOpts {
+-    /// Use the new resolver instead of the old one.
+-    new_resolver: bool,
+     /// Build deps and proc-macros will not share share features with other dep kinds.
+     decouple_host_deps: bool,
+     /// Dev dep features will not be activated unless needed.
+@@ -132,7 +117,6 @@ impl FeatureOpts {
+         let mut opts = FeatureOpts::default();
+         let unstable_flags = ws.config().cli_unstable();
+         let mut enable = |feat_opts: &Vec<String>| {
+-            opts.new_resolver = true;
+             for opt in feat_opts {
+                 match opt.as_ref() {
+                     "build_dep" | "host_dep" => opts.decouple_host_deps = true,
+@@ -159,15 +143,6 @@ impl FeatureOpts {
+                 enable(&vec!["all".to_string()]).unwrap();
+             }
+         }
+-        // This env var is intended for testing only.
+-        if let Ok(env_opts) = std::env::var("__CARGO_FORCE_NEW_FEATURES") {
+-            if env_opts == "1" {
+-                opts.new_resolver = true;
+-            } else {
+-                let env_opts = env_opts.split(',').map(|s| s.to_string()).collect();
+-                enable(&env_opts)?;
+-            }
+-        }
+         if let HasDevUnits::Yes = has_dev_units {
+             // Dev deps cannot be decoupled when they are in use.
+             opts.decouple_dev_deps = false;
+@@ -175,10 +150,6 @@ impl FeatureOpts {
+         if let ForceAllTargets::Yes = force_all_targets {
+             opts.ignore_inactive_targets = false;
+         }
+-        if unstable_flags.weak_dep_features {
+-            // Force this ON because it only works with the new resolver.
+-            opts.new_resolver = true;
+-        }
+         Ok(opts)
+     }
+ 
+@@ -187,7 +158,6 @@ impl FeatureOpts {
+         match behavior {
+             ResolveBehavior::V1 => FeatureOpts::default(),
+             ResolveBehavior::V2 => FeatureOpts {
+-                new_resolver: true,
+                 decouple_host_deps: true,
+                 decouple_dev_deps: has_dev_units == HasDevUnits::No,
+                 ignore_inactive_targets: true,
+@@ -306,18 +276,11 @@ impl ResolvedFeatures {
+         features_for: FeaturesFor,
+         dep_name: InternedString,
+     ) -> bool {
+-        if let Some(legacy) = &self.legacy_dependencies {
+-            legacy
+-                .get(&pkg_id)
+-                .map(|deps| deps.contains(&dep_name))
+-                .unwrap_or(false)
+-        } else {
+-            let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
+-            self.activated_dependencies
+-                .get(&(pkg_id, is_build))
+-                .map(|deps| deps.contains(&dep_name))
+-                .unwrap_or(false)
+-        }
++        let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
++        self.activated_dependencies
++            .get(&(pkg_id, is_build))
++            .map(|deps| deps.contains(&dep_name))
++            .unwrap_or(false)
+     }
+ 
+     /// Variant of `activated_features` that returns `None` if this is
+@@ -336,15 +299,11 @@ impl ResolvedFeatures {
+         pkg_id: PackageId,
+         features_for: FeaturesFor,
+     ) -> CargoResult<Vec<InternedString>> {
+-        if let Some(legacy) = &self.legacy_features {
+-            Ok(legacy.get(&pkg_id).map_or_else(Vec::new, |v| v.clone()))
++        let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
++        if let Some(fs) = self.activated_features.get(&(pkg_id, is_build)) {
++            Ok(fs.iter().cloned().collect())
+         } else {
+-            let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
+-            if let Some(fs) = self.activated_features.get(&(pkg_id, is_build)) {
+-                Ok(fs.iter().cloned().collect())
+-            } else {
+-                bail!("features did not find {:?} {:?}", pkg_id, is_build)
+-            }
++            bail!("features did not find {:?} {:?}", pkg_id, is_build)
+         }
+     }
+ 
+@@ -352,14 +311,16 @@ impl ResolvedFeatures {
+     ///
+     /// Used by `cargo fix --edition` to display any differences.
+     pub fn compare_legacy(&self, legacy: &ResolvedFeatures) -> DiffMap {
+-        let legacy_features = legacy.legacy_features.as_ref().unwrap();
+         self.activated_features
+             .iter()
+             .filter_map(|((pkg_id, for_host), new_features)| {
+-                let old_features = match legacy_features.get(pkg_id) {
+-                    Some(feats) => feats.iter().cloned().collect(),
+-                    None => BTreeSet::new(),
+-                };
++                let old_features = legacy
++                    .activated_features
++                    .get(&(*pkg_id, *for_host))
++                    // The new features may have for_host entries where the old one does not.
++                    .or_else(|| legacy.activated_features.get(&(*pkg_id, false)))
++                    .map(|feats| feats.iter().cloned().collect())
++                    .unwrap_or_else(|| BTreeSet::new());
+                 // The new resolver should never add features.
+                 assert_eq!(new_features.difference(&old_features).next(), None);
+                 let removed_features: BTreeSet<_> =
+@@ -427,17 +388,6 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
+     ) -> CargoResult<ResolvedFeatures> {
+         use crate::util::profile;
+         let _p = profile::start("resolve features");
+-
+-        if !opts.new_resolver {
+-            // Legacy mode.
+-            return Ok(ResolvedFeatures {
+-                activated_features: HashMap::new(),
+-                activated_dependencies: HashMap::new(),
+-                legacy_features: Some(resolve.features_clone()),
+-                legacy_dependencies: Some(compute_legacy_deps(resolve)),
+-                opts,
+-            });
+-        }
+         let track_for_host = opts.decouple_host_deps || opts.ignore_inactive_targets;
+         let mut r = FeatureResolver {
+             ws,
+@@ -460,8 +410,6 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
+         Ok(ResolvedFeatures {
+             activated_features: r.activated_features,
+             activated_dependencies: r.activated_dependencies,
+-            legacy_features: None,
+-            legacy_dependencies: None,
+             opts: r.opts,
+         })
+     }
+@@ -825,20 +773,4 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
+             .expect("packages downloaded")
+             .proc_macro()
+     }
+-}
+-
+-/// Computes a map of PackageId to the set of optional dependencies that are
+-/// enabled for that dep (when the new resolver is not enabled).
+-fn compute_legacy_deps(resolve: &Resolve) -> HashMap<PackageId, HashSet<InternedString>> {
+-    let mut result: HashMap<PackageId, HashSet<InternedString>> = HashMap::new();
+-    for pkg_id in resolve.iter() {
+-        for (_dep_id, deps) in resolve.deps(pkg_id) {
+-            for dep in deps {
+-                if dep.is_optional() {
+-                    result.entry(pkg_id).or_default().insert(dep.name_in_toml());
+-                }
+-            }
+-        }
+-    }
+-    result
+ }
+--- cargo-crates/cargo-0.60.0/src/cargo/core/summary.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/core/summary.rs
+@@ -23,8 +23,6 @@ struct Inner {
+     package_id: PackageId,
+     dependencies: Vec<Dependency>,
+     features: Rc<FeatureMap>,
+-    has_namespaced_features: bool,
+-    has_overlapping_features: Option<InternedString>,
+     checksum: Option<String>,
+     links: Option<InternedString>,
+ }
+@@ -37,15 +35,11 @@ impl Summary {
+         features: &BTreeMap<InternedString, Vec<InternedString>>,
+         links: Option<impl Into<InternedString>>,
+     ) -> CargoResult<Summary> {
+-        // ****CAUTION**** If you change anything here than may raise a new
++        // ****CAUTION**** If you change anything here that may raise a new
+         // error, be sure to coordinate that change with either the index
+         // schema field or the SummariesCache version.
+-        let mut has_overlapping_features = None;
+         for dep in dependencies.iter() {
+             let dep_name = dep.name_in_toml();
+-            if features.contains_key(&dep_name) {
+-                has_overlapping_features = Some(dep_name);
+-            }
+             if dep.is_optional() && !dep.is_transitive() {
+                 bail!(
+                     "dev-dependencies are not allowed to be optional: `{}`",
+@@ -53,8 +47,7 @@ impl Summary {
+                 )
+             }
+         }
+-        let (feature_map, has_namespaced_features) =
+-            build_feature_map(config, pkg_id, features, &dependencies)?;
++        let feature_map = build_feature_map(config, pkg_id, features, &dependencies)?;
+         Ok(Summary {
+             inner: Rc::new(Inner {
+                 package_id: pkg_id,
+@@ -62,8 +55,6 @@ impl Summary {
+                 features: Rc::new(feature_map),
+                 checksum: None,
+                 links: links.map(|l| l.into()),
+-                has_namespaced_features,
+-                has_overlapping_features,
+             }),
+         })
+     }
+@@ -87,46 +78,6 @@ impl Summary {
+         &self.inner.features
+     }
+ 
+-    /// Returns an error if this Summary is using an unstable feature that is
+-    /// not enabled.
+-    pub fn unstable_gate(
+-        &self,
+-        namespaced_features: bool,
+-        weak_dep_features: bool,
+-    ) -> CargoResult<()> {
+-        if !namespaced_features {
+-            if self.inner.has_namespaced_features {
+-                bail!(
+-                    "namespaced features with the `dep:` prefix are only allowed on \
+-                     the nightly channel and requires the `-Z namespaced-features` flag on the command-line"
+-                );
+-            }
+-            if let Some(dep_name) = self.inner.has_overlapping_features {
+-                bail!(
+-                    "features and dependencies cannot have the same name: `{}`",
+-                    dep_name
+-                )
+-            }
+-        }
+-        if !weak_dep_features {
+-            for (feat_name, features) in self.features() {
+-                for fv in features {
+-                    if matches!(fv, FeatureValue::DepFeature { weak: true, .. }) {
+-                        bail!(
+-                            "optional dependency features with `?` syntax are only \
+-                             allowed on the nightly channel and requires the \
+-                             `-Z weak-dep-features` flag on the command line\n\
+-                             Feature `{}` had feature value `{}`.",
+-                            feat_name,
+-                            fv
+-                        );
+-                    }
+-                }
+-            }
+-        }
+-        Ok(())
+-    }
+-
+     pub fn checksum(&self) -> Option<&str> {
+         self.inner.checksum.as_deref()
+     }
+@@ -181,16 +132,12 @@ impl Hash for Summary {
+ 
+ /// Checks features for errors, bailing out a CargoResult:Err if invalid,
+ /// and creates FeatureValues for each feature.
+-///
+-/// The returned `bool` indicates whether or not the `[features]` table
+-/// included a `dep:` prefixed namespaced feature (used for gating on
+-/// nightly).
+ fn build_feature_map(
+     config: &Config,
+     pkg_id: PackageId,
+     features: &BTreeMap<InternedString, Vec<InternedString>>,
+     dependencies: &[Dependency],
+-) -> CargoResult<(FeatureMap, bool)> {
++) -> CargoResult<FeatureMap> {
+     use self::FeatureValue::*;
+     let mut dep_map = HashMap::new();
+     for dep in dependencies.iter() {
+@@ -210,7 +157,6 @@ fn build_feature_map(
+             (*feature, fvs)
+         })
+         .collect();
+-    let has_namespaced_features = map.values().flatten().any(|fv| fv.has_dep_prefix());
+ 
+     // Add implicit features for optional dependencies if they weren't
+     // explicitly listed anywhere.
+@@ -372,7 +318,7 @@ fn build_feature_map(
+         );
+     }
+ 
+-    Ok((map, has_namespaced_features))
++    Ok(map)
+ }
+ 
+ /// FeatureValue represents the types of dependencies a feature can have.
+--- cargo-crates/cargo-0.60.0/src/cargo/ops/cargo_output_metadata.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/ops/cargo_output_metadata.rs
+@@ -31,9 +31,8 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &Outpu
+             VERSION
+         );
+     }
+-    let config = ws.config();
+     let (packages, resolve) = if opt.no_deps {
+-        let packages = ws.members().map(|pkg| pkg.serialized(config)).collect();
++        let packages = ws.members().map(|pkg| pkg.serialized()).collect();
+         (packages, None)
+     } else {
+         let (packages, resolve) = build_resolve_graph(ws, opt)?;
+@@ -152,11 +151,10 @@ fn build_resolve_graph(
+         );
+     }
+     // Get a Vec of Packages.
+-    let config = ws.config();
+     let actual_packages = package_map
+         .into_iter()
+         .filter_map(|(pkg_id, pkg)| node_map.get(&pkg_id).map(|_| pkg))
+-        .map(|pkg| pkg.serialized(config))
++        .map(|pkg| pkg.serialized())
+         .collect();
+ 
+     let mr = MetadataResolve {
+--- cargo-crates/cargo-0.60.0/src/cargo/ops/registry.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/ops/registry.rs
+@@ -287,7 +287,6 @@ fn transmit(
+                 license_file: license_file.clone(),
+                 badges: badges.clone(),
+                 links: links.clone(),
+-                v: None,
+             },
+             tarball,
+         )
+--- cargo-crates/cargo-0.60.0/src/cargo/sources/registry/index.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/sources/registry/index.rs
+@@ -293,8 +293,6 @@ impl<'cfg> RegistryIndex<'cfg> {
+     {
+         let source_id = self.source_id;
+         let config = self.config;
+-        let namespaced_features = self.config.cli_unstable().namespaced_features;
+-        let weak_dep_features = self.config.cli_unstable().weak_dep_features;
+ 
+         // First up actually parse what summaries we have available. If Cargo
+         // has run previously this will parse a Cargo-specific cache file rather
+@@ -309,11 +307,6 @@ impl<'cfg> RegistryIndex<'cfg> {
+         // minimize the amount of work being done here and parse as little as
+         // necessary.
+         let raw_data = &summaries.raw_data;
+-        let max_version = if namespaced_features || weak_dep_features {
+-            INDEX_V_MAX
+-        } else {
+-            1
+-        };
+         Ok(summaries
+             .versions
+             .iter_mut()
+@@ -328,7 +321,7 @@ impl<'cfg> RegistryIndex<'cfg> {
+                 },
+             )
+             .filter(move |is| {
+-                if is.v > max_version {
++                if is.v > INDEX_V_MAX {
+                     debug!(
+                         "unsupported schema version {} ({} {})",
+                         is.v,
+@@ -339,11 +332,6 @@ impl<'cfg> RegistryIndex<'cfg> {
+                 } else {
+                     true
+                 }
+-            })
+-            .filter(move |is| {
+-                is.summary
+-                    .unstable_gate(namespaced_features, weak_dep_features)
+-                    .is_ok()
+             }))
+     }
+ 
+--- cargo-crates/cargo-0.60.0/src/cargo/util/toml/mod.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/cargo/util/toml/mod.rs
+@@ -1299,8 +1299,6 @@ impl TomlManifest {
+             me.features.as_ref().unwrap_or(&empty_features),
+             project.links.as_deref(),
+         )?;
+-        let unstable = config.cli_unstable();
+-        summary.unstable_gate(unstable.namespaced_features, unstable.weak_dep_features)?;
+ 
+         let metadata = ManifestMetadata {
+             description: project.description.clone(),
+--- cargo-crates/cargo-0.60.0/src/doc/src/reference/features.md.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/doc/src/reference/features.md
+@@ -116,32 +116,47 @@ gif = { version = "0.11.1", optional = true }
+ gif = { version = "0.11.1", optional = true }
+ ```
+ 
+-Optional dependencies implicitly define a feature of the same name as the
+-dependency. This means that the same `cfg(feature = "gif")` syntax can be used
+-in the code, and the dependency can be enabled just like a feature such as
+-`--features gif` (see [Command-line feature
+-options](#command-line-feature-options) below).
++By default, this optional dependency implicitly defines a feature that looks
++like this:
+ 
+-> **Note**: A feature in the `[feature]` table cannot use the same name as a
+-> dependency. Experimental support for enabling this and other extensions is
+-> available on the nightly channel via [namespaced
+-> features](unstable.md#namespaced-features).
++```toml
++[features]
++gif = ["dep:gif"]
++```
+ 
+-Explicitly defined features can enable optional dependencies, too. Just
+-include the name of the optional dependency in the feature list. For example,
+-let's say in order to support the AVIF image format, our library needs two
+-other dependencies to be enabled:
++This means that this dependency will only be included if the `gif`
++feature is enabled.
++The same `cfg(feature = "gif")` syntax can be used in the code, and the
++dependency can be enabled just like any feature such as `--features gif` (see
++[Command-line feature options](#command-line-feature-options) below).
+ 
++In some cases, you may not want to expose a feature that has the same name
++as the optional dependency.
++For example, perhaps the optional dependency is an internal detail, or you
++want to group multiple optional dependencies together, or you just want to use
++a better name.
++If you specify the optional dependency with the `dep:` prefix anywhere
++in the `[features]` table, that disables the implicit feature.
++
++> **Note**: The `dep:` syntax is only available starting with Rust 1.60.
++> Previous versions can only use the implicit feature name.
++
++For example, let's say in order to support the AVIF image format, our library
++needs two other dependencies to be enabled:
++
+ ```toml
+ [dependencies]
+ ravif = { version = "0.6.3", optional = true }
+ rgb = { version = "0.8.25", optional = true }
+ 
+ [features]
+-avif = ["ravif", "rgb"]
++avif = ["dep:ravif", "dep:rgb"]
+ ```
+ 
+ In this example, the `avif` feature will enable the two listed dependencies.
++This also avoids creating the implicit `ravif` and `rgb` features, since we
++don't want users to enable those individually as they are internal details to
++our crate.
+ 
+ > **Note**: Another way to optionally include a dependency is to use
+ > [platform-specific dependencies]. Instead of using features, these are
+@@ -185,10 +200,31 @@ parallel = ["jpeg-decoder/rayon"]
+ parallel = ["jpeg-decoder/rayon"]
+ ```
+ 
+-> **Note**: The `"package-name/feature-name"` syntax will also enable
+-> `package-name` if it is an optional dependency. Experimental support for
+-> disabling that behavior is available on the nightly channel via [weak
+-> dependency features](unstable.md#weak-dependency-features).
++The `"package-name/feature-name"` syntax will also enable `package-name`
++if it is an optional dependency. Often this is not what you want.
++You can add a `?` as in `"package-name?/feature-name"` which will only enable
++the given feature if something else enables the optional dependency.
++
++> **Note**: The `?` syntax is only available starting with Rust 1.60.
++
++For example, let's say we have added some serialization support to our
++library, and it requires enabling a corresponding feature in some optional
++dependencies.
++That can be done like this:
++
++```toml
++[dependencies]
++serde = { version = "1.0.133", optional = true }
++rgb = { version = "0.8.25", optional = true }
++
++[features]
++serde = ["dep:serde", "rgb?/serde"]
++```
++
++In this example, enabling the `serde` feature will enable the serde
++dependency.
++It will also enable the `serde` feature for the `rgb` dependency, but only if
++something else has enabled the `rgb` dependency.
+ 
+ ### Command-line feature options
+ 
+--- cargo-crates/cargo-0.60.0/src/doc/src/reference/registries.md.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/doc/src/reference/registries.md
+@@ -263,7 +263,45 @@ explaining the format of the entry.
+     "yanked": false,
+     // The `links` string value from the package's manifest, or null if not
+     // specified. This field is optional and defaults to null.
+-    "links": null
++    "links": null,
++    // An unsigned 32-bit integer value indicating the schema version of this
++    // entry.
++    //
++    // If this not specified, it should be interpreted as the default of 1.
++    //
++    // Cargo (starting with version 1.51) will ignore versions it does not
++    // recognize. This provides a method to safely introduce changes to index
++    // entries and allow older versions of cargo to ignore newer entries it
++    // doesn't understand. Versions older than 1.51 ignore this field, and
++    // thus may misinterpret the meaning of the index entry.
++    //
++    // The current values are:
++    //
++    // * 1: The schema as documented here, not including newer additions.
++    //      This is honored in Rust version 1.51 and newer.
++    // * 2: The addition of the `features2` field.
++    //      This is honored in Rust version 1.60 and newer.
++    "v": 2,
++    // This optional field contains features with new, extended syntax.
++    // Specifically, namespaced features (`dep:`) and weak dependencies
++    // (`pkg?/feat`).
++    //
++    // This is separated from `features` because versions older than 1.19
++    // will fail to load due to not being able to parse the new syntax, even
++    // with a `Cargo.lock` file.
++    //
++    // Cargo will merge any values listed here with the "features" field.
++    //
++    // If this field is included, the "v" field should be set to at least 2.
++    //
++    // Registries are not required to use this field for extended feature
++    // syntax, they are allowed to include those in the "features" field.
++    // Using this is only necessary if the registry wants to support cargo
++    // versions older than 1.19, which in practice is only crates.io since
++    // those older versions do not support other registries.
++    "features2": {
++        "serde": ["dep:serde", "chrono?/serde"]
++    }
+ }
+ ```
+ 
+--- cargo-crates/cargo-0.60.0/src/doc/src/reference/unstable.md.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/src/doc/src/reference/unstable.md
+@@ -69,8 +69,6 @@ Each new feature described below should explain how to
+     * [avoid-dev-deps](#avoid-dev-deps) — Prevents the resolver from including dev-dependencies during resolution.
+     * [minimal-versions](#minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest.
+     * [public-dependency](#public-dependency) — Allows dependencies to be classified as either public or private.
+-    * [Namespaced features](#namespaced-features) — Separates optional dependencies into a separate namespace from regular features, and allows feature names to be the same as some dependency name.
+-    * [Weak dependency features](#weak-dependency-features) — Allows setting features for dependencies without enabling optional dependencies.
+ * Output behavior
+     * [out-dir](#out-dir) — Adds a directory where artifacts are copied to.
+     * [terminal-width](#terminal-width) — Tells rustc the width of the terminal so that long diagnostic messages can be truncated to be more readable.
+@@ -252,68 +250,6 @@ lto = true
+ lto = true
+ ```
+ 
+-
+-### Namespaced features
+-* Original issue: [#1286](https://github.com/rust-lang/cargo/issues/1286)
+-* Tracking Issue: [#5565](https://github.com/rust-lang/cargo/issues/5565)
+-
+-The `namespaced-features` option makes two changes to how features can be
+-specified:
+-
+-* Features may now be defined with the same name as a dependency.
+-* Optional dependencies can be explicitly enabled in the `[features]` table
+-  with the `dep:` prefix, which enables the dependency without enabling a
+-  feature of the same name.
+-
+-By default, an optional dependency `foo` will define a feature `foo =
+-["dep:foo"]` *unless* `dep:foo` is mentioned in any other feature, or the
+-`foo` feature is already defined. This helps prevent unnecessary boilerplate
+-of listing every optional dependency, but still allows you to override the
+-implicit feature.
+-
+-This allows two use cases that were previously not possible:
+-
+-* You can "hide" an optional dependency, so that external users cannot
+-  explicitly enable that optional dependency.
+-* There is no longer a need to create "funky" feature names to work around the
+-  restriction that features cannot shadow dependency names.
+-
+-To enable namespaced-features, use the `-Z namespaced-features` command-line
+-flag.
+-
+-An example of hiding an optional dependency:
+-
+-```toml
+-[dependencies]
+-regex = { version = "1.4.1", optional = true }
+-lazy_static = { version = "1.4.0", optional = true }
+-
+-[features]
+-regex = ["dep:regex", "dep:lazy_static"]
+-```
+-
+-In this example, the "regex" feature enables both `regex` and `lazy_static`.
+-The `lazy_static` feature does not exist, and a user cannot explicitly enable
+-it. This helps hide internal details of how your package is implemented.
+-
+-An example of avoiding "funky" names:
+-
+-```toml
+-[dependencies]
+-bigdecimal = "0.1"
+-chrono = "0.4"
+-num-bigint = "0.2"
+-serde = {version = "1.0", optional = true }
+-
+-[features]
+-serde = ["dep:serde", "bigdecimal/serde", "chrono/serde", "num-bigint/serde"]
+-```
+-
+-In this case, `serde` is a natural name to use for a feature, because it is
+-relevant to your exported API. However, previously you would need to use a
+-name like `serde1` to work around the naming limitation if you wanted to also
+-enable other features.
+-
+ ### Build-plan
+ * Tracking Issue: [#5579](https://github.com/rust-lang/cargo/issues/5579)
+ 
+@@ -898,29 +834,6 @@ error: aborting due to previous error
+ error: aborting due to previous error
+ ```
+ 
+-### Weak dependency features
+-* Tracking Issue: [#8832](https://github.com/rust-lang/cargo/issues/8832)
+-
+-The `-Z weak-dep-features` command-line options enables the ability to use
+-`dep_name?/feat_name` syntax in the `[features]` table. The `?` indicates that
+-the optional dependency `dep_name` will not be automatically enabled. The
+-feature `feat_name` will only be added if something else enables the
+-`dep_name` dependency.
+-
+-Example:
+-
+-```toml
+-[dependencies]
+-serde = { version = "1.0.117", optional = true, default-features = false }
+-
+-[features]
+-std = ["serde?/std"]
+-```
+-
+-In this example, the `std` feature enables the `std` feature on the `serde`
+-dependency. However, unlike the normal `serde/std` syntax, it will not enable
+-the optional dependency `serde` unless something else has included it.
+-
+ ### per-package-target
+ * Tracking Issue: [#9406](https://github.com/rust-lang/cargo/pull/9406)
+ * Original Pull Request: [#9030](https://github.com/rust-lang/cargo/pull/9030)
+@@ -1375,3 +1288,13 @@ for more information.
+ Support for generating a future-incompat report has been stabilized
+ in the 1.59 release. See the [future incompat report chapter](future-incompat-report.md)
+ for more information.
++
++### Namespaced features
++
++Namespaced features has been stabilized in the 1.60 release.
++See the [Features chapter](features.md#optional-dependencies) for more information.
++
++### Weak dependency features
++
++Weak dependency features has been stabilized in the 1.60 release.
++See the [Features chapter](features.md#dependency-features) for more information.
+--- cargo-crates/cargo-0.60.0/tests/testsuite/features.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/tests/testsuite/features.rs
+@@ -36,7 +36,8 @@ Caused by:
+ }
+ 
+ #[cargo_test]
+-fn invalid2() {
++fn same_name() {
++    // Feature with the same name as a dependency.
+     let p = project()
+         .file(
+             "Cargo.toml",
+@@ -59,14 +60,24 @@ fn invalid2() {
+         .file("bar/src/lib.rs", "")
+         .build();
+ 
+-    p.cargo("build")
+-        .with_status(101)
+-        .with_stderr(
++    p.cargo("tree -f")
++        .arg("{p} [{f}]")
++        .with_stderr("")
++        .with_stdout(
+             "\
+-[ERROR] failed to parse manifest at `[..]`
++foo v0.0.1 ([..]) []
++└── bar v1.0.0 ([..]) []
++",
++        )
++        .run();
+ 
+-Caused by:
+-  features and dependencies cannot have the same name: `bar`
++    p.cargo("tree --features bar -f")
++        .arg("{p} [{f}]")
++        .with_stderr("")
++        .with_stdout(
++            "\
++foo v0.0.1 ([..]) [bar,baz]
++└── bar v1.0.0 ([..]) []
+ ",
+         )
+         .run();
+--- cargo-crates/cargo-0.60.0/tests/testsuite/features_namespaced.rs.orig	1970-01-01 00:00:01 UTC
++++ cargo-crates/cargo-0.60.0/tests/testsuite/features_namespaced.rs
+@@ -5,99 +5,6 @@ use cargo_test_support::{project, publish};
+ use cargo_test_support::{project, publish};
+ 
+ #[cargo_test]
+-fn gated() {
+-    // Need namespaced-features to use `dep:` syntax.
+-    Package::new("bar", "1.0.0").publish();
+-    let p = project()
+-        .file(
+-            "Cargo.toml",
+-            r#"
+-                [package]
+-                name = "foo"
+-                version = "0.1.0"
+-
+-                [dependencies]
+-                bar = { version = "1.0", optional = true }
+-
+-                [features]
+-                foo = ["dep:bar"]
+-            "#,
+-        )
+-        .file("src/lib.rs", "")
+-        .build();
+-
+-    p.cargo("check")
+-        .with_status(101)
+-        .with_stderr(
+-            "\
+-[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`
+-
+-Caused by:
+-  namespaced features with the `dep:` prefix are only allowed on the nightly channel \
+-  and requires the `-Z namespaced-features` flag on the command-line
+-",
+-        )
+-        .run();
+-}
+-
+-#[cargo_test]
+-fn dependency_gate_ignored() {
+-    // Dependencies with `dep:` features are ignored in the registry if not on nightly.
+-    Package::new("baz", "1.0.0").publish();
+-    Package::new("bar", "1.0.0")
+-        .add_dep(Dependency::new("baz", "1.0").optional(true))
+-        .feature("feat", &["dep:baz"])
+-        .publish();
+-    let p = project()
+-        .file(
+-            "Cargo.toml",
+-            r#"
+-                [package]
+-                name = "foo"
+-                version = "0.1.0"
+-
+-                [dependencies]
+-                bar = "1.0"
+-            "#,
+-        )
+-        .file("src/lib.rs", "")
+-        .build();
*** 696 LINES SKIPPED ***