Skip to content

Commit de61a78

Browse files
Use Cow to reduce numbers of memory clone
1 parent c8c342c commit de61a78

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

src/librustdoc/clean/mod.rs

+29-25
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
3232
use rustc_span::{self, ExpnKind};
3333

3434
use std::assert_matches::assert_matches;
35+
use std::borrow::Cow;
3536
use std::collections::hash_map::Entry;
3637
use std::collections::BTreeMap;
3738
use std::default::Default;
@@ -2171,26 +2172,25 @@ fn get_all_import_attributes<'hir>(
21712172
target_def_id: LocalDefId,
21722173
is_inline: bool,
21732174
mut prev_import: LocalDefId,
2174-
) -> Vec<(ast::Attribute, Option<DefId>)> {
2175-
let mut attributes: Vec<(ast::Attribute, Option<DefId>)> = Vec::new();
2175+
) -> Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> {
2176+
let mut attributes: Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)> = Vec::new();
21762177
let mut first = true;
21772178
let hir_map = cx.tcx.hir();
21782179
let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
21792180
let mut visited = FxHashSet::default();
2180-
let mut import_attrs = Vec::new();
21812181

21822182
// If the item is an import and has at least a path with two parts, we go into it.
21832183
while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
21842184
let import_parent = cx.tcx.opt_local_parent(prev_import).map(|def_id| def_id.to_def_id());
21852185
if first {
21862186
// This is the "original" reexport so we get all its attributes without filtering them.
2187-
attributes = hir_map.attrs(item.hir_id()).iter().cloned().map(|attr| (attr, import_parent)).collect::<Vec<_>>();
2187+
attributes = hir_map.attrs(item.hir_id())
2188+
.iter()
2189+
.map(|attr| (Cow::Borrowed(attr), import_parent))
2190+
.collect::<Vec<_>>();
21882191
first = false;
21892192
} else {
2190-
add_without_unwanted_attributes(&mut import_attrs, hir_map.attrs(item.hir_id()), is_inline);
2191-
for attr in import_attrs.drain(..) {
2192-
attributes.push((attr, import_parent));
2193-
}
2193+
add_without_unwanted_attributes(&mut attributes, hir_map.attrs(item.hir_id()), is_inline, import_parent);
21942194
}
21952195

21962196
if let Some(i) = visitor.find_target(cx.tcx, item.owner_id.def_id.to_def_id(), path) {
@@ -2246,17 +2246,24 @@ fn filter_tokens_from_list(
22462246
/// * `doc(inline)`
22472247
/// * `doc(no_inline)`
22482248
/// * `doc(hidden)`
2249-
fn add_without_unwanted_attributes(
2250-
attrs: &mut Vec<ast::Attribute>,
2251-
new_attrs: &[ast::Attribute],
2249+
fn add_without_unwanted_attributes<'hir>(
2250+
attrs: &mut Vec<(Cow<'hir, ast::Attribute>, Option<DefId>)>,
2251+
new_attrs: &'hir [ast::Attribute],
22522252
is_inline: bool,
2253+
import_parent: Option<DefId>,
22532254
) {
22542255
// If it's not `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything.
22552256
if !is_inline {
2256-
attrs.extend_from_slice(new_attrs);
2257+
for attr in new_attrs {
2258+
attrs.push((Cow::Borrowed(attr), import_parent));
2259+
}
22572260
return;
22582261
}
22592262
for attr in new_attrs {
2263+
if matches!(attr.kind, ast::AttrKind::DocComment(..)) {
2264+
attrs.push((Cow::Borrowed(attr), import_parent));
2265+
continue;
2266+
}
22602267
let mut attr = attr.clone();
22612268
match attr.kind {
22622269
ast::AttrKind::Normal(ref mut normal) => {
@@ -2283,18 +2290,15 @@ fn add_without_unwanted_attributes(
22832290
)
22842291
});
22852292
args.tokens = TokenStream::new(tokens);
2286-
attrs.push(attr);
2293+
attrs.push((Cow::Owned(attr), import_parent));
22872294
}
22882295
ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {
2289-
attrs.push(attr);
2290-
continue;
2296+
attrs.push((Cow::Owned(attr), import_parent));
22912297
}
22922298
}
22932299
}
22942300
}
2295-
ast::AttrKind::DocComment(..) => {
2296-
attrs.push(attr);
2297-
}
2301+
_ => unreachable!(),
22982302
}
22992303
}
23002304
}
@@ -2397,23 +2401,23 @@ fn clean_maybe_renamed_item<'tcx>(
23972401
import_id,
23982402
);
23992403

2400-
let mut target_attrs = Vec::new();
24012404
add_without_unwanted_attributes(
2402-
&mut target_attrs,
2405+
&mut attrs,
24032406
inline::load_attrs(cx, def_id),
24042407
is_inline,
2408+
None
24052409
);
2406-
for attr in target_attrs.into_iter() {
2407-
attrs.push((attr, None));
2408-
}
24092410
attrs
24102411
} else {
24112412
// We only keep the item's attributes.
2412-
inline::load_attrs(cx, def_id).iter().cloned().map(|attr| (attr, None)).collect::<Vec<_>>()
2413+
inline::load_attrs(cx, def_id).iter().map(|attr| (Cow::Borrowed(attr), None)).collect::<Vec<_>>()
24132414
};
24142415

24152416
let cfg = attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
2416-
let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (attr, *did)), false);
2417+
let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| match attr {
2418+
Cow::Borrowed(attr) => (*attr, *did),
2419+
Cow::Owned(attr) => (attr, *did)
2420+
}), false);
24172421

24182422
let mut item =
24192423
Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg);

src/librustdoc/clean/types.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::cell::RefCell;
23
use std::default::Default;
34
use std::hash::Hash;
@@ -985,9 +986,11 @@ impl AttributesExt for [ast::Attribute] {
985986
}
986987
}
987988

988-
impl AttributesExt for [(ast::Attribute, Option<DefId>)] {
989-
type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a;
990-
type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a;
989+
impl AttributesExt for [(Cow<'_, ast::Attribute>, Option<DefId>)] {
990+
type AttributeIterator<'a> = impl Iterator<Item = ast::NestedMetaItem> + 'a
991+
where Self: 'a;
992+
type Attributes<'a> = impl Iterator<Item = &'a ast::Attribute> + 'a
993+
where Self: 'a;
991994

992995
fn lists<'a>(&'a self, name: Symbol) -> Self::AttributeIterator<'a> {
993996
AttributesExt::iter(self)
@@ -997,7 +1000,10 @@ impl AttributesExt for [(ast::Attribute, Option<DefId>)] {
9971000
}
9981001

9991002
fn iter<'a>(&'a self) -> Self::Attributes<'a> {
1000-
self.into_iter().map(|(attr, _)| attr)
1003+
self.into_iter().map(move |(attr, _)| match attr {
1004+
Cow::Borrowed(attr) => *attr,
1005+
Cow::Owned(attr) => attr,
1006+
})
10011007
}
10021008
}
10031009

0 commit comments

Comments
 (0)