]> git.proxmox.com Git - cargo.git/commitdiff
Don't synthesize feature diretives for non-optional deps
authorAlex Crichton <alex@alexcrichton.com>
Wed, 5 Jun 2019 16:10:10 +0000 (09:10 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 5 Jun 2019 16:10:10 +0000 (09:10 -0700)
Currently when Cargo is invoked on the command like `cargo build
--features foo/bar` then it will actually always compile the current
crate with `feature = "foo"` even if `foo` is a non-optional dependency.
This isn't intended because the crate doesn't actually have a `foo`
feature as so no directive should be emitted or passed to the compiler.

This was discovered in rust-lang/rust where Cargo is being built with
the `rustc-workspace-hack` feature but when the RLS depends on Cargo it
doesn't enable the same feature. This feature, however, doesn't actually
exist for Cargo!

src/cargo/core/resolver/dep_cache.rs
tests/testsuite/features.rs

index a6ae59132d5cc943fbb9ab112edd6f1d76d29c02..58b52a617d55861980c92cec293f5f5926f828dd 100644 (file)
@@ -415,7 +415,19 @@ impl Requirements<'_> {
     }
 
     fn require_crate_feature(&mut self, package: InternedString, feat: InternedString) {
-        self.used.insert(package);
+        // If `package` is indeed an optional dependency then we activate the
+        // feature named `package`, but otherwise if `package` is a required
+        // dependency then there's no feature associated with it.
+        if let Some(dep) = self
+            .summary
+            .dependencies()
+            .iter()
+            .find(|p| p.name_in_toml() == package)
+        {
+            if dep.is_optional() {
+                self.used.insert(package);
+            }
+        }
         self.deps
             .entry(package)
             .or_insert((false, BTreeSet::new()))
index 35a4fa9d24758fb6041f832875c15bc4a0af3d06..3c38143ec44f05b93d648a11160a911114c96b18 100644 (file)
@@ -1870,3 +1870,44 @@ fn warn_if_default_features() {
             "#.trim(),
         ).run();
 }
+
+#[test]
+fn no_feature_for_non_optional_dep() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+                [project]
+                name = "foo"
+                version = "0.0.1"
+                authors = []
+
+                [dependencies]
+                bar = { path = "bar" }
+             "#,
+        )
+        .file(
+            "src/main.rs",
+            r#"
+                #[cfg(not(feature = "bar"))]
+                fn main() {
+                }
+            "#,
+        )
+        .file(
+            "bar/Cargo.toml",
+            r#"
+                [project]
+                name = "bar"
+                version = "0.0.1"
+                authors = []
+
+                [features]
+                a = []
+             "#,
+        )
+        .file("bar/src/lib.rs", "pub fn bar() {}")
+        .build();
+
+    p.cargo("build --features bar/a").run();
+}