Skip to content

Commit

Permalink
Avoid more MetaItem-to-Attribute conversions.
Browse files Browse the repository at this point in the history
There is code for converting `Attribute` (syntactic) to `MetaItem`
(semantic). There is also code for the reverse direction. The reverse
direction isn't really necessary; it's currently only used when
generating attributes, e.g. in `derive` code.

This commit adds some new functions for creating `Attributes`s directly,
without involving `MetaItem`s: `mk_attr_word`, `mk_attr_name_value_str`,
`mk_attr_nested_word`, and
`ExtCtxt::attr_{word,name_value_str,nested_word}`.

These new methods replace the old functions for creating `Attribute`s:
`mk_attr_inner`, `mk_attr_outer`, and `ExtCtxt::attribute`. Those
functions took `MetaItem`s as input, and relied on many other functions
that created `MetaItems`, which are also removed: `mk_name_value_item`,
`mk_list_item`, `mk_word_item`, `mk_nested_word_item`,
`{MetaItem,MetaItemKind,NestedMetaItem}::token_trees`,
`MetaItemKind::attr_args`, `MetaItemLit::{from_lit_kind,to_token}`,
`ExtCtxt::meta_word`.

Overall this cuts more than 100 lines of code and makes thing simpler.
  • Loading branch information
nnethercote committed Nov 29, 2022
1 parent d1b61a3 commit ba1751a
Show file tree
Hide file tree
Showing 20 changed files with 116 additions and 211 deletions.
167 changes: 52 additions & 115 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
//! Functions dealing with attributes and meta items.
use crate::ast;
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, Attribute};
use crate::ast::{DelimArgs, LitKind, MetaItemLit};
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem};
use crate::ast::{Path, PathSegment};
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID};
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter, Token};
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
use crate::util::comments;
use rustc_data_structures::sync::WorkerLocal;
use rustc_index::bit_set::GrowableBitSet;
use rustc_span::source_map::BytePos;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use std::cell::Cell;
Expand Down Expand Up @@ -223,11 +222,7 @@ impl AttrItem {
}

pub fn meta(&self, span: Span) -> Option<MetaItem> {
Some(MetaItem {
path: self.path.clone(),
kind: MetaItemKind::from_attr_args(&self.args)?,
span,
})
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
}

pub fn meta_kind(&self) -> Option<MetaItemKind> {
Expand Down Expand Up @@ -329,26 +324,13 @@ impl Attribute {
/* Constructors */

pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked);
mk_name_value_item(ident, lit_kind, str_span)
mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span)
}

pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span };
let span = ident.span.to(lit_span);
MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) }
}

pub fn mk_list_item(ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) }
}

pub fn mk_word_item(ident: Ident) -> MetaItem {
MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word }
}

pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
NestedMetaItem::MetaItem(mk_word_item(ident))
MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
}

pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
Expand Down Expand Up @@ -406,21 +388,58 @@ pub fn mk_attr_from_item(
span: Span,
) -> Attribute {
Attribute {
kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })),
kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
id: g.mk_attr_id(),
style,
span,
}
}

/// Returns an inner attribute with the given value and span.
pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
mk_attr(g, AttrStyle::Inner, item.path, item.kind.attr_args(item.span), item.span)
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
let path = Path::from_ident(Ident::new(name, span));
let args = AttrArgs::Empty;
mk_attr(g, style, path, args, span)
}

pub fn mk_attr_name_value_str(
g: &AttrIdGenerator,
style: AttrStyle,
name: Symbol,
val: Symbol,
span: Span,
) -> Attribute {
let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit();
let expr = P(Expr {
id: DUMMY_NODE_ID,
kind: ExprKind::Lit(lit),
span,
attrs: AttrVec::new(),
tokens: None,
});
let path = Path::from_ident(Ident::new(name, span));
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
mk_attr(g, style, path, args, span)
}

/// Returns an outer attribute with the given value and span.
pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute {
mk_attr(g, AttrStyle::Outer, item.path, item.kind.attr_args(item.span), item.span)
pub fn mk_attr_nested_word(
g: &AttrIdGenerator,
style: AttrStyle,
outer: Symbol,
inner: Symbol,
span: Span,
) -> Attribute {
let inner_tokens = TokenStream::new(vec![TokenTree::Token(
Token::from_ast_ident(Ident::new(inner, span)),
Spacing::Alone,
)]);
let outer_ident = Ident::new(outer, span);
let path = Path::from_ident(outer_ident);
let attr_args = AttrArgs::Delimited(DelimArgs {
dspan: DelimSpan::from_single(span),
delim: MacDelimiter::Parenthesis,
tokens: inner_tokens,
});
mk_attr(g, style, path, attr_args, span)
}

pub fn mk_doc_comment(
Expand All @@ -438,23 +457,6 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
}

impl MetaItem {
fn token_trees(&self) -> Vec<TokenTree> {
let mut idents = vec![];
let mut last_pos = BytePos(0_u32);
for (i, segment) in self.path.segments.iter().enumerate() {
let is_first = i == 0;
if !is_first {
let mod_sep_span =
Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
idents.push(TokenTree::token_alone(token::ModSep, mod_sep_span));
}
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident), Spacing::Alone));
last_pos = segment.ident.span.hi();
}
idents.extend(self.kind.token_trees(self.span));
idents
}

fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
where
I: Iterator<Item = TokenTree>,
Expand Down Expand Up @@ -526,62 +528,6 @@ impl MetaItemKind {
}
}

pub fn attr_args(&self, span: Span) -> AttrArgs {
match self {
MetaItemKind::Word => AttrArgs::Empty,
MetaItemKind::NameValue(lit) => {
let expr = P(ast::Expr {
id: ast::DUMMY_NODE_ID,
kind: ast::ExprKind::Lit(lit.token_lit.clone()),
span: lit.span,
attrs: ast::AttrVec::new(),
tokens: None,
});
AttrArgs::Eq(span, AttrArgsEq::Ast(expr))
}
MetaItemKind::List(list) => {
let mut tts = Vec::new();
for (i, item) in list.iter().enumerate() {
if i > 0 {
tts.push(TokenTree::token_alone(token::Comma, span));
}
tts.extend(item.token_trees())
}
AttrArgs::Delimited(DelimArgs {
dspan: DelimSpan::from_single(span),
delim: MacDelimiter::Parenthesis,
tokens: TokenStream::new(tts),
})
}
}
}

fn token_trees(&self, span: Span) -> Vec<TokenTree> {
match self {
MetaItemKind::Word => vec![],
MetaItemKind::NameValue(lit) => {
vec![
TokenTree::token_alone(token::Eq, span),
TokenTree::Token(lit.to_token(), Spacing::Alone),
]
}
MetaItemKind::List(list) => {
let mut tokens = Vec::new();
for (i, item) in list.iter().enumerate() {
if i > 0 {
tokens.push(TokenTree::token_alone(token::Comma, span));
}
tokens.extend(item.token_trees())
}
vec![TokenTree::Delimited(
DelimSpan::from_single(span),
Delimiter::Parenthesis,
TokenStream::new(tokens),
)]
}
}
}

fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
let mut tokens = tokens.into_trees().peekable();
let mut result = Vec::new();
Expand Down Expand Up @@ -620,7 +566,7 @@ impl MetaItemKind {
}) => MetaItemKind::list_from_tokens(tokens.clone()),
AttrArgs::Delimited(..) => None,
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
ast::ExprKind::Lit(token_lit) => {
ExprKind::Lit(token_lit) => {
// Turn failures to `None`, we'll get parse errors elsewhere.
MetaItemLit::from_token_lit(token_lit, expr.span)
.ok()
Expand Down Expand Up @@ -659,15 +605,6 @@ impl NestedMetaItem {
}
}

fn token_trees(&self) -> Vec<TokenTree> {
match self {
NestedMetaItem::MetaItem(item) => item.token_trees(),
NestedMetaItem::Lit(lit) => {
vec![TokenTree::Token(lit.to_token(), Spacing::Alone)]
}
}
}

fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
where
I: Iterator<Item = TokenTree>,
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_ast/src/util/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,6 @@ impl MetaItemLit {
token::Lit::from_token(token)
.and_then(|token_lit| MetaItemLit::from_token_lit(token_lit, token.span).ok())
}

/// Losslessly convert a meta item literal into a token.
pub fn to_token(&self) -> Token {
let kind = match self.token_lit.kind {
token::Bool => token::Ident(self.token_lit.symbol, false),
_ => token::Literal(self.token_lit),
};
Token::new(kind, self.span)
}
}

fn strip_underscores(symbol: Symbol) -> Symbol {
Expand Down
17 changes: 7 additions & 10 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1606,16 +1606,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
};

// `#[allow(unreachable_code)]`
let attr = {
// `allow(unreachable_code)`
let allow = {
let allow_ident = Ident::new(sym::allow, self.lower_span(span));
let uc_ident = Ident::new(sym::unreachable_code, self.lower_span(span));
let uc_nested = attr::mk_nested_word_item(uc_ident);
attr::mk_list_item(allow_ident, vec![uc_nested])
};
attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow)
};
let attr = attr::mk_attr_nested_word(
&self.tcx.sess.parse_sess.attr_id_generator,
AttrStyle::Outer,
sym::allow,
sym::unreachable_code,
self.lower_span(span),
);
let attrs: AttrVec = thin_vec![attr];

// `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
Expand Down
19 changes: 11 additions & 8 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
use rustc_span::{BytePos, FileName, Span};
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};

use rustc_ast::attr::AttrIdGenerator;
use std::borrow::Cow;
Expand Down Expand Up @@ -119,17 +119,20 @@ pub fn print_crate<'a>(
// of the feature gate, so we fake them up here.

// `#![feature(prelude_import)]`
let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
let fake_attr = attr::mk_attr_inner(g, list);
let fake_attr = attr::mk_attr_nested_word(
g,
ast::AttrStyle::Inner,
sym::feature,
sym::prelude_import,
DUMMY_SP,
);
s.print_attribute(&fake_attr);

// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
// root, so this is not needed, and actually breaks things.
if edition == Edition::Edition2015 {
// `#![no_std]`
let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
let fake_attr = attr::mk_attr_inner(g, no_std_meta);
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
s.print_attribute(&fake_attr);
}
}
Expand Down Expand Up @@ -1712,9 +1715,9 @@ impl<'a> State<'a> {
where_clause: ast::WhereClause {
has_where_token: false,
predicates: Vec::new(),
span: rustc_span::DUMMY_SP,
span: DUMMY_SP,
},
span: rustc_span::DUMMY_SP,
span: DUMMY_SP,
};
let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
self.print_fn(decl, header, name, &generics);
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_builtin_macros/src/alloc_error_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
body,
}));

let special = sym::rustc_std_internal_symbol;
let special = cx.meta_word(span, special);
let attrs = thin_vec![cx.attribute(special)];
let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];

let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind);
cx.stmt_item(sig_span, item)
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_builtin_macros/src/assert/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use rustc_ast::{
attr,
ptr::P,
token,
tokenstream::{DelimSpan, TokenStream, TokenTree},
Expand Down Expand Up @@ -118,10 +117,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.cx.item(
self.span,
Ident::empty(),
thin_vec![self.cx.attribute(attr::mk_list_item(
Ident::new(sym::allow, self.span),
vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
))],
thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
ItemKind::Use(UseTree {
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
kind: UseTreeKind::Nested(vec![
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_builtin_macros/src/deriving/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ pub fn expand_deriving_clone(
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
}

let inline = cx.meta_word(span, sym::inline);
let attrs = thin_vec![cx.attribute(inline)];
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
let trait_def = TraitDef {
span,
path: path_std!(clone::Clone),
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::deriving::path_std;
use rustc_ast::{self as ast, MetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::symbol::sym;
use rustc_span::Span;
use thin_vec::thin_vec;

Expand All @@ -18,11 +18,11 @@ pub fn expand_deriving_eq(
is_const: bool,
) {
let span = cx.with_def_site_ctxt(span);
let inline = cx.meta_word(span, sym::inline);
let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
let no_coverage = cx.meta_word(span, sym::no_coverage);
let attrs = thin_vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
let attrs = thin_vec![
cx.attr_word(sym::inline, span),
cx.attr_nested_word(sym::doc, sym::hidden, span),
cx.attr_word(sym::no_coverage, span)
];
let trait_def = TraitDef {
span,
path: path_std!(cmp::Eq),
Expand Down
Loading

0 comments on commit ba1751a

Please sign in to comment.