12
12
13
13
//! Validates all used crates and extern libraries and loads their metadata
14
14
15
- use common:: rustc_version;
16
15
use cstore:: { self , CStore , CrateSource , MetadataBlob } ;
17
16
use decoder;
18
17
use loader:: { self , CratePaths } ;
@@ -24,7 +23,7 @@ use rustc::session::{config, Session};
24
23
use rustc:: session:: config:: PanicStrategy ;
25
24
use rustc:: session:: search_paths:: PathKind ;
26
25
use rustc:: middle:: cstore:: { CrateStore , validate_crate_name, ExternCrate } ;
27
- use rustc:: util:: nodemap:: FnvHashMap ;
26
+ use rustc:: util:: nodemap:: { FnvHashMap , FnvHashSet } ;
28
27
use rustc:: hir:: map as hir_map;
29
28
30
29
use std:: cell:: { RefCell , Cell } ;
@@ -132,7 +131,7 @@ struct ExtensionCrate {
132
131
}
133
132
134
133
enum PMDSource {
135
- Registered ( Rc < cstore:: crate_metadata > ) ,
134
+ Registered ( Rc < cstore:: CrateMetadata > ) ,
136
135
Owned ( MetadataBlob ) ,
137
136
}
138
137
@@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
236
235
return ret;
237
236
}
238
237
239
- fn verify_rustc_version ( & self ,
240
- name : & str ,
241
- span : Span ,
242
- metadata : & MetadataBlob ) {
243
- let crate_rustc_version = decoder:: crate_rustc_version ( metadata. as_slice ( ) ) ;
244
- if crate_rustc_version != Some ( rustc_version ( ) ) {
245
- let mut err = struct_span_fatal ! ( self . sess, span, E0514 ,
246
- "the crate `{}` has been compiled with {}, which is \
247
- incompatible with this version of rustc",
248
- name,
249
- crate_rustc_version
250
- . as_ref( ) . map( |s| & * * s)
251
- . unwrap_or( "an old version of rustc" ) ) ;
252
- err. help ( "consider removing the compiled binaries and recompiling \
253
- with your current version of rustc") ;
254
- err. emit ( ) ;
255
- }
256
- }
257
-
258
238
fn verify_no_symbol_conflicts ( & self ,
259
239
span : Span ,
260
240
metadata : & MetadataBlob ) {
@@ -294,9 +274,8 @@ impl<'a> CrateReader<'a> {
294
274
span : Span ,
295
275
lib : loader:: Library ,
296
276
explicitly_linked : bool )
297
- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > ,
277
+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > ,
298
278
cstore:: CrateSource ) {
299
- self . verify_rustc_version ( name, span, & lib. metadata ) ;
300
279
self . verify_no_symbol_conflicts ( span, & lib. metadata ) ;
301
280
302
281
// Claim this crate number and cache it
@@ -318,10 +297,10 @@ impl<'a> CrateReader<'a> {
318
297
319
298
let loader:: Library { dylib, rlib, metadata } = lib;
320
299
321
- let cnum_map = self . resolve_crate_deps ( root, metadata. as_slice ( ) , span) ;
300
+ let cnum_map = self . resolve_crate_deps ( root, metadata. as_slice ( ) , cnum , span) ;
322
301
let staged_api = self . is_staged_api ( metadata. as_slice ( ) ) ;
323
302
324
- let cmeta = Rc :: new ( cstore:: crate_metadata {
303
+ let cmeta = Rc :: new ( cstore:: CrateMetadata {
325
304
name : name. to_string ( ) ,
326
305
extern_crate : Cell :: new ( None ) ,
327
306
index : decoder:: load_index ( metadata. as_slice ( ) ) ,
@@ -364,7 +343,7 @@ impl<'a> CrateReader<'a> {
364
343
span : Span ,
365
344
kind : PathKind ,
366
345
explicitly_linked : bool )
367
- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > , cstore:: CrateSource ) {
346
+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > , cstore:: CrateSource ) {
368
347
let result = match self . existing_match ( name, hash, kind) {
369
348
Some ( cnum) => LoadResult :: Previous ( cnum) ,
370
349
None => {
@@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
381
360
rejected_via_hash : vec ! ( ) ,
382
361
rejected_via_triple : vec ! ( ) ,
383
362
rejected_via_kind : vec ! ( ) ,
363
+ rejected_via_version : vec ! ( ) ,
384
364
should_match_name : true ,
385
365
} ;
386
366
match self . load ( & mut load_ctxt) {
@@ -438,8 +418,11 @@ impl<'a> CrateReader<'a> {
438
418
439
419
fn update_extern_crate ( & mut self ,
440
420
cnum : ast:: CrateNum ,
441
- mut extern_crate : ExternCrate )
421
+ mut extern_crate : ExternCrate ,
422
+ visited : & mut FnvHashSet < ( ast:: CrateNum , bool ) > )
442
423
{
424
+ if !visited. insert ( ( cnum, extern_crate. direct ) ) { return }
425
+
443
426
let cmeta = self . cstore . get_crate_data ( cnum) ;
444
427
let old_extern_crate = cmeta. extern_crate . get ( ) ;
445
428
@@ -458,24 +441,24 @@ impl<'a> CrateReader<'a> {
458
441
}
459
442
460
443
cmeta. extern_crate . set ( Some ( extern_crate) ) ;
461
-
462
444
// Propagate the extern crate info to dependencies.
463
445
extern_crate. direct = false ;
464
- for & dep_cnum in cmeta. cnum_map . borrow ( ) . values ( ) {
465
- self . update_extern_crate ( dep_cnum, extern_crate) ;
446
+ for & dep_cnum in cmeta. cnum_map . borrow ( ) . iter ( ) {
447
+ self . update_extern_crate ( dep_cnum, extern_crate, visited ) ;
466
448
}
467
449
}
468
450
469
451
// Go through the crate metadata and load any crates that it references
470
452
fn resolve_crate_deps ( & mut self ,
471
453
root : & Option < CratePaths > ,
472
454
cdata : & [ u8 ] ,
473
- span : Span )
474
- -> cstore:: cnum_map {
455
+ krate : ast:: CrateNum ,
456
+ span : Span )
457
+ -> cstore:: CrateNumMap {
475
458
debug ! ( "resolving deps of external crate" ) ;
476
459
// The map from crate numbers in the crate we're resolving to local crate
477
460
// numbers
478
- decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
461
+ let map : FnvHashMap < _ , _ > = decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
479
462
debug ! ( "resolving dep crate {} hash: `{}`" , dep. name, dep. hash) ;
480
463
let ( local_cnum, _, _) = self . resolve_crate ( root,
481
464
& dep. name ,
@@ -485,7 +468,13 @@ impl<'a> CrateReader<'a> {
485
468
PathKind :: Dependency ,
486
469
dep. explicitly_linked ) ;
487
470
( dep. cnum , local_cnum)
488
- } ) . collect ( )
471
+ } ) . collect ( ) ;
472
+
473
+ let max_cnum = map. values ( ) . cloned ( ) . max ( ) . unwrap_or ( 0 ) ;
474
+
475
+ // we map 0 and all other holes in the map to our parent crate. The "additional"
476
+ // self-dependencies should be harmless.
477
+ ( 0 ..max_cnum+1 ) . map ( |cnum| map. get ( & cnum) . cloned ( ) . unwrap_or ( krate) ) . collect ( )
489
478
}
490
479
491
480
fn read_extension_crate ( & mut self , span : Span , info : & CrateInfo ) -> ExtensionCrate {
@@ -508,6 +497,7 @@ impl<'a> CrateReader<'a> {
508
497
rejected_via_hash : vec ! ( ) ,
509
498
rejected_via_triple : vec ! ( ) ,
510
499
rejected_via_kind : vec ! ( ) ,
500
+ rejected_via_version : vec ! ( ) ,
511
501
should_match_name : true ,
512
502
} ;
513
503
let library = self . load ( & mut load_ctxt) . or_else ( || {
@@ -826,7 +816,7 @@ impl<'a> CrateReader<'a> {
826
816
fn inject_dependency_if ( & self ,
827
817
krate : ast:: CrateNum ,
828
818
what : & str ,
829
- needs_dep : & Fn ( & cstore:: crate_metadata ) -> bool ) {
819
+ needs_dep : & Fn ( & cstore:: CrateMetadata ) -> bool ) {
830
820
// don't perform this validation if the session has errors, as one of
831
821
// those errors may indicate a circular dependency which could cause
832
822
// this to stack overflow.
@@ -837,7 +827,17 @@ impl<'a> CrateReader<'a> {
837
827
// Before we inject any dependencies, make sure we don't inject a
838
828
// circular dependency by validating that this crate doesn't
839
829
// transitively depend on any crates satisfying `needs_dep`.
840
- validate ( self , krate, krate, what, needs_dep) ;
830
+ for dep in self . cstore . crate_dependencies_in_rpo ( krate) {
831
+ let data = self . cstore . get_crate_data ( dep) ;
832
+ if needs_dep ( & data) {
833
+ self . sess . err ( & format ! ( "the crate `{}` cannot depend \
834
+ on a crate that needs {}, but \
835
+ it depends on `{}`",
836
+ self . cstore. get_crate_data( krate) . name( ) ,
837
+ what,
838
+ data. name( ) ) ) ;
839
+ }
840
+ }
841
841
842
842
// All crates satisfying `needs_dep` do not explicitly depend on the
843
843
// crate provided for this compile, but in order for this compilation to
@@ -849,32 +849,8 @@ impl<'a> CrateReader<'a> {
849
849
}
850
850
851
851
info ! ( "injecting a dep from {} to {}" , cnum, krate) ;
852
- let mut cnum_map = data. cnum_map . borrow_mut ( ) ;
853
- let remote_cnum = cnum_map. len ( ) + 1 ;
854
- let prev = cnum_map. insert ( remote_cnum as ast:: CrateNum , krate) ;
855
- assert ! ( prev. is_none( ) ) ;
852
+ data. cnum_map . borrow_mut ( ) . push ( krate) ;
856
853
} ) ;
857
-
858
- fn validate ( me : & CrateReader ,
859
- krate : ast:: CrateNum ,
860
- root : ast:: CrateNum ,
861
- what : & str ,
862
- needs_dep : & Fn ( & cstore:: crate_metadata ) -> bool ) {
863
- let data = me. cstore . get_crate_data ( krate) ;
864
- if needs_dep ( & data) {
865
- let krate_name = data. name ( ) ;
866
- let data = me. cstore . get_crate_data ( root) ;
867
- let root_name = data. name ( ) ;
868
- me. sess . err ( & format ! ( "the crate `{}` cannot depend \
869
- on a crate that needs {}, but \
870
- it depends on `{}`", root_name, what,
871
- krate_name) ) ;
872
- }
873
-
874
- for ( _, & dep) in data. cnum_map . borrow ( ) . iter ( ) {
875
- validate ( me, dep, root, what, needs_dep) ;
876
- }
877
- }
878
854
}
879
855
}
880
856
@@ -948,7 +924,8 @@ impl<'a> LocalCrateReader<'a> {
948
924
span : i. span ,
949
925
direct : true ,
950
926
path_len : len,
951
- } ) ;
927
+ } ,
928
+ & mut FnvHashSet ( ) ) ;
952
929
self . cstore . add_extern_mod_stmt_cnum ( info. id , cnum) ;
953
930
}
954
931
}
0 commit comments