3
3
mod version;
4
4
5
5
use proc_macro:: bridge;
6
- use std:: {
7
- fmt,
8
- fs:: { self , File } ,
9
- io,
10
- time:: SystemTime ,
11
- } ;
6
+ use std:: { fmt, fs, io, time:: SystemTime } ;
12
7
13
8
use libloading:: Library ;
14
9
use memmap2:: Mmap ;
15
10
use object:: Object ;
16
- use paths:: { AbsPath , Utf8Path , Utf8PathBuf } ;
11
+ use paths:: { Utf8Path , Utf8PathBuf } ;
17
12
use proc_macro_api:: ProcMacroKind ;
18
13
19
14
use crate :: ProcMacroSrvSpan ;
@@ -28,14 +23,9 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
28
23
symbol. contains ( NEW_REGISTRAR_SYMBOL )
29
24
}
30
25
31
- fn find_registrar_symbol ( file : & Utf8Path ) -> io:: Result < Option < String > > {
32
- let file = File :: open ( file) ?;
33
- let buffer = unsafe { Mmap :: map ( & file) ? } ;
34
-
35
- Ok ( object:: File :: parse ( & * buffer)
36
- . map_err ( invalid_data_err) ?
37
- . exports ( )
38
- . map_err ( invalid_data_err) ?
26
+ fn find_registrar_symbol ( buffer : & [ u8 ] ) -> object:: Result < Option < String > > {
27
+ Ok ( object:: File :: parse ( buffer) ?
28
+ . exports ( ) ?
39
29
. into_iter ( )
40
30
. map ( |export| export. name ( ) )
41
31
. filter_map ( |sym| String :: from_utf8 ( sym. into ( ) ) . ok ( ) )
@@ -118,17 +108,17 @@ struct ProcMacroLibraryLibloading {
118
108
}
119
109
120
110
impl ProcMacroLibraryLibloading {
121
- fn open ( file : & Utf8Path ) -> Result < Self , LoadProcMacroDylibError > {
122
- let symbol_name = find_registrar_symbol ( file) ?. ok_or_else ( || {
123
- invalid_data_err ( format ! ( "Cannot find registrar symbol in file {file}" ) )
124
- } ) ?;
111
+ fn open ( path : & Utf8Path ) -> Result < Self , LoadProcMacroDylibError > {
112
+ let buffer = unsafe { Mmap :: map ( & fs:: File :: open ( path) ?) ? } ;
113
+ let symbol_name =
114
+ find_registrar_symbol ( & buffer) . map_err ( invalid_data_err) ?. ok_or_else ( || {
115
+ invalid_data_err ( format ! ( "Cannot find registrar symbol in file {path}" ) )
116
+ } ) ?;
125
117
126
- let abs_file: & AbsPath = file
127
- . try_into ( )
128
- . map_err ( |_| invalid_data_err ( format ! ( "expected an absolute path, got {file}" ) ) ) ?;
129
- let version_info = version:: read_dylib_info ( abs_file) ?;
118
+ let version_info = version:: read_dylib_info ( & buffer) ?;
119
+ drop ( buffer) ;
130
120
131
- let lib = load_library ( file ) . map_err ( invalid_data_err) ?;
121
+ let lib = load_library ( path ) . map_err ( invalid_data_err) ?;
132
122
let proc_macros = crate :: proc_macros:: ProcMacros :: from_lib (
133
123
& lib,
134
124
symbol_name,
@@ -138,20 +128,22 @@ impl ProcMacroLibraryLibloading {
138
128
}
139
129
}
140
130
141
- pub ( crate ) struct Expander {
142
- inner : ProcMacroLibraryLibloading ,
143
- path : Utf8PathBuf ,
144
- modified_time : SystemTime ,
145
- }
146
-
147
- impl Drop for Expander {
131
+ struct RemoveFileOnDrop ( Utf8PathBuf ) ;
132
+ impl Drop for RemoveFileOnDrop {
148
133
fn drop ( & mut self ) {
149
134
#[ cfg( windows) ]
150
- std:: fs:: remove_file ( & self . path ) . ok ( ) ;
151
- _ = self . path ;
135
+ std:: fs:: remove_file ( & self . 0 ) . unwrap ( ) ;
136
+ _ = self . 0 ;
152
137
}
153
138
}
154
139
140
+ // Drop order matters as we can't remove the dylib before the library is unloaded
141
+ pub ( crate ) struct Expander {
142
+ inner : ProcMacroLibraryLibloading ,
143
+ _remove_on_drop : RemoveFileOnDrop ,
144
+ modified_time : SystemTime ,
145
+ }
146
+
155
147
impl Expander {
156
148
pub ( crate ) fn new ( lib : & Utf8Path ) -> Result < Expander , LoadProcMacroDylibError > {
157
149
// Some libraries for dynamic loading require canonicalized path even when it is
@@ -160,10 +152,9 @@ impl Expander {
160
152
let modified_time = fs:: metadata ( & lib) . and_then ( |it| it. modified ( ) ) ?;
161
153
162
154
let path = ensure_file_with_lock_free_access ( & lib) ?;
163
-
164
155
let library = ProcMacroLibraryLibloading :: open ( path. as_ref ( ) ) ?;
165
156
166
- Ok ( Expander { inner : library, path, modified_time } )
157
+ Ok ( Expander { inner : library, _remove_on_drop : RemoveFileOnDrop ( path) , modified_time } )
167
158
}
168
159
169
160
pub ( crate ) fn expand < S : ProcMacroSrvSpan > (
@@ -205,20 +196,23 @@ fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf>
205
196
}
206
197
207
198
let mut to = Utf8PathBuf :: from_path_buf ( std:: env:: temp_dir ( ) ) . unwrap ( ) ;
199
+ to. push ( "rust-analyzer-proc-macros" ) ;
200
+ _ = fs:: create_dir ( & to) ;
208
201
209
202
let file_name = path. file_name ( ) . ok_or_else ( || {
210
203
io:: Error :: new ( io:: ErrorKind :: InvalidInput , format ! ( "File path is invalid: {path}" ) )
211
204
} ) ?;
212
205
213
- // Generate a unique number by abusing `HashMap`'s hasher.
214
- // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd.
215
- let t = RandomState :: new ( ) . build_hasher ( ) . finish ( ) ;
216
-
217
- let mut unique_name = t. to_string ( ) ;
218
- unique_name. push_str ( file_name) ;
219
-
220
- to. push ( unique_name) ;
221
- std:: fs:: copy ( path, & to) ?;
206
+ to. push ( {
207
+ // Generate a unique number by abusing `HashMap`'s hasher.
208
+ // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd.
209
+ let t = RandomState :: new ( ) . build_hasher ( ) . finish ( ) ;
210
+ let mut unique_name = t. to_string ( ) ;
211
+ unique_name. push_str ( file_name) ;
212
+ unique_name. push ( '-' ) ;
213
+ unique_name
214
+ } ) ;
215
+ fs:: copy ( path, & to) ?;
222
216
Ok ( to)
223
217
}
224
218
0 commit comments