Skip to content

Commit 717a117

Browse files
committed
Correctly handle stability of #[diagnostic] attributes
This commit changes the way we treat the stability of attributes in the `#[diagnostic]` namespace. Instead of relaying on ad-hoc checks to ensure at call side that a certain attribute is really usable at that location it centralises the logic to one place. For diagnostic attributes comming from other crates it just skips serializing attributes that are not stable and that do not have the corresponding feature enabled. For attributes from the current crate we can just use the feature information provided by `TyCtx`.
1 parent 59d4114 commit 717a117

5 files changed

Lines changed: 51 additions & 6 deletions

File tree

‎compiler/rustc_feature/src/builtin_attrs.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,3 +1186,11 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
11861186
}
11871187
map
11881188
});
1189+
1190+
pubfnis_stable_diagnostic_attribute(sym:Symbol,features:&Features) -> bool{
1191+
match sym {
1192+
sym::on_unimplemented => true,
1193+
sym::do_not_recommend => features.do_not_recommend,
1194+
_ => false,
1195+
}
1196+
}

‎compiler/rustc_feature/src/lib.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,9 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
130130
pubuse accepted::ACCEPTED_FEATURES;
131131
pubuse builtin_attrs::{
132132
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
133-
is_valid_for_get_attr,AttributeDuplicates,AttributeGate,AttributeSafety,AttributeTemplate,
134-
AttributeType,BuiltinAttribute,GatedCfg,BUILTIN_ATTRIBUTES,BUILTIN_ATTRIBUTE_MAP,
133+
is_stable_diagnostic_attribute, is_valid_for_get_attr,AttributeDuplicates,AttributeGate,
134+
AttributeSafety,AttributeTemplate,AttributeType,BuiltinAttribute,GatedCfg,
135+
BUILTIN_ATTRIBUTES,BUILTIN_ATTRIBUTE_MAP,
135136
};
136137
pubuse removed::REMOVED_FEATURES;
137138
pubuse unstable::{Features,INCOMPATIBLE_FEATURES,UNSTABLE_FEATURES};

‎compiler/rustc_metadata/src/rmeta/encoder.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
99
use rustc_data_structures::memmap::{Mmap,MmapMut};
1010
use rustc_data_structures::sync::{join, par_for_each_in,Lrc};
1111
use rustc_data_structures::temp_dir::MaybeTempDir;
12+
use rustc_feature::Features;
1213
use rustc_hir as hir;
1314
use rustc_hir::def_id::{LocalDefId,LocalDefIdSet,CRATE_DEF_ID,CRATE_DEF_INDEX,LOCAL_CRATE};
1415
use rustc_hir::definitions::DefPathData;
@@ -797,9 +798,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
797798
}
798799
}
799800

800-
structAnalyzeAttrState{
801+
structAnalyzeAttrState<'a>{
801802
is_exported:bool,
802803
is_doc_hidden:bool,
804+
features:&'aFeatures,
803805
}
804806

805807
/// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
@@ -812,7 +814,7 @@ struct AnalyzeAttrState {
812814
/// visibility: this is a piece of data that can be computed once per defid, and not once per
813815
/// attribute. Some attributes would only be usable downstream if they are public.
814816
#[inline]
815-
fnanalyze_attr(attr:&Attribute,state:&mutAnalyzeAttrState) -> bool{
817+
fnanalyze_attr(attr:&Attribute,state:&mutAnalyzeAttrState<'_>) -> bool{
816818
letmut should_encode = false;
817819
if !rustc_feature::encode_cross_crate(attr.name_or_empty()){
818820
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
@@ -837,6 +839,9 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
837839
}
838840
}
839841
}
842+
}elseif attr.path().starts_with(&[sym::diagnostic]) && attr.path().len() == 2{
843+
should_encode =
844+
rustc_feature::is_stable_diagnostic_attribute(attr.path()[1], state.features);
840845
}else{
841846
should_encode = true;
842847
}
@@ -1343,6 +1348,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13431348
letmut state = AnalyzeAttrState{
13441349
is_exported: tcx.effective_visibilities(()).is_exported(def_id),
13451350
is_doc_hidden:false,
1351+
features:&tcx.features(),
13461352
};
13471353
let attr_iter = tcx
13481354
.hir()

‎compiler/rustc_middle/src/ty/context.rs‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,8 +3183,7 @@ impl<'tcx> TyCtxt<'tcx> {
31833183

31843184
/// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
31853185
pubfndo_not_recommend_impl(self,def_id:DefId) -> bool{
3186-
matches!(self.def_kind(def_id),DefKind::Impl{ of_trait:true})
3187-
&& self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend)
3186+
self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some()
31883187
}
31893188
}
31903189

‎compiler/rustc_middle/src/ty/mod.rs‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,37 @@ impl<'tcx> TyCtxt<'tcx> {
17971797
}
17981798
}
17991799

1800+
/// Get an attribute from the diagnostic attribute namespace
1801+
///
1802+
/// This function requests an attribute with the following structure:
1803+
///
1804+
/// `#[diagnostic::$attr]`
1805+
///
1806+
/// This function performs feature checking, so if an attribute is returned
1807+
/// it can be used by the consumer
1808+
pubfnget_diagnostic_attr(
1809+
self,
1810+
did:implInto<DefId>,
1811+
attr:Symbol,
1812+
) -> Option<&'tcx ast::Attribute>{
1813+
let did:DefId = did.into();
1814+
if did.as_local().is_some(){
1815+
// it's a crate local item, we need to check feature flags
1816+
if rustc_feature::is_stable_diagnostic_attribute(attr,self.features()){
1817+
self.get_attrs_by_path(did,&[sym::diagnostic, sym::do_not_recommend]).next()
1818+
}else{
1819+
None
1820+
}
1821+
}else{
1822+
// we filter out unstable diagnostic attributes before
1823+
// encoding attributes
1824+
debug_assert!(rustc_feature::encode_cross_crate(attr));
1825+
self.item_attrs(did)
1826+
.iter()
1827+
.find(|a| matches!(a.path().as_ref(),[sym::diagnostic, a]if*a == attr))
1828+
}
1829+
}
1830+
18001831
pubfnget_attrs_by_path<'attr>(
18011832
self,
18021833
did:DefId,

0 commit comments

Comments
 (0)