@@ -2,13 +2,17 @@ use std::any::Any;
22use std:: mem;
33use std:: sync:: Arc ;
44
5+ use rustc_data_structures:: fingerprint:: Fingerprint ;
6+ use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
7+ use rustc_data_structures:: svh:: Svh ;
58use rustc_hir:: attrs:: Deprecation ;
69use rustc_hir:: def:: { CtorKind , DefKind } ;
710use rustc_hir:: def_id:: { CrateNum , DefId , DefIdMap , LOCAL_CRATE } ;
811use rustc_hir:: definitions:: { DefKey , DefPath , DefPathHash } ;
912use rustc_middle:: arena:: ArenaAllocatable ;
1013use rustc_middle:: bug;
1114use rustc_middle:: metadata:: { AmbigModChild , ModChild } ;
15+ use rustc_middle:: middle:: debugger_visualizer:: DebuggerVisualizerFile ;
1216use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
1317use rustc_middle:: middle:: stability:: DeprecationEntry ;
1418use rustc_middle:: queries:: ExternProviders ;
@@ -20,7 +24,7 @@ use rustc_serialize::Decoder;
2024use rustc_session:: StableCrateId ;
2125use rustc_session:: cstore:: { CrateStore , ExternCrate } ;
2226use rustc_span:: hygiene:: ExpnId ;
23- use rustc_span:: { Span , Symbol , kw} ;
27+ use rustc_span:: { Span , Symbol , kw, with_metavar_spans } ;
2428
2529use super :: { Decodable , DecodeIterator } ;
2630use crate :: creader:: { CStore , LoadedMacro } ;
@@ -750,4 +754,104 @@ fn provide_cstore_hooks(providers: &mut Providers) {
750754 cdata. imported_source_file ( tcx, file_index as u32 ) ;
751755 }
752756 } ;
757+
758+ providers. queries . crate_hash = |tcx : TyCtxt < ' _ > , _: LocalCrate | {
759+ if tcx. needs_metadata ( ) {
760+ * tcx. untracked ( )
761+ . local_crate_hash
762+ . get ( )
763+ . expect ( "crate_hash(LOCAL_CRATE) called before metadata encoding" )
764+ } else {
765+ crate_hash ( tcx)
766+ }
767+ } ;
768+ }
769+
770+ pub ( super ) fn crate_hash ( tcx : TyCtxt < ' _ > ) -> Svh {
771+ let krate = tcx. hir_crate ( ( ) ) ;
772+ let hir_body_hash = krate. opt_hir_hash . expect ( "HIR hash missing while computing crate hash" ) ;
773+
774+ let upstream_crates = upstream_crates ( tcx) ;
775+
776+ let resolutions = tcx. resolutions ( ( ) ) ;
777+
778+ // We hash the final, remapped names of all local source files so we
779+ // don't have to include the path prefix remapping commandline args.
780+ // If we included the full mapping in the SVH, we could only have
781+ // reproducible builds by compiling from the same directory. So we just
782+ // hash the result of the mapping instead of the mapping itself.
783+ let mut source_file_names: Vec < _ > = tcx
784+ . sess
785+ . source_map ( )
786+ . files ( )
787+ . iter ( )
788+ . filter ( |source_file| source_file. cnum == LOCAL_CRATE )
789+ . map ( |source_file| source_file. stable_id )
790+ . collect ( ) ;
791+
792+ source_file_names. sort_unstable ( ) ;
793+
794+ // We have to take care of debugger visualizers explicitly. The HIR (and
795+ // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
796+ // these attributes only store the file path to the visualizer file, not
797+ // their content. Yet that content is exported into crate metadata, so any
798+ // changes to it need to be reflected in the crate hash.
799+ let debugger_visualizers: Vec < _ > = tcx
800+ . debugger_visualizers ( LOCAL_CRATE )
801+ . iter ( )
802+ // We ignore the path to the visualizer file since it's not going to be
803+ // encoded in crate metadata and we already hash the full contents of
804+ // the file.
805+ . map ( DebuggerVisualizerFile :: path_erased)
806+ . collect ( ) ;
807+
808+ let crate_hash: Fingerprint = tcx. with_stable_hashing_context ( |mut hcx| {
809+ let mut stable_hasher = StableHasher :: new ( ) ;
810+ hir_body_hash. hash_stable ( & mut hcx, & mut stable_hasher) ;
811+ upstream_crates. hash_stable ( & mut hcx, & mut stable_hasher) ;
812+ source_file_names. hash_stable ( & mut hcx, & mut stable_hasher) ;
813+ debugger_visualizers. hash_stable ( & mut hcx, & mut stable_hasher) ;
814+ if tcx. sess . opts . incremental . is_some ( ) {
815+ let definitions = tcx. untracked ( ) . definitions . freeze ( ) ;
816+ let mut owner_spans: Vec < _ > = tcx
817+ . hir_crate_items ( ( ) )
818+ . definitions ( )
819+ . map ( |def_id| {
820+ let def_path_hash = definitions. def_path_hash ( def_id) ;
821+ let span = tcx. source_span ( def_id) ;
822+ debug_assert_eq ! ( span. parent( ) , None ) ;
823+ ( def_path_hash, span)
824+ } )
825+ . collect ( ) ;
826+ owner_spans. sort_unstable_by_key ( |bn| bn. 0 ) ;
827+ owner_spans. hash_stable ( & mut hcx, & mut stable_hasher) ;
828+ }
829+ tcx. sess . opts . dep_tracking_hash ( true ) . hash_stable ( & mut hcx, & mut stable_hasher) ;
830+ tcx. stable_crate_id ( LOCAL_CRATE ) . hash_stable ( & mut hcx, & mut stable_hasher) ;
831+ // Hash visibility information since it does not appear in HIR.
832+ // FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on
833+ // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`,
834+ // and combining it with other hashes here.
835+ resolutions. visibilities_for_hashing . hash_stable ( & mut hcx, & mut stable_hasher) ;
836+ with_metavar_spans ( |mspans| {
837+ mspans. freeze_and_get_read_spans ( ) . hash_stable ( & mut hcx, & mut stable_hasher) ;
838+ } ) ;
839+ stable_hasher. finish ( )
840+ } ) ;
841+
842+ Svh :: new ( crate_hash)
843+ }
844+
845+ fn upstream_crates ( tcx : TyCtxt < ' _ > ) -> Vec < ( StableCrateId , Svh ) > {
846+ let mut upstream_crates: Vec < _ > = tcx
847+ . crates ( ( ) )
848+ . iter ( )
849+ . map ( |& cnum| {
850+ let stable_crate_id = tcx. stable_crate_id ( cnum) ;
851+ let hash = tcx. crate_hash ( cnum) ;
852+ ( stable_crate_id, hash)
853+ } )
854+ . collect ( ) ;
855+ upstream_crates. sort_unstable_by_key ( |& ( stable_crate_id, _) | stable_crate_id) ;
856+ upstream_crates
753857}
0 commit comments