diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c5f42aa7af72..f512594977c8 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -147,6 +147,16 @@ pub enum AttributeDuplicates { 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)]`. @@ -168,9 +178,10 @@ macro_rules! template { } 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, @@ -180,18 +191,20 @@ macro_rules! 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, @@ -201,12 +214,13 @@ macro_rules! gated { } 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), @@ -215,9 +229,10 @@ macro_rules! rustc_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, @@ -237,6 +252,10 @@ const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never b 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, @@ -295,7 +314,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ 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, @@ -394,6 +413,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Plugins: BuiltinAttribute { name: sym::plugin, + only_local: false, type_: CrateLevel, template: template!(List: "name"), duplicates: DuplicatesOk, @@ -475,7 +495,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // 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, @@ -633,7 +653,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // 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!( @@ -642,11 +662,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "#[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!( @@ -656,6 +676,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), 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, @@ -676,7 +698,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "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", @@ -778,6 +800,10 @@ pub fn is_builtin_attr_name(name: Symbol) -> bool { 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> = SyncLazy::new(|| { let mut map = FxHashMap::default(); diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 940c4ecdcc23..26e0538b0eb4 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -149,7 +149,8 @@ pub use accepted::ACCEPTED_FEATURES; pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES}; pub use builtin_attrs::AttributeDuplicates; pub use builtin_attrs::{ - deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate, - AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, + deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local, + AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, + BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, }; pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 81388a0bf585..2f006dfabec8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -986,9 +986,13 @@ fn should_encode_generics(def_kind: DefKind) -> bool { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: DefId) { - let attrs = self.tcx.get_attrs(def_id); - record!(self.tables.attributes[def_id] <- attrs); - if attrs.iter().any(|attr| attr.may_have_doc_links()) { + let mut attrs = self + .tcx + .get_attrs(def_id) + .iter() + .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty())); + record!(self.tables.attributes[def_id] <- attrs.clone()); + if attrs.any(|attr| attr.may_have_doc_links()) { self.tables.may_have_doc_links.set(def_id.index, ()); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 629a550b7759..ec268fc2343d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1072,6 +1072,9 @@ rustc_queries! { desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } } + /// Returns the attributes on the item at `def_id`. + /// + /// Do not use this directly, use `tcx.get_attrs` instead. query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] { desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d847068b5bfb..722257f9c5eb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2187,6 +2187,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Gets the attributes of a definition. + /// + /// Note that attributes which are be relevant while + /// the current local crate are not stored in the crate metadata + /// and therefore cannot be accessed outside of that crate. pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> { if let Some(did) = did.as_local() { self.hir().attrs(self.hir().local_def_id_to_hir_id(did))