Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #19243 from Veykril/push-qrrqsywkwyzp
Allow unsetting default cfgs
Lukas Wirth 2025-03-03
parent 8ff0b67 · parent 5e18ad0 · commit b685ada
-rw-r--r--crates/cfg/src/cfg_expr.rs19
-rw-r--r--crates/cfg/src/dnf.rs19
-rw-r--r--crates/cfg/src/lib.rs20
-rw-r--r--crates/project-model/src/tests.rs4
-rw-r--r--crates/project-model/src/workspace.rs8
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs56
-rw-r--r--crates/rust-analyzer/src/flycheck.rs26
-rw-r--r--docs/book/src/configuration_generated.md4
-rw-r--r--editors/code/package.json2
10 files changed, 96 insertions, 64 deletions
diff --git a/crates/cfg/src/cfg_expr.rs b/crates/cfg/src/cfg_expr.rs
index 84b91a527f..0ec082dfa7 100644
--- a/crates/cfg/src/cfg_expr.rs
+++ b/crates/cfg/src/cfg_expr.rs
@@ -18,6 +18,25 @@ pub enum CfgAtom {
KeyValue { key: Symbol, value: Symbol },
}
+impl PartialOrd for CfgAtom {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for CfgAtom {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ match (self, other) {
+ (CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()),
+ (CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less,
+ (CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater,
+ (CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => {
+ key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str()))
+ }
+ }
+ }
+}
+
impl fmt::Display for CfgAtom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
diff --git a/crates/cfg/src/dnf.rs b/crates/cfg/src/dnf.rs
index f3ebca0465..424672a275 100644
--- a/crates/cfg/src/dnf.rs
+++ b/crates/cfg/src/dnf.rs
@@ -66,9 +66,9 @@ impl DnfExpr {
}
}
- res.enabled.sort_unstable_by(compare);
+ res.enabled.sort_unstable();
res.enabled.dedup();
- res.disabled.sort_unstable_by(compare);
+ res.disabled.sort_unstable();
res.disabled.dedup();
Some(res)
}
@@ -114,25 +114,14 @@ impl DnfExpr {
};
// Undo the FxHashMap randomization for consistent output.
- diff.enable.sort_unstable_by(compare);
- diff.disable.sort_unstable_by(compare);
+ diff.enable.sort_unstable();
+ diff.disable.sort_unstable();
Some(diff)
})
}
}
-fn compare(a: &CfgAtom, b: &CfgAtom) -> std::cmp::Ordering {
- match (a, b) {
- (CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()),
- (CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less,
- (CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater,
- (CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => {
- key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str()))
- }
- }
-}
-
impl fmt::Display for DnfExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.conjunctions.len() != 1 {
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index 6a6213a871..08545b6851 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -148,16 +148,20 @@ pub struct CfgDiff {
}
impl CfgDiff {
- /// Create a new CfgDiff. Will return None if the same item appears more than once in the set
- /// of both.
- pub fn new(enable: Vec<CfgAtom>, disable: Vec<CfgAtom>) -> Option<CfgDiff> {
- let mut occupied = FxHashSet::default();
- if enable.iter().chain(disable.iter()).any(|item| !occupied.insert(item)) {
- // was present
- return None;
+ /// Create a new CfgDiff.
+ pub fn new(mut enable: Vec<CfgAtom>, mut disable: Vec<CfgAtom>) -> CfgDiff {
+ enable.sort();
+ enable.dedup();
+ disable.sort();
+ disable.dedup();
+ for i in (0..enable.len()).rev() {
+ if let Some(j) = disable.iter().position(|atom| *atom == enable[i]) {
+ enable.remove(i);
+ disable.remove(j);
+ }
}
- Some(CfgDiff { enable, disable })
+ CfgDiff { enable, disable }
}
/// Returns the total number of atoms changed by this diff.
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index cfc666970b..8374062273 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -166,7 +166,7 @@ fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) {
#[test]
fn cargo_hello_world_project_model_with_wildcard_overrides() {
let cfg_overrides = CfgOverrides {
- global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(),
+ global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]),
selective: Default::default(),
};
let (crate_graph, _proc_macros) =
@@ -185,7 +185,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
global: Default::default(),
selective: std::iter::once((
"libc".to_owned(),
- CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(),
+ CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]),
))
.collect(),
};
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 2c9f41e828..89818be8d4 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -1521,7 +1521,7 @@ fn extend_crate_graph_with_sysroot(
) -> (SysrootPublicDeps, Option<CrateId>) {
let mut pub_deps = vec![];
let mut libproc_macro = None;
- let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap();
+ let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]);
for (cid, c) in sysroot_crate_graph.iter_mut() {
// uninject `test` flag so `core` keeps working.
Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
@@ -1599,8 +1599,7 @@ fn sysroot_to_crate_graph(
CfgAtom::Flag(sym::miri.clone()),
],
vec![],
- )
- .unwrap(),
+ ),
..Default::default()
},
&WorkspaceBuildScripts::default(),
@@ -1623,8 +1622,7 @@ fn sysroot_to_crate_graph(
CfgAtom::Flag(sym::miri.clone()),
],
vec![],
- )
- .unwrap(),
+ ),
..Default::default()
},
false,
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 4fc6180920..b9e4457fc9 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -69,7 +69,7 @@ impl flags::AnalysisStats {
all_targets: true,
set_test: !self.no_test,
cfg_overrides: CfgOverrides {
- global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]).unwrap(),
+ global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]),
selective: Default::default(),
},
..Default::default()
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 713e28c87c..45ac68339b 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -18,7 +18,7 @@ use ide_db::{
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
SnippetCap,
};
-use itertools::Itertools;
+use itertools::{Either, Itertools};
use paths::{Utf8Path, Utf8PathBuf};
use project_model::{
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand,
@@ -589,6 +589,10 @@ config_data! {
/// avoid checking unnecessary things.
cargo_buildScripts_useRustcWrapper: bool = true,
/// List of cfg options to enable with the given values.
+ ///
+ /// To enable a name without a value, use `"key"`.
+ /// To enable a name with a value, use `"key=value"`.
+ /// To disable, prefix the entry with a `!`.
cargo_cfgs: Vec<String> = {
vec!["debug_assertions".into(), "miri".into()]
},
@@ -1980,27 +1984,35 @@ impl Config {
rustc_source,
extra_includes,
cfg_overrides: project_model::CfgOverrides {
- global: CfgDiff::new(
- self.cargo_cfgs(source_root)
- .iter()
- // parse any cfg setting formatted as key=value or just key (without value)
- .filter_map(|s| {
- let mut sp = s.splitn(2, "=");
- let key = sp.next();
- let val = sp.next();
- key.map(|key| (key, val))
- })
- .map(|(key, val)| match val {
- Some(val) => CfgAtom::KeyValue {
- key: Symbol::intern(key),
- value: Symbol::intern(val),
- },
- None => CfgAtom::Flag(Symbol::intern(key)),
- })
- .collect(),
- vec![],
- )
- .unwrap(),
+ global: {
+ let (enabled, disabled): (Vec<_>, Vec<_>) =
+ self.cargo_cfgs(source_root).iter().partition_map(|s| {
+ s.strip_prefix("!").map_or(Either::Left(s), Either::Right)
+ });
+ CfgDiff::new(
+ enabled
+ .into_iter()
+ // parse any cfg setting formatted as key=value or just key (without value)
+ .map(|s| match s.split_once("=") {
+ Some((key, val)) => CfgAtom::KeyValue {
+ key: Symbol::intern(key),
+ value: Symbol::intern(val),
+ },
+ None => CfgAtom::Flag(Symbol::intern(s)),
+ })
+ .collect(),
+ disabled
+ .into_iter()
+ .map(|s| match s.split_once("=") {
+ Some((key, val)) => CfgAtom::KeyValue {
+ key: Symbol::intern(key),
+ value: Symbol::intern(val),
+ },
+ None => CfgAtom::Flag(Symbol::intern(s)),
+ })
+ .collect(),
+ )
+ },
selective: Default::default(),
},
wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(source_root),
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index 2309f94a74..7529e7c188 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -244,8 +244,14 @@ struct FlycheckActor {
/// The receiver side of the channel mentioned above.
command_receiver: Option<Receiver<CargoCheckMessage>>,
diagnostics_cleared_for: FxHashSet<Arc<PackageId>>,
- diagnostics_cleared_for_all: bool,
- diagnostics_received: bool,
+ diagnostics_received: DiagnosticsReceived,
+}
+
+#[derive(PartialEq)]
+enum DiagnosticsReceived {
+ Yes,
+ No,
+ YesAndClearedForAll,
}
#[allow(clippy::large_enum_variant)]
@@ -276,8 +282,7 @@ impl FlycheckActor {
command_handle: None,
command_receiver: None,
diagnostics_cleared_for: Default::default(),
- diagnostics_cleared_for_all: false,
- diagnostics_received: false,
+ diagnostics_received: DiagnosticsReceived::No,
}
}
@@ -354,7 +359,7 @@ impl FlycheckActor {
error
);
}
- if !self.diagnostics_received {
+ if self.diagnostics_received == DiagnosticsReceived::No {
tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
// We finished without receiving any diagnostics.
// Clear everything for good measure
@@ -396,7 +401,7 @@ impl FlycheckActor {
package_id = package_id.as_ref().map(|it| &it.repr),
"diagnostic received"
);
- self.diagnostics_received = true;
+ self.diagnostics_received = DiagnosticsReceived::Yes;
if let Some(package_id) = &package_id {
if self.diagnostics_cleared_for.insert(package_id.clone()) {
tracing::trace!(
@@ -409,8 +414,10 @@ impl FlycheckActor {
package_id: Some(package_id.clone()),
});
}
- } else if !self.diagnostics_cleared_for_all {
- self.diagnostics_cleared_for_all = true;
+ } else if self.diagnostics_received
+ != DiagnosticsReceived::YesAndClearedForAll
+ {
+ self.diagnostics_received = DiagnosticsReceived::YesAndClearedForAll;
self.send(FlycheckMessage::ClearDiagnostics {
id: self.id,
package_id: None,
@@ -445,8 +452,7 @@ impl FlycheckActor {
fn clear_diagnostics_state(&mut self) {
self.diagnostics_cleared_for.clear();
- self.diagnostics_cleared_for_all = false;
- self.diagnostics_received = false;
+ self.diagnostics_received = DiagnosticsReceived::No;
}
/// Construct a `Command` object for checking the user's code. If the user
diff --git a/docs/book/src/configuration_generated.md b/docs/book/src/configuration_generated.md
index 1cbe51836f..0a612d20b9 100644
--- a/docs/book/src/configuration_generated.md
+++ b/docs/book/src/configuration_generated.md
@@ -102,6 +102,10 @@ Default:
List of cfg options to enable with the given values.
+To enable a name without a value, use `"key"`.
+To enable a name with a value, use `"key=value"`.
+To disable, prefix the entry with a `!`.
+
**rust-analyzer.cargo.extraArgs** (default: [])
diff --git a/editors/code/package.json b/editors/code/package.json
index 587ae92520..9df41c7487 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -825,7 +825,7 @@
"title": "cargo",
"properties": {
"rust-analyzer.cargo.cfgs": {
- "markdownDescription": "List of cfg options to enable with the given values.",
+ "markdownDescription": "List of cfg options to enable with the given values.\n\nTo enable a name without a value, use `\"key\"`.\nTo enable a name with a value, use `\"key=value\"`.\nTo disable, prefix the entry with a `!`.",
"default": [
"debug_assertions",
"miri"