Skip to content

Commit

Permalink
Auto merge of #92353 - Kobzol:doc-attr-lists-gat, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Rustdoc: remove ListAttributesIter and use impl Iterator instead

This is a continuation of #92227.

I found that `ListAttributesIter` did not optimize well and replacing it with a simple `impl Iterator` resulted in 1-3 % instruction count wins locally.

Because I needed to use `impl Iterator` on a slice of AST attributes, I had to implement it using GAT + impl trait. I also have a version without GAT [here](Kobzol@5470e2a), if GATs are not welcome in rustdoc :D Locally it resulted in equal performance numbers.

Can I ask for a perf. run? Thanks.

r? rust-lang/rustdoc
  • Loading branch information
bors committed Jan 25, 2022
2 parents 17dfae7 + 3a3e4b7 commit 92ed874
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 46 deletions.
63 changes: 17 additions & 46 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::lazy::SyncOnceCell as OnceCell;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::{slice, vec};
use std::vec;

use arrayvec::ArrayVec;

Expand Down Expand Up @@ -733,43 +733,12 @@ crate struct Module {
crate span: Span,
}

crate struct ListAttributesIter<'a> {
attrs: slice::Iter<'a, ast::Attribute>,
current_list: vec::IntoIter<ast::NestedMetaItem>,
name: Symbol,
}

impl<'a> Iterator for ListAttributesIter<'a> {
type Item = ast::NestedMetaItem;

fn next(&mut self) -> Option<Self::Item> {
if let Some(nested) = self.current_list.next() {
return Some(nested);
}

for attr in &mut self.attrs {
if let Some(list) = attr.meta_item_list() {
if attr.has_name(self.name) {
self.current_list = list.into_iter();
if let Some(nested) = self.current_list.next() {
return Some(nested);
}
}
}
}

None
}

fn size_hint(&self) -> (usize, Option<usize>) {
let lower = self.current_list.len();
(lower, None)
}
}

crate trait AttributesExt {
/// Finds an attribute as List and returns the list of attributes nested inside.
fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
type AttributeIterator<'a>: Iterator<Item = ast::NestedMetaItem>
where
Self: 'a;

fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a>;

fn span(&self) -> Option<rustc_span::Span>;

Expand All @@ -781,8 +750,13 @@ crate trait AttributesExt {
}

impl AttributesExt for [ast::Attribute] {
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a;

fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
self.iter()
.filter(move |attr| attr.has_name(name))
.filter_map(ast::Attribute::meta_item_list)
.flatten()
}

/// Return the span of the first doc-comment, if it exists.
Expand Down Expand Up @@ -902,12 +876,9 @@ crate trait NestedAttributesExt {
fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem>;
}

impl<I> NestedAttributesExt for I
where
I: IntoIterator<Item = ast::NestedMetaItem>,
{
fn get_word_attr(self, word: Symbol) -> Option<ast::NestedMetaItem> {
self.into_iter().find(|attr| attr.is_word() && attr.has_name(word))
impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
self.find(|attr| attr.is_word() && attr.has_name(word))
}
}

Expand Down Expand Up @@ -1015,7 +986,7 @@ crate struct Attributes {
}

impl Attributes {
crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
crate fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::NestedMetaItem> + '_ {
self.other_attrs.lists(name)
}

Expand Down
2 changes: 2 additions & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#![feature(once_cell)]
#![feature(type_ascription)]
#![feature(iter_intersperse)]
#![feature(type_alias_impl_trait)]
#![feature(generic_associated_types)]
#![recursion_limit = "256"]
#![warn(rustc::internal)]
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
Expand Down

0 comments on commit 92ed874

Please sign in to comment.