@@ -350,6 +350,7 @@ impl<'a> CrateLocator<'a> {
350350 self . crate_rejections . via_kind . clear ( ) ;
351351 self . crate_rejections . via_version . clear ( ) ;
352352 self . crate_rejections . via_filename . clear ( ) ;
353+ self . crate_rejections . via_invalid . clear ( ) ;
353354 }
354355
355356 crate fn maybe_load_library_crate ( & mut self ) -> Result < Option < Library > , CrateError > {
@@ -548,7 +549,17 @@ impl<'a> CrateLocator<'a> {
548549 continue ;
549550 }
550551 }
551- Err ( err) => {
552+ Err ( MetadataError :: LoadFailure ( err) ) => {
553+ info ! ( "no metadata found: {}" , err) ;
554+ // The file was present and created by the same compiler version, but we
555+ // couldn't load it for some reason. Give a hard error instead of silently
556+ // ignoring it, but only if we would have given an error anyway.
557+ self . crate_rejections
558+ . via_invalid
559+ . push ( CrateMismatch { path : lib, got : err } ) ;
560+ continue ;
561+ }
562+ Err ( err @ MetadataError :: NotPresent ( _) ) => {
552563 info ! ( "no metadata found: {}" , err) ;
553564 continue ;
554565 }
@@ -726,25 +737,28 @@ impl<'a> CrateLocator<'a> {
726737fn get_metadata_section (
727738 target : & Target ,
728739 flavor : CrateFlavor ,
729- filename : & Path ,
740+ filename : & ' p Path ,
730741 loader : & dyn MetadataLoader ,
731- ) -> Result < MetadataBlob , String > {
742+ ) -> Result < MetadataBlob , MetadataError < ' p > > {
732743 if !filename. exists ( ) {
733- return Err ( format ! ( "no such file: '{}'" , filename . display ( ) ) ) ;
744+ return Err ( MetadataError :: NotPresent ( filename ) ) ;
734745 }
735746 let raw_bytes: MetadataRef = match flavor {
736- CrateFlavor :: Rlib => loader. get_rlib_metadata ( target, filename) ?,
747+ CrateFlavor :: Rlib => {
748+ loader. get_rlib_metadata ( target, filename) . map_err ( MetadataError :: LoadFailure ) ?
749+ }
737750 CrateFlavor :: Dylib => {
738- let buf = loader. get_dylib_metadata ( target, filename) ?;
751+ let buf =
752+ loader. get_dylib_metadata ( target, filename) . map_err ( MetadataError :: LoadFailure ) ?;
739753 // The header is uncompressed
740754 let header_len = METADATA_HEADER . len ( ) ;
741755 debug ! ( "checking {} bytes of metadata-version stamp" , header_len) ;
742756 let header = & buf[ ..cmp:: min ( header_len, buf. len ( ) ) ] ;
743757 if header != METADATA_HEADER {
744- return Err ( format ! (
745- "incompatible metadata version found: '{}' " ,
758+ return Err ( MetadataError :: LoadFailure ( format ! (
759+ "invalid metadata version found: {} " ,
746760 filename. display( )
747- ) ) ;
761+ ) ) ) ;
748762 }
749763
750764 // Header is okay -> inflate the actual metadata
@@ -756,17 +770,28 @@ fn get_metadata_section(
756770 match FrameDecoder :: new ( compressed_bytes) . read_to_end ( & mut inflated) {
757771 Ok ( _) => rustc_erase_owner ! ( OwningRef :: new( inflated) . map_owner_box( ) ) ,
758772 Err ( _) => {
759- return Err ( format ! ( "failed to decompress metadata: {}" , filename. display( ) ) ) ;
773+ return Err ( MetadataError :: LoadFailure ( format ! (
774+ "failed to decompress metadata: {}" ,
775+ filename. display( )
776+ ) ) ) ;
760777 }
761778 }
762779 }
763780 CrateFlavor :: Rmeta => {
764781 // mmap the file, because only a small fraction of it is read.
765- let file = std:: fs:: File :: open ( filename)
766- . map_err ( |_| format ! ( "failed to open rmeta metadata: '{}'" , filename. display( ) ) ) ?;
782+ let file = std:: fs:: File :: open ( filename) . map_err ( |_| {
783+ MetadataError :: LoadFailure ( format ! (
784+ "failed to open rmeta metadata: '{}'" ,
785+ filename. display( )
786+ ) )
787+ } ) ?;
767788 let mmap = unsafe { Mmap :: map ( file) } ;
768- let mmap = mmap
769- . map_err ( |_| format ! ( "failed to mmap rmeta metadata: '{}'" , filename. display( ) ) ) ?;
789+ let mmap = mmap. map_err ( |_| {
790+ MetadataError :: LoadFailure ( format ! (
791+ "failed to mmap rmeta metadata: '{}'" ,
792+ filename. display( )
793+ ) )
794+ } ) ?;
770795
771796 rustc_erase_owner ! ( OwningRef :: new( mmap) . map_owner_box( ) )
772797 }
@@ -775,7 +800,10 @@ fn get_metadata_section(
775800 if blob. is_compatible ( ) {
776801 Ok ( blob)
777802 } else {
778- Err ( format ! ( "incompatible metadata version found: '{}'" , filename. display( ) ) )
803+ Err ( MetadataError :: LoadFailure ( format ! (
804+ "invalid metadata version found: {}" ,
805+ filename. display( )
806+ ) ) )
779807 }
780808}
781809
@@ -854,6 +882,7 @@ struct CrateRejections {
854882 via_kind : Vec < CrateMismatch > ,
855883 via_version : Vec < CrateMismatch > ,
856884 via_filename : Vec < CrateMismatch > ,
885+ via_invalid : Vec < CrateMismatch > ,
857886}
858887
859888/// Candidate rejection reasons collected during crate search.
@@ -883,6 +912,24 @@ crate enum CrateError {
883912 NonDylibPlugin ( Symbol ) ,
884913}
885914
915+ enum MetadataError < ' a > {
916+ /// The file was missing.
917+ NotPresent ( & ' a Path ) ,
918+ /// The file was present and invalid.
919+ LoadFailure ( String ) ,
920+ }
921+
922+ impl fmt:: Display for MetadataError < ' _ > {
923+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
924+ match self {
925+ MetadataError :: NotPresent ( filename) => {
926+ f. write_str ( & format ! ( "no such file: '{}'" , filename. display( ) ) )
927+ }
928+ MetadataError :: LoadFailure ( msg) => f. write_str ( msg) ,
929+ }
930+ }
931+ }
932+
886933impl CrateError {
887934 crate fn report ( self , sess : & Session , span : Span , missing_core : bool ) -> ! {
888935 let mut err = match self {
@@ -1064,6 +1111,19 @@ impl CrateError {
10641111 }
10651112 err. note ( & msg) ;
10661113 err
1114+ } else if !locator. crate_rejections . via_invalid . is_empty ( ) {
1115+ let mut err = struct_span_err ! (
1116+ sess,
1117+ span,
1118+ E0786 ,
1119+ "found invalid metadata files for crate `{}`{}" ,
1120+ crate_name,
1121+ add,
1122+ ) ;
1123+ for CrateMismatch { path : _, got } in locator. crate_rejections . via_invalid {
1124+ err. note ( & got) ;
1125+ }
1126+ err
10671127 } else {
10681128 let mut err = struct_span_err ! (
10691129 sess,
0 commit comments