@@ -243,7 +243,6 @@ use std::{cmp, fmt};
243
243
pub ( crate ) struct CrateLocator < ' a > {
244
244
// Immutable per-session configuration.
245
245
only_needs_metadata : bool ,
246
- sysroot : & ' a Path ,
247
246
metadata_loader : & ' a dyn MetadataLoader ,
248
247
cfg_version : & ' static str ,
249
248
@@ -319,7 +318,6 @@ impl<'a> CrateLocator<'a> {
319
318
320
319
CrateLocator {
321
320
only_needs_metadata,
322
- sysroot : & sess. sysroot ,
323
321
metadata_loader,
324
322
cfg_version : sess. cfg_version ,
325
323
crate_name,
@@ -569,31 +567,47 @@ impl<'a> CrateLocator<'a> {
569
567
debug ! ( "skipping empty file" ) ;
570
568
continue ;
571
569
}
572
- let ( hash, metadata) =
573
- match get_metadata_section ( self . target , flavor, & lib, self . metadata_loader ) {
574
- Ok ( blob) => {
575
- if let Some ( h) = self . crate_matches ( & blob, & lib) {
576
- ( h, blob)
577
- } else {
578
- info ! ( "metadata mismatch" ) ;
579
- continue ;
580
- }
581
- }
582
- Err ( MetadataError :: LoadFailure ( err) ) => {
583
- info ! ( "no metadata found: {}" , err) ;
584
- // The file was present and created by the same compiler version, but we
585
- // couldn't load it for some reason. Give a hard error instead of silently
586
- // ignoring it, but only if we would have given an error anyway.
587
- self . crate_rejections
588
- . via_invalid
589
- . push ( CrateMismatch { path : lib, got : err } ) ;
590
- continue ;
591
- }
592
- Err ( err @ MetadataError :: NotPresent ( _) ) => {
593
- info ! ( "no metadata found: {}" , err) ;
570
+ let ( hash, metadata) = match get_metadata_section (
571
+ self . target ,
572
+ flavor,
573
+ & lib,
574
+ self . metadata_loader ,
575
+ self . cfg_version ,
576
+ ) {
577
+ Ok ( blob) => {
578
+ if let Some ( h) = self . crate_matches ( & blob, & lib) {
579
+ ( h, blob)
580
+ } else {
581
+ info ! ( "metadata mismatch" ) ;
594
582
continue ;
595
583
}
596
- } ;
584
+ }
585
+ Err ( MetadataError :: VersionMismatch { expected_version, found_version } ) => {
586
+ // The file was present and created by the same compiler version, but we
587
+ // couldn't load it for some reason. Give a hard error instead of silently
588
+ // ignoring it, but only if we would have given an error anyway.
589
+ info ! (
590
+ "Rejecting via version: expected {} got {}" ,
591
+ expected_version, found_version
592
+ ) ;
593
+ self . crate_rejections
594
+ . via_version
595
+ . push ( CrateMismatch { path : lib, got : found_version } ) ;
596
+ continue ;
597
+ }
598
+ Err ( MetadataError :: LoadFailure ( err) ) => {
599
+ info ! ( "no metadata found: {}" , err) ;
600
+ // The file was present and created by the same compiler version, but we
601
+ // couldn't load it for some reason. Give a hard error instead of silently
602
+ // ignoring it, but only if we would have given an error anyway.
603
+ self . crate_rejections . via_invalid . push ( CrateMismatch { path : lib, got : err } ) ;
604
+ continue ;
605
+ }
606
+ Err ( err @ MetadataError :: NotPresent ( _) ) => {
607
+ info ! ( "no metadata found: {}" , err) ;
608
+ continue ;
609
+ }
610
+ } ;
597
611
// If we see multiple hashes, emit an error about duplicate candidates.
598
612
if slot. as_ref ( ) . is_some_and ( |s| s. 0 != hash) {
599
613
if let Some ( candidates) = err_data {
@@ -610,33 +624,11 @@ impl<'a> CrateLocator<'a> {
610
624
continue ;
611
625
}
612
626
613
- // Ok so at this point we've determined that `(lib, kind)` above is
614
- // a candidate crate to load, and that `slot` is either none (this
615
- // is the first crate of its kind) or if some the previous path has
616
- // the exact same hash (e.g., it's the exact same crate).
617
- //
618
- // In principle these two candidate crates are exactly the same so
619
- // we can choose either of them to link. As a stupidly gross hack,
620
- // however, we favor crate in the sysroot.
621
- //
622
- // You can find more info in rust-lang/rust#39518 and various linked
623
- // issues, but the general gist is that during testing libstd the
624
- // compilers has two candidates to choose from: one in the sysroot
625
- // and one in the deps folder. These two crates are the exact same
626
- // crate but if the compiler chooses the one in the deps folder
627
- // it'll cause spurious errors on Windows.
628
- //
629
- // As a result, we favor the sysroot crate here. Note that the
630
- // candidates are all canonicalized, so we canonicalize the sysroot
631
- // as well.
632
- if let Some ( ( prev, _) ) = & ret {
633
- let sysroot = self . sysroot ;
634
- let sysroot = try_canonicalize ( sysroot) . unwrap_or_else ( |_| sysroot. to_path_buf ( ) ) ;
635
- if prev. starts_with ( & sysroot) {
636
- continue ;
637
- }
627
+ if !metadata. get_header ( ) . is_reference {
628
+ // FIXME nicer error when only an rlib or dylib with is_reference is found
629
+ // and no .rmeta?
630
+ * slot = Some ( ( hash, metadata, lib. clone ( ) ) ) ;
638
631
}
639
- * slot = Some ( ( hash, metadata, lib. clone ( ) ) ) ;
640
632
ret = Some ( ( lib, kind) ) ;
641
633
}
642
634
@@ -648,16 +640,6 @@ impl<'a> CrateLocator<'a> {
648
640
}
649
641
650
642
fn crate_matches ( & mut self , metadata : & MetadataBlob , libpath : & Path ) -> Option < Svh > {
651
- let rustc_version = rustc_version ( self . cfg_version ) ;
652
- let found_version = metadata. get_rustc_version ( ) ;
653
- if found_version != rustc_version {
654
- info ! ( "Rejecting via version: expected {} got {}" , rustc_version, found_version) ;
655
- self . crate_rejections
656
- . via_version
657
- . push ( CrateMismatch { path : libpath. to_path_buf ( ) , got : found_version } ) ;
658
- return None ;
659
- }
660
-
661
643
let header = metadata. get_header ( ) ;
662
644
if header. is_proc_macro_crate != self . is_proc_macro {
663
645
info ! (
@@ -736,10 +718,12 @@ impl<'a> CrateLocator<'a> {
736
718
let loc_canon = loc. canonicalized ( ) . clone ( ) ;
737
719
let loc = loc. original ( ) ;
738
720
if loc. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".rlib" ) {
721
+ rmetas. insert ( loc_canon. with_extension ( "rmeta" ) , PathKind :: ExternFlag ) ;
739
722
rlibs. insert ( loc_canon, PathKind :: ExternFlag ) ;
740
723
} else if loc. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".rmeta" ) {
741
724
rmetas. insert ( loc_canon, PathKind :: ExternFlag ) ;
742
725
} else {
726
+ rmetas. insert ( loc_canon. with_extension ( "rmeta" ) , PathKind :: ExternFlag ) ;
743
727
dylibs. insert ( loc_canon, PathKind :: ExternFlag ) ;
744
728
}
745
729
} else {
@@ -770,6 +754,7 @@ fn get_metadata_section<'p>(
770
754
flavor : CrateFlavor ,
771
755
filename : & ' p Path ,
772
756
loader : & dyn MetadataLoader ,
757
+ cfg_version : & ' static str ,
773
758
) -> Result < MetadataBlob , MetadataError < ' p > > {
774
759
if !filename. exists ( ) {
775
760
return Err ( MetadataError :: NotPresent ( filename) ) ;
@@ -847,13 +832,12 @@ fn get_metadata_section<'p>(
847
832
}
848
833
} ;
849
834
let blob = MetadataBlob ( raw_bytes) ;
850
- if blob. is_compatible ( ) {
851
- Ok ( blob)
852
- } else {
853
- Err ( MetadataError :: LoadFailure ( format ! (
854
- "invalid metadata version found: {}" ,
855
- filename. display( )
856
- ) ) )
835
+ match blob. check_compatibility ( cfg_version) {
836
+ Ok ( ( ) ) => Ok ( blob) ,
837
+ Err ( version) => Err ( MetadataError :: VersionMismatch {
838
+ expected_version : cfg_version,
839
+ found_version : version,
840
+ } ) ,
857
841
}
858
842
}
859
843
@@ -864,9 +848,10 @@ pub fn list_file_metadata(
864
848
metadata_loader : & dyn MetadataLoader ,
865
849
out : & mut dyn Write ,
866
850
ls_kinds : & [ String ] ,
851
+ cfg_version : & ' static str ,
867
852
) -> IoResult < ( ) > {
868
853
let flavor = get_flavor_from_path ( path) ;
869
- match get_metadata_section ( target, flavor, path, metadata_loader) {
854
+ match get_metadata_section ( target, flavor, path, metadata_loader, cfg_version ) {
870
855
Ok ( metadata) => metadata. list_crate_metadata ( out, ls_kinds) ,
871
856
Err ( msg) => write ! ( out, "{msg}\n " ) ,
872
857
}
@@ -932,6 +917,8 @@ enum MetadataError<'a> {
932
917
NotPresent ( & ' a Path ) ,
933
918
/// The file was present and invalid.
934
919
LoadFailure ( String ) ,
920
+ /// The file was present, but compiled with a different rustc version.
921
+ VersionMismatch { expected_version : & ' static str , found_version : String } ,
935
922
}
936
923
937
924
impl fmt:: Display for MetadataError < ' _ > {
@@ -941,6 +928,12 @@ impl fmt::Display for MetadataError<'_> {
941
928
f. write_str ( & format ! ( "no such file: '{}'" , filename. display( ) ) )
942
929
}
943
930
MetadataError :: LoadFailure ( msg) => f. write_str ( msg) ,
931
+ MetadataError :: VersionMismatch { expected_version, found_version } => {
932
+ f. write_str ( & format ! (
933
+ "rustc version mismatch. expected {}, found {}" ,
934
+ expected_version, found_version,
935
+ ) )
936
+ }
944
937
}
945
938
}
946
939
}
0 commit comments