Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expand: Refactor InvocationCollector visitor for better code reuse #92573

Merged
merged 4 commits into from
Jan 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions compiler/rustc_ast/src/ast_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deriving this impl puts the Debug requirement on tag types, unfortunately.


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()
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
17 changes: 7 additions & 10 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand All @@ -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 }
}
Expand All @@ -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,
Expand Down Expand Up @@ -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));
});
Expand All @@ -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];
}
Expand Down Expand Up @@ -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);
}
Expand Down
Loading