Skip to content

Commit 31d2b3b

Browse files
Merge #8386
8386: Avoid O(n²) when constructing AttrSourceMap r=jonas-schievink a=jonas-schievink Brings #8377 down to 2.52s on my machine. Not quite back to where it was before, so I'll leave that issue open for now. bors r+ Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
2 parents 1643d15 + 035d845 commit 31d2b3b

File tree

4 files changed

+74
-10
lines changed

4 files changed

+74
-10
lines changed

crates/hir_def/src/attr.rs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use mbe::ast_to_token_tree;
1616
use smallvec::{smallvec, SmallVec};
1717
use syntax::{
1818
ast::{self, AstNode, AttrsOwner},
19-
match_ast, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
19+
match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
2020
};
2121
use tt::Subtree;
2222

@@ -403,21 +403,27 @@ impl AttrsWithOwner {
403403
return AttrSourceMap { attrs };
404404
}
405405
AttrDefId::FieldId(id) => {
406-
id.parent.child_source(db).map(|source| match &source[id.local_id] {
407-
Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()),
408-
Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()),
409-
})
406+
let map = db.fields_attrs_source_map(id.parent);
407+
let file_id = id.parent.file_id(db);
408+
let root = db.parse_or_expand(file_id).unwrap();
409+
let owner = match &map[id.local_id] {
410+
Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
411+
Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
412+
};
413+
InFile::new(file_id, owner)
410414
}
411415
AttrDefId::AdtId(adt) => match adt {
412416
AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
413417
AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
414418
AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
415419
},
416420
AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
417-
AttrDefId::EnumVariantId(id) => id
418-
.parent
419-
.child_source(db)
420-
.map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())),
421+
AttrDefId::EnumVariantId(id) => {
422+
let map = db.variants_attrs_source_map(id.parent);
423+
let file_id = id.parent.lookup(db).id.file_id();
424+
let root = db.parse_or_expand(file_id).unwrap();
425+
InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
426+
}
421427
AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
422428
AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
423429
AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -746,3 +752,36 @@ fn collect_attrs(
746752

747753
attrs.into_iter().map(|(_, attr)| attr)
748754
}
755+
756+
pub(crate) fn variants_attrs_source_map(
757+
db: &dyn DefDatabase,
758+
def: EnumId,
759+
) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
760+
let mut res = ArenaMap::default();
761+
let child_source = def.child_source(db);
762+
763+
for (idx, variant) in child_source.value.iter() {
764+
res.insert(idx, AstPtr::new(variant));
765+
}
766+
767+
Arc::new(res)
768+
}
769+
770+
pub(crate) fn fields_attrs_source_map(
771+
db: &dyn DefDatabase,
772+
def: VariantId,
773+
) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
774+
let mut res = ArenaMap::default();
775+
let child_source = def.child_source(db);
776+
777+
for (idx, variant) in child_source.value.iter() {
778+
res.insert(
779+
idx,
780+
variant
781+
.as_ref()
782+
.either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
783+
);
784+
}
785+
786+
Arc::new(res)
787+
}

crates/hir_def/src/db.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
use std::sync::Arc;
33

44
use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5+
use either::Either;
56
use hir_expand::{db::AstDatabase, HirFileId};
67
use la_arena::ArenaMap;
7-
use syntax::SmolStr;
8+
use syntax::{ast, AstPtr, SmolStr};
89

910
use crate::{
1011
adt::{EnumData, StructData},
@@ -122,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
122123
#[salsa::invoke(Attrs::fields_attrs_query)]
123124
fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
124125

126+
#[salsa::invoke(crate::attr::variants_attrs_source_map)]
127+
fn variants_attrs_source_map(
128+
&self,
129+
def: EnumId,
130+
) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
131+
132+
#[salsa::invoke(crate::attr::fields_attrs_source_map)]
133+
fn fields_attrs_source_map(
134+
&self,
135+
def: VariantId,
136+
) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>;
137+
125138
#[salsa::invoke(AttrsWithOwner::attrs_query)]
126139
fn attrs(&self, def: AttrDefId) -> AttrsWithOwner;
127140

crates/hir_def/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,14 @@ impl VariantId {
453453
}
454454
}
455455
}
456+
457+
pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
458+
match self {
459+
VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
460+
VariantId::StructId(it) => it.lookup(db).id.file_id(),
461+
VariantId::UnionId(it) => it.lookup(db).id.file_id(),
462+
}
463+
}
456464
}
457465

458466
trait Intern {

crates/ide_db/src/apply_change.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ impl RootDatabase {
152152
hir::db::FileItemTreeQuery
153153
hir::db::BlockDefMapQuery
154154
hir::db::CrateDefMapQueryQuery
155+
hir::db::FieldsAttrsQuery
156+
hir::db::VariantsAttrsQuery
157+
hir::db::FieldsAttrsSourceMapQuery
158+
hir::db::VariantsAttrsSourceMapQuery
155159
hir::db::StructDataQuery
156160
hir::db::UnionDataQuery
157161
hir::db::EnumDataQuery

0 commit comments

Comments
 (0)