about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-02-12 13:38:24 +0000
committerGitHub <noreply@github.com>2025-02-12 13:38:24 +0000
commit815919578b3edcc82f1f43b94705a392e1f15390 (patch)
treeb90dda29a5ec2cac733ec8957775278f629840b7
parent444c2f961a11debadc8113b7493490911800f9f2 (diff)
parentb5ad702c621ca92a2a24088b6fb2e7fcf30638e9 (diff)
downloadrust-815919578b3edcc82f1f43b94705a392e1f15390.tar.gz
rust-815919578b3edcc82f1f43b94705a392e1f15390.zip
Merge pull request #19125 from ChayimFriedman2/cfg-attr-fast
fix: Censor cfg_attr for attribute macros
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs56
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs44
3 files changed, 96 insertions, 24 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
index 70e3e1ed4e9..a43c0eb9d70 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
@@ -5,7 +5,7 @@
 //! in-memory macros.
 use expect_test::expect;
 
-use crate::macro_expansion_tests::check;
+use crate::macro_expansion_tests::{check, check_errors};
 
 #[test]
 fn attribute_macro_attr_censoring() {
@@ -216,3 +216,21 @@ struct S;
 #[doc = "doc attr"] struct S;"##]],
     );
 }
+
+#[test]
+fn cfg_evaluated_before_attr_macros() {
+    check_errors(
+        r#"
+//- proc_macros: disallow_cfg
+
+use proc_macros::disallow_cfg;
+
+#[disallow_cfg] #[cfg(false)] fn foo() {}
+// True cfg are kept.
+// #[disallow_cfg] #[cfg(true)] fn bar() {}
+#[disallow_cfg] #[cfg_attr(false, inline)] fn baz() {}
+#[disallow_cfg] #[cfg_attr(true, inline)] fn qux() {}
+    "#,
+        expect![[r#""#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs
index 01a3103af82..626a82ae08e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs
@@ -201,9 +201,6 @@ pub(crate) fn process_cfg_attrs(
         MacroDefKind::BuiltInAttr(_, expander) => expander.is_derive(),
         _ => false,
     };
-    if !is_derive {
-        return None;
-    }
     let mut remove = FxHashSet::default();
 
     let item = ast::Item::cast(node.clone())?;
@@ -220,28 +217,43 @@ pub(crate) fn process_cfg_attrs(
             }
         }
     }
-    match item {
-        ast::Item::Struct(it) => match it.field_list()? {
-            ast::FieldList::RecordFieldList(fields) => {
-                process_has_attrs_with_possible_comma(db, fields.fields(), loc.krate, &mut remove)?;
+
+    if is_derive {
+        // Only derives get their code cfg-clean, normal attribute macros process only the cfg at their level
+        // (cfg_attr is handled above, cfg is handled in the def map).
+        match item {
+            ast::Item::Struct(it) => match it.field_list()? {
+                ast::FieldList::RecordFieldList(fields) => {
+                    process_has_attrs_with_possible_comma(
+                        db,
+                        fields.fields(),
+                        loc.krate,
+                        &mut remove,
+                    )?;
+                }
+                ast::FieldList::TupleFieldList(fields) => {
+                    process_has_attrs_with_possible_comma(
+                        db,
+                        fields.fields(),
+                        loc.krate,
+                        &mut remove,
+                    )?;
+                }
+            },
+            ast::Item::Enum(it) => {
+                process_enum(db, it.variant_list()?, loc.krate, &mut remove)?;
             }
-            ast::FieldList::TupleFieldList(fields) => {
-                process_has_attrs_with_possible_comma(db, fields.fields(), loc.krate, &mut remove)?;
+            ast::Item::Union(it) => {
+                process_has_attrs_with_possible_comma(
+                    db,
+                    it.record_field_list()?.fields(),
+                    loc.krate,
+                    &mut remove,
+                )?;
             }
-        },
-        ast::Item::Enum(it) => {
-            process_enum(db, it.variant_list()?, loc.krate, &mut remove)?;
-        }
-        ast::Item::Union(it) => {
-            process_has_attrs_with_possible_comma(
-                db,
-                it.record_field_list()?.fields(),
-                loc.krate,
-                &mut remove,
-            )?;
+            // FIXME: Implement for other items if necessary. As we do not support #[cfg_eval] yet, we do not need to implement it for now
+            _ => {}
         }
-        // FIXME: Implement for other items if necessary. As we do not support #[cfg_eval] yet, we do not need to implement it for now
-        _ => {}
     }
     Some(remove)
 }
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index ca596583590..613f27c7958 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -17,7 +17,7 @@ use hir_expand::{
     tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter},
     FileRange,
 };
-use intern::Symbol;
+use intern::{sym, Symbol};
 use rustc_hash::FxHashMap;
 use span::{Edition, EditionedFileId, FileId, Span};
 use stdx::itertools::Itertools;
@@ -511,6 +511,21 @@ pub fn issue_18898(_attr: TokenStream, input: TokenStream) -> TokenStream {
                 disabled: false,
             },
         ),
+        (
+            r#"
+#[proc_macro_attribute]
+pub fn disallow_cfg(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+"#
+            .into(),
+            ProcMacro {
+                name: Symbol::intern("disallow_cfg"),
+                kind: ProcMacroKind::Attr,
+                expander: sync::Arc::new(DisallowCfgProcMacroExpander),
+                disabled: false,
+            },
+        ),
     ])
 }
 
@@ -865,3 +880,30 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander {
         })
     }
 }
+
+// Reads ident type within string quotes, for issue #17479.
+#[derive(Debug)]
+struct DisallowCfgProcMacroExpander;
+impl ProcMacroExpander for DisallowCfgProcMacroExpander {
+    fn expand(
+        &self,
+        subtree: &TopSubtree,
+        _: Option<&TopSubtree>,
+        _: &Env,
+        _: Span,
+        _: Span,
+        _: Span,
+        _: Option<String>,
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
+        for tt in subtree.token_trees().flat_tokens() {
+            if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt {
+                if ident.sym == sym::cfg || ident.sym == sym::cfg_attr {
+                    return Err(ProcMacroExpansionError::Panic(
+                        "cfg or cfg_attr found in DisallowCfgProcMacroExpander".to_owned(),
+                    ));
+                }
+            }
+        }
+        Ok(subtree.clone())
+    }
+}