@@ -24,7 +24,7 @@ use rustc::session::{config, Session};
24
24
use rustc:: session:: config:: PanicStrategy ;
25
25
use rustc:: session:: search_paths:: PathKind ;
26
26
use rustc:: middle:: cstore:: { CrateStore , validate_crate_name, ExternCrate } ;
27
- use rustc:: util:: nodemap:: FnvHashMap ;
27
+ use rustc:: util:: nodemap:: { FnvHashMap , FnvHashSet } ;
28
28
use rustc:: hir:: map as hir_map;
29
29
30
30
use std:: cell:: { RefCell , Cell } ;
@@ -132,7 +132,7 @@ struct ExtensionCrate {
132
132
}
133
133
134
134
enum PMDSource {
135
- Registered ( Rc < cstore:: crate_metadata > ) ,
135
+ Registered ( Rc < cstore:: CrateMetadata > ) ,
136
136
Owned ( MetadataBlob ) ,
137
137
}
138
138
@@ -294,7 +294,7 @@ impl<'a> CrateReader<'a> {
294
294
span : Span ,
295
295
lib : loader:: Library ,
296
296
explicitly_linked : bool )
297
- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > ,
297
+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > ,
298
298
cstore:: CrateSource ) {
299
299
self . verify_rustc_version ( name, span, & lib. metadata ) ;
300
300
self . verify_no_symbol_conflicts ( span, & lib. metadata ) ;
@@ -318,10 +318,10 @@ impl<'a> CrateReader<'a> {
318
318
319
319
let loader:: Library { dylib, rlib, metadata } = lib;
320
320
321
- let cnum_map = self . resolve_crate_deps ( root, metadata. as_slice ( ) , span) ;
321
+ let cnum_map = self . resolve_crate_deps ( root, metadata. as_slice ( ) , cnum , span) ;
322
322
let staged_api = self . is_staged_api ( metadata. as_slice ( ) ) ;
323
323
324
- let cmeta = Rc :: new ( cstore:: crate_metadata {
324
+ let cmeta = Rc :: new ( cstore:: CrateMetadata {
325
325
name : name. to_string ( ) ,
326
326
extern_crate : Cell :: new ( None ) ,
327
327
index : decoder:: load_index ( metadata. as_slice ( ) ) ,
@@ -364,7 +364,7 @@ impl<'a> CrateReader<'a> {
364
364
span : Span ,
365
365
kind : PathKind ,
366
366
explicitly_linked : bool )
367
- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > , cstore:: CrateSource ) {
367
+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > , cstore:: CrateSource ) {
368
368
let result = match self . existing_match ( name, hash, kind) {
369
369
Some ( cnum) => LoadResult :: Previous ( cnum) ,
370
370
None => {
@@ -438,8 +438,11 @@ impl<'a> CrateReader<'a> {
438
438
439
439
fn update_extern_crate ( & mut self ,
440
440
cnum : ast:: CrateNum ,
441
- mut extern_crate : ExternCrate )
441
+ mut extern_crate : ExternCrate ,
442
+ visited : & mut FnvHashSet < ( ast:: CrateNum , bool ) > )
442
443
{
444
+ if !visited. insert ( ( cnum, extern_crate. direct ) ) { return }
445
+
443
446
let cmeta = self . cstore . get_crate_data ( cnum) ;
444
447
let old_extern_crate = cmeta. extern_crate . get ( ) ;
445
448
@@ -458,24 +461,24 @@ impl<'a> CrateReader<'a> {
458
461
}
459
462
460
463
cmeta. extern_crate . set ( Some ( extern_crate) ) ;
461
-
462
464
// Propagate the extern crate info to dependencies.
463
465
extern_crate. direct = false ;
464
- for & dep_cnum in cmeta. cnum_map . borrow ( ) . values ( ) {
465
- self . update_extern_crate ( dep_cnum, extern_crate) ;
466
+ for & dep_cnum in cmeta. cnum_map . borrow ( ) . iter ( ) {
467
+ self . update_extern_crate ( dep_cnum, extern_crate, visited ) ;
466
468
}
467
469
}
468
470
469
471
// Go through the crate metadata and load any crates that it references
470
472
fn resolve_crate_deps ( & mut self ,
471
473
root : & Option < CratePaths > ,
472
474
cdata : & [ u8 ] ,
473
- span : Span )
474
- -> cstore:: cnum_map {
475
+ krate : ast:: CrateNum ,
476
+ span : Span )
477
+ -> cstore:: CrateNumMap {
475
478
debug ! ( "resolving deps of external crate" ) ;
476
479
// The map from crate numbers in the crate we're resolving to local crate
477
480
// numbers
478
- decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
481
+ let map : FnvHashMap < _ , _ > = decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
479
482
debug ! ( "resolving dep crate {} hash: `{}`" , dep. name, dep. hash) ;
480
483
let ( local_cnum, _, _) = self . resolve_crate ( root,
481
484
& dep. name ,
@@ -485,7 +488,13 @@ impl<'a> CrateReader<'a> {
485
488
PathKind :: Dependency ,
486
489
dep. explicitly_linked ) ;
487
490
( dep. cnum , local_cnum)
488
- } ) . collect ( )
491
+ } ) . collect ( ) ;
492
+
493
+ let max_cnum = map. values ( ) . cloned ( ) . max ( ) . unwrap_or ( 0 ) ;
494
+
495
+ // we map 0 and all other holes in the map to our parent crate. The "additional"
496
+ // self-dependencies should be harmless.
497
+ ( 0 ..max_cnum+1 ) . map ( |cnum| map. get ( & cnum) . cloned ( ) . unwrap_or ( krate) ) . collect ( )
489
498
}
490
499
491
500
fn read_extension_crate ( & mut self , span : Span , info : & CrateInfo ) -> ExtensionCrate {
@@ -826,7 +835,7 @@ impl<'a> CrateReader<'a> {
826
835
fn inject_dependency_if ( & self ,
827
836
krate : ast:: CrateNum ,
828
837
what : & str ,
829
- needs_dep : & Fn ( & cstore:: crate_metadata ) -> bool ) {
838
+ needs_dep : & Fn ( & cstore:: CrateMetadata ) -> bool ) {
830
839
// don't perform this validation if the session has errors, as one of
831
840
// those errors may indicate a circular dependency which could cause
832
841
// this to stack overflow.
@@ -837,7 +846,17 @@ impl<'a> CrateReader<'a> {
837
846
// Before we inject any dependencies, make sure we don't inject a
838
847
// circular dependency by validating that this crate doesn't
839
848
// transitively depend on any crates satisfying `needs_dep`.
840
- validate ( self , krate, krate, what, needs_dep) ;
849
+ for dep in self . cstore . crate_dependencies_in_rpo ( krate) {
850
+ let data = self . cstore . get_crate_data ( dep) ;
851
+ if needs_dep ( & data) {
852
+ self . sess . err ( & format ! ( "the crate `{}` cannot depend \
853
+ on a crate that needs {}, but \
854
+ it depends on `{}`",
855
+ self . cstore. get_crate_data( krate) . name( ) ,
856
+ what,
857
+ data. name( ) ) ) ;
858
+ }
859
+ }
841
860
842
861
// All crates satisfying `needs_dep` do not explicitly depend on the
843
862
// crate provided for this compile, but in order for this compilation to
@@ -849,32 +868,8 @@ impl<'a> CrateReader<'a> {
849
868
}
850
869
851
870
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( ) ) ;
871
+ data. cnum_map . borrow_mut ( ) . push ( krate) ;
856
872
} ) ;
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
873
}
879
874
}
880
875
@@ -948,7 +943,8 @@ impl<'a> LocalCrateReader<'a> {
948
943
span : i. span ,
949
944
direct : true ,
950
945
path_len : len,
951
- } ) ;
946
+ } ,
947
+ & mut FnvHashSet ( ) ) ;
952
948
self . cstore . add_extern_mod_stmt_cnum ( info. id , cnum) ;
953
949
}
954
950
}
0 commit comments