@@ -349,6 +349,7 @@ impl<'a> CrateLocator<'a> {
349349 self . crate_rejections . via_kind . clear ( ) ;
350350 self . crate_rejections . via_version . clear ( ) ;
351351 self . crate_rejections . via_filename . clear ( ) ;
352+ self . crate_rejections . via_invalid . clear ( ) ;
352353 }
353354
354355 crate fn maybe_load_library_crate ( & mut self ) -> Result < Option < Library > , CrateError > {
@@ -538,7 +539,16 @@ impl<'a> CrateLocator<'a> {
538539 continue ;
539540 }
540541 }
541- Err ( err) => {
542+ Err ( MetadataError :: LoadFailure ( err) ) => {
543+ // The file was present and created by the same compiler version, but we
544+ // couldn't load it for some reason. Give a hard error instead of silently
545+ // ignoring it, but only if we would have given an error anyway.
546+ self . crate_rejections
547+ . via_invalid
548+ . push ( CrateMismatch { path : lib, got : err } ) ;
549+ continue ;
550+ }
551+ Err ( err @ MetadataError :: NotPresent ( _) ) => {
542552 warn ! ( "no metadata found: {}" , err) ;
543553 continue ;
544554 }
@@ -716,25 +726,28 @@ impl<'a> CrateLocator<'a> {
716726fn get_metadata_section (
717727 target : & Target ,
718728 flavor : CrateFlavor ,
719- filename : & Path ,
729+ filename : & ' p Path ,
720730 loader : & dyn MetadataLoader ,
721- ) -> Result < MetadataBlob , String > {
731+ ) -> Result < MetadataBlob , MetadataError < ' p > > {
722732 if !filename. exists ( ) {
723- return Err ( format ! ( "no such file: '{}'" , filename . display ( ) ) ) ;
733+ return Err ( MetadataError :: NotPresent ( filename ) ) ;
724734 }
725735 let raw_bytes: MetadataRef = match flavor {
726- CrateFlavor :: Rlib => loader. get_rlib_metadata ( target, filename) ?,
736+ CrateFlavor :: Rlib => {
737+ loader. get_rlib_metadata ( target, filename) . map_err ( MetadataError :: LoadFailure ) ?
738+ }
727739 CrateFlavor :: Dylib => {
728- let buf = loader. get_dylib_metadata ( target, filename) ?;
740+ let buf =
741+ loader. get_dylib_metadata ( target, filename) . map_err ( MetadataError :: LoadFailure ) ?;
729742 // The header is uncompressed
730743 let header_len = METADATA_HEADER . len ( ) ;
731744 debug ! ( "checking {} bytes of metadata-version stamp" , header_len) ;
732745 let header = & buf[ ..cmp:: min ( header_len, buf. len ( ) ) ] ;
733746 if header != METADATA_HEADER {
734- return Err ( format ! (
735- "incompatible metadata version found: '{}' " ,
747+ return Err ( MetadataError :: LoadFailure ( format ! (
748+ "invalid metadata version found: {} " ,
736749 filename. display( )
737- ) ) ;
750+ ) ) ) ;
738751 }
739752
740753 // Header is okay -> inflate the actual metadata
@@ -744,17 +757,28 @@ fn get_metadata_section(
744757 match FrameDecoder :: new ( compressed_bytes) . read_to_end ( & mut inflated) {
745758 Ok ( _) => rustc_erase_owner ! ( OwningRef :: new( inflated) . map_owner_box( ) ) ,
746759 Err ( _) => {
747- return Err ( format ! ( "failed to decompress metadata: {}" , filename. display( ) ) ) ;
760+ return Err ( MetadataError :: LoadFailure ( format ! (
761+ "failed to decompress metadata: {}" ,
762+ filename. display( )
763+ ) ) ) ;
748764 }
749765 }
750766 }
751767 CrateFlavor :: Rmeta => {
752768 // mmap the file, because only a small fraction of it is read.
753- let file = std:: fs:: File :: open ( filename)
754- . map_err ( |_| format ! ( "failed to open rmeta metadata: '{}'" , filename. display( ) ) ) ?;
769+ let file = std:: fs:: File :: open ( filename) . map_err ( |_| {
770+ MetadataError :: LoadFailure ( format ! (
771+ "failed to open rmeta metadata: '{}'" ,
772+ filename. display( )
773+ ) )
774+ } ) ?;
755775 let mmap = unsafe { Mmap :: map ( file) } ;
756- let mmap = mmap
757- . map_err ( |_| format ! ( "failed to mmap rmeta metadata: '{}'" , filename. display( ) ) ) ?;
776+ let mmap = mmap. map_err ( |_| {
777+ MetadataError :: LoadFailure ( format ! (
778+ "failed to mmap rmeta metadata: '{}'" ,
779+ filename. display( )
780+ ) )
781+ } ) ?;
758782
759783 rustc_erase_owner ! ( OwningRef :: new( mmap) . map_owner_box( ) )
760784 }
@@ -763,7 +787,10 @@ fn get_metadata_section(
763787 if blob. is_compatible ( ) {
764788 Ok ( blob)
765789 } else {
766- Err ( format ! ( "incompatible metadata version found: '{}'" , filename. display( ) ) )
790+ Err ( MetadataError :: LoadFailure ( format ! (
791+ "invalid metadata version found: {}" ,
792+ filename. display( )
793+ ) ) )
767794 }
768795}
769796
@@ -842,6 +869,7 @@ struct CrateRejections {
842869 via_kind : Vec < CrateMismatch > ,
843870 via_version : Vec < CrateMismatch > ,
844871 via_filename : Vec < CrateMismatch > ,
872+ via_invalid : Vec < CrateMismatch > ,
845873}
846874
847875/// Candidate rejection reasons collected during crate search.
@@ -871,6 +899,24 @@ crate enum CrateError {
871899 NonDylibPlugin ( Symbol ) ,
872900}
873901
902+ enum MetadataError < ' a > {
903+ /// The file was missing.
904+ NotPresent ( & ' a Path ) ,
905+ /// The file was present and invalid.
906+ LoadFailure ( String ) ,
907+ }
908+
909+ impl fmt:: Display for MetadataError < ' _ > {
910+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
911+ match self {
912+ MetadataError :: NotPresent ( filename) => {
913+ f. write_str ( & format ! ( "no such file: '{}'" , filename. display( ) ) )
914+ }
915+ MetadataError :: LoadFailure ( msg) => f. write_str ( msg) ,
916+ }
917+ }
918+ }
919+
874920impl CrateError {
875921 crate fn report ( self , sess : & Session , span : Span , missing_core : bool ) -> ! {
876922 let mut err = match self {
@@ -1044,6 +1090,19 @@ impl CrateError {
10441090 }
10451091 err. note ( & msg) ;
10461092 err
1093+ } else if !locator. crate_rejections . via_invalid . is_empty ( ) {
1094+ let mut err = struct_span_err ! (
1095+ sess,
1096+ span,
1097+ E0786 ,
1098+ "found invalid metadata files for crate `{}`{}" ,
1099+ crate_name,
1100+ add,
1101+ ) ;
1102+ for CrateMismatch { path : _, got } in locator. crate_rejections . via_invalid {
1103+ err. note ( & got) ;
1104+ }
1105+ err
10471106 } else {
10481107 let mut err = struct_span_err ! (
10491108 sess,
0 commit comments