use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::{sym, Symbol};
-use std::lazy::SyncLazy;
+use std::sync::LazyLock;
type GateFn = fn(&Features) -> bool;
FutureWarnPreceding,
}
+/// A conveniece macro to deal with `$($expr)?`.
+macro_rules! or_default {
+ ($default:expr,) => {
+ $default
+ };
+ ($default:expr, $next:expr) => {
+ $next
+ };
+}
+
/// 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! ungated {
- ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(,)?) => {
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)? $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
gate: Ungated,
}
macro_rules! gated {
- ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $gate:ident, $msg:expr $(,)?) => {
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $gate:ident, $msg:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
}
};
- ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => {
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
duplicates: $duplicates,
}
macro_rules! rustc_attr {
- (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(,)?) => {
+ (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(, @only_local: $only_local:expr)? $(,)?) => {
rustc_attr!(
$attr,
$typ,
$tpl,
$duplicate,
+ $(@only_local: $only_local,)?
concat!(
"the `#[",
stringify!($attr),
),
)
};
- ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => {
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
BuiltinAttribute {
name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
type_: $typ,
template: $tpl,
duplicates: $duplicates,
pub struct BuiltinAttribute {
pub name: Symbol,
+ /// 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,
pub duplicates: AttributeDuplicates,
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing),
gated!(
must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing,
- must_not_suspend, experimental!(must_not_suspend)
+ experimental!(must_not_suspend)
),
ungated!(
deprecated, Normal,
List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
NameValueStr: "reason"
),
- // This has special duplicate handling in E0550 to handle duplicates with rustc_deprecated
- DuplicatesOk
+ ErrorFollowing
),
// Crate properties:
ungated!(crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing),
- ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), FutureWarnFollowing),
+ ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk),
// crate_id is deprecated
ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing),
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk),
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
- ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
- ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing),
+ ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true),
+ ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, @only_local: true),
// Limits:
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070
// Code generation:
- ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing),
- ungated!(cold, Normal, template!(Word), WarnFollowing),
+ 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),
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
// Unstable attributes:
// ==========================================================================
+ // RFC #3191: #[debugger_visualizer] support
+ gated!(
+ debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
+ DuplicatesOk, experimental!(debugger_visualizer)
+ ),
+
// Linking:
- gated!(naked, Normal, template!(Word), WarnFollowing, naked_functions, experimental!(naked)),
+ gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)),
gated!(
link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib,
experimental!(link_ordinal)
// Plugins:
BuiltinAttribute {
name: sym::plugin,
+ only_local: false,
type_: CrateLevel,
template: template!(List: "name"),
duplicates: DuplicatesOk,
),
// RFC 2632
gated!(
- default_method_body_is_const, Normal, template!(Word), WarnFollowing, const_trait_impl,
- "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
- as `const`, which may be removed or renamed in the future."
+ const_trait, Normal, template!(Word), WarnFollowing, const_trait_impl,
+ "`const` is a temporary placeholder for marking a trait that is suitable for `const` \
+ `impls` and all default bodies as `const`, which may be removed or renamed in the \
+ future."
),
// lang-team MCP 147
gated!(
ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk),
// DuplicatesOk since it has its own validation
ungated!(
- rustc_deprecated, Normal,
- template!(List: r#"since = "version", note = "...""#), DuplicatesOk // See E0550
- ),
- // DuplicatesOk since it has its own validation
- ungated!(
- stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk
+ stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
),
ungated!(
unstable, Normal,
// ==========================================================================
gated!(
- linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding,
+ linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, @only_local: true,
"the `linkage` attribute is experimental and not portable across platforms",
),
rustc_attr!(
- rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
+ rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, @only_local: true, INTERNAL_UNSTABLE
),
// ==========================================================================
// 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),
+ // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
+ // to assist in changes to diagnostic APIs.
+ rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
// ==========================================================================
// Internal attributes, Const related:
// Internal attributes, Misc:
// ==========================================================================
gated!(
- lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
+ lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, @only_local: true, lang_items,
"language items are subject to change",
),
rustc_attr!(
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
),
rustc_attr!(
- rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing,
+ 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!(
- rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing,
+ 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]."
+ ),
+ rustc_attr!(
+ rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing,
+ "#[rustc_box] allows creating boxes \
+ and it is only intended to be used in `alloc`."
+ ),
+
BuiltinAttribute {
name: sym::rustc_diagnostic_item,
+ // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
+ only_local: false,
type_: Normal,
template: template!(NameValueStr: "name"),
duplicates: ErrorFollowing,
"unboxed_closures are still evolving",
),
rustc_attr!(
- rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing,
+ rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true,
"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",
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
}
-pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy<FxHashMap<Symbol, &BuiltinAttribute>> =
- SyncLazy::new(|| {
+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: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
+ LazyLock::new(|| {
let mut map = FxHashMap::default();
for attr in BUILTIN_ATTRIBUTES.iter() {
if map.insert(attr.name, attr).is_some() {