about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-04-10 19:47:55 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-04-15 15:20:05 +0200
commitb82ab24bbf9b6dc6bf7cdccb516ea196f3d0a71f (patch)
treecc2941b2bc27a547ef8b4add9cf536b70f8824a7 /src
parentfcf850f34a4db4baa3ccda0e8e2e53eca5fc9936 (diff)
downloadrust-b82ab24bbf9b6dc6bf7cdccb516ea196f3d0a71f.tar.gz
rust-b82ab24bbf9b6dc6bf7cdccb516ea196f3d0a71f.zip
Preallocate BUILTIN_ATTRIBUTES symbols and use a hash map instead of looping
Diffstat (limited to 'src')
-rw-r--r--src/librustc_lint/builtin.rs7
-rw-r--r--src/librustc_lint/lib.rs2
-rw-r--r--src/librustc_lint/unused.rs37
-rw-r--r--src/librustc_resolve/macros.rs5
-rw-r--r--src/libsyntax/Cargo.toml2
-rw-r--r--src/libsyntax/feature_gate.rs884
-rw-r--r--src/libsyntax_pos/symbol.rs131
-rw-r--r--src/test/ui/malformed/malformed-regressions.stderr4
8 files changed, 649 insertions, 423 deletions
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 7fe047ec2c6..f289b0b48fb 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -42,7 +42,7 @@ use syntax::edition::Edition;
 use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType};
 use syntax::feature_gate::{Stability, deprecated_attributes};
 use syntax_pos::{BytePos, Span, SyntaxContext};
-use syntax::symbol::keywords;
+use syntax::symbol::{Symbol, keywords};
 use syntax::errors::{Applicability, DiagnosticBuilder};
 use syntax::print::pprust::expr_to_string;
 use syntax::visit::FnKind;
@@ -653,7 +653,7 @@ impl EarlyLintPass for AnonymousParameters {
 pub struct DeprecatedAttr {
     // This is not free to compute, so we want to keep it around, rather than
     // compute it for every attribute.
-    depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeTemplate, AttributeGate)>,
+    depr_attrs: Vec<&'static (Symbol, AttributeType, AttributeTemplate, AttributeGate)>,
 }
 
 impl_lint_pass!(DeprecatedAttr => []);
@@ -668,9 +668,8 @@ impl DeprecatedAttr {
 
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
-        let name = attr.name_or_empty();
         for &&(n, _, _, ref g) in &self.depr_attrs {
-            if name == n {
+            if attr.ident().map(|ident| ident.name) == Some(n) {
                 if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
                                              ref name,
                                              ref reason,
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 4a2d6dc68ae..9354f203e4e 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -118,7 +118,7 @@ macro_rules! late_lint_passes {
             UnusedBrokenConst: UnusedBrokenConst,
 
             // Uses attr::is_used which is untracked, can't be an incremental module pass.
-            UnusedAttributes: UnusedAttributes,
+            UnusedAttributes: UnusedAttributes::new(),
 
             // Needs to run after UnusedAttributes as it marks all `feature` attributes as used.
             UnstableFeatures: UnstableFeatures,
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 2aee21abb58..1182307600d 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -3,15 +3,17 @@ use rustc::hir::def_id::DefId;
 use rustc::lint;
 use rustc::ty;
 use rustc::ty::adjustment;
+use rustc_data_structures::fx::FxHashMap;
 use lint::{LateContext, EarlyContext, LintContext, LintArray};
 use lint::{LintPass, EarlyLintPass, LateLintPass};
 
 use syntax::ast;
 use syntax::attr;
 use syntax::errors::Applicability;
-use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
+use syntax::feature_gate::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use syntax::print::pprust;
 use syntax::symbol::keywords;
+use syntax::symbol::Symbol;
 use syntax::util::parser;
 use syntax_pos::Span;
 
@@ -210,17 +212,32 @@ declare_lint! {
     "detects attributes that were not used by the compiler"
 }
 
-declare_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
+#[derive(Copy, Clone)]
+pub struct UnusedAttributes {
+    builtin_attributes: &'static FxHashMap<Symbol, &'static BuiltinAttribute>,
+}
+
+impl UnusedAttributes {
+    pub fn new() -> Self {
+        UnusedAttributes {
+            builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP,
+        }
+    }
+}
+
+impl_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
     fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
         debug!("checking attribute: {:?}", attr);
-        // Note that check_name() marks the attribute as used if it matches.
-        for &(name, ty, ..) in BUILTIN_ATTRIBUTES {
+
+        let attr_info = attr.ident().and_then(|ident| self.builtin_attributes.get(&ident.name));
+
+        if let Some(&&(name, ty, ..)) = attr_info {
             match ty {
-                AttributeType::Whitelisted if attr.check_name(name) => {
+                AttributeType::Whitelisted => {
                     debug!("{:?} is Whitelisted", name);
-                    break;
+                    return;
                 }
                 _ => (),
             }
@@ -239,11 +256,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
             debug!("Emitting warning for: {:?}", attr);
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
             // Is it a builtin attribute that must be used at the crate level?
-            let known_crate = BUILTIN_ATTRIBUTES.iter()
-                .find(|&&(builtin, ty, ..)| {
-                    name == builtin && ty == AttributeType::CrateLevel
-                })
-                .is_some();
+            let known_crate = attr_info.map(|&&(_, ty, ..)| {
+                    ty == AttributeType::CrateLevel
+            }).unwrap_or(false);
 
             // Has a plugin registered this attribute as one that must be used at
             // the crate level?
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 64f652d6eeb..cb0cfd93a60 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -360,8 +360,8 @@ impl<'a> Resolver<'a> {
 
         let attr_candidates = BUILTIN_ATTRIBUTES
             .iter()
-            .filter_map(|(name, _, _, gate)| {
-                if name.starts_with("rustc_") && !features.rustc_attrs {
+            .filter_map(|&(name, _, _, ref gate)| {
+                if name.as_str().starts_with("rustc_") && !features.rustc_attrs {
                     return None;
                 }
 
@@ -376,7 +376,6 @@ impl<'a> Resolver<'a> {
                     _ => None,
                 }
             })
-            .map(|name| Symbol::intern(name))
             .chain(
                 // Add built-in macro attributes as well.
                 self.builtin_macros.iter().filter_map(|(name, binding)| {
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 71c2ab82f65..b48f3c9b8b8 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -14,8 +14,10 @@ bitflags = "1.0"
 serialize = { path = "../libserialize" }
 log = "0.4"
 scoped-tls = "1.0"
+lazy_static = "1.0.0"
 syntax_pos = { path = "../libsyntax_pos" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ba4380416fb..c8b020d8c0b 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -30,6 +30,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::{Span, DUMMY_SP, symbols};
 use log::debug;
+use lazy_static::lazy_static;
 
 use std::env;
 
@@ -811,406 +812,473 @@ macro_rules! cfg_fn {
     }}
 }
 
-pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType,
+pub fn deprecated_attributes() -> Vec<&'static (Symbol, AttributeType,
                                                 AttributeTemplate, AttributeGate)> {
     BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect()
 }
 
 pub fn is_builtin_attr_name(name: ast::Name) -> bool {
-    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, ..)| name == builtin_name)
+    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
 }
 
 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
-    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, ..)| attr.path == builtin_name)
+    attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).is_some()
 }
 
-// Attributes that have a special meaning to rustc or rustdoc
-pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, AttributeGate)] = &[
+/// Attributes that have a special meaning to rustc or rustdoc
+pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Normal attributes
 
-    ("warn", Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated),
-    ("allow", Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated),
-    ("forbid", Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated),
-    ("deny", Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), Ungated),
-
-    ("macro_use", Normal, template!(Word, List: "name1, name2, ..."), Ungated),
-    ("macro_export", Normal, template!(Word, List: "local_inner_macros"), Ungated),
-    ("plugin_registrar", Normal, template!(Word), Ungated),
-
-    ("cfg", Normal, template!(List: "predicate"), Ungated),
-    ("cfg_attr", Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated),
-    ("main", Normal, template!(Word), Ungated),
-    ("start", Normal, template!(Word), Ungated),
-    ("repr", Normal, template!(List: "C, packed, ..."), Ungated),
-    ("path", Normal, template!(NameValueStr: "file"), Ungated),
-    ("automatically_derived", Normal, template!(Word), Ungated),
-    ("no_mangle", Normal, template!(Word), Ungated),
-    ("no_link", Normal, template!(Word), Ungated),
-    ("derive", Normal, template!(List: "Trait1, Trait2, ..."), Ungated),
-    ("should_panic", Normal, template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"),
-                                Ungated),
-    ("ignore", Normal, template!(Word, NameValueStr: "reason"), Ungated),
-    ("no_implicit_prelude", Normal, template!(Word), Ungated),
-    ("reexport_test_harness_main", Normal, template!(NameValueStr: "name"), Ungated),
-    ("link_args", Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable,
+    (
+        symbols::warn,
+        Normal,
+        template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+        Ungated
+    ),
+    (
+        symbols::allow,
+        Normal,
+        template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+        Ungated
+    ),
+    (
+        symbols::forbid,
+        Normal,
+        template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+        Ungated
+    ),
+    (
+        symbols::deny,
+        Normal,
+        template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+        Ungated
+    ),
+
+    (symbols::macro_use, Normal, template!(Word, List: "name1, name2, ..."), Ungated),
+    (symbols::macro_export, Normal, template!(Word, List: "local_inner_macros"), Ungated),
+    (symbols::plugin_registrar, Normal, template!(Word), Ungated),
+
+    (symbols::cfg, Normal, template!(List: "predicate"), Ungated),
+    (symbols::cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), Ungated),
+    (symbols::main, Normal, template!(Word), Ungated),
+    (symbols::start, Normal, template!(Word), Ungated),
+    (symbols::repr, Normal, template!(List: "C, packed, ..."), Ungated),
+    (symbols::path, Normal, template!(NameValueStr: "file"), Ungated),
+    (symbols::automatically_derived, Normal, template!(Word), Ungated),
+    (symbols::no_mangle, Normal, template!(Word), Ungated),
+    (symbols::no_link, Normal, template!(Word), Ungated),
+    (symbols::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated),
+    (
+        symbols::should_panic,
+        Normal,
+        template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"),
+        Ungated
+    ),
+    (symbols::ignore, Normal, template!(Word, NameValueStr: "reason"), Ungated),
+    (symbols::no_implicit_prelude, Normal, template!(Word), Ungated),
+    (symbols::reexport_test_harness_main, Normal, template!(NameValueStr: "name"), Ungated),
+    (symbols::link_args, Normal, template!(NameValueStr: "args"), Gated(Stability::Unstable,
                                 "link_args",
                                 "the `link_args` attribute is experimental and not \
-                                 portable across platforms, it is recommended to \
-                                 use `#[link(name = \"foo\")] instead",
+                                portable across platforms, it is recommended to \
+                                use `#[link(name = \"foo\")] instead",
                                 cfg_fn!(link_args))),
-    ("macro_escape", Normal, template!(Word), Ungated),
+    (symbols::macro_escape, Normal, template!(Word), Ungated),
 
     // RFC #1445.
-    ("structural_match", Whitelisted, template!(Word), Gated(Stability::Unstable,
+    (symbols::structural_match, Whitelisted, template!(Word), Gated(Stability::Unstable,
                                             "structural_match",
                                             "the semantics of constant patterns is \
-                                             not yet settled",
+                                            not yet settled",
                                             cfg_fn!(structural_match))),
 
     // RFC #2008
-    ("non_exhaustive", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                          "non_exhaustive",
-                                          "non exhaustive is an experimental feature",
-                                          cfg_fn!(non_exhaustive))),
+    (symbols::non_exhaustive, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                        "non_exhaustive",
+                                        "non exhaustive is an experimental feature",
+                                        cfg_fn!(non_exhaustive))),
 
     // RFC #1268
-    ("marker", Normal, template!(Word), Gated(Stability::Unstable,
-                             "marker_trait_attr",
-                             "marker traits is an experimental feature",
-                             cfg_fn!(marker_trait_attr))),
-
-    ("plugin", CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable,
-                                 "plugin",
-                                 "compiler plugins are experimental \
-                                  and possibly buggy",
-                                 cfg_fn!(plugin))),
-
-    ("no_std", CrateLevel, template!(Word), Ungated),
-    ("no_core", CrateLevel, template!(Word), Gated(Stability::Unstable,
-                                  "no_core",
-                                  "no_core is experimental",
-                                  cfg_fn!(no_core))),
-    ("lang", Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable,
-                           "lang_items",
-                           "language items are subject to change",
-                           cfg_fn!(lang_items))),
-    ("linkage", Whitelisted, template!(NameValueStr: "external|internal|..."),
-                                   Gated(Stability::Unstable,
-                                   "linkage",
-                                   "the `linkage` attribute is experimental \
+    (symbols::marker, Normal, template!(Word), Gated(Stability::Unstable,
+                            "marker_trait_attr",
+                            "marker traits is an experimental feature",
+                            cfg_fn!(marker_trait_attr))),
+
+    (symbols::plugin, CrateLevel, template!(List: "name|name(args)"), Gated(Stability::Unstable,
+                                "plugin",
+                                "compiler plugins are experimental \
+                                and possibly buggy",
+                                cfg_fn!(plugin))),
+
+    (symbols::no_std, CrateLevel, template!(Word), Ungated),
+    (symbols::no_core, CrateLevel, template!(Word), Gated(Stability::Unstable,
+                                "no_core",
+                                "no_core is experimental",
+                                cfg_fn!(no_core))),
+    (symbols::lang, Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable,
+                        "lang_items",
+                        "language items are subject to change",
+                        cfg_fn!(lang_items))),
+    (symbols::linkage, Whitelisted, template!(NameValueStr: "external|internal|..."),
+                                Gated(Stability::Unstable,
+                                "linkage",
+                                "the `linkage` attribute is experimental \
                                     and not portable across platforms",
-                                   cfg_fn!(linkage))),
-    ("thread_local", Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                cfg_fn!(linkage))),
+    (symbols::thread_local, Whitelisted, template!(Word), Gated(Stability::Unstable,
                                         "thread_local",
                                         "`#[thread_local]` is an experimental feature, and does \
                                          not currently handle destructors",
                                         cfg_fn!(thread_local))),
 
-    ("rustc_on_unimplemented", Whitelisted, template!(List:
-                          r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
-                          NameValueStr: "message"),
-                                             Gated(Stability::Unstable,
-                                             "on_unimplemented",
-                                             "the `#[rustc_on_unimplemented]` attribute \
-                                              is an experimental feature",
-                                             cfg_fn!(on_unimplemented))),
-    ("rustc_const_unstable", Normal, template!(List: r#"feature = "name""#),
-                                             Gated(Stability::Unstable,
-                                             "rustc_const_unstable",
-                                             "the `#[rustc_const_unstable]` attribute \
-                                              is an internal feature",
-                                             cfg_fn!(rustc_const_unstable))),
-    ("global_allocator", Normal, template!(Word), Ungated),
-    ("default_lib_allocator", Whitelisted, template!(Word), Gated(Stability::Unstable,
+    (symbols::rustc_on_unimplemented, Whitelisted, template!(List:
+                        r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
+                        NameValueStr: "message"),
+                                            Gated(Stability::Unstable,
+                                            "on_unimplemented",
+                                            "the `#[rustc_on_unimplemented]` attribute \
+                                            is an experimental feature",
+                                            cfg_fn!(on_unimplemented))),
+    (symbols::rustc_const_unstable, Normal, template!(List: r#"feature = "name""#),
+                                            Gated(Stability::Unstable,
+                                            "rustc_const_unstable",
+                                            "the `#[rustc_const_unstable]` attribute \
+                                            is an internal feature",
+                                            cfg_fn!(rustc_const_unstable))),
+    (symbols::global_allocator, Normal, template!(Word), Ungated),
+    (symbols::default_lib_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable,
                                             "allocator_internals",
                                             "the `#[default_lib_allocator]` \
-                                             attribute is an experimental feature",
+                                            attribute is an experimental feature",
                                             cfg_fn!(allocator_internals))),
-    ("needs_allocator", Normal, template!(Word), Gated(Stability::Unstable,
-                                      "allocator_internals",
-                                      "the `#[needs_allocator]` \
-                                       attribute is an experimental \
-                                       feature",
-                                      cfg_fn!(allocator_internals))),
-    ("panic_runtime", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                         "panic_runtime",
-                                         "the `#[panic_runtime]` attribute is \
-                                          an experimental feature",
-                                         cfg_fn!(panic_runtime))),
-    ("needs_panic_runtime", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                               "needs_panic_runtime",
-                                               "the `#[needs_panic_runtime]` \
+    (symbols::needs_allocator, Normal, template!(Word), Gated(Stability::Unstable,
+                                    "allocator_internals",
+                                    "the `#[needs_allocator]` \
+                                    attribute is an experimental \
+                                    feature",
+                                    cfg_fn!(allocator_internals))),
+    (symbols::panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                        "panic_runtime",
+                                        "the `#[panic_runtime]` attribute is \
+                                        an experimental feature",
+                                        cfg_fn!(panic_runtime))),
+    (symbols::needs_panic_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                            "needs_panic_runtime",
+                                            "the `#[needs_panic_runtime]` \
                                                 attribute is an experimental \
                                                 feature",
-                                               cfg_fn!(needs_panic_runtime))),
-    ("rustc_outlives", Normal, template!(Word), Gated(Stability::Unstable,
-                                     "rustc_attrs",
-                                     "the `#[rustc_outlives]` attribute \
-                                      is just used for rustc unit tests \
-                                      and will never be stable",
-                                     cfg_fn!(rustc_attrs))),
-    ("rustc_variance", Normal, template!(Word), Gated(Stability::Unstable,
-                                     "rustc_attrs",
-                                     "the `#[rustc_variance]` attribute \
-                                      is just used for rustc unit tests \
-                                      and will never be stable",
-                                     cfg_fn!(rustc_attrs))),
-    ("rustc_layout", Normal, template!(List: "field1, field2, ..."),
-     Gated(Stability::Unstable,
-           "rustc_attrs",
-           "the `#[rustc_layout]` attribute \
+                                            cfg_fn!(needs_panic_runtime))),
+    (symbols::rustc_outlives, Normal, template!(Word), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_outlives]` attribute \
+                                    is just used for rustc unit tests \
+                                    and will never be stable",
+                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_variance, Normal, template!(Word), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_variance]` attribute \
+                                    is just used for rustc unit tests \
+                                    and will never be stable",
+                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_layout, Normal, template!(List: "field1, field2, ..."),
+    Gated(Stability::Unstable,
+        "rustc_attrs",
+        "the `#[rustc_layout]` attribute \
             is just used for rustc unit tests \
             and will never be stable",
-           cfg_fn!(rustc_attrs))),
-    ("rustc_layout_scalar_valid_range_start", Whitelisted, template!(List: "value"),
-     Gated(Stability::Unstable,
-           "rustc_attrs",
-           "the `#[rustc_layout_scalar_valid_range_start]` attribute \
+        cfg_fn!(rustc_attrs))),
+    (symbols::rustc_layout_scalar_valid_range_start, Whitelisted, template!(List: "value"),
+    Gated(Stability::Unstable,
+        "rustc_attrs",
+        "the `#[rustc_layout_scalar_valid_range_start]` attribute \
             is just used to enable niche optimizations in libcore \
             and will never be stable",
-           cfg_fn!(rustc_attrs))),
-    ("rustc_layout_scalar_valid_range_end", Whitelisted, template!(List: "value"),
-     Gated(Stability::Unstable,
-           "rustc_attrs",
-           "the `#[rustc_layout_scalar_valid_range_end]` attribute \
+        cfg_fn!(rustc_attrs))),
+    (symbols::rustc_layout_scalar_valid_range_end, Whitelisted, template!(List: "value"),
+    Gated(Stability::Unstable,
+        "rustc_attrs",
+        "the `#[rustc_layout_scalar_valid_range_end]` attribute \
             is just used to enable niche optimizations in libcore \
             and will never be stable",
-           cfg_fn!(rustc_attrs))),
-    ("rustc_regions", Normal, template!(Word), Gated(Stability::Unstable,
+        cfg_fn!(rustc_attrs))),
+    (symbols::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable,
                                     "rustc_attrs",
                                     "the `#[rustc_regions]` attribute \
-                                     is just used for rustc unit tests \
-                                     and will never be stable",
+                                    is just used for rustc unit tests \
+                                    and will never be stable",
                                     cfg_fn!(rustc_attrs))),
-    ("rustc_error", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                       "rustc_attrs",
-                                       "the `#[rustc_error]` attribute \
+    (symbols::rustc_error, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_error]` attribute \
                                         is just used for rustc unit tests \
                                         and will never be stable",
-                                       cfg_fn!(rustc_attrs))),
-    ("rustc_dump_user_substs", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                       "rustc_attrs",
-                                       "this attribute \
+                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_dump_user_substs, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "this attribute \
                                         is just used for rustc unit tests \
                                         and will never be stable",
-                                       cfg_fn!(rustc_attrs))),
-    ("rustc_if_this_changed", Whitelisted, template!(Word, List: "DepNode"),
-                                                 Gated(Stability::Unstable,
-                                                 "rustc_attrs",
-                                                 "the `#[rustc_if_this_changed]` attribute \
-                                                  is just used for rustc unit tests \
-                                                  and will never be stable",
-                                                 cfg_fn!(rustc_attrs))),
-    ("rustc_then_this_would_need", Whitelisted, template!(List: "DepNode"),
-                                                      Gated(Stability::Unstable,
-                                                      "rustc_attrs",
-                                                      "the `#[rustc_if_this_changed]` attribute \
-                                                       is just used for rustc unit tests \
-                                                       and will never be stable",
-                                                      cfg_fn!(rustc_attrs))),
-    ("rustc_dirty", Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
+                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode"),
+                                                Gated(Stability::Unstable,
+                                                "rustc_attrs",
+                                                "the `#[rustc_if_this_changed]` attribute \
+                                                is just used for rustc unit tests \
+                                                and will never be stable",
+                                                cfg_fn!(rustc_attrs))),
+    (symbols::rustc_then_this_would_need, Whitelisted, template!(List: "DepNode"),
+                                                    Gated(Stability::Unstable,
+                                                    "rustc_attrs",
+                                                    "the `#[rustc_if_this_changed]` attribute \
+                                                    is just used for rustc unit tests \
+                                                    and will never be stable",
+                                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
                                                     /*opt*/ except = "...""#),
-                                       Gated(Stability::Unstable,
-                                       "rustc_attrs",
-                                       "the `#[rustc_dirty]` attribute \
+                                    Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_dirty]` attribute \
                                         is just used for rustc unit tests \
                                         and will never be stable",
-                                       cfg_fn!(rustc_attrs))),
-    ("rustc_clean", Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
+                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
                                                     /*opt*/ except = "...""#),
-                                       Gated(Stability::Unstable,
-                                       "rustc_attrs",
-                                       "the `#[rustc_clean]` attribute \
+                                    Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_clean]` attribute \
                                         is just used for rustc unit tests \
                                         and will never be stable",
-                                       cfg_fn!(rustc_attrs))),
-    ("rustc_partition_reused", Whitelisted, template!(List: r#"cfg = "...", module = "...""#),
-                                                  Gated(Stability::Unstable,
-                                                  "rustc_attrs",
-                                                  "this attribute \
-                                                   is just used for rustc unit tests \
-                                                   and will never be stable",
-                                                  cfg_fn!(rustc_attrs))),
-    ("rustc_partition_codegened", Whitelisted, template!(List: r#"cfg = "...", module = "...""#),
-                                                      Gated(Stability::Unstable,
-                                                      "rustc_attrs",
-                                                      "this attribute \
-                                                       is just used for rustc unit tests \
-                                                       and will never be stable",
-                                                      cfg_fn!(rustc_attrs))),
-    ("rustc_expected_cgu_reuse", Whitelisted, template!(List: r#"cfg = "...", module = "...",
-                                                              kind = "...""#),
+                                    cfg_fn!(rustc_attrs))),
+    (
+        symbols::rustc_partition_reused,
+        Whitelisted,
+        template!(List: r#"cfg = "...", module = "...""#),
+        Gated(
+            Stability::Unstable,
+            "rustc_attrs",
+            "this attribute \
+            is just used for rustc unit tests \
+            and will never be stable",
+            cfg_fn!(rustc_attrs)
+        )
+    ),
+    (
+        symbols::rustc_partition_codegened,
+        Whitelisted,
+        template!(List: r#"cfg = "...", module = "...""#),
+        Gated(
+            Stability::Unstable,
+            "rustc_attrs",
+            "this attribute \
+            is just used for rustc unit tests \
+            and will never be stable",
+            cfg_fn!(rustc_attrs),
+        )
+    ),
+    (symbols::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...",
+                                                            kind = "...""#),
                                                     Gated(Stability::Unstable,
                                                     "rustc_attrs",
                                                     "this attribute \
-                                                     is just used for rustc unit tests \
-                                                     and will never be stable",
+                                                    is just used for rustc unit tests \
+                                                    and will never be stable",
+                                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_synthetic, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                                    "rustc_attrs",
+                                                    "this attribute \
+                                                    is just used for rustc unit tests \
+                                                    and will never be stable",
+                                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_symbol_name, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                            "rustc_attrs",
+                                            "internal rustc attributes will never be stable",
+                                            cfg_fn!(rustc_attrs))),
+    (symbols::rustc_def_path, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                        "rustc_attrs",
+                                        "internal rustc attributes will never be stable",
+                                        cfg_fn!(rustc_attrs))),
+    (symbols::rustc_mir, Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_mir]` attribute \
+                                    is just used for rustc unit tests \
+                                    and will never be stable",
+                                    cfg_fn!(rustc_attrs))),
+    (
+        symbols::rustc_inherit_overflow_checks,
+        Whitelisted,
+        template!(Word),
+        Gated(
+            Stability::Unstable,
+            "rustc_attrs",
+            "the `#[rustc_inherit_overflow_checks]` \
+            attribute is just used to control \
+            overflow checking behavior of several \
+            libcore functions that are inlined \
+            across crates and will never be stable",
+            cfg_fn!(rustc_attrs),
+        )
+    ),
+
+    (symbols::rustc_dump_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                                    "rustc_attrs",
+                                                    "the `#[rustc_dump_program_clauses]` \
+                                                    attribute is just used for rustc unit \
+                                                    tests and will never be stable",
                                                     cfg_fn!(rustc_attrs))),
-    ("rustc_synthetic", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                      "rustc_attrs",
-                                                      "this attribute \
-                                                       is just used for rustc unit tests \
-                                                       and will never be stable",
-                                                      cfg_fn!(rustc_attrs))),
-    ("rustc_symbol_name", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                             "rustc_attrs",
-                                             "internal rustc attributes will never be stable",
-                                             cfg_fn!(rustc_attrs))),
-    ("rustc_def_path", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                           "rustc_attrs",
-                                           "internal rustc attributes will never be stable",
-                                           cfg_fn!(rustc_attrs))),
-    ("rustc_mir", Whitelisted, template!(List: "arg1, arg2, ..."), Gated(Stability::Unstable,
-                                     "rustc_attrs",
-                                     "the `#[rustc_mir]` attribute \
-                                      is just used for rustc unit tests \
-                                      and will never be stable",
-                                     cfg_fn!(rustc_attrs))),
-    ("rustc_inherit_overflow_checks", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                         "rustc_attrs",
-                                                         "the `#[rustc_inherit_overflow_checks]` \
-                                                          attribute is just used to control \
-                                                          overflow checking behavior of several \
-                                                          libcore functions that are inlined \
-                                                          across crates and will never be stable",
-                                                          cfg_fn!(rustc_attrs))),
-
-    ("rustc_dump_program_clauses", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                     "rustc_attrs",
-                                                     "the `#[rustc_dump_program_clauses]` \
-                                                      attribute is just used for rustc unit \
-                                                      tests and will never be stable",
-                                                     cfg_fn!(rustc_attrs))),
-    ("rustc_test_marker", Normal, template!(Word), Gated(Stability::Unstable,
-                                     "rustc_attrs",
-                                     "the `#[rustc_test_marker]` attribute \
-                                      is used internally to track tests",
-                                     cfg_fn!(rustc_attrs))),
-    ("rustc_transparent_macro", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                   "rustc_attrs",
-                                                   "used internally for testing macro hygiene",
+    (symbols::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_test_marker]` attribute \
+                                    is used internally to track tests",
+                                    cfg_fn!(rustc_attrs))),
+    (symbols::rustc_transparent_macro, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                                "rustc_attrs",
+                                                "used internally for testing macro hygiene",
                                                     cfg_fn!(rustc_attrs))),
-    ("compiler_builtins", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                             "compiler_builtins",
-                                             "the `#[compiler_builtins]` attribute is used to \
-                                              identify the `compiler_builtins` crate which \
-                                              contains compiler-rt intrinsics and will never be \
-                                              stable",
-                                          cfg_fn!(compiler_builtins))),
-    ("sanitizer_runtime", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                             "sanitizer_runtime",
-                                             "the `#[sanitizer_runtime]` attribute is used to \
-                                              identify crates that contain the runtime of a \
-                                              sanitizer and will never be stable",
-                                             cfg_fn!(sanitizer_runtime))),
-    ("profiler_runtime", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                             "profiler_runtime",
-                                             "the `#[profiler_runtime]` attribute is used to \
-                                              identify the `profiler_builtins` crate which \
-                                              contains the profiler runtime and will never be \
-                                              stable",
-                                             cfg_fn!(profiler_runtime))),
-
-    ("allow_internal_unstable", Normal, template!(Word, List: "feat1, feat2, ..."),
-                                              Gated(Stability::Unstable,
-                                              "allow_internal_unstable",
-                                              EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
-                                              cfg_fn!(allow_internal_unstable))),
-
-    ("allow_internal_unsafe", Normal, template!(Word), Gated(Stability::Unstable,
+    (symbols::compiler_builtins, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                            "compiler_builtins",
+                                            "the `#[compiler_builtins]` attribute is used to \
+                                            identify the `compiler_builtins` crate which \
+                                            contains compiler-rt intrinsics and will never be \
+                                            stable",
+                                        cfg_fn!(compiler_builtins))),
+    (symbols::sanitizer_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                            "sanitizer_runtime",
+                                            "the `#[sanitizer_runtime]` attribute is used to \
+                                            identify crates that contain the runtime of a \
+                                            sanitizer and will never be stable",
+                                            cfg_fn!(sanitizer_runtime))),
+    (symbols::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                            "profiler_runtime",
+                                            "the `#[profiler_runtime]` attribute is used to \
+                                            identify the `profiler_builtins` crate which \
+                                            contains the profiler runtime and will never be \
+                                            stable",
+                                            cfg_fn!(profiler_runtime))),
+
+    (symbols::allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
+                                            Gated(Stability::Unstable,
+                                            "allow_internal_unstable",
+                                            EXPLAIN_ALLOW_INTERNAL_UNSTABLE,
+                                            cfg_fn!(allow_internal_unstable))),
+
+    (symbols::allow_internal_unsafe, Normal, template!(Word), Gated(Stability::Unstable,
                                             "allow_internal_unsafe",
                                             EXPLAIN_ALLOW_INTERNAL_UNSAFE,
                                             cfg_fn!(allow_internal_unsafe))),
 
-    ("fundamental", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                       "fundamental",
-                                       "the `#[fundamental]` attribute \
+    (symbols::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                    "fundamental",
+                                    "the `#[fundamental]` attribute \
                                         is an experimental feature",
-                                       cfg_fn!(fundamental))),
+                                    cfg_fn!(fundamental))),
 
-    ("proc_macro_derive", Normal, template!(List: "TraitName, \
-                                                   /*opt*/ attributes(name1, name2, ...)"),
-                                       Ungated),
+    (symbols::proc_macro_derive, Normal, template!(List: "TraitName, \
+                                                /*opt*/ attributes(name1, name2, ...)"),
+                                    Ungated),
 
-    ("rustc_copy_clone_marker", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                   "rustc_attrs",
-                                                   "internal implementation detail",
-                                                   cfg_fn!(rustc_attrs))),
+    (symbols::rustc_copy_clone_marker, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                                "rustc_attrs",
+                                                "internal implementation detail",
+                                                cfg_fn!(rustc_attrs))),
 
     // FIXME: #14408 whitelist docs since rustdoc looks at them
-    ("doc", Whitelisted, template!(List: "hidden|inline|...", NameValueStr: "string"), Ungated),
+    (
+        symbols::doc,
+        Whitelisted,
+        template!(List: "hidden|inline|...", NameValueStr: "string"),
+        Ungated
+    ),
 
     // FIXME: #14406 these are processed in codegen, which happens after the
     // lint pass
-    ("cold", Whitelisted, template!(Word), Ungated),
-    ("naked", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                 "naked_functions",
-                                 "the `#[naked]` attribute \
-                                  is an experimental feature",
-                                 cfg_fn!(naked_functions))),
-    ("ffi_returns_twice", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                 "ffi_returns_twice",
-                                 "the `#[ffi_returns_twice]` attribute \
-                                  is an experimental feature",
-                                 cfg_fn!(ffi_returns_twice))),
-    ("target_feature", Whitelisted, template!(List: r#"enable = "name""#), Ungated),
-    ("export_name", Whitelisted, template!(NameValueStr: "name"), Ungated),
-    ("inline", Whitelisted, template!(Word, List: "always|never"), Ungated),
-    ("link", Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...",
-                                             /*opt*/ cfg = "...""#), Ungated),
-    ("link_name", Whitelisted, template!(NameValueStr: "name"), Ungated),
-    ("link_section", Whitelisted, template!(NameValueStr: "name"), Ungated),
-    ("no_builtins", Whitelisted, template!(Word), Ungated),
-    ("no_mangle", Whitelisted, template!(Word), Ungated),
-    ("no_debug", Whitelisted, template!(Word), Gated(
+    (symbols::cold, Whitelisted, template!(Word), Ungated),
+    (symbols::naked, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                "naked_functions",
+                                "the `#[naked]` attribute \
+                                is an experimental feature",
+                                cfg_fn!(naked_functions))),
+    (symbols::ffi_returns_twice, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                "ffi_returns_twice",
+                                "the `#[ffi_returns_twice]` attribute \
+                                is an experimental feature",
+                                cfg_fn!(ffi_returns_twice))),
+    (symbols::target_feature, Whitelisted, template!(List: r#"enable = "name""#), Ungated),
+    (symbols::export_name, Whitelisted, template!(NameValueStr: "name"), Ungated),
+    (symbols::inline, Whitelisted, template!(Word, List: "always|never"), Ungated),
+    (symbols::link, Whitelisted, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...",
+                                               /*opt*/ cfg = "...""#), Ungated),
+    (symbols::link_name, Whitelisted, template!(NameValueStr: "name"), Ungated),
+    (symbols::link_section, Whitelisted, template!(NameValueStr: "name"), Ungated),
+    (symbols::no_builtins, Whitelisted, template!(Word), Ungated),
+    (symbols::no_debug, Whitelisted, template!(Word), Gated(
         Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None),
         "no_debug",
         "the `#[no_debug]` attribute was an experimental feature that has been \
-         deprecated due to lack of demand",
+        deprecated due to lack of demand",
         cfg_fn!(no_debug))),
-    ("omit_gdb_pretty_printer_section", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                       "omit_gdb_pretty_printer_section",
-                                                       "the `#[omit_gdb_pretty_printer_section]` \
-                                                        attribute is just used for the Rust test \
-                                                        suite",
-                                                       cfg_fn!(omit_gdb_pretty_printer_section))),
-    ("unsafe_destructor_blind_to_params",
-     Normal,
-     template!(Word),
-     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761",
-                                 Some("replace this attribute with `#[may_dangle]`")),
-           "dropck_parametricity",
-           "unsafe_destructor_blind_to_params has been replaced by \
+    (
+        symbols::omit_gdb_pretty_printer_section,
+        Whitelisted,
+        template!(Word),
+        Gated(
+            Stability::Unstable,
+            "omit_gdb_pretty_printer_section",
+            "the `#[omit_gdb_pretty_printer_section]` \
+                attribute is just used for the Rust test \
+                suite",
+            cfg_fn!(omit_gdb_pretty_printer_section)
+        )
+    ),
+    (symbols::unsafe_destructor_blind_to_params,
+    Normal,
+    template!(Word),
+    Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761",
+                                Some("replace this attribute with `#[may_dangle]`")),
+        "dropck_parametricity",
+        "unsafe_destructor_blind_to_params has been replaced by \
             may_dangle and will be removed in the future",
-           cfg_fn!(dropck_parametricity))),
-    ("may_dangle",
-     Normal,
-     template!(Word),
-     Gated(Stability::Unstable,
-           "dropck_eyepatch",
-           "may_dangle has unstable semantics and may be removed in the future",
-           cfg_fn!(dropck_eyepatch))),
-    ("unwind", Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
-                                  "unwind_attributes",
-                                  "#[unwind] is experimental",
-                                  cfg_fn!(unwind_attributes))),
-    ("used", Whitelisted, template!(Word), Ungated),
+        cfg_fn!(dropck_parametricity))),
+    (symbols::may_dangle,
+    Normal,
+    template!(Word),
+    Gated(Stability::Unstable,
+        "dropck_eyepatch",
+        "may_dangle has unstable semantics and may be removed in the future",
+        cfg_fn!(dropck_eyepatch))),
+    (symbols::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
+                                "unwind_attributes",
+                                "#[unwind] is experimental",
+                                cfg_fn!(unwind_attributes))),
+    (symbols::used, Whitelisted, template!(Word), Ungated),
 
     // used in resolve
-    ("prelude_import", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                          "prelude_import",
-                                          "`#[prelude_import]` is for use by rustc only",
-                                          cfg_fn!(prelude_import))),
+    (symbols::prelude_import, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                        "prelude_import",
+                                        "`#[prelude_import]` is for use by rustc only",
+                                        cfg_fn!(prelude_import))),
 
     // FIXME: #14407 these are only looked at on-demand so we can't
     // guarantee they'll have already been checked
-    ("rustc_deprecated", Whitelisted, template!(List: r#"since = "version", reason = "...""#),
-                                        Ungated),
-    ("must_use", Whitelisted, template!(Word, NameValueStr: "reason"), Ungated),
-    ("stable", Whitelisted, template!(List: r#"feature = "name", since = "version""#), Ungated),
-    ("unstable", Whitelisted, template!(List: r#"feature = "name", reason = "...", issue = "N""#),
-                                        Ungated),
-    ("deprecated",
+    (
+        symbols::rustc_deprecated,
+        Whitelisted,
+        template!(List: r#"since = "version", reason = "...""#),
+        Ungated
+    ),
+    (symbols::must_use, Whitelisted, template!(Word, NameValueStr: "reason"), Ungated),
+    (
+        symbols::stable,
+        Whitelisted,
+        template!(List: r#"feature = "name", since = "version""#),
+        Ungated
+    ),
+    (
+        symbols::unstable,
+        Whitelisted,
+        template!(List: r#"feature = "name", reason = "...", issue = "N""#),
+        Ungated
+    ),
+    (symbols::deprecated,
         Normal,
         template!(
             Word,
@@ -1220,73 +1288,88 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
         Ungated
     ),
 
-    ("rustc_paren_sugar", Normal, template!(Word), Gated(Stability::Unstable,
+    (symbols::rustc_paren_sugar, Normal, template!(Word), Gated(Stability::Unstable,
                                         "unboxed_closures",
                                         "unboxed_closures are still evolving",
                                         cfg_fn!(unboxed_closures))),
 
-    ("windows_subsystem", Whitelisted, template!(NameValueStr: "windows|console"), Ungated),
+    (symbols::windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console"), Ungated),
 
-    ("proc_macro_attribute", Normal, template!(Word), Ungated),
-    ("proc_macro", Normal, template!(Word), Ungated),
+    (symbols::proc_macro_attribute, Normal, template!(Word), Ungated),
+    (symbols::proc_macro, Normal, template!(Word), Ungated),
 
-    ("rustc_proc_macro_decls", Normal, template!(Word), Gated(Stability::Unstable,
-                                             "rustc_attrs",
-                                             "used internally by rustc",
-                                             cfg_fn!(rustc_attrs))),
+    (symbols::rustc_proc_macro_decls, Normal, template!(Word), Gated(Stability::Unstable,
+                                            "rustc_attrs",
+                                            "used internally by rustc",
+                                            cfg_fn!(rustc_attrs))),
 
-    ("allow_fail", Normal, template!(Word), Gated(Stability::Unstable,
-                                 "allow_fail",
-                                 "allow_fail attribute is currently unstable",
-                                 cfg_fn!(allow_fail))),
+    (symbols::allow_fail, Normal, template!(Word), Gated(Stability::Unstable,
+                                "allow_fail",
+                                "allow_fail attribute is currently unstable",
+                                cfg_fn!(allow_fail))),
 
-    ("rustc_std_internal_symbol", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                     "rustc_attrs",
-                                     "this is an internal attribute that will \
-                                      never be stable",
-                                     cfg_fn!(rustc_attrs))),
+    (symbols::rustc_std_internal_symbol, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "this is an internal attribute that will \
+                                    never be stable",
+                                    cfg_fn!(rustc_attrs))),
 
     // whitelists "identity-like" conversion methods to suggest on type mismatch
-    ("rustc_conversion_suggestion", Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                       "rustc_attrs",
-                                                       "this is an internal attribute that will \
+    (symbols::rustc_conversion_suggestion, Whitelisted, template!(Word), Gated(Stability::Unstable,
+                                                    "rustc_attrs",
+                                                    "this is an internal attribute that will \
                                                         never be stable",
-                                                       cfg_fn!(rustc_attrs))),
+                                                    cfg_fn!(rustc_attrs))),
 
-    ("rustc_args_required_const", Whitelisted, template!(List: "N"), Gated(Stability::Unstable,
-                                 "rustc_attrs",
-                                 "never will be stable",
-                                 cfg_fn!(rustc_attrs))),
+    (
+        symbols::rustc_args_required_const,
+        Whitelisted,
+        template!(List: "N"),
+        Gated(Stability::Unstable, "rustc_attrs", "never will be stable", cfg_fn!(rustc_attrs))
+    ),
     // RFC 2070
-    ("panic_handler", Normal, template!(Word), Ungated),
+    (symbols::panic_handler, Normal, template!(Word), Ungated),
 
-    ("alloc_error_handler", Normal, template!(Word), Gated(Stability::Unstable,
-                           "alloc_error_handler",
-                           "#[alloc_error_handler] is an unstable feature",
-                           cfg_fn!(alloc_error_handler))),
+    (symbols::alloc_error_handler, Normal, template!(Word), Gated(Stability::Unstable,
+                        "alloc_error_handler",
+                        "#[alloc_error_handler] is an unstable feature",
+                        cfg_fn!(alloc_error_handler))),
 
     // RFC 2412
-    ("optimize", Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable,
-                               "optimize_attribute",
-                               "#[optimize] attribute is an unstable feature",
-                               cfg_fn!(optimize_attribute))),
+    (symbols::optimize, Whitelisted, template!(List: "size|speed"), Gated(Stability::Unstable,
+                            "optimize_attribute",
+                            "#[optimize] attribute is an unstable feature",
+                            cfg_fn!(optimize_attribute))),
 
     // Crate level attributes
-    ("crate_name", CrateLevel, template!(NameValueStr: "name"), Ungated),
-    ("crate_type", CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated),
-    ("crate_id", CrateLevel, template!(NameValueStr: "ignored"), Ungated),
-    ("feature", CrateLevel, template!(List: "name1, name1, ..."), Ungated),
-    ("no_start", CrateLevel, template!(Word), Ungated),
-    ("no_main", CrateLevel, template!(Word), Ungated),
-    ("no_builtins", CrateLevel, template!(Word), Ungated),
-    ("recursion_limit", CrateLevel, template!(NameValueStr: "N"), Ungated),
-    ("type_length_limit", CrateLevel, template!(NameValueStr: "N"), Ungated),
-    ("test_runner", CrateLevel, template!(List: "path"), Gated(Stability::Unstable,
+    (symbols::crate_name, CrateLevel, template!(NameValueStr: "name"), Ungated),
+    (symbols::crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), Ungated),
+    (symbols::crate_id, CrateLevel, template!(NameValueStr: "ignored"), Ungated),
+    (symbols::feature, CrateLevel, template!(List: "name1, name1, ..."), Ungated),
+    (symbols::no_start, CrateLevel, template!(Word), Ungated),
+    (symbols::no_main, CrateLevel, template!(Word), Ungated),
+    (symbols::recursion_limit, CrateLevel, template!(NameValueStr: "N"), Ungated),
+    (symbols::type_length_limit, CrateLevel, template!(NameValueStr: "N"), Ungated),
+    (symbols::test_runner, CrateLevel, template!(List: "path"), Gated(Stability::Unstable,
                     "custom_test_frameworks",
                     EXPLAIN_CUSTOM_TEST_FRAMEWORKS,
                     cfg_fn!(custom_test_frameworks))),
 ];
 
+pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate);
+
+lazy_static! {
+    pub static ref BUILTIN_ATTRIBUTE_MAP: FxHashMap<Symbol, &'static BuiltinAttribute> = {
+        let mut map = FxHashMap::default();
+        for attr in BUILTIN_ATTRIBUTES.iter() {
+            if map.insert(attr.0, attr).is_some() {
+                panic!("duplicate builtin attribute `{}`", attr.0);
+            }
+        }
+        map
+    };
+}
+
 // cfg(...)'s that are feature gated
 const GATED_CFGS: &[(&str, &str, fn(&Features) -> bool)] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
@@ -1353,29 +1436,31 @@ macro_rules! gate_feature {
 }
 
 impl<'a> Context<'a> {
-    fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
+    fn check_attribute(
+        &self,
+        attr: &ast::Attribute,
+        attr_info: Option<&BuiltinAttribute>,
+        is_macro: bool
+    ) {
         debug!("check_attribute(attr = {:?})", attr);
-        let name = attr.name_or_empty();
-        for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES {
-            if name == n {
-                if let Gated(_, name, desc, ref has_feature) = *gateage {
-                    if !attr.span.allows_unstable(name) {
-                        gate_feature_fn!(
-                            self, has_feature, attr.span, name, desc, GateStrength::Hard
+        if let Some(&(name, ty, _template, ref gateage)) = attr_info {
+            if let Gated(_, name, desc, ref has_feature) = *gateage {
+                if !attr.span.allows_unstable(name) {
+                    gate_feature_fn!(
+                        self, has_feature, attr.span, name, desc, GateStrength::Hard
+                    );
+                }
+            } else if name == symbols::doc {
+                if let Some(content) = attr.meta_item_list() {
+                    if content.iter().any(|c| c.check_name(symbols::include)) {
+                        gate_feature!(self, external_doc, attr.span,
+                            "#[doc(include = \"...\")] is experimental"
                         );
                     }
-                } else if n == "doc" {
-                    if let Some(content) = attr.meta_item_list() {
-                        if content.iter().any(|c| c.check_name(symbols::include)) {
-                            gate_feature!(self, external_doc, attr.span,
-                                "#[doc(include = \"...\")] is experimental"
-                            );
-                        }
-                    }
                 }
-                debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
-                return;
             }
+            debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
+            return;
         }
         for &(ref n, ref ty) in self.plugin_attributes {
             if attr.path == &**n {
@@ -1387,7 +1472,7 @@ impl<'a> Context<'a> {
             }
         }
         if !attr::is_known(attr) {
-            if name.starts_with("rustc_") {
+            if attr.name_or_empty().starts_with("rustc_") {
                 let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
                            are reserved for internal compiler diagnostics";
                 gate_feature!(self, rustc_attrs, attr.span, msg);
@@ -1405,7 +1490,11 @@ impl<'a> Context<'a> {
 
 pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
     let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
-    cx.check_attribute(attr, true);
+    cx.check_attribute(
+        attr,
+        attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)),
+        true
+    );
 }
 
 fn find_lang_feature_issue(feature: &str) -> Option<u32> {
@@ -1542,6 +1631,7 @@ pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str =
 
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
+    builtin_attributes: &'static FxHashMap<Symbol, &'static BuiltinAttribute>,
 }
 
 macro_rules! gate_feature_post {
@@ -1615,15 +1705,15 @@ impl<'a> PostExpansionVisitor<'a> {
         }
     }
 
-    fn check_builtin_attribute(&mut self, attr: &ast::Attribute, name: &str,
+    fn check_builtin_attribute(&mut self, attr: &ast::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 == "cfg";
+        let should_skip = |name| name == symbols::cfg;
         // Some of previously accepted forms were used in practice,
         // report them as warnings for now.
-        let should_warn = |name| name == "doc" || name == "ignore" ||
-                                 name == "inline" || name == "link";
+        let should_warn = |name| name == symbols::doc || name == symbols::ignore ||
+                                 name == symbols::inline || name == symbols::link;
 
         match attr.parse_meta(self.context.parse_sess) {
             Ok(meta) => if !should_skip(name) && !template.compatible(&meta.node) {
@@ -1664,8 +1754,12 @@ impl<'a> PostExpansionVisitor<'a> {
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
+        let attr_info = attr.ident().and_then(|ident| {
+            self.builtin_attributes.get(&ident.name).map(|a| *a)
+        });
+
         // check for gated attributes
-        self.context.check_attribute(attr, false);
+        self.context.check_attribute(attr, attr_info, false);
 
         if attr.check_name(symbols::doc) {
             if let Some(content) = attr.meta_item_list() {
@@ -1693,8 +1787,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             }
         }
 
-        match BUILTIN_ATTRIBUTES.iter().find(|(name, ..)| attr.path == *name) {
-            Some(&(name, _, template, _)) => self.check_builtin_attribute(attr, name, template),
+        match attr_info {
+            Some(&(name, _, template, _)) => self.check_builtin_attribute(
+                attr,
+                name,
+                template
+            ),
             None => if let Some(TokenTree::Token(_, token::Eq)) = attr.tokens.trees().next() {
                 // All key-value attributes are restricted to meta-item syntax.
                 attr.parse_meta(self.context.parse_sess).map_err(|mut err| err.emit()).ok();
@@ -2210,8 +2308,10 @@ pub fn check_crate(krate: &ast::Crate,
         parse_sess: sess,
         plugin_attributes,
     };
-
-    let visitor = &mut PostExpansionVisitor { context: &ctx };
+    let visitor = &mut PostExpansionVisitor {
+        context: &ctx,
+        builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP,
+    };
     visit::walk_crate(visitor, krate);
 }
 
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index c89bccd5afb..cdbfabae7ce 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -100,8 +100,127 @@ symbols! {
 
     // Other symbols that can be referred to with syntax_pos::symbols::*
     Other {
-        doc, cfg, masked, spotlight, alias, keyword, feature, include, simd, align, stable,
-        unstable, rustc_const_unstable,
+        alias,
+        align,
+        alloc_error_handler,
+        allow,
+        allow_fail,
+        allow_internal_unsafe,
+        allow_internal_unstable,
+        automatically_derived,
+        cfg,
+        cfg_attr,
+        cold,
+        compiler_builtins,
+        crate_id,
+        crate_name,
+        crate_type,
+        default_lib_allocator,
+        deny,
+        deprecated,
+        derive,
+        doc,
+        export_name,
+        feature,
+        ffi_returns_twice,
+        forbid,
+        fundamental,
+        global_allocator,
+        ignore,
+        include,
+        inline,
+        keyword,
+        lang,
+        link,
+        link_args,
+        link_name,
+        link_section,
+        linkage,
+        macro_escape,
+        macro_export,
+        macro_use,
+        main,
+        marker,
+        masked,
+        may_dangle,
+        must_use,
+        naked,
+        needs_allocator,
+        needs_panic_runtime,
+        no_builtins,
+        no_core,
+        no_debug,
+        no_implicit_prelude,
+        no_link,
+        no_main,
+        no_mangle,
+        no_start,
+        no_std,
+        non_exhaustive,
+        omit_gdb_pretty_printer_section,
+        optimize,
+        panic_handler,
+        panic_runtime,
+        path,
+        plugin,
+        plugin_registrar,
+        prelude_import,
+        proc_macro,
+        proc_macro_attribute,
+        proc_macro_derive,
+        profiler_runtime,
+        recursion_limit,
+        reexport_test_harness_main,
+        repr,
+        rustc_args_required_const,
+        rustc_clean,
+        rustc_const_unstable,
+        rustc_conversion_suggestion,
+        rustc_copy_clone_marker,
+        rustc_def_path,
+        rustc_deprecated,
+        rustc_dirty,
+        rustc_dump_program_clauses,
+        rustc_dump_user_substs,
+        rustc_error,
+        rustc_expected_cgu_reuse,
+        rustc_if_this_changed,
+        rustc_inherit_overflow_checks,
+        rustc_layout,
+        rustc_layout_scalar_valid_range_end,
+        rustc_layout_scalar_valid_range_start,
+        rustc_mir,
+        rustc_on_unimplemented,
+        rustc_outlives,
+        rustc_paren_sugar,
+        rustc_partition_codegened,
+        rustc_partition_reused,
+        rustc_proc_macro_decls,
+        rustc_regions,
+        rustc_std_internal_symbol,
+        rustc_symbol_name,
+        rustc_synthetic,
+        rustc_test_marker,
+        rustc_then_this_would_need,
+        rustc_transparent_macro,
+        rustc_variance,
+        sanitizer_runtime,
+        should_panic,
+        simd,
+        spotlight,
+        stable,
+        start,
+        structural_match,
+        target_feature,
+        test_runner,
+        thread_local,
+        type_length_limit,
+        unsafe_destructor_blind_to_params,
+        unstable,
+        unwind,
+        used,
+        warn,
+        windows_subsystem,
     }
 }
 
@@ -237,14 +356,6 @@ newtype_index! {
     pub struct SymbolIndex { .. }
 }
 
-// The interner is pointed to by a thread local value which is only set on the main thread
-// with parallelization is disabled. So we don't allow `Symbol` to transfer between threads
-// to avoid panics and other errors, even though it would be memory safe to do so.
-#[cfg(not(parallel_compiler))]
-impl !Send for Symbol { }
-#[cfg(not(parallel_compiler))]
-impl !Sync for Symbol { }
-
 impl Symbol {
     const fn new(n: u32) -> Self {
         Symbol(SymbolIndex::from_u32_const(n))
diff --git a/src/test/ui/malformed/malformed-regressions.stderr b/src/test/ui/malformed/malformed-regressions.stderr
index 9a81c1056ca..99a87f0c3aa 100644
--- a/src/test/ui/malformed/malformed-regressions.stderr
+++ b/src/test/ui/malformed/malformed-regressions.stderr
@@ -27,7 +27,7 @@ LL | #[inline = ""]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...",
-                                             /*opt*/ cfg = "...")]`
+                                               /*opt*/ cfg = "...")]`
   --> $DIR/malformed-regressions.rs:6:1
    |
 LL | #[link]
@@ -37,7 +37,7 @@ LL | #[link]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 warning: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...",
-                                             /*opt*/ cfg = "...")]`
+                                               /*opt*/ cfg = "...")]`
   --> $DIR/malformed-regressions.rs:7:1
    |
 LL | #[link = ""]