diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/ast_like.rs | 88 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/cfg_eval.rs | 157 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/derive.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/config.rs | 175 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr_wrapper.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 |
9 files changed, 226 insertions, 259 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index de44a2031ab..99196210e00 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -915,16 +915,6 @@ impl Stmt { } } - pub fn tokens_mut(&mut self) -> Option<&mut LazyTokenStream> { - match self.kind { - StmtKind::Local(ref mut local) => local.tokens.as_mut(), - StmtKind::Item(ref mut item) => item.tokens.as_mut(), - StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens.as_mut(), - StmtKind::Empty => None, - StmtKind::MacCall(ref mut mac) => mac.tokens.as_mut(), - } - } - pub fn has_trailing_semicolon(&self) -> bool { match &self.kind { StmtKind::Semi(_) => true, diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index 6649cda69a0..a71f2ac9815 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -11,13 +11,7 @@ use super::{AttrVec, Attribute, Stmt, StmtKind}; pub trait AstLike: Sized { fn attrs(&self) -> &[Attribute]; fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)); - /// Called by `Parser::collect_tokens` to store the collected - /// tokens inside an AST node - fn finalize_tokens(&mut self, _tokens: LazyTokenStream) { - // This default impl makes this trait easier to implement - // in tools like `rust-analyzer` - panic!("`finalize_tokens` is not supported!") - } + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>; } impl<T: AstLike + 'static> AstLike for P<T> { @@ -27,8 +21,8 @@ impl<T: AstLike + 'static> AstLike for P<T> { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { (**self).visit_attrs(f); } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - (**self).finalize_tokens(tokens) + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + (**self).tokens_mut() } } @@ -42,12 +36,12 @@ fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) { impl AstLike for StmtKind { fn attrs(&self) -> &[Attribute] { - match *self { - StmtKind::Local(ref local) => local.attrs(), - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), - StmtKind::Item(ref item) => item.attrs(), + match self { + StmtKind::Local(local) => local.attrs(), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(), + StmtKind::Item(item) => item.attrs(), StmtKind::Empty => &[], - StmtKind::MacCall(ref mac) => &*mac.attrs, + StmtKind::MacCall(mac) => &mac.attrs, } } @@ -60,17 +54,14 @@ impl AstLike for StmtKind { StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f), } } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - let stmt_tokens = match self { - StmtKind::Local(ref mut local) => &mut local.tokens, - StmtKind::Item(ref mut item) => &mut item.tokens, - StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => &mut expr.tokens, - StmtKind::Empty => return, - StmtKind::MacCall(ref mut mac) => &mut mac.tokens, - }; - if stmt_tokens.is_none() { - *stmt_tokens = Some(tokens); - } + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + Some(match self { + StmtKind::Local(local) => &mut local.tokens, + StmtKind::Item(item) => &mut item.tokens, + StmtKind::Expr(expr) | StmtKind::Semi(expr) => &mut expr.tokens, + StmtKind::Empty => return None, + StmtKind::MacCall(mac) => &mut mac.tokens, + }) } } @@ -82,8 +73,8 @@ impl AstLike for Stmt { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { self.kind.visit_attrs(f); } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - self.kind.finalize_tokens(tokens) + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + self.kind.tokens_mut() } } @@ -92,17 +83,13 @@ impl AstLike for Attribute { &[] } fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {} - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - match &mut self.kind { - AttrKind::Normal(_, attr_tokens) => { - if attr_tokens.is_none() { - *attr_tokens = Some(tokens); - } + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + Some(match &mut self.kind { + AttrKind::Normal(_, tokens) => tokens, + kind @ AttrKind::DocComment(..) => { + panic!("Called tokens_mut on doc comment attr {:?}", kind) } - AttrKind::DocComment(..) => { - panic!("Called finalize_tokens on doc comment attr {:?}", self) - } - } + }) } } @@ -115,10 +102,8 @@ impl<T: AstLike> AstLike for Option<T> { inner.visit_attrs(f); } } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if let Some(inner) = self { - inner.finalize_tokens(tokens); - } + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + self.as_mut().and_then(|inner| inner.tokens_mut()) } } @@ -152,11 +137,8 @@ macro_rules! derive_has_tokens_and_attrs { VecOrAttrVec::visit(&mut self.attrs, f) } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if self.tokens.is_none() { - self.tokens = Some(tokens); - } - + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + Some(&mut self.tokens) } } )* } @@ -173,7 +155,9 @@ macro_rules! derive_has_attrs_no_tokens { VecOrAttrVec::visit(&mut self.attrs, f) } - fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {} + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + None + } } )* } } @@ -185,14 +169,10 @@ macro_rules! derive_has_tokens_no_attrs { &[] } - fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) { - } - - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if self.tokens.is_none() { - self.tokens = Some(tokens); - } + fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {} + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + Some(&mut self.tokens) } } )* } diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs new file mode 100644 index 00000000000..eea4d785dee --- /dev/null +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -0,0 +1,157 @@ +use crate::util::check_builtin_macro_attribute; + +use rustc_ast::mut_visit::{self, MutVisitor}; +use rustc_ast::ptr::P; +use rustc_ast::{self as ast, AstLike}; +use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::config::StripUnconfigured; +use rustc_expand::configure; +use rustc_span::symbol::sym; +use rustc_span::Span; +use smallvec::SmallVec; + +crate fn expand( + ecx: &mut ExtCtxt<'_>, + _span: Span, + meta_item: &ast::MetaItem, + annotatable: Annotatable, +) -> Vec<Annotatable> { + check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); + cfg_eval(ecx, annotatable) +} + +crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> { + let mut visitor = CfgEval { + cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false }, + }; + let mut annotatable = visitor.configure_annotatable(annotatable); + if visitor.cfg.modified { + // 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. + if let Some(tokens) = annotatable.tokens_mut() { + *tokens = None; + } + } + vec![annotatable] +} + +struct CfgEval<'a> { + cfg: StripUnconfigured<'a>, +} + +impl CfgEval<'_> { + fn configure<T: AstLike>(&mut self, node: T) -> Option<T> { + self.cfg.configure(node) + } + + fn configure_annotatable(&mut self, annotatable: Annotatable) -> Annotatable { + // Since the item itself has already been configured by the InvocationCollector, + // we know that fold result vector will contain exactly one element + match annotatable { + 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()), + Annotatable::Field(field) => { + Annotatable::Field(self.flat_map_field(field).pop().unwrap()) + } + Annotatable::FieldPat(fp) => { + Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap()) + } + 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()) + } + Annotatable::StructField(sf) => { + Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap()) + } + 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) + } + + 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) + } + + fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> { + mut_visit::noop_flat_map_field(configure!(self, field), self) + } + + fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> { + mut_visit::noop_flat_map_field_pattern(configure!(self, fp), self) + } + + fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> { + mut_visit::noop_flat_map_param(configure!(self, p), self) + } + + fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> { + mut_visit::noop_flat_map_struct_field(configure!(self, sf), self) + } + + fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { + mut_visit::noop_flat_map_variant(configure!(self, variant), self) + } +} diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index fad64858ce3..0da2c1c1021 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,7 +1,8 @@ +use crate::cfg_eval::cfg_eval; + use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; -use rustc_expand::config::StripUnconfigured; use rustc_feature::AttributeTemplate; use rustc_parse::validate_attr; use rustc_session::Session; @@ -51,26 +52,7 @@ impl MultiItemModifier for Expander { // FIXME: Try to cache intermediate results to avoid collecting same paths multiple times. match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) { - Ok(()) => { - let mut visitor = - StripUnconfigured { sess, features: ecx.ecfg.features, modified: false }; - let mut item = visitor.fully_configure(item); - if visitor.modified { - // 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. - match &mut item { - Annotatable::Item(item) => item, - Annotatable::Stmt(stmt) => match &mut stmt.kind { - StmtKind::Item(item) => item, - _ => unreachable!(), - }, - _ => unreachable!(), - } - .tokens = None; - } - ExpandResult::Ready(vec![item]) - } + Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)), Err(Indeterminate) => ExpandResult::Retry(item), } } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9a3c914337c..1017b23e567 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -24,6 +24,7 @@ mod asm; mod assert; mod cfg; mod cfg_accessible; +mod cfg_eval; mod compile_error; mod concat; mod concat_idents; @@ -89,6 +90,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, + cfg_eval: cfg_eval::expand, derive: derive::Expander, global_allocator: global_allocator::expand, test: test::expand_test, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 5bd06e8e7d1..666065efdfb 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -81,8 +81,22 @@ impl AstLike for Annotatable { } } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - panic!("Called finalize_tokens on an Annotatable: {:?}", tokens); + fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> { + match self { + Annotatable::Item(item) => item.tokens_mut(), + Annotatable::TraitItem(trait_item) => trait_item.tokens_mut(), + Annotatable::ImplItem(impl_item) => impl_item.tokens_mut(), + Annotatable::ForeignItem(foreign_item) => foreign_item.tokens_mut(), + Annotatable::Stmt(stmt) => stmt.tokens_mut(), + Annotatable::Expr(expr) => expr.tokens_mut(), + Annotatable::Arm(arm) => arm.tokens_mut(), + Annotatable::Field(field) => field.tokens_mut(), + Annotatable::FieldPat(fp) => fp.tokens_mut(), + Annotatable::GenericParam(gp) => gp.tokens_mut(), + Annotatable::Param(p) => p.tokens_mut(), + Annotatable::StructField(sf) => sf.tokens_mut(), + Annotatable::Variant(v) => v.tokens_mut(), + } } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 7d0becf1f5d..a23731cf309 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -1,8 +1,5 @@ //! Conditional compilation stripping. -use crate::base::Annotatable; - -use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{DelimToken, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing, TokenStream, TokenTree}; @@ -22,8 +19,6 @@ use rustc_span::edition::{Edition, ALL_EDITIONS}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use smallvec::SmallVec; - /// A folder that strips out items that do not belong in the current configuration. pub struct StripUnconfigured<'a> { pub sess: &'a Session, @@ -272,7 +267,7 @@ impl<'a> StripUnconfigured<'a> { /// Gives compiler warnings 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: AstLike>(&mut self, node: &mut T) { + fn process_cfg_attrs<T: AstLike>(&mut self, node: &mut T) { node.visit_attrs(|attrs| { attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); }); @@ -387,7 +382,7 @@ impl<'a> StripUnconfigured<'a> { } /// Determines if a node with the given attributes should be included in this configuration. - pub fn in_cfg(&self, attrs: &[Attribute]) -> bool { + fn in_cfg(&self, attrs: &[Attribute]) -> bool { attrs.iter().all(|attr| { if !is_cfg(self.sess, attr) { return true; @@ -427,16 +422,8 @@ impl<'a> StripUnconfigured<'a> { }) } - /// Visit attributes on expression and statements (but not attributes on items in blocks). - fn visit_expr_attrs(&mut self, attrs: &[Attribute]) { - // flag the offending attributes - for attr in attrs.iter() { - self.maybe_emit_expr_attr_err(attr); - } - } - /// If attributes are not allowed on expressions, emit an error for `attr` - pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { + crate fn maybe_emit_expr_attr_err(&self, attr: &Attribute) { if !self.features.map_or(true, |features| features.stmt_expr_attributes) { let mut err = feature_err( &self.sess.parse_sess, @@ -453,49 +440,10 @@ impl<'a> StripUnconfigured<'a> { } } - pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - let ast::ForeignMod { unsafety: _, abi: _, items } = foreign_mod; - items.flat_map_in_place(|item| self.configure(item)); - } - - fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { - match vdata { - ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => { - fields.flat_map_in_place(|field| self.configure(field)) - } - ast::VariantData::Unit(_) => {} - } - } - - pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) { - match item { - 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.data); - } - } - _ => {} - } - } - - pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) { - match expr_kind { - ast::ExprKind::Match(_m, arms) => { - arms.flat_map_in_place(|arm| self.configure(arm)); - } - ast::ExprKind::Struct(_path, fields, _base) => { - fields.flat_map_in_place(|field| self.configure(field)); - } - _ => {} - } - } - pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) { - self.visit_expr_attrs(expr.attrs()); + for attr in expr.attrs.iter() { + self.maybe_emit_expr_attr_err(attr); + } // If an expr is valid to cfg away it will have been removed by the // outer stmt or expression folder before descending in here. @@ -511,117 +459,6 @@ impl<'a> StripUnconfigured<'a> { self.process_cfg_attrs(expr) } - - pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) { - if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind { - fields.flat_map_in_place(|field| self.configure(field)); - } - } - - pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { - fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); - } - - pub fn fully_configure(&mut self, item: Annotatable) -> Annotatable { - // Since the item itself has already been configured by the InvocationCollector, - // we know that fold result vector will contain exactly one element - match item { - 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()), - Annotatable::Field(field) => { - Annotatable::Field(self.flat_map_field(field).pop().unwrap()) - } - Annotatable::FieldPat(fp) => { - Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap()) - } - 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()) - } - Annotatable::StructField(sf) => { - Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap()) - } - Annotatable::Variant(v) => { - Annotatable::Variant(self.flat_map_variant(v).pop().unwrap()) - } - } - } -} - -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 visit_item_kind(&mut self, item: &mut ast::ItemKind) { - self.configure_item_kind(item); - noop_visit_item_kind(item, self); - } - - fn visit_expr(&mut self, expr: &mut P<ast::Expr>) { - self.configure_expr(expr); - self.configure_expr_kind(&mut expr.kind); - 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); - self.configure_expr_kind(&mut expr.kind); - noop_visit_expr(&mut expr, self); - Some(expr) - } - - fn flat_map_generic_param( - &mut self, - param: ast::GenericParam, - ) -> SmallVec<[ast::GenericParam; 1]> { - noop_flat_map_generic_param(configure!(self, param), self) - } - - fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { - noop_flat_map_stmt(configure!(self, stmt), 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 flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> { - 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]> { - noop_flat_map_assoc_item(configure!(self, item), self) - } - - fn visit_pat(&mut self, pat: &mut P<ast::Pat>) { - self.configure_pat(pat); - noop_visit_pat(pat, self) - } - - fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) { - self.configure_fn_decl(&mut fn_decl); - noop_visit_fn_decl(fn_decl, self); - } } fn is_cfg(sess: &Session, attr: &Attribute) -> bool { diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index f45d8d6c7a0..7512f46988c 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -72,6 +72,10 @@ impl<'a> Parser<'a> { let cursor_snapshot = self.token_cursor.clone(); let (mut ret, trailing_token) = f(self, attrs.attrs)?; + let tokens = match ret.tokens_mut() { + Some(tokens) if tokens.is_none() => tokens, + _ => return Ok(ret), + }; // Produces a `TokenStream` on-demand. Using `cursor_snapshot` // and `num_calls`, we can reconstruct the `TokenStream` seen @@ -128,14 +132,14 @@ impl<'a> Parser<'a> { } } - let lazy_impl = LazyTokenStreamImpl { + *tokens = Some(LazyTokenStream::new(LazyTokenStreamImpl { start_token, num_calls, cursor_snapshot, desugar_doc_comments: self.desugar_doc_comments, append_unglued_token: self.token_cursor.append_unglued_token.clone(), - }; - ret.finalize_tokens(LazyTokenStream::new(lazy_impl)); + })); + Ok(ret) } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9663760cba1..507eb1e1cbe 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -344,6 +344,7 @@ symbols! { cfg_attr, cfg_attr_multi, cfg_doctest, + cfg_eval, cfg_panic, cfg_sanitize, cfg_target_feature, |
