rust/compiler/rustc_feature/src/builtin_attrs.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

817 lines
34 KiB
Rust
Raw Normal View History

2019-08-22 16:32:31 +00:00
//! Built-in attributes and `cfg` flag gating.
2021-09-05 23:30:37 +00:00
use AttributeDuplicates::*;
2019-08-22 16:32:31 +00:00
use AttributeGate::*;
use AttributeType::*;
2019-08-22 16:32:31 +00:00
2019-11-30 01:34:18 +00:00
use crate::{Features, Stability};
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::{sym, Symbol};
2019-08-22 16:32:31 +00:00
use std::lazy::SyncLazy;
2019-08-22 16:37:28 +00:00
type GateFn = fn(&Features) -> bool;
2019-08-22 16:32:31 +00:00
macro_rules! cfg_fn {
2019-08-22 16:37:28 +00:00
($field: ident) => {
(|features| features.$field) as GateFn
};
2019-08-22 16:32:31 +00:00
}
2019-11-30 00:57:53 +00:00
pub type GatedCfg = (Symbol, Symbol, GateFn);
2019-08-22 16:37:28 +00:00
/// `cfg(...)`'s that are feature gated.
2019-11-30 00:57:53 +00:00
const GATED_CFGS: &[GatedCfg] = &[
2019-08-22 16:32:31 +00:00
// (name in cfg, feature, function to check if the feature is enabled)
(sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)),
2019-08-22 16:32:31 +00:00
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
(
sym::target_has_atomic_equal_alignment,
sym::cfg_target_has_atomic_equal_alignment,
cfg_fn!(cfg_target_has_atomic_equal_alignment),
),
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
(sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
(sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
2019-08-22 16:32:31 +00:00
];
2019-11-30 00:57:53 +00:00
/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg> {
GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym))
2019-08-22 16:32:31 +00:00
}
// If you change this, please modify `src/doc/unstable-book` as well. You must
// move that documentation into the relevant place in the other docs, and
// remove the chapter on the flag.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum AttributeType {
/// Normal, builtin attribute that is consumed
/// by the compiler before the unused_attribute check
Normal,
/// Builtin attribute that is only allowed at the crate level
CrateLevel,
}
#[derive(Clone, Copy)]
2019-08-22 16:32:31 +00:00
pub enum AttributeGate {
/// Is gated by a given feature gate, reason
/// and function to check if enabled
Gated(Stability, Symbol, &'static str, fn(&Features) -> bool),
/// Ungated attribute, can be used on all release channels
Ungated,
}
// fn() is not Debug
impl std::fmt::Debug for AttributeGate {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
Self::Gated(ref stab, name, expl, _) => {
write!(fmt, "Gated({:?}, {}, {})", stab, name, expl)
}
Self::Ungated => write!(fmt, "Ungated"),
2019-08-22 16:32:31 +00:00
}
}
}
impl AttributeGate {
fn is_deprecated(&self) -> bool {
2020-10-27 01:02:48 +00:00
matches!(*self, Self::Gated(Stability::Deprecated(_, _), ..))
2019-08-22 16:32:31 +00:00
}
}
/// A template that the attribute input must match.
/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
2019-12-30 18:38:43 +00:00
#[derive(Clone, Copy, Default)]
pub struct AttributeTemplate {
2021-09-05 23:30:37 +00:00
/// If `true`, the attribute is allowed to be a bare word like `#[test]`.
pub word: bool,
2021-09-05 23:30:37 +00:00
/// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`.
pub list: Option<&'static str>,
2021-09-05 23:30:37 +00:00
/// If `Some`, the attribute is allowed to be a name/value pair where the
/// value is a string, like `#[must_use = "reason"]`.
pub name_value_str: Option<&'static str>,
}
2021-09-05 23:30:37 +00:00
/// How to handle multiple duplicate attributes on the same item.
#[derive(Clone, Copy, Default)]
pub enum AttributeDuplicates {
/// Duplicates of this attribute are allowed.
///
/// This should only be used with attributes where duplicates have semantic
/// meaning, or some kind of "additive" behavior. For example, `#[warn(..)]`
/// can be specified multiple times, and it combines all the entries. Or use
/// this if there is validation done elsewhere.
#[default]
DuplicatesOk,
/// Duplicates after the first attribute will be an unused_attribute warning.
///
/// This is usually used for "word" attributes, where they are used as a
/// boolean marker, like `#[used]`. It is not necessarily wrong that there
/// are duplicates, but the others should probably be removed.
WarnFollowing,
/// Same as `WarnFollowing`, but only issues warnings for word-style attributes.
///
/// This is only for special cases, for example multiple `#[macro_use]` can
/// be warned, but multiple `#[macro_use(...)]` should not because the list
/// form has different meaning from the word form.
WarnFollowingWordOnly,
/// Duplicates after the first attribute will be an error.
///
/// This should be used where duplicates would be ignored, but carry extra
/// meaning that could cause confusion. For example, `#[stable(since="1.0")]
/// #[stable(since="2.0")]`, which version should be used for `stable`?
ErrorFollowing,
/// Duplicates preceding the last instance of the attribute will be an error.
///
/// This is the same as `ErrorFollowing`, except the last attribute is the
/// one that is "used". This is typically used in cases like codegen
/// attributes which usually only honor the last attribute.
ErrorPreceding,
/// Duplicates after the first attribute will be an unused_attribute warning
/// with a note that this will be an error in the future.
///
/// This should be used for attributes that should be `ErrorFollowing`, but
/// because older versions of rustc silently accepted (and ignored) the
/// attributes, this is used to transition.
FutureWarnFollowing,
/// Duplicates preceding the last instance of the attribute will be a
/// warning, with a note that this will be an error in the future.
///
/// This is the same as `FutureWarnFollowing`, except the last attribute is
/// the one that is "used". Ideally these can eventually migrate to
/// `ErrorPreceding`.
FutureWarnPreceding,
}
2022-04-01 13:04:47 +00:00
/// A conveniece macro to deal with `$($expr)?`.
macro_rules! or_default {
($default:expr,) => {
$default
};
($default:expr, $next:expr) => {
$next
};
}
2019-08-22 16:32:31 +00:00
/// A convenience macro for constructing attribute templates.
/// E.g., `template!(Word, List: "description")` means that the attribute
/// supports forms `#[attr]` and `#[attr(description)]`.
macro_rules! template {
(Word) => { template!(@ true, None, None) };
(List: $descr: expr) => { template!(@ false, Some($descr), None) };
(NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) };
(Word, List: $descr: expr) => { template!(@ true, Some($descr), None) };
(Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) };
(List: $descr1: expr, NameValueStr: $descr2: expr) => {
template!(@ false, Some($descr1), Some($descr2))
};
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
template!(@ true, Some($descr1), Some($descr2))
};
(@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate {
word: $word, list: $list, name_value_str: $name_value_str
} };
}
macro_rules! ungated {
2022-04-01 13:04:47 +00:00
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)? $(,)?) => {
2021-09-05 23:30:37 +00:00
BuiltinAttribute {
name: sym::$attr,
2022-04-01 13:04:47 +00:00
only_local: or_default!(false, $($only_local)?),
2021-09-05 23:30:37 +00:00
type_: $typ,
template: $tpl,
gate: Ungated,
duplicates: $duplicates,
}
};
}
macro_rules! gated {
2022-04-01 13:04:47 +00:00
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $gate:ident, $msg:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
2022-04-01 13:04:47 +00:00
only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
2021-09-05 23:30:37 +00:00
duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
}
};
2022-04-01 13:04:47 +00:00
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
2022-04-01 13:04:47 +00:00
only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
2021-09-05 23:30:37 +00:00
duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
}
};
}
macro_rules! rustc_attr {
2022-04-01 13:04:47 +00:00
(TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(, @only_local: $only_local:expr)? $(,)?) => {
rustc_attr!(
$attr,
$typ,
$tpl,
2021-09-05 23:30:37 +00:00
$duplicate,
2022-04-01 13:04:47 +00:00
$(@only_local: $only_local,)?
concat!(
"the `#[",
stringify!($attr),
"]` attribute is just used for rustc unit tests \
and will never be stable",
),
)
};
2022-04-01 13:04:47 +00:00
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
2022-04-01 13:04:47 +00:00
only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
2021-09-05 23:30:37 +00:00
duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
}
};
}
2019-08-22 21:30:59 +00:00
macro_rules! experimental {
($attr:ident) => {
concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature")
};
2019-08-22 21:30:59 +00:00
}
const IMPL_DETAIL: &str = "internal implementation detail";
const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable";
2019-08-22 21:30:59 +00:00
pub struct BuiltinAttribute {
pub name: Symbol,
2022-04-01 13:04:47 +00:00
/// Whether this attribute is only used in the local crate.
///
/// If so, it is not encoded in the crate metadata.
pub only_local: bool,
pub type_: AttributeType,
pub template: AttributeTemplate,
2021-09-05 23:30:37 +00:00
pub duplicates: AttributeDuplicates,
pub gate: AttributeGate,
}
2019-08-22 16:32:31 +00:00
/// Attributes that have a special meaning to rustc or rustdoc.
#[rustfmt::skip]
2019-08-22 16:32:31 +00:00
pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Stable attributes:
// ==========================================================================
2020-03-06 11:13:55 +00:00
// Conditional compilation:
2021-09-05 23:30:37 +00:00
ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk),
ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk),
2019-08-22 16:32:31 +00:00
2019-08-22 21:30:59 +00:00
// Testing:
2021-09-05 23:30:37 +00:00
ungated!(ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing),
2019-08-22 21:30:59 +00:00
ungated!(
should_panic, Normal,
2021-09-05 23:30:37 +00:00
template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), FutureWarnFollowing,
2019-08-22 21:30:59 +00:00
),
// FIXME(Centril): This can be used on stable but shouldn't.
2021-09-05 23:30:37 +00:00
ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing),
2019-08-22 21:30:59 +00:00
// Macros:
2021-09-05 23:30:37 +00:00
ungated!(automatically_derived, Normal, template!(Word), WarnFollowing),
ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly),
ungated!(macro_escape, Normal, template!(Word), WarnFollowing), // Deprecated synonym for `macro_use`.
ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros"), WarnFollowing),
ungated!(proc_macro, Normal, template!(Word), ErrorFollowing),
2019-08-22 21:30:59 +00:00
ungated!(
proc_macro_derive, Normal,
2021-09-05 23:30:37 +00:00
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
2019-08-22 21:30:59 +00:00
),
2021-09-05 23:30:37 +00:00
ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing),
2019-08-22 21:30:59 +00:00
// Lints:
2021-09-05 23:30:37 +00:00
ungated!(
warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
),
ungated!(
allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
),
gated!(
expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk,
lint_reasons, experimental!(expect)
),
2021-09-05 23:30:37 +00:00
ungated!(
forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
),
ungated!(
deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
),
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing),
2021-09-05 02:36:51 +00:00
gated!(
2021-09-05 23:30:37 +00:00
must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing,
2022-04-01 13:04:47 +00:00
experimental!(must_not_suspend)
2021-09-05 02:36:51 +00:00
),
2019-08-22 21:30:59 +00:00
ungated!(
deprecated, Normal,
template!(
Word,
List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
NameValueStr: "reason"
),
2022-04-12 00:43:42 +00:00
ErrorFollowing
2019-08-22 21:30:59 +00:00
),
2019-08-22 21:30:59 +00:00
// Crate properties:
2021-09-05 23:30:37 +00:00
ungated!(crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing),
ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk),
2021-09-05 23:30:37 +00:00
// crate_id is deprecated
ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing),
2019-08-22 21:30:59 +00:00
// ABI, linking, symbols, and FFI
ungated!(
link, Normal,
template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#),
2021-09-05 23:30:37 +00:00
DuplicatesOk,
2019-08-22 21:30:59 +00:00
),
2021-09-05 23:30:37 +00:00
ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
ungated!(no_link, Normal, template!(Word), WarnFollowing),
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk),
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
2022-05-02 07:48:17 +00:00
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true),
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, @only_local: true),
2019-08-22 21:30:59 +00:00
// Limits:
2021-09-05 23:30:37 +00:00
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
gated!(
2021-09-05 23:30:37 +00:00
const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
const_eval_limit, experimental!(const_eval_limit)
),
gated!(
2021-09-05 23:30:37 +00:00
move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
large_assignments, experimental!(move_size_limit)
),
2019-08-22 21:30:59 +00:00
// Entry point:
2021-09-05 23:30:37 +00:00
ungated!(start, Normal, template!(Word), WarnFollowing),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
2019-08-22 21:30:59 +00:00
// Modules, prelude, and resolution:
2021-09-05 23:30:37 +00:00
ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing),
ungated!(no_std, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing),
ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing),
2019-08-22 21:30:59 +00:00
// Runtime
2021-09-05 23:30:37 +00:00
ungated!(
windows_subsystem, CrateLevel,
2021-09-05 23:30:37 +00:00
template!(NameValueStr: "windows|console"), FutureWarnFollowing
),
ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070
2019-08-22 21:30:59 +00:00
// Code generation:
2022-05-02 07:48:17 +00:00
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true),
ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true),
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
2021-09-05 23:30:37 +00:00
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
gated!(
no_sanitize, Normal,
2021-09-05 23:30:37 +00:00
template!(List: "address, memory, thread"), DuplicatesOk,
experimental!(no_sanitize)
),
2021-09-05 23:30:37 +00:00
gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
2019-08-22 21:30:59 +00:00
2021-09-05 23:30:37 +00:00
ungated!(
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Unstable attributes:
// ==========================================================================
// RFC #3191: #[debugger_visualizer] support
gated!(
debugger_visualizer, Normal, template!(List: r#"natvis_file = "...""#),
DuplicatesOk, experimental!(debugger_visualizer)
),
2019-08-22 21:30:59 +00:00
// Linking:
2022-05-02 07:48:17 +00:00
gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)),
2019-08-27 14:42:44 +00:00
gated!(
2021-09-05 23:30:37 +00:00
link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib,
2019-08-27 14:42:44 +00:00
experimental!(link_ordinal)
),
2019-09-18 14:40:08 +00:00
2019-08-22 21:30:59 +00:00
// Plugins:
BuiltinAttribute {
name: sym::plugin,
2022-04-01 13:04:47 +00:00
only_local: false,
type_: CrateLevel,
template: template!(List: "name"),
2021-09-05 23:30:37 +00:00
duplicates: DuplicatesOk,
gate: Gated(
Stability::Deprecated(
"https://github.com/rust-lang/rust/pull/64675",
Some("may be removed in a future compiler version"),
),
sym::plugin,
"compiler plugins are deprecated",
cfg_fn!(plugin)
),
},
2019-08-22 16:32:31 +00:00
2019-08-22 21:30:59 +00:00
// Testing:
gated!(
2021-09-05 23:30:37 +00:00
test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks,
2019-08-22 21:30:59 +00:00
"custom test frameworks are an unstable feature",
),
2019-08-22 16:32:31 +00:00
// RFC #1268
gated!(
2021-09-05 23:30:37 +00:00
marker, Normal, template!(Word), WarnFollowing, marker_trait_attr, experimental!(marker)
),
gated!(
thread_local, Normal, template!(Word), WarnFollowing,
2019-08-22 21:30:59 +00:00
"`#[thread_local]` is an experimental feature, and does not currently handle destructors",
),
2021-09-05 23:30:37 +00:00
gated!(no_core, CrateLevel, template!(Word), WarnFollowing, experimental!(no_core)),
2019-08-22 21:30:59 +00:00
// RFC 2412
gated!(
2021-09-05 23:30:37 +00:00
optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute,
2019-08-22 21:30:59 +00:00
experimental!(optimize),
),
// RFC 2867
2021-09-05 23:30:37 +00:00
gated!(
instruction_set, Normal, template!(List: "set"), ErrorPreceding,
isa_attribute, experimental!(instruction_set)
),
gated!(
2021-09-05 23:30:37 +00:00
ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice)
),
gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)),
gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)),
gated!(
register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), DuplicatesOk,
experimental!(register_attr),
),
gated!(
2021-09-05 23:30:37 +00:00
register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk,
experimental!(register_tool),
),
2019-08-22 21:30:59 +00:00
2021-09-05 23:30:37 +00:00
gated!(
cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing,
experimental!(cmse_nonsecure_entry)
),
2021-07-04 15:50:34 +00:00
// RFC 2632
gated!(
2021-09-05 23:30:37 +00:00
default_method_body_is_const, Normal, template!(Word), WarnFollowing, const_trait_impl,
2021-07-04 15:50:34 +00:00
"`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
as `const`, which may be removed or renamed in the future."
),
// lang-team MCP 147
gated!(
deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
experimental!(deprecated_safe),
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes: Stability, deprecation, and unsafe:
// ==========================================================================
2022-02-21 09:17:37 +00:00
ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk),
2022-04-12 00:43:42 +00:00
// FIXME(jhpratt) remove this eventually
2019-08-22 21:30:59 +00:00
ungated!(
rustc_deprecated, Normal,
2022-04-12 00:43:42 +00:00
template!(List: r#"since = "version", note = "...""#), ErrorFollowing
2021-09-05 23:30:37 +00:00
),
// DuplicatesOk since it has its own validation
ungated!(
2022-04-01 13:04:47 +00:00
stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
2019-08-22 21:30:59 +00:00
),
ungated!(
unstable, Normal,
2021-09-05 23:30:37 +00:00
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
),
2021-09-05 23:30:37 +00:00
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
gated!(
2021-09-05 23:30:37 +00:00
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
2019-11-30 01:03:32 +00:00
"allow_internal_unstable side-steps feature gating and stability checks",
),
gated!(
2021-09-05 23:30:37 +00:00
rustc_allow_const_fn_unstable, Normal,
template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
"rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
),
2019-11-30 01:03:32 +00:00
gated!(
2021-09-05 23:30:37 +00:00
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
2019-11-30 01:03:32 +00:00
"allow_internal_unsafe side-steps the unsafe_code lint",
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes: Type system related:
// ==========================================================================
2021-09-05 23:30:37 +00:00
gated!(fundamental, Normal, template!(Word), WarnFollowing, experimental!(fundamental)),
gated!(
2021-09-05 23:30:37 +00:00
may_dangle, Normal, template!(Word), WarnFollowing, dropck_eyepatch,
2019-08-22 21:30:59 +00:00
"`may_dangle` has unstable semantics and may be removed in the future",
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes: Runtime related:
// ==========================================================================
2021-09-05 23:30:37 +00:00
rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
gated!(
alloc_error_handler, Normal, template!(Word), WarnFollowing,
experimental!(alloc_error_handler)
),
gated!(
2021-09-05 23:30:37 +00:00
default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
2019-08-22 21:30:59 +00:00
experimental!(default_lib_allocator),
),
gated!(
2021-09-05 23:30:37 +00:00
needs_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
2019-08-22 21:30:59 +00:00
experimental!(needs_allocator),
),
2021-09-05 23:30:37 +00:00
gated!(panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(panic_runtime)),
gated!(
2021-09-05 23:30:37 +00:00
needs_panic_runtime, Normal, template!(Word), WarnFollowing,
experimental!(needs_panic_runtime)
),
gated!(
compiler_builtins, Normal, template!(Word), WarnFollowing,
"the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
which contains compiler-rt intrinsics and will never be stable",
),
gated!(
2021-09-05 23:30:37 +00:00
profiler_runtime, Normal, template!(Word), WarnFollowing,
"the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
which contains the profiler runtime and will never be stable",
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Linkage:
// ==========================================================================
gated!(
2022-05-02 07:48:17 +00:00
linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, @only_local: true,
2019-08-22 21:30:59 +00:00
"the `linkage` attribute is experimental and not portable across platforms",
),
2021-09-05 23:30:37 +00:00
rustc_attr!(
2022-05-02 07:48:17 +00:00
rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, @only_local: true, INTERNAL_UNSTABLE
2021-09-05 23:30:37 +00:00
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Macro related:
// ==========================================================================
rustc_attr!(
rustc_builtin_macro, Normal,
2021-09-05 23:30:37 +00:00
template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
IMPL_DETAIL,
),
2021-09-05 23:30:37 +00:00
rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
2019-08-22 21:30:59 +00:00
rustc_attr!(
rustc_macro_transparency, Normal,
2021-09-05 23:30:37 +00:00
template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing,
2019-08-22 21:30:59 +00:00
"used internally for testing macro hygiene",
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Diagnostics related:
// ==========================================================================
rustc_attr!(
rustc_on_unimplemented, Normal,
2019-08-22 21:30:59 +00:00
template!(
List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
NameValueStr: "message"
),
2021-09-05 23:30:37 +00:00
ErrorFollowing,
INTERNAL_UNSTABLE
),
// Enumerates "identity-like" conversion methods to suggest on type mismatch.
2021-09-05 23:30:37 +00:00
rustc_attr!(
rustc_conversion_suggestion, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
),
// Prevents field reads in the marked trait or method to be considered
// during dead code analysis.
2021-09-05 23:30:37 +00:00
rustc_attr!(
rustc_trivial_field_reads, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
),
2022-01-05 12:02:16 +00:00
// Used by the `rustc::potential_query_instability` lint to warn methods which
// might not be stable during incremental compilation.
rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Const related:
// ==========================================================================
2021-09-05 23:30:37 +00:00
rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
rustc_attr!(
rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
INTERNAL_UNSTABLE
),
2021-10-12 05:06:37 +00:00
// Do not const-check this function's body. It will always get replaced during CTFE.
2021-09-05 23:30:37 +00:00
rustc_attr!(
rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
),
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Layout related:
// ==========================================================================
2019-08-22 16:32:31 +00:00
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
2019-08-22 21:30:59 +00:00
"the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
Generalize `get_nullable_type` to allow types where null is all-ones. Generalize get_nullable_type to accept types that have an all-ones bit pattern as their sentry "null" value. This will allow [`OwnedFd`], [`BorrowedFd`], [`OwnedSocket`], and [`BorrowedSocket`] to be marked with `#[rustc_nonnull_optimization_guaranteed]`, which will allow `Option<OwnedFd>`, `Option<BorrowedFd>`, `Option<OwnedSocket>`, and `Option<BorrowedSocket>` to be used in FFI declarations, as described in the [I/O safety RFC]. For example, it will allow a function like `open` on Unix and `WSASocketW` on Windows to be declared using `Option<OwnedFd>` and `Option<OwnedSocket>` return types, respectively. The actual change to add `#[rustc_nonnull_optimization_guaranteed]` to the abovementioned types will be a separate PR, as it'll depend on having this patch in the stage0 compiler. Also, update the diagnostics to mention that "niche optimizations" are used in libstd as well as libcore, as `rustc_layout_scalar_valid_range_start` and `rustc_layout_scalar_valid_range_end` are already in use in libstd. [`OwnedFd`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/fd/owned.rs#L49 [`BorrowedFd`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/fd/owned.rs#L29 [`OwnedSocket`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/windows/io/socket.rs#L51 [`BorrowedSocket`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/windows/io/socket.rs#L29 [I/O safety RFC]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md#ownedfd-and-borrowedfdfd-1
2022-03-03 22:41:10 +00:00
niche optimizations in libcore and libstd and will never be stable",
),
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
2019-08-22 21:30:59 +00:00
"the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
Generalize `get_nullable_type` to allow types where null is all-ones. Generalize get_nullable_type to accept types that have an all-ones bit pattern as their sentry "null" value. This will allow [`OwnedFd`], [`BorrowedFd`], [`OwnedSocket`], and [`BorrowedSocket`] to be marked with `#[rustc_nonnull_optimization_guaranteed]`, which will allow `Option<OwnedFd>`, `Option<BorrowedFd>`, `Option<OwnedSocket>`, and `Option<BorrowedSocket>` to be used in FFI declarations, as described in the [I/O safety RFC]. For example, it will allow a function like `open` on Unix and `WSASocketW` on Windows to be declared using `Option<OwnedFd>` and `Option<OwnedSocket>` return types, respectively. The actual change to add `#[rustc_nonnull_optimization_guaranteed]` to the abovementioned types will be a separate PR, as it'll depend on having this patch in the stage0 compiler. Also, update the diagnostics to mention that "niche optimizations" are used in libstd as well as libcore, as `rustc_layout_scalar_valid_range_start` and `rustc_layout_scalar_valid_range_end` are already in use in libstd. [`OwnedFd`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/fd/owned.rs#L49 [`BorrowedFd`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/fd/owned.rs#L29 [`OwnedSocket`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/windows/io/socket.rs#L51 [`BorrowedSocket`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/windows/io/socket.rs#L29 [I/O safety RFC]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md#ownedfd-and-borrowedfdfd-1
2022-03-03 22:41:10 +00:00
niche optimizations in libcore and libstd and will never be stable",
),
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
2019-08-22 21:30:59 +00:00
"the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \
Generalize `get_nullable_type` to allow types where null is all-ones. Generalize get_nullable_type to accept types that have an all-ones bit pattern as their sentry "null" value. This will allow [`OwnedFd`], [`BorrowedFd`], [`OwnedSocket`], and [`BorrowedSocket`] to be marked with `#[rustc_nonnull_optimization_guaranteed]`, which will allow `Option<OwnedFd>`, `Option<BorrowedFd>`, `Option<OwnedSocket>`, and `Option<BorrowedSocket>` to be used in FFI declarations, as described in the [I/O safety RFC]. For example, it will allow a function like `open` on Unix and `WSASocketW` on Windows to be declared using `Option<OwnedFd>` and `Option<OwnedSocket>` return types, respectively. The actual change to add `#[rustc_nonnull_optimization_guaranteed]` to the abovementioned types will be a separate PR, as it'll depend on having this patch in the stage0 compiler. Also, update the diagnostics to mention that "niche optimizations" are used in libstd as well as libcore, as `rustc_layout_scalar_valid_range_start` and `rustc_layout_scalar_valid_range_end` are already in use in libstd. [`OwnedFd`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/fd/owned.rs#L49 [`BorrowedFd`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/fd/owned.rs#L29 [`OwnedSocket`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/windows/io/socket.rs#L51 [`BorrowedSocket`]: https://github.com/rust-lang/rust/blob/c9dc44be24c58ff13ce46416c4b97ab5c1bd8429/library/std/src/os/windows/io/socket.rs#L29 [I/O safety RFC]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md#ownedfd-and-borrowedfdfd-1
2022-03-03 22:41:10 +00:00
niche optimizations in libcore and libstd and will never be stable",
),
2019-08-22 16:32:31 +00:00
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Misc:
// ==========================================================================
gated!(
2022-04-01 13:04:47 +00:00
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, @only_local: true, lang_items,
2019-08-22 21:30:59 +00:00
"language items are subject to change",
),
rustc_attr!(
rustc_pass_by_value, Normal,
2022-01-27 06:58:33 +00:00
template!(Word), ErrorFollowing,
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
),
rustc_attr!(
2022-04-01 13:04:47 +00:00
rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, @only_local: true,
"#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`."
),
rustc_attr!(
2022-04-01 13:04:47 +00:00
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
),
rustc_attr!(
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
the given type by annotating all impl items with #[rustc_allow_incoherent_impl]."
),
BuiltinAttribute {
name: sym::rustc_diagnostic_item,
2022-04-01 13:04:47 +00:00
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
only_local: false,
type_: Normal,
template: template!(NameValueStr: "name"),
2021-09-05 23:30:37 +00:00
duplicates: ErrorFollowing,
gate: Gated(
Stability::Unstable,
sym::rustc_attrs,
"diagnostic items compiler internal support for linting",
cfg_fn!(rustc_attrs),
),
},
gated!(
2019-08-22 21:30:59 +00:00
// Used in resolve:
2021-09-05 23:30:37 +00:00
prelude_import, Normal, template!(Word), WarnFollowing,
"`#[prelude_import]` is for use by rustc only",
),
gated!(
2021-09-05 23:30:37 +00:00
rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures,
"unboxed_closures are still evolving",
),
2019-08-22 21:30:59 +00:00
rustc_attr!(
2022-04-01 13:04:47 +00:00
rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true,
2019-08-22 21:30:59 +00:00
"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",
),
2021-09-05 23:30:37 +00:00
rustc_attr!(
rustc_reservation_impl, Normal,
template!(NameValueStr: "reservation message"), ErrorFollowing,
"the `#[rustc_reservation_impl]` attribute is internally used \
for reserving for `for<T> From<!> for T` impl"
),
2019-08-22 21:30:59 +00:00
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_test_marker, Normal, template!(Word), WarnFollowing,
2019-08-22 21:30:59 +00:00
"the `#[rustc_test_marker]` attribute is used internally to track tests",
),
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing,
"the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
),
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_specialization_trait, Normal, template!(Word), WarnFollowing,
"the `#[rustc_specialization_trait]` attribute is used to check specializations"
),
2021-04-08 13:37:38 +00:00
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_main, Normal, template!(Word), WarnFollowing,
2021-04-08 13:37:38 +00:00
"the `#[rustc_main]` attribute is used internally to specify test entry point function",
),
rustc_attr!(
2021-09-05 23:30:37 +00:00
rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing,
"the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \
from method dispatch when the receiver is an array, for compatibility in editions < 2021."
),
rustc_attr!(
rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing,
"the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
definition of a trait, it's currently in experimental form and should be changed before \
being exposed outside of the std"
),
2019-08-22 16:32:31 +00:00
2019-08-22 21:30:59 +00:00
// ==========================================================================
// Internal attributes, Testing:
// ==========================================================================
2019-08-22 16:32:31 +00:00
2021-09-05 23:30:37 +00:00
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
rustc_attr!(
TEST, rustc_error, Normal,
2021-09-05 23:30:37 +00:00
template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly
),
rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing),
rustc_attr!(
TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk
),
rustc_attr!(
TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk
),
rustc_attr!(
TEST, rustc_clean, Normal,
2019-08-22 21:30:59 +00:00
template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
2021-09-05 23:30:37 +00:00
DuplicatesOk,
),
rustc_attr!(
TEST, rustc_partition_reused, Normal,
2021-09-05 23:30:37 +00:00
template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk,
2019-08-22 16:32:31 +00:00
),
2019-08-22 21:30:59 +00:00
rustc_attr!(
TEST, rustc_partition_codegened, Normal,
2021-09-05 23:30:37 +00:00
template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk,
),
2019-08-22 21:30:59 +00:00
rustc_attr!(
TEST, rustc_expected_cgu_reuse, Normal,
2021-09-05 23:30:37 +00:00
template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk,
),
rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), DuplicatesOk),
gated!(
2021-09-05 23:30:37 +00:00
omit_gdb_pretty_printer_section, Normal, template!(Word), WarnFollowing,
2019-08-22 21:30:59 +00:00
"the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
),
2019-08-22 16:32:31 +00:00
];
pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> {
BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect()
2019-08-22 16:32:31 +00:00
}
2019-11-30 01:20:07 +00:00
pub fn is_builtin_attr_name(name: Symbol) -> bool {
2019-08-22 16:32:31 +00:00
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
}
2022-04-01 13:04:47 +00:00
pub fn is_builtin_only_local(name: Symbol) -> bool {
BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
}
pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy<FxHashMap<Symbol, &BuiltinAttribute>> =
SyncLazy::new(|| {
let mut map = FxHashMap::default();
for attr in BUILTIN_ATTRIBUTES.iter() {
if map.insert(attr.name, attr).is_some() {
panic!("duplicate builtin attribute `{}`", attr.name);
}
2019-08-22 16:32:31 +00:00
}
map
});