@@ -9,37 +9,7 @@ use libloading::Library;
9
9
use object:: Object ;
10
10
use paths:: { Utf8Path , Utf8PathBuf } ;
11
11
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 } ;
43
13
44
14
/// Loads dynamic library in platform dependent manner.
45
15
///
@@ -99,13 +69,14 @@ impl From<libloading::Error> for LoadProcMacroDylibError {
99
69
}
100
70
}
101
71
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 ,
103
75
// Hold on to the library so it doesn't unload
104
76
_lib : Library ,
105
- proc_macros : crate :: proc_macros:: ProcMacros ,
106
77
}
107
78
108
- impl ProcMacroLibraryLibloading {
79
+ impl ProcMacroLibrary {
109
80
fn open ( path : & Utf8Path ) -> Result < Self , LoadProcMacroDylibError > {
110
81
let file = fs:: File :: open ( path) ?;
111
82
let file = unsafe { memmap2:: Mmap :: map ( & file) } ?;
@@ -118,27 +89,22 @@ impl ProcMacroLibraryLibloading {
118
89
} ) ?;
119
90
120
91
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 } )
136
102
}
137
103
}
138
104
139
105
// Drop order matters as we can't remove the dylib before the library is unloaded
140
106
pub ( crate ) struct Expander {
141
- inner : ProcMacroLibraryLibloading ,
107
+ inner : ProcMacroLibrary ,
142
108
_remove_on_drop : RemoveFileOnDrop ,
143
109
modified_time : SystemTime ,
144
110
}
@@ -151,7 +117,7 @@ impl Expander {
151
117
let modified_time = fs:: metadata ( & lib) . and_then ( |it| it. modified ( ) ) ?;
152
118
153
119
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 ( ) ) ?;
155
121
156
122
Ok ( Expander { inner : library, _remove_on_drop : RemoveFileOnDrop ( path) , modified_time } )
157
123
}
@@ -184,6 +150,44 @@ impl Expander {
184
150
}
185
151
}
186
152
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
+
187
191
/// Copy the dylib to temp directory to prevent locking in Windows
188
192
#[ cfg( windows) ]
189
193
fn ensure_file_with_lock_free_access ( path : & Utf8Path ) -> io:: Result < Utf8PathBuf > {
0 commit comments