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

Split AttrArgs from MacArgs. #96209

Closed
wants to merge 1 commit into from
Closed
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
100 changes: 57 additions & 43 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters.
//! - [`EnumDef`] and [`Variant`]: Enum declaration.
//! - [`Lit`] and [`LitKind`]: Literal expressions.
//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimiter`]: Macro definition and invocation.
//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`AttrMacDelimiter`]: Macro definition and invocation.
//! - [`Attribute`]: Metadata associated with item.
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.

Expand Down Expand Up @@ -1521,80 +1521,58 @@ pub struct MacCall {

impl MacCall {
pub fn span(&self) -> Span {
self.path.span.to(self.args.span().unwrap_or(self.path.span))
self.path.span.to(self.args.span())
}
}

/// Arguments passed to an attribute or a function-like macro.
/// Arguments passed to a function-like macro.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacArgs {
/// No arguments - `#[attr]`.
Empty,
/// Delimited arguments - `#[attr()/[]/{}]` or `mac!()/[]/{}`.
Delimited(DelimSpan, MacDelimiter, TokenStream),
/// Arguments of a key-value attribute - `#[attr = "value"]`.
Eq(
/// Span of the `=` token.
Span,
/// "value" as a nonterminal token.
Token,
),
}
pub struct MacArgs(pub DelimSpan, pub AttrMacDelimiter, pub TokenStream);

impl MacArgs {
pub fn delim(&self) -> DelimToken {
match self {
MacArgs::Delimited(_, delim, _) => delim.to_token(),
MacArgs::Empty | MacArgs::Eq(..) => token::NoDelim,
}
pub fn span(&self) -> Span {
self.0.entire()
}

pub fn span(&self) -> Option<Span> {
match self {
MacArgs::Empty => None,
MacArgs::Delimited(dspan, ..) => Some(dspan.entire()),
MacArgs::Eq(eq_span, token) => Some(eq_span.to(token.span)),
}
pub fn delim(&self) -> DelimToken {
self.1.to_token()
}

/// Tokens inside the delimiters or after `=`.
/// Proc macros see these tokens, for example.
pub fn inner_tokens(&self) -> TokenStream {
match self {
MacArgs::Empty => TokenStream::default(),
MacArgs::Delimited(.., tokens) => tokens.clone(),
MacArgs::Eq(.., token) => TokenTree::Token(token.clone()).into(),
}
self.2.clone()
}

/// Whether a macro with these arguments needs a semicolon
/// when used as a standalone item or statement.
pub fn need_semicolon(&self) -> bool {
!matches!(self, MacArgs::Delimited(_, MacDelimiter::Brace, _))
!matches!(self, MacArgs(_, AttrMacDelimiter::Brace, _))
}
}

// This is used in both attributes and macro calls, hence the name.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacDelimiter {
pub enum AttrMacDelimiter {
Parenthesis,
Bracket,
Brace,
}

impl MacDelimiter {
impl AttrMacDelimiter {
pub fn to_token(self) -> DelimToken {
match self {
MacDelimiter::Parenthesis => DelimToken::Paren,
MacDelimiter::Bracket => DelimToken::Bracket,
MacDelimiter::Brace => DelimToken::Brace,
AttrMacDelimiter::Parenthesis => DelimToken::Paren,
AttrMacDelimiter::Bracket => DelimToken::Bracket,
AttrMacDelimiter::Brace => DelimToken::Brace,
}
}

pub fn from_token(delim: DelimToken) -> Option<MacDelimiter> {
pub fn from_token(delim: DelimToken) -> Option<AttrMacDelimiter> {
match delim {
token::Paren => Some(MacDelimiter::Parenthesis),
token::Bracket => Some(MacDelimiter::Bracket),
token::Brace => Some(MacDelimiter::Brace),
token::Paren => Some(AttrMacDelimiter::Parenthesis),
token::Bracket => Some(AttrMacDelimiter::Bracket),
token::Brace => Some(AttrMacDelimiter::Brace),
token::NoDelim => None,
}
}
Expand Down Expand Up @@ -2454,10 +2432,46 @@ impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AttrItem {
pub path: Path,
pub args: MacArgs,
pub args: AttrArgs,
pub tokens: Option<LazyTokenStream>,
}

/// Arguments passed to an attribute.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum AttrArgs {
/// No arguments - `#[attr]`.
Empty,
/// Delimited arguments - `#[attr()/[]/{}]`.
Delimited(DelimSpan, AttrMacDelimiter, TokenStream),
/// Arguments of a key-value attribute - `#[attr = "value"]`.
Eq(
/// Span of the `=` token.
Span,
/// "value" as a nonterminal token.
Token,
),
}

impl AttrArgs {
pub fn span(&self) -> Option<Span> {
match self {
AttrArgs::Empty => None,
AttrArgs::Delimited(dspan, ..) => Some(dspan.entire()),
AttrArgs::Eq(eq_span, token) => Some(eq_span.to(token.span)),
}
}

/// Tokens inside the delimiters or after `=`.
/// Proc macros see these tokens, for example.
pub fn inner_tokens(&self) -> TokenStream {
match self {
AttrArgs::Empty => TokenStream::default(),
AttrArgs::Delimited(.., tokens) => tokens.clone(),
AttrArgs::Eq(.., token) => TokenTree::Token(token.clone()).into(),
}
}
}

/// A list of attributes.
pub type AttrVec = ThinVec<Attribute>;

Expand Down
36 changes: 18 additions & 18 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! Functions dealing with attributes and meta items.

use crate::ast;
use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
use crate::ast::{AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
use crate::ast::{AttrMacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
use crate::ast::{Lit, LitKind};
use crate::ast::{MacArgs, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
use crate::ast::{Path, PathSegment};
use crate::token::{self, CommentKind, Token};
use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
Expand Down Expand Up @@ -152,7 +152,7 @@ impl Attribute {

pub fn is_word(&self) -> bool {
if let AttrKind::Normal(item, _) = &self.kind {
matches!(item.args, MacArgs::Empty)
matches!(item.args, AttrArgs::Empty)
} else {
false
}
Expand Down Expand Up @@ -223,13 +223,13 @@ impl AttrItem {
pub fn meta(&self, span: Span) -> Option<MetaItem> {
Some(MetaItem {
path: self.path.clone(),
kind: MetaItemKind::from_mac_args(&self.args)?,
kind: MetaItemKind::from_attr_args(&self.args)?,
span,
})
}

pub fn meta_kind(&self) -> Option<MetaItemKind> {
MetaItemKind::from_mac_args(&self.args)
MetaItemKind::from_attr_args(&self.args)
}
}

Expand Down Expand Up @@ -344,7 +344,7 @@ crate fn mk_attr_id() -> AttrId {
AttrId::from_u32(id)
}

pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
pub fn mk_attr(style: AttrStyle, path: Path, args: AttrArgs, span: Span) -> Attribute {
mk_attr_from_item(AttrItem { path, args, tokens: None }, None, style, span)
}

Expand All @@ -359,12 +359,12 @@ pub fn mk_attr_from_item(

/// Returns an inner attribute with the given value and span.
pub fn mk_attr_inner(item: MetaItem) -> Attribute {
mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span)
mk_attr(AttrStyle::Inner, item.path, item.kind.attr_args(item.span), item.span)
}

/// Returns an outer attribute with the given value and span.
pub fn mk_attr_outer(item: MetaItem) -> Attribute {
mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span)
mk_attr(AttrStyle::Outer, item.path, item.kind.attr_args(item.span), item.span)
}

pub fn mk_doc_comment(
Expand Down Expand Up @@ -467,10 +467,10 @@ impl MetaItemKind {
}
}

pub fn mac_args(&self, span: Span) -> MacArgs {
pub fn attr_args(&self, span: Span) -> AttrArgs {
match self {
MetaItemKind::Word => MacArgs::Empty,
MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.to_token()),
MetaItemKind::Word => AttrArgs::Empty,
MetaItemKind::NameValue(lit) => AttrArgs::Eq(span, lit.to_token()),
MetaItemKind::List(list) => {
let mut tts = Vec::new();
for (i, item) in list.iter().enumerate() {
Expand All @@ -479,9 +479,9 @@ impl MetaItemKind {
}
tts.extend(item.token_trees_and_spacings())
}
MacArgs::Delimited(
AttrArgs::Delimited(
DelimSpan::from_single(span),
MacDelimiter::Parenthesis,
AttrMacDelimiter::Parenthesis,
TokenStream::new(tts),
)
}
Expand Down Expand Up @@ -545,14 +545,14 @@ impl MetaItemKind {
}
}

fn from_mac_args(args: &MacArgs) -> Option<MetaItemKind> {
fn from_attr_args(args: &AttrArgs) -> Option<MetaItemKind> {
match args {
MacArgs::Delimited(_, MacDelimiter::Parenthesis, tokens) => {
AttrArgs::Delimited(_, AttrMacDelimiter::Parenthesis, tokens) => {
MetaItemKind::list_from_tokens(tokens.clone())
}
MacArgs::Delimited(..) => None,
MacArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
MacArgs::Empty => Some(MetaItemKind::Word),
AttrArgs::Delimited(..) => None,
AttrArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
AttrArgs::Empty => Some(MetaItemKind::Word),
}
}

Expand Down
19 changes: 13 additions & 6 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,14 @@ pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl, span }: &mut FnSig, vis
}

// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
pub fn visit_attr_args<T: MutVisitor>(args: &mut AttrArgs, vis: &mut T) {
match args {
MacArgs::Empty => {}
MacArgs::Delimited(dspan, _delim, tokens) => {
AttrArgs::Empty => {}
AttrArgs::Delimited(dspan, _delim, tokens) => {
visit_delim_span(dspan, vis);
visit_tts(tokens, vis);
}
MacArgs::Eq(eq_span, token) => {
AttrArgs::Eq(eq_span, token) => {
vis.visit_span(eq_span);
if T::VISIT_TOKENS {
visit_token(token, vis);
Expand All @@ -389,6 +389,13 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
}
}

// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
let MacArgs(dspan, _delim, tokens) = args;
visit_delim_span(dspan, vis);
visit_tts(tokens, vis);
}

pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) {
vis.visit_span(&mut dspan.open);
vis.visit_span(&mut dspan.close);
Expand Down Expand Up @@ -602,7 +609,7 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
match kind {
AttrKind::Normal(AttrItem { path, args, tokens }, attr_tokens) => {
vis.visit_path(path);
visit_mac_args(args, vis);
visit_attr_args(args, vis);
visit_lazy_tts(tokens, vis);
visit_lazy_tts(attr_tokens, vis);
}
Expand Down Expand Up @@ -793,7 +800,7 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
token::NtMeta(item) => {
let AttrItem { path, args, tokens } = item.deref_mut();
vis.visit_path(path);
visit_mac_args(args, vis);
visit_attr_args(args, vis);
visit_lazy_tts(tokens, vis);
}
token::NtPath(path) => vis.visit_path(path),
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,18 +906,18 @@ pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {

pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
match attr.kind {
AttrKind::Normal(ref item, ref _tokens) => walk_mac_args(visitor, &item.args),
AttrKind::Normal(ref item, ref _tokens) => walk_attr_args(visitor, &item.args),
AttrKind::DocComment(..) => {}
}
}

pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) {
match args {
MacArgs::Empty => {}
MacArgs::Delimited(_dspan, _delim, _tokens) => {}
AttrArgs::Empty => {}
AttrArgs::Delimited(_dspan, _delim, _tokens) => {}
// The value in `#[key = VALUE]` must be visited as an expression for backward
// compatibility, so that macros can be expanded in that position.
MacArgs::Eq(_eq_span, token) => match &token.kind {
AttrArgs::Eq(_eq_span, token) => match &token.kind {
token::Interpolated(nt) => match &**nt {
token::NtExpr(expr) => visitor.visit_expr(expr),
t => panic!("unexpected token in key-value attribute: {:?}", t),
Expand Down
Loading