Skip to content

Commit 8971681

Browse files
committed
Properly clean proc-macro-srv proc-macro temp dir
1 parent 2918a2b commit 8971681

File tree

8 files changed

+125
-18
lines changed

8 files changed

+125
-18
lines changed

src/tools/rust-analyzer/Cargo.lock

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ version = "0.7.6"
5050
source = "registry+https://github.com/rust-lang/crates.io-index"
5151
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
5252

53+
[[package]]
54+
name = "atomic-polyfill"
55+
version = "1.0.3"
56+
source = "registry+https://github.com/rust-lang/crates.io-index"
57+
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
58+
dependencies = [
59+
"critical-section",
60+
]
61+
5362
[[package]]
5463
name = "autocfg"
5564
version = "1.4.0"
@@ -125,6 +134,12 @@ version = "0.2.13"
125134
source = "registry+https://github.com/rust-lang/crates.io-index"
126135
checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa"
127136

137+
[[package]]
138+
name = "byteorder"
139+
version = "1.5.0"
140+
source = "registry+https://github.com/rust-lang/crates.io-index"
141+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
142+
128143
[[package]]
129144
name = "camino"
130145
version = "1.1.10"
@@ -318,6 +333,15 @@ version = "0.7.5"
318333
source = "registry+https://github.com/rust-lang/crates.io-index"
319334
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
320335

336+
[[package]]
337+
name = "cobs"
338+
version = "0.3.0"
339+
source = "registry+https://github.com/rust-lang/crates.io-index"
340+
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
341+
dependencies = [
342+
"thiserror 2.0.12",
343+
]
344+
321345
[[package]]
322346
name = "countme"
323347
version = "3.0.1"
@@ -339,6 +363,12 @@ dependencies = [
339363
"cfg-if",
340364
]
341365

366+
[[package]]
367+
name = "critical-section"
368+
version = "1.2.0"
369+
source = "registry+https://github.com/rust-lang/crates.io-index"
370+
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
371+
342372
[[package]]
343373
name = "crossbeam-channel"
344374
version = "0.5.15"
@@ -596,6 +626,15 @@ version = "0.31.1"
596626
source = "registry+https://github.com/rust-lang/crates.io-index"
597627
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
598628

629+
[[package]]
630+
name = "hash32"
631+
version = "0.2.1"
632+
source = "registry+https://github.com/rust-lang/crates.io-index"
633+
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
634+
dependencies = [
635+
"byteorder",
636+
]
637+
599638
[[package]]
600639
name = "hashbrown"
601640
version = "0.14.5"
@@ -622,6 +661,20 @@ dependencies = [
622661
"hashbrown 0.15.4",
623662
]
624663

664+
[[package]]
665+
name = "heapless"
666+
version = "0.7.17"
667+
source = "registry+https://github.com/rust-lang/crates.io-index"
668+
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
669+
dependencies = [
670+
"atomic-polyfill",
671+
"hash32",
672+
"rustc_version",
673+
"serde",
674+
"spin",
675+
"stable_deref_trait",
676+
]
677+
625678
[[package]]
626679
name = "hermit-abi"
627680
version = "0.5.2"
@@ -1592,6 +1645,17 @@ version = "1.11.1"
15921645
source = "registry+https://github.com/rust-lang/crates.io-index"
15931646
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
15941647

1648+
[[package]]
1649+
name = "postcard"
1650+
version = "1.1.3"
1651+
source = "registry+https://github.com/rust-lang/crates.io-index"
1652+
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
1653+
dependencies = [
1654+
"cobs",
1655+
"heapless",
1656+
"serde",
1657+
]
1658+
15951659
[[package]]
15961660
name = "potential_utf"
15971661
version = "0.1.2"
@@ -1639,6 +1703,7 @@ dependencies = [
16391703
"ra-ap-rustc_lexer 0.122.0",
16401704
"span",
16411705
"syntax-bridge",
1706+
"temp-dir",
16421707
"tt",
16431708
]
16441709

@@ -1647,6 +1712,7 @@ name = "proc-macro-srv-cli"
16471712
version = "0.0.0"
16481713
dependencies = [
16491714
"clap",
1715+
"postcard",
16501716
"proc-macro-api",
16511717
"proc-macro-srv",
16521718
"tt",
@@ -2023,6 +2089,15 @@ dependencies = [
20232089
"smallvec",
20242090
]
20252091

2092+
[[package]]
2093+
name = "rustc_version"
2094+
version = "0.4.1"
2095+
source = "registry+https://github.com/rust-lang/crates.io-index"
2096+
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
2097+
dependencies = [
2098+
"semver",
2099+
]
2100+
20262101
[[package]]
20272102
name = "ryu"
20282103
version = "1.0.20"
@@ -2240,6 +2315,15 @@ dependencies = [
22402315
"vfs",
22412316
]
22422317

2318+
[[package]]
2319+
name = "spin"
2320+
version = "0.9.8"
2321+
source = "registry+https://github.com/rust-lang/crates.io-index"
2322+
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
2323+
dependencies = [
2324+
"lock_api",
2325+
]
2326+
22432327
[[package]]
22442328
name = "stable_deref_trait"
22452329
version = "1.2.0"

src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ proc-macro-srv.workspace = true
1515
proc-macro-api.workspace = true
1616
tt.workspace = true
1717
clap = {version = "4.5.42", default-features = false, features = ["std"]}
18+
postcard = { version = "1.1.3", optional = true }
1819

1920
[features]
21+
default = ["postcard"]
2022
sysroot-abi = ["proc-macro-srv/sysroot-abi"]
2123
in-rust-tree = ["proc-macro-srv/in-rust-tree", "sysroot-abi"]
24+
postcard = ["dep:postcard"]
2225

2326

2427
[[bin]]

src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ fn main() -> std::io::Result<()> {
3939
#[derive(Copy, Clone)]
4040
enum ProtocolFormat {
4141
Json,
42+
#[cfg(feature = "postcard")]
4243
Postcard,
4344
}
4445

@@ -50,12 +51,14 @@ impl ValueEnum for ProtocolFormat {
5051
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
5152
match self {
5253
ProtocolFormat::Json => Some(clap::builder::PossibleValue::new("json")),
54+
#[cfg(feature = "postcard")]
5355
ProtocolFormat::Postcard => Some(clap::builder::PossibleValue::new("postcard")),
5456
}
5557
}
5658
fn from_str(input: &str, _ignore_case: bool) -> Result<Self, String> {
5759
match input {
5860
"json" => Ok(ProtocolFormat::Json),
61+
#[cfg(feature = "postcard")]
5962
"postcard" => Ok(ProtocolFormat::Postcard),
6063
_ => Err(format!("unknown protocol format: {input}")),
6164
}

src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ impl SpanTransformer for SpanTrans {
3737
pub(crate) fn run(format: ProtocolFormat) -> io::Result<()> {
3838
match format {
3939
ProtocolFormat::Json => run_json(),
40+
#[cfg(feature = "postcard")]
4041
ProtocolFormat::Postcard => unimplemented!(),
4142
}
4243
}
@@ -96,7 +97,7 @@ fn run_json() -> io::Result<()> {
9697

9798
srv.expand(
9899
lib,
99-
env,
100+
&env,
100101
current_dir,
101102
macro_name,
102103
macro_body,
@@ -127,7 +128,7 @@ fn run_json() -> io::Result<()> {
127128
});
128129
srv.expand(
129130
lib,
130-
env,
131+
&env,
131132
current_dir,
132133
macro_name,
133134
macro_body,

src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ doctest = false
1616
object.workspace = true
1717
libloading.workspace = true
1818
memmap2.workspace = true
19+
temp-dir.workspace = true
1920

2021
tt.workspace = true
2122
syntax-bridge.workspace = true
@@ -26,6 +27,7 @@ intern.workspace = true
2627

2728
ra-ap-rustc_lexer.workspace = true
2829

30+
2931
[target.'cfg(unix)'.dependencies]
3032
libc.workspace = true
3133

src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod version;
44

55
use proc_macro::bridge;
66
use std::{fmt, fs, io, time::SystemTime};
7+
use temp_dir::TempDir;
78

89
use libloading::Library;
910
use object::Object;
@@ -141,13 +142,16 @@ pub(crate) struct Expander {
141142
}
142143

143144
impl Expander {
144-
pub(crate) fn new(lib: &Utf8Path) -> Result<Expander, LoadProcMacroDylibError> {
145+
pub(crate) fn new(
146+
temp_dir: &TempDir,
147+
lib: &Utf8Path,
148+
) -> Result<Expander, LoadProcMacroDylibError> {
145149
// Some libraries for dynamic loading require canonicalized path even when it is
146150
// already absolute
147151
let lib = lib.canonicalize_utf8()?;
148152
let modified_time = fs::metadata(&lib).and_then(|it| it.modified())?;
149153

150-
let path = ensure_file_with_lock_free_access(&lib)?;
154+
let path = ensure_file_with_lock_free_access(temp_dir, &lib)?;
151155
let library = ProcMacroLibrary::open(path.as_ref())?;
152156

153157
Ok(Expander { inner: library, _remove_on_drop: RemoveFileOnDrop(path), modified_time })
@@ -221,17 +225,18 @@ impl Drop for RemoveFileOnDrop {
221225

222226
/// Copy the dylib to temp directory to prevent locking in Windows
223227
#[cfg(windows)]
224-
fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
228+
fn ensure_file_with_lock_free_access(
229+
temp_dir: &TempDir,
230+
path: &Utf8Path,
231+
) -> io::Result<Utf8PathBuf> {
225232
use std::collections::hash_map::RandomState;
226233
use std::hash::{BuildHasher, Hasher};
227234

228235
if std::env::var("RA_DONT_COPY_PROC_MACRO_DLL").is_ok() {
229236
return Ok(path.to_path_buf());
230237
}
231238

232-
let mut to = Utf8PathBuf::from_path_buf(std::env::temp_dir()).unwrap();
233-
to.push("rust-analyzer-proc-macros");
234-
_ = fs::create_dir(&to);
239+
let mut to = Utf8Path::from_path(temp_dir.path()).unwrap().to_owned();
235240

236241
let file_name = path.file_stem().ok_or_else(|| {
237242
io::Error::new(io::ErrorKind::InvalidInput, format!("File path is invalid: {path}"))
@@ -248,6 +253,9 @@ fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf>
248253
}
249254

250255
#[cfg(unix)]
251-
fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
256+
fn ensure_file_with_lock_free_access(
257+
_temp_dir: &TempDir,
258+
path: &Utf8Path,
259+
) -> io::Result<Utf8PathBuf> {
252260
Ok(path.to_owned())
253261
}

src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use std::{
4242

4343
use paths::{Utf8Path, Utf8PathBuf};
4444
use span::Span;
45+
use temp_dir::TempDir;
4546

4647
use crate::server_impl::TokenStream;
4748

@@ -59,11 +60,16 @@ pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION");
5960
pub struct ProcMacroSrv<'env> {
6061
expanders: Mutex<HashMap<Utf8PathBuf, Arc<dylib::Expander>>>,
6162
env: &'env EnvSnapshot,
63+
temp_dir: TempDir,
6264
}
6365

6466
impl<'env> ProcMacroSrv<'env> {
6567
pub fn new(env: &'env EnvSnapshot) -> Self {
66-
Self { expanders: Default::default(), env }
68+
Self {
69+
expanders: Default::default(),
70+
env,
71+
temp_dir: TempDir::with_prefix("proc-macro-srv").unwrap(),
72+
}
6773
}
6874
}
6975

@@ -73,7 +79,7 @@ impl ProcMacroSrv<'_> {
7379
pub fn expand<S: ProcMacroSrvSpan>(
7480
&self,
7581
lib: impl AsRef<Utf8Path>,
76-
env: Vec<(String, String)>,
82+
env: &[(String, String)],
7783
current_dir: Option<impl AsRef<Path>>,
7884
macro_name: String,
7985
macro_body: tt::TopSubtree<S>,
@@ -131,7 +137,7 @@ impl ProcMacroSrv<'_> {
131137

132138
fn expander(&self, path: &Utf8Path) -> Result<Arc<dylib::Expander>, String> {
133139
let expander = || {
134-
let expander = dylib::Expander::new(path)
140+
let expander = dylib::Expander::new(&self.temp_dir, path)
135141
.map_err(|err| format!("Cannot create expander for {path}: {err}",));
136142
expander.map(Arc::new)
137143
};
@@ -203,7 +209,7 @@ impl Default for EnvSnapshot {
203209
static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
204210

205211
struct EnvChange<'snap> {
206-
changed_vars: Vec<String>,
212+
changed_vars: Vec<&'snap str>,
207213
prev_working_dir: Option<PathBuf>,
208214
snap: &'snap EnvSnapshot,
209215
_guard: std::sync::MutexGuard<'snap, ()>,
@@ -212,7 +218,7 @@ struct EnvChange<'snap> {
212218
impl<'snap> EnvChange<'snap> {
213219
fn apply(
214220
snap: &'snap EnvSnapshot,
215-
new_vars: Vec<(String, String)>,
221+
new_vars: &'snap [(String, String)],
216222
current_dir: Option<&Path>,
217223
) -> EnvChange<'snap> {
218224
let guard = ENV_LOCK.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
@@ -232,11 +238,11 @@ impl<'snap> EnvChange<'snap> {
232238
EnvChange {
233239
snap,
234240
changed_vars: new_vars
235-
.into_iter()
241+
.iter()
236242
.map(|(k, v)| {
237243
// SAFETY: We have acquired the environment lock
238-
unsafe { env::set_var(&k, v) };
239-
k
244+
unsafe { env::set_var(k, v) };
245+
&**k
240246
})
241247
.collect(),
242248
prev_working_dir,

src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fn assert_expand_impl(
5555
expect_spanned: Expect,
5656
) {
5757
let path = proc_macro_test_dylib_path();
58-
let expander = dylib::Expander::new(&path).unwrap();
58+
let expander = dylib::Expander::new(&temp_dir::TempDir::new().unwrap(), &path).unwrap();
5959

6060
let def_site = SpanId(0);
6161
let call_site = SpanId(1);

0 commit comments

Comments
 (0)