Skip to content

Commit a61e15f

Browse files
authored
Unrolled build for rust-lang#135428
Rollup merge of rust-lang#135428 - camelid:attr-cleanup, r=GuillaumeGomez rustdoc: Remove `AttributesExt` trait magic that added needless complexity The new code is more explicit and avoids trait magic that added needless complexity to this part of rustdoc.
2 parents 27f3361 + f92b32c commit a61e15f

File tree

5 files changed

+119
-148
lines changed

5 files changed

+119
-148
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ use rustc_span::symbol::{Symbol, sym};
1717
use thin_vec::{ThinVec, thin_vec};
1818
use tracing::{debug, trace};
1919

20-
use super::Item;
20+
use super::{Item, extract_cfg_from_attrs};
2121
use crate::clean::{
22-
self, Attributes, AttributesExt, ImplKind, ItemId, Type, clean_bound_vars, clean_generics,
23-
clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty,
24-
clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type,
25-
clean_ty_generics, clean_variant_def, utils,
22+
self, Attributes, ImplKind, ItemId, Type, clean_bound_vars, clean_generics, clean_impl_item,
23+
clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_poly_fn_sig,
24+
clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type, clean_ty_generics,
25+
clean_variant_def, utils,
2626
};
2727
use crate::core::DocContext;
2828
use crate::formats::item_type::ItemType;
@@ -408,10 +408,13 @@ pub(crate) fn merge_attrs(
408408
} else {
409409
Attributes::from_hir(&both)
410410
},
411-
both.cfg(cx.tcx, &cx.cache.hidden_cfg),
411+
extract_cfg_from_attrs(both.iter(), cx.tcx, &cx.cache.hidden_cfg),
412412
)
413413
} else {
414-
(Attributes::from_hir(old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg))
414+
(
415+
Attributes::from_hir(old_attrs),
416+
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
417+
)
415418
}
416419
}
417420

src/librustdoc/clean/mod.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,7 @@ fn generate_item_with_correct_attrs(
186186
// For glob re-exports the item may or may not exist to be re-exported (potentially the cfgs
187187
// on the path up until the glob can be removed, and only cfgs on the globbed item itself
188188
// matter), for non-inlined re-exports see #85043.
189-
let is_inline = inline::load_attrs(cx, import_id.to_def_id())
190-
.lists(sym::doc)
189+
let is_inline = hir_attr_lists(inline::load_attrs(cx, import_id.to_def_id()), sym::doc)
191190
.get_word_attr(sym::inline)
192191
.is_some()
193192
|| (is_glob_import(cx.tcx, import_id)
@@ -199,8 +198,14 @@ fn generate_item_with_correct_attrs(
199198
// We only keep the item's attributes.
200199
target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect()
201200
};
202-
203-
let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
201+
let cfg = extract_cfg_from_attrs(
202+
attrs.iter().map(move |(attr, _)| match attr {
203+
Cow::Borrowed(attr) => *attr,
204+
Cow::Owned(attr) => attr,
205+
}),
206+
cx.tcx,
207+
&cx.cache.hidden_cfg,
208+
);
204209
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
205210

206211
let name = renamed.or(Some(name));
@@ -979,13 +984,14 @@ fn clean_proc_macro<'tcx>(
979984
) -> ItemKind {
980985
let attrs = cx.tcx.hir().attrs(item.hir_id());
981986
if kind == MacroKind::Derive
982-
&& let Some(derive_name) = attrs.lists(sym::proc_macro_derive).find_map(|mi| mi.ident())
987+
&& let Some(derive_name) =
988+
hir_attr_lists(attrs, sym::proc_macro_derive).find_map(|mi| mi.ident())
983989
{
984990
*name = derive_name.name;
985991
}
986992

987993
let mut helpers = Vec::new();
988-
for mi in attrs.lists(sym::proc_macro_derive) {
994+
for mi in hir_attr_lists(attrs, sym::proc_macro_derive) {
989995
if !mi.has_name(sym::attributes) {
990996
continue;
991997
}
@@ -2985,7 +2991,7 @@ fn clean_use_statement_inner<'tcx>(
29852991

29862992
let visibility = cx.tcx.visibility(import.owner_id);
29872993
let attrs = cx.tcx.hir().attrs(import.hir_id());
2988-
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
2994+
let inline_attr = hir_attr_lists(attrs, sym::doc).get_word_attr(sym::inline);
29892995
let pub_underscore = visibility.is_public() && name == kw::Underscore;
29902996
let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
29912997
let import_def_id = import.owner_id.def_id;

src/librustdoc/clean/types.rs

Lines changed: 89 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::borrow::Cow;
21
use std::hash::Hash;
32
use std::path::PathBuf;
43
use std::sync::{Arc, OnceLock as OnceCell};
@@ -479,7 +478,7 @@ impl Item {
479478
name,
480479
kind,
481480
Attributes::from_hir(hir_attrs),
482-
hir_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
481+
extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
483482
)
484483
}
485484

@@ -990,147 +989,107 @@ pub(crate) struct Module {
990989
pub(crate) span: Span,
991990
}
992991

993-
pub(crate) trait AttributesExt {
994-
type AttributeIterator<'a>: Iterator<Item = ast::MetaItemInner>
995-
where
996-
Self: 'a;
997-
type Attributes<'a>: Iterator<Item = &'a hir::Attribute>
998-
where
999-
Self: 'a;
1000-
1001-
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_>;
1002-
1003-
fn iter(&self) -> Self::Attributes<'_>;
1004-
1005-
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
1006-
let sess = tcx.sess;
1007-
let doc_cfg_active = tcx.features().doc_cfg();
1008-
let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
1009-
1010-
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
1011-
let mut iter = it.into_iter();
1012-
let item = iter.next()?;
1013-
if iter.next().is_some() {
1014-
return None;
1015-
}
1016-
Some(item)
992+
pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
993+
attrs: I,
994+
name: Symbol,
995+
) -> impl Iterator<Item = ast::MetaItemInner> + use<'a, I> {
996+
attrs
997+
.into_iter()
998+
.filter(move |attr| attr.has_name(name))
999+
.filter_map(ast::attr::AttributeExt::meta_item_list)
1000+
.flatten()
1001+
}
1002+
1003+
pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>(
1004+
attrs: I,
1005+
tcx: TyCtxt<'_>,
1006+
hidden_cfg: &FxHashSet<Cfg>,
1007+
) -> Option<Arc<Cfg>> {
1008+
let sess = tcx.sess;
1009+
let doc_cfg_active = tcx.features().doc_cfg();
1010+
let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
1011+
1012+
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
1013+
let mut iter = it.into_iter();
1014+
let item = iter.next()?;
1015+
if iter.next().is_some() {
1016+
return None;
10171017
}
1018+
Some(item)
1019+
}
10181020

1019-
let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
1020-
let mut doc_cfg = self
1021-
.iter()
1022-
.filter(|attr| attr.has_name(sym::doc))
1023-
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
1021+
let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
1022+
let mut doc_cfg = attrs
1023+
.clone()
1024+
.filter(|attr| attr.has_name(sym::doc))
1025+
.flat_map(|attr| attr.meta_item_list().unwrap_or_default())
1026+
.filter(|attr| attr.has_name(sym::cfg))
1027+
.peekable();
1028+
if doc_cfg.peek().is_some() && doc_cfg_active {
1029+
doc_cfg
1030+
.filter_map(|attr| Cfg::parse(&attr).ok())
1031+
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
1032+
} else if doc_auto_cfg_active {
1033+
// If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
1034+
// `doc(cfg())` overrides `cfg()`).
1035+
attrs
1036+
.clone()
10241037
.filter(|attr| attr.has_name(sym::cfg))
1025-
.peekable();
1026-
if doc_cfg.peek().is_some() && doc_cfg_active {
1027-
doc_cfg
1028-
.filter_map(|attr| Cfg::parse(&attr).ok())
1029-
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
1030-
} else if doc_auto_cfg_active {
1031-
// If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
1032-
// `doc(cfg())` overrides `cfg()`).
1033-
self.iter()
1034-
.filter(|attr| attr.has_name(sym::cfg))
1035-
.filter_map(|attr| single(attr.meta_item_list()?))
1036-
.filter_map(|attr| {
1037-
Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()
1038-
})
1039-
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
1040-
} else {
1041-
Cfg::True
1042-
}
1038+
.filter_map(|attr| single(attr.meta_item_list()?))
1039+
.filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten())
1040+
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
10431041
} else {
10441042
Cfg::True
1045-
};
1046-
1047-
for attr in self.iter() {
1048-
// #[doc]
1049-
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
1050-
// #[doc(...)]
1051-
if let Some(list) = attr.meta_item_list() {
1052-
for item in list {
1053-
// #[doc(hidden)]
1054-
if !item.has_name(sym::cfg) {
1055-
continue;
1056-
}
1057-
// #[doc(cfg(...))]
1058-
if let Some(cfg_mi) = item
1059-
.meta_item()
1060-
.and_then(|item| rustc_expand::config::parse_cfg(item, sess))
1061-
{
1062-
match Cfg::parse(cfg_mi) {
1063-
Ok(new_cfg) => cfg &= new_cfg,
1064-
Err(e) => {
1065-
sess.dcx().span_err(e.span, e.msg);
1066-
}
1043+
}
1044+
} else {
1045+
Cfg::True
1046+
};
1047+
1048+
for attr in attrs.clone() {
1049+
// #[doc]
1050+
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
1051+
// #[doc(...)]
1052+
if let Some(list) = attr.meta_item_list() {
1053+
for item in list {
1054+
// #[doc(hidden)]
1055+
if !item.has_name(sym::cfg) {
1056+
continue;
1057+
}
1058+
// #[doc(cfg(...))]
1059+
if let Some(cfg_mi) = item
1060+
.meta_item()
1061+
.and_then(|item| rustc_expand::config::parse_cfg(item, sess))
1062+
{
1063+
match Cfg::parse(cfg_mi) {
1064+
Ok(new_cfg) => cfg &= new_cfg,
1065+
Err(e) => {
1066+
sess.dcx().span_err(e.span, e.msg);
10671067
}
10681068
}
10691069
}
10701070
}
10711071
}
10721072
}
1073+
}
10731074

1074-
// treat #[target_feature(enable = "feat")] attributes as if they were
1075-
// #[doc(cfg(target_feature = "feat"))] attributes as well
1076-
for attr in self.lists(sym::target_feature) {
1077-
if attr.has_name(sym::enable) {
1078-
if attr.value_str().is_some() {
1079-
// Clone `enable = "feat"`, change to `target_feature = "feat"`.
1080-
// Unwrap is safe because `value_str` succeeded above.
1081-
let mut meta = attr.meta_item().unwrap().clone();
1082-
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
1083-
1084-
if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
1085-
cfg &= feat_cfg;
1086-
}
1075+
// treat #[target_feature(enable = "feat")] attributes as if they were
1076+
// #[doc(cfg(target_feature = "feat"))] attributes as well
1077+
for attr in hir_attr_lists(attrs, sym::target_feature) {
1078+
if attr.has_name(sym::enable) {
1079+
if attr.value_str().is_some() {
1080+
// Clone `enable = "feat"`, change to `target_feature = "feat"`.
1081+
// Unwrap is safe because `value_str` succeeded above.
1082+
let mut meta = attr.meta_item().unwrap().clone();
1083+
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
1084+
1085+
if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) {
1086+
cfg &= feat_cfg;
10871087
}
10881088
}
10891089
}
1090-
1091-
if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
10921090
}
1093-
}
1094-
1095-
impl AttributesExt for [hir::Attribute] {
1096-
type AttributeIterator<'a> = impl Iterator<Item = ast::MetaItemInner> + 'a;
1097-
type Attributes<'a> = impl Iterator<Item = &'a hir::Attribute> + 'a;
10981091

1099-
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
1100-
self.iter()
1101-
.filter(move |attr| attr.has_name(name))
1102-
.filter_map(ast::attr::AttributeExt::meta_item_list)
1103-
.flatten()
1104-
}
1105-
1106-
fn iter(&self) -> Self::Attributes<'_> {
1107-
self.iter()
1108-
}
1109-
}
1110-
1111-
impl AttributesExt for [(Cow<'_, hir::Attribute>, Option<DefId>)] {
1112-
type AttributeIterator<'a>
1113-
= impl Iterator<Item = ast::MetaItemInner> + 'a
1114-
where
1115-
Self: 'a;
1116-
type Attributes<'a>
1117-
= impl Iterator<Item = &'a hir::Attribute> + 'a
1118-
where
1119-
Self: 'a;
1120-
1121-
fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> {
1122-
AttributesExt::iter(self)
1123-
.filter(move |attr| attr.has_name(name))
1124-
.filter_map(hir::Attribute::meta_item_list)
1125-
.flatten()
1126-
}
1127-
1128-
fn iter(&self) -> Self::Attributes<'_> {
1129-
self.iter().map(move |(attr, _)| match attr {
1130-
Cow::Borrowed(attr) => *attr,
1131-
Cow::Owned(attr) => attr,
1132-
})
1133-
}
1092+
if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
11341093
}
11351094

11361095
pub(crate) trait NestedAttributesExt {
@@ -1196,7 +1155,7 @@ pub(crate) struct Attributes {
11961155

11971156
impl Attributes {
11981157
pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> + '_ {
1199-
self.other_attrs.lists(name)
1158+
hir_attr_lists(&self.other_attrs[..], name)
12001159
}
12011160

12021161
pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool {
@@ -1263,7 +1222,9 @@ impl Attributes {
12631222
pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> {
12641223
let mut aliases = FxIndexSet::default();
12651224

1266-
for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) {
1225+
for attr in
1226+
hir_attr_lists(&self.other_attrs[..], sym::doc).filter(|a| a.has_name(sym::alias))
1227+
{
12671228
if let Some(values) = attr.meta_item_list() {
12681229
for l in values {
12691230
if let Some(lit) = l.lit()

src/librustdoc/doctest/rust.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ use rustc_span::source_map::SourceMap;
1313
use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span};
1414

1515
use super::{DocTestVisitor, ScrapedDocTest};
16-
use crate::clean::Attributes;
17-
use crate::clean::types::AttributesExt;
16+
use crate::clean::{Attributes, extract_cfg_from_attrs};
1817
use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine};
1918

2019
struct RustCollector {
@@ -97,7 +96,9 @@ impl HirCollector<'_> {
9796
nested: F,
9897
) {
9998
let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
100-
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
99+
if let Some(ref cfg) =
100+
extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
101+
{
101102
if !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features())) {
102103
return;
103104
}

src/librustdoc/visit_ast.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use tracing::debug;
1919

2020
use crate::clean::cfg::Cfg;
2121
use crate::clean::utils::{inherits_doc_hidden, should_ignore_res};
22-
use crate::clean::{AttributesExt, NestedAttributesExt, reexport_chain};
22+
use crate::clean::{NestedAttributesExt, hir_attr_lists, reexport_chain};
2323
use crate::core;
2424

2525
/// This module is used to store stuff from Rust's AST in a more convenient
@@ -247,8 +247,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
247247
let document_hidden = self.cx.render_options.document_hidden;
248248
let use_attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
249249
// Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
250-
let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
251-
|| (document_hidden && use_attrs.lists(sym::doc).has_word(sym::hidden));
250+
let is_no_inline = hir_attr_lists(use_attrs, sym::doc).has_word(sym::no_inline)
251+
|| (document_hidden && hir_attr_lists(use_attrs, sym::doc).has_word(sym::hidden));
252252

253253
if is_no_inline {
254254
return false;

0 commit comments

Comments
 (0)