Skip to content

Commit a94b9fd

Browse files
committed
Auto merge of rust-lang#107569 - petrochenkov:optattr, r=nnethercote
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.
2 parents 7c46fb2 + a9c8a5c commit a94b9fd

File tree

4 files changed

+90
-76
lines changed

4 files changed

+90
-76
lines changed

compiler/rustc_ast/src/ast.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,13 @@ pub enum LitKind {
18261826
}
18271827

18281828
impl LitKind {
1829+
pub fn str(&self) -> Option<Symbol> {
1830+
match *self {
1831+
LitKind::Str(s, _) => Some(s),
1832+
_ => None,
1833+
}
1834+
}
1835+
18291836
/// Returns `true` if this literal is a string.
18301837
pub fn is_str(&self) -> bool {
18311838
matches!(self, LitKind::Str(..))

compiler/rustc_ast/src/attr/mod.rs

+43-23
Original file line numberDiff line numberDiff line change
@@ -140,17 +140,14 @@ impl Attribute {
140140

141141
pub fn value_str(&self) -> Option<Symbol> {
142142
match &self.kind {
143-
AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()),
143+
AttrKind::Normal(normal) => normal.item.value_str(),
144144
AttrKind::DocComment(..) => None,
145145
}
146146
}
147147

148148
pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
149149
match &self.kind {
150-
AttrKind::Normal(normal) => match normal.item.meta_kind() {
151-
Some(MetaItemKind::List(list)) => Some(list),
152-
_ => None,
153-
},
150+
AttrKind::Normal(normal) => normal.item.meta_item_list(),
154151
AttrKind::DocComment(..) => None,
155152
}
156153
}
@@ -216,6 +213,20 @@ impl MetaItem {
216213
}
217214
}
218215

216+
impl AttrArgsEq {
217+
fn value_str(&self) -> Option<Symbol> {
218+
match self {
219+
AttrArgsEq::Ast(expr) => match expr.kind {
220+
ExprKind::Lit(token_lit) => {
221+
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
222+
}
223+
_ => None,
224+
},
225+
AttrArgsEq::Hir(lit) => lit.kind.str(),
226+
}
227+
}
228+
}
229+
219230
impl AttrItem {
220231
pub fn span(&self) -> Span {
221232
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
@@ -228,6 +239,22 @@ impl AttrItem {
228239
pub fn meta_kind(&self) -> Option<MetaItemKind> {
229240
MetaItemKind::from_attr_args(&self.args)
230241
}
242+
243+
fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
244+
match &self.args {
245+
AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
246+
MetaItemKind::list_from_tokens(args.tokens.clone())
247+
}
248+
AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
249+
}
250+
}
251+
252+
fn value_str(&self) -> Option<Symbol> {
253+
match &self.args {
254+
AttrArgs::Eq(_, args) => args.value_str(),
255+
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
256+
}
257+
}
231258
}
232259

233260
impl Attribute {
@@ -247,13 +274,11 @@ impl Attribute {
247274
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
248275
/// * `#[doc(...)]` returns `None`.
249276
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
250-
match self.kind {
251-
AttrKind::DocComment(kind, data) => Some((data, kind)),
252-
AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
253-
.item
254-
.meta_kind()
255-
.and_then(|kind| kind.value_str())
256-
.map(|data| (data, CommentKind::Line)),
277+
match &self.kind {
278+
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
279+
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
280+
normal.item.value_str().map(|s| (s, CommentKind::Line))
281+
}
257282
_ => None,
258283
}
259284
}
@@ -265,9 +290,7 @@ impl Attribute {
265290
pub fn doc_str(&self) -> Option<Symbol> {
266291
match &self.kind {
267292
AttrKind::DocComment(.., data) => Some(*data),
268-
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
269-
normal.item.meta_kind().and_then(|kind| kind.value_str())
270-
}
293+
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
271294
_ => None,
272295
}
273296
}
@@ -508,15 +531,12 @@ impl MetaItem {
508531
impl MetaItemKind {
509532
pub fn value_str(&self) -> Option<Symbol> {
510533
match self {
511-
MetaItemKind::NameValue(v) => match v.kind {
512-
LitKind::Str(s, _) => Some(s),
513-
_ => None,
514-
},
534+
MetaItemKind::NameValue(v) => v.kind.str(),
515535
_ => None,
516536
}
517537
}
518538

519-
fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
539+
fn list_from_tokens(tokens: TokenStream) -> Option<Vec<NestedMetaItem>> {
520540
let mut tokens = tokens.into_trees().peekable();
521541
let mut result = Vec::new();
522542
while tokens.peek().is_some() {
@@ -527,7 +547,7 @@ impl MetaItemKind {
527547
_ => return None,
528548
}
529549
}
530-
Some(MetaItemKind::List(result))
550+
Some(result)
531551
}
532552

533553
fn name_value_from_tokens(
@@ -551,7 +571,7 @@ impl MetaItemKind {
551571
dspan: _,
552572
delim: MacDelimiter::Parenthesis,
553573
tokens,
554-
}) => MetaItemKind::list_from_tokens(tokens.clone()),
574+
}) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List),
555575
AttrArgs::Delimited(..) => None,
556576
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
557577
ExprKind::Lit(token_lit) => {
@@ -573,7 +593,7 @@ impl MetaItemKind {
573593
Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
574594
let inner_tokens = inner_tokens.clone();
575595
tokens.next();
576-
MetaItemKind::list_from_tokens(inner_tokens)
596+
MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
577597
}
578598
Some(TokenTree::Delimited(..)) => None,
579599
Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+38-50
Original file line numberDiff line numberDiff line change
@@ -319,74 +319,62 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
319319
}
320320
}
321321
} else if attr.has_name(sym::instruction_set) {
322-
codegen_fn_attrs.instruction_set = match attr.meta_kind() {
323-
Some(MetaItemKind::List(ref items)) => match items.as_slice() {
324-
[NestedMetaItem::MetaItem(set)] => {
325-
let segments =
326-
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
327-
match segments.as_slice() {
328-
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
329-
if !tcx.sess.target.has_thumb_interworking {
330-
struct_span_err!(
331-
tcx.sess.diagnostic(),
332-
attr.span,
333-
E0779,
334-
"target does not support `#[instruction_set]`"
335-
)
336-
.emit();
337-
None
338-
} else if segments[1] == sym::a32 {
339-
Some(InstructionSetAttr::ArmA32)
340-
} else if segments[1] == sym::t32 {
341-
Some(InstructionSetAttr::ArmT32)
342-
} else {
343-
unreachable!()
344-
}
345-
}
346-
_ => {
322+
codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] {
323+
[NestedMetaItem::MetaItem(set)] => {
324+
let segments =
325+
set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
326+
match segments.as_slice() {
327+
[sym::arm, sym::a32] | [sym::arm, sym::t32] => {
328+
if !tcx.sess.target.has_thumb_interworking {
347329
struct_span_err!(
348330
tcx.sess.diagnostic(),
349331
attr.span,
350332
E0779,
351-
"invalid instruction set specified",
333+
"target does not support `#[instruction_set]`"
352334
)
353335
.emit();
354336
None
337+
} else if segments[1] == sym::a32 {
338+
Some(InstructionSetAttr::ArmA32)
339+
} else if segments[1] == sym::t32 {
340+
Some(InstructionSetAttr::ArmT32)
341+
} else {
342+
unreachable!()
355343
}
356344
}
345+
_ => {
346+
struct_span_err!(
347+
tcx.sess.diagnostic(),
348+
attr.span,
349+
E0779,
350+
"invalid instruction set specified",
351+
)
352+
.emit();
353+
None
354+
}
357355
}
358-
[] => {
359-
struct_span_err!(
360-
tcx.sess.diagnostic(),
361-
attr.span,
362-
E0778,
363-
"`#[instruction_set]` requires an argument"
364-
)
365-
.emit();
366-
None
367-
}
368-
_ => {
369-
struct_span_err!(
370-
tcx.sess.diagnostic(),
371-
attr.span,
372-
E0779,
373-
"cannot specify more than one instruction set"
374-
)
375-
.emit();
376-
None
377-
}
378-
},
379-
_ => {
356+
}
357+
[] => {
380358
struct_span_err!(
381359
tcx.sess.diagnostic(),
382360
attr.span,
383361
E0778,
384-
"must specify an instruction set"
362+
"`#[instruction_set]` requires an argument"
385363
)
386364
.emit();
387365
None
388366
}
389-
};
367+
_ => {
368+
struct_span_err!(
369+
tcx.sess.diagnostic(),
370+
attr.span,
371+
E0779,
372+
"cannot specify more than one instruction set"
373+
)
374+
.emit();
375+
None
376+
}
377+
})
390378
} else if attr.has_name(sym::repr) {
391379
codegen_fn_attrs.alignment = match attr.meta_item_list() {
392380
Some(items) => match items.as_slice() {

compiler/rustc_passes/src/lib_features.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! but are not declared in one single location (unlike lang features), which means we need to
55
//! collect them instead.
66
7-
use rustc_ast::{Attribute, MetaItemKind};
7+
use rustc_ast::Attribute;
88
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
99
use rustc_hir::intravisit::Visitor;
1010
use rustc_middle::hir::nested_filter;
@@ -42,8 +42,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
4242
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
4343
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
4444
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
45-
let meta_kind = attr.meta_kind();
46-
if let Some(MetaItemKind::List(ref metas)) = meta_kind {
45+
if let Some(metas) = attr.meta_item_list() {
4746
let mut feature = None;
4847
let mut since = None;
4948
for meta in metas {

0 commit comments

Comments
 (0)