Skip to content

Commit 0fcbc71

Browse files
author
Jonas Schievink
committed
Split namespace maps in ItemScope
Reduces memory usage of the CrateDefMap query by ~130 MB on r-a.
1 parent 5a0fb3c commit 0fcbc71

File tree

1 file changed

+79
-34
lines changed

1 file changed

+79
-34
lines changed

crates/ra_hir_def/src/item_scope.rs

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
1212
LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
1313
};
14+
use std::collections::hash_map::Entry;
1415

1516
#[derive(Copy, Clone)]
1617
pub(crate) enum ImportType {
@@ -27,7 +28,11 @@ pub struct PerNsGlobImports {
2728

2829
#[derive(Debug, Default, PartialEq, Eq)]
2930
pub struct ItemScope {
30-
visible: FxHashMap<Name, PerNs>,
31+
types: FxHashMap<Name, (ModuleDefId, Visibility)>,
32+
values: FxHashMap<Name, (ModuleDefId, Visibility)>,
33+
macros: FxHashMap<Name, (MacroDefId, Visibility)>,
34+
unresolved: FxHashSet<Name>,
35+
3136
defs: Vec<ModuleDefId>,
3237
impls: Vec<ImplId>,
3338
/// Macros visible in current module in legacy textual scope
@@ -65,14 +70,22 @@ pub(crate) enum BuiltinShadowMode {
6570
/// Other methods will only resolve values, types and module scoped macros only.
6671
impl ItemScope {
6772
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
68-
//FIXME: shadowing
69-
self.visible.iter().map(|(n, def)| (n, *def))
73+
// FIXME: shadowing
74+
let keys: FxHashSet<_> = self
75+
.types
76+
.keys()
77+
.chain(self.values.keys())
78+
.chain(self.macros.keys())
79+
.chain(self.unresolved.iter())
80+
.collect();
81+
82+
keys.into_iter().map(move |name| (name, self.get(name)))
7083
}
7184

7285
pub fn entries_without_primitives<'a>(
7386
&'a self,
7487
) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
75-
self.visible.iter().map(|(n, def)| (n, *def))
88+
self.entries()
7689
}
7790

7891
pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
@@ -91,7 +104,7 @@ impl ItemScope {
91104

92105
/// Iterate over all module scoped macros
93106
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
94-
self.visible.iter().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
107+
self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
95108
}
96109

97110
/// Iterate over all legacy textual scoped macros visible at the end of the module
@@ -101,21 +114,25 @@ impl ItemScope {
101114

102115
/// Get a name from current module scope, legacy macros are not included
103116
pub(crate) fn get(&self, name: &Name) -> PerNs {
104-
self.visible.get(name).copied().unwrap_or_else(PerNs::none)
117+
PerNs {
118+
types: self.types.get(name).copied(),
119+
values: self.values.get(name).copied(),
120+
macros: self.macros.get(name).copied(),
121+
}
105122
}
106123

107124
pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
108-
for (name, per_ns) in &self.visible {
109-
if let Some(vis) = item.match_with(*per_ns) {
125+
for (name, per_ns) in self.entries() {
126+
if let Some(vis) = item.match_with(per_ns) {
110127
return Some((name, vis));
111128
}
112129
}
113130
None
114131
}
115132

116133
pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
117-
self.visible.values().filter_map(|def| match def.take_types() {
118-
Some(ModuleDefId::TraitId(t)) => Some(t),
134+
self.types.values().filter_map(|(def, _)| match def {
135+
ModuleDefId::TraitId(t) => Some(*t),
119136
_ => None,
120137
})
121138
}
@@ -138,21 +155,39 @@ impl ItemScope {
138155

139156
pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
140157
let mut changed = false;
141-
let existing = self.visible.entry(name).or_default();
142158

143-
if existing.types.is_none() && def.types.is_some() {
144-
existing.types = def.types;
145-
changed = true;
159+
if let Some(types) = def.types {
160+
match self.types.entry(name.clone()) {
161+
Entry::Occupied(_) => {}
162+
Entry::Vacant(e) => {
163+
e.insert(types);
164+
changed = true;
165+
}
166+
}
146167
}
147-
148-
if existing.values.is_none() && def.values.is_some() {
149-
existing.values = def.values;
150-
changed = true;
168+
if let Some(values) = def.values {
169+
match self.values.entry(name.clone()) {
170+
Entry::Occupied(_) => {}
171+
Entry::Vacant(e) => {
172+
e.insert(values);
173+
changed = true;
174+
}
175+
}
176+
}
177+
if let Some(macros) = def.macros {
178+
match self.macros.entry(name.clone()) {
179+
Entry::Occupied(_) => {}
180+
Entry::Vacant(e) => {
181+
e.insert(macros);
182+
changed = true;
183+
}
184+
}
151185
}
152186

153-
if existing.macros.is_none() && def.macros.is_some() {
154-
existing.macros = def.macros;
155-
changed = true;
187+
if def.is_none() {
188+
if self.unresolved.insert(name) {
189+
changed = true;
190+
}
156191
}
157192

158193
changed
@@ -166,17 +201,17 @@ impl ItemScope {
166201
def_import_type: ImportType,
167202
) -> bool {
168203
let mut changed = false;
169-
let existing = self.visible.entry(lookup.1.clone()).or_default();
170204

171205
macro_rules! check_changed {
172206
(
173207
$changed:ident,
174-
( $existing:ident / $def:ident ) . $field:ident,
208+
( $this:ident / $def:ident ) . $field:ident,
175209
$glob_imports:ident [ $lookup:ident ],
176210
$def_import_type:ident
177-
) => {
178-
match ($existing.$field, $def.$field) {
179-
(None, Some(_)) => {
211+
) => {{
212+
let existing = $this.$field.entry($lookup.1.clone());
213+
match (existing, $def.$field) {
214+
(Entry::Vacant(entry), Some(_)) => {
180215
match $def_import_type {
181216
ImportType::Glob => {
182217
$glob_imports.$field.insert($lookup.clone());
@@ -186,32 +221,42 @@ impl ItemScope {
186221
}
187222
}
188223

189-
$existing.$field = $def.$field;
224+
if let Some(fld) = $def.$field {
225+
entry.insert(fld);
226+
}
190227
$changed = true;
191228
}
192-
(Some(_), Some(_))
229+
(Entry::Occupied(mut entry), Some(_))
193230
if $glob_imports.$field.contains(&$lookup)
194231
&& matches!($def_import_type, ImportType::Named) =>
195232
{
196233
mark::hit!(import_shadowed);
197234
$glob_imports.$field.remove(&$lookup);
198-
$existing.$field = $def.$field;
235+
if let Some(fld) = $def.$field {
236+
entry.insert(fld);
237+
}
199238
$changed = true;
200239
}
201240
_ => {}
202241
}
203-
};
242+
}};
204243
}
205244

206-
check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type);
207-
check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type);
208-
check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type);
245+
check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type);
246+
check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type);
247+
check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type);
248+
249+
if def.is_none() {
250+
if self.unresolved.insert(lookup.1) {
251+
changed = true;
252+
}
253+
}
209254

210255
changed
211256
}
212257

213258
pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a {
214-
self.visible.iter().map(|(name, res)| (name.clone(), *res))
259+
self.entries().map(|(name, res)| (name.clone(), res))
215260
}
216261

217262
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {

0 commit comments

Comments
 (0)