Auto merge of #77990 - bugadani:copies, r=lcnr

Eliminate some temporary vectors

This PR changes `get_item_attrs` and `get_item_variances` to return iterator impls instead of vectors. On top of that, this PR replaces some seemingly unnecessary vectors with iterators or SmallVec, and also reserves space where we know (the minimum) number of elements that will be inserted. This change hopes to remove a few heap allocations and unnecessary copies.
This commit is contained in:
bors 2020-11-13 11:49:33 +00:00
commit a1f7ca788d
8 changed files with 50 additions and 45 deletions

View File

@ -221,7 +221,7 @@ impl TokenStream {
}
}
if let Some((pos, comma, sp)) = suggestion {
let mut new_stream = vec![];
let mut new_stream = Vec::with_capacity(self.0.len() + 1);
let parts = self.0.split_at(pos + 1);
new_stream.extend_from_slice(parts.0);
new_stream.push(comma);

View File

@ -1367,14 +1367,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut used_input_regs = FxHashMap::default();
let mut used_output_regs = FxHashMap::default();
let mut required_features: Vec<&str> = vec![];
for (idx, op) in operands.iter().enumerate() {
let op_sp = asm.operands[idx].1;
if let Some(reg) = op.reg() {
// Make sure we don't accidentally carry features from the
// previous iteration.
required_features.clear();
// Validate register classes against currently enabled target
// features. We check that at least one type is available for
// the current target.
let reg_class = reg.reg_class();
let mut required_features: Vec<&str> = vec![];
for &(_, feature) in reg_class.supported_types(asm_arch) {
if let Some(feature) = feature {
if self.sess.target_features.contains(&Symbol::intern(feature)) {

View File

@ -2011,17 +2011,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
//
// For the "output" lifetime parameters, we just want to
// generate `'_`.
let mut generic_args: Vec<_> = lifetime_params[..input_lifetimes_count]
.iter()
.map(|&(span, hir_name)| {
let mut generic_args = Vec::with_capacity(lifetime_params.len());
generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map(
|&(span, hir_name)| {
// Input lifetime like `'a` or `'1`:
GenericArg::Lifetime(hir::Lifetime {
hir_id: self.next_id(),
span,
name: hir::LifetimeName::Param(hir_name),
})
})
.collect();
},
));
generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)|
// Output lifetime like `'_`.
GenericArg::Lifetime(hir::Lifetime {
@ -2312,29 +2312,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> {
let mut stmts = vec![];
let mut expr: Option<&'hir _> = None;
for (index, stmt) in b.stmts.iter().enumerate() {
if index == b.stmts.len() - 1 {
if let StmtKind::Expr(ref e) = stmt.kind {
expr = Some(self.lower_expr(e));
} else {
stmts.extend(self.lower_stmt(stmt));
}
} else {
stmts.extend(self.lower_stmt(stmt));
}
}
let stmts = self.arena.alloc_from_iter(
b.stmts
.iter()
.enumerate()
.filter_map(|(index, stmt)| {
if index == b.stmts.len() - 1 {
if let StmtKind::Expr(ref e) = stmt.kind {
expr = Some(self.lower_expr(e));
None
} else {
Some(self.lower_stmt(stmt))
}
} else {
Some(self.lower_stmt(stmt))
}
})
.flatten(),
);
let rules = self.lower_block_check_mode(&b.rules);
let hir_id = self.lower_node_id(b.id);
hir::Block {
hir_id: self.lower_node_id(b.id),
stmts: self.arena.alloc_from_iter(stmts),
expr,
rules: self.lower_block_check_mode(&b.rules),
span: b.span,
targeted_by_break,
}
hir::Block { hir_id, stmts, expr, rules, span: b.span, targeted_by_break }
}
/// Lowers a block directly to an expression, presuming that it

View File

@ -66,7 +66,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let fmt = substr.nonself_args[0].clone();
let mut stmts = vec![];
let mut stmts = Vec::with_capacity(fields.len() + 2);
match vdata {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
// tuple struct/"normal" variant

View File

@ -30,6 +30,8 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
let mut builder = LintLevelMapBuilder { levels, tcx, store };
let krate = tcx.hir().krate();
builder.levels.id_to_set.reserve(krate.exported_macros.len() + 1);
let push = builder.levels.push(&krate.item.attrs, &store, true);
builder.levels.register_id(hir::CRATE_HIR_ID);
for macro_def in krate.exported_macros {

View File

@ -784,6 +784,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
};
let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
SyntaxExtension::new(
sess,
kind,
@ -791,7 +792,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
helper_attrs,
self.root.edition,
Symbol::intern(name),
&self.get_item_attrs(id, sess),
&attrs,
)
}
@ -1157,7 +1158,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
// within the crate. We only need this for fictive constructors,
// for other constructors correct visibilities
// were already encoded in metadata.
let attrs = self.get_item_attrs(def_id.index, sess);
let attrs: Vec<_> =
self.get_item_attrs(def_id.index, sess).collect();
if sess.contains_name(&attrs, sym::non_exhaustive) {
let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
vis = ty::Visibility::Restricted(crate_def_id);
@ -1283,8 +1285,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
}
fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self).collect()
fn get_item_variances(&'a self, id: DefIndex) -> impl Iterator<Item = ty::Variance> + 'a {
self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self)
}
fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
@ -1308,7 +1310,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
}
fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Vec<ast::Attribute> {
fn get_item_attrs(
&'a self,
node_id: DefIndex,
sess: &'a Session,
) -> impl Iterator<Item = ast::Attribute> + 'a {
// The attributes for a tuple struct/variant are attached to the definition, not the ctor;
// we assume that someone passing in a tuple struct ctor is actually wanting to
// look at the definition
@ -1325,7 +1331,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.get(self, item_id)
.unwrap_or_else(Lazy::empty)
.decode((self, sess))
.collect::<Vec<_>>()
}
fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<Symbol>> {

View File

@ -138,7 +138,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
}
item_attrs => { tcx.arena.alloc_from_iter(
cdata.get_item_attrs(def_id.index, tcx.sess).into_iter()
cdata.get_item_attrs(def_id.index, tcx.sess)
) }
fn_arg_names => { cdata.get_fn_param_names(tcx, def_id.index) }
rendered_const => { cdata.get_rendered_const(def_id.index) }
@ -415,11 +415,7 @@ impl CStore {
let span = data.get_span(id.index, sess);
// Mark the attrs as used
let attrs = data.get_item_attrs(id.index, sess);
for attr in attrs.iter() {
sess.mark_attr_used(attr);
}
let attrs = data.get_item_attrs(id.index, sess).collect();
let ident = data.item_ident(id.index, sess);
@ -428,7 +424,7 @@ impl CStore {
ident,
id: ast::DUMMY_NODE_ID,
span,
attrs: attrs.to_vec(),
attrs,
kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)),
vis: ast::Visibility {
span: span.shrink_to_lo(),

View File

@ -353,16 +353,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
// Keep only those bounds which may apply, and propagate overflow if it occurs.
let mut param_candidates = vec![];
for bound in matching_bounds {
let wc = self.evaluate_where_clause(stack, bound)?;
if wc.may_apply() {
param_candidates.push(ParamCandidate(bound));
candidates.vec.push(ParamCandidate(bound));
}
}
candidates.vec.extend(param_candidates);
Ok(())
}