Skip to content

Commit

Permalink
Auto merge of rust-lang#17671 - Veykril:binding-size, r=Veykril
Browse files Browse the repository at this point in the history
internal: Shrink size of `Binding`

This should save a bit of memory now that we LRU the source map
  • Loading branch information
bors committed Jul 22, 2024
2 parents be1dc79 + 83a3087 commit 28b8c24
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 56 deletions.
10 changes: 9 additions & 1 deletion src/tools/rust-analyzer/crates/hir-def/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ pub mod scope;
#[cfg(test)]
mod tests;

use std::ops::Index;
use std::ops::{Deref, Index};

use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use hir_expand::{name::Name, InFile};
use la_arena::{Arena, ArenaMap};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::MacroFileId;
use syntax::{ast, AstPtr, SyntaxNodePtr};
use triomphe::Arc;
Expand Down Expand Up @@ -91,6 +92,7 @@ pub struct BodySourceMap {
label_map_back: ArenaMap<LabelId, LabelSource>,

self_param: Option<InFile<AstPtr<ast::SelfParam>>>,
binding_definitions: FxHashMap<BindingId, SmallVec<[PatId; 4]>>,

/// We don't create explicit nodes for record fields (`S { record_field: 92 }`).
/// Instead, we use id of expression (`92`) to identify the field.
Expand Down Expand Up @@ -377,6 +379,10 @@ impl BodySourceMap {
self.label_map_back[label]
}

pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] {
self.binding_definitions.get(&binding).map_or(&[], Deref::deref)
}

pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
let src = node.map(AstPtr::new);
self.label_map.get(&src).cloned()
Expand Down Expand Up @@ -428,6 +434,7 @@ impl BodySourceMap {
expansions,
format_args_template_map,
diagnostics,
binding_definitions,
} = self;
format_args_template_map.shrink_to_fit();
expr_map.shrink_to_fit();
Expand All @@ -440,5 +447,6 @@ impl BodySourceMap {
pat_field_map_back.shrink_to_fit();
expansions.shrink_to_fit();
diagnostics.shrink_to_fit();
binding_definitions.shrink_to_fit();
}
}
15 changes: 5 additions & 10 deletions src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use hir_expand::{
};
use intern::{sym, Interned, Symbol};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::AstIdMap;
use stdx::never;
use syntax::{
Expand Down Expand Up @@ -1437,11 +1436,12 @@ impl ExprCollector<'_> {
args: AstChildren<ast::Pat>,
has_leading_comma: bool,
binding_list: &mut BindingList,
) -> (Box<[PatId]>, Option<usize>) {
) -> (Box<[PatId]>, Option<u32>) {
let args: Vec<_> = args.map(|p| self.collect_pat_possibly_rest(p, binding_list)).collect();
// Find the location of the `..`, if there is one. Note that we do not
// consider the possibility of there being multiple `..` here.
let ellipsis = args.iter().position(|p| p.is_right());
let ellipsis = args.iter().position(|p| p.is_right()).map(|it| it as u32);

// We want to skip the `..` pattern here, since we account for it above.
let mut args: Vec<_> = args.into_iter().filter_map(Either::left).collect();
// if there is a leading comma, the user is most likely to type out a leading pattern
Expand Down Expand Up @@ -1512,7 +1512,7 @@ impl ExprCollector<'_> {
}

fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) {
self.body.bindings[binding_id].definitions.push(pat_id);
self.source_map.binding_definitions.entry(binding_id).or_default().push(pat_id);
}

// region: labels
Expand Down Expand Up @@ -2058,12 +2058,7 @@ impl ExprCollector<'_> {
}

fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
let binding = self.body.bindings.alloc(Binding {
name,
mode,
definitions: SmallVec::new(),
problems: None,
});
let binding = self.body.bindings.alloc(Binding { name, mode, problems: None });
if let Some(owner) = self.current_binding_owner {
self.body.binding_owners.insert(binding, owner);
}
Expand Down
4 changes: 2 additions & 2 deletions src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl Printer<'_> {
if i != 0 {
w!(self, ", ");
}
if *ellipsis == Some(i) {
if *ellipsis == Some(i as u32) {
w!(self, ".., ");
}
self.print_pat(*pat);
Expand Down Expand Up @@ -595,7 +595,7 @@ impl Printer<'_> {
if i != 0 {
w!(self, ", ");
}
if *ellipsis == Some(i) {
if *ellipsis == Some(i as u32) {
w!(self, ", ..");
}
self.print_pat(*arg);
Expand Down
4 changes: 2 additions & 2 deletions src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ fn foo() {
let function = find_function(&db, file_id.file_id());

let scopes = db.expr_scopes(function.into());
let (body, source_map) = db.body_with_source_map(function.into());
let (_, source_map) = db.body_with_source_map(function.into());

let expr_scope = {
let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
Expand All @@ -495,7 +495,7 @@ fn foo() {

let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
let pat_src = source_map
.pat_syntax(*body.bindings[resolved.binding()].definitions.first().unwrap())
.pat_syntax(*source_map.binding_definitions[&resolved.binding()].first().unwrap())
.unwrap();

let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax());
Expand Down
6 changes: 2 additions & 4 deletions src/tools/rust-analyzer/crates/hir-def/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use hir_expand::name::Name;
use intern::{Interned, Symbol};
use la_arena::{Idx, RawIdx};
use rustc_apfloat::ieee::{Half as f16, Quad as f128};
use smallvec::SmallVec;
use syntax::ast;

use crate::{
Expand Down Expand Up @@ -525,7 +524,6 @@ pub enum BindingProblems {
pub struct Binding {
pub name: Name,
pub mode: BindingAnnotation,
pub definitions: SmallVec<[PatId; 1]>,
pub problems: Option<BindingProblems>,
}

Expand All @@ -540,15 +538,15 @@ pub struct RecordFieldPat {
pub enum Pat {
Missing,
Wild,
Tuple { args: Box<[PatId]>, ellipsis: Option<usize> },
Tuple { args: Box<[PatId]>, ellipsis: Option<u32> },
Or(Box<[PatId]>),
Record { path: Option<Box<Path>>, args: Box<[RecordFieldPat]>, ellipsis: bool },
Range { start: Option<Box<LiteralOrConst>>, end: Option<Box<LiteralOrConst>> },
Slice { prefix: Box<[PatId]>, slice: Option<PatId>, suffix: Box<[PatId]> },
Path(Box<Path>),
Lit(ExprId),
Bind { id: BindingId, subpat: Option<PatId> },
TupleStruct { path: Option<Box<Path>>, args: Box<[PatId]>, ellipsis: Option<usize> },
TupleStruct { path: Option<Box<Path>>, args: Box<[PatId]>, ellipsis: Option<u32> },
Ref { pat: PatId, mutability: Mutability },
Box { inner: PatId },
ConstBlock(ExprId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,15 @@ impl<'a> PatCtxt<'a> {
&mut self,
pats: &[PatId],
expected_len: usize,
ellipsis: Option<usize>,
ellipsis: Option<u32>,
) -> Vec<FieldPat> {
if pats.len() > expected_len {
self.errors.push(PatternError::ExtraFields);
return Vec::new();
}

pats.iter()
.enumerate_and_adjust(expected_len, ellipsis)
.enumerate_and_adjust(expected_len, ellipsis.map(|it| it as usize))
.map(|(i, &subpattern)| FieldPat {
field: LocalFieldId::from_raw((i as u32).into()),
pattern: self.lower_pattern(subpattern),
Expand Down
4 changes: 2 additions & 2 deletions src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,7 @@ impl InferenceContext<'_> {
match &self.body[pat] {
Pat::Missing | Pat::Wild => (),
Pat::Tuple { args, ellipsis } => {
let (al, ar) = args.split_at(ellipsis.unwrap_or(args.len()));
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let field_count = match self.result[pat].kind(Interner) {
TyKind::Tuple(_, s) => s.len(Interner),
_ => return,
Expand Down Expand Up @@ -964,7 +964,7 @@ impl InferenceContext<'_> {
}
VariantId::StructId(s) => {
let vd = &*self.db.struct_data(s).variant_data;
let (al, ar) = args.split_at(ellipsis.unwrap_or(args.len()));
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let fields = vd.fields().iter();
let it =
al.iter().zip(fields.clone()).chain(ar.iter().rev().zip(fields.rev()));
Expand Down
4 changes: 2 additions & 2 deletions src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ impl InferenceContext<'_> {
Expr::Tuple { exprs, .. } => {
// We don't consider multiple ellipses. This is analogous to
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e));
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e)).map(|it| it as u32);
let exprs: Vec<_> = exprs.iter().filter(|e| !is_rest_expr(**e)).copied().collect();

self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
Expand All @@ -1184,7 +1184,7 @@ impl InferenceContext<'_> {

// We don't consider multiple ellipses. This is analogous to
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
let ellipsis = args.iter().position(|e| is_rest_expr(*e));
let ellipsis = args.iter().position(|e| is_rest_expr(*e)).map(|it| it as u32);
let args: Vec<_> = args.iter().filter(|e| !is_rest_expr(**e)).copied().collect();

self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args)
Expand Down
10 changes: 6 additions & 4 deletions src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl InferenceContext<'_> {
expected: &Ty,
default_bm: T::BindingMode,
id: T,
ellipsis: Option<usize>,
ellipsis: Option<u32>,
subs: &[T],
) -> Ty {
let (ty, def) = self.resolve_variant(path, true);
Expand Down Expand Up @@ -98,7 +98,7 @@ impl InferenceContext<'_> {
let visibilities = self.db.field_visibilities(def);

let (pre, post) = match ellipsis {
Some(idx) => subs.split_at(idx),
Some(idx) => subs.split_at(idx as usize),
None => (subs, &[][..]),
};
let post_idx_offset = field_types.iter().count().saturating_sub(post.len());
Expand Down Expand Up @@ -219,7 +219,7 @@ impl InferenceContext<'_> {
&mut self,
expected: &Ty,
default_bm: T::BindingMode,
ellipsis: Option<usize>,
ellipsis: Option<u32>,
subs: &[T],
) -> Ty {
let expected = self.resolve_ty_shallow(expected);
Expand All @@ -229,7 +229,9 @@ impl InferenceContext<'_> {
};

let ((pre, post), n_uncovered_patterns) = match ellipsis {
Some(idx) => (subs.split_at(idx), expectations.len().saturating_sub(subs.len())),
Some(idx) => {
(subs.split_at(idx as usize), expectations.len().saturating_sub(subs.len()))
}
None => ((subs, &[][..]), 0),
};
let mut expectations_iter = expectations
Expand Down
1 change: 1 addition & 0 deletions src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,7 @@ impl MirBody {
pub enum MirSpan {
ExprId(ExprId),
PatId(PatId),
BindingId(BindingId),
SelfParam,
Unknown,
}
Expand Down
10 changes: 10 additions & 0 deletions src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,16 @@ impl MirEvalError {
Ok(s) => s.map(|it| it.syntax_node_ptr()),
Err(_) => continue,
},
MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(*b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.map(|it| it.syntax_node_ptr()),
None => continue,
}
}
MirSpan::SelfParam => match source_map.self_param_syntax() {
Some(s) => s.map(|it| it.syntax_node_ptr()),
None => continue,
Expand Down
8 changes: 1 addition & 7 deletions src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1720,14 +1720,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
/// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and
/// `Drop` in the appropriated places.
fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<()> {
let span = self.body.bindings[b]
.definitions
.first()
.copied()
.map(MirSpan::PatId)
.unwrap_or(MirSpan::Unknown);
let l = self.binding_local(b)?;
self.push_storage_live_for_local(l, current, span)
self.push_storage_live_for_local(l, current, MirSpan::BindingId(b))
}

fn push_storage_live_for_local(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ macro_rules! not_supported {
}

pub(super) enum AdtPatternShape<'a> {
Tuple { args: &'a [PatId], ellipsis: Option<usize> },
Tuple { args: &'a [PatId], ellipsis: Option<u32> },
Record { args: &'a [RecordFieldPat] },
Unit,
}
Expand Down Expand Up @@ -627,12 +627,12 @@ impl MirLowerCtx<'_> {
current: BasicBlockId,
current_else: Option<BasicBlockId>,
args: &[PatId],
ellipsis: Option<usize>,
ellipsis: Option<u32>,
fields: impl DoubleEndedIterator<Item = PlaceElem> + Clone,
cond_place: &Place,
mode: MatchingMode,
) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
let (al, ar) = args.split_at(ellipsis.unwrap_or(args.len()));
let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let it = al
.iter()
.zip(fields.clone())
Expand Down
32 changes: 26 additions & 6 deletions src/tools/rust-analyzer/crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,16 @@ impl DefWithBody {
Some(s) => s.map(|it| it.into()),
None => continue,
},
mir::MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.map(|it| it.into()),
None => continue,
}
}
mir::MirSpan::Unknown => continue,
};
acc.push(
Expand All @@ -1822,8 +1832,8 @@ impl DefWithBody {
let Some(&local) = mir_body.binding_locals.get(binding_id) else {
continue;
};
if body[binding_id]
.definitions
if source_map
.patterns_for_binding(binding_id)
.iter()
.any(|&pat| source_map.pat_syntax(pat).is_err())
{
Expand Down Expand Up @@ -1859,6 +1869,16 @@ impl DefWithBody {
Ok(s) => s.map(|it| it.into()),
Err(_) => continue,
},
mir::MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(*b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.map(|it| it.into()),
None => continue,
}
}
mir::MirSpan::SelfParam => match source_map.self_param_syntax()
{
Some(s) => s.map(|it| it.into()),
Expand Down Expand Up @@ -3291,8 +3311,8 @@ impl Local {
source: source.map(|ast| Either::Right(ast.to_node(&root))),
}]
}
_ => body[self.binding_id]
.definitions
_ => source_map
.patterns_for_binding(self.binding_id)
.iter()
.map(|&definition| {
let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
Expand Down Expand Up @@ -3320,8 +3340,8 @@ impl Local {
source: source.map(|ast| Either::Right(ast.to_node(&root))),
}
}
_ => body[self.binding_id]
.definitions
_ => source_map
.patterns_for_binding(self.binding_id)
.first()
.map(|&definition| {
let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
Expand Down
Loading

0 comments on commit 28b8c24

Please sign in to comment.