Preallocate BUILTIN_ATTRIBUTES symbols and use a hash map instead of looping
This commit is contained in:
parent
fcf850f34a
commit
b82ab24bbf
9 changed files with 645 additions and 417 deletions
|
@ -3356,9 +3356,11 @@ name = "syntax"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_macros 0.1.0",
|
||||
"rustc_target 0.0.0",
|
||||
"scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serialize 0.0.0",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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)| {
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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,102 +812,126 @@ 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),
|
||||
(
|
||||
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
|
||||
),
|
||||
|
||||
("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),
|
||||
(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),
|
||||
|
||||
("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::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",
|
||||
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",
|
||||
cfg_fn!(structural_match))),
|
||||
|
||||
// RFC #2008
|
||||
("non_exhaustive", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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,
|
||||
(symbols::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,
|
||||
(symbols::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,
|
||||
(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))),
|
||||
("lang", Normal, template!(NameValueStr: "name"), Gated(Stability::Unstable,
|
||||
(symbols::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|..."),
|
||||
(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,
|
||||
(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:
|
||||
(symbols::rustc_on_unimplemented, Whitelisted, template!(List:
|
||||
r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
|
||||
NameValueStr: "message"),
|
||||
Gated(Stability::Unstable,
|
||||
|
@ -914,101 +939,101 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
"the `#[rustc_on_unimplemented]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(on_unimplemented))),
|
||||
("rustc_const_unstable", Normal, template!(List: r#"feature = "name""#),
|
||||
(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))),
|
||||
("global_allocator", Normal, template!(Word), Ungated),
|
||||
("default_lib_allocator", Whitelisted, template!(Word), Gated(Stability::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",
|
||||
cfg_fn!(allocator_internals))),
|
||||
("needs_allocator", Normal, template!(Word), Gated(Stability::Unstable,
|
||||
(symbols::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,
|
||||
(symbols::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,
|
||||
(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,
|
||||
(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))),
|
||||
("rustc_variance", Normal, template!(Word), Gated(Stability::Unstable,
|
||||
(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))),
|
||||
("rustc_layout", Normal, template!(List: "field1, field2, ..."),
|
||||
(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"),
|
||||
(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"),
|
||||
(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,
|
||||
(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",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_error", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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,
|
||||
(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"),
|
||||
(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))),
|
||||
("rustc_then_this_would_need", Whitelisted, template!(List: "DepNode"),
|
||||
(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))),
|
||||
("rustc_dirty", Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
|
||||
(symbols::rustc_dirty, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
|
||||
/*opt*/ except = "...""#),
|
||||
Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
|
@ -1016,7 +1041,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
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 = "...",
|
||||
(symbols::rustc_clean, Whitelisted, template!(List: r#"cfg = "...", /*opt*/ label = "...",
|
||||
/*opt*/ except = "...""#),
|
||||
Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
|
@ -1024,21 +1049,33 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
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,
|
||||
(
|
||||
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))),
|
||||
("rustc_partition_codegened", Whitelisted, template!(List: r#"cfg = "...", module = "...""#),
|
||||
Gated(Stability::Unstable,
|
||||
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))),
|
||||
("rustc_expected_cgu_reuse", Whitelisted, template!(List: r#"cfg = "...", module = "...",
|
||||
cfg_fn!(rustc_attrs),
|
||||
)
|
||||
),
|
||||
(symbols::rustc_expected_cgu_reuse, Whitelisted, template!(List: r#"cfg = "...", module = "...",
|
||||
kind = "...""#),
|
||||
Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
|
@ -1046,64 +1083,71 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_synthetic", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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))),
|
||||
("rustc_symbol_name", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(symbols::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,
|
||||
(symbols::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,
|
||||
(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))),
|
||||
("rustc_inherit_overflow_checks", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(
|
||||
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))),
|
||||
cfg_fn!(rustc_attrs),
|
||||
)
|
||||
),
|
||||
|
||||
("rustc_dump_program_clauses", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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_test_marker", Normal, template!(Word), Gated(Stability::Unstable,
|
||||
(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))),
|
||||
("rustc_transparent_macro", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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,
|
||||
(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))),
|
||||
("sanitizer_runtime", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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))),
|
||||
("profiler_runtime", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(symbols::profiler_runtime, Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
"profiler_runtime",
|
||||
"the `#[profiler_runtime]` attribute is used to \
|
||||
identify the `profiler_builtins` crate which \
|
||||
|
@ -1111,70 +1155,81 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
stable",
|
||||
cfg_fn!(profiler_runtime))),
|
||||
|
||||
("allow_internal_unstable", Normal, template!(Word, List: "feat1, feat2, ..."),
|
||||
(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))),
|
||||
|
||||
("allow_internal_unsafe", Normal, template!(Word), Gated(Stability::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,
|
||||
(symbols::fundamental, Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
"fundamental",
|
||||
"the `#[fundamental]` attribute \
|
||||
is an experimental feature",
|
||||
cfg_fn!(fundamental))),
|
||||
|
||||
("proc_macro_derive", Normal, template!(List: "TraitName, \
|
||||
(symbols::proc_macro_derive, Normal, template!(List: "TraitName, \
|
||||
/*opt*/ attributes(name1, name2, ...)"),
|
||||
Ungated),
|
||||
|
||||
("rustc_copy_clone_marker", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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,
|
||||
(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))),
|
||||
("ffi_returns_twice", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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))),
|
||||
("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|...",
|
||||
(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),
|
||||
("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::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",
|
||||
cfg_fn!(no_debug))),
|
||||
("omit_gdb_pretty_printer_section", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(
|
||||
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))),
|
||||
("unsafe_destructor_blind_to_params",
|
||||
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",
|
||||
|
@ -1183,34 +1238,47 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
"unsafe_destructor_blind_to_params has been replaced by \
|
||||
may_dangle and will be removed in the future",
|
||||
cfg_fn!(dropck_parametricity))),
|
||||
("may_dangle",
|
||||
(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))),
|
||||
("unwind", Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
|
||||
(symbols::unwind, Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
|
||||
"unwind_attributes",
|
||||
"#[unwind] is experimental",
|
||||
cfg_fn!(unwind_attributes))),
|
||||
("used", Whitelisted, template!(Word), Ungated),
|
||||
(symbols::used, Whitelisted, template!(Word), Ungated),
|
||||
|
||||
// used in resolve
|
||||
("prelude_import", Whitelisted, template!(Word), Gated(Stability::Unstable,
|
||||
(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,
|
||||
(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,
|
||||
(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,
|
||||
(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,
|
||||
(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))),
|
||||
|
||||
("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,
|
||||
(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,
|
||||
(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,18 +1436,21 @@ 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 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 n == "doc" {
|
||||
} 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,
|
||||
|
@ -1376,7 +1462,6 @@ impl<'a> Context<'a> {
|
|||
debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for &(ref n, ref ty) in self.plugin_attributes {
|
||||
if attr.path == &**n {
|
||||
// Plugins can't gate attributes, so we don't check for it
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue