about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-26 20:17:24 +0000
committerbors <bors@rust-lang.org>2023-05-26 20:17:24 +0000
commit7c81fff52015b044a0d5dfadcd1e8caa2f237ea3 (patch)
treee9d1511812df2e074c3a2768d9278458b18f5f4f
parent9e6ae6bac701e8c49f7f303548b162bcb9839dfb (diff)
parent35b208aaa72b5848050ac4e2d3094ecd948cf3a5 (diff)
downloadrust-7c81fff52015b044a0d5dfadcd1e8caa2f237ea3.tar.gz
rust-7c81fff52015b044a0d5dfadcd1e8caa2f237ea3.zip
Auto merge of #14910 - Veykril:cargo-features, r=Veykril
Filter out unused cargo features from config

Closes https://github.com/rust-lang/rust-analyzer/issues/11836
-rw-r--r--.github/workflows/ci.yaml1
-rw-r--r--Cargo.lock1
-rw-r--r--crates/project-model/Cargo.toml1
-rw-r--r--crates/project-model/src/build_scripts.rs28
-rw-r--r--crates/project-model/src/cargo_workspace.rs17
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs14
6 files changed, 50 insertions, 12 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 220d88afe4d..622da105fdd 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -58,7 +58,6 @@ jobs:
         uses: actions/checkout@v3
         with:
           ref: ${{ github.event.pull_request.head.sha }}
-          fetch-depth: 20
 
       - name: Install Rust toolchain
         run: |
diff --git a/Cargo.lock b/Cargo.lock
index e7ae42a2d9b..f9c5417ffb5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1334,6 +1334,7 @@ dependencies = [
  "cargo_metadata",
  "cfg",
  "expect-test",
+ "itertools",
  "la-arena",
  "paths",
  "profile",
diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml
index efe61eb8f68..3abff64a83b 100644
--- a/crates/project-model/Cargo.toml
+++ b/crates/project-model/Cargo.toml
@@ -21,6 +21,7 @@ serde.workspace = true
 triomphe.workspace = true
 anyhow = "1.0.62"
 la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
+itertools = "0.10.5"
 
 # local deps
 base-db.workspace = true
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index fe4cbfc8867..6cbf403cb2e 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -14,9 +14,10 @@ use std::{
 };
 
 use cargo_metadata::{camino::Utf8Path, Message};
+use itertools::Itertools;
 use la_arena::ArenaMap;
 use paths::{AbsPath, AbsPathBuf};
-use rustc_hash::FxHashMap;
+use rustc_hash::{FxHashMap, FxHashSet};
 use semver::Version;
 use serde::Deserialize;
 
@@ -56,7 +57,10 @@ impl BuildScriptOutput {
 }
 
 impl WorkspaceBuildScripts {
-    fn build_command(config: &CargoConfig) -> io::Result<Command> {
+    fn build_command(
+        config: &CargoConfig,
+        allowed_features: &FxHashSet<String>,
+    ) -> io::Result<Command> {
         let mut cmd = match config.run_build_script_command.as_deref() {
             Some([program, args @ ..]) => {
                 let mut cmd = Command::new(program);
@@ -88,7 +92,12 @@ impl WorkspaceBuildScripts {
                         }
                         if !features.is_empty() {
                             cmd.arg("--features");
-                            cmd.arg(features.join(" "));
+                            cmd.arg(
+                                features
+                                    .iter()
+                                    .filter(|&feat| allowed_features.contains(feat))
+                                    .join(","),
+                            );
                         }
                     }
                 }
@@ -127,13 +136,20 @@ impl WorkspaceBuildScripts {
         }
         .as_ref();
 
-        match Self::run_per_ws(Self::build_command(config)?, workspace, current_dir, progress) {
+        let allowed_features = workspace.workspace_features();
+
+        match Self::run_per_ws(
+            Self::build_command(config, &allowed_features)?,
+            workspace,
+            current_dir,
+            progress,
+        ) {
             Ok(WorkspaceBuildScripts { error: Some(error), .. })
                 if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) =>
             {
                 // building build scripts failed, attempt to build with --keep-going so
                 // that we potentially get more build data
-                let mut cmd = Self::build_command(config)?;
+                let mut cmd = Self::build_command(config, &allowed_features)?;
                 cmd.args(["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1");
                 let mut res = Self::run_per_ws(cmd, workspace, current_dir, progress)?;
                 res.error = Some(error);
@@ -161,7 +177,7 @@ impl WorkspaceBuildScripts {
                 ))
             }
         };
-        let cmd = Self::build_command(config)?;
+        let cmd = Self::build_command(config, &Default::default())?;
         // NB: Cargo.toml could have been modified between `cargo metadata` and
         // `cargo check`. We shouldn't assume that package ids we see here are
         // exactly those from `config`.
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index e3fdeb448db..649a149504c 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -10,7 +10,7 @@ use base_db::Edition;
 use cargo_metadata::{CargoOpt, MetadataCommand};
 use la_arena::{Arena, Idx};
 use paths::{AbsPath, AbsPathBuf};
-use rustc_hash::FxHashMap;
+use rustc_hash::{FxHashMap, FxHashSet};
 use serde::Deserialize;
 use serde_json::from_value;
 
@@ -491,6 +491,21 @@ impl CargoWorkspace {
         None
     }
 
+    /// Returns the union of the features of all member crates in this workspace.
+    pub fn workspace_features(&self) -> FxHashSet<String> {
+        self.packages()
+            .filter_map(|package| {
+                let package = &self[package];
+                if package.is_member {
+                    Some(package.features.keys().cloned())
+                } else {
+                    None
+                }
+            })
+            .flatten()
+            .collect()
+    }
+
     fn is_unique(&self, name: &str) -> bool {
         self.packages.iter().filter(|(_, v)| v.name == name).count() == 1
     }
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index cf51cf15a0e..3035dc33308 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -5,6 +5,7 @@ use std::mem;
 use cfg::{CfgAtom, CfgExpr};
 use ide::{Cancellable, FileId, RunnableKind, TestId};
 use project_model::{self, CargoFeatures, ManifestPath, TargetKind};
+use rustc_hash::FxHashSet;
 use vfs::AbsPathBuf;
 
 use crate::global_state::GlobalStateSnapshot;
@@ -21,6 +22,7 @@ pub(crate) struct CargoTargetSpec {
     pub(crate) target: String,
     pub(crate) target_kind: TargetKind,
     pub(crate) required_features: Vec<String>,
+    pub(crate) features: FxHashSet<String>,
 }
 
 impl CargoTargetSpec {
@@ -73,12 +75,13 @@ impl CargoTargetSpec {
             }
         }
 
-        let target_required_features = if let Some(mut spec) = spec {
+        let (allowed_features, target_required_features) = if let Some(mut spec) = spec {
+            let allowed_features = mem::take(&mut spec.features);
             let required_features = mem::take(&mut spec.required_features);
             spec.push_to(&mut args, kind);
-            required_features
+            (allowed_features, required_features)
         } else {
-            Vec::new()
+            (Default::default(), Default::default())
         };
 
         let cargo_config = snap.config.cargo();
@@ -97,7 +100,9 @@ impl CargoTargetSpec {
                     required_features(cfg, &mut feats);
                 }
 
-                feats.extend(features.iter().cloned());
+                feats.extend(
+                    features.iter().filter(|&feat| allowed_features.contains(feat)).cloned(),
+                );
                 feats.extend(target_required_features);
 
                 feats.dedup();
@@ -136,6 +141,7 @@ impl CargoTargetSpec {
             target: target_data.name.clone(),
             target_kind: target_data.kind,
             required_features: target_data.required_features.clone(),
+            features: package_data.features.keys().cloned().collect(),
         };
 
         Ok(Some(res))