about summary refs log tree commit diff
path: root/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs')
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs39
1 files changed, 24 insertions, 15 deletions
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
index 7ae75713ebf..f28821b4afc 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
@@ -35,6 +35,7 @@ use std::{
     ffi::OsString,
     fs,
     path::{Path, PathBuf},
+    sync::{Arc, Mutex, PoisonError},
     thread,
 };
 
@@ -53,7 +54,7 @@ pub enum ProcMacroKind {
 pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION");
 
 pub struct ProcMacroSrv<'env> {
-    expanders: HashMap<Utf8PathBuf, dylib::Expander>,
+    expanders: Mutex<HashMap<Utf8PathBuf, Arc<dylib::Expander>>>,
     env: &'env EnvSnapshot,
 }
 
@@ -67,7 +68,7 @@ const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;
 
 impl ProcMacroSrv<'_> {
     pub fn expand<S: ProcMacroSrvSpan>(
-        &mut self,
+        &self,
         lib: impl AsRef<Utf8Path>,
         env: Vec<(String, String)>,
         current_dir: Option<impl AsRef<Path>>,
@@ -118,29 +119,37 @@ impl ProcMacroSrv<'_> {
     }
 
     pub fn list_macros(
-        &mut self,
+        &self,
         dylib_path: &Utf8Path,
     ) -> Result<Vec<(String, ProcMacroKind)>, String> {
         let expander = self.expander(dylib_path)?;
         Ok(expander.list_macros())
     }
 
-    fn expander(&mut self, path: &Utf8Path) -> Result<&dylib::Expander, String> {
+    fn expander(&self, path: &Utf8Path) -> Result<Arc<dylib::Expander>, String> {
         let expander = || {
-            dylib::Expander::new(path)
-                .map_err(|err| format!("Cannot create expander for {path}: {err}",))
+            let expander = dylib::Expander::new(path)
+                .map_err(|err| format!("Cannot create expander for {path}: {err}",));
+            expander.map(Arc::new)
         };
 
-        Ok(match self.expanders.entry(path.to_path_buf()) {
-            Entry::Vacant(v) => v.insert(expander()?),
-            Entry::Occupied(mut e) => {
-                let time = fs::metadata(path).and_then(|it| it.modified()).ok();
-                if Some(e.get().modified_time()) != time {
-                    e.insert(expander()?);
+        Ok(
+            match self
+                .expanders
+                .lock()
+                .unwrap_or_else(PoisonError::into_inner)
+                .entry(path.to_path_buf())
+            {
+                Entry::Vacant(v) => v.insert(expander()?).clone(),
+                Entry::Occupied(mut e) => {
+                    let time = fs::metadata(path).and_then(|it| it.modified()).ok();
+                    if Some(e.get().modified_time()) != time {
+                        e.insert(expander()?);
+                    }
+                    e.get().clone()
                 }
-                e.into_mut()
-            }
-        })
+            },
+        )
     }
 }