1212
1313//! Validates all used crates and extern libraries and loads their metadata
1414
15- use common:: rustc_version;
1615use cstore:: { self , CStore , CrateSource , MetadataBlob } ;
1716use decoder;
1817use loader:: { self , CratePaths } ;
@@ -24,7 +23,7 @@ use rustc::session::{config, Session};
2423use rustc:: session:: config:: PanicStrategy ;
2524use rustc:: session:: search_paths:: PathKind ;
2625use rustc:: middle:: cstore:: { CrateStore , validate_crate_name, ExternCrate } ;
27- use rustc:: util:: nodemap:: FnvHashMap ;
26+ use rustc:: util:: nodemap:: { FnvHashMap , FnvHashSet } ;
2827use rustc:: hir:: map as hir_map;
2928
3029use std:: cell:: { RefCell , Cell } ;
@@ -132,7 +131,7 @@ struct ExtensionCrate {
132131}
133132
134133enum PMDSource {
135- Registered ( Rc < cstore:: crate_metadata > ) ,
134+ Registered ( Rc < cstore:: CrateMetadata > ) ,
136135 Owned ( MetadataBlob ) ,
137136}
138137
@@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
236235 return ret;
237236 }
238237
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-
258238 fn verify_no_symbol_conflicts ( & self ,
259239 span : Span ,
260240 metadata : & MetadataBlob ) {
@@ -294,9 +274,8 @@ impl<'a> CrateReader<'a> {
294274 span : Span ,
295275 lib : loader:: Library ,
296276 explicitly_linked : bool )
297- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > ,
277+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > ,
298278 cstore:: CrateSource ) {
299- self . verify_rustc_version ( name, span, & lib. metadata ) ;
300279 self . verify_no_symbol_conflicts ( span, & lib. metadata ) ;
301280
302281 // Claim this crate number and cache it
@@ -318,10 +297,10 @@ impl<'a> CrateReader<'a> {
318297
319298 let loader:: Library { dylib, rlib, metadata } = lib;
320299
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) ;
322301 let staged_api = self . is_staged_api ( metadata. as_slice ( ) ) ;
323302
324- let cmeta = Rc :: new ( cstore:: crate_metadata {
303+ let cmeta = Rc :: new ( cstore:: CrateMetadata {
325304 name : name. to_string ( ) ,
326305 extern_crate : Cell :: new ( None ) ,
327306 index : decoder:: load_index ( metadata. as_slice ( ) ) ,
@@ -364,7 +343,7 @@ impl<'a> CrateReader<'a> {
364343 span : Span ,
365344 kind : PathKind ,
366345 explicitly_linked : bool )
367- -> ( ast:: CrateNum , Rc < cstore:: crate_metadata > , cstore:: CrateSource ) {
346+ -> ( ast:: CrateNum , Rc < cstore:: CrateMetadata > , cstore:: CrateSource ) {
368347 let result = match self . existing_match ( name, hash, kind) {
369348 Some ( cnum) => LoadResult :: Previous ( cnum) ,
370349 None => {
@@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
381360 rejected_via_hash : vec ! ( ) ,
382361 rejected_via_triple : vec ! ( ) ,
383362 rejected_via_kind : vec ! ( ) ,
363+ rejected_via_version : vec ! ( ) ,
384364 should_match_name : true ,
385365 } ;
386366 match self . load ( & mut load_ctxt) {
@@ -438,8 +418,11 @@ impl<'a> CrateReader<'a> {
438418
439419 fn update_extern_crate ( & mut self ,
440420 cnum : ast:: CrateNum ,
441- mut extern_crate : ExternCrate )
421+ mut extern_crate : ExternCrate ,
422+ visited : & mut FnvHashSet < ( ast:: CrateNum , bool ) > )
442423 {
424+ if !visited. insert ( ( cnum, extern_crate. direct ) ) { return }
425+
443426 let cmeta = self . cstore . get_crate_data ( cnum) ;
444427 let old_extern_crate = cmeta. extern_crate . get ( ) ;
445428
@@ -458,24 +441,24 @@ impl<'a> CrateReader<'a> {
458441 }
459442
460443 cmeta. extern_crate . set ( Some ( extern_crate) ) ;
461-
462444 // Propagate the extern crate info to dependencies.
463445 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 ) ;
466448 }
467449 }
468450
469451 // Go through the crate metadata and load any crates that it references
470452 fn resolve_crate_deps ( & mut self ,
471453 root : & Option < CratePaths > ,
472454 cdata : & [ u8 ] ,
473- span : Span )
474- -> cstore:: cnum_map {
455+ krate : ast:: CrateNum ,
456+ span : Span )
457+ -> cstore:: CrateNumMap {
475458 debug ! ( "resolving deps of external crate" ) ;
476459 // The map from crate numbers in the crate we're resolving to local crate
477460 // numbers
478- decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
461+ let map : FnvHashMap < _ , _ > = decoder:: get_crate_deps ( cdata) . iter ( ) . map ( |dep| {
479462 debug ! ( "resolving dep crate {} hash: `{}`" , dep. name, dep. hash) ;
480463 let ( local_cnum, _, _) = self . resolve_crate ( root,
481464 & dep. name ,
@@ -485,7 +468,13 @@ impl<'a> CrateReader<'a> {
485468 PathKind :: Dependency ,
486469 dep. explicitly_linked ) ;
487470 ( 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 ( )
489478 }
490479
491480 fn read_extension_crate ( & mut self , span : Span , info : & CrateInfo ) -> ExtensionCrate {
@@ -508,6 +497,7 @@ impl<'a> CrateReader<'a> {
508497 rejected_via_hash : vec ! ( ) ,
509498 rejected_via_triple : vec ! ( ) ,
510499 rejected_via_kind : vec ! ( ) ,
500+ rejected_via_version : vec ! ( ) ,
511501 should_match_name : true ,
512502 } ;
513503 let library = self . load ( & mut load_ctxt) . or_else ( || {
@@ -826,7 +816,7 @@ impl<'a> CrateReader<'a> {
826816 fn inject_dependency_if ( & self ,
827817 krate : ast:: CrateNum ,
828818 what : & str ,
829- needs_dep : & Fn ( & cstore:: crate_metadata ) -> bool ) {
819+ needs_dep : & Fn ( & cstore:: CrateMetadata ) -> bool ) {
830820 // don't perform this validation if the session has errors, as one of
831821 // those errors may indicate a circular dependency which could cause
832822 // this to stack overflow.
@@ -837,7 +827,17 @@ impl<'a> CrateReader<'a> {
837827 // Before we inject any dependencies, make sure we don't inject a
838828 // circular dependency by validating that this crate doesn't
839829 // 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+ }
841841
842842 // All crates satisfying `needs_dep` do not explicitly depend on the
843843 // crate provided for this compile, but in order for this compilation to
@@ -849,32 +849,8 @@ impl<'a> CrateReader<'a> {
849849 }
850850
851851 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) ;
856853 } ) ;
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- }
878854 }
879855}
880856
@@ -948,7 +924,8 @@ impl<'a> LocalCrateReader<'a> {
948924 span : i. span ,
949925 direct : true ,
950926 path_len : len,
951- } ) ;
927+ } ,
928+ & mut FnvHashSet ( ) ) ;
952929 self . cstore . add_extern_mod_stmt_cnum ( info. id , cnum) ;
953930 }
954931 }
0 commit comments