@@ -7,7 +7,8 @@ use std::sync::Arc;
77
88use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
99use rustc_data_structures:: memmap:: { Mmap , MmapMut } ;
10- use rustc_data_structures:: sync:: { par_for_each_in, par_join} ;
10+ use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
11+ use rustc_data_structures:: sync:: { join, par_for_each_in} ;
1112use rustc_data_structures:: temp_dir:: MaybeTempDir ;
1213use rustc_data_structures:: thousands:: usize_with_underscores;
1314use rustc_feature:: Features ;
@@ -26,6 +27,7 @@ use rustc_middle::ty::AssocContainer;
2627use rustc_middle:: ty:: codec:: TyEncoder ;
2728use rustc_middle:: ty:: fast_reject:: { self , TreatParams } ;
2829use rustc_middle:: { bug, span_bug} ;
30+ use rustc_query_system:: ich:: StableHashingContext ;
2931use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder , opaque} ;
3032use rustc_session:: config:: { CrateType , OptLevel , TargetModifier } ;
3133use rustc_span:: hygiene:: HygieneEncodeContext ;
@@ -39,8 +41,14 @@ use crate::eii::EiiMapEncodedKeyValue;
3941use crate :: errors:: { FailCreateFileEncoder , FailWriteFile } ;
4042use crate :: rmeta:: * ;
4143
42- pub ( super ) struct EncodeContext < ' a , ' tcx > {
44+ // Struct to enable split borrows.
45+ struct ContextEncoder < ' a > {
4346 opaque : opaque:: FileEncoder ,
47+ stable_hasher : StableHasher ,
48+ hcx : StableHashingContext < ' a > ,
49+ }
50+
51+ pub ( super ) struct EncodeContext < ' a , ' tcx > {
4452 tcx : TyCtxt < ' tcx > ,
4553 feat : & ' tcx rustc_feature:: Features ,
4654 tables : TableBuilders ,
@@ -67,6 +75,8 @@ pub(super) struct EncodeContext<'a, 'tcx> {
6775 hygiene_ctxt : & ' a HygieneEncodeContext ,
6876 // Used for both `Symbol`s and `ByteSymbol`s.
6977 symbol_index_table : FxHashMap < u32 , usize > ,
78+
79+ encoder : ContextEncoder < ' a > ,
7080}
7181
7282/// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
@@ -80,14 +90,49 @@ macro_rules! empty_proc_macro {
8090 } ;
8191}
8292
83- macro_rules! encoder_methods {
93+ macro_rules! context_encoder_methods {
8494 ( $( $name: ident( $ty: ty) ; ) * ) => {
8595 $( fn $name( & mut self , value: $ty) {
96+ value. hash_stable( & mut self . hcx, & mut self . stable_hasher) ;
8697 self . opaque. $name( value)
8798 } ) *
8899 }
89100}
90101
102+ impl < ' a > Encoder for ContextEncoder < ' a > {
103+ context_encoder_methods ! {
104+ emit_usize( usize ) ;
105+ emit_u128( u128 ) ;
106+ emit_u64( u64 ) ;
107+ emit_u32( u32 ) ;
108+ emit_u16( u16 ) ;
109+ emit_u8( u8 ) ;
110+
111+ emit_isize( isize ) ;
112+ emit_i128( i128 ) ;
113+ emit_i64( i64 ) ;
114+ emit_i32( i32 ) ;
115+ emit_i16( i16 ) ;
116+
117+ emit_raw_bytes( & [ u8 ] ) ;
118+ }
119+ }
120+
121+ impl < ' a > ContextEncoder < ' a > {
122+ #[ inline]
123+ fn position ( & self ) -> usize {
124+ self . opaque . position ( )
125+ }
126+ }
127+
128+ macro_rules! encoder_methods {
129+ ( $( $name: ident( $ty: ty) ; ) * ) => {
130+ $( fn $name( & mut self , value: $ty) {
131+ self . encoder. $name( value)
132+ } ) *
133+ }
134+ }
135+
91136impl < ' a , ' tcx > Encoder for EncodeContext < ' a , ' tcx > {
92137 encoder_methods ! {
93138 emit_usize( usize ) ;
@@ -149,6 +194,11 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
149194 }
150195
151196 fn encode_def_id ( & mut self , def_id : DefId ) {
197+ HashStable :: < StableHashingContext < ' _ > > :: hash_stable (
198+ & def_id,
199+ & mut self . encoder . hcx ,
200+ & mut self . encoder . stable_hasher ,
201+ ) ;
152202 def_id. krate . encode ( self ) ;
153203 def_id. index . encode ( self ) ;
154204 }
@@ -177,25 +227,25 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
177227 let last_location = * o. get ( ) ;
178228 // This cannot underflow. Metadata is written with increasing position(), so any
179229 // previously saved offset must be smaller than the current position.
180- let offset = self . opaque . position ( ) - last_location;
230+ let offset = self . encoder . position ( ) - last_location;
181231 if offset < last_location {
182232 let needed = bytes_needed ( offset) ;
183233 SpanTag :: indirect ( true , needed as u8 ) . encode ( self ) ;
184- self . opaque . write_with ( |dest| {
234+ self . encoder . opaque . write_with ( |dest| {
185235 * dest = offset. to_le_bytes ( ) ;
186236 needed
187237 } ) ;
188238 } else {
189239 let needed = bytes_needed ( last_location) ;
190240 SpanTag :: indirect ( false , needed as u8 ) . encode ( self ) ;
191- self . opaque . write_with ( |dest| {
241+ self . encoder . opaque . write_with ( |dest| {
192242 * dest = last_location. to_le_bytes ( ) ;
193243 needed
194244 } ) ;
195245 }
196246 }
197247 Entry :: Vacant ( v) => {
198- let position = self . opaque . position ( ) ;
248+ let position = self . encoder . position ( ) ;
199249 v. insert ( position) ;
200250 // Data is encoded with a SpanTag prefix (see below).
201251 span. data ( ) . encode ( self ) ;
@@ -372,7 +422,7 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
372422 const CLEAR_CROSS_CRATE : bool = true ;
373423
374424 fn position ( & self ) -> usize {
375- self . opaque . position ( )
425+ self . encoder . position ( )
376426 }
377427
378428 fn type_shorthands ( & mut self ) -> & mut FxHashMap < Ty < ' tcx > , usize > {
@@ -489,21 +539,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
489539 ) {
490540 // if symbol/byte symbol is predefined, emit tag and symbol index
491541 if Symbol :: is_predefined ( index) {
492- self . opaque . emit_u8 ( SYMBOL_PREDEFINED ) ;
493- self . opaque . emit_u32 ( index) ;
542+ self . encoder . emit_u8 ( SYMBOL_PREDEFINED ) ;
543+ self . encoder . emit_u32 ( index) ;
494544 } else {
495545 // otherwise write it as string or as offset to it
496546 match self . symbol_index_table . entry ( index) {
497547 Entry :: Vacant ( o) => {
498- self . opaque . emit_u8 ( SYMBOL_STR ) ;
499- let pos = self . opaque . position ( ) ;
548+ self . encoder . emit_u8 ( SYMBOL_STR ) ;
549+ let pos = self . encoder . position ( ) ;
500550 o. insert ( pos) ;
501551 emit_str_or_byte_str ( self ) ;
502552 }
503553 Entry :: Occupied ( o) => {
504554 let x = * o. get ( ) ;
505- self . emit_u8 ( SYMBOL_OFFSET ) ;
506- self . emit_usize ( x) ;
555+ self . encoder . emit_u8 ( SYMBOL_OFFSET ) ;
556+ self . encoder . emit_usize ( x) ;
507557 }
508558 }
509559 }
@@ -598,7 +648,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
598648 adapted. set_some ( on_disk_index, self . lazy ( adapted_source_file) ) ;
599649 }
600650
601- adapted. encode ( & mut self . opaque )
651+ adapted. encode ( & mut self . encoder . opaque )
602652 }
603653
604654 fn encode_crate_root ( & mut self ) -> LazyValue < CrateRoot > {
@@ -682,7 +732,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
682732 // encode_def_path_table.
683733 let proc_macro_data = stat ! ( "proc-macro-data" , || self . encode_proc_macros( ) ) ;
684734
685- let tables = stat ! ( "tables" , || self . tables. encode( & mut self . opaque) ) ;
735+ let tables = stat ! ( "tables" , || self . tables. encode( & mut self . encoder . opaque) ) ;
686736
687737 let debugger_visualizers =
688738 stat ! ( "debugger-visualizers" , || self . encode_debugger_visualizers( ) ) ;
@@ -783,19 +833,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
783833 if tcx. sess . opts . unstable_opts . meta_stats {
784834 use std:: fmt:: Write ;
785835
786- self . opaque . flush ( ) ;
836+ let opaque = & mut self . encoder . opaque ;
837+ opaque. flush ( ) ;
787838
788839 // Rewind and re-read all the metadata to count the zero bytes we wrote.
789- let pos_before_rewind = self . opaque . file ( ) . stream_position ( ) . unwrap ( ) ;
840+ let pos_before_rewind = opaque. file ( ) . stream_position ( ) . unwrap ( ) ;
790841 let mut zero_bytes = 0 ;
791- self . opaque . file ( ) . rewind ( ) . unwrap ( ) ;
792- let file = std:: io:: BufReader :: new ( self . opaque . file ( ) ) ;
842+ opaque. file ( ) . rewind ( ) . unwrap ( ) ;
843+ let file = std:: io:: BufReader :: new ( opaque. file ( ) ) ;
793844 for e in file. bytes ( ) {
794845 if e. unwrap ( ) == 0 {
795846 zero_bytes += 1 ;
796847 }
797848 }
798- assert_eq ! ( self . opaque. file( ) . stream_position( ) . unwrap( ) , pos_before_rewind) ;
849+ assert_eq ! ( opaque. file( ) . stream_position( ) . unwrap( ) , pos_before_rewind) ;
799850
800851 stats. sort_by_key ( |& ( _, usize) | usize) ;
801852 stats. reverse ( ) ; // bigger items first
@@ -1967,9 +2018,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19672018 ) ;
19682019
19692020 (
1970- syntax_contexts. encode ( & mut self . opaque ) ,
1971- expn_data_table. encode ( & mut self . opaque ) ,
1972- expn_hash_table. encode ( & mut self . opaque ) ,
2021+ syntax_contexts. encode ( & mut self . encoder . opaque ) ,
2022+ expn_data_table. encode ( & mut self . encoder . opaque ) ,
2023+ expn_hash_table. encode ( & mut self . encoder . opaque ) ,
19732024 )
19742025 }
19752026
@@ -2482,12 +2533,12 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
24822533 let root = ecx. encode_crate_root ( ) ;
24832534
24842535 // Flush buffer to ensure backing file has the correct size.
2485- ecx. opaque . flush ( ) ;
2536+ ecx. encoder . opaque . flush ( ) ;
24862537 // Record metadata size for self-profiling
24872538 tcx. prof . artifact_size (
24882539 "crate_metadata" ,
24892540 "crate_metadata" ,
2490- ecx. opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
2541+ ecx. encoder . opaque . file ( ) . metadata ( ) . unwrap ( ) . len ( ) ,
24912542 ) ;
24922543
24932544 root. position . get ( )
@@ -2502,53 +2553,55 @@ fn with_encode_metadata_header(
25022553 path : & Path ,
25032554 f : impl FnOnce ( & mut EncodeContext < ' _ , ' _ > ) -> usize ,
25042555) {
2505- let mut encoder = opaque:: FileEncoder :: new ( path)
2506- . unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2507- encoder. emit_raw_bytes ( METADATA_HEADER ) ;
2508-
2509- // Will be filled with the root position after encoding everything.
2510- encoder. emit_raw_bytes ( & 0u64 . to_le_bytes ( ) ) ;
2511-
2512- let source_map_files = tcx. sess . source_map ( ) . files ( ) ;
2513- let source_file_cache = ( Arc :: clone ( & source_map_files[ 0 ] ) , 0 ) ;
2514- let required_source_files = Some ( FxIndexSet :: default ( ) ) ;
2515- drop ( source_map_files) ;
2516-
2517- let hygiene_ctxt = HygieneEncodeContext :: default ( ) ;
2518-
2519- let mut ecx = EncodeContext {
2520- opaque : encoder,
2521- tcx,
2522- feat : tcx. features ( ) ,
2523- tables : Default :: default ( ) ,
2524- lazy_state : LazyState :: NoNode ,
2525- span_shorthands : Default :: default ( ) ,
2526- type_shorthands : Default :: default ( ) ,
2527- predicate_shorthands : Default :: default ( ) ,
2528- source_file_cache,
2529- interpret_allocs : Default :: default ( ) ,
2530- required_source_files,
2531- is_proc_macro : tcx. crate_types ( ) . contains ( & CrateType :: ProcMacro ) ,
2532- hygiene_ctxt : & hygiene_ctxt,
2533- symbol_index_table : Default :: default ( ) ,
2534- } ;
2556+ tcx. with_stable_hashing_context ( |hcx| {
2557+ let mut encoder = opaque:: FileEncoder :: new ( path)
2558+ . unwrap_or_else ( |err| tcx. dcx ( ) . emit_fatal ( FailCreateFileEncoder { err } ) ) ;
2559+ encoder. emit_raw_bytes ( METADATA_HEADER ) ;
2560+
2561+ // Will be filled with the root position after encoding everything.
2562+ encoder. emit_raw_bytes ( & 0u64 . to_le_bytes ( ) ) ;
2563+
2564+ let source_map_files = tcx. sess . source_map ( ) . files ( ) ;
2565+ let source_file_cache = ( Arc :: clone ( & source_map_files[ 0 ] ) , 0 ) ;
2566+ let required_source_files = Some ( FxIndexSet :: default ( ) ) ;
2567+ drop ( source_map_files) ;
2568+
2569+ let hygiene_ctxt = HygieneEncodeContext :: default ( ) ;
2570+
2571+ let mut ecx = EncodeContext {
2572+ tcx,
2573+ feat : tcx. features ( ) ,
2574+ tables : Default :: default ( ) ,
2575+ lazy_state : LazyState :: NoNode ,
2576+ span_shorthands : Default :: default ( ) ,
2577+ type_shorthands : Default :: default ( ) ,
2578+ predicate_shorthands : Default :: default ( ) ,
2579+ source_file_cache,
2580+ interpret_allocs : Default :: default ( ) ,
2581+ required_source_files,
2582+ is_proc_macro : tcx. crate_types ( ) . contains ( & CrateType :: ProcMacro ) ,
2583+ hygiene_ctxt : & hygiene_ctxt,
2584+ symbol_index_table : Default :: default ( ) ,
2585+ encoder : ContextEncoder { opaque : encoder, stable_hasher : StableHasher :: new ( ) , hcx } ,
2586+ } ;
25352587
2536- // Encode the rustc version string in a predictable location.
2537- rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
2588+ // Encode the rustc version string in a predictable location.
2589+ rustc_version ( tcx. sess . cfg_version ) . encode ( & mut ecx) ;
25382590
2539- let root_position = f ( & mut ecx) ;
2591+ let root_position = f ( & mut ecx) ;
25402592
2541- // Make sure we report any errors from writing to the file.
2542- // If we forget this, compilation can succeed with an incomplete rmeta file,
2543- // causing an ICE when the rmeta file is read by another compilation.
2544- if let Err ( ( path, err) ) = ecx. opaque . finish ( ) {
2545- tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : & path, err } ) ;
2546- }
2593+ // Make sure we report any errors from writing to the file.
2594+ // If we forget this, compilation can succeed with an incomplete rmeta file,
2595+ // causing an ICE when the rmeta file is read by another compilation.
2596+ if let Err ( ( path, err) ) = ecx. encoder . opaque . finish ( ) {
2597+ tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : & path, err } ) ;
2598+ }
25472599
2548- let file = ecx. opaque . file ( ) ;
2549- if let Err ( err) = encode_root_position ( file, root_position) {
2550- tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. opaque . path ( ) , err } ) ;
2551- }
2600+ let file = ecx. encoder . opaque . file ( ) ;
2601+ if let Err ( err) = encode_root_position ( file, root_position) {
2602+ tcx. dcx ( ) . emit_fatal ( FailWriteFile { path : ecx. encoder . opaque . path ( ) , err } ) ;
2603+ }
2604+ } )
25522605}
25532606
25542607fn encode_root_position ( mut file : & File , pos : usize ) -> Result < ( ) , std:: io:: Error > {
0 commit comments