From 638e49b0fcb0df56212e328689bbcce029cfc000 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 26 Jun 2025 14:02:59 +0200 Subject: [PATCH] Skip unnecessary `eq` work in `BodySourceMap` --- crates/hir-def/src/expr_store.rs | 58 +++++++++++++++++++++----- crates/hir-def/src/expr_store/scope.rs | 2 +- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs index 85bd193223..51612f341a 100644 --- a/crates/hir-def/src/expr_store.rs +++ b/crates/hir-def/src/expr_store.rs @@ -93,7 +93,7 @@ pub type TypeSource = InFile; pub type LifetimePtr = AstPtr; pub type LifetimeSource = InFile; -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct ExpressionStore { pub exprs: Arena, pub pats: Arena, @@ -114,7 +114,7 @@ pub struct ExpressionStore { ident_hygiene: FxHashMap, } -#[derive(Debug, Eq, PartialEq, Default)] +#[derive(Debug, Eq, Default)] pub struct ExpressionStoreSourceMap { // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected). @@ -127,19 +127,20 @@ pub struct ExpressionStoreSourceMap { label_map: FxHashMap, label_map_back: ArenaMap, - binding_definitions: FxHashMap>, - - /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). - /// Instead, we use id of expression (`92`) to identify the field. - field_map_back: FxHashMap, - pat_field_map_back: FxHashMap, - types_map_back: ArenaMap, types_map: FxHashMap, lifetime_map_back: ArenaMap, lifetime_map: FxHashMap, + binding_definitions: + ArenaMap() / size_of::()]>>, + + /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). + /// Instead, we use id of expression (`92`) to identify the field. + field_map_back: FxHashMap, + pat_field_map_back: FxHashMap, + template_map: Option>, pub expansions: FxHashMap, MacroCallId>, @@ -149,6 +150,43 @@ pub struct ExpressionStoreSourceMap { pub diagnostics: Vec, } +impl PartialEq for ExpressionStoreSourceMap { + fn eq(&self, other: &Self) -> bool { + // we only need to compare one of the two mappings + // as the other is a reverse mapping and thus will compare + // the same as normal mapping + let Self { + expr_map: _, + expr_map_back, + pat_map: _, + pat_map_back, + label_map: _, + label_map_back, + types_map_back, + types_map: _, + lifetime_map_back, + lifetime_map: _, + // If this changed, our pattern data must have changed + binding_definitions: _, + // If this changed, our expression data must have changed + field_map_back: _, + // If this changed, our pattern data must have changed + pat_field_map_back: _, + template_map, + expansions, + diagnostics, + } = self; + *expr_map_back == other.expr_map_back + && *pat_map_back == other.pat_map_back + && *label_map_back == other.label_map_back + && *types_map_back == other.types_map_back + && *lifetime_map_back == other.lifetime_map_back + && *template_map == other.template_map + && *expansions == other.expansions + && *diagnostics == other.diagnostics + } +} + /// The body of an item (function, const etc.). #[derive(Debug, Eq, PartialEq, Default)] pub struct ExpressionStoreBuilder { @@ -698,7 +736,7 @@ impl ExpressionStoreSourceMap { } pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] { - self.binding_definitions.get(&binding).map_or(&[], Deref::deref) + self.binding_definitions.get(binding).map_or(&[], Deref::deref) } pub fn node_label(&self, node: InFile<&ast::Label>) -> Option { diff --git a/crates/hir-def/src/expr_store/scope.rs b/crates/hir-def/src/expr_store/scope.rs index a46711c67e..2dd0b9bdb8 100644 --- a/crates/hir-def/src/expr_store/scope.rs +++ b/crates/hir-def/src/expr_store/scope.rs @@ -535,7 +535,7 @@ fn foo() { let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); let pat_src = source_map - .pat_syntax(*source_map.binding_definitions[&resolved.binding()].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());