about summary refs log tree commit diff
path: root/compiler/rustc_expand
diff options
context:
space:
mode:
authorFrank King <frankking1729@gmail.com>2025-02-05 18:58:29 +0800
committerFrank King <frankking1729@gmail.com>2025-03-01 22:02:46 +0800
commit42f51d4fd42c95e0c51c3f8742d63db0548cd5a0 (patch)
tree754318d4e5ccbdb944dc38741039989a48d124e4 /compiler/rustc_expand
parent30508faeb3248d399079513b6e0107af30a43948 (diff)
downloadrust-42f51d4fd42c95e0c51c3f8742d63db0548cd5a0.tar.gz
rust-42f51d4fd42c95e0c51c3f8742d63db0548cd5a0.zip
Implment `#[cfg]` and `#[cfg_attr]` in `where` clauses
Diffstat (limited to 'compiler/rustc_expand')
-rw-r--r--compiler/rustc_expand/src/base.rs16
-rw-r--r--compiler/rustc_expand/src/expand.rs38
-rw-r--r--compiler/rustc_expand/src/placeholders.rs24
3 files changed, 75 insertions, 3 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 4a250145308..86b12f6be4e 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -53,6 +53,7 @@ pub enum Annotatable {
     Param(ast::Param),
     FieldDef(ast::FieldDef),
     Variant(ast::Variant),
+    WherePredicate(ast::WherePredicate),
     Crate(ast::Crate),
 }
 
@@ -71,6 +72,7 @@ impl Annotatable {
             Annotatable::Param(p) => p.span,
             Annotatable::FieldDef(sf) => sf.span,
             Annotatable::Variant(v) => v.span,
+            Annotatable::WherePredicate(wp) => wp.span,
             Annotatable::Crate(c) => c.spans.inner_span,
         }
     }
@@ -89,6 +91,7 @@ impl Annotatable {
             Annotatable::Param(p) => p.visit_attrs(f),
             Annotatable::FieldDef(sf) => sf.visit_attrs(f),
             Annotatable::Variant(v) => v.visit_attrs(f),
+            Annotatable::WherePredicate(wp) => wp.visit_attrs(f),
             Annotatable::Crate(c) => c.visit_attrs(f),
         }
     }
@@ -107,6 +110,7 @@ impl Annotatable {
             Annotatable::Param(p) => visitor.visit_param(p),
             Annotatable::FieldDef(sf) => visitor.visit_field_def(sf),
             Annotatable::Variant(v) => visitor.visit_variant(v),
+            Annotatable::WherePredicate(wp) => visitor.visit_where_predicate(wp),
             Annotatable::Crate(c) => visitor.visit_crate(c),
         }
     }
@@ -128,6 +132,7 @@ impl Annotatable {
             | Annotatable::Param(..)
             | Annotatable::FieldDef(..)
             | Annotatable::Variant(..)
+            | Annotatable::WherePredicate(..)
             | Annotatable::Crate(..) => panic!("unexpected annotatable"),
         }
     }
@@ -223,6 +228,13 @@ impl Annotatable {
         }
     }
 
+    pub fn expect_where_predicate(self) -> ast::WherePredicate {
+        match self {
+            Annotatable::WherePredicate(wp) => wp,
+            _ => panic!("expected where predicate"),
+        }
+    }
+
     pub fn expect_crate(self) -> ast::Crate {
         match self {
             Annotatable::Crate(krate) => krate,
@@ -446,6 +458,10 @@ pub trait MacResult {
         None
     }
 
+    fn make_where_predicates(self: Box<Self>) -> Option<SmallVec<[ast::WherePredicate; 1]>> {
+        None
+    }
+
     fn make_crate(self: Box<Self>) -> Option<ast::Crate> {
         // Fn-like macros cannot produce a crate.
         unreachable!()
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index e3f31ebeca3..c523bcece72 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -227,6 +227,12 @@ ast_fragments! {
     Variants(SmallVec<[ast::Variant; 1]>) {
         "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants;
     }
+    WherePredicates(SmallVec<[ast::WherePredicate; 1]>) {
+        "where predicate";
+        many fn flat_map_where_predicate;
+        fn visit_where_predicate();
+        fn make_where_predicates;
+     }
     Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; }
 }
 
@@ -259,7 +265,8 @@ impl AstFragmentKind {
             | AstFragmentKind::GenericParams
             | AstFragmentKind::Params
             | AstFragmentKind::FieldDefs
-            | AstFragmentKind::Variants => SupportsMacroExpansion::No,
+            | AstFragmentKind::Variants
+            | AstFragmentKind::WherePredicates => SupportsMacroExpansion::No,
         }
     }
 
@@ -290,6 +297,9 @@ impl AstFragmentKind {
             AstFragmentKind::Variants => {
                 AstFragment::Variants(items.map(Annotatable::expect_variant).collect())
             }
+            AstFragmentKind::WherePredicates => AstFragment::WherePredicates(
+                items.map(Annotatable::expect_where_predicate).collect(),
+            ),
             AstFragmentKind::Items => {
                 AstFragment::Items(items.map(Annotatable::expect_item).collect())
             }
@@ -865,7 +875,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             | Annotatable::GenericParam(..)
             | Annotatable::Param(..)
             | Annotatable::FieldDef(..)
-            | Annotatable::Variant(..) => panic!("unexpected annotatable"),
+            | Annotatable::Variant(..)
+            | Annotatable::WherePredicate(..) => panic!("unexpected annotatable"),
         };
         if self.cx.ecfg.features.proc_macro_hygiene() {
             return;
@@ -1002,7 +1013,8 @@ pub fn parse_ast_fragment<'a>(
         | AstFragmentKind::GenericParams
         | AstFragmentKind::Params
         | AstFragmentKind::FieldDefs
-        | AstFragmentKind::Variants => panic!("unexpected AST fragment kind"),
+        | AstFragmentKind::Variants
+        | AstFragmentKind::WherePredicates => panic!("unexpected AST fragment kind"),
     })
 }
 
@@ -1414,6 +1426,19 @@ impl InvocationCollectorNode for ast::Variant {
     }
 }
 
+impl InvocationCollectorNode for ast::WherePredicate {
+    const KIND: AstFragmentKind = AstFragmentKind::WherePredicates;
+    fn to_annotatable(self) -> Annotatable {
+        Annotatable::WherePredicate(self)
+    }
+    fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
+        fragment.make_where_predicates()
+    }
+    fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
+        walk_flat_map_where_predicate(visitor, self)
+    }
+}
+
 impl InvocationCollectorNode for ast::FieldDef {
     const KIND: AstFragmentKind = AstFragmentKind::FieldDefs;
     fn to_annotatable(self) -> Annotatable {
@@ -2116,6 +2141,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         self.flat_map_node(node)
     }
 
+    fn flat_map_where_predicate(
+        &mut self,
+        node: ast::WherePredicate,
+    ) -> SmallVec<[ast::WherePredicate; 1]> {
+        self.flat_map_node(node)
+    }
+
     fn flat_map_field_def(&mut self, node: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
         self.flat_map_node(node)
     }
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index e969f2d4fb5..3a470924c7f 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -188,6 +188,19 @@ pub(crate) fn placeholder(
             vis,
             is_placeholder: true,
         }]),
+        AstFragmentKind::WherePredicates => {
+            AstFragment::WherePredicates(smallvec![ast::WherePredicate {
+                attrs: Default::default(),
+                id,
+                span,
+                kind: ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
+                    bound_generic_params: Default::default(),
+                    bounded_ty: ty(),
+                    bounds: Default::default(),
+                }),
+                is_placeholder: true,
+            }])
+        }
     }
 }
 
@@ -267,6 +280,17 @@ impl MutVisitor for PlaceholderExpander {
         }
     }
 
+    fn flat_map_where_predicate(
+        &mut self,
+        predicate: ast::WherePredicate,
+    ) -> SmallVec<[ast::WherePredicate; 1]> {
+        if predicate.is_placeholder {
+            self.remove(predicate.id).make_where_predicates()
+        } else {
+            walk_flat_map_where_predicate(self, predicate)
+        }
+    }
+
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
             ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),