From c9ae38c71e2838f1ac282803ddde47f21f4ca76e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 24 Nov 2022 16:00:57 +1100 Subject: [PATCH 1/7] 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. --- .../rustc_ast_passes/src/ast_validation.rs | 2 +- .../src/cfg_accessible.rs | 6 +-- compiler/rustc_builtin_macros/src/derive.rs | 9 ++-- compiler/rustc_builtin_macros/src/util.rs | 11 +++-- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_parse/src/validate_attr.rs | 43 +++++++++++-------- 6 files changed, 44 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index acd7eb69ffc37..29bf794877014 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -912,7 +912,7 @@ fn validate_generic_param_order( impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_meta(&self.session.parse_sess, attr); + validate_attr::check_attr(&self.session.parse_sess, attr); } fn visit_expr(&mut self, expr: &'a Expr) { diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 86df3c44eb334..4e4cafc71823a 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -37,10 +37,10 @@ impl MultiItemModifier for Expander { _is_derive_const: bool, ) -> ExpandResult, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; - let attr = &ecx.attribute(meta_item.clone()); - validate_attr::check_builtin_attribute( + validate_attr::check_builtin_meta_item( &ecx.sess.parse_sess, - attr, + &meta_item, + ast::AttrStyle::Outer, sym::cfg_accessible, template, ); diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index c8a2fca00e800..0358c0b1b5fab 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -33,14 +33,15 @@ impl MultiItemModifier for Expander { ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { let template = AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; - let attr = - attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone()); - validate_attr::check_builtin_attribute( + validate_attr::check_builtin_meta_item( &sess.parse_sess, - &attr, + &meta_item, + ast::AttrStyle::Outer, sym::derive, template, ); + let attr = + attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone()); let mut resolutions: Vec<_> = attr .meta_item_list() diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 527fe50eff0ce..83812631c2ff7 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -1,4 +1,4 @@ -use rustc_ast::{Attribute, MetaItem}; +use rustc_ast::{AttrStyle, Attribute, MetaItem}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_feature::AttributeTemplate; use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; @@ -8,8 +8,13 @@ use rustc_span::Symbol; pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { // All the built-in macro attributes are "words" at the moment. let template = AttributeTemplate { word: true, ..Default::default() }; - let attr = ecx.attribute(meta_item.clone()); - validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template); + validate_attr::check_builtin_meta_item( + &ecx.sess.parse_sess, + &meta_item, + AttrStyle::Outer, + name, + template, + ); } /// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3e98b024c73b9..e799fa404f6fd 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1644,7 +1644,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let mut span: Option = None; while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_meta(&self.cx.sess.parse_sess, attr); + validate_attr::check_attr(&self.cx.sess.parse_sess, attr); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 59e564114e5cf..72402a200907a 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -10,9 +10,9 @@ use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::ParseSess; -use rustc_span::{sym, Symbol}; +use rustc_span::{sym, Span, Symbol}; -pub fn check_meta(sess: &ParseSess, attr: &Attribute) { +pub fn check_attr(sess: &ParseSess, attr: &Attribute) { if attr.is_doc_comment() { return; } @@ -115,25 +115,34 @@ pub fn check_builtin_attribute( name: Symbol, template: AttributeTemplate, ) { - // Some special attributes like `cfg` must be checked - // before the generic check, so we skip them here. - let should_skip = |name| name == sym::cfg; - match parse_meta(sess, attr) { - Ok(meta) => { - if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { - emit_malformed_attribute(sess, attr, name, template); - } - } + Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template), Err(mut err) => { err.emit(); } } } +pub fn check_builtin_meta_item( + sess: &ParseSess, + meta: &MetaItem, + style: ast::AttrStyle, + name: Symbol, + template: AttributeTemplate, +) { + // Some special attributes like `cfg` must be checked + // before the generic check, so we skip them here. + let should_skip = |name| name == sym::cfg; + + if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { + emit_malformed_attribute(sess, style, meta.span, name, template); + } +} + fn emit_malformed_attribute( sess: &ParseSess, - attr: &Attribute, + style: ast::AttrStyle, + span: Span, name: Symbol, template: AttributeTemplate, ) { @@ -147,7 +156,7 @@ fn emit_malformed_attribute( let mut msg = "attribute must be of the form ".to_owned(); let mut suggestions = vec![]; let mut first = true; - let inner = if attr.style == ast::AttrStyle::Inner { "!" } else { "" }; + let inner = if style == ast::AttrStyle::Inner { "!" } else { "" }; if template.word { first = false; let code = format!("#{}[{}]", inner, name); @@ -172,12 +181,12 @@ fn emit_malformed_attribute( suggestions.push(code); } if should_warn(name) { - sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, attr.span, ast::CRATE_NODE_ID, &msg); + sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg); } else { sess.span_diagnostic - .struct_span_err(attr.span, &error_msg) + .struct_span_err(span, &error_msg) .span_suggestions( - attr.span, + span, if suggestions.len() == 1 { "must be of the form" } else { @@ -196,7 +205,7 @@ pub fn emit_fatal_malformed_builtin_attribute( name: Symbol, ) -> ! { let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; - emit_malformed_attribute(sess, attr, name, template); + emit_malformed_attribute(sess, attr.style, attr.span, name, template); // This is fatal, otherwise it will likely cause a cascade of other errors // (and an error here is expected to be very rare). FatalError.raise() From 5a2fd1a47ffb72c060b77b717e8bfa85c7e0e5bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 25 Nov 2022 09:53:37 +1100 Subject: [PATCH 2/7] Improve comments about attributes and meta items. I have found the distinction confusing. --- compiler/rustc_ast/src/ast.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index d0bb05c36549b..9d23bb5c1596a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -479,20 +479,24 @@ pub struct Crate { pub is_placeholder: bool, } -/// Possible values inside of compile-time attribute lists. +/// Values inside meta item lists. /// -/// E.g., the '..' in `#[name(..)]`. +/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub enum NestedMetaItem { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), + /// A literal. /// /// E.g., `"foo"`, `64`, `true`. Lit(MetaItemLit), } -/// A spanned compile-time attribute item. +/// A semantic representation of a meta item. A meta item is a slightly +/// restricted form of an attribute -- it can only contain expressions in +/// certain leaf positions, rather than arbitrary token streams -- that is used +/// for most built-in attributes. /// /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] @@ -502,22 +506,22 @@ pub struct MetaItem { pub span: Span, } -/// A compile-time attribute item. -/// -/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. +/// The meta item kind, containing the data after the initial path. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub enum MetaItemKind { /// Word meta item. /// - /// E.g., `test` as in `#[test]`. + /// E.g., `#[test]`, which lacks any arguments after `test`. Word, + /// List meta item. /// - /// E.g., `derive(..)` as in `#[derive(..)]`. + /// E.g., `#[derive(..)]`, where the field represents the `..`. List(Vec), + /// Name value meta item. /// - /// E.g., `feature = "foo"` as in `#[feature = "foo"]`. + /// E.g., `#[feature = "foo"]`, where the field represents the `"foo"`. NameValue(MetaItemLit), } @@ -2580,7 +2584,7 @@ pub struct AttrItem { /// A list of attributes. pub type AttrVec = ThinVec; -/// Metadata associated with an item. +/// A syntax-level representation of an attribute. #[derive(Clone, Encodable, Decodable, Debug)] pub struct Attribute { pub kind: AttrKind, From fc2a8a0c675bf7d111846b19fd3d5d7a13915425 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 25 Nov 2022 09:59:36 +1100 Subject: [PATCH 3/7] Reorder some types. So that `Attribute` and `MetaItem` are listed first, and then the component types are below them in a logical order. --- compiler/rustc_ast/src/ast.rs | 54 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9d23bb5c1596a..6a2f1f0c5749c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -479,20 +479,6 @@ pub struct Crate { pub is_placeholder: bool, } -/// Values inside meta item lists. -/// -/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`. -#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] -pub enum NestedMetaItem { - /// A full MetaItem, for recursive meta items. - MetaItem(MetaItem), - - /// A literal. - /// - /// E.g., `"foo"`, `64`, `true`. - Lit(MetaItemLit), -} - /// A semantic representation of a meta item. A meta item is a slightly /// restricted form of an attribute -- it can only contain expressions in /// certain leaf positions, rather than arbitrary token streams -- that is used @@ -525,6 +511,20 @@ pub enum MetaItemKind { NameValue(MetaItemLit), } +/// Values inside meta item lists. +/// +/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`. +#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum NestedMetaItem { + /// A full MetaItem, for recursive meta items. + MetaItem(MetaItem), + + /// A literal. + /// + /// E.g., `"foo"`, `64`, `true`. + Lit(MetaItemLit), +} + /// A block (`{ .. }`). /// /// E.g., `{ .. }` as in `fn foo() { .. }`. @@ -2574,13 +2574,6 @@ impl Decodable for AttrId { } } -#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] -pub struct AttrItem { - pub path: Path, - pub args: AttrArgs, - pub tokens: Option, -} - /// A list of attributes. pub type AttrVec = ThinVec; @@ -2595,12 +2588,6 @@ pub struct Attribute { pub span: Span, } -#[derive(Clone, Encodable, Decodable, Debug)] -pub struct NormalAttr { - pub item: AttrItem, - pub tokens: Option, -} - #[derive(Clone, Encodable, Decodable, Debug)] pub enum AttrKind { /// A normal attribute. @@ -2612,6 +2599,19 @@ pub enum AttrKind { DocComment(CommentKind, Symbol), } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct NormalAttr { + pub item: AttrItem, + pub tokens: Option, +} + +#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct AttrItem { + pub path: Path, + pub args: AttrArgs, + pub tokens: Option, +} + /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all From a709f87be7d66e8a91c5ee2818cac6f077caac08 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 28 Nov 2022 11:17:45 +1100 Subject: [PATCH 4/7] Avoid more unnecessary `MetaItem`/`Attribute` conversions. In `Expander::expand` the code currently uses `mk_attr_outer` to convert a `MetaItem` to an `Attribute`, and then follows that with `meta_item_list` which converts back. This commit avoids the unnecessary conversions. There was one wrinkle: the existing conversions caused the bogus `<>` on `Default<>` to be removed. With the conversion gone, we get a second error message about the `<>`. This is a rare case, so I think it probably doesn't matter much. --- compiler/rustc_builtin_macros/src/derive.rs | 45 +++++++++++---------- src/test/ui/span/macro-ty-params.rs | 4 +- src/test/ui/span/macro-ty-params.stderr | 8 +++- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 0358c0b1b5fab..fa5a45730ac7a 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,7 +1,7 @@ use crate::cfg_eval::cfg_eval; use rustc_ast as ast; -use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; @@ -40,28 +40,29 @@ impl MultiItemModifier for Expander { sym::derive, template, ); - let attr = - attr::mk_attr_outer(&sess.parse_sess.attr_id_generator, meta_item.clone()); - let mut resolutions: Vec<_> = attr - .meta_item_list() - .unwrap_or_default() - .into_iter() - .filter_map(|nested_meta| match nested_meta { - NestedMetaItem::MetaItem(meta) => Some(meta), - NestedMetaItem::Lit(lit) => { - // Reject `#[derive("Debug")]`. - report_unexpected_meta_item_lit(sess, &lit); - None - } - }) - .map(|meta| { - // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths. - report_path_args(sess, &meta); - meta.path - }) - .map(|path| (path, dummy_annotatable(), None, self.0)) - .collect(); + let mut resolutions = match &meta_item.kind { + MetaItemKind::List(list) => { + list.iter() + .filter_map(|nested_meta| match nested_meta { + NestedMetaItem::MetaItem(meta) => Some(meta), + NestedMetaItem::Lit(lit) => { + // Reject `#[derive("Debug")]`. + report_unexpected_meta_item_lit(sess, &lit); + None + } + }) + .map(|meta| { + // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the + // paths. + report_path_args(sess, &meta); + meta.path.clone() + }) + .map(|path| (path, dummy_annotatable(), None, self.0)) + .collect() + } + _ => vec![], + }; // Do not configure or clone items unless necessary. match &mut resolutions[..] { diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs index 0a93105b66477..cf28b0255d17d 100644 --- a/src/test/ui/span/macro-ty-params.rs +++ b/src/test/ui/span/macro-ty-params.rs @@ -9,5 +9,7 @@ macro_rules! foo { () => () } fn main() { foo::!(); //~ ERROR generic arguments in macro path foo::<>!(); //~ ERROR generic arguments in macro path - m!(Default<>); //~ ERROR unexpected generic arguments in path + m!(Default<>); + //~^ ERROR unexpected generic arguments in path + //~^^ ERROR generic arguments in macro path } diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr index 138cd2598a1c5..7023ef8cd1c33 100644 --- a/src/test/ui/span/macro-ty-params.stderr +++ b/src/test/ui/span/macro-ty-params.stderr @@ -16,5 +16,11 @@ error: unexpected generic arguments in path LL | m!(Default<>); | ^^ -error: aborting due to 3 previous errors +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:12:15 + | +LL | m!(Default<>); + | ^^ + +error: aborting due to 4 previous errors From ac7a7499df4c21de001475d8acf8bf43ee46498d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Nov 2022 17:13:38 +1100 Subject: [PATCH 5/7] Remove an out-of-date comment. This comment dates back to at least 2013, and is no longer relevant. (There used to be an `allow` attribute, but that's no longer present.) --- compiler/rustc_expand/src/build.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 234cf1b315a23..c2a2326d30123 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -579,8 +579,6 @@ impl<'a> ExtCtxt<'a> { attrs: ast::AttrVec, kind: ast::ItemKind, ) -> P { - // FIXME: Would be nice if our generated code didn't violate - // Rust coding conventions P(ast::Item { ident: name, attrs, From d1b61a31c5d28075f7c5a7f376315350672e2d93 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Nov 2022 18:42:40 +1100 Subject: [PATCH 6/7] Inline and remove `MetaItemLit::from_lit_kind`. It has a single call site. --- compiler/rustc_ast/src/attr/mod.rs | 4 ++-- compiler/rustc_ast/src/util/literal.rs | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 7a86b471ba298..e08be6970ebae 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -333,8 +333,8 @@ pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> Meta mk_name_value_item(ident, lit_kind, str_span) } -pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { - let lit = MetaItemLit::from_lit_kind(lit_kind, lit_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) } } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 42cba07fcef8d..14ee4d481209c 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -207,13 +207,6 @@ impl MetaItemLit { .and_then(|token_lit| MetaItemLit::from_token_lit(token_lit, token.span).ok()) } - /// Attempts to create a meta item literal from a `LitKind`. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn from_lit_kind(kind: LitKind, span: Span) -> MetaItemLit { - MetaItemLit { token_lit: kind.to_token_lit(), kind, span } - } - /// Losslessly convert a meta item literal into a token. pub fn to_token(&self) -> Token { let kind = match self.token_lit.kind { From ba1751a201190930a16ef20e6f7021c785d3891d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Nov 2022 18:43:44 +1100 Subject: [PATCH 7/7] Avoid more `MetaItem`-to-`Attribute` conversions. 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. --- compiler/rustc_ast/src/attr/mod.rs | 167 ++++++------------ compiler/rustc_ast/src/util/literal.rs | 9 - compiler/rustc_ast_lowering/src/expr.rs | 17 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 19 +- .../src/alloc_error_handler.rs | 4 +- .../src/assert/context.rs | 6 +- .../src/deriving/clone.rs | 3 +- .../src/deriving/cmp/eq.rs | 12 +- .../src/deriving/cmp/ord.rs | 3 +- .../src/deriving/cmp/partial_eq.rs | 3 +- .../src/deriving/cmp/partial_ord.rs | 3 +- .../src/deriving/default.rs | 3 +- .../src/deriving/generic/mod.rs | 2 +- .../rustc_builtin_macros/src/deriving/mod.rs | 2 +- .../src/global_allocator.rs | 4 +- .../src/proc_macro_harness.rs | 14 +- .../src/standard_library_imports.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 18 +- .../rustc_builtin_macros/src/test_harness.rs | 14 +- compiler/rustc_expand/src/build.rs | 20 ++- 20 files changed, 116 insertions(+), 211 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index e08be6970ebae..057cc26b5799e 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -1,10 +1,10 @@ //! 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}; @@ -12,7 +12,6 @@ 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; @@ -223,11 +222,7 @@ impl AttrItem { } pub fn meta(&self, span: Span) -> Option { - 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 { @@ -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) -> 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>); @@ -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( @@ -438,23 +457,6 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool { } impl MetaItem { - fn token_trees(&self) -> Vec { - 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(tokens: &mut iter::Peekable) -> Option where I: Iterator, @@ -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 { - 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 { let mut tokens = tokens.into_trees().peekable(); let mut result = Vec::new(); @@ -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() @@ -659,15 +605,6 @@ impl NestedMetaItem { } } - fn token_trees(&self) -> Vec { - match self { - NestedMetaItem::MetaItem(item) => item.token_trees(), - NestedMetaItem::Lit(lit) => { - vec![TokenTree::Token(lit.to_token(), Spacing::Alone)] - } - } - } - fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 14ee4d481209c..1d6e7914f3a5c 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -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 { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c14c591d3875d..82912a733d552 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -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,` diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7a9243c511b92..2d7fd83195d94 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -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; @@ -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); } } @@ -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); diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index eaf1b1167cf21..460175ed2ac84 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -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) diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 9f42a0c2d585c..bd415901ae34d 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -1,5 +1,4 @@ use rustc_ast::{ - attr, ptr::P, token, tokenstream::{DelimSpan, TokenStream, TokenTree}, @@ -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![ diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 2f19fbcac7d72..23b96d4176d3a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -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), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index a0b836171bea9..f861d47ed408e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -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; @@ -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), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 52780981248b9..96d18c7afb924 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -15,8 +15,7 @@ pub fn expand_deriving_ord( push: &mut dyn FnMut(Annotatable), is_const: bool, ) { - 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!(cmp::Ord), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 34de4a620b462..7f95551fc483a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -68,8 +68,7 @@ pub fn expand_deriving_partial_eq( // No need to generate `ne`, the default suffices, and not generating it is // faster. - 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 methods = vec![MethodDef { name: sym::eq, generics: Bounds::empty(), diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 6cc8f26df559c..5c4e5b7f81675 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -19,8 +19,7 @@ pub fn expand_deriving_partial_ord( let ret_ty = Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); - 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 partial_cmp_def = MethodDef { name: sym::partial_cmp, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 93f297ad88b5f..e4e2435848dd2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -20,8 +20,7 @@ pub fn expand_deriving_default( ) { item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); - 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::new(vec![kw::Default, sym::Default]), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 1467d4eaec068..7fcaf0b436b90 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -718,7 +718,7 @@ impl<'a> TraitDef<'a> { let path = cx.path_all(self.span, false, vec![type_ident], self_params); let self_type = cx.ty_path(path); - let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived)); + let attr = cx.attr_word(sym::automatically_derived, self.span); let attrs = thin_vec![attr]; let opt_trait_ref = Some(trait_ref); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 73a1df5d426d2..13fdd4fa68c43 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -188,7 +188,7 @@ fn inject_impl_of_structural_trait( .cloned(), ); // Mark as `automatically_derived` to avoid some silly lints. - attrs.push(cx.attribute(cx.meta_word(span, sym::automatically_derived))); + attrs.push(cx.attr_word(sym::automatically_derived, span)); let newitem = cx.item( span, diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 45b9b8ab6b641..0817aed037ef8 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -115,9 +115,7 @@ impl AllocFnFactory<'_, '_> { } fn attrs(&self) -> AttrVec { - let special = sym::rustc_std_internal_symbol; - let special = self.cx.meta_word(self.span, special); - thin_vec![self.cx.attribute(special)] + thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)] } fn arg_ty( diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index ebe1c3663e3a7..ece660cf6f645 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -1,6 +1,3 @@ -use std::mem; - -use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, NodeId}; @@ -13,6 +10,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use smallvec::smallvec; +use std::mem; struct ProcMacroDerive { id: NodeId, @@ -365,14 +363,8 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { cx.expr_array_ref(span, decls), ) .map(|mut i| { - let attr = cx.meta_word(span, sym::rustc_proc_macro_decls); - i.attrs.push(cx.attribute(attr)); - - let deprecated_attr = attr::mk_nested_word_item(Ident::new(sym::deprecated, span)); - let allow_deprecated_attr = - attr::mk_list_item(Ident::new(sym::allow, span), vec![deprecated_attr]); - i.attrs.push(cx.attribute(allow_deprecated_attr)); - + i.attrs.push(cx.attr_word(sym::rustc_proc_macro_decls, span)); + i.attrs.push(cx.attr_nested_word(sym::allow, sym::deprecated, span)); i }); diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 49ef538f04e14..f73f20c84a39d 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -52,7 +52,7 @@ pub fn inject( cx.item( span, ident, - thin_vec![cx.attribute(cx.meta_word(span, sym::macro_use))], + thin_vec![cx.attr_word(sym::macro_use, span)], ast::ItemKind::ExternCrate(None), ), ); @@ -79,7 +79,7 @@ pub fn inject( let use_item = cx.item( span, Ident::empty(), - thin_vec![cx.attribute(cx.meta_word(span, sym::prelude_import))], + thin_vec![cx.attr_word(sym::prelude_import, span)], ast::ItemKind::Use(ast::UseTree { prefix: cx.path(span, import_path), kind: ast::UseTreeKind::Glob, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 82baf1da28f2f..3bcb60478efbc 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -2,7 +2,6 @@ /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; -use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast_pretty::pprust; use rustc_errors::Applicability; @@ -47,11 +46,7 @@ pub fn expand_test_case( tokens: None, }; item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); - item.attrs.push(ecx.attribute(attr::mk_name_value_item_str( - Ident::new(sym::rustc_test_marker, sp), - test_path_symbol, - sp, - ))); + item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp)); item }); @@ -241,16 +236,9 @@ pub fn expand_test_or_bench( Ident::new(item.ident.name, sp), thin_vec![ // #[cfg(test)] - cx.attribute(attr::mk_list_item( - Ident::new(sym::cfg, attr_sp), - vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))], - )), + cx.attr_nested_word(sym::cfg, sym::test, attr_sp), // #[rustc_test_marker = "test_case_sort_key"] - cx.attribute(attr::mk_name_value_item_str( - Ident::new(sym::rustc_test_marker, attr_sp), - test_path_symbol, - attr_sp, - )), + cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), ] .into(), // const $ident: test::TestDescAndFn = diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 3269f62b105b9..b5bce9278a907 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -185,13 +185,12 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { let item = match entry_point_type(self.sess, &item, self.depth) { EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => { item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { - let allow_ident = Ident::new(sym::allow, self.def_site); - let dc_nested = - attr::mk_nested_word_item(Ident::new(sym::dead_code, self.def_site)); - let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); - let allow_dead_code = attr::mk_attr_outer( + let allow_dead_code = attr::mk_attr_nested_word( &self.sess.parse_sess.attr_id_generator, - allow_dead_code_item, + ast::AttrStyle::Outer, + sym::allow, + sym::dead_code, + self.def_site, ); let attrs = attrs .into_iter() @@ -309,8 +308,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { ); // #[rustc_main] - let main_meta = ecx.meta_word(sp, sym::rustc_main); - let main_attr = ecx.attribute(main_meta); + let main_attr = ecx.attr_word(sym::rustc_main, sp); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index c2a2326d30123..c978297295d40 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -616,11 +616,23 @@ impl<'a> ExtCtxt<'a> { self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr))) } - pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { - attr::mk_attr_outer(&self.sess.parse_sess.attr_id_generator, mi) + // Builds `#[name]`. + pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute { + let g = &self.sess.parse_sess.attr_id_generator; + attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span) } - pub fn meta_word(&self, sp: Span, w: Symbol) -> ast::MetaItem { - attr::mk_word_item(Ident::new(w, sp)) + // Builds `#[name = val]`. + // + // Note: `span` is used for both the identifer and the value. + pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute { + let g = &self.sess.parse_sess.attr_id_generator; + attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span) + } + + // Builds `#[outer(inner)]`. + pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute { + let g = &self.sess.parse_sess.attr_id_generator; + attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span) } }