@@ -692,20 +692,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
692692 path : & Path ,
693693 stable_crate_id : StableCrateId ,
694694 ) -> Result < & ' static [ ProcMacro ] , CrateError > {
695- // Make sure the path contains a / or the linker will search for it.
696- let path = try_canonicalize ( path) . unwrap ( ) ;
697- let lib = load_dylib ( & path, 5 ) . map_err ( |err| CrateError :: DlOpen ( err) ) ?;
698-
699695 let sym_name = self . sess . generate_proc_macro_decls_symbol ( stable_crate_id) ;
700- let sym = unsafe { lib. get :: < * const & [ ProcMacro ] > ( sym_name. as_bytes ( ) ) }
701- . map_err ( |err| CrateError :: DlSym ( err. to_string ( ) ) ) ?;
702-
703- // Intentionally leak the dynamic library. We can't ever unload it
704- // since the library can make things that will live arbitrarily long.
705- let sym = unsafe { sym. into_raw ( ) } ;
706- std:: mem:: forget ( lib) ;
707-
708- Ok ( unsafe { * * sym } )
696+ Ok ( unsafe { * load_symbol_from_dylib :: < * const & [ ProcMacro ] > ( path, & sym_name) ? } )
709697 }
710698
711699 fn inject_panic_runtime ( & mut self , krate : & ast:: Crate ) {
@@ -1116,6 +1104,10 @@ fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
11161104 f. spans
11171105}
11181106
1107+ fn format_dlopen_err ( e : & ( dyn std:: error:: Error + ' static ) ) -> String {
1108+ e. sources ( ) . map ( |e| format ! ( ": {e}" ) ) . collect ( )
1109+ }
1110+
11191111// On Windows the compiler would sometimes intermittently fail to open the
11201112// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
11211113// system still holds a lock on the file, so we retry a few times before calling it
@@ -1154,9 +1146,43 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
11541146
11551147 let last_error = last_error. unwrap ( ) ;
11561148 let message = if let Some ( src) = last_error. source ( ) {
1157- format ! ( "{last_error } ({src}) (retried {max_attempts} times)" )
1149+ format ! ( "{} ({src}) (retried {max_attempts} times)" , format_dlopen_err ( & last_error ) )
11581150 } else {
1159- format ! ( "{last_error } (retried {max_attempts} times)" )
1151+ format ! ( "{} (retried {max_attempts} times)" , format_dlopen_err ( & last_error ) )
11601152 } ;
11611153 Err ( message)
11621154}
1155+
1156+ pub enum DylibError {
1157+ DlOpen ( String , String ) ,
1158+ DlSym ( String , String ) ,
1159+ }
1160+
1161+ impl From < DylibError > for CrateError {
1162+ fn from ( err : DylibError ) -> CrateError {
1163+ match err {
1164+ DylibError :: DlOpen ( path, err) => CrateError :: DlOpen ( path, err) ,
1165+ DylibError :: DlSym ( path, err) => CrateError :: DlSym ( path, err) ,
1166+ }
1167+ }
1168+ }
1169+
1170+ pub unsafe fn load_symbol_from_dylib < T : Copy > (
1171+ path : & Path ,
1172+ sym_name : & str ,
1173+ ) -> Result < T , DylibError > {
1174+ // Make sure the path contains a / or the linker will search for it.
1175+ let path = try_canonicalize ( path) . unwrap ( ) ;
1176+ let lib =
1177+ load_dylib ( & path, 5 ) . map_err ( |err| DylibError :: DlOpen ( path. display ( ) . to_string ( ) , err) ) ?;
1178+
1179+ let sym = unsafe { lib. get :: < T > ( sym_name. as_bytes ( ) ) }
1180+ . map_err ( |err| DylibError :: DlSym ( path. display ( ) . to_string ( ) , format_dlopen_err ( & err) ) ) ?;
1181+
1182+ // Intentionally leak the dynamic library. We can't ever unload it
1183+ // since the library can make things that will live arbitrarily long.
1184+ let sym = unsafe { sym. into_raw ( ) } ;
1185+ std:: mem:: forget ( lib) ;
1186+
1187+ Ok ( * sym)
1188+ }
0 commit comments