Rollup merge of #92573 - petrochenkov:ltrattr3, r=Aaron1011
expand: Refactor InvocationCollector visitor for better code reuse The refactoring part of https://github.com/rust-lang/rust/pull/92473. Invocation collector visitor logic now lives in two main functions: - `fn flat_map_node`, corresponding to "one to many" expansions - `fn visit_node`, corresponding to "one to one" expansions All specific mut visitor methods now use one of these functions. The new `InvocationCollectorNode` trait implemented for all `AstFragment` nodes provides the necessary small pieces of functionality required to implement the `(flat_map,visit)_node` functions. r? `@Aaron1011`
This commit is contained in:
commit
b681dc2af4
|
@ -6,12 +6,13 @@ use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt};
|
|||
use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
|
||||
use super::{AttrVec, Attribute, Stmt, StmtKind};
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// 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 + Debug {
|
||||
pub trait AstLike: Sized + fmt::Debug {
|
||||
/// This is `true` if this `AstLike` might support 'custom' (proc-macro) inner
|
||||
/// attributes. Attributes like `#![cfg]` and `#![cfg_attr]` are not
|
||||
/// considered 'custom' attributes
|
||||
|
@ -285,3 +286,37 @@ derive_has_attrs_no_tokens! {
|
|||
derive_has_tokens_no_attrs! {
|
||||
Ty, Block, AttrItem, Pat, Path, Visibility
|
||||
}
|
||||
|
||||
/// A newtype around an `AstLike` node that implements `AstLike` itself.
|
||||
pub struct AstLikeWrapper<Wrapped, Tag> {
|
||||
pub wrapped: Wrapped,
|
||||
pub tag: PhantomData<Tag>,
|
||||
}
|
||||
|
||||
impl<Wrapped, Tag> AstLikeWrapper<Wrapped, Tag> {
|
||||
pub fn new(wrapped: Wrapped, _tag: Tag) -> AstLikeWrapper<Wrapped, Tag> {
|
||||
AstLikeWrapper { wrapped, tag: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Wrapped: fmt::Debug, Tag> fmt::Debug for AstLikeWrapper<Wrapped, Tag> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("AstLikeWrapper")
|
||||
.field("wrapped", &self.wrapped)
|
||||
.field("tag", &self.tag)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Wrapped: AstLike, Tag> AstLike for AstLikeWrapper<Wrapped, Tag> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = Wrapped::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
self.wrapped.attrs()
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
self.wrapped.visit_attrs(f)
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
self.wrapped.tokens_mut()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ pub mod tokenstream;
|
|||
pub mod visit;
|
||||
|
||||
pub use self::ast::*;
|
||||
pub use self::ast_like::AstLike;
|
||||
pub use self::ast_like::{AstLike, AstLikeWrapper};
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ macro_rules! configure {
|
|||
}
|
||||
|
||||
impl<'a> StripUnconfigured<'a> {
|
||||
pub fn configure<T: AstLike>(&mut self, mut node: T) -> Option<T> {
|
||||
pub fn configure<T: AstLike>(&self, mut node: T) -> Option<T> {
|
||||
self.process_cfg_attrs(&mut node);
|
||||
if self.in_cfg(node.attrs()) {
|
||||
self.try_configure_tokens(&mut node);
|
||||
|
@ -248,7 +248,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_configure_tokens<T: AstLike>(&mut self, node: &mut T) {
|
||||
fn try_configure_tokens<T: AstLike>(&self, node: &mut T) {
|
||||
if self.config_tokens {
|
||||
if let Some(Some(tokens)) = node.tokens_mut() {
|
||||
let attr_annotated_tokens = tokens.create_token_stream();
|
||||
|
@ -257,10 +257,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn configure_krate_attrs(
|
||||
&mut self,
|
||||
mut attrs: Vec<ast::Attribute>,
|
||||
) -> Option<Vec<ast::Attribute>> {
|
||||
fn configure_krate_attrs(&self, mut attrs: Vec<ast::Attribute>) -> Option<Vec<ast::Attribute>> {
|
||||
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
|
||||
if self.in_cfg(&attrs) { Some(attrs) } else { None }
|
||||
}
|
||||
|
@ -269,7 +266,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
/// This is only used during the invocation of `derive` proc-macros,
|
||||
/// which require that we cfg-expand their entire input.
|
||||
/// Normal cfg-expansion operates on parsed AST nodes via the `configure` method
|
||||
fn configure_tokens(&mut self, stream: &AttrAnnotatedTokenStream) -> AttrAnnotatedTokenStream {
|
||||
fn configure_tokens(&self, stream: &AttrAnnotatedTokenStream) -> AttrAnnotatedTokenStream {
|
||||
fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool {
|
||||
stream.0.iter().all(|(tree, _spacing)| match tree {
|
||||
AttrAnnotatedTokenTree::Attributes(_) => false,
|
||||
|
@ -325,7 +322,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.
|
||||
fn process_cfg_attrs<T: AstLike>(&mut self, node: &mut T) {
|
||||
fn process_cfg_attrs<T: AstLike>(&self, node: &mut T) {
|
||||
node.visit_attrs(|attrs| {
|
||||
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
|
||||
});
|
||||
|
@ -338,7 +335,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
/// 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.
|
||||
fn process_cfg_attr(&mut self, attr: Attribute) -> Vec<Attribute> {
|
||||
fn process_cfg_attr(&self, attr: Attribute) -> Vec<Attribute> {
|
||||
if !attr.has_name(sym::cfg_attr) {
|
||||
return vec![attr];
|
||||
}
|
||||
|
@ -461,7 +458,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
pub fn configure_expr(&self, expr: &mut P<ast::Expr>) {
|
||||
for attr in expr.attrs.iter() {
|
||||
self.maybe_emit_expr_attr_err(attr);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
|||
#![feature(associated_type_bounds)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(decl_macro)]
|
||||
#![cfg_attr(bootstrap, feature(destructuring_assignment))]
|
||||
|
|
|
@ -123,7 +123,7 @@ pub fn placeholder(
|
|||
span,
|
||||
is_placeholder: true,
|
||||
}]),
|
||||
AstFragmentKind::Fields => AstFragment::Fields(smallvec![ast::ExprField {
|
||||
AstFragmentKind::ExprFields => AstFragment::ExprFields(smallvec![ast::ExprField {
|
||||
attrs: Default::default(),
|
||||
expr: expr_placeholder(),
|
||||
id,
|
||||
|
@ -132,7 +132,7 @@ pub fn placeholder(
|
|||
span,
|
||||
is_placeholder: true,
|
||||
}]),
|
||||
AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![ast::PatField {
|
||||
AstFragmentKind::PatFields => AstFragment::PatFields(smallvec![ast::PatField {
|
||||
attrs: Default::default(),
|
||||
id,
|
||||
ident,
|
||||
|
@ -159,7 +159,7 @@ pub fn placeholder(
|
|||
ty: ty(),
|
||||
is_placeholder: true,
|
||||
}]),
|
||||
AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ast::FieldDef {
|
||||
AstFragmentKind::FieldDefs => AstFragment::FieldDefs(smallvec![ast::FieldDef {
|
||||
attrs: Default::default(),
|
||||
id,
|
||||
ident: None,
|
||||
|
|
Loading…
Reference in a new issue