]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_metadata/src/rmeta/encoder.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / compiler / rustc_metadata / src / rmeta / encoder.rs
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> {
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> {
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> {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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
341 fn position(&self) -> usize {
342 self.opaque.position()
343 }
344
345 fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
346 &mut self.type_shorthands
347 }
348
349 fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
350 &mut self.predicate_shorthands
351 }
352
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> {
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
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
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
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
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
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
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]
769 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
800 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
836 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
877 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
914 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
951 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.
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
1029 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
1066 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
1103 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
1181 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
1218 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
1257 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.
1294 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> {
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
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))]
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))]
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
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))]
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
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))]
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))]
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))]
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))]
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
1691 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))]
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))]
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
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
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
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
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
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
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
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
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
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
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
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
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
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))]
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))]
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).
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
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.
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]
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]
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 {
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 {
2151 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
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
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
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 }