-use attr::HasAttrs;
-use feature_gate::{
+use crate::attr::HasAttrs;
+use crate::feature_gate::{
feature_err,
EXPLAIN_STMT_ATTR_SYNTAX,
Features,
get_features,
GateIssue,
};
-use {fold, attr};
-use ast;
-use source_map::Spanned;
-use edition::Edition;
-use parse::{token, ParseSess};
-use smallvec::SmallVec;
-use errors::Applicability;
+use crate::attr;
+use crate::ast;
+use crate::edition::Edition;
+use crate::mut_visit::*;
+use crate::parse::{token, ParseSess};
+use crate::ptr::P;
+use crate::util::map_in_place::MapInPlace;
-use ptr::P;
+use errors::Applicability;
+use smallvec::SmallVec;
/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
}
impl<'a> StripUnconfigured<'a> {
- pub fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
- let node = self.process_cfg_attrs(node);
+ pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
+ self.process_cfg_attrs(&mut node);
if self.in_cfg(node.attrs()) { Some(node) } else { None }
}
/// Gives compiler warnigns if any `cfg_attr` does not contain any
/// attributes and is in the original source code. Gives compiler errors if
/// the syntax of any `cfg_attr` is incorrect.
- pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: T) -> T {
- node.map_attrs(|attrs| {
- attrs.into_iter().flat_map(|attr| self.process_cfg_attr(attr)).collect()
- })
+ pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: &mut T) {
+ node.visit_attrs(|attrs| {
+ attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
+ });
}
/// Parse and expand a single `cfg_attr` attribute into a list of attributes
///
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
/// is in the original source file. Gives a compiler error if the syntax of
- /// the attribute is incorrect
+ /// the attribute is incorrect.
fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
if !attr.check_name("cfg_attr") {
return vec![attr];
}
}
- /// Determine if a node with the given attributes should be included in this configuration.
+ /// Determines if a node with the given attributes should be included in this configuration.
pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
attrs.iter().all(|attr| {
if !is_cfg(attr) {
}
}
- pub fn configure_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
- ast::ForeignMod {
- abi: foreign_mod.abi,
- items: foreign_mod.items.into_iter().filter_map(|item| self.configure(item)).collect(),
- }
+ pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
+ let ast::ForeignMod { abi: _, items } = foreign_mod;
+ items.flat_map_in_place(|item| self.configure(item));
}
- fn configure_variant_data(&mut self, vdata: ast::VariantData) -> ast::VariantData {
+ fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
match vdata {
- ast::VariantData::Struct(fields, id) => {
- let fields = fields.into_iter().filter_map(|field| self.configure(field));
- ast::VariantData::Struct(fields.collect(), id)
- }
- ast::VariantData::Tuple(fields, id) => {
- let fields = fields.into_iter().filter_map(|field| self.configure(field));
- ast::VariantData::Tuple(fields.collect(), id)
- }
- ast::VariantData::Unit(id) => ast::VariantData::Unit(id)
+ ast::VariantData::Struct(fields, _id) |
+ ast::VariantData::Tuple(fields, _id) =>
+ fields.flat_map_in_place(|field| self.configure(field)),
+ ast::VariantData::Unit(_id) => {}
}
}
- pub fn configure_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
+ pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
match item {
- ast::ItemKind::Struct(def, generics) => {
- ast::ItemKind::Struct(self.configure_variant_data(def), generics)
- }
- ast::ItemKind::Union(def, generics) => {
- ast::ItemKind::Union(self.configure_variant_data(def), generics)
- }
- ast::ItemKind::Enum(def, generics) => {
- let variants = def.variants.into_iter().filter_map(|v| {
- self.configure(v).map(|v| {
- Spanned {
- node: ast::Variant_ {
- ident: v.node.ident,
- attrs: v.node.attrs,
- data: self.configure_variant_data(v.node.data),
- disr_expr: v.node.disr_expr,
- },
- span: v.span
- }
- })
- });
- ast::ItemKind::Enum(ast::EnumDef {
- variants: variants.collect(),
- }, generics)
+ ast::ItemKind::Struct(def, _generics) |
+ ast::ItemKind::Union(def, _generics) => self.configure_variant_data(def),
+ ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
+ variants.flat_map_in_place(|variant| self.configure(variant));
+ for variant in variants {
+ self.configure_variant_data(&mut variant.node.data);
+ }
}
- item => item,
+ _ => {}
}
}
- pub fn configure_expr_kind(&mut self, expr_kind: ast::ExprKind) -> ast::ExprKind {
+ pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
match expr_kind {
- ast::ExprKind::Match(m, arms) => {
- let arms = arms.into_iter().filter_map(|a| self.configure(a)).collect();
- ast::ExprKind::Match(m, arms)
+ ast::ExprKind::Match(_m, arms) => {
+ arms.flat_map_in_place(|arm| self.configure(arm));
}
- ast::ExprKind::Struct(path, fields, base) => {
- let fields = fields.into_iter()
- .filter_map(|field| {
- self.configure(field)
- })
- .collect();
- ast::ExprKind::Struct(path, fields, base)
+ ast::ExprKind::Struct(_path, fields, _base) => {
+ fields.flat_map_in_place(|field| self.configure(field));
}
- _ => expr_kind,
+ _ => {}
}
}
- pub fn configure_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
+ pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
self.visit_expr_attrs(expr.attrs());
// If an expr is valid to cfg away it will have been removed by the
// Anything else is always required, and thus has to error out
// in case of a cfg attr.
//
- // N.B., this is intentionally not part of the fold_expr() function
- // in order for fold_opt_expr() to be able to avoid this check
+ // N.B., this is intentionally not part of the visit_expr() function
+ // in order for filter_map_expr() to be able to avoid this check
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
let msg = "removing an expression is not supported in this position";
self.sess.span_diagnostic.span_err(attr.span, msg);
self.process_cfg_attrs(expr)
}
- pub fn configure_stmt(&mut self, stmt: ast::Stmt) -> Option<ast::Stmt> {
- self.configure(stmt)
- }
-
- pub fn configure_struct_expr_field(&mut self, field: ast::Field) -> Option<ast::Field> {
- self.configure(field)
- }
-
- pub fn configure_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> {
- pattern.map(|mut pattern| {
- if let ast::PatKind::Struct(path, fields, etc) = pattern.node {
- let fields = fields.into_iter()
- .filter_map(|field| {
- self.configure(field)
- })
- .collect();
- pattern.node = ast::PatKind::Struct(path, fields, etc);
- }
- pattern
- })
+ pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
+ if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.node {
+ fields.flat_map_in_place(|field| self.configure(field));
+ }
}
- // deny #[cfg] on generic parameters until we decide what to do with it.
- // see issue #51279.
+ /// Denies `#[cfg]` on generic parameters until we decide what to do with it.
+ /// See issue #51279.
pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) {
for attr in param.attrs() {
let offending_attr = if attr.check_name("cfg") {
}
}
-impl<'a> fold::Folder for StripUnconfigured<'a> {
- fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
- let foreign_mod = self.configure_foreign_mod(foreign_mod);
- fold::noop_fold_foreign_mod(foreign_mod, self)
+impl<'a> MutVisitor for StripUnconfigured<'a> {
+ fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
+ self.configure_foreign_mod(foreign_mod);
+ noop_visit_foreign_mod(foreign_mod, self);
}
- fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
- let item = self.configure_item_kind(item);
- fold::noop_fold_item_kind(item, self)
+ fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
+ self.configure_item_kind(item);
+ noop_visit_item_kind(item, self);
}
- fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
- let mut expr = self.configure_expr(expr).into_inner();
- expr.node = self.configure_expr_kind(expr.node);
- P(fold::noop_fold_expr(expr, self))
+ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
+ self.configure_expr(expr);
+ self.configure_expr_kind(&mut expr.node);
+ noop_visit_expr(expr, self);
}
- fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
- let mut expr = configure!(self, expr).into_inner();
- expr.node = self.configure_expr_kind(expr.node);
- Some(P(fold::noop_fold_expr(expr, self)))
+ fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
+ let mut expr = configure!(self, expr);
+ self.configure_expr_kind(&mut expr.node);
+ noop_visit_expr(&mut expr, self);
+ Some(expr)
}
- fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
- match self.configure_stmt(stmt) {
- Some(stmt) => fold::noop_fold_stmt(stmt, self),
- None => return SmallVec::new(),
- }
+ fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
+ noop_flat_map_stmt(configure!(self, stmt), self)
}
- fn fold_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
- fold::noop_fold_item(configure!(self, item), self)
+ fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+ noop_flat_map_item(configure!(self, item), self)
}
- fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]>
- {
- fold::noop_fold_impl_item(configure!(self, item), self)
+ fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
+ noop_flat_map_impl_item(configure!(self, item), self)
}
- fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
- fold::noop_fold_trait_item(configure!(self, item), self)
+ fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
+ noop_flat_map_trait_item(configure!(self, item), self)
}
- fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+ fn visit_mac(&mut self, _mac: &mut ast::Mac) {
// Don't configure interpolated AST (cf. issue #34171).
// Interpolated AST will get configured once the surrounding tokens are parsed.
- mac
}
- fn fold_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> {
- fold::noop_fold_pat(self.configure_pat(pattern), self)
+ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
+ self.configure_pat(pat);
+ noop_visit_pat(pat, self)
}
}