@@ -9,37 +9,7 @@ use libloading::Library;
99use object:: Object ;
1010use paths:: { Utf8Path , Utf8PathBuf } ;
1111
12- use crate :: { proc_macros:: ProcMacroKind , ProcMacroSrvSpan } ;
13-
14- const NEW_REGISTRAR_SYMBOL : & str = "_rustc_proc_macro_decls_" ;
15-
16- fn invalid_data_err ( e : impl Into < Box < dyn std:: error:: Error + Send + Sync > > ) -> io:: Error {
17- io:: Error :: new ( io:: ErrorKind :: InvalidData , e)
18- }
19-
20- fn is_derive_registrar_symbol ( symbol : & str ) -> bool {
21- symbol. contains ( NEW_REGISTRAR_SYMBOL )
22- }
23-
24- fn find_registrar_symbol ( obj : & object:: File < ' _ > ) -> object:: Result < Option < String > > {
25- Ok ( obj
26- . exports ( ) ?
27- . into_iter ( )
28- . map ( |export| export. name ( ) )
29- . filter_map ( |sym| String :: from_utf8 ( sym. into ( ) ) . ok ( ) )
30- . find ( |sym| is_derive_registrar_symbol ( sym) )
31- . map ( |sym| {
32- // From MacOS docs:
33- // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
34- // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
35- // prepended with an underscore.
36- if cfg ! ( target_os = "macos" ) && sym. starts_with ( '_' ) {
37- sym[ 1 ..] . to_owned ( )
38- } else {
39- sym
40- }
41- } ) )
42- }
12+ use crate :: { proc_macros:: ProcMacros , ProcMacroKind , ProcMacroSrvSpan } ;
4313
4414/// Loads dynamic library in platform dependent manner.
4515///
@@ -99,13 +69,14 @@ impl From<libloading::Error> for LoadProcMacroDylibError {
9969 }
10070}
10171
102- struct ProcMacroLibraryLibloading {
72+ struct ProcMacroLibrary {
73+ // 'static is actually the lifetime of library, so make sure this drops before _lib
74+ proc_macros : & ' static ProcMacros ,
10375 // Hold on to the library so it doesn't unload
10476 _lib : Library ,
105- proc_macros : crate :: proc_macros:: ProcMacros ,
10677}
10778
108- impl ProcMacroLibraryLibloading {
79+ impl ProcMacroLibrary {
10980 fn open ( path : & Utf8Path ) -> Result < Self , LoadProcMacroDylibError > {
11081 let file = fs:: File :: open ( path) ?;
11182 let file = unsafe { memmap2:: Mmap :: map ( & file) } ?;
@@ -118,27 +89,22 @@ impl ProcMacroLibraryLibloading {
11889 } ) ?;
11990
12091 let lib = load_library ( path) . map_err ( invalid_data_err) ?;
121- let proc_macros = crate :: proc_macros:: ProcMacros :: from_lib (
122- & lib,
123- symbol_name,
124- & version_info. version_string ,
125- ) ?;
126- Ok ( ProcMacroLibraryLibloading { _lib : lib, proc_macros } )
127- }
128- }
129-
130- struct RemoveFileOnDrop ( Utf8PathBuf ) ;
131- impl Drop for RemoveFileOnDrop {
132- fn drop ( & mut self ) {
133- #[ cfg( windows) ]
134- std:: fs:: remove_file ( & self . 0 ) . unwrap ( ) ;
135- _ = self . 0 ;
92+ let proc_macros = unsafe {
93+ // SAFETY: We extend the lifetime here to avoid referential borrow problems
94+ // We never reveal proc_macros to the outside and drop it before _lib
95+ std:: mem:: transmute :: < & ProcMacros , & ' static ProcMacros > ( ProcMacros :: from_lib (
96+ & lib,
97+ symbol_name,
98+ & version_info. version_string ,
99+ ) ?)
100+ } ;
101+ Ok ( ProcMacroLibrary { _lib : lib, proc_macros } )
136102 }
137103}
138104
139105// Drop order matters as we can't remove the dylib before the library is unloaded
140106pub ( crate ) struct Expander {
141- inner : ProcMacroLibraryLibloading ,
107+ inner : ProcMacroLibrary ,
142108 _remove_on_drop : RemoveFileOnDrop ,
143109 modified_time : SystemTime ,
144110}
@@ -151,7 +117,7 @@ impl Expander {
151117 let modified_time = fs:: metadata ( & lib) . and_then ( |it| it. modified ( ) ) ?;
152118
153119 let path = ensure_file_with_lock_free_access ( & lib) ?;
154- let library = ProcMacroLibraryLibloading :: open ( path. as_ref ( ) ) ?;
120+ let library = ProcMacroLibrary :: open ( path. as_ref ( ) ) ?;
155121
156122 Ok ( Expander { inner : library, _remove_on_drop : RemoveFileOnDrop ( path) , modified_time } )
157123 }
@@ -184,6 +150,44 @@ impl Expander {
184150 }
185151}
186152
153+ fn invalid_data_err ( e : impl Into < Box < dyn std:: error:: Error + Send + Sync > > ) -> io:: Error {
154+ io:: Error :: new ( io:: ErrorKind :: InvalidData , e)
155+ }
156+
157+ fn is_derive_registrar_symbol ( symbol : & str ) -> bool {
158+ const NEW_REGISTRAR_SYMBOL : & str = "_rustc_proc_macro_decls_" ;
159+ symbol. contains ( NEW_REGISTRAR_SYMBOL )
160+ }
161+
162+ fn find_registrar_symbol ( obj : & object:: File < ' _ > ) -> object:: Result < Option < String > > {
163+ Ok ( obj
164+ . exports ( ) ?
165+ . into_iter ( )
166+ . map ( |export| export. name ( ) )
167+ . filter_map ( |sym| String :: from_utf8 ( sym. into ( ) ) . ok ( ) )
168+ . find ( |sym| is_derive_registrar_symbol ( sym) )
169+ . map ( |sym| {
170+ // From MacOS docs:
171+ // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
172+ // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
173+ // prepended with an underscore.
174+ if cfg ! ( target_os = "macos" ) && sym. starts_with ( '_' ) {
175+ sym[ 1 ..] . to_owned ( )
176+ } else {
177+ sym
178+ }
179+ } ) )
180+ }
181+
182+ struct RemoveFileOnDrop ( Utf8PathBuf ) ;
183+ impl Drop for RemoveFileOnDrop {
184+ fn drop ( & mut self ) {
185+ #[ cfg( windows) ]
186+ std:: fs:: remove_file ( & self . 0 ) . unwrap ( ) ;
187+ _ = self . 0 ;
188+ }
189+ }
190+
187191/// Copy the dylib to temp directory to prevent locking in Windows
188192#[ cfg( windows) ]
189193fn ensure_file_with_lock_free_access ( path : & Utf8Path ) -> io:: Result < Utf8PathBuf > {
0 commit comments