ast: Introduce some traits to get AST node properties generically
And use them to avoid constructing some artificial `Nonterminal` tokens during expansion
This commit is contained in:
parent
ee6eaabdd4
commit
f2b7fa4847
@ -929,16 +929,6 @@ pub struct Stmt {
|
||||
}
|
||||
|
||||
impl Stmt {
|
||||
pub fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
match self.kind {
|
||||
StmtKind::Local(ref local) => local.tokens.as_ref(),
|
||||
StmtKind::Item(ref item) => item.tokens.as_ref(),
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.tokens.as_ref(),
|
||||
StmtKind::Empty => None,
|
||||
StmtKind::MacCall(ref mac) => mac.tokens.as_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_trailing_semicolon(&self) -> bool {
|
||||
match &self.kind {
|
||||
StmtKind::Semi(_) => true,
|
||||
@ -2684,13 +2674,6 @@ pub fn span_with_attributes(&self) -> Span {
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Into<ItemKind>> Item<K> {
|
||||
pub fn into_item(self) -> Item {
|
||||
let Item { attrs, id, span, vis, ident, kind, tokens } = self;
|
||||
Item { attrs, id, span, vis, ident, kind: kind.into(), tokens }
|
||||
}
|
||||
}
|
||||
|
||||
/// `extern` qualifier on a function item or function type.
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
|
||||
pub enum Extern {
|
||||
|
@ -1,320 +0,0 @@
|
||||
use super::ptr::P;
|
||||
use super::token::Nonterminal;
|
||||
use super::tokenstream::LazyTokenStream;
|
||||
use super::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
|
||||
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;
|
||||
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 + 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
|
||||
///
|
||||
/// If this is `false`, then this `AstLike` definitely does
|
||||
/// not support 'custom' inner attributes, which enables some optimizations
|
||||
/// during token collection.
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool;
|
||||
fn attrs(&self) -> &[Attribute];
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>;
|
||||
}
|
||||
|
||||
impl<T: AstLike + 'static> AstLike for P<T> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
(**self).attrs()
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
(**self).visit_attrs(f);
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
(**self).tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl AstLike for crate::token::Nonterminal {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.attrs(),
|
||||
Nonterminal::NtStmt(stmt) => stmt.attrs(),
|
||||
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.attrs(),
|
||||
Nonterminal::NtPat(_)
|
||||
| Nonterminal::NtTy(_)
|
||||
| Nonterminal::NtMeta(_)
|
||||
| Nonterminal::NtPath(_)
|
||||
| Nonterminal::NtVis(_)
|
||||
| Nonterminal::NtBlock(_)
|
||||
| Nonterminal::NtIdent(..)
|
||||
| Nonterminal::NtLifetime(_) => &[],
|
||||
}
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.visit_attrs(f),
|
||||
Nonterminal::NtStmt(stmt) => stmt.visit_attrs(f),
|
||||
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.visit_attrs(f),
|
||||
Nonterminal::NtPat(_)
|
||||
| Nonterminal::NtTy(_)
|
||||
| Nonterminal::NtMeta(_)
|
||||
| Nonterminal::NtPath(_)
|
||||
| Nonterminal::NtVis(_)
|
||||
| Nonterminal::NtBlock(_)
|
||||
| Nonterminal::NtIdent(..)
|
||||
| Nonterminal::NtLifetime(_) => {}
|
||||
}
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.tokens_mut(),
|
||||
Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
|
||||
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
|
||||
Nonterminal::NtPat(pat) => pat.tokens_mut(),
|
||||
Nonterminal::NtTy(ty) => ty.tokens_mut(),
|
||||
Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),
|
||||
Nonterminal::NtPath(path) => path.tokens_mut(),
|
||||
Nonterminal::NtVis(vis) => vis.tokens_mut(),
|
||||
Nonterminal::NtBlock(block) => block.tokens_mut(),
|
||||
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
// This might be an `StmtKind::Item`, which contains
|
||||
// an item that supports inner attrs
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
match self {
|
||||
StmtKind::Local(local) => local.attrs(),
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(),
|
||||
StmtKind::Item(item) => item.attrs(),
|
||||
StmtKind::Empty => &[],
|
||||
StmtKind::MacCall(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 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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AstLike for Stmt {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = StmtKind::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
self.kind.attrs()
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
self.kind.visit_attrs(f);
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
self.kind.tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl AstLike for Attribute {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&[]
|
||||
}
|
||||
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AstLike> AstLike for Option<T> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
|
||||
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 tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
self.as_mut().and_then(|inner| inner.tokens_mut())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
(
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner_attrs:literal;
|
||||
$($ty:path),*
|
||||
) => { $(
|
||||
impl AstLike for $ty {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner_attrs;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
VecOrAttrVec::visit(&mut self.attrs, f)
|
||||
}
|
||||
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
Some(&mut self.tokens)
|
||||
}
|
||||
|
||||
}
|
||||
)* }
|
||||
}
|
||||
|
||||
macro_rules! derive_has_attrs_no_tokens {
|
||||
($($ty:path),*) => { $(
|
||||
impl AstLike for $ty {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
VecOrAttrVec::visit(&mut self.attrs, f)
|
||||
}
|
||||
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
|
||||
macro_rules! derive_has_tokens_no_attrs {
|
||||
($($ty:path),*) => { $(
|
||||
impl AstLike for $ty {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
Some(&mut self.tokens)
|
||||
}
|
||||
}
|
||||
)* }
|
||||
}
|
||||
|
||||
// These ast nodes support both active and inert attributes,
|
||||
// so they have tokens collected to pass to proc macros
|
||||
derive_has_tokens_and_attrs! {
|
||||
// Both `Item` and `AssocItem` can have bodies, which
|
||||
// can contain inner attributes
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true;
|
||||
Item, AssocItem, ForeignItem
|
||||
}
|
||||
|
||||
derive_has_tokens_and_attrs! {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
|
||||
Local, MacCallStmt, Expr
|
||||
}
|
||||
|
||||
// These ast nodes only support inert attributes, so they don't
|
||||
// store tokens (since nothing can observe them)
|
||||
derive_has_attrs_no_tokens! {
|
||||
FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam, Crate
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
}
|
436
compiler/rustc_ast/src/ast_traits.rs
Normal file
436
compiler/rustc_ast/src/ast_traits.rs
Normal file
@ -0,0 +1,436 @@
|
||||
//! A set of traits implemented for various AST nodes,
|
||||
//! typically those used in AST fragments during macro expansion.
|
||||
//! The traits are not implemented exhaustively, only when actually necessary.
|
||||
|
||||
use crate::ptr::P;
|
||||
use crate::token::Nonterminal;
|
||||
use crate::tokenstream::LazyTokenStream;
|
||||
use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
|
||||
use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
|
||||
use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
|
||||
use crate::{AttrVec, Attribute, Stmt, StmtKind};
|
||||
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// A utility trait to reduce boilerplate.
|
||||
/// Standard `Deref(Mut)` cannot be reused due to coherence.
|
||||
pub trait AstDeref {
|
||||
type Target;
|
||||
fn ast_deref(&self) -> &Self::Target;
|
||||
fn ast_deref_mut(&mut self) -> &mut Self::Target;
|
||||
}
|
||||
|
||||
macro_rules! impl_not_ast_deref {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl !AstDeref for $T {}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_not_ast_deref!(AssocItem, Expr, ForeignItem, Item, Stmt);
|
||||
|
||||
impl<T> AstDeref for P<T> {
|
||||
type Target = T;
|
||||
fn ast_deref(&self) -> &Self::Target {
|
||||
self
|
||||
}
|
||||
fn ast_deref_mut(&mut self) -> &mut Self::Target {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having an ID.
|
||||
pub trait HasNodeId {
|
||||
fn node_id(&self) -> NodeId;
|
||||
fn node_id_mut(&mut self) -> &mut NodeId;
|
||||
}
|
||||
|
||||
macro_rules! impl_has_node_id {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasNodeId for $T {
|
||||
fn node_id(&self) -> NodeId {
|
||||
self.id
|
||||
}
|
||||
fn node_id_mut(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_has_node_id!(
|
||||
Arm,
|
||||
AssocItem,
|
||||
Crate,
|
||||
Expr,
|
||||
ExprField,
|
||||
FieldDef,
|
||||
ForeignItem,
|
||||
GenericParam,
|
||||
Item,
|
||||
Param,
|
||||
Pat,
|
||||
PatField,
|
||||
Stmt,
|
||||
Ty,
|
||||
Variant,
|
||||
);
|
||||
|
||||
impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
|
||||
fn node_id(&self) -> NodeId {
|
||||
self.ast_deref().node_id()
|
||||
}
|
||||
fn node_id_mut(&mut self) -> &mut NodeId {
|
||||
self.ast_deref_mut().node_id_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having a span.
|
||||
pub trait HasSpan {
|
||||
fn span(&self) -> Span;
|
||||
}
|
||||
|
||||
macro_rules! impl_has_span {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasSpan for $T {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_has_span!(AssocItem, Expr, ForeignItem, Item, Stmt);
|
||||
|
||||
impl<T: AstDeref<Target: HasSpan>> HasSpan for T {
|
||||
fn span(&self) -> Span {
|
||||
self.ast_deref().span()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having (or not having) collected tokens.
|
||||
pub trait HasTokens {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream>;
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>;
|
||||
}
|
||||
|
||||
macro_rules! impl_has_tokens {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasTokens for $T {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
self.tokens.as_ref()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
Some(&mut self.tokens)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_has_tokens_none {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasTokens for $T {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
None
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility);
|
||||
impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant);
|
||||
|
||||
impl<T: AstDeref<Target: HasTokens>> HasTokens for T {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
self.ast_deref().tokens()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
self.ast_deref_mut().tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasTokens> HasTokens for Option<T> {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
self.as_ref().and_then(|inner| inner.tokens())
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
self.as_mut().and_then(|inner| inner.tokens_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for StmtKind {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
match self {
|
||||
StmtKind::Local(local) => local.tokens.as_ref(),
|
||||
StmtKind::Item(item) => item.tokens(),
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(),
|
||||
StmtKind::Empty => return None,
|
||||
StmtKind::MacCall(mac) => mac.tokens.as_ref(),
|
||||
}
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
match self {
|
||||
StmtKind::Local(local) => Some(&mut local.tokens),
|
||||
StmtKind::Item(item) => item.tokens_mut(),
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(),
|
||||
StmtKind::Empty => return None,
|
||||
StmtKind::MacCall(mac) => Some(&mut mac.tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for Stmt {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
self.kind.tokens()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
self.kind.tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for Attribute {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(_, tokens) => tokens.as_ref(),
|
||||
kind @ AttrKind::DocComment(..) => {
|
||||
panic!("Called tokens on doc comment attr {:?}", kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for Nonterminal {
|
||||
fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.tokens(),
|
||||
Nonterminal::NtStmt(stmt) => stmt.tokens(),
|
||||
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(),
|
||||
Nonterminal::NtPat(pat) => pat.tokens(),
|
||||
Nonterminal::NtTy(ty) => ty.tokens(),
|
||||
Nonterminal::NtMeta(attr_item) => attr_item.tokens(),
|
||||
Nonterminal::NtPath(path) => path.tokens(),
|
||||
Nonterminal::NtVis(vis) => vis.tokens(),
|
||||
Nonterminal::NtBlock(block) => block.tokens(),
|
||||
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
|
||||
}
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||
match self {
|
||||
Nonterminal::NtItem(item) => item.tokens_mut(),
|
||||
Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
|
||||
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
|
||||
Nonterminal::NtPat(pat) => pat.tokens_mut(),
|
||||
Nonterminal::NtTy(ty) => ty.tokens_mut(),
|
||||
Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),
|
||||
Nonterminal::NtPath(path) => path.tokens_mut(),
|
||||
Nonterminal::NtVis(vis) => vis.tokens_mut(),
|
||||
Nonterminal::NtBlock(block) => block.tokens_mut(),
|
||||
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having (or not having) attributes.
|
||||
pub trait HasAttrs {
|
||||
/// This is `true` if this `HasAttrs` might support 'custom' (proc-macro) inner
|
||||
/// attributes. Attributes like `#![cfg]` and `#![cfg_attr]` are not
|
||||
/// considered 'custom' attributes.
|
||||
///
|
||||
/// If this is `false`, then this `HasAttrs` definitely does
|
||||
/// not support 'custom' inner attributes, which enables some optimizations
|
||||
/// during token collection.
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool;
|
||||
fn attrs(&self) -> &[Attribute];
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
|
||||
}
|
||||
|
||||
macro_rules! impl_has_attrs {
|
||||
(const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner:literal, $($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasAttrs for $T {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
VecOrAttrVec::visit(&mut self.attrs, f)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_has_attrs_none {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl HasAttrs for $T {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
&[]
|
||||
}
|
||||
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_has_attrs!(
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true,
|
||||
AssocItem,
|
||||
ForeignItem,
|
||||
Item,
|
||||
);
|
||||
impl_has_attrs!(
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false,
|
||||
Arm,
|
||||
Crate,
|
||||
Expr,
|
||||
ExprField,
|
||||
FieldDef,
|
||||
GenericParam,
|
||||
Param,
|
||||
PatField,
|
||||
Variant,
|
||||
);
|
||||
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
|
||||
|
||||
impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::Target::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
self.ast_deref().attrs()
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
self.ast_deref_mut().visit_attrs(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasAttrs> HasAttrs for Option<T> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasAttrs for StmtKind {
|
||||
// This might be a `StmtKind::Item`, which contains
|
||||
// an item that supports inner attrs.
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true;
|
||||
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
match self {
|
||||
StmtKind::Local(local) => &local.attrs,
|
||||
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(),
|
||||
StmtKind::Item(item) => item.attrs(),
|
||||
StmtKind::Empty => &[],
|
||||
StmtKind::MacCall(mac) => &mac.attrs,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
match self {
|
||||
StmtKind::Local(local) => visit_attrvec(&mut local.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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasAttrs for Stmt {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = StmtKind::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
self.kind.attrs()
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||
self.kind.visit_attrs(f);
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait for the impls above. 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)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
});
|
||||
}
|
||||
|
||||
/// A newtype around an AST node that implements the traits above if the node implements them.
|
||||
pub struct AstNodeWrapper<Wrapped, Tag> {
|
||||
pub wrapped: Wrapped,
|
||||
pub tag: PhantomData<Tag>,
|
||||
}
|
||||
|
||||
impl<Wrapped, Tag> AstNodeWrapper<Wrapped, Tag> {
|
||||
pub fn new(wrapped: Wrapped, _tag: Tag) -> AstNodeWrapper<Wrapped, Tag> {
|
||||
AstNodeWrapper { wrapped, tag: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Wrapped, Tag> AstDeref for AstNodeWrapper<Wrapped, Tag> {
|
||||
type Target = Wrapped;
|
||||
fn ast_deref(&self) -> &Self::Target {
|
||||
&self.wrapped
|
||||
}
|
||||
fn ast_deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.wrapped
|
||||
}
|
||||
}
|
||||
|
||||
impl<Wrapped: fmt::Debug, Tag> fmt::Debug for AstNodeWrapper<Wrapped, Tag> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("AstNodeWrapper")
|
||||
.field("wrapped", &self.wrapped)
|
||||
.field("tag", &self.tag)
|
||||
.finish()
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(attr(deny(warnings)))
|
||||
)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(const_default_impls)]
|
||||
#![feature(const_trait_impl)]
|
||||
@ -16,6 +17,7 @@
|
||||
#![feature(label_break_value)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(nll)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
@ -33,7 +35,7 @@ pub mod util {
|
||||
}
|
||||
|
||||
pub mod ast;
|
||||
pub mod ast_like;
|
||||
pub mod ast_traits;
|
||||
pub mod attr;
|
||||
pub mod entry;
|
||||
pub mod expand;
|
||||
@ -45,7 +47,7 @@ pub mod util {
|
||||
pub mod visit;
|
||||
|
||||
pub use self::ast::*;
|
||||
pub use self::ast_like::{AstLike, AstLikeWrapper};
|
||||
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasSpan, HasTokens};
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(with_negative_coherence)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
mod helpers;
|
||||
|
@ -4,12 +4,42 @@
|
||||
pub mod state;
|
||||
pub use state::{print_crate, AnnNode, Comments, PpAnn, PrintState, State};
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::token::{Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_ast::{self as ast, AstDeref};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub trait AstPrettyPrint {
|
||||
fn pretty_print(&self) -> String;
|
||||
}
|
||||
|
||||
impl<T: AstDeref<Target: AstPrettyPrint>> AstPrettyPrint for T {
|
||||
fn pretty_print(&self) -> String {
|
||||
self.ast_deref().pretty_print()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_ast_pretty_print {
|
||||
($($T:ty => $method:ident),+ $(,)?) => {
|
||||
$(
|
||||
impl AstPrettyPrint for $T {
|
||||
fn pretty_print(&self) -> String {
|
||||
State::new().$method(self)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_ast_pretty_print! {
|
||||
ast::Item => item_to_string,
|
||||
ast::AssocItem => assoc_item_to_string,
|
||||
ast::ForeignItem => foreign_item_to_string,
|
||||
ast::Expr => expr_to_string,
|
||||
ast::Stmt => stmt_to_string,
|
||||
}
|
||||
|
||||
pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
|
||||
State::new().nonterminal_to_string(nt)
|
||||
}
|
||||
|
@ -858,6 +858,14 @@ fn item_to_string(&self, i: &ast::Item) -> String {
|
||||
Self::to_string(|s| s.print_item(i))
|
||||
}
|
||||
|
||||
fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String {
|
||||
Self::to_string(|s| s.print_assoc_item(i))
|
||||
}
|
||||
|
||||
fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String {
|
||||
Self::to_string(|s| s.print_foreign_item(i))
|
||||
}
|
||||
|
||||
fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String {
|
||||
Self::to_string(|s| s.print_generic_params(generic_params))
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]
|
||||
}
|
||||
}
|
||||
|
||||
fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
||||
crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
||||
let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
|
||||
self.ann.pre(self, AnnNode::SubItem(id));
|
||||
self.hardbreak_if_not_bol();
|
||||
@ -496,7 +496,7 @@ fn print_struct(
|
||||
}
|
||||
}
|
||||
|
||||
fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
||||
crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
||||
let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
|
||||
self.ann.pre(self, AnnNode::SubItem(id));
|
||||
self.hardbreak_if_not_bol();
|
||||
|
@ -7,7 +7,7 @@
|
||||
use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::NodeId;
|
||||
use rustc_ast::{mut_visit, visit};
|
||||
use rustc_ast::{AstLike, Attribute};
|
||||
use rustc_ast::{Attribute, HasAttrs, HasTokens};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_expand::config::StripUnconfigured;
|
||||
use rustc_expand::configure;
|
||||
@ -125,7 +125,7 @@ fn visit_attribute(&mut self, attr: &'ast Attribute) {
|
||||
}
|
||||
|
||||
impl CfgEval<'_, '_> {
|
||||
fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
|
||||
fn configure<T: HasAttrs + HasTokens>(&mut self, node: T) -> Option<T> {
|
||||
self.cfg.configure(node)
|
||||
}
|
||||
|
||||
@ -173,13 +173,8 @@ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Anno
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let nt = annotatable.into_nonterminal();
|
||||
|
||||
let mut orig_tokens = rustc_parse::nt_to_tokenstream(
|
||||
&nt,
|
||||
&self.cfg.sess.parse_sess,
|
||||
CanSynthesizeMissingTokens::No,
|
||||
);
|
||||
let mut orig_tokens = annotatable.to_tokens(&self.cfg.sess.parse_sess);
|
||||
|
||||
// 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`)
|
||||
// to `None`-delimited groups containing the corresponding tokens. This
|
||||
|
@ -6,14 +6,14 @@
|
||||
use rustc_ast::token::{self, Nonterminal};
|
||||
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream};
|
||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
|
||||
use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind};
|
||||
use rustc_attr::{self as attr, Deprecation, Stability};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult};
|
||||
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
|
||||
use rustc_lint_defs::BuiltinLintDiagnostics;
|
||||
use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
|
||||
use rustc_parse::{self, parser, to_token_stream, MACRO_ARGUMENTS};
|
||||
use rustc_session::{parse::ParseSess, Limit, Session};
|
||||
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
|
||||
use rustc_span::edition::Edition;
|
||||
@ -109,17 +109,20 @@ pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_nonterminal(self) -> Nonterminal {
|
||||
pub fn to_tokens(&self, sess: &ParseSess) -> TokenStream {
|
||||
match self {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
|
||||
token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
|
||||
Annotatable::Item(node) => to_token_stream(node, sess, CanSynthesizeMissingTokens::No),
|
||||
Annotatable::TraitItem(node) | Annotatable::ImplItem(node) => {
|
||||
to_token_stream(node, sess, CanSynthesizeMissingTokens::No)
|
||||
}
|
||||
Annotatable::ForeignItem(item) => {
|
||||
token::NtItem(P(item.and_then(ast::ForeignItem::into_item)))
|
||||
Annotatable::ForeignItem(node) => {
|
||||
to_token_stream(node, sess, CanSynthesizeMissingTokens::No)
|
||||
}
|
||||
Annotatable::Stmt(stmt) => token::NtStmt(stmt),
|
||||
Annotatable::Expr(expr) => token::NtExpr(expr),
|
||||
Annotatable::Stmt(node) => {
|
||||
assert!(!matches!(node.kind, ast::StmtKind::Empty));
|
||||
to_token_stream(node, sess, CanSynthesizeMissingTokens::No)
|
||||
}
|
||||
Annotatable::Expr(node) => to_token_stream(node, sess, CanSynthesizeMissingTokens::No),
|
||||
Annotatable::Arm(..)
|
||||
| Annotatable::ExprField(..)
|
||||
| Annotatable::PatField(..)
|
||||
@ -131,10 +134,6 @@ pub fn into_nonterminal(self) -> Nonterminal {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn into_tokens(self, sess: &ParseSess) -> TokenStream {
|
||||
nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No)
|
||||
}
|
||||
|
||||
pub fn expect_item(self) -> P<ast::Item> {
|
||||
match self {
|
||||
Annotatable::Item(i) => i,
|
||||
@ -1380,16 +1379,7 @@ pub fn parse_macro_name_and_helper_attrs(
|
||||
/// asserts in old versions of those crates and their wide use in the ecosystem.
|
||||
/// See issue #73345 for more details.
|
||||
/// FIXME(#73933): Remove this eventually.
|
||||
pub(crate) fn pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool {
|
||||
let item = match nt {
|
||||
Nonterminal::NtItem(item) => item,
|
||||
Nonterminal::NtStmt(stmt) => match &stmt.kind {
|
||||
ast::StmtKind::Item(item) => item,
|
||||
_ => return false,
|
||||
},
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
|
||||
let name = item.ident.name;
|
||||
if name == sym::ProceduralMasqueradeDummyType {
|
||||
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
|
||||
@ -1411,3 +1401,27 @@ pub(crate) fn pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseS
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &ParseSess) -> bool {
|
||||
let item = match ann {
|
||||
Annotatable::Item(item) => item,
|
||||
Annotatable::Stmt(stmt) => match &stmt.kind {
|
||||
ast::StmtKind::Item(item) => item,
|
||||
_ => return false,
|
||||
},
|
||||
_ => return false,
|
||||
};
|
||||
pretty_printing_compatibility_hack(item, sess)
|
||||
}
|
||||
|
||||
pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool {
|
||||
let item = match nt {
|
||||
Nonterminal::NtItem(item) => item,
|
||||
Nonterminal::NtStmt(stmt) => match &stmt.kind {
|
||||
ast::StmtKind::Item(item) => item,
|
||||
_ => return false,
|
||||
},
|
||||
_ => return false,
|
||||
};
|
||||
pretty_printing_compatibility_hack(item, sess)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{LazyTokenStream, TokenTree};
|
||||
use rustc_ast::NodeId;
|
||||
use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem};
|
||||
use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
@ -246,7 +246,7 @@ macro_rules! configure {
|
||||
}
|
||||
|
||||
impl<'a> StripUnconfigured<'a> {
|
||||
pub fn configure<T: AstLike>(&self, mut node: T) -> Option<T> {
|
||||
pub fn configure<T: HasAttrs + HasTokens>(&self, mut node: T) -> Option<T> {
|
||||
self.process_cfg_attrs(&mut node);
|
||||
if self.in_cfg(node.attrs()) {
|
||||
self.try_configure_tokens(&mut node);
|
||||
@ -256,7 +256,7 @@ pub fn configure<T: AstLike>(&self, mut node: T) -> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_configure_tokens<T: AstLike>(&self, node: &mut T) {
|
||||
fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
|
||||
if self.config_tokens {
|
||||
if let Some(Some(tokens)) = node.tokens_mut() {
|
||||
let attr_annotated_tokens = tokens.create_token_stream();
|
||||
@ -330,7 +330,7 @@ fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool {
|
||||
/// 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>(&self, node: &mut T) {
|
||||
fn process_cfg_attrs<T: HasAttrs>(&self, node: &mut T) {
|
||||
node.visit_attrs(|attrs| {
|
||||
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
|
||||
});
|
||||
|
@ -11,7 +11,8 @@
|
||||
use rustc_ast::token::{self, Delimiter};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor};
|
||||
use rustc_ast::{AssocItemKind, AstLike, AstLikeWrapper, AttrStyle, ExprKind, ForeignItemKind};
|
||||
use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, ExprKind, ForeignItemKind};
|
||||
use rustc_ast::{HasAttrs, HasNodeId};
|
||||
use rustc_ast::{Inline, ItemKind, MacArgs, MacStmtStyle, MetaItemKind, ModKind};
|
||||
use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
@ -678,12 +679,9 @@ fn expand_invoc(
|
||||
)
|
||||
) =>
|
||||
{
|
||||
rustc_parse::fake_token_stream(
|
||||
&self.cx.sess.parse_sess,
|
||||
&item.into_nonterminal(),
|
||||
)
|
||||
rustc_parse::fake_token_stream(&self.cx.sess.parse_sess, item_inner)
|
||||
}
|
||||
_ => item.into_tokens(&self.cx.sess.parse_sess),
|
||||
_ => item.to_tokens(&self.cx.sess.parse_sess),
|
||||
};
|
||||
let attr_item = attr.unwrap_normal_item();
|
||||
if let MacArgs::Eq(..) = attr_item.args {
|
||||
@ -998,13 +996,12 @@ enum AddSemicolon {
|
||||
|
||||
/// A trait implemented for all `AstFragment` nodes and providing all pieces
|
||||
/// of functionality used by `InvocationCollector`.
|
||||
trait InvocationCollectorNode: AstLike {
|
||||
trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
|
||||
type OutputTy = SmallVec<[Self; 1]>;
|
||||
type AttrsTy: Deref<Target = [ast::Attribute]> = Vec<ast::Attribute>;
|
||||
const KIND: AstFragmentKind;
|
||||
fn to_annotatable(self) -> Annotatable;
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
|
||||
fn id(&mut self) -> &mut NodeId;
|
||||
fn descr() -> &'static str {
|
||||
unreachable!()
|
||||
}
|
||||
@ -1040,9 +1037,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_items()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_item(self, visitor)
|
||||
}
|
||||
@ -1142,7 +1136,7 @@ fn wrap_flat_map_node_noop_flat_map(
|
||||
}
|
||||
|
||||
struct TraitItemTag;
|
||||
impl InvocationCollectorNode for AstLikeWrapper<P<ast::AssocItem>, TraitItemTag> {
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> {
|
||||
type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
@ -1151,9 +1145,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_trait_items()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.wrapped.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_assoc_item(self.wrapped, visitor)
|
||||
}
|
||||
@ -1170,7 +1161,7 @@ fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
|
||||
}
|
||||
|
||||
struct ImplItemTag;
|
||||
impl InvocationCollectorNode for AstLikeWrapper<P<ast::AssocItem>, ImplItemTag> {
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> {
|
||||
type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
@ -1179,9 +1170,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_impl_items()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.wrapped.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_assoc_item(self.wrapped, visitor)
|
||||
}
|
||||
@ -1205,9 +1193,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_foreign_items()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_foreign_item(self, visitor)
|
||||
}
|
||||
@ -1231,9 +1216,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_variants()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_variant(self, visitor)
|
||||
}
|
||||
@ -1247,9 +1229,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_field_defs()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_field_def(self, visitor)
|
||||
}
|
||||
@ -1263,9 +1242,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_pat_fields()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_pat_field(self, visitor)
|
||||
}
|
||||
@ -1279,9 +1255,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_expr_fields()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_expr_field(self, visitor)
|
||||
}
|
||||
@ -1295,9 +1268,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_params()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_param(self, visitor)
|
||||
}
|
||||
@ -1311,9 +1281,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_generic_params()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_generic_param(self, visitor)
|
||||
}
|
||||
@ -1327,9 +1294,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_arms()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_arm(self, visitor)
|
||||
}
|
||||
@ -1344,9 +1308,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_stmts()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_flat_map_stmt(self, visitor)
|
||||
}
|
||||
@ -1403,9 +1364,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_crate()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
noop_visit_crate(self, visitor)
|
||||
}
|
||||
@ -1420,9 +1378,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_ty()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
noop_visit_ty(self, visitor)
|
||||
}
|
||||
@ -1447,9 +1402,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_pat()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
noop_visit_pat(self, visitor)
|
||||
}
|
||||
@ -1475,9 +1427,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_expr()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.id
|
||||
}
|
||||
fn descr() -> &'static str {
|
||||
"an expression"
|
||||
}
|
||||
@ -1497,7 +1446,7 @@ fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
|
||||
}
|
||||
|
||||
struct OptExprTag;
|
||||
impl InvocationCollectorNode for AstLikeWrapper<P<ast::Expr>, OptExprTag> {
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
|
||||
type OutputTy = Option<P<ast::Expr>>;
|
||||
type AttrsTy = ast::AttrVec;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::OptExpr;
|
||||
@ -1507,9 +1456,6 @@ fn to_annotatable(self) -> Annotatable {
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_opt_expr()
|
||||
}
|
||||
fn id(&mut self) -> &mut NodeId {
|
||||
&mut self.wrapped.id
|
||||
}
|
||||
fn noop_flat_map<V: MutVisitor>(mut self, visitor: &mut V) -> Self::OutputTy {
|
||||
noop_visit_expr(&mut self.wrapped, visitor);
|
||||
Some(self.wrapped)
|
||||
@ -1584,7 +1530,7 @@ fn collect_attr(
|
||||
/// legacy derive helpers (helpers written before derives that introduce them).
|
||||
fn take_first_attr(
|
||||
&self,
|
||||
item: &mut impl AstLike,
|
||||
item: &mut impl HasAttrs,
|
||||
) -> Option<(ast::Attribute, usize, Vec<ast::Path>)> {
|
||||
let mut attr = None;
|
||||
|
||||
@ -1680,7 +1626,7 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
|
||||
|
||||
fn expand_cfg_true(
|
||||
&mut self,
|
||||
node: &mut impl AstLike,
|
||||
node: &mut impl HasAttrs,
|
||||
attr: ast::Attribute,
|
||||
pos: usize,
|
||||
) -> bool {
|
||||
@ -1695,7 +1641,7 @@ fn expand_cfg_true(
|
||||
res
|
||||
}
|
||||
|
||||
fn expand_cfg_attr(&self, node: &mut impl AstLike, attr: ast::Attribute, pos: usize) {
|
||||
fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) {
|
||||
node.visit_attrs(|attrs| {
|
||||
attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
|
||||
});
|
||||
@ -1733,7 +1679,7 @@ fn flat_map_node<Node: InvocationCollectorNode<OutputTy: Default>>(
|
||||
}
|
||||
None => {
|
||||
match Node::wrap_flat_map_node_noop_flat_map(node, self, |mut node, this| {
|
||||
assign_id!(this, node.id(), || node.noop_flat_map(this))
|
||||
assign_id!(this, node.node_id_mut(), || node.noop_flat_map(this))
|
||||
}) {
|
||||
Ok(output) => output,
|
||||
Err(returned_node) => {
|
||||
@ -1781,7 +1727,7 @@ fn visit_node<Node: InvocationCollectorNode<OutputTy = Node> + DummyAstNode>(
|
||||
})
|
||||
}
|
||||
None => {
|
||||
assign_id!(self, node.id(), || node.noop_visit(self))
|
||||
assign_id!(self, node.node_id_mut(), || node.noop_visit(self))
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1794,11 +1740,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, node: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
self.flat_map_node(AstLikeWrapper::new(node, TraitItemTag))
|
||||
self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag))
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, node: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
self.flat_map_node(AstLikeWrapper::new(node, ImplItemTag))
|
||||
self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
|
||||
}
|
||||
|
||||
fn flat_map_foreign_item(
|
||||
@ -1889,7 +1835,7 @@ fn visit_expr(&mut self, node: &mut P<ast::Expr>) {
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
self.flat_map_node(AstLikeWrapper::new(node, OptExprTag))
|
||||
self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, node: &mut P<ast::Block>) {
|
||||
|
@ -4,10 +4,9 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_parse::nt_to_tokenstream;
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_span::profiling::SpannedEventArgRecorder;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
@ -87,25 +86,17 @@ fn expand(
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
// We need special handling for statement items
|
||||
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
|
||||
let mut is_stmt = false;
|
||||
let item = match item {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
Annotatable::Stmt(stmt) => {
|
||||
is_stmt = true;
|
||||
assert!(stmt.is_item());
|
||||
|
||||
// A proc macro can't observe the fact that we're passing
|
||||
// them an `NtStmt` - it can only see the underlying tokens
|
||||
// of the wrapped item
|
||||
token::NtStmt(stmt)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let input = if crate::base::pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess)
|
||||
{
|
||||
TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
|
||||
let is_stmt = matches!(item, Annotatable::Stmt(..));
|
||||
let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess);
|
||||
let input = if hack {
|
||||
let nt = match item {
|
||||
Annotatable::Item(item) => token::NtItem(item),
|
||||
Annotatable::Stmt(stmt) => token::NtStmt(stmt),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into()
|
||||
} else {
|
||||
nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
|
||||
item.to_tokens(&ecx.sess.parse_sess)
|
||||
};
|
||||
|
||||
let stream = {
|
||||
|
@ -184,7 +184,7 @@ macro_rules! op {
|
||||
delimiter: pm::Delimiter::None,
|
||||
stream,
|
||||
span: DelimSpan::from_single(span),
|
||||
flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess()),
|
||||
flatten: crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.sess()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,7 @@
|
||||
use crate::passes::{EarlyLintPass, EarlyLintPassObject};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{self as ast_visit, Visitor};
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_ast::{self as ast, walk_list};
|
||||
use rustc_ast::{self as ast, walk_list, HasAttrs};
|
||||
use rustc_middle::ty::RegisteredTools;
|
||||
use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
|
||||
use rustc_session::Session;
|
||||
|
@ -17,17 +17,17 @@
|
||||
use rustc_ast::tokenstream::{self, AttributesData, CanSynthesizeMissingTokens, LazyTokenStream};
|
||||
use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
|
||||
use rustc_ast::tokenstream::{Spacing, TokenStream};
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_ast::{AttrItem, MetaItem};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_ast::{HasAttrs, HasSpan, HasTokens};
|
||||
use rustc_ast_pretty::pprust::{self, AstPrettyPrint};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{FileName, SourceFile, Span};
|
||||
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
||||
pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments");
|
||||
|
||||
@ -244,6 +244,20 @@ pub fn parse_in<'a, T>(
|
||||
// NOTE(Centril): The following probably shouldn't be here but it acknowledges the
|
||||
// fact that architecturally, we are using parsing (read on below to understand why).
|
||||
|
||||
pub fn to_token_stream(
|
||||
node: &(impl HasAttrs + HasSpan + HasTokens + AstPrettyPrint + fmt::Debug),
|
||||
sess: &ParseSess,
|
||||
synthesize_tokens: CanSynthesizeMissingTokens,
|
||||
) -> TokenStream {
|
||||
if let Some(tokens) = prepend_attrs(&node.attrs(), node.tokens()) {
|
||||
return tokens;
|
||||
} else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) {
|
||||
return fake_token_stream(sess, node);
|
||||
} else {
|
||||
panic!("Missing tokens for nt {:?} at {:?}: {:?}", node, node.span(), node.pretty_print());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nt_to_tokenstream(
|
||||
nt: &Nonterminal,
|
||||
sess: &ParseSess,
|
||||
@ -298,7 +312,7 @@ pub fn nt_to_tokenstream(
|
||||
if let Some(tokens) = tokens {
|
||||
return tokens;
|
||||
} else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) {
|
||||
return fake_token_stream(sess, nt);
|
||||
return nt_fake_token_stream(sess, nt);
|
||||
} else {
|
||||
panic!(
|
||||
"Missing tokens for nt {:?} at {:?}: {:?}",
|
||||
@ -322,7 +336,13 @@ fn prepend_attrs(attrs: &[Attribute], tokens: Option<&LazyTokenStream>) -> Optio
|
||||
Some(wrapped.to_tokenstream())
|
||||
}
|
||||
|
||||
pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
|
||||
pub fn fake_token_stream(sess: &ParseSess, node: &(impl AstPrettyPrint + HasSpan)) -> TokenStream {
|
||||
let source = node.pretty_print();
|
||||
let filename = FileName::macro_expansion_source_code(&source);
|
||||
parse_stream_from_source_str(filename, source, sess, Some(node.span()))
|
||||
}
|
||||
|
||||
fn nt_fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
|
||||
let source = pprust::nonterminal_to_string(nt);
|
||||
let filename = FileName::macro_expansion_source_code(&source);
|
||||
parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttributesData, CreateTokenStream};
|
||||
use rustc_ast::tokenstream::{AttrAnnotatedTokenTree, DelimSpan, LazyTokenStream, Spacing};
|
||||
use rustc_ast::{self as ast};
|
||||
use rustc_ast::{AstLike, AttrVec, Attribute};
|
||||
use rustc_ast::{AttrVec, Attribute, HasAttrs, HasTokens};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
@ -192,7 +192,7 @@ impl<'a> Parser<'a> {
|
||||
/// This restriction shouldn't be an issue in practice,
|
||||
/// since this function is used to record the tokens for
|
||||
/// a parsed AST item, which always has matching delimiters.
|
||||
pub fn collect_tokens_trailing_token<R: AstLike>(
|
||||
pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
|
||||
&mut self,
|
||||
attrs: AttrWrapper,
|
||||
force_collect: ForceCollect,
|
||||
|
@ -25,9 +25,9 @@
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_ast::AttrId;
|
||||
use rustc_ast::DUMMY_NODE_ID;
|
||||
use rustc_ast::{self as ast, AnonConst, AstLike, AttrStyle, AttrVec, Const, CrateSugar, Extern};
|
||||
use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, CrateSugar, Extern};
|
||||
use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacArgsEq, MacDelimiter, Mutability, StrLit};
|
||||
use rustc_ast::{Unsafe, Visibility, VisibilityKind};
|
||||
use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::PResult;
|
||||
@ -1389,7 +1389,7 @@ fn parse_abi(&mut self) -> Option<StrLit> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_tokens_no_attrs<R: AstLike>(
|
||||
pub fn collect_tokens_no_attrs<R: HasAttrs + HasTokens>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut Self) -> PResult<'a, R>,
|
||||
) -> PResult<'a, R> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_ast::HasTokens;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
|
@ -13,10 +13,8 @@
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, TokenKind};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::{
|
||||
AstLike, AttrStyle, AttrVec, Attribute, LocalKind, MacCall, MacCallStmt, MacStmtStyle,
|
||||
};
|
||||
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt};
|
||||
use rustc_ast::{AttrStyle, AttrVec, Attribute, LocalKind, MacCall, MacCallStmt, MacStmtStyle};
|
||||
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Stmt};
|
||||
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
||||
use rustc_span::source_map::{BytePos, Span};
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Format attributes and meta items.
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_ast::HasAttrs;
|
||||
use rustc_span::{symbol::sym, Span, Symbol};
|
||||
|
||||
use self::doc_comment::DocCommentFormatter;
|
||||
|
@ -5,7 +5,6 @@
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_span::Span;
|
||||
|
||||
use self::newline_style::apply_newline_style;
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_span::symbol::{self, sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
use thiserror::Error;
|
||||
@ -50,19 +49,10 @@ pub(crate) fn new(
|
||||
ast_mod_kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AstLike for Module<'a> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true;
|
||||
fn attrs(&self) -> &[ast::Attribute] {
|
||||
pub(crate) fn attrs(&self) -> &[ast::Attribute] {
|
||||
&self.inner_attr
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<ast::Attribute>)) {
|
||||
f(&mut self.inner_attr)
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<rustc_ast::tokenstream::LazyTokenStream>> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps each module to the corresponding file.
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
use rustc_ast::{ast, token::Delimiter, visit, AstLike};
|
||||
use rustc_ast::{ast, token::Delimiter, visit};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::{symbol, BytePos, Pos, Span};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user