@@ -350,6 +350,7 @@ impl<'a> CrateLocator<'a> {
350
350
self . crate_rejections . via_kind . clear ( ) ;
351
351
self . crate_rejections . via_version . clear ( ) ;
352
352
self . crate_rejections . via_filename . clear ( ) ;
353
+ self . crate_rejections . via_invalid . clear ( ) ;
353
354
}
354
355
355
356
crate fn maybe_load_library_crate ( & mut self ) -> Result < Option < Library > , CrateError > {
@@ -548,7 +549,17 @@ impl<'a> CrateLocator<'a> {
548
549
continue ;
549
550
}
550
551
}
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 ( _) ) => {
552
563
info ! ( "no metadata found: {}" , err) ;
553
564
continue ;
554
565
}
@@ -726,25 +737,28 @@ impl<'a> CrateLocator<'a> {
726
737
fn get_metadata_section (
727
738
target : & Target ,
728
739
flavor : CrateFlavor ,
729
- filename : & Path ,
740
+ filename : & ' p Path ,
730
741
loader : & dyn MetadataLoader ,
731
- ) -> Result < MetadataBlob , String > {
742
+ ) -> Result < MetadataBlob , MetadataError < ' p > > {
732
743
if !filename. exists ( ) {
733
- return Err ( format ! ( "no such file: '{}'" , filename . display ( ) ) ) ;
744
+ return Err ( MetadataError :: NotPresent ( filename ) ) ;
734
745
}
735
746
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
+ }
737
750
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 ) ?;
739
753
// The header is uncompressed
740
754
let header_len = METADATA_HEADER . len ( ) ;
741
755
debug ! ( "checking {} bytes of metadata-version stamp" , header_len) ;
742
756
let header = & buf[ ..cmp:: min ( header_len, buf. len ( ) ) ] ;
743
757
if header != METADATA_HEADER {
744
- return Err ( format ! (
745
- "incompatible metadata version found: '{}' " ,
758
+ return Err ( MetadataError :: LoadFailure ( format ! (
759
+ "invalid metadata version found: {} " ,
746
760
filename. display( )
747
- ) ) ;
761
+ ) ) ) ;
748
762
}
749
763
750
764
// Header is okay -> inflate the actual metadata
@@ -756,17 +770,28 @@ fn get_metadata_section(
756
770
match FrameDecoder :: new ( compressed_bytes) . read_to_end ( & mut inflated) {
757
771
Ok ( _) => rustc_erase_owner ! ( OwningRef :: new( inflated) . map_owner_box( ) ) ,
758
772
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
+ ) ) ) ;
760
777
}
761
778
}
762
779
}
763
780
CrateFlavor :: Rmeta => {
764
781
// 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
+ } ) ?;
767
788
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
+ } ) ?;
770
795
771
796
rustc_erase_owner ! ( OwningRef :: new( mmap) . map_owner_box( ) )
772
797
}
@@ -775,7 +800,10 @@ fn get_metadata_section(
775
800
if blob. is_compatible ( ) {
776
801
Ok ( blob)
777
802
} else {
778
- Err ( format ! ( "incompatible metadata version found: '{}'" , filename. display( ) ) )
803
+ Err ( MetadataError :: LoadFailure ( format ! (
804
+ "invalid metadata version found: {}" ,
805
+ filename. display( )
806
+ ) ) )
779
807
}
780
808
}
781
809
@@ -854,6 +882,7 @@ struct CrateRejections {
854
882
via_kind : Vec < CrateMismatch > ,
855
883
via_version : Vec < CrateMismatch > ,
856
884
via_filename : Vec < CrateMismatch > ,
885
+ via_invalid : Vec < CrateMismatch > ,
857
886
}
858
887
859
888
/// Candidate rejection reasons collected during crate search.
@@ -883,6 +912,24 @@ crate enum CrateError {
883
912
NonDylibPlugin ( Symbol ) ,
884
913
}
885
914
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
+
886
933
impl CrateError {
887
934
crate fn report ( self , sess : & Session , span : Span , missing_core : bool ) -> ! {
888
935
let mut err = match self {
@@ -1064,6 +1111,19 @@ impl CrateError {
1064
1111
}
1065
1112
err. note ( & msg) ;
1066
1113
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
1067
1127
} else {
1068
1128
let mut err = struct_span_err ! (
1069
1129
sess,
0 commit comments