@@ -24,7 +24,7 @@ use rustc::session::{config, Session};
2424use rustc:: session:: config:: PanicStrategy ;
2525use rustc:: session:: search_paths:: PathKind ;
2626use rustc:: middle:: cstore:: { CrateStore , validate_crate_name, ExternCrate } ;
27- use rustc:: util:: nodemap:: FnvHashMap ;
27+ use rustc:: util:: nodemap:: { FnvHashMap , FnvHashSet } ;
2828use rustc:: hir:: map as hir_map;
2929
3030use std:: cell:: { RefCell , Cell } ;
@@ -132,7 +132,7 @@ struct ExtensionCrate {
132132}
133133
134134enum PMDSource {
135- Registered ( Rc < cstore:: crate_metadata > ) ,
135+ Registered ( Rc < cstore:: CrateMetadata > ) ,
136136 Owned ( MetadataBlob ) ,
137137}
138138
@@ -294,7 +294,7 @@ impl<'a> CrateReader<'a> {
294294 span : Span ,
295295 lib : loader:: Library ,
296296 explicitly_linked : bool )
297- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > ,
297+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > ,
298298 cstore:: CrateSource ) {
299299 self . verify_rustc_version ( name, span, & lib. metadata ) ;
300300 self . verify_no_symbol_conflicts ( span, & lib. metadata ) ;
@@ -318,10 +318,10 @@ impl<'a> CrateReader<'a> {
318318
319319 let loader:: Library { dylib, rlib, metadata } = lib;
320320
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) ;
322322 let staged_api = self . is_staged_api ( metadata. as_slice ( ) ) ;
323323
324- let cmeta = Rc :: new ( cstore:: crate_metadata {
324+ let cmeta = Rc :: new ( cstore:: CrateMetadata {
325325 name : name. to_string ( ) ,
326326 extern_crate : Cell :: new ( None ) ,
327327 index : decoder:: load_index ( metadata. as_slice ( ) ) ,
@@ -364,7 +364,7 @@ impl<'a> CrateReader<'a> {
364364 span : Span ,
365365 kind : PathKind ,
366366 explicitly_linked : bool )
367- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > , cstore:: CrateSource ) {
367+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > , cstore:: CrateSource ) {
368368 let result = match self . existing_match ( name, hash, kind) {
369369 Some ( cnum) => LoadResult :: Previous ( cnum) ,
370370 None => {
@@ -438,8 +438,11 @@ impl<'a> CrateReader<'a> {
438438
439439 fn update_extern_crate ( & mut self ,
440440 cnum : ast:: CrateNum ,
441- mut extern_crate : ExternCrate )
441+ mut extern_crate : ExternCrate ,
442+ visited : & mut FnvHashSet < ( ast:: CrateNum , bool ) > )
442443 {
444+ if !visited. insert ( ( cnum, extern_crate. direct ) ) { return }
445+
443446 let cmeta = self . cstore . get_crate_data ( cnum) ;
444447 let old_extern_crate = cmeta. extern_crate . get ( ) ;
445448
@@ -458,24 +461,24 @@ impl<'a> CrateReader<'a> {
458461 }
459462
460463 cmeta. extern_crate . set ( Some ( extern_crate) ) ;
461-
462464 // Propagate the extern crate info to dependencies.
463465 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 ) ;
466468 }
467469 }
468470
469471 // Go through the crate metadata and load any crates that it references
470472 fn resolve_crate_deps ( & mut self ,
471473 root : & Option < CratePaths > ,
472474 cdata : & [ u8 ] ,
473- span : Span )
474- -> cstore:: cnum_map {
475+ krate : ast:: CrateNum ,
476+ span : Span )
477+ -> cstore:: CrateNumMap {
475478 debug ! ( "resolving deps of external crate" ) ;
476479 // The map from crate numbers in the crate we're resolving to local crate
477480 // numbers
478- decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
481+ let map : FnvHashMap < _ , _ > = decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
479482 debug ! ( "resolving dep crate {} hash: `{}`" , dep. name, dep. hash) ;
480483 let ( local_cnum, _, _) = self . resolve_crate ( root,
481484 & dep. name ,
@@ -485,7 +488,13 @@ impl<'a> CrateReader<'a> {
485488 PathKind :: Dependency ,
486489 dep. explicitly_linked ) ;
487490 ( 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 ( )
489498 }
490499
491500 fn read_extension_crate ( & mut self , span : Span , info : & CrateInfo ) -> ExtensionCrate {
@@ -826,7 +835,7 @@ impl<'a> CrateReader<'a> {
826835 fn inject_dependency_if ( & self ,
827836 krate : ast:: CrateNum ,
828837 what : & str ,
829- needs_dep : & Fn ( & cstore:: crate_metadata ) -> bool ) {
838+ needs_dep : & Fn ( & cstore:: CrateMetadata ) -> bool ) {
830839 // don't perform this validation if the session has errors, as one of
831840 // those errors may indicate a circular dependency which could cause
832841 // this to stack overflow.
@@ -837,7 +846,17 @@ impl<'a> CrateReader<'a> {
837846 // Before we inject any dependencies, make sure we don't inject a
838847 // circular dependency by validating that this crate doesn't
839848 // 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+ }
841860
842861 // All crates satisfying `needs_dep` do not explicitly depend on the
843862 // crate provided for this compile, but in order for this compilation to
@@ -849,32 +868,8 @@ impl<'a> CrateReader<'a> {
849868 }
850869
851870 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) ;
856872 } ) ;
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- }
878873 }
879874}
880875
@@ -948,7 +943,8 @@ impl<'a> LocalCrateReader<'a> {
948943 span : i. span ,
949944 direct : true ,
950945 path_len : len,
951- } ) ;
946+ } ,
947+ & mut FnvHashSet ( ) ) ;
952948 self . cstore . add_extern_mod_stmt_cnum ( info. id , cnum) ;
953949 }
954950 }
0 commit comments