Skip to content

Commit 43a063c

Browse files
committed
Stabilize namespaced and weak dependency features.
1 parent 2478331 commit 43a063c

File tree

19 files changed

+229
-611
lines changed

19 files changed

+229
-611
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ atty = "0.2"
2020
bytesize = "1.0"
2121
cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" }
2222
cargo-util = { path = "crates/cargo-util", version = "0.1.2" }
23-
crates-io = { path = "crates/crates-io", version = "0.33.1" }
23+
crates-io = { path = "crates/crates-io", version = "0.34.0" }
2424
crossbeam-utils = "0.8"
2525
curl = { version = "0.4.41", features = ["http2"] }
2626
curl-sys = "0.4.50"

crates/crates-io/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "crates-io"
3-
version = "0.33.1"
3+
version = "0.34.0"
44
edition = "2021"
55
license = "MIT OR Apache-2.0"
66
repository = "https://github.com/rust-lang/cargo"

crates/crates-io/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ pub struct NewCrate {
5555
pub repository: Option<String>,
5656
pub badges: BTreeMap<String, BTreeMap<String, String>>,
5757
pub links: Option<String>,
58-
#[serde(skip_serializing_if = "Option::is_none")]
59-
pub v: Option<u32>,
6058
}
6159

6260
#[derive(Serialize)]

src/bin/cargo/commands/read_manifest.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ Deprecated, use `cargo metadata --no-deps` instead.\
1515

1616
pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
1717
let ws = args.workspace(config)?;
18-
config
19-
.shell()
20-
.print_json(&ws.current()?.serialized(config))?;
18+
config.shell().print_json(&ws.current()?.serialized())?;
2119
Ok(())
2220
}

src/cargo/core/features.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,6 @@ unstable_cli_options!(
642642
minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum"),
643643
mtime_on_use: bool = ("Configure Cargo to update the mtime of used files"),
644644
multitarget: bool = ("Allow passing multiple `--target` flags to the cargo subcommand selected"),
645-
namespaced_features: bool = ("Allow features with `dep:` prefix"),
646645
no_index_update: bool = ("Do not update the registry index even if the cache is outdated"),
647646
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
648647
host_config: bool = ("Enable the [host] section in the .cargo/config.toml file"),
@@ -652,7 +651,6 @@ unstable_cli_options!(
652651
terminal_width: Option<Option<usize>> = ("Provide a terminal width to rustc for error truncation"),
653652
timings: Option<Vec<String>> = ("Display concurrency information"),
654653
unstable_options: bool = ("Allow the usage of unstable options"),
655-
weak_dep_features: bool = ("Allow `dep_name?/feature` feature syntax"),
656654
// TODO(wcrichto): move scrape example configuration into Cargo.toml before stabilization
657655
// See: https://github.com/rust-lang/cargo/pull/9525#discussion_r728470927
658656
rustdoc_scrape_examples: Option<String> = ("Allow rustdoc to scrape examples from reverse-dependencies for documentation"),
@@ -707,6 +705,10 @@ const STABILIZED_NAMED_PROFILES: &str = "The named-profiles feature is now alway
707705
const STABILIZED_FUTURE_INCOMPAT_REPORT: &str =
708706
"The future-incompat-report feature is now always enabled.";
709707

708+
const STABILIZED_WEAK_DEP_FEATURES: &str = "Weak dependency features are now always available.";
709+
710+
const STABILISED_NAMESPACED_FEATURES: &str = "Namespaced features are now always available.";
711+
710712
fn deserialize_build_std<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
711713
where
712714
D: serde::Deserializer<'de>,
@@ -873,8 +875,8 @@ impl CliUnstable {
873875
"multitarget" => self.multitarget = parse_empty(k, v)?,
874876
"rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
875877
"terminal-width" => self.terminal_width = Some(parse_usize_opt(v)?),
876-
"namespaced-features" => self.namespaced_features = parse_empty(k, v)?,
877-
"weak-dep-features" => self.weak_dep_features = parse_empty(k, v)?,
878+
"namespaced-features" => stabilized_warn(k, "1.60", STABILISED_NAMESPACED_FEATURES),
879+
"weak-dep-features" => stabilized_warn(k, "1.60", STABILIZED_WEAK_DEP_FEATURES),
878880
"credential-process" => self.credential_process = parse_empty(k, v)?,
879881
"rustdoc-scrape-examples" => {
880882
if let Some(s) = v {

src/cargo/core/package.rs

+14-22
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl Package {
208208
self.targets().iter().any(|t| t.is_example() || t.is_bin())
209209
}
210210

211-
pub fn serialized(&self, config: &Config) -> SerializedPackage {
211+
pub fn serialized(&self) -> SerializedPackage {
212212
let summary = self.manifest().summary();
213213
let package_id = summary.package_id();
214214
let manmeta = self.manifest().metadata();
@@ -222,27 +222,19 @@ impl Package {
222222
.filter(|t| t.src_path().is_path())
223223
.cloned()
224224
.collect();
225-
let features = if config.cli_unstable().namespaced_features {
226-
// Convert Vec<FeatureValue> to Vec<InternedString>
227-
summary
228-
.features()
229-
.iter()
230-
.map(|(k, v)| {
231-
(
232-
*k,
233-
v.iter()
234-
.map(|fv| InternedString::new(&fv.to_string()))
235-
.collect(),
236-
)
237-
})
238-
.collect()
239-
} else {
240-
self.manifest()
241-
.original()
242-
.features()
243-
.cloned()
244-
.unwrap_or_default()
245-
};
225+
// Convert Vec<FeatureValue> to Vec<InternedString>
226+
let features = summary
227+
.features()
228+
.iter()
229+
.map(|(k, v)| {
230+
(
231+
*k,
232+
v.iter()
233+
.map(|fv| InternedString::new(&fv.to_string()))
234+
.collect(),
235+
)
236+
})
237+
.collect();
246238

247239
SerializedPackage {
248240
name: package_id.name(),

src/cargo/core/resolver/features.rs

+19-87
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
//! Feature resolver.
22
//!
33
//! This is a new feature resolver that runs independently of the main
4-
//! dependency resolver. It is enabled when the user specifies `resolver =
5-
//! "2"` in `Cargo.toml`.
4+
//! dependency resolver. It has several options which can enable new feature
5+
//! resolution behavior.
66
//!
77
//! One of its key characteristics is that it can avoid unifying features for
88
//! shared dependencies in some situations. See `FeatureOpts` for the
99
//! different behaviors that can be enabled. If no extra options are enabled,
1010
//! then it should behave exactly the same as the dependency resolver's
11-
//! feature resolution. This can be verified by setting the
12-
//! `__CARGO_FORCE_NEW_FEATURES=compare` environment variable and running
13-
//! Cargo's test suite (or building other projects), and checking if it
14-
//! panics. Note: the `features2` tests will fail because they intentionally
15-
//! compare the old vs new behavior, so forcing the old behavior will
16-
//! naturally fail the tests.
11+
//! feature resolution.
1712
//!
1813
//! The preferred way to engage this new resolver is via
1914
//! `resolve_ws_with_opts`.
@@ -59,22 +54,12 @@ pub struct ResolvedFeatures {
5954
///
6055
/// The value is the `name_in_toml` of the dependencies.
6156
activated_dependencies: ActivateMap,
62-
/// This is only here for legacy support when the new resolver is not enabled.
63-
///
64-
/// This is the set of features enabled for each package.
65-
legacy_features: Option<HashMap<PackageId, Vec<InternedString>>>,
66-
/// This is only here for legacy support when the new resolver is not enabled.
67-
///
68-
/// This is the set of optional dependencies enabled for each package.
69-
legacy_dependencies: Option<HashMap<PackageId, HashSet<InternedString>>>,
7057
opts: FeatureOpts,
7158
}
7259

7360
/// Options for how the feature resolver works.
7461
#[derive(Default)]
7562
pub struct FeatureOpts {
76-
/// Use the new resolver instead of the old one.
77-
new_resolver: bool,
7863
/// Build deps and proc-macros will not share share features with other dep kinds.
7964
decouple_host_deps: bool,
8065
/// Dev dep features will not be activated unless needed.
@@ -132,7 +117,6 @@ impl FeatureOpts {
132117
let mut opts = FeatureOpts::default();
133118
let unstable_flags = ws.config().cli_unstable();
134119
let mut enable = |feat_opts: &Vec<String>| {
135-
opts.new_resolver = true;
136120
for opt in feat_opts {
137121
match opt.as_ref() {
138122
"build_dep" | "host_dep" => opts.decouple_host_deps = true,
@@ -159,26 +143,13 @@ impl FeatureOpts {
159143
enable(&vec!["all".to_string()]).unwrap();
160144
}
161145
}
162-
// This env var is intended for testing only.
163-
if let Ok(env_opts) = std::env::var("__CARGO_FORCE_NEW_FEATURES") {
164-
if env_opts == "1" {
165-
opts.new_resolver = true;
166-
} else {
167-
let env_opts = env_opts.split(',').map(|s| s.to_string()).collect();
168-
enable(&env_opts)?;
169-
}
170-
}
171146
if let HasDevUnits::Yes = has_dev_units {
172147
// Dev deps cannot be decoupled when they are in use.
173148
opts.decouple_dev_deps = false;
174149
}
175150
if let ForceAllTargets::Yes = force_all_targets {
176151
opts.ignore_inactive_targets = false;
177152
}
178-
if unstable_flags.weak_dep_features {
179-
// Force this ON because it only works with the new resolver.
180-
opts.new_resolver = true;
181-
}
182153
Ok(opts)
183154
}
184155

@@ -187,7 +158,6 @@ impl FeatureOpts {
187158
match behavior {
188159
ResolveBehavior::V1 => FeatureOpts::default(),
189160
ResolveBehavior::V2 => FeatureOpts {
190-
new_resolver: true,
191161
decouple_host_deps: true,
192162
decouple_dev_deps: has_dev_units == HasDevUnits::No,
193163
ignore_inactive_targets: true,
@@ -306,18 +276,11 @@ impl ResolvedFeatures {
306276
features_for: FeaturesFor,
307277
dep_name: InternedString,
308278
) -> bool {
309-
if let Some(legacy) = &self.legacy_dependencies {
310-
legacy
311-
.get(&pkg_id)
312-
.map(|deps| deps.contains(&dep_name))
313-
.unwrap_or(false)
314-
} else {
315-
let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
316-
self.activated_dependencies
317-
.get(&(pkg_id, is_build))
318-
.map(|deps| deps.contains(&dep_name))
319-
.unwrap_or(false)
320-
}
279+
let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
280+
self.activated_dependencies
281+
.get(&(pkg_id, is_build))
282+
.map(|deps| deps.contains(&dep_name))
283+
.unwrap_or(false)
321284
}
322285

323286
/// Variant of `activated_features` that returns `None` if this is
@@ -336,30 +299,28 @@ impl ResolvedFeatures {
336299
pkg_id: PackageId,
337300
features_for: FeaturesFor,
338301
) -> CargoResult<Vec<InternedString>> {
339-
if let Some(legacy) = &self.legacy_features {
340-
Ok(legacy.get(&pkg_id).map_or_else(Vec::new, |v| v.clone()))
302+
let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
303+
if let Some(fs) = self.activated_features.get(&(pkg_id, is_build)) {
304+
Ok(fs.iter().cloned().collect())
341305
} else {
342-
let is_build = self.opts.decouple_host_deps && features_for == FeaturesFor::HostDep;
343-
if let Some(fs) = self.activated_features.get(&(pkg_id, is_build)) {
344-
Ok(fs.iter().cloned().collect())
345-
} else {
346-
bail!("features did not find {:?} {:?}", pkg_id, is_build)
347-
}
306+
bail!("features did not find {:?} {:?}", pkg_id, is_build)
348307
}
349308
}
350309

351310
/// Compares the result against the original resolver behavior.
352311
///
353312
/// Used by `cargo fix --edition` to display any differences.
354313
pub fn compare_legacy(&self, legacy: &ResolvedFeatures) -> DiffMap {
355-
let legacy_features = legacy.legacy_features.as_ref().unwrap();
356314
self.activated_features
357315
.iter()
358316
.filter_map(|((pkg_id, for_host), new_features)| {
359-
let old_features = match legacy_features.get(pkg_id) {
360-
Some(feats) => feats.iter().cloned().collect(),
361-
None => BTreeSet::new(),
362-
};
317+
let old_features = legacy
318+
.activated_features
319+
.get(&(*pkg_id, *for_host))
320+
// The new features may have for_host entries where the old one does not.
321+
.or_else(|| legacy.activated_features.get(&(*pkg_id, false)))
322+
.map(|feats| feats.iter().cloned().collect())
323+
.unwrap_or_else(|| BTreeSet::new());
363324
// The new resolver should never add features.
364325
assert_eq!(new_features.difference(&old_features).next(), None);
365326
let removed_features: BTreeSet<_> =
@@ -427,17 +388,6 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
427388
) -> CargoResult<ResolvedFeatures> {
428389
use crate::util::profile;
429390
let _p = profile::start("resolve features");
430-
431-
if !opts.new_resolver {
432-
// Legacy mode.
433-
return Ok(ResolvedFeatures {
434-
activated_features: HashMap::new(),
435-
activated_dependencies: HashMap::new(),
436-
legacy_features: Some(resolve.features_clone()),
437-
legacy_dependencies: Some(compute_legacy_deps(resolve)),
438-
opts,
439-
});
440-
}
441391
let track_for_host = opts.decouple_host_deps || opts.ignore_inactive_targets;
442392
let mut r = FeatureResolver {
443393
ws,
@@ -460,8 +410,6 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
460410
Ok(ResolvedFeatures {
461411
activated_features: r.activated_features,
462412
activated_dependencies: r.activated_dependencies,
463-
legacy_features: None,
464-
legacy_dependencies: None,
465413
opts: r.opts,
466414
})
467415
}
@@ -826,19 +774,3 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
826774
.proc_macro()
827775
}
828776
}
829-
830-
/// Computes a map of PackageId to the set of optional dependencies that are
831-
/// enabled for that dep (when the new resolver is not enabled).
832-
fn compute_legacy_deps(resolve: &Resolve) -> HashMap<PackageId, HashSet<InternedString>> {
833-
let mut result: HashMap<PackageId, HashSet<InternedString>> = HashMap::new();
834-
for pkg_id in resolve.iter() {
835-
for (_dep_id, deps) in resolve.deps(pkg_id) {
836-
for dep in deps {
837-
if dep.is_optional() {
838-
result.entry(pkg_id).or_default().insert(dep.name_in_toml());
839-
}
840-
}
841-
}
842-
}
843-
result
844-
}

0 commit comments

Comments
 (0)