• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::errors::{FailCreateFileEncoder, FailSeekFile, FailWriteFile};
2 use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
3 use crate::rmeta::table::TableBuilder;
4 use crate::rmeta::*;
5 
6 use rustc_ast::expand::StrippedCfgItem;
7 use rustc_ast::Attribute;
8 use rustc_data_structures::fingerprint::Fingerprint;
9 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
10 use rustc_data_structures::memmap::{Mmap, MmapMut};
11 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
12 use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
13 use rustc_data_structures::temp_dir::MaybeTempDir;
14 use rustc_hir as hir;
15 use rustc_hir::def::DefKind;
16 use rustc_hir::def_id::{
17     CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE,
18 };
19 use rustc_hir::definitions::DefPathData;
20 use rustc_hir::intravisit;
21 use rustc_hir::lang_items::LangItem;
22 use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
23 use rustc_middle::middle::dependency_format::Linkage;
24 use rustc_middle::middle::exported_symbols::{
25     metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
26 };
27 use rustc_middle::mir::interpret;
28 use rustc_middle::query::LocalCrate;
29 use rustc_middle::query::Providers;
30 use rustc_middle::traits::specialization_graph;
31 use rustc_middle::ty::codec::TyEncoder;
32 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
33 use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
34 use rustc_middle::util::common::to_readable_str;
35 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
36 use rustc_session::config::{CrateType, OptLevel};
37 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
38 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
39 use rustc_span::symbol::{sym, Symbol};
40 use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
41 use std::borrow::Borrow;
42 use std::collections::hash_map::Entry;
43 use std::hash::Hash;
44 use std::io::{Read, Seek, Write};
45 use std::num::NonZeroUsize;
46 use std::path::{Path, PathBuf};
47 
48 pub(super) struct EncodeContext<'a, 'tcx> {
49     opaque: opaque::FileEncoder,
50     tcx: TyCtxt<'tcx>,
51     feat: &'tcx rustc_feature::Features,
52 
53     tables: TableBuilders,
54 
55     lazy_state: LazyState,
56     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
57     predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
58 
59     interpret_allocs: FxIndexSet<interpret::AllocId>,
60 
61     // This is used to speed up Span encoding.
62     // The `usize` is an index into the `MonotonicVec`
63     // that stores the `SourceFile`
64     source_file_cache: (Lrc<SourceFile>, usize),
65     // The indices (into the `SourceMap`'s `MonotonicVec`)
66     // of all of the `SourceFiles` that we need to serialize.
67     // When we serialize a `Span`, we insert the index of its
68     // `SourceFile` into the `FxIndexSet`.
69     // The order inside the `FxIndexSet` is used as on-disk
70     // order of `SourceFiles`, and encoded inside `Span`s.
71     required_source_files: Option<FxIndexSet<usize>>,
72     is_proc_macro: bool,
73     hygiene_ctxt: &'a HygieneEncodeContext,
74     symbol_table: FxHashMap<Symbol, usize>,
75 }
76 
77 /// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
78 /// This is useful for skipping the encoding of things that aren't needed
79 /// for proc-macro crates.
80 macro_rules! empty_proc_macro {
81     ($self:ident) => {
82         if $self.is_proc_macro {
83             return LazyArray::default();
84         }
85     };
86 }
87 
88 macro_rules! encoder_methods {
89     ($($name:ident($ty:ty);)*) => {
90         $(fn $name(&mut self, value: $ty) {
91             self.opaque.$name(value)
92         })*
93     }
94 }
95 
96 impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
97     encoder_methods! {
98         emit_usize(usize);
99         emit_u128(u128);
100         emit_u64(u64);
101         emit_u32(u32);
102         emit_u16(u16);
103         emit_u8(u8);
104 
105         emit_isize(isize);
106         emit_i128(i128);
107         emit_i64(i64);
108         emit_i32(i32);
109         emit_i16(i16);
110 
111         emit_raw_bytes(&[u8]);
112     }
113 }
114 
115 impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
encode(&self, e: &mut EncodeContext<'a, 'tcx>)116     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
117         e.emit_lazy_distance(self.position);
118     }
119 }
120 
121 impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
encode(&self, e: &mut EncodeContext<'a, 'tcx>)122     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
123         e.emit_usize(self.num_elems);
124         if self.num_elems > 0 {
125             e.emit_lazy_distance(self.position)
126         }
127     }
128 }
129 
130 impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
encode(&self, e: &mut EncodeContext<'a, 'tcx>)131     fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
132         e.emit_usize(self.encoded_size);
133         e.emit_lazy_distance(self.position);
134     }
135 }
136 
137 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)138     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
139         if *self != LOCAL_CRATE && s.is_proc_macro {
140             panic!("Attempted to encode non-local CrateNum {self:?} for proc-macro crate");
141         }
142         s.emit_u32(self.as_u32());
143     }
144 }
145 
146 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)147     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
148         s.emit_u32(self.as_u32());
149     }
150 }
151 
152 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)153     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
154         s.emit_u32(self.as_u32());
155     }
156 }
157 
158 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)159     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
160         rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s);
161     }
162 }
163 
164 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)165     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
166         if self.krate == LOCAL_CRATE {
167             // We will only write details for local expansions. Non-local expansions will fetch
168             // data from the corresponding crate's metadata.
169             // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
170             // metadata from proc-macro crates.
171             s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
172         }
173         self.krate.encode(s);
174         self.local_id.encode(s);
175     }
176 }
177 
178 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)179     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
180         let span = self.data();
181 
182         // Don't serialize any `SyntaxContext`s from a proc-macro crate,
183         // since we don't load proc-macro dependencies during serialization.
184         // This means that any hygiene information from macros used *within*
185         // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
186         // definition) will be lost.
187         //
188         // This can show up in two ways:
189         //
190         // 1. Any hygiene information associated with identifier of
191         // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
192         // Since proc-macros can only be invoked from a different crate,
193         // real code should never need to care about this.
194         //
195         // 2. Using `Span::def_site` or `Span::mixed_site` will not
196         // include any hygiene information associated with the definition
197         // site. This means that a proc-macro cannot emit a `$crate`
198         // identifier which resolves to one of its dependencies,
199         // which also should never come up in practice.
200         //
201         // Additionally, this affects `Span::parent`, and any other
202         // span inspection APIs that would otherwise allow traversing
203         // the `SyntaxContexts` associated with a span.
204         //
205         // None of these user-visible effects should result in any
206         // cross-crate inconsistencies (getting one behavior in the same
207         // crate, and a different behavior in another crate) due to the
208         // limited surface that proc-macros can expose.
209         //
210         // IMPORTANT: If this is ever changed, be sure to update
211         // `rustc_span::hygiene::raw_encode_expn_id` to handle
212         // encoding `ExpnData` for proc-macro crates.
213         if s.is_proc_macro {
214             SyntaxContext::root().encode(s);
215         } else {
216             span.ctxt.encode(s);
217         }
218 
219         if self.is_dummy() {
220             return TAG_PARTIAL_SPAN.encode(s);
221         }
222 
223         // The Span infrastructure should make sure that this invariant holds:
224         debug_assert!(span.lo <= span.hi);
225 
226         if !s.source_file_cache.0.contains(span.lo) {
227             let source_map = s.tcx.sess.source_map();
228             let source_file_index = source_map.lookup_source_file_idx(span.lo);
229             s.source_file_cache =
230                 (source_map.files()[source_file_index].clone(), source_file_index);
231         }
232         let (ref source_file, source_file_index) = s.source_file_cache;
233         debug_assert!(source_file.contains(span.lo));
234 
235         if !source_file.contains(span.hi) {
236             // Unfortunately, macro expansion still sometimes generates Spans
237             // that malformed in this way.
238             return TAG_PARTIAL_SPAN.encode(s);
239         }
240 
241         // There are two possible cases here:
242         // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
243         // crate we are writing metadata for. When the metadata for *this* crate gets
244         // deserialized, the deserializer will need to know which crate it originally came
245         // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
246         // be deserialized after the rest of the span data, which tells the deserializer
247         // which crate contains the source map information.
248         // 2. This span comes from our own crate. No special handling is needed - we just
249         // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
250         // our own source map information.
251         //
252         // If we're a proc-macro crate, we always treat this as a local `Span`.
253         // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata
254         // if we're a proc-macro crate.
255         // This allows us to avoid loading the dependencies of proc-macro crates: all of
256         // the information we need to decode `Span`s is stored in the proc-macro crate.
257         let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
258             // To simplify deserialization, we 'rebase' this span onto the crate it originally came
259             // from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'
260             // values are relative to the source map information for the 'foreign' crate whose
261             // CrateNum we write into the metadata. This allows `imported_source_files` to binary
262             // search through the 'foreign' crate's source map information, using the
263             // deserialized 'lo' and 'hi' values directly.
264             //
265             // All of this logic ensures that the final result of deserialization is a 'normal'
266             // Span that can be used without any additional trouble.
267             let metadata_index = {
268                 // Introduce a new scope so that we drop the 'lock()' temporary
269                 match &*source_file.external_src.lock() {
270                     ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
271                     src => panic!("Unexpected external source {src:?}"),
272                 }
273             };
274 
275             (TAG_VALID_SPAN_FOREIGN, metadata_index)
276         } else {
277             // Record the fact that we need to encode the data for this `SourceFile`
278             let source_files =
279                 s.required_source_files.as_mut().expect("Already encoded SourceMap!");
280             let (metadata_index, _) = source_files.insert_full(source_file_index);
281             let metadata_index: u32 =
282                 metadata_index.try_into().expect("cannot export more than U32_MAX files");
283 
284             (TAG_VALID_SPAN_LOCAL, metadata_index)
285         };
286 
287         // Encode the start position relative to the file start, so we profit more from the
288         // variable-length integer encoding.
289         let lo = span.lo - source_file.start_pos;
290 
291         // Encode length which is usually less than span.hi and profits more
292         // from the variable-length integer encoding that we use.
293         let len = span.hi - span.lo;
294 
295         tag.encode(s);
296         lo.encode(s);
297         len.encode(s);
298 
299         // Encode the index of the `SourceFile` for the span, in order to make decoding faster.
300         metadata_index.encode(s);
301 
302         if tag == TAG_VALID_SPAN_FOREIGN {
303             // This needs to be two lines to avoid holding the `s.source_file_cache`
304             // while calling `cnum.encode(s)`
305             let cnum = s.source_file_cache.0.cnum;
306             cnum.encode(s);
307         }
308     }
309 }
310 
311 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Symbol {
encode(&self, s: &mut EncodeContext<'a, 'tcx>)312     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
313         // if symbol preinterned, emit tag and symbol index
314         if self.is_preinterned() {
315             s.opaque.emit_u8(SYMBOL_PREINTERNED);
316             s.opaque.emit_u32(self.as_u32());
317         } else {
318             // otherwise write it as string or as offset to it
319             match s.symbol_table.entry(*self) {
320                 Entry::Vacant(o) => {
321                     s.opaque.emit_u8(SYMBOL_STR);
322                     let pos = s.opaque.position();
323                     o.insert(pos);
324                     s.emit_str(self.as_str());
325                 }
326                 Entry::Occupied(o) => {
327                     let x = *o.get();
328                     s.emit_u8(SYMBOL_OFFSET);
329                     s.emit_usize(x);
330                 }
331             }
332         }
333     }
334 }
335 
336 impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
337     const CLEAR_CROSS_CRATE: bool = true;
338 
339     type I = TyCtxt<'tcx>;
340 
position(&self) -> usize341     fn position(&self) -> usize {
342         self.opaque.position()
343     }
344 
type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>345     fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
346         &mut self.type_shorthands
347     }
348 
predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>349     fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
350         &mut self.predicate_shorthands
351     }
352 
encode_alloc_id(&mut self, alloc_id: &rustc_middle::mir::interpret::AllocId)353     fn encode_alloc_id(&mut self, alloc_id: &rustc_middle::mir::interpret::AllocId) {
354         let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
355 
356         index.encode(self);
357     }
358 }
359 
360 // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
361 // normally need extra variables to avoid errors about multiple mutable borrows.
362 macro_rules! record {
363     ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
364         {
365             let value = $value;
366             let lazy = $self.lazy(value);
367             $self.$tables.$table.set_some($def_id.index, lazy);
368         }
369     }};
370 }
371 
372 // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
373 // normally need extra variables to avoid errors about multiple mutable borrows.
374 macro_rules! record_array {
375     ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
376         {
377             let value = $value;
378             let lazy = $self.lazy_array(value);
379             $self.$tables.$table.set_some($def_id.index, lazy);
380         }
381     }};
382 }
383 
384 macro_rules! record_defaulted_array {
385     ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
386         {
387             let value = $value;
388             let lazy = $self.lazy_array(value);
389             $self.$tables.$table.set($def_id.index, lazy);
390         }
391     }};
392 }
393 
394 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
emit_lazy_distance(&mut self, position: NonZeroUsize)395     fn emit_lazy_distance(&mut self, position: NonZeroUsize) {
396         let pos = position.get();
397         let distance = match self.lazy_state {
398             LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
399             LazyState::NodeStart(start) => {
400                 let start = start.get();
401                 assert!(pos <= start);
402                 start - pos
403             }
404             LazyState::Previous(last_pos) => {
405                 assert!(
406                     last_pos <= position,
407                     "make sure that the calls to `lazy*` \
408                      are in the same order as the metadata fields",
409                 );
410                 position.get() - last_pos.get()
411             }
412         };
413         self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap());
414         self.emit_usize(distance);
415     }
416 
lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T> where T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,417     fn lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T>
418     where
419         T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
420     {
421         let pos = NonZeroUsize::new(self.position()).unwrap();
422 
423         assert_eq!(self.lazy_state, LazyState::NoNode);
424         self.lazy_state = LazyState::NodeStart(pos);
425         value.borrow().encode(self);
426         self.lazy_state = LazyState::NoNode;
427 
428         assert!(pos.get() <= self.position());
429 
430         LazyValue::from_position(pos)
431     }
432 
lazy_array<T: ParameterizedOverTcx, I: IntoIterator<Item = B>, B: Borrow<T::Value<'tcx>>>( &mut self, values: I, ) -> LazyArray<T> where T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,433     fn lazy_array<T: ParameterizedOverTcx, I: IntoIterator<Item = B>, B: Borrow<T::Value<'tcx>>>(
434         &mut self,
435         values: I,
436     ) -> LazyArray<T>
437     where
438         T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
439     {
440         let pos = NonZeroUsize::new(self.position()).unwrap();
441 
442         assert_eq!(self.lazy_state, LazyState::NoNode);
443         self.lazy_state = LazyState::NodeStart(pos);
444         let len = values.into_iter().map(|value| value.borrow().encode(self)).count();
445         self.lazy_state = LazyState::NoNode;
446 
447         assert!(pos.get() <= self.position());
448 
449         LazyArray::from_position_and_num_elems(pos, len)
450     }
451 
encode_def_path_table(&mut self)452     fn encode_def_path_table(&mut self) {
453         let table = self.tcx.def_path_table();
454         if self.is_proc_macro {
455             for def_index in std::iter::once(CRATE_DEF_INDEX)
456                 .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index))
457             {
458                 let def_key = self.lazy(table.def_key(def_index));
459                 let def_path_hash = table.def_path_hash(def_index);
460                 self.tables.def_keys.set_some(def_index, def_key);
461                 self.tables.def_path_hashes.set(def_index, def_path_hash);
462             }
463         } else {
464             for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
465                 let def_key = self.lazy(def_key);
466                 self.tables.def_keys.set_some(def_index, def_key);
467                 self.tables.def_path_hashes.set(def_index, *def_path_hash);
468             }
469         }
470     }
471 
encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'static>>472     fn encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'static>> {
473         self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map()))
474     }
475 
encode_source_map(&mut self) -> LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>>476     fn encode_source_map(&mut self) -> LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>> {
477         let source_map = self.tcx.sess.source_map();
478         let all_source_files = source_map.files();
479 
480         // By replacing the `Option` with `None`, we ensure that we can't
481         // accidentally serialize any more `Span`s after the source map encoding
482         // is done.
483         let required_source_files = self.required_source_files.take().unwrap();
484 
485         let working_directory = &self.tcx.sess.opts.working_dir;
486 
487         let mut adapted = TableBuilder::default();
488 
489         // Only serialize `SourceFile`s that were used during the encoding of a `Span`.
490         //
491         // The order in which we encode source files is important here: the on-disk format for
492         // `Span` contains the index of the corresponding `SourceFile`.
493         for (on_disk_index, &source_file_index) in required_source_files.iter().enumerate() {
494             let source_file = &all_source_files[source_file_index];
495             // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate.
496             assert!(!source_file.is_imported() || self.is_proc_macro);
497 
498             // At export time we expand all source file paths to absolute paths because
499             // downstream compilation sessions can have a different compiler working
500             // directory, so relative paths from this or any other upstream crate
501             // won't be valid anymore.
502             //
503             // At this point we also erase the actual on-disk path and only keep
504             // the remapped version -- as is necessary for reproducible builds.
505             let mut source_file = match source_file.name {
506                 FileName::Real(ref original_file_name) => {
507                     let adapted_file_name = source_map
508                         .path_mapping()
509                         .to_embeddable_absolute_path(original_file_name.clone(), working_directory);
510 
511                     if adapted_file_name != *original_file_name {
512                         let mut adapted: SourceFile = (**source_file).clone();
513                         adapted.name = FileName::Real(adapted_file_name);
514                         adapted.name_hash = {
515                             let mut hasher: StableHasher = StableHasher::new();
516                             adapted.name.hash(&mut hasher);
517                             hasher.finish::<Hash128>()
518                         };
519                         Lrc::new(adapted)
520                     } else {
521                         // Nothing to adapt
522                         source_file.clone()
523                     }
524                 }
525                 // expanded code, not from a file
526                 _ => source_file.clone(),
527             };
528 
529             // We're serializing this `SourceFile` into our crate metadata,
530             // so mark it as coming from this crate.
531             // This also ensures that we don't try to deserialize the
532             // `CrateNum` for a proc-macro dependency - since proc macro
533             // dependencies aren't loaded when we deserialize a proc-macro,
534             // trying to remap the `CrateNum` would fail.
535             if self.is_proc_macro {
536                 Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE;
537             }
538 
539             let on_disk_index: u32 =
540                 on_disk_index.try_into().expect("cannot export more than U32_MAX files");
541             adapted.set_some(on_disk_index, self.lazy(source_file));
542         }
543 
544         adapted.encode(&mut self.opaque)
545     }
546 
encode_crate_root(&mut self) -> LazyValue<CrateRoot>547     fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
548         let tcx = self.tcx;
549         let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
550 
551         macro_rules! stat {
552             ($label:literal, $f:expr) => {{
553                 let orig_pos = self.position();
554                 let res = $f();
555                 stats.push(($label, self.position() - orig_pos));
556                 res
557             }};
558         }
559 
560         // We have already encoded some things. Get their combined size from the current position.
561         stats.push(("preamble", self.position()));
562 
563         let (crate_deps, dylib_dependency_formats) =
564             stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
565 
566         let lib_features = stat!("lib-features", || self.encode_lib_features());
567 
568         let stability_implications =
569             stat!("stability-implications", || self.encode_stability_implications());
570 
571         let (lang_items, lang_items_missing) = stat!("lang-items", || {
572             (self.encode_lang_items(), self.encode_lang_items_missing())
573         });
574 
575         let stripped_cfg_items = stat!("stripped-cfg-items", || self.encode_stripped_cfg_items());
576 
577         let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
578 
579         let native_libraries = stat!("native-libs", || self.encode_native_libraries());
580 
581         let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
582 
583         _ = stat!("def-path-table", || self.encode_def_path_table());
584 
585         // Encode the def IDs of traits, for rustdoc and diagnostics.
586         let traits = stat!("traits", || self.encode_traits());
587 
588         // Encode the def IDs of impls, for coherence checking.
589         let impls = stat!("impls", || self.encode_impls());
590 
591         let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
592 
593         _ = stat!("mir", || self.encode_mir());
594 
595         _ = stat!("def-ids", || self.encode_def_ids());
596 
597         let interpret_alloc_index = stat!("interpret-alloc-index", || {
598             let mut interpret_alloc_index = Vec::new();
599             let mut n = 0;
600             trace!("beginning to encode alloc ids");
601             loop {
602                 let new_n = self.interpret_allocs.len();
603                 // if we have found new ids, serialize those, too
604                 if n == new_n {
605                     // otherwise, abort
606                     break;
607                 }
608                 trace!("encoding {} further alloc ids", new_n - n);
609                 for idx in n..new_n {
610                     let id = self.interpret_allocs[idx];
611                     let pos = self.position() as u32;
612                     interpret_alloc_index.push(pos);
613                     interpret::specialized_encode_alloc_id(self, tcx, id);
614                 }
615                 n = new_n;
616             }
617             self.lazy_array(interpret_alloc_index)
618         });
619 
620         // Encode the proc macro data. This affects `tables`, so we need to do this before we
621         // encode the tables. This overwrites def_keys, so it must happen after
622         // encode_def_path_table.
623         let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
624 
625         let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
626 
627         let debugger_visualizers =
628             stat!("debugger-visualizers", || self.encode_debugger_visualizers());
629 
630         // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
631         // this as late as possible to give the prefetching as much time as possible to complete.
632         let exported_symbols = stat!("exported-symbols", || {
633             self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
634         });
635 
636         // Encode the hygiene data.
637         // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
638         // process of encoding other items (e.g. `optimized_mir`) may cause us to load data from
639         // the incremental cache. If this causes us to deserialize a `Span`, then we may load
640         // additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
641         // the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
642         let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
643 
644         let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
645 
646         // Encode source_map. This needs to be done last, because encoding `Span`s tells us which
647         // `SourceFiles` we actually need to encode.
648         let source_map = stat!("source-map", || self.encode_source_map());
649 
650         let root = stat!("final", || {
651             let attrs = tcx.hir().krate_attrs();
652             self.lazy(CrateRoot {
653                 header: CrateHeader {
654                     name: tcx.crate_name(LOCAL_CRATE),
655                     triple: tcx.sess.opts.target_triple.clone(),
656                     hash: tcx.crate_hash(LOCAL_CRATE),
657                     is_proc_macro_crate: proc_macro_data.is_some(),
658                 },
659                 extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
660                 stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
661                 required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
662                 panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
663                 edition: tcx.sess.edition(),
664                 has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
665                 has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE),
666                 has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
667                 has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator),
668                 proc_macro_data,
669                 debugger_visualizers,
670                 compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins),
671                 needs_allocator: attr::contains_name(&attrs, sym::needs_allocator),
672                 needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime),
673                 no_builtins: attr::contains_name(&attrs, sym::no_builtins),
674                 panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
675                 profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
676                 symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
677 
678                 crate_deps,
679                 dylib_dependency_formats,
680                 lib_features,
681                 stability_implications,
682                 lang_items,
683                 diagnostic_items,
684                 lang_items_missing,
685                 stripped_cfg_items,
686                 native_libraries,
687                 foreign_modules,
688                 source_map,
689                 traits,
690                 impls,
691                 incoherent_impls,
692                 exported_symbols,
693                 interpret_alloc_index,
694                 tables,
695                 syntax_contexts,
696                 expn_data,
697                 expn_hashes,
698                 def_path_hash_map,
699             })
700         });
701 
702         let total_bytes = self.position();
703 
704         let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
705         assert_eq!(total_bytes, computed_total_bytes);
706 
707         if tcx.sess.opts.unstable_opts.meta_stats {
708             self.opaque.flush();
709 
710             // Rewind and re-read all the metadata to count the zero bytes we wrote.
711             let pos_before_rewind = self.opaque.file().stream_position().unwrap();
712             let mut zero_bytes = 0;
713             self.opaque.file().rewind().unwrap();
714             let file = std::io::BufReader::new(self.opaque.file());
715             for e in file.bytes() {
716                 if e.unwrap() == 0 {
717                     zero_bytes += 1;
718                 }
719             }
720             assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
721 
722             stats.sort_by_key(|&(_, usize)| usize);
723 
724             let prefix = "meta-stats";
725             let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
726 
727             eprintln!("{prefix} METADATA STATS");
728             eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
729             eprintln!("{prefix} ----------------------------------------------------------------");
730             for (label, size) in stats {
731                 eprintln!(
732                     "{} {:<23}{:>10} ({:4.1}%)",
733                     prefix,
734                     label,
735                     to_readable_str(size),
736                     perc(size)
737                 );
738             }
739             eprintln!("{prefix} ----------------------------------------------------------------");
740             eprintln!(
741                 "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
742                 prefix,
743                 "Total",
744                 to_readable_str(total_bytes),
745                 perc(zero_bytes)
746             );
747             eprintln!("{prefix}");
748         }
749 
750         root
751     }
752 }
753 
754 struct AnalyzeAttrState {
755     is_exported: bool,
756     is_doc_hidden: bool,
757 }
758 
759 /// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
760 /// useful in downstream crates. Local-only attributes are an obvious example, but some
761 /// rustdoc-specific attributes can equally be of use while documenting the current crate only.
762 ///
763 /// Removing these superfluous attributes speeds up compilation by making the metadata smaller.
764 ///
765 /// Note: the `is_exported` parameter is used to cache whether the given `DefId` has a public
766 /// visibility: this is a piece of data that can be computed once per defid, and not once per
767 /// attribute. Some attributes would only be usable downstream if they are public.
768 #[inline]
analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool769 fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
770     let mut should_encode = false;
771     if rustc_feature::is_builtin_only_local(attr.name_or_empty()) {
772         // Attributes marked local-only don't need to be encoded for downstream crates.
773     } else if attr.doc_str().is_some() {
774         // We keep all doc comments reachable to rustdoc because they might be "imported" into
775         // downstream crates if they use `#[doc(inline)]` to copy an item's documentation into
776         // their own.
777         if state.is_exported {
778             should_encode = true;
779         }
780     } else if attr.has_name(sym::doc) {
781         // If this is a `doc` attribute that doesn't have anything except maybe `inline` (as in
782         // `#[doc(inline)]`), then we can remove it. It won't be inlinable in downstream crates.
783         if let Some(item_list) = attr.meta_item_list() {
784             for item in item_list {
785                 if !item.has_name(sym::inline) {
786                     should_encode = true;
787                     if item.has_name(sym::hidden) {
788                         state.is_doc_hidden = true;
789                         break;
790                     }
791                 }
792             }
793         }
794     } else {
795         should_encode = true;
796     }
797     should_encode
798 }
799 
should_encode_span(def_kind: DefKind) -> bool800 fn should_encode_span(def_kind: DefKind) -> bool {
801     match def_kind {
802         DefKind::Mod
803         | DefKind::Struct
804         | DefKind::Union
805         | DefKind::Enum
806         | DefKind::Variant
807         | DefKind::Trait
808         | DefKind::TyAlias
809         | DefKind::ForeignTy
810         | DefKind::TraitAlias
811         | DefKind::AssocTy
812         | DefKind::TyParam
813         | DefKind::ConstParam
814         | DefKind::LifetimeParam
815         | DefKind::Fn
816         | DefKind::Const
817         | DefKind::Static(_)
818         | DefKind::Ctor(..)
819         | DefKind::AssocFn
820         | DefKind::AssocConst
821         | DefKind::Macro(_)
822         | DefKind::ExternCrate
823         | DefKind::Use
824         | DefKind::AnonConst
825         | DefKind::InlineConst
826         | DefKind::OpaqueTy
827         | DefKind::ImplTraitPlaceholder
828         | DefKind::Field
829         | DefKind::Impl { .. }
830         | DefKind::Closure
831         | DefKind::Generator => true,
832         DefKind::ForeignMod | DefKind::GlobalAsm => false,
833     }
834 }
835 
should_encode_attrs(def_kind: DefKind) -> bool836 fn should_encode_attrs(def_kind: DefKind) -> bool {
837     match def_kind {
838         DefKind::Mod
839         | DefKind::Struct
840         | DefKind::Union
841         | DefKind::Enum
842         | DefKind::Variant
843         | DefKind::Trait
844         | DefKind::TyAlias
845         | DefKind::ForeignTy
846         | DefKind::TraitAlias
847         | DefKind::AssocTy
848         | DefKind::Fn
849         | DefKind::Const
850         | DefKind::Static(_)
851         | DefKind::AssocFn
852         | DefKind::AssocConst
853         | DefKind::Macro(_)
854         | DefKind::Field
855         | DefKind::Impl { .. } => true,
856         // Tools may want to be able to detect their tool lints on
857         // closures from upstream crates, too. This is used by
858         // https://github.com/model-checking/kani and is not a performance
859         // or maintenance issue for us.
860         DefKind::Closure => true,
861         DefKind::TyParam
862         | DefKind::ConstParam
863         | DefKind::Ctor(..)
864         | DefKind::ExternCrate
865         | DefKind::Use
866         | DefKind::ForeignMod
867         | DefKind::AnonConst
868         | DefKind::InlineConst
869         | DefKind::OpaqueTy
870         | DefKind::ImplTraitPlaceholder
871         | DefKind::LifetimeParam
872         | DefKind::GlobalAsm
873         | DefKind::Generator => false,
874     }
875 }
876 
should_encode_expn_that_defined(def_kind: DefKind) -> bool877 fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
878     match def_kind {
879         DefKind::Mod
880         | DefKind::Struct
881         | DefKind::Union
882         | DefKind::Enum
883         | DefKind::Variant
884         | DefKind::Trait
885         | DefKind::Impl { .. } => true,
886         DefKind::TyAlias
887         | DefKind::ForeignTy
888         | DefKind::TraitAlias
889         | DefKind::AssocTy
890         | DefKind::TyParam
891         | DefKind::Fn
892         | DefKind::Const
893         | DefKind::ConstParam
894         | DefKind::Static(_)
895         | DefKind::Ctor(..)
896         | DefKind::AssocFn
897         | DefKind::AssocConst
898         | DefKind::Macro(_)
899         | DefKind::ExternCrate
900         | DefKind::Use
901         | DefKind::ForeignMod
902         | DefKind::AnonConst
903         | DefKind::InlineConst
904         | DefKind::OpaqueTy
905         | DefKind::ImplTraitPlaceholder
906         | DefKind::Field
907         | DefKind::LifetimeParam
908         | DefKind::GlobalAsm
909         | DefKind::Closure
910         | DefKind::Generator => false,
911     }
912 }
913 
should_encode_visibility(def_kind: DefKind) -> bool914 fn should_encode_visibility(def_kind: DefKind) -> bool {
915     match def_kind {
916         DefKind::Mod
917         | DefKind::Struct
918         | DefKind::Union
919         | DefKind::Enum
920         | DefKind::Variant
921         | DefKind::Trait
922         | DefKind::TyAlias
923         | DefKind::ForeignTy
924         | DefKind::TraitAlias
925         | DefKind::AssocTy
926         | DefKind::Fn
927         | DefKind::Const
928         | DefKind::Static(..)
929         | DefKind::Ctor(..)
930         | DefKind::AssocFn
931         | DefKind::AssocConst
932         | DefKind::Macro(..)
933         | DefKind::Field => true,
934         DefKind::Use
935         | DefKind::ForeignMod
936         | DefKind::TyParam
937         | DefKind::ConstParam
938         | DefKind::LifetimeParam
939         | DefKind::AnonConst
940         | DefKind::InlineConst
941         | DefKind::OpaqueTy
942         | DefKind::ImplTraitPlaceholder
943         | DefKind::GlobalAsm
944         | DefKind::Impl { .. }
945         | DefKind::Closure
946         | DefKind::Generator
947         | DefKind::ExternCrate => false,
948     }
949 }
950 
should_encode_stability(def_kind: DefKind) -> bool951 fn should_encode_stability(def_kind: DefKind) -> bool {
952     match def_kind {
953         DefKind::Mod
954         | DefKind::Ctor(..)
955         | DefKind::Variant
956         | DefKind::Field
957         | DefKind::Struct
958         | DefKind::AssocTy
959         | DefKind::AssocFn
960         | DefKind::AssocConst
961         | DefKind::TyParam
962         | DefKind::ConstParam
963         | DefKind::Static(..)
964         | DefKind::Const
965         | DefKind::Fn
966         | DefKind::ForeignMod
967         | DefKind::TyAlias
968         | DefKind::OpaqueTy
969         | DefKind::ImplTraitPlaceholder
970         | DefKind::Enum
971         | DefKind::Union
972         | DefKind::Impl { .. }
973         | DefKind::Trait
974         | DefKind::TraitAlias
975         | DefKind::Macro(..)
976         | DefKind::ForeignTy => true,
977         DefKind::Use
978         | DefKind::LifetimeParam
979         | DefKind::AnonConst
980         | DefKind::InlineConst
981         | DefKind::GlobalAsm
982         | DefKind::Closure
983         | DefKind::Generator
984         | DefKind::ExternCrate => false,
985     }
986 }
987 
988 /// Whether we should encode MIR.
989 ///
990 /// Computing, optimizing and encoding the MIR is a relatively expensive operation.
991 /// We want to avoid this work when not required. Therefore:
992 /// - we only compute `mir_for_ctfe` on items with const-eval semantics;
993 /// - we skip `optimized_mir` for check runs.
994 ///
995 /// Return a pair, resp. for CTFE and for LLVM.
should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool)996 fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
997     match tcx.def_kind(def_id) {
998         // Constructors
999         DefKind::Ctor(_, _) => {
1000             let mir_opt_base = tcx.sess.opts.output_types.should_codegen()
1001                 || tcx.sess.opts.unstable_opts.always_encode_mir;
1002             (true, mir_opt_base)
1003         }
1004         // Constants
1005         DefKind::AnonConst
1006         | DefKind::InlineConst
1007         | DefKind::AssocConst
1008         | DefKind::Static(..)
1009         | DefKind::Const => (true, false),
1010         // Full-fledged functions + closures
1011         DefKind::AssocFn | DefKind::Fn | DefKind::Closure => {
1012             let generics = tcx.generics_of(def_id);
1013             let needs_inline = (generics.requires_monomorphization(tcx)
1014                 || tcx.codegen_fn_attrs(def_id).requests_inline())
1015                 && tcx.sess.opts.output_types.should_codegen();
1016             // The function has a `const` modifier or is in a `#[const_trait]`.
1017             let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
1018                 || tcx.is_const_default_method(def_id.to_def_id());
1019             let always_encode_mir = tcx.sess.opts.unstable_opts.always_encode_mir;
1020             (is_const_fn, needs_inline || always_encode_mir)
1021         }
1022         // Generators require optimized MIR to compute layout.
1023         DefKind::Generator => (false, true),
1024         // The others don't have MIR.
1025         _ => (false, false),
1026     }
1027 }
1028 
should_encode_variances(def_kind: DefKind) -> bool1029 fn should_encode_variances(def_kind: DefKind) -> bool {
1030     match def_kind {
1031         DefKind::Struct
1032         | DefKind::Union
1033         | DefKind::Enum
1034         | DefKind::Variant
1035         | DefKind::OpaqueTy
1036         | DefKind::ImplTraitPlaceholder
1037         | DefKind::Fn
1038         | DefKind::Ctor(..)
1039         | DefKind::AssocFn => true,
1040         DefKind::Mod
1041         | DefKind::Field
1042         | DefKind::AssocTy
1043         | DefKind::AssocConst
1044         | DefKind::TyParam
1045         | DefKind::ConstParam
1046         | DefKind::Static(..)
1047         | DefKind::Const
1048         | DefKind::ForeignMod
1049         | DefKind::TyAlias
1050         | DefKind::Impl { .. }
1051         | DefKind::Trait
1052         | DefKind::TraitAlias
1053         | DefKind::Macro(..)
1054         | DefKind::ForeignTy
1055         | DefKind::Use
1056         | DefKind::LifetimeParam
1057         | DefKind::AnonConst
1058         | DefKind::InlineConst
1059         | DefKind::GlobalAsm
1060         | DefKind::Closure
1061         | DefKind::Generator
1062         | DefKind::ExternCrate => false,
1063     }
1064 }
1065 
should_encode_generics(def_kind: DefKind) -> bool1066 fn should_encode_generics(def_kind: DefKind) -> bool {
1067     match def_kind {
1068         DefKind::Struct
1069         | DefKind::Union
1070         | DefKind::Enum
1071         | DefKind::Variant
1072         | DefKind::Trait
1073         | DefKind::TyAlias
1074         | DefKind::ForeignTy
1075         | DefKind::TraitAlias
1076         | DefKind::AssocTy
1077         | DefKind::Fn
1078         | DefKind::Const
1079         | DefKind::Static(..)
1080         | DefKind::Ctor(..)
1081         | DefKind::AssocFn
1082         | DefKind::AssocConst
1083         | DefKind::AnonConst
1084         | DefKind::InlineConst
1085         | DefKind::OpaqueTy
1086         | DefKind::ImplTraitPlaceholder
1087         | DefKind::Impl { .. }
1088         | DefKind::Field
1089         | DefKind::TyParam
1090         | DefKind::Closure
1091         | DefKind::Generator => true,
1092         DefKind::Mod
1093         | DefKind::ForeignMod
1094         | DefKind::ConstParam
1095         | DefKind::Macro(..)
1096         | DefKind::Use
1097         | DefKind::LifetimeParam
1098         | DefKind::GlobalAsm
1099         | DefKind::ExternCrate => false,
1100     }
1101 }
1102 
should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> bool1103 fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> bool {
1104     match def_kind {
1105         DefKind::Struct
1106         | DefKind::Union
1107         | DefKind::Enum
1108         | DefKind::Variant
1109         | DefKind::Ctor(..)
1110         | DefKind::Field
1111         | DefKind::Fn
1112         | DefKind::Const
1113         | DefKind::Static(..)
1114         | DefKind::TyAlias
1115         | DefKind::ForeignTy
1116         | DefKind::Impl { .. }
1117         | DefKind::AssocFn
1118         | DefKind::AssocConst
1119         | DefKind::Closure
1120         | DefKind::Generator
1121         | DefKind::ConstParam
1122         | DefKind::AnonConst
1123         | DefKind::InlineConst => true,
1124 
1125         DefKind::OpaqueTy => {
1126             let origin = tcx.opaque_type_origin(def_id);
1127             if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
1128                 && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
1129                 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
1130             {
1131                 false
1132             } else {
1133                 true
1134             }
1135         }
1136 
1137         DefKind::ImplTraitPlaceholder => {
1138             let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
1139             let assoc_item = tcx.associated_item(parent_def_id);
1140             match assoc_item.container {
1141                 // Always encode an RPIT in an impl fn, since it always has a body
1142                 ty::AssocItemContainer::ImplContainer => true,
1143                 ty::AssocItemContainer::TraitContainer => {
1144                     // Encode an RPIT for a trait only if the trait has a default body
1145                     assoc_item.defaultness(tcx).has_value()
1146                 }
1147             }
1148         }
1149 
1150         DefKind::AssocTy => {
1151             let assoc_item = tcx.associated_item(def_id);
1152             match assoc_item.container {
1153                 ty::AssocItemContainer::ImplContainer => true,
1154                 // Always encode RPITITs, since we need to be able to project
1155                 // from an RPITIT associated item to an opaque when installing
1156                 // the default projection predicates in default trait methods
1157                 // with RPITITs.
1158                 ty::AssocItemContainer::TraitContainer => {
1159                     assoc_item.defaultness(tcx).has_value() || assoc_item.opt_rpitit_info.is_some()
1160                 }
1161             }
1162         }
1163         DefKind::TyParam => {
1164             let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(def_id) else { bug!() };
1165             let hir::GenericParamKind::Type { default, .. } = param.kind else { bug!() };
1166             default.is_some()
1167         }
1168 
1169         DefKind::Trait
1170         | DefKind::TraitAlias
1171         | DefKind::Mod
1172         | DefKind::ForeignMod
1173         | DefKind::Macro(..)
1174         | DefKind::Use
1175         | DefKind::LifetimeParam
1176         | DefKind::GlobalAsm
1177         | DefKind::ExternCrate => false,
1178     }
1179 }
1180 
should_encode_fn_sig(def_kind: DefKind) -> bool1181 fn should_encode_fn_sig(def_kind: DefKind) -> bool {
1182     match def_kind {
1183         DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) => true,
1184 
1185         DefKind::Struct
1186         | DefKind::Union
1187         | DefKind::Enum
1188         | DefKind::Variant
1189         | DefKind::Field
1190         | DefKind::Const
1191         | DefKind::Static(..)
1192         | DefKind::Ctor(..)
1193         | DefKind::TyAlias
1194         | DefKind::OpaqueTy
1195         | DefKind::ImplTraitPlaceholder
1196         | DefKind::ForeignTy
1197         | DefKind::Impl { .. }
1198         | DefKind::AssocConst
1199         | DefKind::Closure
1200         | DefKind::Generator
1201         | DefKind::ConstParam
1202         | DefKind::AnonConst
1203         | DefKind::InlineConst
1204         | DefKind::AssocTy
1205         | DefKind::TyParam
1206         | DefKind::Trait
1207         | DefKind::TraitAlias
1208         | DefKind::Mod
1209         | DefKind::ForeignMod
1210         | DefKind::Macro(..)
1211         | DefKind::Use
1212         | DefKind::LifetimeParam
1213         | DefKind::GlobalAsm
1214         | DefKind::ExternCrate => false,
1215     }
1216 }
1217 
should_encode_constness(def_kind: DefKind) -> bool1218 fn should_encode_constness(def_kind: DefKind) -> bool {
1219     match def_kind {
1220         DefKind::Fn
1221         | DefKind::AssocFn
1222         | DefKind::Closure
1223         | DefKind::Impl { of_trait: true }
1224         | DefKind::Variant
1225         | DefKind::Ctor(..) => true,
1226 
1227         DefKind::Struct
1228         | DefKind::Union
1229         | DefKind::Enum
1230         | DefKind::Field
1231         | DefKind::Const
1232         | DefKind::AssocConst
1233         | DefKind::AnonConst
1234         | DefKind::Static(..)
1235         | DefKind::TyAlias
1236         | DefKind::OpaqueTy
1237         | DefKind::Impl { of_trait: false }
1238         | DefKind::ImplTraitPlaceholder
1239         | DefKind::ForeignTy
1240         | DefKind::Generator
1241         | DefKind::ConstParam
1242         | DefKind::InlineConst
1243         | DefKind::AssocTy
1244         | DefKind::TyParam
1245         | DefKind::Trait
1246         | DefKind::TraitAlias
1247         | DefKind::Mod
1248         | DefKind::ForeignMod
1249         | DefKind::Macro(..)
1250         | DefKind::Use
1251         | DefKind::LifetimeParam
1252         | DefKind::GlobalAsm
1253         | DefKind::ExternCrate => false,
1254     }
1255 }
1256 
should_encode_const(def_kind: DefKind) -> bool1257 fn should_encode_const(def_kind: DefKind) -> bool {
1258     match def_kind {
1259         DefKind::Const | DefKind::AssocConst | DefKind::AnonConst | DefKind::InlineConst => true,
1260 
1261         DefKind::Struct
1262         | DefKind::Union
1263         | DefKind::Enum
1264         | DefKind::Variant
1265         | DefKind::Ctor(..)
1266         | DefKind::Field
1267         | DefKind::Fn
1268         | DefKind::Static(..)
1269         | DefKind::TyAlias
1270         | DefKind::OpaqueTy
1271         | DefKind::ImplTraitPlaceholder
1272         | DefKind::ForeignTy
1273         | DefKind::Impl { .. }
1274         | DefKind::AssocFn
1275         | DefKind::Closure
1276         | DefKind::Generator
1277         | DefKind::ConstParam
1278         | DefKind::AssocTy
1279         | DefKind::TyParam
1280         | DefKind::Trait
1281         | DefKind::TraitAlias
1282         | DefKind::Mod
1283         | DefKind::ForeignMod
1284         | DefKind::Macro(..)
1285         | DefKind::Use
1286         | DefKind::LifetimeParam
1287         | DefKind::GlobalAsm
1288         | DefKind::ExternCrate => false,
1289     }
1290 }
1291 
1292 // We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
1293 // option.
should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool1294 fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
1295     if tcx.lower_impl_trait_in_trait_to_assoc_ty()
1296         && let Some(assoc_item) = tcx.opt_associated_item(def_id)
1297         && assoc_item.container == ty::AssocItemContainer::TraitContainer
1298         && assoc_item.kind == ty::AssocKind::Fn
1299     {
1300         true
1301     } else {
1302         false
1303     }
1304 }
1305 
1306 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
encode_attrs(&mut self, def_id: LocalDefId)1307     fn encode_attrs(&mut self, def_id: LocalDefId) {
1308         let tcx = self.tcx;
1309         let mut state = AnalyzeAttrState {
1310             is_exported: tcx.effective_visibilities(()).is_exported(def_id),
1311             is_doc_hidden: false,
1312         };
1313         let attr_iter = tcx
1314             .opt_local_def_id_to_hir_id(def_id)
1315             .map_or(Default::default(), |hir_id| tcx.hir().attrs(hir_id))
1316             .iter()
1317             .filter(|attr| analyze_attr(attr, &mut state));
1318 
1319         record_array!(self.tables.attributes[def_id.to_def_id()] <- attr_iter);
1320 
1321         let mut attr_flags = AttrFlags::empty();
1322         if state.is_doc_hidden {
1323             attr_flags |= AttrFlags::IS_DOC_HIDDEN;
1324         }
1325         self.tables.attr_flags.set(def_id.local_def_index, attr_flags);
1326     }
1327 
encode_def_ids(&mut self)1328     fn encode_def_ids(&mut self) {
1329         self.encode_info_for_mod(CRATE_DEF_ID);
1330 
1331         // Proc-macro crates only export proc-macro items, which are looked
1332         // up using `proc_macro_data`
1333         if self.is_proc_macro {
1334             return;
1335         }
1336 
1337         let tcx = self.tcx;
1338 
1339         for local_id in tcx.iter_local_def_id() {
1340             let def_id = local_id.to_def_id();
1341             let def_kind = tcx.opt_def_kind(local_id);
1342             let Some(def_kind) = def_kind else { continue };
1343             self.tables.opt_def_kind.set_some(def_id.index, def_kind);
1344             if should_encode_span(def_kind) {
1345                 let def_span = tcx.def_span(local_id);
1346                 record!(self.tables.def_span[def_id] <- def_span);
1347             }
1348             if should_encode_attrs(def_kind) {
1349                 self.encode_attrs(local_id);
1350             }
1351             if should_encode_expn_that_defined(def_kind) {
1352                 record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
1353             }
1354             if should_encode_span(def_kind) && let Some(ident_span) = tcx.def_ident_span(def_id) {
1355                 record!(self.tables.def_ident_span[def_id] <- ident_span);
1356             }
1357             if def_kind.has_codegen_attrs() {
1358                 record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
1359             }
1360             if should_encode_visibility(def_kind) {
1361                 let vis =
1362                     self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index);
1363                 record!(self.tables.visibility[def_id] <- vis);
1364             }
1365             if should_encode_stability(def_kind) {
1366                 self.encode_stability(def_id);
1367                 self.encode_const_stability(def_id);
1368                 self.encode_default_body_stability(def_id);
1369                 self.encode_deprecation(def_id);
1370             }
1371             if should_encode_variances(def_kind) {
1372                 let v = self.tcx.variances_of(def_id);
1373                 record_array!(self.tables.variances_of[def_id] <- v);
1374             }
1375             if should_encode_fn_sig(def_kind) {
1376                 record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
1377             }
1378             if should_encode_generics(def_kind) {
1379                 let g = tcx.generics_of(def_id);
1380                 record!(self.tables.generics_of[def_id] <- g);
1381                 record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
1382                 let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
1383                 record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
1384 
1385                 for param in &g.params {
1386                     if let ty::GenericParamDefKind::Const { has_default: true, .. } = param.kind {
1387                         let default = self.tcx.const_param_default(param.def_id);
1388                         record!(self.tables.const_param_default[param.def_id] <- default);
1389                     }
1390                 }
1391             }
1392             if should_encode_type(tcx, local_id, def_kind) {
1393                 record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
1394             }
1395             if should_encode_constness(def_kind) {
1396                 self.tables.constness.set_some(def_id.index, self.tcx.constness(def_id));
1397             }
1398             if let DefKind::Fn | DefKind::AssocFn = def_kind {
1399                 self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id));
1400                 record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
1401                 self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
1402             }
1403             if let DefKind::TyParam = def_kind {
1404                 let default = self.tcx.object_lifetime_default(def_id);
1405                 record!(self.tables.object_lifetime_default[def_id] <- default);
1406             }
1407             if let DefKind::Trait = def_kind {
1408                 record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
1409                 record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
1410 
1411                 let module_children = self.tcx.module_children_local(local_id);
1412                 record_array!(self.tables.module_children_non_reexports[def_id] <-
1413                     module_children.iter().map(|child| child.res.def_id().index));
1414             }
1415             if let DefKind::TraitAlias = def_kind {
1416                 record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
1417                 record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
1418                 record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id));
1419             }
1420             if let DefKind::Trait | DefKind::Impl { .. } = def_kind {
1421                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
1422                 record_array!(self.tables.associated_item_or_field_def_ids[def_id] <-
1423                     associated_item_def_ids.iter().map(|&def_id| {
1424                         assert!(def_id.is_local());
1425                         def_id.index
1426                     })
1427                 );
1428                 for &def_id in associated_item_def_ids {
1429                     self.encode_info_for_assoc_item(def_id);
1430                 }
1431             }
1432             if let DefKind::Generator = def_kind {
1433                 self.encode_info_for_generator(local_id);
1434             }
1435             if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
1436                 self.encode_info_for_adt(local_id);
1437             }
1438             if let DefKind::Mod = def_kind {
1439                 self.encode_info_for_mod(local_id);
1440             }
1441             if let DefKind::Macro(_) = def_kind {
1442                 self.encode_info_for_macro(local_id);
1443             }
1444             if let DefKind::OpaqueTy = def_kind {
1445                 self.encode_explicit_item_bounds(def_id);
1446                 self.tables
1447                     .is_type_alias_impl_trait
1448                     .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
1449             }
1450             if let DefKind::ImplTraitPlaceholder = def_kind {
1451                 self.encode_explicit_item_bounds(def_id);
1452             }
1453             if tcx.impl_method_has_trait_impl_trait_tys(def_id)
1454                 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
1455             {
1456                 record!(self.tables.trait_impl_trait_tys[def_id] <- table);
1457             }
1458             if should_encode_fn_impl_trait_in_trait(tcx, def_id) {
1459                 let table = tcx.associated_types_for_impl_traits_in_associated_fn(def_id);
1460                 record_defaulted_array!(self.tables.associated_types_for_impl_traits_in_associated_fn[def_id] <- table);
1461             }
1462         }
1463 
1464         let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
1465             tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)
1466         });
1467         for (def_id, impls) in inherent_impls {
1468             record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
1469                 assert!(def_id.is_local());
1470                 def_id.index
1471             }));
1472         }
1473 
1474         for (def_id, res_map) in &tcx.resolutions(()).doc_link_resolutions {
1475             record!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map);
1476         }
1477 
1478         for (def_id, traits) in &tcx.resolutions(()).doc_link_traits_in_scope {
1479             record_array!(self.tables.doc_link_traits_in_scope[def_id.to_def_id()] <- traits);
1480         }
1481     }
1482 
1483     #[instrument(level = "trace", skip(self))]
encode_info_for_adt(&mut self, local_def_id: LocalDefId)1484     fn encode_info_for_adt(&mut self, local_def_id: LocalDefId) {
1485         let def_id = local_def_id.to_def_id();
1486         let tcx = self.tcx;
1487         let adt_def = tcx.adt_def(def_id);
1488         record!(self.tables.repr_options[def_id] <- adt_def.repr());
1489 
1490         let params_in_repr = self.tcx.params_in_repr(def_id);
1491         record!(self.tables.params_in_repr[def_id] <- params_in_repr);
1492 
1493         if adt_def.is_enum() {
1494             let module_children = tcx.module_children_local(local_def_id);
1495             record_array!(self.tables.module_children_non_reexports[def_id] <-
1496                 module_children.iter().map(|child| child.res.def_id().index));
1497         } else {
1498             // For non-enum, there is only one variant, and its def_id is the adt's.
1499             debug_assert_eq!(adt_def.variants().len(), 1);
1500             debug_assert_eq!(adt_def.non_enum_variant().def_id, def_id);
1501             // Therefore, the loop over variants will encode its fields as the adt's children.
1502         }
1503 
1504         for (idx, variant) in adt_def.variants().iter_enumerated() {
1505             let data = VariantData {
1506                 discr: variant.discr,
1507                 idx,
1508                 ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
1509                 is_non_exhaustive: variant.is_field_list_non_exhaustive(),
1510             };
1511             record!(self.tables.variant_data[variant.def_id] <- data);
1512 
1513             record_array!(self.tables.associated_item_or_field_def_ids[variant.def_id] <- variant.fields.iter().map(|f| {
1514                 assert!(f.did.is_local());
1515                 f.did.index
1516             }));
1517 
1518             if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
1519                 let fn_sig = tcx.fn_sig(ctor_def_id);
1520                 // FIXME only encode signature for ctor_def_id
1521                 record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
1522             }
1523         }
1524     }
1525 
1526     #[instrument(level = "debug", skip(self))]
encode_info_for_mod(&mut self, local_def_id: LocalDefId)1527     fn encode_info_for_mod(&mut self, local_def_id: LocalDefId) {
1528         let tcx = self.tcx;
1529         let def_id = local_def_id.to_def_id();
1530 
1531         // If we are encoding a proc-macro crates, `encode_info_for_mod` will
1532         // only ever get called for the crate root. We still want to encode
1533         // the crate root for consistency with other crates (some of the resolver
1534         // code uses it). However, we skip encoding anything relating to child
1535         // items - we encode information about proc-macros later on.
1536         if self.is_proc_macro {
1537             // Encode this here because we don't do it in encode_def_ids.
1538             record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
1539         } else {
1540             let module_children = tcx.module_children_local(local_def_id);
1541 
1542             record_array!(self.tables.module_children_non_reexports[def_id] <-
1543                 module_children.iter().filter(|child| child.reexport_chain.is_empty())
1544                     .map(|child| child.res.def_id().index));
1545 
1546             record_defaulted_array!(self.tables.module_children_reexports[def_id] <-
1547                 module_children.iter().filter(|child| !child.reexport_chain.is_empty()));
1548         }
1549     }
1550 
encode_explicit_item_bounds(&mut self, def_id: DefId)1551     fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
1552         debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
1553         let bounds = self.tcx.explicit_item_bounds(def_id).skip_binder();
1554         record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
1555     }
1556 
1557     #[instrument(level = "debug", skip(self))]
encode_info_for_assoc_item(&mut self, def_id: DefId)1558     fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
1559         let tcx = self.tcx;
1560         let item = tcx.associated_item(def_id);
1561 
1562         self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
1563         self.tables.assoc_container.set_some(def_id.index, item.container);
1564 
1565         match item.container {
1566             AssocItemContainer::TraitContainer => {
1567                 if let ty::AssocKind::Type = item.kind {
1568                     self.encode_explicit_item_bounds(def_id);
1569                 }
1570             }
1571             AssocItemContainer::ImplContainer => {
1572                 if let Some(trait_item_def_id) = item.trait_item_def_id {
1573                     self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
1574                 }
1575             }
1576         }
1577         if let Some(rpitit_info) = item.opt_rpitit_info {
1578             record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info);
1579         }
1580     }
1581 
encode_mir(&mut self)1582     fn encode_mir(&mut self) {
1583         if self.is_proc_macro {
1584             return;
1585         }
1586 
1587         let tcx = self.tcx;
1588 
1589         let keys_and_jobs = tcx.mir_keys(()).iter().filter_map(|&def_id| {
1590             let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
1591             if encode_const || encode_opt { Some((def_id, encode_const, encode_opt)) } else { None }
1592         });
1593         for (def_id, encode_const, encode_opt) in keys_and_jobs {
1594             debug_assert!(encode_const || encode_opt);
1595 
1596             debug!("EntryBuilder::encode_mir({:?})", def_id);
1597             if encode_opt {
1598                 record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
1599                 record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
1600                     <- tcx.closure_saved_names_of_captured_variables(def_id));
1601 
1602                 if tcx.sess.opts.unstable_opts.drop_tracking_mir
1603                     && let DefKind::Generator = self.tcx.def_kind(def_id)
1604                     && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
1605                 {
1606                     record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
1607                 }
1608             }
1609             if encode_const {
1610                 record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id));
1611 
1612                 // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
1613                 let abstract_const = tcx.thir_abstract_const(def_id);
1614                 if let Ok(Some(abstract_const)) = abstract_const {
1615                     record!(self.tables.thir_abstract_const[def_id.to_def_id()] <- abstract_const);
1616                 }
1617 
1618                 if should_encode_const(tcx.def_kind(def_id)) {
1619                     let qualifs = tcx.mir_const_qualif(def_id);
1620                     record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs);
1621                     let body_id = tcx.hir().maybe_body_owned_by(def_id);
1622                     if let Some(body_id) = body_id {
1623                         let const_data = self.encode_rendered_const_for_body(body_id);
1624                         record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data);
1625                     }
1626                 }
1627             }
1628             record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
1629 
1630             let instance = ty::InstanceDef::Item(def_id.to_def_id());
1631             let unused = tcx.unused_generic_params(instance);
1632             self.tables.unused_generic_params.set(def_id.local_def_index, unused);
1633         }
1634 
1635         // Encode all the deduced parameter attributes for everything that has MIR, even for items
1636         // that can't be inlined. But don't if we aren't optimizing in non-incremental mode, to
1637         // save the query traffic.
1638         if tcx.sess.opts.output_types.should_codegen()
1639             && tcx.sess.opts.optimize != OptLevel::No
1640             && tcx.sess.opts.incremental.is_none()
1641         {
1642             for &local_def_id in tcx.mir_keys(()) {
1643                 if let DefKind::AssocFn | DefKind::Fn = tcx.def_kind(local_def_id) {
1644                     record_array!(self.tables.deduced_param_attrs[local_def_id.to_def_id()] <-
1645                         self.tcx.deduced_param_attrs(local_def_id.to_def_id()));
1646                 }
1647             }
1648         }
1649     }
1650 
1651     #[instrument(level = "debug", skip(self))]
encode_stability(&mut self, def_id: DefId)1652     fn encode_stability(&mut self, def_id: DefId) {
1653         // The query lookup can take a measurable amount of time in crates with many items. Check if
1654         // the stability attributes are even enabled before using their queries.
1655         if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
1656             if let Some(stab) = self.tcx.lookup_stability(def_id) {
1657                 record!(self.tables.lookup_stability[def_id] <- stab)
1658             }
1659         }
1660     }
1661 
1662     #[instrument(level = "debug", skip(self))]
encode_const_stability(&mut self, def_id: DefId)1663     fn encode_const_stability(&mut self, def_id: DefId) {
1664         // The query lookup can take a measurable amount of time in crates with many items. Check if
1665         // the stability attributes are even enabled before using their queries.
1666         if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
1667             if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
1668                 record!(self.tables.lookup_const_stability[def_id] <- stab)
1669             }
1670         }
1671     }
1672 
1673     #[instrument(level = "debug", skip(self))]
encode_default_body_stability(&mut self, def_id: DefId)1674     fn encode_default_body_stability(&mut self, def_id: DefId) {
1675         // The query lookup can take a measurable amount of time in crates with many items. Check if
1676         // the stability attributes are even enabled before using their queries.
1677         if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
1678             if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) {
1679                 record!(self.tables.lookup_default_body_stability[def_id] <- stab)
1680             }
1681         }
1682     }
1683 
1684     #[instrument(level = "debug", skip(self))]
encode_deprecation(&mut self, def_id: DefId)1685     fn encode_deprecation(&mut self, def_id: DefId) {
1686         if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
1687             record!(self.tables.lookup_deprecation_entry[def_id] <- depr);
1688         }
1689     }
1690 
encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> String1691     fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> String {
1692         let hir = self.tcx.hir();
1693         let body = hir.body(body_id);
1694         rustc_hir_pretty::to_string(&(&hir as &dyn intravisit::Map<'_>), |s| {
1695             s.print_expr(&body.value)
1696         })
1697     }
1698 
1699     #[instrument(level = "debug", skip(self))]
encode_info_for_macro(&mut self, def_id: LocalDefId)1700     fn encode_info_for_macro(&mut self, def_id: LocalDefId) {
1701         let tcx = self.tcx;
1702 
1703         let hir::ItemKind::Macro(ref macro_def, _) = tcx.hir().expect_item(def_id).kind else { bug!() };
1704         self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules);
1705         record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
1706     }
1707 
1708     #[instrument(level = "debug", skip(self))]
encode_info_for_generator(&mut self, def_id: LocalDefId)1709     fn encode_info_for_generator(&mut self, def_id: LocalDefId) {
1710         let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
1711         let data = self.tcx.generator_kind(def_id).unwrap();
1712         let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data();
1713         record!(self.tables.generator_kind[def_id.to_def_id()] <- data);
1714         record!(self.tables.generator_diagnostic_data[def_id.to_def_id()]  <- generator_diagnostic_data);
1715     }
1716 
encode_native_libraries(&mut self) -> LazyArray<NativeLib>1717     fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
1718         empty_proc_macro!(self);
1719         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1720         self.lazy_array(used_libraries.iter())
1721     }
1722 
encode_foreign_modules(&mut self) -> LazyArray<ForeignModule>1723     fn encode_foreign_modules(&mut self) -> LazyArray<ForeignModule> {
1724         empty_proc_macro!(self);
1725         let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
1726         self.lazy_array(foreign_modules.iter().map(|(_, m)| m).cloned())
1727     }
1728 
encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable)1729     fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
1730         let mut syntax_contexts: TableBuilder<_, _> = Default::default();
1731         let mut expn_data_table: TableBuilder<_, _> = Default::default();
1732         let mut expn_hash_table: TableBuilder<_, _> = Default::default();
1733 
1734         self.hygiene_ctxt.encode(
1735             &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
1736             |(this, syntax_contexts, _, _), index, ctxt_data| {
1737                 syntax_contexts.set_some(index, this.lazy(ctxt_data));
1738             },
1739             |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
1740                 if let Some(index) = index.as_local() {
1741                     expn_data_table.set_some(index.as_raw(), this.lazy(expn_data));
1742                     expn_hash_table.set_some(index.as_raw(), this.lazy(hash));
1743                 }
1744             },
1745         );
1746 
1747         (
1748             syntax_contexts.encode(&mut self.opaque),
1749             expn_data_table.encode(&mut self.opaque),
1750             expn_hash_table.encode(&mut self.opaque),
1751         )
1752     }
1753 
encode_proc_macros(&mut self) -> Option<ProcMacroData>1754     fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
1755         let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
1756         if is_proc_macro {
1757             let tcx = self.tcx;
1758             let hir = tcx.hir();
1759 
1760             let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
1761             let stability = tcx.lookup_stability(CRATE_DEF_ID);
1762             let macros =
1763                 self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
1764             for (i, span) in self.tcx.sess.parse_sess.proc_macro_quoted_spans() {
1765                 let span = self.lazy(span);
1766                 self.tables.proc_macro_quoted_spans.set_some(i, span);
1767             }
1768 
1769             self.tables.opt_def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
1770             record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
1771             self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local());
1772             let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index);
1773             record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- vis);
1774             if let Some(stability) = stability {
1775                 record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
1776             }
1777             self.encode_deprecation(LOCAL_CRATE.as_def_id());
1778             if let Some(res_map) = tcx.resolutions(()).doc_link_resolutions.get(&CRATE_DEF_ID) {
1779                 record!(self.tables.doc_link_resolutions[LOCAL_CRATE.as_def_id()] <- res_map);
1780             }
1781             if let Some(traits) = tcx.resolutions(()).doc_link_traits_in_scope.get(&CRATE_DEF_ID) {
1782                 record_array!(self.tables.doc_link_traits_in_scope[LOCAL_CRATE.as_def_id()] <- traits);
1783             }
1784 
1785             // Normally, this information is encoded when we walk the items
1786             // defined in this crate. However, we skip doing that for proc-macro crates,
1787             // so we manually encode just the information that we need
1788             for &proc_macro in &tcx.resolutions(()).proc_macros {
1789                 let id = proc_macro;
1790                 let proc_macro = hir.local_def_id_to_hir_id(proc_macro);
1791                 let mut name = hir.name(proc_macro);
1792                 let span = hir.span(proc_macro);
1793                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1794                 // so downstream crates need access to them.
1795                 let attrs = hir.attrs(proc_macro);
1796                 let macro_kind = if attr::contains_name(attrs, sym::proc_macro) {
1797                     MacroKind::Bang
1798                 } else if attr::contains_name(attrs, sym::proc_macro_attribute) {
1799                     MacroKind::Attr
1800                 } else if let Some(attr) = attr::find_by_name(attrs, sym::proc_macro_derive) {
1801                     // This unwrap chain should have been checked by the proc-macro harness.
1802                     name = attr.meta_item_list().unwrap()[0]
1803                         .meta_item()
1804                         .unwrap()
1805                         .ident()
1806                         .unwrap()
1807                         .name;
1808                     MacroKind::Derive
1809                 } else {
1810                     bug!("Unknown proc-macro type for item {:?}", id);
1811                 };
1812 
1813                 let mut def_key = self.tcx.hir().def_key(id);
1814                 def_key.disambiguated_data.data = DefPathData::MacroNs(name);
1815 
1816                 let def_id = id.to_def_id();
1817                 self.tables.opt_def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
1818                 self.tables.proc_macro.set_some(def_id.index, macro_kind);
1819                 self.encode_attrs(id);
1820                 record!(self.tables.def_keys[def_id] <- def_key);
1821                 record!(self.tables.def_ident_span[def_id] <- span);
1822                 record!(self.tables.def_span[def_id] <- span);
1823                 record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
1824                 if let Some(stability) = stability {
1825                     record!(self.tables.lookup_stability[def_id] <- stability);
1826                 }
1827             }
1828 
1829             Some(ProcMacroData { proc_macro_decls_static, stability, macros })
1830         } else {
1831             None
1832         }
1833     }
1834 
encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile>1835     fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
1836         empty_proc_macro!(self);
1837         self.lazy_array(
1838             self.tcx
1839                 .debugger_visualizers(LOCAL_CRATE)
1840                 .iter()
1841                 // Erase the path since it may contain privacy sensitive data
1842                 // that we don't want to end up in crate metadata.
1843                 // The path is only needed for the local crate because of
1844                 // `--emit dep-info`.
1845                 .map(DebuggerVisualizerFile::path_erased),
1846         )
1847     }
1848 
encode_crate_deps(&mut self) -> LazyArray<CrateDep>1849     fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
1850         empty_proc_macro!(self);
1851 
1852         let deps = self
1853             .tcx
1854             .crates(())
1855             .iter()
1856             .map(|&cnum| {
1857                 let dep = CrateDep {
1858                     name: self.tcx.crate_name(cnum),
1859                     hash: self.tcx.crate_hash(cnum),
1860                     host_hash: self.tcx.crate_host_hash(cnum),
1861                     kind: self.tcx.dep_kind(cnum),
1862                     extra_filename: self.tcx.extra_filename(cnum).clone(),
1863                     is_private: self.tcx.is_private_dep(cnum),
1864                 };
1865                 (cnum, dep)
1866             })
1867             .collect::<Vec<_>>();
1868 
1869         {
1870             // Sanity-check the crate numbers
1871             let mut expected_cnum = 1;
1872             for &(n, _) in &deps {
1873                 assert_eq!(n, CrateNum::new(expected_cnum));
1874                 expected_cnum += 1;
1875             }
1876         }
1877 
1878         // We're just going to write a list of crate 'name-hash-version's, with
1879         // the assumption that they are numbered 1 to n.
1880         // FIXME (#2166): This is not nearly enough to support correct versioning
1881         // but is enough to get transitive crate dependencies working.
1882         self.lazy_array(deps.iter().map(|(_, dep)| dep))
1883     }
1884 
encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)>1885     fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
1886         empty_proc_macro!(self);
1887         let tcx = self.tcx;
1888         let lib_features = tcx.lib_features(());
1889         self.lazy_array(lib_features.to_vec())
1890     }
1891 
encode_stability_implications(&mut self) -> LazyArray<(Symbol, Symbol)>1892     fn encode_stability_implications(&mut self) -> LazyArray<(Symbol, Symbol)> {
1893         empty_proc_macro!(self);
1894         let tcx = self.tcx;
1895         let implications = tcx.stability_implications(LOCAL_CRATE);
1896         self.lazy_array(implications.iter().map(|(k, v)| (*k, *v)))
1897     }
1898 
encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)>1899     fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
1900         empty_proc_macro!(self);
1901         let tcx = self.tcx;
1902         let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id;
1903         self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
1904     }
1905 
encode_lang_items(&mut self) -> LazyArray<(DefIndex, LangItem)>1906     fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, LangItem)> {
1907         empty_proc_macro!(self);
1908         let lang_items = self.tcx.lang_items().iter();
1909         self.lazy_array(lang_items.filter_map(|(lang_item, def_id)| {
1910             def_id.as_local().map(|id| (id.local_def_index, lang_item))
1911         }))
1912     }
1913 
encode_lang_items_missing(&mut self) -> LazyArray<LangItem>1914     fn encode_lang_items_missing(&mut self) -> LazyArray<LangItem> {
1915         empty_proc_macro!(self);
1916         let tcx = self.tcx;
1917         self.lazy_array(&tcx.lang_items().missing)
1918     }
1919 
encode_stripped_cfg_items(&mut self) -> LazyArray<StrippedCfgItem<DefIndex>>1920     fn encode_stripped_cfg_items(&mut self) -> LazyArray<StrippedCfgItem<DefIndex>> {
1921         self.lazy_array(
1922             self.tcx
1923                 .stripped_cfg_items(LOCAL_CRATE)
1924                 .into_iter()
1925                 .map(|item| item.clone().map_mod_id(|def_id| def_id.index)),
1926         )
1927     }
1928 
encode_traits(&mut self) -> LazyArray<DefIndex>1929     fn encode_traits(&mut self) -> LazyArray<DefIndex> {
1930         empty_proc_macro!(self);
1931         self.lazy_array(self.tcx.traits(LOCAL_CRATE).iter().map(|def_id| def_id.index))
1932     }
1933 
1934     /// Encodes an index, mapping each trait to its (local) implementations.
1935     #[instrument(level = "debug", skip(self))]
encode_impls(&mut self) -> LazyArray<TraitImpls>1936     fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
1937         empty_proc_macro!(self);
1938         let tcx = self.tcx;
1939         let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
1940             FxHashMap::default();
1941 
1942         for id in tcx.hir().items() {
1943             let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else { continue; };
1944             let def_id = id.owner_id.to_def_id();
1945 
1946             self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
1947             self.tables.impl_polarity.set_some(def_id.index, tcx.impl_polarity(def_id));
1948 
1949             if of_trait && let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
1950                 record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
1951 
1952                 let trait_ref = trait_ref.subst_identity();
1953                 let simplified_self_ty =
1954                     fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey);
1955                 fx_hash_map
1956                     .entry(trait_ref.def_id)
1957                     .or_default()
1958                     .push((id.owner_id.def_id.local_def_index, simplified_self_ty));
1959 
1960                 let trait_def = tcx.trait_def(trait_ref.def_id);
1961                 if let Some(mut an) = trait_def.ancestors(tcx, def_id).ok() {
1962                     if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
1963                         self.tables.impl_parent.set_some(def_id.index, parent.into());
1964                     }
1965                 }
1966 
1967                 // if this is an impl of `CoerceUnsized`, create its
1968                 // "unsized info", else just store None
1969                 if Some(trait_ref.def_id) == tcx.lang_items().coerce_unsized_trait() {
1970                     let coerce_unsized_info = tcx.coerce_unsized_info(def_id);
1971                     record!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info);
1972                 }
1973             }
1974         }
1975 
1976         let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();
1977 
1978         // Bring everything into deterministic order for hashing
1979         all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
1980 
1981         let all_impls: Vec<_> = all_impls
1982             .into_iter()
1983             .map(|(trait_def_id, mut impls)| {
1984                 // Bring everything into deterministic order for hashing
1985                 impls.sort_by_cached_key(|&(index, _)| {
1986                     tcx.hir().def_path_hash(LocalDefId { local_def_index: index })
1987                 });
1988 
1989                 TraitImpls {
1990                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
1991                     impls: self.lazy_array(&impls),
1992                 }
1993             })
1994             .collect();
1995 
1996         self.lazy_array(&all_impls)
1997     }
1998 
1999     #[instrument(level = "debug", skip(self))]
encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls>2000     fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
2001         empty_proc_macro!(self);
2002         let tcx = self.tcx;
2003         let mut all_impls: Vec<_> = tcx.crate_inherent_impls(()).incoherent_impls.iter().collect();
2004         tcx.with_stable_hashing_context(|mut ctx| {
2005             all_impls.sort_by_cached_key(|&(&simp, _)| {
2006                 let mut hasher = StableHasher::new();
2007                 simp.hash_stable(&mut ctx, &mut hasher);
2008                 hasher.finish::<Fingerprint>()
2009             })
2010         });
2011         let all_impls: Vec<_> = all_impls
2012             .into_iter()
2013             .map(|(&simp, impls)| {
2014                 let mut impls: Vec<_> =
2015                     impls.into_iter().map(|def_id| def_id.local_def_index).collect();
2016                 impls.sort_by_cached_key(|&local_def_index| {
2017                     tcx.hir().def_path_hash(LocalDefId { local_def_index })
2018                 });
2019 
2020                 IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
2021             })
2022             .collect();
2023 
2024         self.lazy_array(&all_impls)
2025     }
2026 
2027     // Encodes all symbols exported from this crate into the metadata.
2028     //
2029     // This pass is seeded off the reachability list calculated in the
2030     // middle::reachable module but filters out items that either don't have a
2031     // symbol associated with them (they weren't translated) or if they're an FFI
2032     // definition (as that's not defined in this crate).
encode_exported_symbols( &mut self, exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)], ) -> LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>2033     fn encode_exported_symbols(
2034         &mut self,
2035         exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)],
2036     ) -> LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)> {
2037         empty_proc_macro!(self);
2038         // The metadata symbol name is special. It should not show up in
2039         // downstream crates.
2040         let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx));
2041 
2042         self.lazy_array(
2043             exported_symbols
2044                 .iter()
2045                 .filter(|&(exported_symbol, _)| match *exported_symbol {
2046                     ExportedSymbol::NoDefId(symbol_name) => symbol_name != metadata_symbol_name,
2047                     _ => true,
2048                 })
2049                 .cloned(),
2050         )
2051     }
2052 
encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>>2053     fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> {
2054         empty_proc_macro!(self);
2055         let formats = self.tcx.dependency_formats(());
2056         for (ty, arr) in formats.iter() {
2057             if *ty != CrateType::Dylib {
2058                 continue;
2059             }
2060             return self.lazy_array(arr.iter().map(|slot| match *slot {
2061                 Linkage::NotLinked | Linkage::IncludedFromDylib => None,
2062 
2063                 Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
2064                 Linkage::Static => Some(LinkagePreference::RequireStatic),
2065             }));
2066         }
2067         LazyArray::default()
2068     }
2069 }
2070 
2071 /// Used to prefetch queries which will be needed later by metadata encoding.
2072 /// Only a subset of the queries are actually prefetched to keep this code smaller.
prefetch_mir(tcx: TyCtxt<'_>)2073 fn prefetch_mir(tcx: TyCtxt<'_>) {
2074     if !tcx.sess.opts.output_types.should_codegen() {
2075         // We won't emit MIR, so don't prefetch it.
2076         return;
2077     }
2078 
2079     par_for_each_in(tcx.mir_keys(()), |&def_id| {
2080         let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
2081 
2082         if encode_const {
2083             tcx.ensure_with_value().mir_for_ctfe(def_id);
2084         }
2085         if encode_opt {
2086             tcx.ensure_with_value().optimized_mir(def_id);
2087         }
2088         if encode_opt || encode_const {
2089             tcx.ensure_with_value().promoted_mir(def_id);
2090         }
2091     })
2092 }
2093 
2094 // NOTE(eddyb) The following comment was preserved for posterity, even
2095 // though it's no longer relevant as EBML (which uses nested & tagged
2096 // "documents") was replaced with a scheme that can't go out of bounds.
2097 //
2098 // And here we run into yet another obscure archive bug: in which metadata
2099 // loaded from archives may have trailing garbage bytes. Awhile back one of
2100 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
2101 // and opt) by having ebml generate an out-of-bounds panic when looking at
2102 // metadata.
2103 //
2104 // Upon investigation it turned out that the metadata file inside of an rlib
2105 // (and ar archive) was being corrupted. Some compilations would generate a
2106 // metadata file which would end in a few extra bytes, while other
2107 // compilations would not have these extra bytes appended to the end. These
2108 // extra bytes were interpreted by ebml as an extra tag, so they ended up
2109 // being interpreted causing the out-of-bounds.
2110 //
2111 // The root cause of why these extra bytes were appearing was never
2112 // discovered, and in the meantime the solution we're employing is to insert
2113 // the length of the metadata to the start of the metadata. Later on this
2114 // will allow us to slice the metadata to the precise length that we just
2115 // generated regardless of trailing bytes that end up in it.
2116 
2117 pub struct EncodedMetadata {
2118     // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2119     mmap: Option<Mmap>,
2120     // We need to carry MaybeTempDir to avoid deleting the temporary
2121     // directory while accessing the Mmap.
2122     _temp_dir: Option<MaybeTempDir>,
2123 }
2124 
2125 impl EncodedMetadata {
2126     #[inline]
from_path(path: PathBuf, temp_dir: Option<MaybeTempDir>) -> std::io::Result<Self>2127     pub fn from_path(path: PathBuf, temp_dir: Option<MaybeTempDir>) -> std::io::Result<Self> {
2128         let file = std::fs::File::open(&path)?;
2129         let file_metadata = file.metadata()?;
2130         if file_metadata.len() == 0 {
2131             return Ok(Self { mmap: None, _temp_dir: None });
2132         }
2133         let mmap = unsafe { Some(Mmap::map(file)?) };
2134         Ok(Self { mmap, _temp_dir: temp_dir })
2135     }
2136 
2137     #[inline]
raw_data(&self) -> &[u8]2138     pub fn raw_data(&self) -> &[u8] {
2139         self.mmap.as_deref().unwrap_or_default()
2140     }
2141 }
2142 
2143 impl<S: Encoder> Encodable<S> for EncodedMetadata {
encode(&self, s: &mut S)2144     fn encode(&self, s: &mut S) {
2145         let slice = self.raw_data();
2146         slice.encode(s)
2147     }
2148 }
2149 
2150 impl<D: Decoder> Decodable<D> for EncodedMetadata {
decode(d: &mut D) -> Self2151     fn decode(d: &mut D) -> Self {
2152         let len = d.read_usize();
2153         let mmap = if len > 0 {
2154             let mut mmap = MmapMut::map_anon(len).unwrap();
2155             for _ in 0..len {
2156                 (&mut mmap[..]).write(&[d.read_u8()]).unwrap();
2157             }
2158             mmap.flush().unwrap();
2159             Some(mmap.make_read_only().unwrap())
2160         } else {
2161             None
2162         };
2163 
2164         Self { mmap, _temp_dir: None }
2165     }
2166 }
2167 
encode_metadata(tcx: TyCtxt<'_>, path: &Path)2168 pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
2169     let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
2170 
2171     // Since encoding metadata is not in a query, and nothing is cached,
2172     // there's no need to do dep-graph tracking for any of it.
2173     tcx.dep_graph.assert_ignored();
2174 
2175     join(
2176         || encode_metadata_impl(tcx, path),
2177         || {
2178             if tcx.sess.threads() == 1 {
2179                 return;
2180             }
2181             // Prefetch some queries used by metadata encoding.
2182             // This is not necessary for correctness, but is only done for performance reasons.
2183             // It can be removed if it turns out to cause trouble or be detrimental to performance.
2184             join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
2185         },
2186     );
2187 }
2188 
encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path)2189 fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
2190     let mut encoder = opaque::FileEncoder::new(path)
2191         .unwrap_or_else(|err| tcx.sess.emit_fatal(FailCreateFileEncoder { err }));
2192     encoder.emit_raw_bytes(METADATA_HEADER);
2193 
2194     // Will be filled with the root position after encoding everything.
2195     encoder.emit_raw_bytes(&[0, 0, 0, 0]);
2196 
2197     let source_map_files = tcx.sess.source_map().files();
2198     let source_file_cache = (source_map_files[0].clone(), 0);
2199     let required_source_files = Some(FxIndexSet::default());
2200     drop(source_map_files);
2201 
2202     let hygiene_ctxt = HygieneEncodeContext::default();
2203 
2204     let mut ecx = EncodeContext {
2205         opaque: encoder,
2206         tcx,
2207         feat: tcx.features(),
2208         tables: Default::default(),
2209         lazy_state: LazyState::NoNode,
2210         type_shorthands: Default::default(),
2211         predicate_shorthands: Default::default(),
2212         source_file_cache,
2213         interpret_allocs: Default::default(),
2214         required_source_files,
2215         is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
2216         hygiene_ctxt: &hygiene_ctxt,
2217         symbol_table: Default::default(),
2218     };
2219 
2220     // Encode the rustc version string in a predictable location.
2221     rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
2222 
2223     // Encode all the entries and extra information in the crate,
2224     // culminating in the `CrateRoot` which points to all of it.
2225     let root = ecx.encode_crate_root();
2226 
2227     ecx.opaque.flush();
2228 
2229     let mut file = ecx.opaque.file();
2230     // We will return to this position after writing the root position.
2231     let pos_before_seek = file.stream_position().unwrap();
2232 
2233     // Encode the root position.
2234     let header = METADATA_HEADER.len();
2235     file.seek(std::io::SeekFrom::Start(header as u64))
2236         .unwrap_or_else(|err| tcx.sess.emit_fatal(FailSeekFile { err }));
2237     let pos = root.position.get();
2238     file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])
2239         .unwrap_or_else(|err| tcx.sess.emit_fatal(FailWriteFile { err }));
2240 
2241     // Return to the position where we are before writing the root position.
2242     file.seek(std::io::SeekFrom::Start(pos_before_seek)).unwrap();
2243 
2244     // Record metadata size for self-profiling
2245     tcx.prof.artifact_size(
2246         "crate_metadata",
2247         "crate_metadata",
2248         file.metadata().unwrap().len() as u64,
2249     );
2250 }
2251 
provide(providers: &mut Providers)2252 pub fn provide(providers: &mut Providers) {
2253     *providers = Providers {
2254         doc_link_resolutions: |tcx, def_id| {
2255             tcx.resolutions(())
2256                 .doc_link_resolutions
2257                 .get(&def_id)
2258                 .expect("no resolutions for a doc link")
2259         },
2260         doc_link_traits_in_scope: |tcx, def_id| {
2261             tcx.resolutions(())
2262                 .doc_link_traits_in_scope
2263                 .get(&def_id)
2264                 .expect("no traits in scope for a doc link")
2265         },
2266         traits: |tcx, LocalCrate| {
2267             let mut traits = Vec::new();
2268             for id in tcx.hir().items() {
2269                 if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
2270                     traits.push(id.owner_id.to_def_id())
2271                 }
2272             }
2273 
2274             // Bring everything into deterministic order.
2275             traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
2276             tcx.arena.alloc_slice(&traits)
2277         },
2278         trait_impls_in_crate: |tcx, LocalCrate| {
2279             let mut trait_impls = Vec::new();
2280             for id in tcx.hir().items() {
2281                 if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
2282                     && tcx.impl_trait_ref(id.owner_id).is_some()
2283                 {
2284                     trait_impls.push(id.owner_id.to_def_id())
2285                 }
2286             }
2287 
2288             // Bring everything into deterministic order.
2289             trait_impls.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
2290             tcx.arena.alloc_slice(&trait_impls)
2291         },
2292 
2293         ..*providers
2294     }
2295 }
2296