1 use crate::util::check_builtin_macro_attribute;
3 use rustc_ast::mut_visit::{self, MutVisitor};
5 use rustc_ast::{self as ast, AstLike};
6 use rustc_expand::base::{Annotatable, ExtCtxt};
7 use rustc_expand::config::StripUnconfigured;
8 use rustc_expand::configure;
9 use rustc_span::symbol::sym;
11 use smallvec::SmallVec;
14 ecx: &mut ExtCtxt<'_>,
16 meta_item: &ast::MetaItem,
17 annotatable: Annotatable,
18 ) -> Vec<Annotatable> {
19 check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
20 cfg_eval(ecx, annotatable)
23 crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
24 let mut visitor = CfgEval {
25 cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false },
27 let mut annotatable = visitor.configure_annotatable(annotatable);
28 if visitor.cfg.modified {
29 // Erase the tokens if cfg-stripping modified the item
30 // This will cause us to synthesize fake tokens
31 // when `nt_to_tokenstream` is called on this item.
32 if let Some(tokens) = annotatable.tokens_mut() {
40 cfg: StripUnconfigured<'a>,
44 fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
45 self.cfg.configure(node)
48 fn configure_annotatable(&mut self, annotatable: Annotatable) -> Annotatable {
49 // Since the item itself has already been configured by the InvocationCollector,
50 // we know that fold result vector will contain exactly one element
52 Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
53 Annotatable::TraitItem(item) => {
54 Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
56 Annotatable::ImplItem(item) => {
57 Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
59 Annotatable::ForeignItem(item) => {
60 Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
62 Annotatable::Stmt(stmt) => {
63 Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
65 Annotatable::Expr(mut expr) => Annotatable::Expr({
66 self.visit_expr(&mut expr);
69 Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
70 Annotatable::ExprField(field) => {
71 Annotatable::ExprField(self.flat_map_expr_field(field).pop().unwrap())
73 Annotatable::PatField(fp) => {
74 Annotatable::PatField(self.flat_map_pat_field(fp).pop().unwrap())
76 Annotatable::GenericParam(param) => {
77 Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
79 Annotatable::Param(param) => {
80 Annotatable::Param(self.flat_map_param(param).pop().unwrap())
82 Annotatable::FieldDef(sf) => {
83 Annotatable::FieldDef(self.flat_map_field_def(sf).pop().unwrap())
85 Annotatable::Variant(v) => {
86 Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
92 impl MutVisitor for CfgEval<'_> {
93 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
94 self.cfg.configure_expr(expr);
95 mut_visit::noop_visit_expr(expr, self);
98 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
99 let mut expr = configure!(self, expr);
100 mut_visit::noop_visit_expr(&mut expr, self);
104 fn flat_map_generic_param(
106 param: ast::GenericParam,
107 ) -> SmallVec<[ast::GenericParam; 1]> {
108 mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
111 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
112 mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
115 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
116 mut_visit::noop_flat_map_item(configure!(self, item), self)
119 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
120 mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
123 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
124 mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
127 fn flat_map_foreign_item(
129 foreign_item: P<ast::ForeignItem>,
130 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
131 mut_visit::noop_flat_map_foreign_item(configure!(self, foreign_item), self)
134 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
135 mut_visit::noop_flat_map_arm(configure!(self, arm), self)
138 fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
139 mut_visit::noop_flat_map_expr_field(configure!(self, field), self)
142 fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
143 mut_visit::noop_flat_map_pat_field(configure!(self, fp), self)
146 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
147 mut_visit::noop_flat_map_param(configure!(self, p), self)
150 fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
151 mut_visit::noop_flat_map_field_def(configure!(self, sf), self)
154 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
155 mut_visit::noop_flat_map_variant(configure!(self, variant), self)