33mod version;
44
55use 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 } ;
127
138use libloading:: Library ;
149use memmap2:: Mmap ;
1510use object:: Object ;
16- use paths:: { AbsPath , Utf8Path , Utf8PathBuf } ;
11+ use paths:: { Utf8Path , Utf8PathBuf } ;
1712use proc_macro_api:: ProcMacroKind ;
1813
1914use crate :: ProcMacroSrvSpan ;
@@ -28,14 +23,9 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
2823 symbol. contains ( NEW_REGISTRAR_SYMBOL )
2924}
3025
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 ( ) ?
3929 . into_iter ( )
4030 . map ( |export| export. name ( ) )
4131 . filter_map ( |sym| String :: from_utf8 ( sym. into ( ) ) . ok ( ) )
@@ -118,17 +108,17 @@ struct ProcMacroLibraryLibloading {
118108}
119109
120110impl 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+ } ) ?;
125117
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) ;
130120
131- let lib = load_library ( file ) . map_err ( invalid_data_err) ?;
121+ let lib = load_library ( path ) . map_err ( invalid_data_err) ?;
132122 let proc_macros = crate :: proc_macros:: ProcMacros :: from_lib (
133123 & lib,
134124 symbol_name,
@@ -138,20 +128,22 @@ impl ProcMacroLibraryLibloading {
138128 }
139129}
140130
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 {
148133 fn drop ( & mut self ) {
149134 #[ cfg( windows) ]
150- std:: fs:: remove_file ( & self . path ) . ok ( ) ;
151- _ = self . path ;
135+ std:: fs:: remove_file ( & self . 0 ) . unwrap ( ) ;
136+ _ = self . 0 ;
152137 }
153138}
154139
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+
155147impl Expander {
156148 pub ( crate ) fn new ( lib : & Utf8Path ) -> Result < Expander , LoadProcMacroDylibError > {
157149 // Some libraries for dynamic loading require canonicalized path even when it is
@@ -160,10 +152,9 @@ impl Expander {
160152 let modified_time = fs:: metadata ( & lib) . and_then ( |it| it. modified ( ) ) ?;
161153
162154 let path = ensure_file_with_lock_free_access ( & lib) ?;
163-
164155 let library = ProcMacroLibraryLibloading :: open ( path. as_ref ( ) ) ?;
165156
166- Ok ( Expander { inner : library, path, modified_time } )
157+ Ok ( Expander { inner : library, _remove_on_drop : RemoveFileOnDrop ( path) , modified_time } )
167158 }
168159
169160 pub ( crate ) fn expand < S : ProcMacroSrvSpan > (
@@ -205,20 +196,23 @@ fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf>
205196 }
206197
207198 let mut to = Utf8PathBuf :: from_path_buf ( std:: env:: temp_dir ( ) ) . unwrap ( ) ;
199+ to. push ( "rust-analyzer-proc-macros" ) ;
200+ _ = fs:: create_dir ( & to) ;
208201
209202 let file_name = path. file_name ( ) . ok_or_else ( || {
210203 io:: Error :: new ( io:: ErrorKind :: InvalidInput , format ! ( "File path is invalid: {path}" ) )
211204 } ) ?;
212205
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) ?;
222216 Ok ( to)
223217}
224218
0 commit comments