Skip to content

Commit 4d0fda7

Browse files
committed
Fix bug where an optional dependency is disabled in one fork, and enabled in another.
1 parent 3d6b5b1 commit 4d0fda7

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,27 @@ fn compute_deps<'a, 'cfg>(
264264
return false;
265265
}
266266

267+
// If this is an optional dependency, and the new feature resolver
268+
// did not enable it, don't include it.
269+
if dep.is_optional() {
270+
let features_for = match unit_for.is_for_build_dep() {
271+
true => FeaturesFor::BuildDep,
272+
false => FeaturesFor::NormalOrDev,
273+
};
274+
275+
let feats = state.activated_features(id, features_for);
276+
if !feats.contains(&dep.name_in_toml()) {
277+
return false;
278+
}
279+
}
280+
267281
// If we've gotten past all that, then this dependency is
268282
// actually used!
269283
true
270284
})
271285
});
286+
// Separate line to avoid rustfmt indentation. Must collect due to `state` capture.
287+
let filtered_deps: Vec<_> = filtered_deps.collect();
272288

273289
let mut ret = Vec::new();
274290
for (id, _) in filtered_deps {

tests/testsuite/features2.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,3 +821,75 @@ Consider enabling them by passing, e.g., `--features=\"bdep/f1\"`
821821
.masquerade_as_nightly_cargo()
822822
.run();
823823
}
824+
825+
#[cargo_test]
826+
fn disabled_shared_build_dep() {
827+
// Check for situation where an optional dep of a shared dep is enabled in
828+
// a normal dependency, but disabled in an optional one. The unit tree is:
829+
// foo
830+
// ├── foo build.rs
831+
// | └── common (BUILD dependency, NO FEATURES)
832+
// └── common (Normal dependency, default features)
833+
// └── somedep
834+
Package::new("somedep", "1.0.0")
835+
.file(
836+
"src/lib.rs",
837+
r#"
838+
pub fn f() { println!("hello from somedep"); }
839+
"#,
840+
)
841+
.publish();
842+
Package::new("common", "1.0.0")
843+
.feature("default", &["somedep"])
844+
.add_dep(Dependency::new("somedep", "1.0").optional(true))
845+
.file(
846+
"src/lib.rs",
847+
r#"
848+
pub fn check_somedep() -> bool {
849+
#[cfg(feature="somedep")]
850+
{
851+
extern crate somedep;
852+
somedep::f();
853+
true
854+
}
855+
#[cfg(not(feature="somedep"))]
856+
{
857+
println!("no somedep");
858+
false
859+
}
860+
}
861+
"#,
862+
)
863+
.publish();
864+
865+
let p = project()
866+
.file(
867+
"Cargo.toml",
868+
r#"
869+
[package]
870+
name = "foo"
871+
version = "1.0.0"
872+
edition = "2018"
873+
874+
[dependencies]
875+
common = "1.0"
876+
877+
[build-dependencies]
878+
common = {version = "1.0", default-features = false}
879+
"#,
880+
)
881+
.file(
882+
"src/main.rs",
883+
"fn main() { assert!(common::check_somedep()); }",
884+
)
885+
.file(
886+
"build.rs",
887+
"fn main() { assert!(!common::check_somedep()); }",
888+
)
889+
.build();
890+
891+
p.cargo("run -Zfeatures=build_dep -v")
892+
.masquerade_as_nightly_cargo()
893+
.with_stdout("hello from somedep")
894+
.run();
895+
}

0 commit comments

Comments
 (0)