2021-03-06 12:33:02 -06:00
|
|
|
use crate::util::check_builtin_macro_attribute;
|
|
|
|
|
2021-03-06 14:37:59 -06:00
|
|
|
use rustc_ast::mut_visit::{self, MutVisitor};
|
|
|
|
use rustc_ast::ptr::P;
|
2021-03-06 12:33:02 -06:00
|
|
|
use rustc_ast::{self as ast, AstLike};
|
|
|
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
|
|
|
use rustc_expand::config::StripUnconfigured;
|
2021-03-06 14:37:59 -06:00
|
|
|
use rustc_expand::configure;
|
2021-03-06 12:33:02 -06:00
|
|
|
use rustc_span::symbol::sym;
|
|
|
|
use rustc_span::Span;
|
2021-03-06 14:37:59 -06:00
|
|
|
use smallvec::SmallVec;
|
2021-03-06 12:33:02 -06:00
|
|
|
|
2021-03-06 14:37:59 -06:00
|
|
|
crate fn expand(
|
2021-03-06 12:33:02 -06:00
|
|
|
ecx: &mut ExtCtxt<'_>,
|
|
|
|
_span: Span,
|
|
|
|
meta_item: &ast::MetaItem,
|
2021-03-06 16:11:21 -06:00
|
|
|
annotatable: Annotatable,
|
2021-03-06 12:33:02 -06:00
|
|
|
) -> Vec<Annotatable> {
|
|
|
|
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
|
2021-03-06 16:11:21 -06:00
|
|
|
cfg_eval(ecx, annotatable)
|
|
|
|
}
|
2021-03-06 12:33:02 -06:00
|
|
|
|
2021-03-06 16:11:21 -06:00
|
|
|
crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
|
2021-03-06 14:37:59 -06:00
|
|
|
let mut visitor = CfgEval {
|
|
|
|
cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false },
|
|
|
|
};
|
2021-03-06 16:11:21 -06:00
|
|
|
let mut annotatable = visitor.configure_annotatable(annotatable);
|
2021-03-06 14:37:59 -06:00
|
|
|
if visitor.cfg.modified {
|
2021-03-06 12:33:02 -06:00
|
|
|
// Erase the tokens if cfg-stripping modified the item
|
|
|
|
// This will cause us to synthesize fake tokens
|
|
|
|
// when `nt_to_tokenstream` is called on this item.
|
2021-03-06 16:11:21 -06:00
|
|
|
if let Some(tokens) = annotatable.tokens_mut() {
|
2021-03-06 12:33:02 -06:00
|
|
|
*tokens = None;
|
|
|
|
}
|
|
|
|
}
|
2021-03-06 16:11:21 -06:00
|
|
|
vec![annotatable]
|
2021-03-06 12:33:02 -06:00
|
|
|
}
|
2021-03-06 14:37:59 -06:00
|
|
|
|
2021-03-06 16:11:21 -06:00
|
|
|
struct CfgEval<'a> {
|
|
|
|
cfg: StripUnconfigured<'a>,
|
2021-03-06 14:37:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl CfgEval<'_> {
|
|
|
|
fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
|
|
|
|
self.cfg.configure(node)
|
|
|
|
}
|
|
|
|
|
2021-03-06 16:11:21 -06:00
|
|
|
fn configure_annotatable(&mut self, annotatable: Annotatable) -> Annotatable {
|
2021-03-06 14:37:59 -06:00
|
|
|
// Since the item itself has already been configured by the InvocationCollector,
|
|
|
|
// we know that fold result vector will contain exactly one element
|
2021-03-06 16:11:21 -06:00
|
|
|
match annotatable {
|
2021-03-06 14:37:59 -06:00
|
|
|
Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
|
|
|
|
Annotatable::TraitItem(item) => {
|
|
|
|
Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
|
|
|
|
}
|
|
|
|
Annotatable::ImplItem(item) => {
|
|
|
|
Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
|
|
|
|
}
|
|
|
|
Annotatable::ForeignItem(item) => {
|
|
|
|
Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
|
|
|
|
}
|
|
|
|
Annotatable::Stmt(stmt) => {
|
|
|
|
Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
|
|
|
|
}
|
|
|
|
Annotatable::Expr(mut expr) => Annotatable::Expr({
|
|
|
|
self.visit_expr(&mut expr);
|
|
|
|
expr
|
|
|
|
}),
|
|
|
|
Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
|
2021-03-15 16:36:07 -05:00
|
|
|
Annotatable::ExprField(field) => {
|
|
|
|
Annotatable::ExprField(self.flat_map_expr_field(field).pop().unwrap())
|
2021-03-06 14:37:59 -06:00
|
|
|
}
|
2021-03-15 16:36:07 -05:00
|
|
|
Annotatable::PatField(fp) => {
|
|
|
|
Annotatable::PatField(self.flat_map_pat_field(fp).pop().unwrap())
|
2021-03-06 14:37:59 -06:00
|
|
|
}
|
|
|
|
Annotatable::GenericParam(param) => {
|
|
|
|
Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
|
|
|
|
}
|
|
|
|
Annotatable::Param(param) => {
|
|
|
|
Annotatable::Param(self.flat_map_param(param).pop().unwrap())
|
|
|
|
}
|
2021-03-15 16:36:07 -05:00
|
|
|
Annotatable::FieldDef(sf) => {
|
|
|
|
Annotatable::FieldDef(self.flat_map_field_def(sf).pop().unwrap())
|
2021-03-06 14:37:59 -06:00
|
|
|
}
|
|
|
|
Annotatable::Variant(v) => {
|
|
|
|
Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MutVisitor for CfgEval<'_> {
|
|
|
|
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
|
|
|
self.cfg.configure_expr(expr);
|
|
|
|
mut_visit::noop_visit_expr(expr, self);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
|
|
|
let mut expr = configure!(self, expr);
|
|
|
|
mut_visit::noop_visit_expr(&mut expr, self);
|
|
|
|
Some(expr)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_generic_param(
|
|
|
|
&mut self,
|
|
|
|
param: ast::GenericParam,
|
|
|
|
) -> SmallVec<[ast::GenericParam; 1]> {
|
|
|
|
mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
|
|
|
|
mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
|
|
|
mut_visit::noop_flat_map_item(configure!(self, item), self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
|
|
|
mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
|
|
|
mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
|
|
|
|
}
|
|
|
|
|
2021-03-06 15:18:51 -06:00
|
|
|
fn flat_map_foreign_item(
|
|
|
|
&mut self,
|
|
|
|
foreign_item: P<ast::ForeignItem>,
|
|
|
|
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
|
|
|
mut_visit::noop_flat_map_foreign_item(configure!(self, foreign_item), self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
|
|
|
|
mut_visit::noop_flat_map_arm(configure!(self, arm), self)
|
|
|
|
}
|
|
|
|
|
2021-03-15 16:36:07 -05:00
|
|
|
fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
|
|
|
|
mut_visit::noop_flat_map_expr_field(configure!(self, field), self)
|
2021-03-06 15:18:51 -06:00
|
|
|
}
|
|
|
|
|
2021-03-15 16:36:07 -05:00
|
|
|
fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
|
|
|
|
mut_visit::noop_flat_map_pat_field(configure!(self, fp), self)
|
2021-03-06 15:18:51 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
|
|
|
|
mut_visit::noop_flat_map_param(configure!(self, p), self)
|
|
|
|
}
|
|
|
|
|
2021-03-15 16:36:07 -05:00
|
|
|
fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
|
|
|
|
mut_visit::noop_flat_map_field_def(configure!(self, sf), self)
|
2021-03-06 14:37:59 -06:00
|
|
|
}
|
|
|
|
|
2021-03-06 15:18:51 -06:00
|
|
|
fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
|
|
|
|
mut_visit::noop_flat_map_variant(configure!(self, variant), self)
|
2021-03-06 14:37:59 -06:00
|
|
|
}
|
|
|
|
}
|