Skip to content

Commit 9d14b47

Browse files
Return an iterator instead of a Vec in rustdoc Item::attributes
1 parent cb0d6e7 commit 9d14b47

File tree

2 files changed

+76
-44
lines changed

2 files changed

+76
-44
lines changed

src/librustdoc/clean/types.rs

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -759,48 +759,9 @@ impl Item {
759759
Some(tcx.visibility(def_id))
760760
}
761761

762-
pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> {
763-
const ALLOWED_ATTRIBUTES: &[Symbol] =
764-
&[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
765-
762+
fn adt_item_extra_attrs(&self, tcx: TyCtxt<'_>, document_private: bool) -> Option<String> {
766763
use rustc_abi::IntegerType;
767764

768-
let mut attrs: Vec<String> = self
769-
.attrs
770-
.other_attrs
771-
.iter()
772-
.filter_map(|attr| {
773-
if is_json {
774-
match attr {
775-
hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => {
776-
// rustdoc-json stores this in `Item::deprecation`, so we
777-
// don't want it it `Item::attrs`.
778-
None
779-
}
780-
rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr(
781-
..,
782-
)) => {
783-
// We have separate pretty-printing logic for `#[repr(..)]` attributes.
784-
// For example, there are circumstances where `#[repr(transparent)]`
785-
// is applied but should not be publicly shown in rustdoc
786-
// because it isn't public API.
787-
None
788-
}
789-
_ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
790-
}
791-
} else if attr.has_any_name(ALLOWED_ATTRIBUTES) {
792-
Some(
793-
rustc_hir_pretty::attribute_to_string(&tcx, attr)
794-
.replace("\\\n", "")
795-
.replace('\n', "")
796-
.replace(" ", " "),
797-
)
798-
} else {
799-
None
800-
}
801-
})
802-
.collect();
803-
804765
// Add #[repr(...)]
805766
if let Some(def_id) = self.def_id()
806767
&& let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_()
@@ -814,7 +775,7 @@ impl Item {
814775
if repr.transparent() {
815776
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
816777
// field is public in case all fields are 1-ZST fields.
817-
let render_transparent = cache.document_private
778+
let render_transparent = document_private
818779
|| adt
819780
.all_fields()
820781
.find(|field| {
@@ -860,10 +821,55 @@ impl Item {
860821
out.push(&int_s);
861822
}
862823
if !out.is_empty() {
863-
attrs.push(format!("#[repr({})]", out.join(", ")));
824+
return Some(format!("#[repr({})]", out.join(", ")));
864825
}
865826
}
866-
attrs
827+
None
828+
}
829+
830+
pub(crate) fn attributes(
831+
&self,
832+
tcx: TyCtxt<'_>,
833+
cache: &Cache,
834+
is_json: bool,
835+
) -> impl Iterator<Item = String> {
836+
const ALLOWED_ATTRIBUTES: &[Symbol] =
837+
&[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
838+
839+
self.attrs
840+
.other_attrs
841+
.iter()
842+
.filter_map(move |attr| {
843+
if is_json {
844+
match attr {
845+
hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => {
846+
// rustdoc-json stores this in `Item::deprecation`, so we
847+
// don't want it it `Item::attrs`.
848+
None
849+
}
850+
rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr(
851+
..,
852+
)) => {
853+
// We have separate pretty-printing logic for `#[repr(..)]` attributes.
854+
// For example, there are circumstances where `#[repr(transparent)]`
855+
// is applied but should not be publicly shown in rustdoc
856+
// because it isn't public API.
857+
None
858+
}
859+
_ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
860+
}
861+
} else if attr.has_any_name(ALLOWED_ATTRIBUTES) {
862+
Some(
863+
rustc_hir_pretty::attribute_to_string(&tcx, attr)
864+
.replace("\\\n", "")
865+
.replace('\n', "")
866+
.replace(" ", " "),
867+
)
868+
} else {
869+
None
870+
}
871+
})
872+
.chain(AttrIterator::new(self, cache.document_private, tcx))
867873
}
868874

869875
pub fn is_doc_hidden(&self) -> bool {
@@ -875,6 +881,32 @@ impl Item {
875881
}
876882
}
877883

884+
struct AttrIterator<'a, 'tcx> {
885+
item: &'a Item,
886+
document_private: bool,
887+
tcx: TyCtxt<'tcx>,
888+
done: bool,
889+
}
890+
891+
impl<'a, 'tcx> AttrIterator<'a, 'tcx> {
892+
fn new(item: &'a Item, document_private: bool, tcx: TyCtxt<'tcx>) -> Self {
893+
Self { item, document_private, tcx, done: false }
894+
}
895+
}
896+
897+
impl<'a, 'tcx> Iterator for AttrIterator<'a, 'tcx> {
898+
type Item = String;
899+
900+
fn next(&mut self) -> Option<Self::Item> {
901+
if self.done {
902+
return None;
903+
}
904+
let ret = self.item.adt_item_extra_attrs(self.tcx, self.document_private);
905+
self.done = true;
906+
ret
907+
}
908+
}
909+
878910
#[derive(Clone, Debug)]
879911
pub(crate) enum ItemKind {
880912
ExternCrateItem {

src/librustdoc/json/conversions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl JsonRenderer<'_> {
4040
})
4141
.collect();
4242
let docs = item.opt_doc_value();
43-
let attrs = item.attributes(self.tcx, self.cache(), true);
43+
let attrs = item.attributes(self.tcx, self.cache(), true).collect::<Vec<_>>();
4444
let span = item.span(self.tcx);
4545
let visibility = item.visibility(self.tcx);
4646
let clean::ItemInner { name, item_id, .. } = *item.inner;

0 commit comments

Comments
 (0)