1- use  rustc_data_structures:: fx:: { FxHashMap ,   FxHashSet } ; 
1+ use  rustc_data_structures:: fx:: { FxHashSet ,   FxIndexMap } ; 
22use  rustc_data_structures:: temp_dir:: MaybeTempDir ; 
3- use  rustc_errors:: Handler ; 
3+ use  rustc_errors:: { ErrorReported ,   Handler } ; 
44use  rustc_fs_util:: fix_windows_verbatim_for_gcc; 
55use  rustc_hir:: def_id:: CrateNum ; 
6- use  rustc_middle:: middle:: cstore:: { DllCallingConvention ,   DllImport } ; 
6+ use  rustc_middle:: middle:: cstore:: DllImport ; 
77use  rustc_middle:: middle:: dependency_format:: Linkage ; 
88use  rustc_session:: config:: { self ,  CFGuard ,  CrateType ,  DebugInfo ,  LdImpl ,  Strip } ; 
99use  rustc_session:: config:: { OutputFilenames ,  OutputType ,  PrintRequest } ; 
@@ -35,7 +35,6 @@ use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, Se
3535use  tempfile:: Builder  as  TempFileBuilder ; 
3636
3737use  std:: ffi:: OsString ; 
38- use  std:: iter:: FromIterator ; 
3938use  std:: path:: { Path ,  PathBuf } ; 
4039use  std:: process:: { ExitStatus ,  Output ,  Stdio } ; 
4140use  std:: { ascii,  char,  env,  fmt,  fs,  io,  mem,  str} ; 
@@ -54,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
5453    sess :  & ' a  Session , 
5554    codegen_results :  & CodegenResults , 
5655    outputs :  & OutputFilenames , 
57- )  { 
56+ )  ->  Result < ( ) ,   ErrorReported >   { 
5857    let  _timer = sess. timer ( "link_binary" ) ; 
5958    let  output_metadata = sess. opts . output_types . contains_key ( & OutputType :: Metadata ) ; 
6059    for  & crate_type in  sess. crate_types ( ) . iter ( )  { 
@@ -95,11 +94,17 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
9594            match  crate_type { 
9695                CrateType :: Rlib  => { 
9796                    let  _timer = sess. timer ( "link_rlib" ) ; 
98-                     link_rlib :: < B > ( sess,  codegen_results,  RlibFlavor :: Normal ,  & out_filename,  & path) 
99-                         . build ( ) ; 
97+                     link_rlib :: < B > ( 
98+                         sess, 
99+                         codegen_results, 
100+                         RlibFlavor :: Normal , 
101+                         & out_filename, 
102+                         & path, 
103+                     ) ?
104+                     . build ( ) ; 
100105                } 
101106                CrateType :: Staticlib  => { 
102-                     link_staticlib :: < B > ( sess,  codegen_results,  & out_filename,  & path) ; 
107+                     link_staticlib :: < B > ( sess,  codegen_results,  & out_filename,  & path) ? ; 
103108                } 
104109                _ => { 
105110                    link_natively :: < B > ( 
@@ -145,6 +150,8 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
145150            } 
146151        } 
147152    } ) ; 
153+ 
154+     Ok ( ( ) ) 
148155} 
149156
150157pub  fn  each_linked_rlib ( 
@@ -220,7 +227,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
220227    flavor :  RlibFlavor , 
221228    out_filename :  & Path , 
222229    tmpdir :  & MaybeTempDir , 
223- )  -> B  { 
230+ )  -> Result < B ,   ErrorReported >  { 
224231    info ! ( "preparing rlib to {:?}" ,  out_filename) ; 
225232    let  mut  ab = <B  as  ArchiveBuilder >:: new ( sess,  out_filename,  None ) ; 
226233
@@ -259,7 +266,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
259266    } 
260267
261268    for  ( raw_dylib_name,  raw_dylib_imports)  in 
262-         collate_raw_dylibs ( sess,  & codegen_results. crate_info . used_libraries ) 
269+         collate_raw_dylibs ( sess,  & codegen_results. crate_info . used_libraries ) ? 
263270    { 
264271        ab. inject_dll_import_lib ( & raw_dylib_name,  & raw_dylib_imports,  tmpdir) ; 
265272    } 
@@ -312,7 +319,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
312319            } 
313320        } 
314321    } 
315-     return  ab ; 
322+     return  Ok ( ab ) ; 
316323
317324    // For rlibs we "pack" rustc metadata into a dummy object file. When rustc 
318325    // creates a dylib crate type it will pass `--whole-archive` (or the 
@@ -454,65 +461,40 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
454461fn  collate_raw_dylibs ( 
455462    sess :  & Session , 
456463    used_libraries :  & [ NativeLib ] , 
457- )  -> Vec < ( String ,  Vec < DllImport > ) >  { 
458-     let  mut  dylib_table:  FxHashMap < String ,  FxHashSet < DllImport > >  = FxHashMap :: default ( ) ; 
464+ )  -> Result < Vec < ( String ,  Vec < DllImport > ) > ,  ErrorReported >  { 
465+     // Use index maps to preserve original order of imports and libraries. 
466+     let  mut  dylib_table = FxIndexMap :: < String ,  FxIndexMap < Symbol ,  & DllImport > > :: default ( ) ; 
459467
460468    for  lib in  used_libraries { 
461469        if  lib. kind  == NativeLibKind :: RawDylib  { 
462-             let  name = lib. name . unwrap_or_else ( ||
463-                 bug ! ( "`link` attribute with kind = \" raw-dylib\"  and no name should have caused error earlier" ) 
464-             ) ; 
465-             let  name = if  matches ! ( lib. verbatim,  Some ( true ) )  { 
466-                 name. to_string ( ) 
467-             }  else  { 
468-                 format ! ( "{}.dll" ,  name) 
469-             } ; 
470-             dylib_table. entry ( name) . or_default ( ) . extend ( lib. dll_imports . iter ( ) . cloned ( ) ) ; 
471-         } 
472-     } 
473- 
474-     // Rustc already signals an error if we have two imports with the same name but different 
475-     // calling conventions (or function signatures), so we don't have pay attention to those 
476-     // when ordering. 
477-     // FIXME: when we add support for ordinals, figure out if we need to do anything if we 
478-     // have two DllImport values with the same name but different ordinals. 
479-     let  mut  result:  Vec < ( String ,  Vec < DllImport > ) >  = dylib_table
480-         . into_iter ( ) 
481-         . map ( |( lib_name,  import_table) | { 
482-             let  mut  imports = Vec :: from_iter ( import_table. into_iter ( ) ) ; 
483-             imports. sort_unstable_by_key ( |x :  & DllImport | x. name . as_str ( ) ) ; 
484-             ( lib_name,  imports) 
485-         } ) 
486-         . collect :: < Vec < _ > > ( ) ; 
487-     result. sort_unstable_by ( |a :  & ( String ,  Vec < DllImport > ) ,  b :  & ( String ,  Vec < DllImport > ) | { 
488-         a. 0 . cmp ( & b. 0 ) 
489-     } ) ; 
490-     let  result = result; 
491- 
492-     // Check for multiple imports with the same name but different calling conventions or 
493-     // (when relevant) argument list sizes.  Rustc only signals an error for this if the 
494-     // declarations are at the same scope level; if one shadows the other, we only get a lint 
495-     // warning. 
496-     for  ( library,  imports)  in  & result { 
497-         let  mut  import_table:  FxHashMap < Symbol ,  DllCallingConvention >  = FxHashMap :: default ( ) ; 
498-         for  import in  imports { 
499-             if  let  Some ( old_convention)  =
500-                 import_table. insert ( import. name ,  import. calling_convention ) 
501-             { 
502-                 if  import. calling_convention  != old_convention { 
503-                     sess. span_fatal ( 
504-                         import. span , 
505-                         & format ! ( 
506-                             "multiple definitions of external function `{}` from library `{}` have different calling conventions" , 
507-                             import. name, 
508-                             library, 
509-                     ) ) ; 
470+             let  ext = if  matches ! ( lib. verbatim,  Some ( true ) )  {  ""  }  else  {  ".dll"  } ; 
471+             let  name = format ! ( "{}{}" ,  lib. name. expect( "unnamed raw-dylib library" ) ,  ext) ; 
472+             let  imports = dylib_table. entry ( name. clone ( ) ) . or_default ( ) ; 
473+             for  import in  & lib. dll_imports  { 
474+                 if  let  Some ( old_import)  = imports. insert ( import. name ,  import)  { 
475+                     // FIXME: when we add support for ordinals, figure out if we need to do anything 
476+                     // if we have two DllImport values with the same name but different ordinals. 
477+                     if  import. calling_convention  != old_import. calling_convention  { 
478+                         sess. span_err ( 
479+                             import. span , 
480+                             & format ! ( 
481+                                 "multiple declarations of external function `{}` from \  
482+                                   library `{}` have different calling conventions", 
483+                                 import. name,  name, 
484+                             ) , 
485+                         ) ; 
486+                     } 
510487                } 
511488            } 
512489        } 
513490    } 
514- 
515-     result
491+     sess. compile_status ( ) ?; 
492+     Ok ( dylib_table
493+         . into_iter ( ) 
494+         . map ( |( name,  imports) | { 
495+             ( name,  imports. into_iter ( ) . map ( |( _,  import) | import. clone ( ) ) . collect ( ) ) 
496+         } ) 
497+         . collect ( ) ) 
516498} 
517499
518500/// Create a static archive. 
@@ -531,9 +513,9 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
531513    codegen_results :  & CodegenResults , 
532514    out_filename :  & Path , 
533515    tempdir :  & MaybeTempDir , 
534- )  { 
516+ )  ->  Result < ( ) ,   ErrorReported >   { 
535517    let  mut  ab =
536-         link_rlib :: < B > ( sess,  codegen_results,  RlibFlavor :: StaticlibBase ,  out_filename,  tempdir) ; 
518+         link_rlib :: < B > ( sess,  codegen_results,  RlibFlavor :: StaticlibBase ,  out_filename,  tempdir) ? ; 
537519    let  mut  all_native_libs = vec ! [ ] ; 
538520
539521    let  res = each_linked_rlib ( & codegen_results. crate_info ,  & mut  |cnum,  path| { 
@@ -581,6 +563,8 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
581563            print_native_static_libs ( sess,  & all_native_libs) ; 
582564        } 
583565    } 
566+ 
567+     Ok ( ( ) ) 
584568} 
585569
586570fn  escape_stdout_stderr_string ( s :  & [ u8 ] )  -> String  { 
0 commit comments