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:
commit
a1f7ca788d
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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>> {
|
||||
|
@ -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(),
|
||||
|
@ -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(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user