1
Fork 0

Use AttrVec in more places.

In some places we use `Vec<Attribute>` and some places we use
`ThinVec<Attribute>` (a.k.a. `AttrVec`). This results in various points
where we have to convert between `Vec` and `ThinVec`.

This commit changes the places that use `Vec<Attribute>` to use
`AttrVec`. A lot of this is mechanical and boring, but there are
some interesting parts:
- It adds a few new methods to `ThinVec`.
- It implements `MapInPlace` for `ThinVec`, and introduces a macro to
  avoid the repetition of this trait for `Vec`, `SmallVec`, and
  `ThinVec`.

Overall, it makes the code a little nicer, and has little effect on
performance. But it is a precursor to removing
`rustc_data_structures::thin_vec::ThinVec` and replacing it with
`thin_vec::ThinVec`, which is implemented more efficiently.
This commit is contained in:
Nicholas Nethercote 2022-08-17 12:34:33 +10:00
parent 650bff80a6
commit 619b8abaa6
49 changed files with 352 additions and 392 deletions

View file

@ -6,7 +6,7 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Nonterminal};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{AssocCtxt, Visitor};
use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind};
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
use rustc_attr::{self as attr, Deprecation, Stability};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::sync::{self, Lrc};
@ -71,7 +71,7 @@ impl Annotatable {
}
}
pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
match self {
Annotatable::Item(item) => item.visit_attrs(f),
Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f),

View file

@ -575,7 +575,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
name: Ident,
attrs: Vec<ast::Attribute>,
attrs: ast::AttrVec,
kind: ast::ItemKind,
) -> P<ast::Item> {
// FIXME: Would be nice if our generated code didn't violate
@ -603,7 +603,7 @@ impl<'a> ExtCtxt<'a> {
mutbl: ast::Mutability,
expr: P<ast::Expr>,
) -> P<ast::Item> {
self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
self.item(span, name, AttrVec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
}
pub fn item_const(
@ -614,7 +614,7 @@ impl<'a> ExtCtxt<'a> {
expr: P<ast::Expr>,
) -> P<ast::Item> {
let def = ast::Defaultness::Final;
self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
}
pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {

View file

@ -215,7 +215,7 @@ pub fn features(
let features = match strip_unconfigured.configure_krate_attrs(krate.attrs) {
None => {
// The entire crate is unconfigured.
krate.attrs = Vec::new();
krate.attrs = ast::AttrVec::new();
krate.items = Vec::new();
Features::default()
}
@ -265,7 +265,7 @@ impl<'a> StripUnconfigured<'a> {
}
}
fn configure_krate_attrs(&self, mut attrs: Vec<ast::Attribute>) -> Option<Vec<ast::Attribute>> {
fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
if self.in_cfg(&attrs) { Some(attrs) } else { None }
}
@ -292,9 +292,7 @@ impl<'a> StripUnconfigured<'a> {
.iter()
.flat_map(|(tree, spacing)| match tree.clone() {
AttrAnnotatedTokenTree::Attributes(mut data) => {
let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into();
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
data.attrs = attrs.into();
data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
if self.in_cfg(&data.attrs) {
data.tokens = LazyTokenStream::new(

View file

@ -11,7 +11,7 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, ExprKind, ForeignItemKind};
use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, AttrVec, ExprKind, ForeignItemKind};
use rustc_ast::{HasAttrs, HasNodeId};
use rustc_ast::{Inline, ItemKind, MacArgs, MacStmtStyle, MetaItemKind, ModKind};
use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
@ -1001,7 +1001,7 @@ enum AddSemicolon {
/// of functionality used by `InvocationCollector`.
trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
type OutputTy = SmallVec<[Self; 1]>;
type AttrsTy: Deref<Target = [ast::Attribute]> = Vec<ast::Attribute>;
type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
const KIND: AstFragmentKind;
fn to_annotatable(self) -> Annotatable;
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
@ -1333,7 +1333,7 @@ impl InvocationCollectorNode for ast::Stmt {
}
StmtKind::Item(item) => match item.into_inner() {
ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
(mac.args.need_semicolon(), mac, attrs.into())
(mac.args.need_semicolon(), mac, attrs)
}
_ => unreachable!(),
},
@ -1390,7 +1390,7 @@ impl InvocationCollectorNode for P<ast::Ty> {
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
let node = self.into_inner();
match node.kind {
TyKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No),
TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
_ => unreachable!(),
}
}
@ -1414,7 +1414,7 @@ impl InvocationCollectorNode for P<ast::Pat> {
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
let node = self.into_inner();
match node.kind {
PatKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No),
PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
_ => unreachable!(),
}
}
@ -1646,7 +1646,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) {
node.visit_attrs(|attrs| {
attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
// Repeated `insert` calls is inefficient, but the number of
// insertions is almost always 0 or 1 in practice.
for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() {
attrs.insert(pos, cfg)
}
});
}

View file

@ -1,6 +1,6 @@
use crate::base::ModuleData;
use rustc_ast::ptr::P;
use rustc_ast::{token, Attribute, Inline, Item, ModSpans};
use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
use rustc_parse::new_parser_from_file;
use rustc_parse::validate_attr;
@ -48,7 +48,7 @@ pub(crate) fn parse_external_mod(
span: Span, // The span to blame on errors.
module: &ModuleData,
mut dir_ownership: DirOwnership,
attrs: &mut Vec<Attribute>,
attrs: &mut AttrVec,
) -> ParsedExternalMod {
// We bail on the first error, but that error does not cause a fatal error... (1)
let result: Result<_, ModError<'_>> = try {
@ -63,9 +63,9 @@ pub(crate) fn parse_external_mod(
// Actually parse the external file as a module.
let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span));
let (mut inner_attrs, items, inner_span) =
let (inner_attrs, items, inner_span) =
parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?;
attrs.append(&mut inner_attrs);
attrs.extend(inner_attrs);
(items, inner_span, mp.file_path)
};
// (1) ...instead, we return a dummy module.

View file

@ -24,7 +24,7 @@ pub fn placeholder(
}
let ident = Ident::empty();
let attrs = Vec::new();
let attrs = ast::AttrVec::new();
let vis = vis.unwrap_or(ast::Visibility {
span: DUMMY_SP,
kind: ast::VisibilityKind::Inherited,