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,
// Plugins:
BuiltinAttribute {
name: sym::plugin,
+ only_local: false,
type_: CrateLevel,
template: template!(List: "name"),
duplicates: DuplicatesOk,
),
// 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,
// 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!(
),
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 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();