don't encode only locally used attrs

This commit is contained in:
lcnr 2022-04-01 15:04:47 +02:00
parent 87fd70c107
commit 74b6d296db
5 changed files with 54 additions and 16 deletions

View file

@ -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<FxHashMap<Symbol, &BuiltinAttribute>> =
SyncLazy::new(|| {
let mut map = FxHashMap::default();

View file

@ -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};

View file

@ -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, ());
}
}

View file

@ -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

View file

@ -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))