From 5a5bba5a4655be4ee7978f8577ce3351526655a5 Mon Sep 17 00:00:00 2001
From: Edwin Cheng <edwin0cheng@gmail.com>
Date: Sat, 25 Apr 2020 12:29:49 +0800
Subject: [PATCH] Copy dylib to temp directory

---
 crates/ra_proc_macro_srv/src/dylib.rs | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs
index 476bc5c0142..018cc7bb807 100644
--- a/crates/ra_proc_macro_srv/src/dylib.rs
+++ b/crates/ra_proc_macro_srv/src/dylib.rs
@@ -2,7 +2,7 @@
 
 use crate::{proc_macro::bridge, rustc_server::TokenStream};
 use std::fs::File;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 use goblin::{mach::Mach, Object};
 use libloading::Library;
@@ -123,6 +123,9 @@ impl Expander {
             .canonicalize()
             .unwrap_or_else(|err| panic!("Cannot canonicalize {}: {:?}", lib.display(), err));
 
+        // Copy the dylib to temp directory to prevent locking in Windows
+        let lib = copy_to_temp_dir(&lib).map_err(|e| e.to_string())?;
+
         let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?;
 
         Ok(Expander { inner: library })
@@ -195,3 +198,17 @@ impl Expander {
             .collect()
     }
 }
+
+fn copy_to_temp_dir(path: &Path) -> io::Result<PathBuf> {
+    let mut to = std::env::temp_dir();
+    let file_name = path.file_name().ok_or_else(|| {
+        io::Error::new(
+            io::ErrorKind::InvalidInput,
+            format!("File path is invalid: {}", path.display()),
+        )
+    })?;
+
+    to.push(file_name);
+    std::fs::copy(path, &to)?;
+    Ok(to)
+}