Skip to content

Commit 25124a8

Browse files
committed
Auto merge of rust-lang#14490 - Veykril:crategraph-dedup, r=Veykril
internal: Switch crate graph to use an Arena instead of a hashmap
2 parents a1ca52e + 7f0fbf7 commit 25124a8

File tree

15 files changed

+1480
-1574
lines changed

15 files changed

+1480
-1574
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/base-db/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ doctest = false
1515
salsa = "0.17.0-pre.2"
1616
rustc-hash = "1.1.0"
1717

18+
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
19+
1820
# local deps
1921
cfg.workspace = true
2022
profile.workspace = true

crates/base-db/src/input.rs

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
use std::{fmt, mem, ops, panic::RefUnwindSafe, str::FromStr, sync::Arc};
1010

1111
use cfg::CfgOptions;
12-
use rustc_hash::FxHashMap;
13-
use stdx::hash::{NoHashHashMap, NoHashHashSet};
12+
use la_arena::{Arena, Idx, RawIdx};
13+
use rustc_hash::{FxHashMap, FxHashSet};
1414
use syntax::SmolStr;
1515
use tt::token_id::Subtree;
1616
use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
@@ -84,17 +84,22 @@ impl SourceRoot {
8484
///
8585
/// `CrateGraph` is `!Serialize` by design, see
8686
/// <https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/architecture.md#serialization>
87-
#[derive(Debug, Clone, Default /* Serialize, Deserialize */)]
87+
#[derive(Clone, Default)]
8888
pub struct CrateGraph {
89-
arena: NoHashHashMap<CrateId, CrateData>,
89+
arena: Arena<CrateData>,
9090
}
9191

92-
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
93-
pub struct CrateId(pub u32);
92+
impl fmt::Debug for CrateGraph {
93+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94+
f.debug_map()
95+
.entries(self.arena.iter().map(|(id, data)| (u32::from(id.into_raw()), data)))
96+
.finish()
97+
}
98+
}
9499

95-
impl stdx::hash::NoHashHashable for CrateId {}
100+
pub type CrateId = Idx<CrateData>;
96101

97-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
102+
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
98103
pub struct CrateName(SmolStr);
99104

100105
impl CrateName {
@@ -182,7 +187,7 @@ impl fmt::Display for LangCrateOrigin {
182187
}
183188
}
184189

185-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
190+
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
186191
pub struct CrateDisplayName {
187192
// The name we use to display various paths (with `_`).
188193
crate_name: CrateName,
@@ -261,7 +266,7 @@ pub struct ProcMacro {
261266
pub expander: Arc<dyn ProcMacroExpander>,
262267
}
263268

264-
#[derive(Debug, Copy, Clone)]
269+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
265270
pub enum ReleaseChannel {
266271
Stable,
267272
Beta,
@@ -287,7 +292,7 @@ impl ReleaseChannel {
287292
}
288293
}
289294

290-
#[derive(Debug, Clone)]
295+
#[derive(Debug, Clone, PartialEq, Eq)]
291296
pub struct CrateData {
292297
pub root_file_id: FileId,
293298
pub edition: Edition,
@@ -327,7 +332,7 @@ pub struct Env {
327332
entries: FxHashMap<String, String>,
328333
}
329334

330-
#[derive(Debug, Clone, PartialEq, Eq)]
335+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
331336
pub struct Dependency {
332337
pub crate_id: CrateId,
333338
pub name: CrateName,
@@ -378,10 +383,7 @@ impl CrateGraph {
378383
is_proc_macro,
379384
channel,
380385
};
381-
let crate_id = CrateId(self.arena.len() as u32);
382-
let prev = self.arena.insert(crate_id, data);
383-
assert!(prev.is_none());
384-
crate_id
386+
self.arena.alloc(data)
385387
}
386388

387389
pub fn add_dep(
@@ -394,14 +396,14 @@ impl CrateGraph {
394396
// Check if adding a dep from `from` to `to` creates a cycle. To figure
395397
// that out, look for a path in the *opposite* direction, from `to` to
396398
// `from`.
397-
if let Some(path) = self.find_path(&mut NoHashHashSet::default(), dep.crate_id, from) {
399+
if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) {
398400
let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect();
399401
let err = CyclicDependenciesError { path };
400402
assert!(err.from().0 == from && err.to().0 == dep.crate_id);
401403
return Err(err);
402404
}
403405

404-
self.arena.get_mut(&from).unwrap().add_dep(dep);
406+
self.arena[from].add_dep(dep);
405407
Ok(())
406408
}
407409

@@ -410,14 +412,14 @@ impl CrateGraph {
410412
}
411413

412414
pub fn iter(&self) -> impl Iterator<Item = CrateId> + '_ {
413-
self.arena.keys().copied()
415+
self.arena.iter().map(|(idx, _)| idx)
414416
}
415417

416418
/// Returns an iterator over all transitive dependencies of the given crate,
417419
/// including the crate itself.
418420
pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
419421
let mut worklist = vec![of];
420-
let mut deps = NoHashHashSet::default();
422+
let mut deps = FxHashSet::default();
421423

422424
while let Some(krate) = worklist.pop() {
423425
if !deps.insert(krate) {
@@ -434,11 +436,11 @@ impl CrateGraph {
434436
/// including the crate itself.
435437
pub fn transitive_rev_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
436438
let mut worklist = vec![of];
437-
let mut rev_deps = NoHashHashSet::default();
439+
let mut rev_deps = FxHashSet::default();
438440
rev_deps.insert(of);
439441

440-
let mut inverted_graph = NoHashHashMap::<_, Vec<_>>::default();
441-
self.arena.iter().for_each(|(&krate, data)| {
442+
let mut inverted_graph = FxHashMap::<_, Vec<_>>::default();
443+
self.arena.iter().for_each(|(krate, data)| {
442444
data.dependencies
443445
.iter()
444446
.for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate))
@@ -461,17 +463,17 @@ impl CrateGraph {
461463
/// come before the crate itself).
462464
pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
463465
let mut res = Vec::new();
464-
let mut visited = NoHashHashSet::default();
466+
let mut visited = FxHashSet::default();
465467

466-
for krate in self.arena.keys().copied() {
468+
for krate in self.iter() {
467469
go(self, &mut visited, &mut res, krate);
468470
}
469471

470472
return res;
471473

472474
fn go(
473475
graph: &CrateGraph,
474-
visited: &mut NoHashHashSet<CrateId>,
476+
visited: &mut FxHashSet<CrateId>,
475477
res: &mut Vec<CrateId>,
476478
source: CrateId,
477479
) {
@@ -487,7 +489,7 @@ impl CrateGraph {
487489

488490
// FIXME: this only finds one crate with the given root; we could have multiple
489491
pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
490-
let (&crate_id, _) =
492+
let (crate_id, _) =
491493
self.arena.iter().find(|(_crate_id, data)| data.root_file_id == file_id)?;
492494
Some(crate_id)
493495
}
@@ -499,24 +501,26 @@ impl CrateGraph {
499501
/// amount.
500502
pub fn extend(&mut self, other: CrateGraph, proc_macros: &mut ProcMacroPaths) -> u32 {
501503
let start = self.arena.len() as u32;
502-
self.arena.extend(other.arena.into_iter().map(|(id, mut data)| {
503-
let new_id = id.shift(start);
504+
self.arena.extend(other.arena.into_iter().map(|(_, mut data)| {
504505
for dep in &mut data.dependencies {
505-
dep.crate_id = dep.crate_id.shift(start);
506+
dep.crate_id =
507+
CrateId::from_raw(RawIdx::from(u32::from(dep.crate_id.into_raw()) + start));
506508
}
507-
(new_id, data)
509+
data
508510
}));
509511

510512
*proc_macros = mem::take(proc_macros)
511513
.into_iter()
512-
.map(|(id, macros)| (id.shift(start), macros))
514+
.map(|(id, macros)| {
515+
(CrateId::from_raw(RawIdx::from(u32::from(id.into_raw()) + start)), macros)
516+
})
513517
.collect();
514518
start
515519
}
516520

517521
fn find_path(
518522
&self,
519-
visited: &mut NoHashHashSet<CrateId>,
523+
visited: &mut FxHashSet<CrateId>,
520524
from: CrateId,
521525
to: CrateId,
522526
) -> Option<Vec<CrateId>> {
@@ -546,10 +550,8 @@ impl CrateGraph {
546550
let std = self.hacky_find_crate("std");
547551
match (cfg_if, std) {
548552
(Some(cfg_if), Some(std)) => {
549-
self.arena.get_mut(&cfg_if).unwrap().dependencies.clear();
550-
self.arena
551-
.get_mut(&std)
552-
.unwrap()
553+
self.arena[cfg_if].dependencies.clear();
554+
self.arena[std]
553555
.dependencies
554556
.push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if));
555557
true
@@ -566,13 +568,7 @@ impl CrateGraph {
566568
impl ops::Index<CrateId> for CrateGraph {
567569
type Output = CrateData;
568570
fn index(&self, crate_id: CrateId) -> &CrateData {
569-
&self.arena[&crate_id]
570-
}
571-
}
572-
573-
impl CrateId {
574-
fn shift(self, amount: u32) -> CrateId {
575-
CrateId(self.0 + amount)
571+
&self.arena[crate_id]
576572
}
577573
}
578574

crates/base-db/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub mod fixture;
88

99
use std::{panic, sync::Arc};
1010

11-
use stdx::hash::NoHashHashSet;
11+
use rustc_hash::FxHashSet;
1212
use syntax::{ast, Parse, SourceFile, TextRange, TextSize};
1313

1414
pub use crate::{
@@ -59,7 +59,7 @@ pub trait FileLoader {
5959
/// Text of the file.
6060
fn file_text(&self, file_id: FileId) -> Arc<String>;
6161
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
62-
fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>>;
62+
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>;
6363
}
6464

6565
/// Database which stores all significant input facts: source code and project
@@ -99,10 +99,10 @@ pub trait SourceDatabaseExt: SourceDatabase {
9999
#[salsa::input]
100100
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
101101

102-
fn source_root_crates(&self, id: SourceRootId) -> Arc<NoHashHashSet<CrateId>>;
102+
fn source_root_crates(&self, id: SourceRootId) -> Arc<FxHashSet<CrateId>>;
103103
}
104104

105-
fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<NoHashHashSet<CrateId>> {
105+
fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<FxHashSet<CrateId>> {
106106
let graph = db.crate_graph();
107107
let res = graph
108108
.iter()
@@ -128,7 +128,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
128128
source_root.resolve_path(path)
129129
}
130130

131-
fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
131+
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
132132
let _p = profile::span("relevant_crates");
133133
let source_root = self.0.file_source_root(file_id);
134134
self.0.source_root_crates(source_root)

crates/hir-def/src/body/tests/block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ fn f() {
148148
}
149149
"#,
150150
expect![[r#"
151-
BlockId(1) in ModuleId { krate: CrateId(0), block: Some(BlockId(0)), local_id: Idx::<ModuleData>(1) }
152-
BlockId(0) in ModuleId { krate: CrateId(0), block: None, local_id: Idx::<ModuleData>(0) }
151+
BlockId(1) in ModuleId { krate: Idx::<CrateData>(0), block: Some(BlockId(0)), local_id: Idx::<ModuleData>(1) }
152+
BlockId(0) in ModuleId { krate: Idx::<CrateData>(0), block: None, local_id: Idx::<ModuleData>(0) }
153153
crate scope
154154
"#]],
155155
);

crates/hir-def/src/test_db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use base_db::{
1111
Upcast,
1212
};
1313
use hir_expand::{db::ExpandDatabase, InFile};
14-
use stdx::hash::NoHashHashSet;
14+
use rustc_hash::FxHashSet;
1515
use syntax::{algo, ast, AstNode};
1616

1717
use crate::{
@@ -77,7 +77,7 @@ impl FileLoader for TestDB {
7777
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
7878
FileLoaderDelegate(self).resolve_path(path)
7979
}
80-
fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
80+
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
8181
FileLoaderDelegate(self).relevant_crates(file_id)
8282
}
8383
}

crates/hir-ty/src/test_db.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use base_db::{
1111
};
1212
use hir_def::{db::DefDatabase, ModuleId};
1313
use hir_expand::db::ExpandDatabase;
14-
use stdx::hash::{NoHashHashMap, NoHashHashSet};
14+
use rustc_hash::FxHashSet;
15+
use stdx::hash::NoHashHashMap;
1516
use syntax::TextRange;
1617
use test_utils::extract_annotations;
1718

@@ -81,7 +82,7 @@ impl FileLoader for TestDB {
8182
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
8283
FileLoaderDelegate(self).resolve_path(path)
8384
}
84-
fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
85+
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
8586
FileLoaderDelegate(self).relevant_crates(file_id)
8687
}
8788
}

crates/ide-db/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ use hir::{
5353
db::{DefDatabase, ExpandDatabase, HirDatabase},
5454
symbols::FileSymbolKind,
5555
};
56-
use stdx::hash::NoHashHashSet;
5756

5857
use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
5958
pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
@@ -120,7 +119,7 @@ impl FileLoader for RootDatabase {
120119
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
121120
FileLoaderDelegate(self).resolve_path(path)
122121
}
123-
fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
122+
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
124123
FileLoaderDelegate(self).relevant_crates(file_id)
125124
}
126125
}

crates/ide-db/src/test_data/test_symbol_index_collection.txt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
(
33
Module {
44
id: ModuleId {
5-
krate: CrateId(
6-
0,
7-
),
5+
krate: Idx::<CrateData>(0),
86
block: None,
97
local_id: Idx::<ModuleData>(0),
108
},
@@ -381,9 +379,7 @@
381379
(
382380
Module {
383381
id: ModuleId {
384-
krate: CrateId(
385-
0,
386-
),
382+
krate: Idx::<CrateData>(0),
387383
block: None,
388384
local_id: Idx::<ModuleData>(1),
389385
},
@@ -412,9 +408,7 @@
412408
(
413409
Module {
414410
id: ModuleId {
415-
krate: CrateId(
416-
0,
417-
),
411+
krate: Idx::<CrateData>(0),
418412
block: None,
419413
local_id: Idx::<ModuleData>(2),
420414
},

0 commit comments

Comments
 (0)