diff options
Diffstat (limited to 'compiler/rustc_ast/src')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 81 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/ast_like.rs | 219 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/attr/mod.rs | 106 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/lib.rs | 2 |
4 files changed, 224 insertions, 184 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 16b4378e7f7..de44a2031ab 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2912,84 +2912,3 @@ impl TryFrom<ItemKind> for ForeignItemKind { } pub type ForeignItem = Item<ForeignItemKind>; - -pub trait HasTokens { - /// Called by `Parser::collect_tokens` to store the collected - /// tokens inside an AST node - fn finalize_tokens(&mut self, tokens: LazyTokenStream); -} - -impl<T: HasTokens + 'static> HasTokens for P<T> { - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - (**self).finalize_tokens(tokens); - } -} - -impl<T: HasTokens> HasTokens for Option<T> { - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if let Some(inner) = self { - inner.finalize_tokens(tokens); - } - } -} - -impl HasTokens for 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); - } - } - AttrKind::DocComment(..) => { - panic!("Called finalize_tokens on doc comment attr {:?}", self) - } - } - } -} - -impl HasTokens for Stmt { - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - let stmt_tokens = match self.kind { - 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); - } - } -} - -macro_rules! derive_has_tokens { - ($($ty:path),*) => { $( - impl HasTokens for $ty { - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if self.tokens.is_none() { - self.tokens = Some(tokens); - } - } - } - )* } -} - -derive_has_tokens! { - Item, Expr, Ty, AttrItem, Visibility, Path, Block, Pat -} - -macro_rules! derive_has_attrs_no_tokens { - ($($ty:path),*) => { $( - impl HasTokens for $ty { - fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {} - } - )* } -} - -// These ast nodes only support inert attributes, so they don't -// store tokens (since nothing can observe them) -derive_has_attrs_no_tokens! { - StructField, Arm, - Field, FieldPat, Variant, Param, GenericParam -} diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs new file mode 100644 index 00000000000..6649cda69a0 --- /dev/null +++ b/compiler/rustc_ast/src/ast_like.rs @@ -0,0 +1,219 @@ +use super::ptr::P; +use super::tokenstream::LazyTokenStream; +use super::{Arm, Field, FieldPat, GenericParam, Param, StructField, Variant}; +use super::{AssocItem, Expr, ForeignItem, Item, Local}; +use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility}; +use super::{AttrVec, Attribute, Stmt, StmtKind}; + +/// An `AstLike` represents an AST node (or some wrapper around +/// and AST node) which stores some combination of attributes +/// and tokens. +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!") + } +} + +impl<T: AstLike + 'static> AstLike for P<T> { + fn attrs(&self) -> &[Attribute] { + (**self).attrs() + } + 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 visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) { + crate::mut_visit::visit_clobber(attrs, |attrs| { + let mut vec = attrs.into(); + f(&mut vec); + vec.into() + }); +} + +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(), + StmtKind::Empty => &[], + StmtKind::MacCall(ref mac) => &*mac.attrs, + } + } + + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + match self { + StmtKind::Local(local) => local.visit_attrs(f), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), + StmtKind::Item(item) => item.visit_attrs(f), + StmtKind::Empty => {} + 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); + } + } +} + +impl AstLike for Stmt { + fn attrs(&self) -> &[Attribute] { + self.kind.attrs() + } + + 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) + } +} + +impl AstLike for Attribute { + fn attrs(&self) -> &[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); + } + } + AttrKind::DocComment(..) => { + panic!("Called finalize_tokens on doc comment attr {:?}", self) + } + } + } +} + +impl<T: AstLike> AstLike for Option<T> { + fn attrs(&self) -> &[Attribute] { + self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[]) + } + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + if let Some(inner) = self.as_mut() { + inner.visit_attrs(f); + } + } + fn finalize_tokens(&mut self, tokens: LazyTokenStream) { + if let Some(inner) = self { + inner.finalize_tokens(tokens); + } + } +} + +/// Helper trait for the macros below. Abstracts over +/// the two types of attribute fields that AST nodes +/// may have (`Vec<Attribute>` or `AttrVec`) +trait VecOrAttrVec { + fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)); +} + +impl VecOrAttrVec for Vec<Attribute> { + fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + f(self) + } +} + +impl VecOrAttrVec for AttrVec { + fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + visit_attrvec(self, f) + } +} + +macro_rules! derive_has_tokens_and_attrs { + ($($ty:path),*) => { $( + impl AstLike for $ty { + fn attrs(&self) -> &[Attribute] { + &self.attrs + } + + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + VecOrAttrVec::visit(&mut self.attrs, f) + } + + fn finalize_tokens(&mut self, tokens: LazyTokenStream) { + if self.tokens.is_none() { + self.tokens = Some(tokens); + } + + } + } + )* } +} + +macro_rules! derive_has_attrs_no_tokens { + ($($ty:path),*) => { $( + impl AstLike for $ty { + fn attrs(&self) -> &[Attribute] { + &self.attrs + } + + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { + VecOrAttrVec::visit(&mut self.attrs, f) + } + + fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {} + } + )* } +} + +macro_rules! derive_has_tokens_no_attrs { + ($($ty:path),*) => { $( + impl AstLike for $ty { + fn attrs(&self) -> &[Attribute] { + &[] + } + + 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); + } + + } + } + )* } +} + +// These AST nodes support both inert and active +// attributes, so they also have tokens. +derive_has_tokens_and_attrs! { + Item, Expr, Local, AssocItem, ForeignItem +} + +// These ast nodes only support inert attributes, so they don't +// store tokens (since nothing can observe them) +derive_has_attrs_no_tokens! { + StructField, Arm, + Field, FieldPat, Variant, Param, GenericParam +} + +// These AST nodes don't support attributes, but can +// be captured by a `macro_rules!` matcher. Therefore, +// they need to store tokens. +derive_has_tokens_no_attrs! { + Ty, Block, AttrItem, Pat, Path, Visibility +} diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 4dcbe4831be..52ac7540f69 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -1,17 +1,15 @@ //! Functions dealing with attributes and meta items. use crate::ast; -use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute}; -use crate::ast::{Expr, GenericParam, Item, Lit, LitKind, Local, Stmt, StmtKind}; +use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, Attribute}; +use crate::ast::{Lit, LitKind}; use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Path, PathSegment}; -use crate::mut_visit::visit_clobber; -use crate::ptr::P; use crate::token::{self, CommentKind, Token}; use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree, TreeAndSpacing}; use rustc_index::bit_set::GrowableBitSet; -use rustc_span::source_map::{BytePos, Spanned}; +use rustc_span::source_map::BytePos; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; @@ -617,101 +615,3 @@ impl NestedMetaItem { MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem) } } - -pub trait HasAttrs: Sized { - fn attrs(&self) -> &[Attribute]; - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)); -} - -impl<T: HasAttrs> HasAttrs for Spanned<T> { - fn attrs(&self) -> &[Attribute] { - self.node.attrs() - } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - self.node.visit_attrs(f); - } -} - -impl HasAttrs for Vec<Attribute> { - fn attrs(&self) -> &[Attribute] { - self - } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - f(self) - } -} - -impl HasAttrs for AttrVec { - fn attrs(&self) -> &[Attribute] { - self - } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - visit_clobber(self, |this| { - let mut vec = this.into(); - f(&mut vec); - vec.into() - }); - } -} - -impl<T: HasAttrs + 'static> HasAttrs for P<T> { - fn attrs(&self) -> &[Attribute] { - (**self).attrs() - } - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - (**self).visit_attrs(f); - } -} - -impl HasAttrs 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(), - StmtKind::Empty => &[], - StmtKind::MacCall(ref mac) => mac.attrs.attrs(), - } - } - - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - match self { - StmtKind::Local(local) => local.visit_attrs(f), - StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), - StmtKind::Item(item) => item.visit_attrs(f), - StmtKind::Empty => {} - StmtKind::MacCall(mac) => { - mac.attrs.visit_attrs(f); - } - } - } -} - -impl HasAttrs for Stmt { - fn attrs(&self) -> &[ast::Attribute] { - self.kind.attrs() - } - - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - self.kind.visit_attrs(f); - } -} - -macro_rules! derive_has_attrs { - ($($ty:path),*) => { $( - impl HasAttrs for $ty { - fn attrs(&self) -> &[Attribute] { - &self.attrs - } - - fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) { - self.attrs.visit_attrs(f); - } - } - )* } -} - -derive_has_attrs! { - Item, Expr, Local, ast::AssocItem, ast::ForeignItem, ast::StructField, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam -} diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index ddf52caed08..4eaef85043c 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -40,6 +40,7 @@ pub mod util { } pub mod ast; +pub mod ast_like; pub mod attr; pub mod crate_disambiguator; pub mod entry; @@ -52,6 +53,7 @@ pub mod tokenstream; pub mod visit; pub use self::ast::*; +pub use self::ast_like::AstLike; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
