aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-06-30 12:23:42 +0100
committerJonas Schievink <[email protected]>2020-06-30 12:23:42 +0100
commit0fcbc716fd56bcf4ecda5089e651be94c60efc3a (patch)
treeae068a4be2b44c9b37da7163fa6c96bf5f74d9ef /crates
parent5a0fb3caff745d20face2d7ab02fa4da63faef9c (diff)
Split namespace maps in `ItemScope`
Reduces memory usage of the CrateDefMap query by ~130 MB on r-a.
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/item_scope.rs113
1 files changed, 79 insertions, 34 deletions
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index 4d446c707..7fc53d86d 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -11,6 +11,7 @@ use crate::{
11 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, 11 db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
12 LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, 12 LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
13}; 13};
14use std::collections::hash_map::Entry;
14 15
15#[derive(Copy, Clone)] 16#[derive(Copy, Clone)]
16pub(crate) enum ImportType { 17pub(crate) enum ImportType {
@@ -27,7 +28,11 @@ pub struct PerNsGlobImports {
27 28
28#[derive(Debug, Default, PartialEq, Eq)] 29#[derive(Debug, Default, PartialEq, Eq)]
29pub struct ItemScope { 30pub 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
31 defs: Vec<ModuleDefId>, 36 defs: Vec<ModuleDefId>,
32 impls: Vec<ImplId>, 37 impls: Vec<ImplId>,
33 /// Macros visible in current module in legacy textual scope 38 /// Macros visible in current module in legacy textual scope
@@ -65,14 +70,22 @@ pub(crate) enum BuiltinShadowMode {
65/// Other methods will only resolve values, types and module scoped macros only. 70/// Other methods will only resolve values, types and module scoped macros only.
66impl ItemScope { 71impl ItemScope {
67 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { 72 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
68 //FIXME: shadowing 73 // FIXME: shadowing
69 self.visible.iter().map(|(n, def)| (n, *def)) 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)))
70 } 83 }
71 84
72 pub fn entries_without_primitives<'a>( 85 pub fn entries_without_primitives<'a>(
73 &'a self, 86 &'a self,
74 ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { 87 ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
75 self.visible.iter().map(|(n, def)| (n, *def)) 88 self.entries()
76 } 89 }
77 90
78 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { 91 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
@@ -91,7 +104,7 @@ impl ItemScope {
91 104
92 /// Iterate over all module scoped macros 105 /// Iterate over all module scoped macros
93 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 106 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_)))
95 } 108 }
96 109
97 /// Iterate over all legacy textual scoped macros visible at the end of the module 110 /// Iterate over all legacy textual scoped macros visible at the end of the module
@@ -101,12 +114,16 @@ impl ItemScope {
101 114
102 /// Get a name from current module scope, legacy macros are not included 115 /// Get a name from current module scope, legacy macros are not included
103 pub(crate) fn get(&self, name: &Name) -> PerNs { 116 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 }
105 } 122 }
106 123
107 pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { 124 pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
108 for (name, per_ns) in &self.visible { 125 for (name, per_ns) in self.entries() {
109 if let Some(vis) = item.match_with(*per_ns) { 126 if let Some(vis) = item.match_with(per_ns) {
110 return Some((name, vis)); 127 return Some((name, vis));
111 } 128 }
112 } 129 }
@@ -114,8 +131,8 @@ impl ItemScope {
114 } 131 }
115 132
116 pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { 133 pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
117 self.visible.values().filter_map(|def| match def.take_types() { 134 self.types.values().filter_map(|(def, _)| match def {
118 Some(ModuleDefId::TraitId(t)) => Some(t), 135 ModuleDefId::TraitId(t) => Some(*t),
119 _ => None, 136 _ => None,
120 }) 137 })
121 } 138 }
@@ -138,21 +155,39 @@ impl ItemScope {
138 155
139 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { 156 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
140 let mut changed = false; 157 let mut changed = false;
141 let existing = self.visible.entry(name).or_default();
142 158
143 if existing.types.is_none() && def.types.is_some() { 159 if let Some(types) = def.types {
144 existing.types = def.types; 160 match self.types.entry(name.clone()) {
145 changed = true; 161 Entry::Occupied(_) => {}
162 Entry::Vacant(e) => {
163 e.insert(types);
164 changed = true;
165 }
166 }
146 } 167 }
147 168 if let Some(values) = def.values {
148 if existing.values.is_none() && def.values.is_some() { 169 match self.values.entry(name.clone()) {
149 existing.values = def.values; 170 Entry::Occupied(_) => {}
150 changed = true; 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 }
151 } 185 }
152 186
153 if existing.macros.is_none() && def.macros.is_some() { 187 if def.is_none() {
154 existing.macros = def.macros; 188 if self.unresolved.insert(name) {
155 changed = true; 189 changed = true;
190 }
156 } 191 }
157 192
158 changed 193 changed
@@ -166,17 +201,17 @@ impl ItemScope {
166 def_import_type: ImportType, 201 def_import_type: ImportType,
167 ) -> bool { 202 ) -> bool {
168 let mut changed = false; 203 let mut changed = false;
169 let existing = self.visible.entry(lookup.1.clone()).or_default();
170 204
171 macro_rules! check_changed { 205 macro_rules! check_changed {
172 ( 206 (
173 $changed:ident, 207 $changed:ident,
174 ( $existing:ident / $def:ident ) . $field:ident, 208 ( $this:ident / $def:ident ) . $field:ident,
175 $glob_imports:ident [ $lookup:ident ], 209 $glob_imports:ident [ $lookup:ident ],
176 $def_import_type:ident 210 $def_import_type:ident
177 ) => { 211 ) => {{
178 match ($existing.$field, $def.$field) { 212 let existing = $this.$field.entry($lookup.1.clone());
179 (None, Some(_)) => { 213 match (existing, $def.$field) {
214 (Entry::Vacant(entry), Some(_)) => {
180 match $def_import_type { 215 match $def_import_type {
181 ImportType::Glob => { 216 ImportType::Glob => {
182 $glob_imports.$field.insert($lookup.clone()); 217 $glob_imports.$field.insert($lookup.clone());
@@ -186,32 +221,42 @@ impl ItemScope {
186 } 221 }
187 } 222 }
188 223
189 $existing.$field = $def.$field; 224 if let Some(fld) = $def.$field {
225 entry.insert(fld);
226 }
190 $changed = true; 227 $changed = true;
191 } 228 }
192 (Some(_), Some(_)) 229 (Entry::Occupied(mut entry), Some(_))
193 if $glob_imports.$field.contains(&$lookup) 230 if $glob_imports.$field.contains(&$lookup)
194 && matches!($def_import_type, ImportType::Named) => 231 && matches!($def_import_type, ImportType::Named) =>
195 { 232 {
196 mark::hit!(import_shadowed); 233 mark::hit!(import_shadowed);
197 $glob_imports.$field.remove(&$lookup); 234 $glob_imports.$field.remove(&$lookup);
198 $existing.$field = $def.$field; 235 if let Some(fld) = $def.$field {
236 entry.insert(fld);
237 }
199 $changed = true; 238 $changed = true;
200 } 239 }
201 _ => {} 240 _ => {}
202 } 241 }
203 }; 242 }};
204 } 243 }
205 244
206 check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type); 245 check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type);
207 check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type); 246 check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type);
208 check_changed!(changed, (existing / def).macros, 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 }
209 254
210 changed 255 changed
211 } 256 }
212 257
213 pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { 258 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))
215 } 260 }
216 261
217 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { 262 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {