Skip to content

Commit 851b970

Browse files
committed
Avoid recomputing the client-config-mixed configs
1 parent ab0149d commit 851b970

File tree

1 file changed

+33
-18
lines changed
  • crates/rust-analyzer/src/config

1 file changed

+33
-18
lines changed

crates/rust-analyzer/src/config/tree.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct ConfigTree {
125125
xdg_config_node_id: NodeId,
126126
ra_file_id_map: FxHashMap<FileId, NodeId>,
127127
computed: SlotMap<ComputedIdx, Option<Arc<LocalConfigData>>>,
128+
with_client_config: slotmap::SecondaryMap<ComputedIdx, Arc<LocalConfigData>>,
128129
}
129130

130131
fn parse_toml(
@@ -179,19 +180,13 @@ impl ConfigTree {
179180
ra_file_id_map,
180181
tree,
181182
computed,
183+
with_client_config: Default::default(),
182184
}
183185
}
184186

185187
fn read_only(&self, file_id: FileId) -> Result<Option<Arc<LocalConfigData>>, ConfigTreeError> {
186188
let node_id = *self.ra_file_id_map.get(&file_id).ok_or(ConfigTreeError::NonExistent)?;
187-
let stored = self.read_only_inner(node_id)?;
188-
Ok(stored.map(|stored| {
189-
if let Some(client_config) = self.client_config.as_deref() {
190-
stored.clone_with_overrides(client_config.local.clone()).into()
191-
} else {
192-
stored
193-
}
194-
}))
189+
self.read_only_inner(node_id)
195190
}
196191

197192
fn read_only_inner(
@@ -204,7 +199,7 @@ impl ConfigTree {
204199
return Err(ConfigTreeError::Removed);
205200
}
206201
let node = self.tree.get(node_id).ok_or(ConfigTreeError::NonExistent)?.get();
207-
let stored = self.computed[node.computed_idx].clone();
202+
let stored = self.with_client_config.get(node.computed_idx).cloned();
208203
tracing::trace!(
209204
"read_only_inner on {:?} got {:?}",
210205
node.src,
@@ -215,14 +210,19 @@ impl ConfigTree {
215210

216211
fn compute(&mut self, file_id: FileId) -> Result<Arc<LocalConfigData>, ConfigTreeError> {
217212
let node_id = *self.ra_file_id_map.get(&file_id).ok_or(ConfigTreeError::NonExistent)?;
218-
let computed = self.compute_inner(node_id)?;
219-
Ok(if let Some(client_config) = self.client_config.as_deref() {
220-
computed.clone_with_overrides(client_config.local.clone()).into()
213+
let (computed, idx) = self.compute_recursive(node_id)?;
214+
let out = if let Some(client_config) = self.client_config.as_deref() {
215+
Arc::new(computed.clone_with_overrides(client_config.local.clone()))
221216
} else {
222217
computed
223-
})
218+
};
219+
self.with_client_config.insert(idx, out.clone());
220+
Ok(out)
224221
}
225-
fn compute_inner(&mut self, node_id: NodeId) -> Result<Arc<LocalConfigData>, ConfigTreeError> {
222+
fn compute_recursive(
223+
&mut self,
224+
node_id: NodeId,
225+
) -> Result<(Arc<LocalConfigData>, ComputedIdx), ConfigTreeError> {
226226
if node_id.is_removed(&self.tree) {
227227
return Err(ConfigTreeError::Removed);
228228
}
@@ -231,14 +231,14 @@ impl ConfigTree {
231231
let idx = node.computed_idx;
232232
let slot = &mut self.computed[idx];
233233
if let Some(slot) = slot {
234-
Ok(slot.clone())
234+
Ok((slot.clone(), idx))
235235
} else {
236236
let self_computed = if let Some(parent) =
237237
self.tree.get(node_id).ok_or(ConfigTreeError::NonExistent)?.parent()
238238
{
239239
tracing::trace!("looking at parent of {node_id:?} -> {parent:?}");
240240
let self_input = node.input.clone();
241-
let parent_computed = self.compute_inner(parent)?;
241+
let (parent_computed, _) = self.compute_recursive(parent)?;
242242
if let Some(input) = self_input.as_deref() {
243243
Arc::new(parent_computed.clone_with_overrides(input.local.clone()))
244244
} else {
@@ -258,7 +258,7 @@ impl ConfigTree {
258258
// Get a new &mut slot because self.compute(parent) also gets mut access
259259
let slot = &mut self.computed[idx];
260260
slot.replace(self_computed.clone());
261-
Ok(self_computed)
261+
Ok((self_computed, idx))
262262
}
263263
}
264264

@@ -322,6 +322,9 @@ impl ConfigTree {
322322
};
323323
tracing::trace!("invalidating {x:?} / {:?}", desc.src);
324324
slot.take();
325+
326+
// Also invalidate the secondary data
327+
self.with_client_config.remove(desc.computed_idx);
325328
});
326329
}
327330

@@ -346,7 +349,16 @@ impl ConfigTree {
346349
let ConfigChanges { client_change, ra_toml_changes, mut parent_changes } = changes;
347350

348351
if let Some(change) = client_change {
349-
self.client_config = change;
352+
match (self.client_config.as_ref(), change.as_ref()) {
353+
(None, None) => {}
354+
(Some(a), Some(b)) if Arc::ptr_eq(a, b) => {}
355+
_ => {
356+
// invalidate the output table only, don't immediately need to recompute
357+
// everything from scratch
358+
self.with_client_config.clear();
359+
self.client_config = change;
360+
}
361+
}
350362
}
351363

352364
for change in ra_toml_changes {
@@ -498,6 +510,9 @@ mod tests {
498510

499511
let prev = local;
500512
let local = config_tree.read_config(crate_a).unwrap();
513+
assert!(!Arc::ptr_eq(&prev, &local));
514+
let local2 = config_tree.read_config(crate_a).unwrap();
515+
assert!(Arc::ptr_eq(&local, &local2));
501516

502517
assert_eq!(
503518
local.inlayHints_discriminantHints_enable,

0 commit comments

Comments
 (0)