Skip to content

Commit

Permalink
fix(fix): Ensure optional dep is available for dep-features
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jun 5, 2024
1 parent 74d2af0 commit 8a02016
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
39 changes: 36 additions & 3 deletions src/cargo/ops/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> {
fixes += rename_dep_fields_2024(workspace, "dependencies");
}

fixes += add_feature_for_unused_deps(pkg, root);
fixes += add_feature_for_unused_deps(pkg, root, ws.gctx());
fixes += rename_table(root, "project", "package");
if let Some(target) = root.get_mut("lib").and_then(|t| t.as_table_like_mut()) {
fixes += rename_target_fields_2024(target);
Expand Down Expand Up @@ -435,7 +435,11 @@ fn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) ->
1
}

fn add_feature_for_unused_deps(pkg: &Package, parent: &mut dyn toml_edit::TableLike) -> usize {
fn add_feature_for_unused_deps(
pkg: &Package,
parent: &mut dyn toml_edit::TableLike,
gctx: &GlobalContext,
) -> usize {
let manifest = pkg.manifest();

let activated_opt_deps = manifest
Expand All @@ -461,14 +465,43 @@ fn add_feature_for_unused_deps(pkg: &Package, parent: &mut dyn toml_edit::TableL
.or_insert(toml_edit::table())
.as_table_like_mut()
{
let activate_dep = format!("dep:{dep_name_in_toml}");
let strong_dep_feature_prefix = format!("{dep_name_in_toml}/");
features
.entry(dep_name_in_toml.as_str())
.or_insert_with(|| {
fixes += 1;
toml_edit::Item::Value(toml_edit::Value::Array(
toml_edit::Array::from_iter(&[format!("dep:{}", dep_name_in_toml)]),
toml_edit::Array::from_iter([&activate_dep]),
))
});
// Ensure `dep:dep_name` is present for `dep_name/feature_name` since `dep:` is the
// only way to guarantee an optional dependency is available for use.
//
// The way we avoid implicitly creating features in Edition2024 is we remove the
// dependency from `resolved_toml` if there is no `dep:` syntax as that is the only
// syntax that suppresses the creation of the implicit feature.
for (feature_name, activations) in features.iter_mut() {
let Some(activations) = activations.as_array_mut() else {
let _ = gctx.shell().warn(format_args!("skipping fix of feature `{feature_name}` in package `{}`: unsupported feature schema", pkg.name()));
continue;
};
if activations
.iter()
.any(|a| a.as_str().map(|a| a == activate_dep).unwrap_or(false))
{
continue;
}
let Some(activate_dep_pos) = activations.iter().position(|a| {
a.as_str()
.map(|a| a.starts_with(&strong_dep_feature_prefix))
.unwrap_or(false)
}) else {
continue;
};
fixes += 1;
activations.insert(activate_dep_pos, &activate_dep);
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions tests/testsuite/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2703,7 +2703,7 @@ unrelated-dep-feature = ["unrelated-feature/a", "unrelated-feature/b"]
.with_stderr(
"\
[MIGRATING] Cargo.toml from 2021 edition to 2024
[FIXED] Cargo.toml (1 fix)
[FIXED] Cargo.toml (4 fixes)
[UPDATING] `dummy-registry` index
[LOCKING] 5 packages to latest compatible versions
[CHECKING] foo v0.1.0 ([CWD])
Expand All @@ -2728,11 +2728,11 @@ renamed-feature = { version = "0.1.0", optional = true }
unrelated-feature = { version = "0.1.0", optional = true }
[features]
dep-feature = ["dep-feature/a", "dep-feature/b"]
dep-feature = [ "dep:dep-feature","dep-feature/a", "dep-feature/b"]
dep-and-dep-feature = ["dep:dep-and-dep-feature", "dep-and-dep-feature/a", "dep-and-dep-feature/b"]
renamed = ["renamed-feature/a", "renamed-feature/b"]
renamed = [ "dep:renamed-feature","renamed-feature/a", "renamed-feature/b"]
unrelated-feature = []
unrelated-dep-feature = ["unrelated-feature/a", "unrelated-feature/b"]
unrelated-dep-feature = [ "dep:unrelated-feature","unrelated-feature/a", "unrelated-feature/b"]
renamed-feature = ["dep:renamed-feature"]
"#]],
Expand Down

0 comments on commit 8a02016

Please sign in to comment.