Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir_expand/Cargo.toml1
-rw-r--r--crates/hir_expand/src/ast_id_map.rs26
3 files changed, 24 insertions, 4 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8a0d809a1b..4d22ebdc18 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -529,6 +529,7 @@ dependencies = [
"la-arena",
"limit",
"mbe",
+ "once_cell",
"profile",
"rustc-hash",
"syntax",
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml
index 380b7ef877..7a61036530 100644
--- a/crates/hir_expand/Cargo.toml
+++ b/crates/hir_expand/Cargo.toml
@@ -16,6 +16,7 @@ either = "1.5.3"
rustc-hash = "1.0.0"
la-arena = { version = "0.3.0", path = "../../lib/arena" }
itertools = "0.10.0"
+once_cell = "1"
base_db = { path = "../base_db", version = "0.0.0" }
cfg = { path = "../cfg", version = "0.0.0" }
diff --git a/crates/hir_expand/src/ast_id_map.rs b/crates/hir_expand/src/ast_id_map.rs
index 64387b8148..9db2bc6410 100644
--- a/crates/hir_expand/src/ast_id_map.rs
+++ b/crates/hir_expand/src/ast_id_map.rs
@@ -61,13 +61,29 @@ impl<N: AstNode> FileAstId<N> {
type ErasedFileAstId = Idx<SyntaxNodePtr>;
/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
-#[derive(Debug, PartialEq, Eq, Default)]
+#[derive(Default)]
pub struct AstIdMap {
arena: Arena<SyntaxNodePtr>,
- map: FxHashMap<SyntaxNodePtr, ErasedFileAstId>,
+ /// Reversed mapping lazily derived from [`self.arena`].
+ ///
+ /// FIXE: Do not store `SyntaxNodePtr` twice.
+ map: once_cell::sync::OnceCell<FxHashMap<SyntaxNodePtr, ErasedFileAstId>>,
_c: Count<Self>,
}
+impl fmt::Debug for AstIdMap {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("AstIdMap").field("arena", &self.arena).finish()
+ }
+}
+
+impl PartialEq for AstIdMap {
+ fn eq(&self, other: &Self) -> bool {
+ self.arena == other.arena
+ }
+}
+impl Eq for AstIdMap {}
+
impl AstIdMap {
pub(crate) fn from_source(node: &SyntaxNode) -> AstIdMap {
assert!(node.parent().is_none());
@@ -91,9 +107,11 @@ impl AstIdMap {
}
}
});
- res.map.extend(res.arena.iter().map(|(idx, ptr)| (ptr.clone(), idx)));
res
}
+ fn map(&self) -> &FxHashMap<SyntaxNodePtr, ErasedFileAstId> {
+ self.map.get_or_init(|| self.arena.iter().map(|(idx, ptr)| (ptr.clone(), idx)).collect())
+ }
pub fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {
let raw = self.erased_ast_id(item.syntax());
@@ -102,7 +120,7 @@ impl AstIdMap {
fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId {
let ptr = SyntaxNodePtr::new(item);
- *self.map.get(&ptr).unwrap_or_else(|| {
+ *self.map().get(&ptr).unwrap_or_else(|| {
panic!(
"Can't find {:?} in AstIdMap:\n{:?}",
item,