213
213
//! metadata::loader or metadata::creader for all the juicy details!
214
214
215
215
use cstore:: { MetadataBlob , MetadataVec , MetadataArchive } ;
216
+ use common:: { metadata_encoding_version, rustc_version} ;
216
217
use decoder;
217
- use encoder;
218
218
219
219
use rustc:: hir:: svh:: Svh ;
220
220
use rustc:: session:: Session ;
@@ -260,6 +260,7 @@ pub struct Context<'a> {
260
260
pub rejected_via_hash : Vec < CrateMismatch > ,
261
261
pub rejected_via_triple : Vec < CrateMismatch > ,
262
262
pub rejected_via_kind : Vec < CrateMismatch > ,
263
+ pub rejected_via_version : Vec < CrateMismatch > ,
263
264
pub should_match_name : bool ,
264
265
}
265
266
@@ -336,6 +337,10 @@ impl<'a> Context<'a> {
336
337
struct_span_err ! ( self . sess, self . span, E0462 ,
337
338
"found staticlib `{}` instead of rlib or dylib{}" ,
338
339
self . ident, add)
340
+ } else if !self . rejected_via_version . is_empty ( ) {
341
+ struct_span_err ! ( self . sess, self . span, E0514 ,
342
+ "found crate `{}` compiled by an incompatible version of rustc{}" ,
343
+ self . ident, add)
339
344
} else {
340
345
struct_span_err ! ( self . sess, self . span, E0463 ,
341
346
"can't find crate for `{}`{}" ,
@@ -350,7 +355,7 @@ impl<'a> Context<'a> {
350
355
}
351
356
}
352
357
if !self . rejected_via_hash . is_empty ( ) {
353
- err. note ( "perhaps this crate needs to be recompiled?" ) ;
358
+ err. note ( "perhaps that crate needs to be recompiled?" ) ;
354
359
let mismatches = self . rejected_via_hash . iter ( ) ;
355
360
for ( i, & CrateMismatch { ref path, .. } ) in mismatches. enumerate ( ) {
356
361
err. note ( & format ! ( "crate `{}` path #{}: {}" ,
@@ -367,13 +372,22 @@ impl<'a> Context<'a> {
367
372
}
368
373
}
369
374
if !self . rejected_via_kind . is_empty ( ) {
370
- err. help ( "please recompile this crate using --crate-type lib" ) ;
375
+ err. help ( "please recompile that crate using --crate-type lib" ) ;
371
376
let mismatches = self . rejected_via_kind . iter ( ) ;
372
377
for ( i, & CrateMismatch { ref path, .. } ) in mismatches. enumerate ( ) {
373
378
err. note ( & format ! ( "crate `{}` path #{}: {}" ,
374
379
self . ident, i+1 , path. display( ) ) ) ;
375
380
}
376
381
}
382
+ if !self . rejected_via_version . is_empty ( ) {
383
+ err. help ( & format ! ( "please recompile that crate using this compiler ({})" ,
384
+ rustc_version( ) ) ) ;
385
+ let mismatches = self . rejected_via_version . iter ( ) ;
386
+ for ( i, & CrateMismatch { ref path, ref got } ) in mismatches. enumerate ( ) {
387
+ err. note ( & format ! ( "crate `{}` path #{}: {} compiled by {:?}" ,
388
+ self . ident, i+1 , path. display( ) , got) ) ;
389
+ }
390
+ }
377
391
378
392
err. emit ( ) ;
379
393
self . sess . abort_if_errors ( ) ;
@@ -591,6 +605,17 @@ impl<'a> Context<'a> {
591
605
}
592
606
593
607
fn crate_matches ( & mut self , crate_data : & [ u8 ] , libpath : & Path ) -> Option < Svh > {
608
+ let crate_rustc_version = decoder:: crate_rustc_version ( crate_data) ;
609
+ if crate_rustc_version != Some ( rustc_version ( ) ) {
610
+ let message = crate_rustc_version. unwrap_or ( format ! ( "an unknown compiler" ) ) ;
611
+ info ! ( "Rejecting via version: expected {} got {}" , rustc_version( ) , message) ;
612
+ self . rejected_via_version . push ( CrateMismatch {
613
+ path : libpath. to_path_buf ( ) ,
614
+ got : message
615
+ } ) ;
616
+ return None ;
617
+ }
618
+
594
619
if self . should_match_name {
595
620
match decoder:: maybe_get_crate_name ( crate_data) {
596
621
Some ( ref name) if self . crate_name == * name => { }
@@ -742,6 +767,21 @@ impl ArchiveMetadata {
742
767
pub fn as_slice < ' a > ( & ' a self ) -> & ' a [ u8 ] { unsafe { & * self . data } }
743
768
}
744
769
770
+ fn verify_decompressed_encoding_version ( blob : & MetadataBlob , filename : & Path )
771
+ -> Result < ( ) , String >
772
+ {
773
+ let data = blob. as_slice_raw ( ) ;
774
+ if data. len ( ) < 4 +metadata_encoding_version. len ( ) ||
775
+ !<[ u8 ] >:: eq ( & data[ ..4 ] , & [ 0 , 0 , 0 , 0 ] ) ||
776
+ & data[ 4 ..4 +metadata_encoding_version. len ( ) ] != metadata_encoding_version
777
+ {
778
+ Err ( ( format ! ( "incompatible metadata version found: '{}'" ,
779
+ filename. display( ) ) ) )
780
+ } else {
781
+ Ok ( ( ) )
782
+ }
783
+ }
784
+
745
785
// Just a small wrapper to time how long reading metadata takes.
746
786
fn get_metadata_section ( target : & Target , flavor : CrateFlavor , filename : & Path )
747
787
-> Result < MetadataBlob , String > {
@@ -772,7 +812,10 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
772
812
return match ArchiveMetadata :: new ( archive) . map ( |ar| MetadataArchive ( ar) ) {
773
813
None => Err ( format ! ( "failed to read rlib metadata: '{}'" ,
774
814
filename. display( ) ) ) ,
775
- Some ( blob) => Ok ( blob)
815
+ Some ( blob) => {
816
+ try!( verify_decompressed_encoding_version ( & blob, filename) ) ;
817
+ Ok ( blob)
818
+ }
776
819
} ;
777
820
}
778
821
unsafe {
@@ -801,12 +844,12 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
801
844
let cbuf = llvm:: LLVMGetSectionContents ( si. llsi ) ;
802
845
let csz = llvm:: LLVMGetSectionSize ( si. llsi ) as usize ;
803
846
let cvbuf: * const u8 = cbuf as * const u8 ;
804
- let vlen = encoder :: metadata_encoding_version. len ( ) ;
847
+ let vlen = metadata_encoding_version. len ( ) ;
805
848
debug ! ( "checking {} bytes of metadata-version stamp" ,
806
849
vlen) ;
807
850
let minsz = cmp:: min ( vlen, csz) ;
808
851
let buf0 = slice:: from_raw_parts ( cvbuf, minsz) ;
809
- let version_ok = buf0 == encoder :: metadata_encoding_version;
852
+ let version_ok = buf0 == metadata_encoding_version;
810
853
if !version_ok {
811
854
return Err ( ( format ! ( "incompatible metadata version found: '{}'" ,
812
855
filename. display( ) ) ) ) ;
@@ -817,7 +860,11 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
817
860
csz - vlen) ;
818
861
let bytes = slice:: from_raw_parts ( cvbuf1, csz - vlen) ;
819
862
match flate:: inflate_bytes ( bytes) {
820
- Ok ( inflated) => return Ok ( MetadataVec ( inflated) ) ,
863
+ Ok ( inflated) => {
864
+ let blob = MetadataVec ( inflated) ;
865
+ try!( verify_decompressed_encoding_version ( & blob, filename) ) ;
866
+ return Ok ( blob) ;
867
+ }
821
868
Err ( _) => { }
822
869
}
823
870
}
0 commit comments