Skip to content

Commit e41605b

Browse files
committed
Auto merge of #12130 - ehuss:dep-with-slash, r=weihanglo
Fix dep/feat syntax with hidden implicit optional dependencies This fixes an issue with `dep/feat` syntax in the `[features]` table where it wouldn't work if the optional dependency had its implicit feature removed via the `dep:` syntax. The problem is that both resolvers were expecting that `dep/feat` would be able to activate a feature named "dep". But if that implicit feature wasn't created, then it would fail with an error. This was just an oversight (which probably happened in #9574). Fixes #10788
2 parents 13413c6 + 996bca2 commit e41605b

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

src/cargo/core/resolver/dep_cache.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,12 @@ impl Requirements<'_> {
455455
.iter()
456456
.any(|dep| dep.name_in_toml() == package && dep.is_optional())
457457
{
458-
self.require_feature(package)?;
458+
// This optional dependency may not have an implicit feature of
459+
// the same name if the `dep:` syntax is used to avoid creating
460+
// that implicit feature.
461+
if self.summary.features().contains_key(&package) {
462+
self.require_feature(package)?;
463+
}
459464
}
460465
self.deps.entry(package).or_default().insert(feat);
461466
Ok(())

src/cargo/core/resolver/features.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,15 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
717717
// The old behavior before weak dependencies were
718718
// added is to also enables a feature of the same
719719
// name.
720-
self.activate_rec(pkg_id, fk, dep_name)?;
720+
//
721+
// Don't enable if the implicit optional dependency
722+
// feature wasn't created due to `dep:` hiding.
723+
// See rust-lang/cargo#10788 and rust-lang/cargo#12130
724+
let summary = self.resolve.summary(pkg_id);
725+
let feature_map = summary.features();
726+
if feature_map.contains_key(&dep_name) {
727+
self.activate_rec(pkg_id, fk, dep_name)?;
728+
}
721729
}
722730
}
723731
// Activate the feature on the dependency.

tests/testsuite/features_namespaced.rs

+78
Original file line numberDiff line numberDiff line change
@@ -1216,3 +1216,81 @@ Caused by:
12161216
)
12171217
.run();
12181218
}
1219+
1220+
#[cargo_test]
1221+
fn dep_feature_when_hidden() {
1222+
// Checks for behavior with dep:bar and bar/feat syntax when there is no
1223+
// `bar` feature.
1224+
let p = project()
1225+
.file(
1226+
"Cargo.toml",
1227+
r#"
1228+
[package]
1229+
name = "foo"
1230+
version = "0.1.0"
1231+
1232+
[dependencies]
1233+
bar = { path = "bar", optional = true }
1234+
1235+
[features]
1236+
f1 = ["dep:bar"]
1237+
f2 = ["bar/bar_feat"]
1238+
"#,
1239+
)
1240+
.file("src/lib.rs", "")
1241+
.file(
1242+
"bar/Cargo.toml",
1243+
r#"
1244+
[package]
1245+
name = "bar"
1246+
version = "0.1.0"
1247+
1248+
[features]
1249+
bar_feat = []
1250+
"#,
1251+
)
1252+
.file("bar/src/lib.rs", "")
1253+
.build();
1254+
1255+
p.cargo("tree -f")
1256+
.arg("{p} features={f}")
1257+
.with_stdout(
1258+
"\
1259+
foo v0.1.0 ([ROOT]/foo) features=",
1260+
)
1261+
.with_stderr("")
1262+
.run();
1263+
1264+
p.cargo("tree -F f1 -f")
1265+
.arg("{p} features={f}")
1266+
.with_stdout(
1267+
"\
1268+
foo v0.1.0 ([ROOT]/foo) features=f1
1269+
└── bar v0.1.0 ([ROOT]/foo/bar) features=
1270+
",
1271+
)
1272+
.with_stderr("")
1273+
.run();
1274+
1275+
p.cargo("tree -F f2 -f")
1276+
.arg("{p} features={f}")
1277+
.with_stdout(
1278+
"\
1279+
foo v0.1.0 ([ROOT]/foo) features=f2
1280+
└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat
1281+
",
1282+
)
1283+
.with_stderr("")
1284+
.run();
1285+
1286+
p.cargo("tree --all-features -f")
1287+
.arg("{p} features={f}")
1288+
.with_stdout(
1289+
"\
1290+
foo v0.1.0 ([ROOT]/foo) features=f1,f2
1291+
└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat
1292+
",
1293+
)
1294+
.with_stderr("")
1295+
.run();
1296+
}

0 commit comments

Comments
 (0)