Skip to content

Commit c9ae38c

Browse files
committed
Avoid unnecessary MetaItem/Attribute conversions.
`check_builtin_attribute` calls `parse_meta` to convert an `Attribute` to a `MetaItem`, which it then checks. However, many callers of `check_builtin_attribute` start with a `MetaItem`, and then convert it to an `Attribute` by calling `cx.attribute(meta_item)`. This `MetaItem` to `Attribute` to `MetaItem` conversion is silly. This commit adds a new function `check_builtin_meta_item`, which can be called instead from these call sites. `check_builtin_attribute` also now calls it. The commit also renames `check_meta` as `check_attr` to better match its arguments.
1 parent 2585bce commit c9ae38c

File tree

6 files changed

+44
-29
lines changed

6 files changed

+44
-29
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ fn validate_generic_param_order(
912912

913913
impl<'a> Visitor<'a> for AstValidator<'a> {
914914
fn visit_attribute(&mut self, attr: &Attribute) {
915-
validate_attr::check_meta(&self.session.parse_sess, attr);
915+
validate_attr::check_attr(&self.session.parse_sess, attr);
916916
}
917917

918918
fn visit_expr(&mut self, expr: &'a Expr) {

compiler/rustc_builtin_macros/src/cfg_accessible.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ impl MultiItemModifier for Expander {
3737
_is_derive_const: bool,
3838
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
3939
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
40-
let attr = &ecx.attribute(meta_item.clone());
41-
validate_attr::check_builtin_attribute(
40+
validate_attr::check_builtin_meta_item(
4241
&ecx.sess.parse_sess,
43-
attr,
42+
&meta_item,
43+
ast::AttrStyle::Outer,
4444
sym::cfg_accessible,
4545
template,
4646
);

compiler/rustc_builtin_macros/src/derive.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ impl MultiItemModifier for Expander {
3333
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
3434
let template =
3535
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
36-
let attr =
37-
attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
38-
validate_attr::check_builtin_attribute(
36+
validate_attr::check_builtin_meta_item(
3937
&sess.parse_sess,
40-
&attr,
38+
&meta_item,
39+
ast::AttrStyle::Outer,
4140
sym::derive,
4241
template,
4342
);
43+
let attr =
44+
attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone());
4445

4546
let mut resolutions: Vec<_> = attr
4647
.meta_item_list()

compiler/rustc_builtin_macros/src/util.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::{Attribute, MetaItem};
1+
use rustc_ast::{AttrStyle, Attribute, MetaItem};
22
use rustc_expand::base::{Annotatable, ExtCtxt};
33
use rustc_feature::AttributeTemplate;
44
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
@@ -8,8 +8,13 @@ use rustc_span::Symbol;
88
pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
99
// All the built-in macro attributes are "words" at the moment.
1010
let template = AttributeTemplate { word: true, ..Default::default() };
11-
let attr = ecx.attribute(meta_item.clone());
12-
validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template);
11+
validate_attr::check_builtin_meta_item(
12+
&ecx.sess.parse_sess,
13+
&meta_item,
14+
AttrStyle::Outer,
15+
name,
16+
template,
17+
);
1318
}
1419

1520
/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when

compiler/rustc_expand/src/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
16441644
let mut span: Option<Span> = None;
16451645
while let Some(attr) = attrs.next() {
16461646
rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
1647-
validate_attr::check_meta(&self.cx.sess.parse_sess, attr);
1647+
validate_attr::check_attr(&self.cx.sess.parse_sess, attr);
16481648

16491649
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
16501650
span = Some(current_span);

compiler/rustc_parse/src/validate_attr.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use rustc_errors::{Applicability, FatalError, PResult};
1010
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
1111
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
1212
use rustc_session::parse::ParseSess;
13-
use rustc_span::{sym, Symbol};
13+
use rustc_span::{sym, Span, Symbol};
1414

15-
pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
15+
pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
1616
if attr.is_doc_comment() {
1717
return;
1818
}
@@ -115,25 +115,34 @@ pub fn check_builtin_attribute(
115115
name: Symbol,
116116
template: AttributeTemplate,
117117
) {
118-
// Some special attributes like `cfg` must be checked
119-
// before the generic check, so we skip them here.
120-
let should_skip = |name| name == sym::cfg;
121-
122118
match parse_meta(sess, attr) {
123-
Ok(meta) => {
124-
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
125-
emit_malformed_attribute(sess, attr, name, template);
126-
}
127-
}
119+
Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template),
128120
Err(mut err) => {
129121
err.emit();
130122
}
131123
}
132124
}
133125

126+
pub fn check_builtin_meta_item(
127+
sess: &ParseSess,
128+
meta: &MetaItem,
129+
style: ast::AttrStyle,
130+
name: Symbol,
131+
template: AttributeTemplate,
132+
) {
133+
// Some special attributes like `cfg` must be checked
134+
// before the generic check, so we skip them here.
135+
let should_skip = |name| name == sym::cfg;
136+
137+
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
138+
emit_malformed_attribute(sess, style, meta.span, name, template);
139+
}
140+
}
141+
134142
fn emit_malformed_attribute(
135143
sess: &ParseSess,
136-
attr: &Attribute,
144+
style: ast::AttrStyle,
145+
span: Span,
137146
name: Symbol,
138147
template: AttributeTemplate,
139148
) {
@@ -147,7 +156,7 @@ fn emit_malformed_attribute(
147156
let mut msg = "attribute must be of the form ".to_owned();
148157
let mut suggestions = vec![];
149158
let mut first = true;
150-
let inner = if attr.style == ast::AttrStyle::Inner { "!" } else { "" };
159+
let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
151160
if template.word {
152161
first = false;
153162
let code = format!("#{}[{}]", inner, name);
@@ -172,12 +181,12 @@ fn emit_malformed_attribute(
172181
suggestions.push(code);
173182
}
174183
if should_warn(name) {
175-
sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, attr.span, ast::CRATE_NODE_ID, &msg);
184+
sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg);
176185
} else {
177186
sess.span_diagnostic
178-
.struct_span_err(attr.span, &error_msg)
187+
.struct_span_err(span, &error_msg)
179188
.span_suggestions(
180-
attr.span,
189+
span,
181190
if suggestions.len() == 1 {
182191
"must be of the form"
183192
} else {
@@ -196,7 +205,7 @@ pub fn emit_fatal_malformed_builtin_attribute(
196205
name: Symbol,
197206
) -> ! {
198207
let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
199-
emit_malformed_attribute(sess, attr, name, template);
208+
emit_malformed_attribute(sess, attr.style, attr.span, name, template);
200209
// This is fatal, otherwise it will likely cause a cascade of other errors
201210
// (and an error here is expected to be very rare).
202211
FatalError.raise()

0 commit comments

Comments
 (0)