Skip to content

Commit

Permalink
Auto merge of #107569 - petrochenkov:optattr, r=nnethercote
Browse files Browse the repository at this point in the history
ast: Optimize list and value extraction primitives for attributes

It's not necessary to convert the whole attribute into a meta item to extract something specific.
  • Loading branch information
bors committed Feb 3, 2023
2 parents 7c46fb2 + a9c8a5c commit a94b9fd
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 76 deletions.
7 changes: 7 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,13 @@ pub enum LitKind {
}

impl LitKind {
pub fn str(&self) -> Option<Symbol> {
match *self {
LitKind::Str(s, _) => Some(s),
_ => None,
}
}

/// Returns `true` if this literal is a string.
pub fn is_str(&self) -> bool {
matches!(self, LitKind::Str(..))
Expand Down
66 changes: 43 additions & 23 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,14 @@ impl Attribute {

pub fn value_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()),
AttrKind::Normal(normal) => normal.item.value_str(),
AttrKind::DocComment(..) => None,
}
}

pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
match &self.kind {
AttrKind::Normal(normal) => match normal.item.meta_kind() {
Some(MetaItemKind::List(list)) => Some(list),
_ => None,
},
AttrKind::Normal(normal) => normal.item.meta_item_list(),
AttrKind::DocComment(..) => None,
}
}
Expand Down Expand Up @@ -216,6 +213,20 @@ impl MetaItem {
}
}

impl AttrArgsEq {
fn value_str(&self) -> Option<Symbol> {
match self {
AttrArgsEq::Ast(expr) => match expr.kind {
ExprKind::Lit(token_lit) => {
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
}
_ => None,
},
AttrArgsEq::Hir(lit) => lit.kind.str(),
}
}
}

impl AttrItem {
pub fn span(&self) -> Span {
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
Expand All @@ -228,6 +239,22 @@ impl AttrItem {
pub fn meta_kind(&self) -> Option<MetaItemKind> {
MetaItemKind::from_attr_args(&self.args)
}

fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
match &self.args {
AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
MetaItemKind::list_from_tokens(args.tokens.clone())
}
AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
}
}

fn value_str(&self) -> Option<Symbol> {
match &self.args {
AttrArgs::Eq(_, args) => args.value_str(),
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
}
}
}

impl Attribute {
Expand All @@ -247,13 +274,11 @@ impl Attribute {
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
/// * `#[doc(...)]` returns `None`.
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
match self.kind {
AttrKind::DocComment(kind, data) => Some((data, kind)),
AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
.item
.meta_kind()
.and_then(|kind| kind.value_str())
.map(|data| (data, CommentKind::Line)),
match &self.kind {
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
normal.item.value_str().map(|s| (s, CommentKind::Line))
}
_ => None,
}
}
Expand All @@ -265,9 +290,7 @@ impl Attribute {
pub fn doc_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::DocComment(.., data) => Some(*data),
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
normal.item.meta_kind().and_then(|kind| kind.value_str())
}
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
_ => None,
}
}
Expand Down Expand Up @@ -508,15 +531,12 @@ impl MetaItem {
impl MetaItemKind {
pub fn value_str(&self) -> Option<Symbol> {
match self {
MetaItemKind::NameValue(v) => match v.kind {
LitKind::Str(s, _) => Some(s),
_ => None,
},
MetaItemKind::NameValue(v) => v.kind.str(),
_ => None,
}
}

fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
fn list_from_tokens(tokens: TokenStream) -> Option<Vec<NestedMetaItem>> {
let mut tokens = tokens.into_trees().peekable();
let mut result = Vec::new();
while tokens.peek().is_some() {
Expand All @@ -527,7 +547,7 @@ impl MetaItemKind {
_ => return None,
}
}
Some(MetaItemKind::List(result))
Some(result)
}

fn name_value_from_tokens(
Expand All @@ -551,7 +571,7 @@ impl MetaItemKind {
dspan: _,
delim: MacDelimiter::Parenthesis,
tokens,
}) => MetaItemKind::list_from_tokens(tokens.clone()),
}) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List),
AttrArgs::Delimited(..) => None,
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
ExprKind::Lit(token_lit) => {
Expand All @@ -573,7 +593,7 @@ impl MetaItemKind {
Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
let inner_tokens = inner_tokens.clone();
tokens.next();
MetaItemKind::list_from_tokens(inner_tokens)
MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
}
Some(TokenTree::Delimited(..)) => None,
Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
Expand Down
88 changes: 38 additions & 50 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,74 +319,62 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
}
} else if attr.has_name(sym::instruction_set) {
codegen_fn_attrs.instruction_set = match attr.meta_kind() {
Some(MetaItemKind::List(ref items)) => match items.as_slice() {
[NestedMetaItem::MetaItem(set)] => {
let segments =
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
match segments.as_slice() {
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
if !tcx.sess.target.has_thumb_interworking {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
"target does not support `#[instruction_set]`"
)
.emit();
None
} else if segments[1] == sym::a32 {
Some(InstructionSetAttr::ArmA32)
} else if segments[1] == sym::t32 {
Some(InstructionSetAttr::ArmT32)
} else {
unreachable!()
}
}
_ => {
codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] {
[NestedMetaItem::MetaItem(set)] => {
let segments =
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
match segments.as_slice() {
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
if !tcx.sess.target.has_thumb_interworking {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
"invalid instruction set specified",
"target does not support `#[instruction_set]`"
)
.emit();
None
} else if segments[1] == sym::a32 {
Some(InstructionSetAttr::ArmA32)
} else if segments[1] == sym::t32 {
Some(InstructionSetAttr::ArmT32)
} else {
unreachable!()
}
}
_ => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
"invalid instruction set specified",
)
.emit();
None
}
}
[] => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0778,
"`#[instruction_set]` requires an argument"
)
.emit();
None
}
_ => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
"cannot specify more than one instruction set"
)
.emit();
None
}
},
_ => {
}
[] => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0778,
"must specify an instruction set"
"`#[instruction_set]` requires an argument"
)
.emit();
None
}
};
_ => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
"cannot specify more than one instruction set"
)
.emit();
None
}
})
} else if attr.has_name(sym::repr) {
codegen_fn_attrs.alignment = match attr.meta_item_list() {
Some(items) => match items.as_slice() {
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_passes/src/lib_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.

use rustc_ast::{Attribute, MetaItemKind};
use rustc_ast::Attribute;
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
Expand Down Expand Up @@ -42,8 +42,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
let meta_kind = attr.meta_kind();
if let Some(MetaItemKind::List(ref metas)) = meta_kind {
if let Some(metas) = attr.meta_item_list() {
let mut feature = None;
let mut since = None;
for meta in metas {
Expand Down

0 comments on commit a94b9fd

Please sign in to comment.