From 074050c2421b56547d4bcc7fe87947032682bbf4 Mon Sep 17 00:00:00 2001
From: Chayim Refael Friedman <chayimfr@gmail.com>
Date: Sun, 27 Oct 2024 10:46:49 +0200
Subject: [PATCH] Support `cfg(true)` and `cfg(false)`

As per RFC 3695.
---
 Cargo.lock                                    |  1 +
 crates/cfg/Cargo.toml                         |  1 +
 crates/cfg/src/lib.rs                         | 32 +++++++++++++++----
 crates/ide-completion/src/tests/attribute.rs  |  2 ++
 .../src/handlers/inactive_code.rs             | 16 ++++++++++
 .../cargo_hello_world_project_model.txt       |  6 ++++
 ...project_model_with_selective_overrides.txt |  6 ++++
 ..._project_model_with_wildcard_overrides.txt |  6 ++++
 .../output/rust_project_cfg_groups.txt        | 12 +++++++
 ...rust_project_hello_world_project_model.txt | 11 +++++++
 10 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8bbccc82aee2..0313de976ed5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -164,6 +164,7 @@ dependencies = [
  "rustc-hash 2.0.0",
  "syntax",
  "syntax-bridge",
+ "tracing",
  "tt",
 ]
 
diff --git a/crates/cfg/Cargo.toml b/crates/cfg/Cargo.toml
index 29b7ad6f8fe2..040bddbd7fd3 100644
--- a/crates/cfg/Cargo.toml
+++ b/crates/cfg/Cargo.toml
@@ -14,6 +14,7 @@ doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
+tracing.workspace = true
 
 # locals deps
 tt = { workspace = true, optional = true }
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index c2d400860561..6a6213a871fd 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -9,7 +9,7 @@ use std::fmt;
 
 use rustc_hash::FxHashSet;
 
-use intern::Symbol;
+use intern::{sym, Symbol};
 
 pub use cfg_expr::{CfgAtom, CfgExpr};
 pub use dnf::DnfExpr;
@@ -24,11 +24,17 @@ pub use dnf::DnfExpr;
 /// of key and value in `key_values`.
 ///
 /// See: <https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options>
-#[derive(Clone, PartialEq, Eq, Default)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct CfgOptions {
     enabled: FxHashSet<CfgAtom>,
 }
 
+impl Default for CfgOptions {
+    fn default() -> Self {
+        Self { enabled: FxHashSet::from_iter([CfgAtom::Flag(sym::true_.clone())]) }
+    }
+}
+
 impl fmt::Debug for CfgOptions {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut items = self
@@ -54,23 +60,37 @@ impl CfgOptions {
     }
 
     pub fn insert_atom(&mut self, key: Symbol) {
-        self.enabled.insert(CfgAtom::Flag(key));
+        self.insert_any_atom(CfgAtom::Flag(key));
     }
 
     pub fn insert_key_value(&mut self, key: Symbol, value: Symbol) {
-        self.enabled.insert(CfgAtom::KeyValue { key, value });
+        self.insert_any_atom(CfgAtom::KeyValue { key, value });
     }
 
     pub fn apply_diff(&mut self, diff: CfgDiff) {
         for atom in diff.enable {
-            self.enabled.insert(atom);
+            self.insert_any_atom(atom);
         }
 
         for atom in diff.disable {
+            let (CfgAtom::Flag(sym) | CfgAtom::KeyValue { key: sym, .. }) = &atom;
+            if *sym == sym::true_ || *sym == sym::false_ {
+                tracing::error!("cannot remove `true` or `false` from cfg");
+                continue;
+            }
             self.enabled.remove(&atom);
         }
     }
 
+    fn insert_any_atom(&mut self, atom: CfgAtom) {
+        let (CfgAtom::Flag(sym) | CfgAtom::KeyValue { key: sym, .. }) = &atom;
+        if *sym == sym::true_ || *sym == sym::false_ {
+            tracing::error!("cannot insert `true` or `false` to cfg");
+            return;
+        }
+        self.enabled.insert(atom);
+    }
+
     pub fn get_cfg_keys(&self) -> impl Iterator<Item = &Symbol> {
         self.enabled.iter().map(|it| match it {
             CfgAtom::Flag(key) => key,
@@ -88,7 +108,7 @@ impl CfgOptions {
 
 impl Extend<CfgAtom> for CfgOptions {
     fn extend<T: IntoIterator<Item = CfgAtom>>(&mut self, iter: T) {
-        iter.into_iter().for_each(|cfg_flag| _ = self.enabled.insert(cfg_flag));
+        iter.into_iter().for_each(|cfg_flag| self.insert_any_atom(cfg_flag));
     }
 }
 
diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs
index 1bbe097cc6c8..45679355b427 100644
--- a/crates/ide-completion/src/tests/attribute.rs
+++ b/crates/ide-completion/src/tests/attribute.rs
@@ -663,6 +663,7 @@ mod cfg {
                 ba dbg
                 ba opt_level
                 ba test
+                ba true
             "#]],
         );
         check(
@@ -674,6 +675,7 @@ mod cfg {
                 ba dbg
                 ba opt_level
                 ba test
+                ba true
             "#]],
         );
     }
diff --git a/crates/ide-diagnostics/src/handlers/inactive_code.rs b/crates/ide-diagnostics/src/handlers/inactive_code.rs
index 1f8f805a1e29..4c0c685e5503 100644
--- a/crates/ide-diagnostics/src/handlers/inactive_code.rs
+++ b/crates/ide-diagnostics/src/handlers/inactive_code.rs
@@ -192,6 +192,22 @@ union FooBar {
 //- /outline_inner.rs
 #![cfg(outline_inner)]
 //- /outline.rs
+"#,
+        );
+    }
+
+    #[test]
+    fn cfg_true_false() {
+        check(
+            r#"
+  #[cfg(false)] fn inactive() {}
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: false is disabled
+
+  #[cfg(true)] fn active() {}
+
+  #[cfg(any(not(true)), false)] fn inactive2() {}
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: true is enabled
+
 "#,
         );
     }
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index 3401d7f7e47f..880e90c52a54 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -19,6 +19,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -81,6 +82,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -151,6 +153,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -221,6 +224,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -291,6 +295,7 @@
             [
                 "feature=default",
                 "feature=std",
+                "true",
             ],
         ),
         potential_cfg_options: Some(
@@ -303,6 +308,7 @@
                     "feature=rustc-dep-of-std",
                     "feature=std",
                     "feature=use_std",
+                    "true",
                 ],
             ),
         ),
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index 3401d7f7e47f..880e90c52a54 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -19,6 +19,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -81,6 +82,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -151,6 +153,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -221,6 +224,7 @@
             [
                 "rust_analyzer",
                 "test",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -291,6 +295,7 @@
             [
                 "feature=default",
                 "feature=std",
+                "true",
             ],
         ),
         potential_cfg_options: Some(
@@ -303,6 +308,7 @@
                     "feature=rustc-dep-of-std",
                     "feature=std",
                     "feature=use_std",
+                    "true",
                 ],
             ),
         ),
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 491568d4b756..7746acd225e3 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -18,6 +18,7 @@
         cfg_options: CfgOptions(
             [
                 "rust_analyzer",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -79,6 +80,7 @@
         cfg_options: CfgOptions(
             [
                 "rust_analyzer",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -148,6 +150,7 @@
         cfg_options: CfgOptions(
             [
                 "rust_analyzer",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -217,6 +220,7 @@
         cfg_options: CfgOptions(
             [
                 "rust_analyzer",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -287,6 +291,7 @@
             [
                 "feature=default",
                 "feature=std",
+                "true",
             ],
         ),
         potential_cfg_options: Some(
@@ -299,6 +304,7 @@
                     "feature=rustc-dep-of-std",
                     "feature=std",
                     "feature=use_std",
+                    "true",
                 ],
             ),
         ),
diff --git a/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/crates/project-model/test_data/output/rust_project_cfg_groups.txt
index 8261e5a2d907..90f41a9c2fc8 100644
--- a/crates/project-model/test_data/output/rust_project_cfg_groups.txt
+++ b/crates/project-model/test_data/output/rust_project_cfg_groups.txt
@@ -17,6 +17,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -56,6 +57,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -86,6 +88,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -116,6 +119,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -146,6 +150,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -193,6 +198,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -223,6 +229,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -318,6 +325,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -348,6 +356,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -378,6 +387,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -410,6 +420,7 @@
                 "group1_other_cfg=other_config",
                 "group2_cfg=yet_another_config",
                 "rust_analyzer",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -485,6 +496,7 @@
                 "group2_cfg=fourth_config",
                 "group2_cfg=yet_another_config",
                 "rust_analyzer",
+                "true",
                 "unrelated_cfg",
             ],
         ),
diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index c123df80a6a3..a0e14b8fcb22 100644
--- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -17,6 +17,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -56,6 +57,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -86,6 +88,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -116,6 +119,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -146,6 +150,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -193,6 +198,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -223,6 +229,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -318,6 +325,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -348,6 +356,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -378,6 +387,7 @@
             [
                 "debug_assertions",
                 "miri",
+                "true",
             ],
         ),
         potential_cfg_options: None,
@@ -407,6 +417,7 @@
         cfg_options: CfgOptions(
             [
                 "rust_analyzer",
+                "true",
             ],
         ),
         potential_cfg_options: None,