1use std::borrow::Borrow;
2use std::collections::hash_map::Entry;
3use std::fs::File;
4use std::io::{Read, Seek, Write};
5use std::path::{Path, PathBuf};
6use std::sync::Arc;
7
8use rustc_attr_data_structures::EncodeCrossCrate;
9use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
10use rustc_data_structures::memmap::{Mmap, MmapMut};
11use rustc_data_structures::sync::{join, par_for_each_in};
12use rustc_data_structures::temp_dir::MaybeTempDir;
13use rustc_data_structures::thousands::usize_with_underscores;
14use rustc_feature::Features;
15use rustc_hir as hir;
16use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
17use rustc_hir::definitions::DefPathData;
18use rustc_hir_pretty::id_to_string;
19use rustc_middle::middle::dependency_format::Linkage;
20use rustc_middle::middle::exported_symbols::metadata_symbol_name;
21use rustc_middle::mir::interpret;
22use rustc_middle::query::Providers;
23use rustc_middle::traits::specialization_graph;
24use rustc_middle::ty::codec::TyEncoder;
25use rustc_middle::ty::fast_reject::{self, TreatParams};
26use rustc_middle::ty::{AssocItemContainer, SymbolName};
27use rustc_middle::{bug, span_bug};
28use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
29use rustc_session::config::{CrateType, OptLevel, TargetModifier};
30use rustc_span::hygiene::HygieneEncodeContext;
31use rustc_span::{
32 ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId, SyntaxContext,
33 sym,
34};
35use tracing::{debug, instrument, trace};
36
37use crate::errors::{FailCreateFileEncoder, FailWriteFile};
38use crate::rmeta::*;
39
40pub(super) struct EncodeContext<'a, 'tcx> {
41 opaque: opaque::FileEncoder,
42 tcx: TyCtxt<'tcx>,
43 feat: &'tcx rustc_feature::Features,
44 tables: TableBuilders,
45
46 lazy_state: LazyState,
47 span_shorthands: FxHashMap<Span, usize>,
48 type_shorthands: FxHashMap<Ty<'tcx>, usize>,
49 predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
50
51 interpret_allocs: FxIndexSet<interpret::AllocId>,
52
53 source_file_cache: (Arc<SourceFile>, usize),
57 required_source_files: Option<FxIndexSet<usize>>,
64 is_proc_macro: bool,
65 hygiene_ctxt: &'a HygieneEncodeContext,
66 symbol_table: FxHashMap<Symbol, usize>,
67}
68
69macro_rules! empty_proc_macro {
73 ($self:ident) => {
74 if $self.is_proc_macro {
75 return LazyArray::default();
76 }
77 };
78}
79
80macro_rules! encoder_methods {
81 ($($name:ident($ty:ty);)*) => {
82 $(fn $name(&mut self, value: $ty) {
83 self.opaque.$name(value)
84 })*
85 }
86}
87
88impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
89 encoder_methods! {
90 emit_usize(usize);
91 emit_u128(u128);
92 emit_u64(u64);
93 emit_u32(u32);
94 emit_u16(u16);
95 emit_u8(u8);
96
97 emit_isize(isize);
98 emit_i128(i128);
99 emit_i64(i64);
100 emit_i32(i32);
101 emit_i16(i16);
102
103 emit_raw_bytes(&[u8]);
104 }
105}
106
107impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
108 fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
109 e.emit_lazy_distance(self.position);
110 }
111}
112
113impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
114 fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
115 e.emit_usize(self.num_elems);
116 if self.num_elems > 0 {
117 e.emit_lazy_distance(self.position)
118 }
119 }
120}
121
122impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
123 fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
124 e.emit_usize(self.width);
125 e.emit_usize(self.len);
126 e.emit_lazy_distance(self.position);
127 }
128}
129
130impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
131 fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
132 s.emit_u32(self.as_u32());
133 }
134}
135
136impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
137 fn encode_crate_num(&mut self, crate_num: CrateNum) {
138 if crate_num != LOCAL_CRATE && self.is_proc_macro {
139 panic!("Attempted to encode non-local CrateNum {crate_num:?} for proc-macro crate");
140 }
141 self.emit_u32(crate_num.as_u32());
142 }
143
144 fn encode_def_index(&mut self, def_index: DefIndex) {
145 self.emit_u32(def_index.as_u32());
146 }
147
148 fn encode_def_id(&mut self, def_id: DefId) {
149 def_id.krate.encode(self);
150 def_id.index.encode(self);
151 }
152
153 fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) {
154 rustc_span::hygiene::raw_encode_syntax_context(syntax_context, self.hygiene_ctxt, self);
155 }
156
157 fn encode_expn_id(&mut self, expn_id: ExpnId) {
158 if expn_id.krate == LOCAL_CRATE {
159 self.hygiene_ctxt.schedule_expn_data_for_encoding(expn_id);
164 }
165 expn_id.krate.encode(self);
166 expn_id.local_id.encode(self);
167 }
168
169 fn encode_span(&mut self, span: Span) {
170 match self.span_shorthands.entry(span) {
171 Entry::Occupied(o) => {
172 let last_location = *o.get();
175 let offset = self.opaque.position() - last_location;
178 if offset < last_location {
179 let needed = bytes_needed(offset);
180 SpanTag::indirect(true, needed as u8).encode(self);
181 self.opaque.write_with(|dest| {
182 *dest = offset.to_le_bytes();
183 needed
184 });
185 } else {
186 let needed = bytes_needed(last_location);
187 SpanTag::indirect(false, needed as u8).encode(self);
188 self.opaque.write_with(|dest| {
189 *dest = last_location.to_le_bytes();
190 needed
191 });
192 }
193 }
194 Entry::Vacant(v) => {
195 let position = self.opaque.position();
196 v.insert(position);
197 span.data().encode(self);
199 }
200 }
201 }
202
203 fn encode_symbol(&mut self, symbol: Symbol) {
204 if symbol.is_predefined() {
206 self.opaque.emit_u8(SYMBOL_PREDEFINED);
207 self.opaque.emit_u32(symbol.as_u32());
208 } else {
209 match self.symbol_table.entry(symbol) {
211 Entry::Vacant(o) => {
212 self.opaque.emit_u8(SYMBOL_STR);
213 let pos = self.opaque.position();
214 o.insert(pos);
215 self.emit_str(symbol.as_str());
216 }
217 Entry::Occupied(o) => {
218 let x = *o.get();
219 self.emit_u8(SYMBOL_OFFSET);
220 self.emit_usize(x);
221 }
222 }
223 }
224 }
225}
226
227fn bytes_needed(n: usize) -> usize {
228 (usize::BITS - n.leading_zeros()).div_ceil(u8::BITS) as usize
229}
230
231impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
232 fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
233 let ctxt = if s.is_proc_macro { SyntaxContext::root() } else { self.ctxt };
265
266 if self.is_dummy() {
267 let tag = SpanTag::new(SpanKind::Partial, ctxt, 0);
268 tag.encode(s);
269 if tag.context().is_none() {
270 ctxt.encode(s);
271 }
272 return;
273 }
274
275 debug_assert!(self.lo <= self.hi);
277
278 if !s.source_file_cache.0.contains(self.lo) {
279 let source_map = s.tcx.sess.source_map();
280 let source_file_index = source_map.lookup_source_file_idx(self.lo);
281 s.source_file_cache =
282 (Arc::clone(&source_map.files()[source_file_index]), source_file_index);
283 }
284 let (ref source_file, source_file_index) = s.source_file_cache;
285 debug_assert!(source_file.contains(self.lo));
286
287 if !source_file.contains(self.hi) {
288 let tag = SpanTag::new(SpanKind::Partial, ctxt, 0);
291 tag.encode(s);
292 if tag.context().is_none() {
293 ctxt.encode(s);
294 }
295 return;
296 }
297
298 let (kind, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
315 let metadata_index = {
325 match &*source_file.external_src.read() {
327 ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
328 src => panic!("Unexpected external source {src:?}"),
329 }
330 };
331
332 (SpanKind::Foreign, metadata_index)
333 } else {
334 let source_files =
336 s.required_source_files.as_mut().expect("Already encoded SourceMap!");
337 let (metadata_index, _) = source_files.insert_full(source_file_index);
338 let metadata_index: u32 =
339 metadata_index.try_into().expect("cannot export more than U32_MAX files");
340
341 (SpanKind::Local, metadata_index)
342 };
343
344 let lo = self.lo - source_file.start_pos;
347
348 let len = self.hi - self.lo;
351
352 let tag = SpanTag::new(kind, ctxt, len.0 as usize);
353 tag.encode(s);
354 if tag.context().is_none() {
355 ctxt.encode(s);
356 }
357 lo.encode(s);
358 if tag.length().is_none() {
359 len.encode(s);
360 }
361
362 metadata_index.encode(s);
364
365 if kind == SpanKind::Foreign {
366 let cnum = s.source_file_cache.0.cnum;
369 cnum.encode(s);
370 }
371 }
372}
373
374impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for [u8] {
375 fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
376 Encoder::emit_usize(e, self.len());
377 e.emit_raw_bytes(self);
378 }
379}
380
381impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
382 const CLEAR_CROSS_CRATE: bool = true;
383
384 fn position(&self) -> usize {
385 self.opaque.position()
386 }
387
388 fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
389 &mut self.type_shorthands
390 }
391
392 fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize> {
393 &mut self.predicate_shorthands
394 }
395
396 fn encode_alloc_id(&mut self, alloc_id: &rustc_middle::mir::interpret::AllocId) {
397 let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
398
399 index.encode(self);
400 }
401}
402
403macro_rules! record {
406 ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
407 {
408 let value = $value;
409 let lazy = $self.lazy(value);
410 $self.$tables.$table.set_some($def_id.index, lazy);
411 }
412 }};
413}
414
415macro_rules! record_array {
418 ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
419 {
420 let value = $value;
421 let lazy = $self.lazy_array(value);
422 $self.$tables.$table.set_some($def_id.index, lazy);
423 }
424 }};
425}
426
427macro_rules! record_defaulted_array {
428 ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
429 {
430 let value = $value;
431 let lazy = $self.lazy_array(value);
432 $self.$tables.$table.set($def_id.index, lazy);
433 }
434 }};
435}
436
437impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
438 fn emit_lazy_distance(&mut self, position: NonZero<usize>) {
439 let pos = position.get();
440 let distance = match self.lazy_state {
441 LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
442 LazyState::NodeStart(start) => {
443 let start = start.get();
444 assert!(pos <= start);
445 start - pos
446 }
447 LazyState::Previous(last_pos) => {
448 assert!(
449 last_pos <= position,
450 "make sure that the calls to `lazy*` \
451 are in the same order as the metadata fields",
452 );
453 position.get() - last_pos.get()
454 }
455 };
456 self.lazy_state = LazyState::Previous(NonZero::new(pos).unwrap());
457 self.emit_usize(distance);
458 }
459
460 fn lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T>
461 where
462 T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
463 {
464 let pos = NonZero::new(self.position()).unwrap();
465
466 assert_eq!(self.lazy_state, LazyState::NoNode);
467 self.lazy_state = LazyState::NodeStart(pos);
468 value.borrow().encode(self);
469 self.lazy_state = LazyState::NoNode;
470
471 assert!(pos.get() <= self.position());
472
473 LazyValue::from_position(pos)
474 }
475
476 fn lazy_array<T: ParameterizedOverTcx, I: IntoIterator<Item = B>, B: Borrow<T::Value<'tcx>>>(
477 &mut self,
478 values: I,
479 ) -> LazyArray<T>
480 where
481 T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
482 {
483 let pos = NonZero::new(self.position()).unwrap();
484
485 assert_eq!(self.lazy_state, LazyState::NoNode);
486 self.lazy_state = LazyState::NodeStart(pos);
487 let len = values.into_iter().map(|value| value.borrow().encode(self)).count();
488 self.lazy_state = LazyState::NoNode;
489
490 assert!(pos.get() <= self.position());
491
492 LazyArray::from_position_and_num_elems(pos, len)
493 }
494
495 fn encode_def_path_table(&mut self) {
496 let table = self.tcx.def_path_table();
497 if self.is_proc_macro {
498 for def_index in std::iter::once(CRATE_DEF_INDEX)
499 .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index))
500 {
501 let def_key = self.lazy(table.def_key(def_index));
502 let def_path_hash = table.def_path_hash(def_index);
503 self.tables.def_keys.set_some(def_index, def_key);
504 self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64());
505 }
506 } else {
507 for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
508 let def_key = self.lazy(def_key);
509 self.tables.def_keys.set_some(def_index, def_key);
510 self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64());
511 }
512 }
513 }
514
515 fn encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'static>> {
516 self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map()))
517 }
518
519 fn encode_source_map(&mut self) -> LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>> {
520 let source_map = self.tcx.sess.source_map();
521 let all_source_files = source_map.files();
522
523 let required_source_files = self.required_source_files.take().unwrap();
527
528 let working_directory = &self.tcx.sess.opts.working_dir;
529
530 let mut adapted = TableBuilder::default();
531
532 let local_crate_stable_id = self.tcx.stable_crate_id(LOCAL_CRATE);
533
534 for (on_disk_index, &source_file_index) in required_source_files.iter().enumerate() {
539 let source_file = &all_source_files[source_file_index];
540 assert!(!source_file.is_imported() || self.is_proc_macro);
542
543 let mut adapted_source_file = (**source_file).clone();
551
552 match source_file.name {
553 FileName::Real(ref original_file_name) => {
554 let adapted_file_name = source_map
555 .path_mapping()
556 .to_embeddable_absolute_path(original_file_name.clone(), working_directory);
557
558 adapted_source_file.name = FileName::Real(adapted_file_name);
559 }
560 _ => {
561 }
563 };
564
565 if self.is_proc_macro {
572 adapted_source_file.cnum = LOCAL_CRATE;
573 }
574
575 adapted_source_file.stable_id = StableSourceFileId::from_filename_for_export(
579 &adapted_source_file.name,
580 local_crate_stable_id,
581 );
582
583 let on_disk_index: u32 =
584 on_disk_index.try_into().expect("cannot export more than U32_MAX files");
585 adapted.set_some(on_disk_index, self.lazy(adapted_source_file));
586 }
587
588 adapted.encode(&mut self.opaque)
589 }
590
591 fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
592 let tcx = self.tcx;
593 let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
594
595 macro_rules! stat {
596 ($label:literal, $f:expr) => {{
597 let orig_pos = self.position();
598 let res = $f();
599 stats.push(($label, self.position() - orig_pos));
600 res
601 }};
602 }
603
604 stats.push(("preamble", self.position()));
606
607 let (crate_deps, dylib_dependency_formats) =
608 stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
609
610 let lib_features = stat!("lib-features", || self.encode_lib_features());
611
612 let stability_implications =
613 stat!("stability-implications", || self.encode_stability_implications());
614
615 let (lang_items, lang_items_missing) = stat!("lang-items", || {
616 (self.encode_lang_items(), self.encode_lang_items_missing())
617 });
618
619 let stripped_cfg_items = stat!("stripped-cfg-items", || self.encode_stripped_cfg_items());
620
621 let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
622
623 let native_libraries = stat!("native-libs", || self.encode_native_libraries());
624
625 let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
626
627 _ = stat!("def-path-table", || self.encode_def_path_table());
628
629 let traits = stat!("traits", || self.encode_traits());
631
632 let impls = stat!("impls", || self.encode_impls());
634
635 let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
636
637 _ = stat!("mir", || self.encode_mir());
638
639 _ = stat!("def-ids", || self.encode_def_ids());
640
641 let interpret_alloc_index = stat!("interpret-alloc-index", || {
642 let mut interpret_alloc_index = Vec::new();
643 let mut n = 0;
644 trace!("beginning to encode alloc ids");
645 loop {
646 let new_n = self.interpret_allocs.len();
647 if n == new_n {
649 break;
651 }
652 trace!("encoding {} further alloc ids", new_n - n);
653 for idx in n..new_n {
654 let id = self.interpret_allocs[idx];
655 let pos = self.position() as u64;
656 interpret_alloc_index.push(pos);
657 interpret::specialized_encode_alloc_id(self, tcx, id);
658 }
659 n = new_n;
660 }
661 self.lazy_array(interpret_alloc_index)
662 });
663
664 let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
668
669 let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
670
671 let debugger_visualizers =
672 stat!("debugger-visualizers", || self.encode_debugger_visualizers());
673
674 let exportable_items = stat!("exportable-items", || self.encode_exportable_items());
675
676 let stable_order_of_exportable_impls =
677 stat!("exportable-items", || self.encode_stable_order_of_exportable_impls());
678
679 let exported_symbols = stat!("exported-symbols", || {
681 self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE))
682 });
683
684 let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
691
692 let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
693
694 let source_map = stat!("source-map", || self.encode_source_map());
697 let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers());
698
699 let root = stat!("final", || {
700 let attrs = tcx.hir_krate_attrs();
701 self.lazy(CrateRoot {
702 header: CrateHeader {
703 name: tcx.crate_name(LOCAL_CRATE),
704 triple: tcx.sess.opts.target_triple.clone(),
705 hash: tcx.crate_hash(LOCAL_CRATE),
706 is_proc_macro_crate: proc_macro_data.is_some(),
707 is_stub: false,
708 },
709 extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
710 stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
711 required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
712 panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
713 edition: tcx.sess.edition(),
714 has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
715 has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE),
716 has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
717 has_default_lib_allocator: ast::attr::contains_name(
718 attrs,
719 sym::default_lib_allocator,
720 ),
721 proc_macro_data,
722 debugger_visualizers,
723 compiler_builtins: ast::attr::contains_name(attrs, sym::compiler_builtins),
724 needs_allocator: ast::attr::contains_name(attrs, sym::needs_allocator),
725 needs_panic_runtime: ast::attr::contains_name(attrs, sym::needs_panic_runtime),
726 no_builtins: ast::attr::contains_name(attrs, sym::no_builtins),
727 panic_runtime: ast::attr::contains_name(attrs, sym::panic_runtime),
728 profiler_runtime: ast::attr::contains_name(attrs, sym::profiler_runtime),
729 symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
730
731 crate_deps,
732 dylib_dependency_formats,
733 lib_features,
734 stability_implications,
735 lang_items,
736 diagnostic_items,
737 lang_items_missing,
738 stripped_cfg_items,
739 native_libraries,
740 foreign_modules,
741 source_map,
742 target_modifiers,
743 traits,
744 impls,
745 incoherent_impls,
746 exportable_items,
747 stable_order_of_exportable_impls,
748 exported_symbols,
749 interpret_alloc_index,
750 tables,
751 syntax_contexts,
752 expn_data,
753 expn_hashes,
754 def_path_hash_map,
755 specialization_enabled_in: tcx.specialization_enabled_in(LOCAL_CRATE),
756 })
757 });
758
759 let total_bytes = self.position();
760
761 let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
762 assert_eq!(total_bytes, computed_total_bytes);
763
764 if tcx.sess.opts.unstable_opts.meta_stats {
765 use std::fmt::Write;
766
767 self.opaque.flush();
768
769 let pos_before_rewind = self.opaque.file().stream_position().unwrap();
771 let mut zero_bytes = 0;
772 self.opaque.file().rewind().unwrap();
773 let file = std::io::BufReader::new(self.opaque.file());
774 for e in file.bytes() {
775 if e.unwrap() == 0 {
776 zero_bytes += 1;
777 }
778 }
779 assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
780
781 stats.sort_by_key(|&(_, usize)| usize);
782 stats.reverse(); let prefix = "meta-stats";
785 let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
786
787 let section_w = 23;
788 let size_w = 10;
789 let banner_w = 64;
790
791 let mut s = String::new();
797 _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w));
798 _ = writeln!(s, "{prefix} METADATA STATS: {}", tcx.crate_name(LOCAL_CRATE));
799 _ = writeln!(s, "{prefix} {:<section_w$}{:>size_w$}", "Section", "Size");
800 _ = writeln!(s, "{prefix} {}", "-".repeat(banner_w));
801 for (label, size) in stats {
802 _ = writeln!(
803 s,
804 "{prefix} {:<section_w$}{:>size_w$} ({:4.1}%)",
805 label,
806 usize_with_underscores(size),
807 perc(size)
808 );
809 }
810 _ = writeln!(s, "{prefix} {}", "-".repeat(banner_w));
811 _ = writeln!(
812 s,
813 "{prefix} {:<section_w$}{:>size_w$} (of which {:.1}% are zero bytes)",
814 "Total",
815 usize_with_underscores(total_bytes),
816 perc(zero_bytes)
817 );
818 _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w));
819 eprint!("{s}");
820 }
821
822 root
823 }
824}
825
826struct AnalyzeAttrState<'a> {
827 is_exported: bool,
828 is_doc_hidden: bool,
829 features: &'a Features,
830}
831
832#[inline]
842fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState<'_>) -> bool {
843 let mut should_encode = false;
844 if let hir::Attribute::Parsed(p) = attr
845 && p.encode_cross_crate() == EncodeCrossCrate::No
846 {
847 } else if let Some(name) = attr.name()
849 && !rustc_feature::encode_cross_crate(name)
850 {
851 } else if attr.doc_str().is_some() {
853 if state.is_exported {
857 should_encode = true;
858 }
859 } else if attr.has_name(sym::doc) {
860 if let Some(item_list) = attr.meta_item_list() {
863 for item in item_list {
864 if !item.has_name(sym::inline) {
865 should_encode = true;
866 if item.has_name(sym::hidden) {
867 state.is_doc_hidden = true;
868 break;
869 }
870 }
871 }
872 }
873 } else if let &[sym::diagnostic, seg] = &*attr.path() {
874 should_encode = rustc_feature::is_stable_diagnostic_attribute(seg, state.features);
875 } else {
876 should_encode = true;
877 }
878 should_encode
879}
880
881fn should_encode_span(def_kind: DefKind) -> bool {
882 match def_kind {
883 DefKind::Mod
884 | DefKind::Struct
885 | DefKind::Union
886 | DefKind::Enum
887 | DefKind::Variant
888 | DefKind::Trait
889 | DefKind::TyAlias
890 | DefKind::ForeignTy
891 | DefKind::TraitAlias
892 | DefKind::AssocTy
893 | DefKind::TyParam
894 | DefKind::ConstParam
895 | DefKind::LifetimeParam
896 | DefKind::Fn
897 | DefKind::Const
898 | DefKind::Static { .. }
899 | DefKind::Ctor(..)
900 | DefKind::AssocFn
901 | DefKind::AssocConst
902 | DefKind::Macro(_)
903 | DefKind::ExternCrate
904 | DefKind::Use
905 | DefKind::AnonConst
906 | DefKind::InlineConst
907 | DefKind::OpaqueTy
908 | DefKind::Field
909 | DefKind::Impl { .. }
910 | DefKind::Closure
911 | DefKind::SyntheticCoroutineBody => true,
912 DefKind::ForeignMod | DefKind::GlobalAsm => false,
913 }
914}
915
916fn should_encode_attrs(def_kind: DefKind) -> bool {
917 match def_kind {
918 DefKind::Mod
919 | DefKind::Struct
920 | DefKind::Union
921 | DefKind::Enum
922 | DefKind::Variant
923 | DefKind::Trait
924 | DefKind::TyAlias
925 | DefKind::ForeignTy
926 | DefKind::TraitAlias
927 | DefKind::AssocTy
928 | DefKind::Fn
929 | DefKind::Const
930 | DefKind::Static { nested: false, .. }
931 | DefKind::AssocFn
932 | DefKind::AssocConst
933 | DefKind::Macro(_)
934 | DefKind::Field
935 | DefKind::Impl { .. } => true,
936 DefKind::Closure => true,
941 DefKind::SyntheticCoroutineBody => false,
942 DefKind::TyParam
943 | DefKind::ConstParam
944 | DefKind::Ctor(..)
945 | DefKind::ExternCrate
946 | DefKind::Use
947 | DefKind::ForeignMod
948 | DefKind::AnonConst
949 | DefKind::InlineConst
950 | DefKind::OpaqueTy
951 | DefKind::LifetimeParam
952 | DefKind::Static { nested: true, .. }
953 | DefKind::GlobalAsm => false,
954 }
955}
956
957fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
958 match def_kind {
959 DefKind::Mod
960 | DefKind::Struct
961 | DefKind::Union
962 | DefKind::Enum
963 | DefKind::Variant
964 | DefKind::Trait
965 | DefKind::Impl { .. } => true,
966 DefKind::TyAlias
967 | DefKind::ForeignTy
968 | DefKind::TraitAlias
969 | DefKind::AssocTy
970 | DefKind::TyParam
971 | DefKind::Fn
972 | DefKind::Const
973 | DefKind::ConstParam
974 | DefKind::Static { .. }
975 | DefKind::Ctor(..)
976 | DefKind::AssocFn
977 | DefKind::AssocConst
978 | DefKind::Macro(_)
979 | DefKind::ExternCrate
980 | DefKind::Use
981 | DefKind::ForeignMod
982 | DefKind::AnonConst
983 | DefKind::InlineConst
984 | DefKind::OpaqueTy
985 | DefKind::Field
986 | DefKind::LifetimeParam
987 | DefKind::GlobalAsm
988 | DefKind::Closure
989 | DefKind::SyntheticCoroutineBody => false,
990 }
991}
992
993fn should_encode_visibility(def_kind: DefKind) -> bool {
994 match def_kind {
995 DefKind::Mod
996 | DefKind::Struct
997 | DefKind::Union
998 | DefKind::Enum
999 | DefKind::Variant
1000 | DefKind::Trait
1001 | DefKind::TyAlias
1002 | DefKind::ForeignTy
1003 | DefKind::TraitAlias
1004 | DefKind::AssocTy
1005 | DefKind::Fn
1006 | DefKind::Const
1007 | DefKind::Static { nested: false, .. }
1008 | DefKind::Ctor(..)
1009 | DefKind::AssocFn
1010 | DefKind::AssocConst
1011 | DefKind::Macro(..)
1012 | DefKind::Field => true,
1013 DefKind::Use
1014 | DefKind::ForeignMod
1015 | DefKind::TyParam
1016 | DefKind::ConstParam
1017 | DefKind::LifetimeParam
1018 | DefKind::AnonConst
1019 | DefKind::InlineConst
1020 | DefKind::Static { nested: true, .. }
1021 | DefKind::OpaqueTy
1022 | DefKind::GlobalAsm
1023 | DefKind::Impl { .. }
1024 | DefKind::Closure
1025 | DefKind::ExternCrate
1026 | DefKind::SyntheticCoroutineBody => false,
1027 }
1028}
1029
1030fn should_encode_stability(def_kind: DefKind) -> bool {
1031 match def_kind {
1032 DefKind::Mod
1033 | DefKind::Ctor(..)
1034 | DefKind::Variant
1035 | DefKind::Field
1036 | DefKind::Struct
1037 | DefKind::AssocTy
1038 | DefKind::AssocFn
1039 | DefKind::AssocConst
1040 | DefKind::TyParam
1041 | DefKind::ConstParam
1042 | DefKind::Static { .. }
1043 | DefKind::Const
1044 | DefKind::Fn
1045 | DefKind::ForeignMod
1046 | DefKind::TyAlias
1047 | DefKind::OpaqueTy
1048 | DefKind::Enum
1049 | DefKind::Union
1050 | DefKind::Impl { .. }
1051 | DefKind::Trait
1052 | DefKind::TraitAlias
1053 | DefKind::Macro(..)
1054 | DefKind::ForeignTy => true,
1055 DefKind::Use
1056 | DefKind::LifetimeParam
1057 | DefKind::AnonConst
1058 | DefKind::InlineConst
1059 | DefKind::GlobalAsm
1060 | DefKind::Closure
1061 | DefKind::ExternCrate
1062 | DefKind::SyntheticCoroutineBody => false,
1063 }
1064}
1065
1066fn should_encode_mir(
1087 tcx: TyCtxt<'_>,
1088 reachable_set: &LocalDefIdSet,
1089 def_id: LocalDefId,
1090) -> (bool, bool) {
1091 match tcx.def_kind(def_id) {
1092 DefKind::Ctor(_, _) => {
1094 let mir_opt_base = tcx.sess.opts.output_types.should_codegen()
1095 || tcx.sess.opts.unstable_opts.always_encode_mir;
1096 (true, mir_opt_base)
1097 }
1098 DefKind::AnonConst | DefKind::InlineConst | DefKind::AssocConst | DefKind::Const => {
1100 (true, false)
1101 }
1102 DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true),
1104 DefKind::SyntheticCoroutineBody => (false, true),
1105 DefKind::AssocFn | DefKind::Fn | DefKind::Closure => {
1107 let generics = tcx.generics_of(def_id);
1108 let opt = tcx.sess.opts.unstable_opts.always_encode_mir
1109 || (tcx.sess.opts.output_types.should_codegen()
1110 && reachable_set.contains(&def_id)
1111 && (generics.requires_monomorphization(tcx)
1112 || tcx.cross_crate_inlinable(def_id)));
1113 let is_const_fn = tcx.is_const_fn(def_id.to_def_id())
1115 || tcx.is_const_default_method(def_id.to_def_id());
1116 (is_const_fn, opt)
1117 }
1118 _ => (false, false),
1120 }
1121}
1122
1123fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool {
1124 match def_kind {
1125 DefKind::Struct
1126 | DefKind::Union
1127 | DefKind::Enum
1128 | DefKind::OpaqueTy
1129 | DefKind::Fn
1130 | DefKind::Ctor(..)
1131 | DefKind::AssocFn => true,
1132 DefKind::AssocTy => {
1133 matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. }))
1135 }
1136 DefKind::Mod
1137 | DefKind::Variant
1138 | DefKind::Field
1139 | DefKind::AssocConst
1140 | DefKind::TyParam
1141 | DefKind::ConstParam
1142 | DefKind::Static { .. }
1143 | DefKind::Const
1144 | DefKind::ForeignMod
1145 | DefKind::Impl { .. }
1146 | DefKind::Trait
1147 | DefKind::TraitAlias
1148 | DefKind::Macro(..)
1149 | DefKind::ForeignTy
1150 | DefKind::Use
1151 | DefKind::LifetimeParam
1152 | DefKind::AnonConst
1153 | DefKind::InlineConst
1154 | DefKind::GlobalAsm
1155 | DefKind::Closure
1156 | DefKind::ExternCrate
1157 | DefKind::SyntheticCoroutineBody => false,
1158 DefKind::TyAlias => tcx.type_alias_is_lazy(def_id),
1159 }
1160}
1161
1162fn should_encode_generics(def_kind: DefKind) -> bool {
1163 match def_kind {
1164 DefKind::Struct
1165 | DefKind::Union
1166 | DefKind::Enum
1167 | DefKind::Variant
1168 | DefKind::Trait
1169 | DefKind::TyAlias
1170 | DefKind::ForeignTy
1171 | DefKind::TraitAlias
1172 | DefKind::AssocTy
1173 | DefKind::Fn
1174 | DefKind::Const
1175 | DefKind::Static { .. }
1176 | DefKind::Ctor(..)
1177 | DefKind::AssocFn
1178 | DefKind::AssocConst
1179 | DefKind::AnonConst
1180 | DefKind::InlineConst
1181 | DefKind::OpaqueTy
1182 | DefKind::Impl { .. }
1183 | DefKind::Field
1184 | DefKind::TyParam
1185 | DefKind::Closure
1186 | DefKind::SyntheticCoroutineBody => true,
1187 DefKind::Mod
1188 | DefKind::ForeignMod
1189 | DefKind::ConstParam
1190 | DefKind::Macro(..)
1191 | DefKind::Use
1192 | DefKind::LifetimeParam
1193 | DefKind::GlobalAsm
1194 | DefKind::ExternCrate => false,
1195 }
1196}
1197
1198fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> bool {
1199 match def_kind {
1200 DefKind::Struct
1201 | DefKind::Union
1202 | DefKind::Enum
1203 | DefKind::Variant
1204 | DefKind::Ctor(..)
1205 | DefKind::Field
1206 | DefKind::Fn
1207 | DefKind::Const
1208 | DefKind::Static { nested: false, .. }
1209 | DefKind::TyAlias
1210 | DefKind::ForeignTy
1211 | DefKind::Impl { .. }
1212 | DefKind::AssocFn
1213 | DefKind::AssocConst
1214 | DefKind::Closure
1215 | DefKind::ConstParam
1216 | DefKind::AnonConst
1217 | DefKind::InlineConst
1218 | DefKind::SyntheticCoroutineBody => true,
1219
1220 DefKind::OpaqueTy => {
1221 let origin = tcx.local_opaque_ty_origin(def_id);
1222 if let hir::OpaqueTyOrigin::FnReturn { parent, .. }
1223 | hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin
1224 && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(parent)
1225 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
1226 {
1227 false
1228 } else {
1229 true
1230 }
1231 }
1232
1233 DefKind::AssocTy => {
1234 let assoc_item = tcx.associated_item(def_id);
1235 match assoc_item.container {
1236 ty::AssocItemContainer::Impl => true,
1237 ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(),
1238 }
1239 }
1240 DefKind::TyParam => {
1241 let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(def_id) else { bug!() };
1242 let hir::GenericParamKind::Type { default, .. } = param.kind else { bug!() };
1243 default.is_some()
1244 }
1245
1246 DefKind::Trait
1247 | DefKind::TraitAlias
1248 | DefKind::Mod
1249 | DefKind::ForeignMod
1250 | DefKind::Macro(..)
1251 | DefKind::Static { nested: true, .. }
1252 | DefKind::Use
1253 | DefKind::LifetimeParam
1254 | DefKind::GlobalAsm
1255 | DefKind::ExternCrate => false,
1256 }
1257}
1258
1259fn should_encode_fn_sig(def_kind: DefKind) -> bool {
1260 match def_kind {
1261 DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) => true,
1262
1263 DefKind::Struct
1264 | DefKind::Union
1265 | DefKind::Enum
1266 | DefKind::Variant
1267 | DefKind::Field
1268 | DefKind::Const
1269 | DefKind::Static { .. }
1270 | DefKind::Ctor(..)
1271 | DefKind::TyAlias
1272 | DefKind::OpaqueTy
1273 | DefKind::ForeignTy
1274 | DefKind::Impl { .. }
1275 | DefKind::AssocConst
1276 | DefKind::Closure
1277 | DefKind::ConstParam
1278 | DefKind::AnonConst
1279 | DefKind::InlineConst
1280 | DefKind::AssocTy
1281 | DefKind::TyParam
1282 | DefKind::Trait
1283 | DefKind::TraitAlias
1284 | DefKind::Mod
1285 | DefKind::ForeignMod
1286 | DefKind::Macro(..)
1287 | DefKind::Use
1288 | DefKind::LifetimeParam
1289 | DefKind::GlobalAsm
1290 | DefKind::ExternCrate
1291 | DefKind::SyntheticCoroutineBody => false,
1292 }
1293}
1294
1295fn should_encode_constness(def_kind: DefKind) -> bool {
1296 match def_kind {
1297 DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Ctor(_, CtorKind::Fn) => true,
1298
1299 DefKind::Struct
1300 | DefKind::Union
1301 | DefKind::Enum
1302 | DefKind::Field
1303 | DefKind::Const
1304 | DefKind::AssocConst
1305 | DefKind::AnonConst
1306 | DefKind::Static { .. }
1307 | DefKind::TyAlias
1308 | DefKind::OpaqueTy
1309 | DefKind::Impl { .. }
1310 | DefKind::ForeignTy
1311 | DefKind::ConstParam
1312 | DefKind::InlineConst
1313 | DefKind::AssocTy
1314 | DefKind::TyParam
1315 | DefKind::Trait
1316 | DefKind::TraitAlias
1317 | DefKind::Mod
1318 | DefKind::ForeignMod
1319 | DefKind::Macro(..)
1320 | DefKind::Use
1321 | DefKind::LifetimeParam
1322 | DefKind::GlobalAsm
1323 | DefKind::ExternCrate
1324 | DefKind::Ctor(_, CtorKind::Const)
1325 | DefKind::Variant
1326 | DefKind::SyntheticCoroutineBody => false,
1327 }
1328}
1329
1330fn should_encode_const(def_kind: DefKind) -> bool {
1331 match def_kind {
1332 DefKind::Const | DefKind::AssocConst | DefKind::AnonConst | DefKind::InlineConst => true,
1333
1334 DefKind::Struct
1335 | DefKind::Union
1336 | DefKind::Enum
1337 | DefKind::Variant
1338 | DefKind::Ctor(..)
1339 | DefKind::Field
1340 | DefKind::Fn
1341 | DefKind::Static { .. }
1342 | DefKind::TyAlias
1343 | DefKind::OpaqueTy
1344 | DefKind::ForeignTy
1345 | DefKind::Impl { .. }
1346 | DefKind::AssocFn
1347 | DefKind::Closure
1348 | DefKind::ConstParam
1349 | DefKind::AssocTy
1350 | DefKind::TyParam
1351 | DefKind::Trait
1352 | DefKind::TraitAlias
1353 | DefKind::Mod
1354 | DefKind::ForeignMod
1355 | DefKind::Macro(..)
1356 | DefKind::Use
1357 | DefKind::LifetimeParam
1358 | DefKind::GlobalAsm
1359 | DefKind::ExternCrate
1360 | DefKind::SyntheticCoroutineBody => false,
1361 }
1362}
1363
1364fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
1365 if let Some(assoc_item) = tcx.opt_associated_item(def_id)
1366 && assoc_item.container == ty::AssocItemContainer::Trait
1367 && assoc_item.is_fn()
1368 {
1369 true
1370 } else {
1371 false
1372 }
1373}
1374
1375impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
1376 fn encode_attrs(&mut self, def_id: LocalDefId) {
1377 let tcx = self.tcx;
1378 let mut state = AnalyzeAttrState {
1379 is_exported: tcx.effective_visibilities(()).is_exported(def_id),
1380 is_doc_hidden: false,
1381 features: &tcx.features(),
1382 };
1383 let attr_iter = tcx
1384 .hir_attrs(tcx.local_def_id_to_hir_id(def_id))
1385 .iter()
1386 .filter(|attr| analyze_attr(*attr, &mut state));
1387
1388 record_array!(self.tables.attributes[def_id.to_def_id()] <- attr_iter);
1389
1390 let mut attr_flags = AttrFlags::empty();
1391 if state.is_doc_hidden {
1392 attr_flags |= AttrFlags::IS_DOC_HIDDEN;
1393 }
1394 self.tables.attr_flags.set(def_id.local_def_index, attr_flags);
1395 }
1396
1397 fn encode_def_ids(&mut self) {
1398 self.encode_info_for_mod(CRATE_DEF_ID);
1399
1400 if self.is_proc_macro {
1403 return;
1404 }
1405
1406 let tcx = self.tcx;
1407
1408 for local_id in tcx.iter_local_def_id() {
1409 let def_id = local_id.to_def_id();
1410 let def_kind = tcx.def_kind(local_id);
1411 self.tables.def_kind.set_some(def_id.index, def_kind);
1412
1413 if def_kind == DefKind::AnonConst
1418 && match tcx.hir_node_by_def_id(local_id) {
1419 hir::Node::ConstArg(hir::ConstArg { kind, .. }) => match kind {
1420 hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true,
1422 hir::ConstArgKind::Anon(..) => false,
1423 },
1424 _ => false,
1425 }
1426 {
1427 continue;
1428 }
1429
1430 if def_kind == DefKind::Field
1431 && let hir::Node::Field(field) = tcx.hir_node_by_def_id(local_id)
1432 && let Some(anon) = field.default
1433 {
1434 record!(self.tables.default_fields[def_id] <- anon.def_id.to_def_id());
1435 }
1436
1437 if should_encode_span(def_kind) {
1438 let def_span = tcx.def_span(local_id);
1439 record!(self.tables.def_span[def_id] <- def_span);
1440 }
1441 if should_encode_attrs(def_kind) {
1442 self.encode_attrs(local_id);
1443 }
1444 if should_encode_expn_that_defined(def_kind) {
1445 record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
1446 }
1447 if should_encode_span(def_kind)
1448 && let Some(ident_span) = tcx.def_ident_span(def_id)
1449 {
1450 record!(self.tables.def_ident_span[def_id] <- ident_span);
1451 }
1452 if def_kind.has_codegen_attrs() {
1453 record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
1454 }
1455 if should_encode_visibility(def_kind) {
1456 let vis =
1457 self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index);
1458 record!(self.tables.visibility[def_id] <- vis);
1459 }
1460 if should_encode_stability(def_kind) {
1461 self.encode_stability(def_id);
1462 self.encode_const_stability(def_id);
1463 self.encode_default_body_stability(def_id);
1464 self.encode_deprecation(def_id);
1465 }
1466 if should_encode_variances(tcx, def_id, def_kind) {
1467 let v = self.tcx.variances_of(def_id);
1468 record_array!(self.tables.variances_of[def_id] <- v);
1469 }
1470 if should_encode_fn_sig(def_kind) {
1471 record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
1472 }
1473 if should_encode_generics(def_kind) {
1474 let g = tcx.generics_of(def_id);
1475 record!(self.tables.generics_of[def_id] <- g);
1476 record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
1477 let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
1478 record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
1479
1480 for param in &g.own_params {
1481 if let ty::GenericParamDefKind::Const { has_default: true, .. } = param.kind {
1482 let default = self.tcx.const_param_default(param.def_id);
1483 record!(self.tables.const_param_default[param.def_id] <- default);
1484 }
1485 }
1486 }
1487 if tcx.is_conditionally_const(def_id) {
1488 record!(self.tables.const_conditions[def_id] <- self.tcx.const_conditions(def_id));
1489 }
1490 if should_encode_type(tcx, local_id, def_kind) {
1491 record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
1492 }
1493 if should_encode_constness(def_kind) {
1494 self.tables.constness.set_some(def_id.index, self.tcx.constness(def_id));
1495 }
1496 if let DefKind::Fn | DefKind::AssocFn = def_kind {
1497 self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id));
1498 record_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id));
1499 }
1500 if let Some(name) = tcx.intrinsic(def_id) {
1501 record!(self.tables.intrinsic[def_id] <- name);
1502 }
1503 if let DefKind::TyParam = def_kind {
1504 let default = self.tcx.object_lifetime_default(def_id);
1505 record!(self.tables.object_lifetime_default[def_id] <- default);
1506 }
1507 if let DefKind::Trait = def_kind {
1508 record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
1509 record_defaulted_array!(self.tables.explicit_super_predicates_of[def_id] <-
1510 self.tcx.explicit_super_predicates_of(def_id).skip_binder());
1511 record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <-
1512 self.tcx.explicit_implied_predicates_of(def_id).skip_binder());
1513 let module_children = self.tcx.module_children_local(local_id);
1514 record_array!(self.tables.module_children_non_reexports[def_id] <-
1515 module_children.iter().map(|child| child.res.def_id().index));
1516 if self.tcx.is_const_trait(def_id) {
1517 record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
1518 <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder());
1519 }
1520 }
1521 if let DefKind::TraitAlias = def_kind {
1522 record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
1523 record_defaulted_array!(self.tables.explicit_super_predicates_of[def_id] <-
1524 self.tcx.explicit_super_predicates_of(def_id).skip_binder());
1525 record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <-
1526 self.tcx.explicit_implied_predicates_of(def_id).skip_binder());
1527 }
1528 if let DefKind::Trait | DefKind::Impl { .. } = def_kind {
1529 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
1530 record_array!(self.tables.associated_item_or_field_def_ids[def_id] <-
1531 associated_item_def_ids.iter().map(|&def_id| {
1532 assert!(def_id.is_local());
1533 def_id.index
1534 })
1535 );
1536 for &def_id in associated_item_def_ids {
1537 self.encode_info_for_assoc_item(def_id);
1538 }
1539 }
1540 if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind
1541 && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)
1542 {
1543 self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind))
1544 }
1545 if def_kind == DefKind::Closure
1546 && tcx.type_of(def_id).skip_binder().is_coroutine_closure()
1547 {
1548 let coroutine_for_closure = self.tcx.coroutine_for_closure(def_id);
1549 self.tables
1550 .coroutine_for_closure
1551 .set_some(def_id.index, coroutine_for_closure.into());
1552
1553 if tcx.needs_coroutine_by_move_body_def_id(coroutine_for_closure) {
1555 self.tables.coroutine_by_move_body_def_id.set_some(
1556 coroutine_for_closure.index,
1557 self.tcx.coroutine_by_move_body_def_id(coroutine_for_closure).into(),
1558 );
1559 }
1560 }
1561 if let DefKind::Static { .. } = def_kind {
1562 if !self.tcx.is_foreign_item(def_id) {
1563 let data = self.tcx.eval_static_initializer(def_id).unwrap();
1564 record!(self.tables.eval_static_initializer[def_id] <- data);
1565 }
1566 }
1567 if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
1568 self.encode_info_for_adt(local_id);
1569 }
1570 if let DefKind::Mod = def_kind {
1571 self.encode_info_for_mod(local_id);
1572 }
1573 if let DefKind::Macro(_) = def_kind {
1574 self.encode_info_for_macro(local_id);
1575 }
1576 if let DefKind::TyAlias = def_kind {
1577 self.tables
1578 .type_alias_is_lazy
1579 .set(def_id.index, self.tcx.type_alias_is_lazy(def_id));
1580 }
1581 if let DefKind::OpaqueTy = def_kind {
1582 self.encode_explicit_item_bounds(def_id);
1583 self.encode_explicit_item_self_bounds(def_id);
1584 record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id));
1585 self.encode_precise_capturing_args(def_id);
1586 if tcx.is_conditionally_const(def_id) {
1587 record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
1588 <- tcx.explicit_implied_const_bounds(def_id).skip_binder());
1589 }
1590 }
1591 if let DefKind::AnonConst = def_kind {
1592 record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
1593 }
1594 if tcx.impl_method_has_trait_impl_trait_tys(def_id)
1595 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
1596 {
1597 record!(self.tables.trait_impl_trait_tys[def_id] <- table);
1598 }
1599 if should_encode_fn_impl_trait_in_trait(tcx, def_id) {
1600 let table = tcx.associated_types_for_impl_traits_in_associated_fn(def_id);
1601 record_defaulted_array!(self.tables.associated_types_for_impl_traits_in_associated_fn[def_id] <- table);
1602 }
1603 }
1604
1605 for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls {
1606 record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
1607 assert!(def_id.is_local());
1608 def_id.index
1609 }));
1610 }
1611
1612 for (def_id, res_map) in &tcx.resolutions(()).doc_link_resolutions {
1613 record!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map);
1614 }
1615
1616 for (def_id, traits) in &tcx.resolutions(()).doc_link_traits_in_scope {
1617 record_array!(self.tables.doc_link_traits_in_scope[def_id.to_def_id()] <- traits);
1618 }
1619 }
1620
1621 #[instrument(level = "trace", skip(self))]
1622 fn encode_info_for_adt(&mut self, local_def_id: LocalDefId) {
1623 let def_id = local_def_id.to_def_id();
1624 let tcx = self.tcx;
1625 let adt_def = tcx.adt_def(def_id);
1626 record!(self.tables.repr_options[def_id] <- adt_def.repr());
1627
1628 let params_in_repr = self.tcx.params_in_repr(def_id);
1629 record!(self.tables.params_in_repr[def_id] <- params_in_repr);
1630
1631 if adt_def.is_enum() {
1632 let module_children = tcx.module_children_local(local_def_id);
1633 record_array!(self.tables.module_children_non_reexports[def_id] <-
1634 module_children.iter().map(|child| child.res.def_id().index));
1635 } else {
1636 debug_assert_eq!(adt_def.variants().len(), 1);
1638 debug_assert_eq!(adt_def.non_enum_variant().def_id, def_id);
1639 }
1641
1642 for (idx, variant) in adt_def.variants().iter_enumerated() {
1643 let data = VariantData {
1644 discr: variant.discr,
1645 idx,
1646 ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
1647 is_non_exhaustive: variant.is_field_list_non_exhaustive(),
1648 };
1649 record!(self.tables.variant_data[variant.def_id] <- data);
1650
1651 record_array!(self.tables.associated_item_or_field_def_ids[variant.def_id] <- variant.fields.iter().map(|f| {
1652 assert!(f.did.is_local());
1653 f.did.index
1654 }));
1655
1656 for field in &variant.fields {
1657 self.tables.safety.set_some(field.did.index, field.safety);
1658 }
1659
1660 if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
1661 let fn_sig = tcx.fn_sig(ctor_def_id);
1662 record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
1664 }
1665 }
1666
1667 if let Some(destructor) = tcx.adt_destructor(local_def_id) {
1668 record!(self.tables.adt_destructor[def_id] <- destructor);
1669 }
1670
1671 if let Some(destructor) = tcx.adt_async_destructor(local_def_id) {
1672 record!(self.tables.adt_async_destructor[def_id] <- destructor);
1673 }
1674 }
1675
1676 #[instrument(level = "debug", skip(self))]
1677 fn encode_info_for_mod(&mut self, local_def_id: LocalDefId) {
1678 let tcx = self.tcx;
1679 let def_id = local_def_id.to_def_id();
1680
1681 if self.is_proc_macro {
1687 record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
1689 } else {
1690 let module_children = tcx.module_children_local(local_def_id);
1691
1692 record_array!(self.tables.module_children_non_reexports[def_id] <-
1693 module_children.iter().filter(|child| child.reexport_chain.is_empty())
1694 .map(|child| child.res.def_id().index));
1695
1696 record_defaulted_array!(self.tables.module_children_reexports[def_id] <-
1697 module_children.iter().filter(|child| !child.reexport_chain.is_empty()));
1698 }
1699 }
1700
1701 fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
1702 debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
1703 let bounds = self.tcx.explicit_item_bounds(def_id).skip_binder();
1704 record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
1705 }
1706
1707 fn encode_explicit_item_self_bounds(&mut self, def_id: DefId) {
1708 debug!("EncodeContext::encode_explicit_item_self_bounds({:?})", def_id);
1709 let bounds = self.tcx.explicit_item_self_bounds(def_id).skip_binder();
1710 record_defaulted_array!(self.tables.explicit_item_self_bounds[def_id] <- bounds);
1711 }
1712
1713 #[instrument(level = "debug", skip(self))]
1714 fn encode_info_for_assoc_item(&mut self, def_id: DefId) {
1715 let tcx = self.tcx;
1716 let item = tcx.associated_item(def_id);
1717
1718 self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
1719 self.tables.assoc_container.set_some(def_id.index, item.container);
1720
1721 match item.container {
1722 AssocItemContainer::Trait => {
1723 if item.is_type() {
1724 self.encode_explicit_item_bounds(def_id);
1725 self.encode_explicit_item_self_bounds(def_id);
1726 if tcx.is_conditionally_const(def_id) {
1727 record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
1728 <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder());
1729 }
1730 }
1731 }
1732 AssocItemContainer::Impl => {
1733 if let Some(trait_item_def_id) = item.trait_item_def_id {
1734 self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
1735 }
1736 }
1737 }
1738 if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind {
1739 record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info);
1740 if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) {
1741 record_array!(
1742 self.tables.assumed_wf_types_for_rpitit[def_id]
1743 <- self.tcx.assumed_wf_types_for_rpitit(def_id)
1744 );
1745 self.encode_precise_capturing_args(def_id);
1746 }
1747 }
1748 }
1749
1750 fn encode_precise_capturing_args(&mut self, def_id: DefId) {
1751 let Some(precise_capturing_args) = self.tcx.rendered_precise_capturing_args(def_id) else {
1752 return;
1753 };
1754
1755 record_array!(self.tables.rendered_precise_capturing_args[def_id] <- precise_capturing_args);
1756 }
1757
1758 fn encode_mir(&mut self) {
1759 if self.is_proc_macro {
1760 return;
1761 }
1762
1763 let tcx = self.tcx;
1764 let reachable_set = tcx.reachable_set(());
1765
1766 let keys_and_jobs = tcx.mir_keys(()).iter().filter_map(|&def_id| {
1767 let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id);
1768 if encode_const || encode_opt { Some((def_id, encode_const, encode_opt)) } else { None }
1769 });
1770 for (def_id, encode_const, encode_opt) in keys_and_jobs {
1771 debug_assert!(encode_const || encode_opt);
1772
1773 debug!("EntryBuilder::encode_mir({:?})", def_id);
1774 if encode_opt {
1775 record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
1776 self.tables
1777 .cross_crate_inlinable
1778 .set(def_id.to_def_id().index, self.tcx.cross_crate_inlinable(def_id));
1779 record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
1780 <- tcx.closure_saved_names_of_captured_variables(def_id));
1781
1782 if self.tcx.is_coroutine(def_id.to_def_id())
1783 && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id)
1784 {
1785 record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
1786 }
1787 }
1788 if encode_const {
1789 record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id));
1790
1791 let abstract_const = tcx.thir_abstract_const(def_id);
1793 if let Ok(Some(abstract_const)) = abstract_const {
1794 record!(self.tables.thir_abstract_const[def_id.to_def_id()] <- abstract_const);
1795 }
1796
1797 if should_encode_const(tcx.def_kind(def_id)) {
1798 let qualifs = tcx.mir_const_qualif(def_id);
1799 record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs);
1800 let body = tcx.hir_maybe_body_owned_by(def_id);
1801 if let Some(body) = body {
1802 let const_data = rendered_const(self.tcx, &body, def_id);
1803 record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data);
1804 }
1805 }
1806 }
1807 record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
1808
1809 if self.tcx.is_coroutine(def_id.to_def_id())
1810 && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id)
1811 {
1812 record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
1813 }
1814 }
1815
1816 if tcx.sess.opts.output_types.should_codegen()
1820 && tcx.sess.opts.optimize != OptLevel::No
1821 && tcx.sess.opts.incremental.is_none()
1822 {
1823 for &local_def_id in tcx.mir_keys(()) {
1824 if let DefKind::AssocFn | DefKind::Fn = tcx.def_kind(local_def_id) {
1825 record_array!(self.tables.deduced_param_attrs[local_def_id.to_def_id()] <-
1826 self.tcx.deduced_param_attrs(local_def_id.to_def_id()));
1827 }
1828 }
1829 }
1830 }
1831
1832 #[instrument(level = "debug", skip(self))]
1833 fn encode_stability(&mut self, def_id: DefId) {
1834 if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
1837 if let Some(stab) = self.tcx.lookup_stability(def_id) {
1838 record!(self.tables.lookup_stability[def_id] <- stab)
1839 }
1840 }
1841 }
1842
1843 #[instrument(level = "debug", skip(self))]
1844 fn encode_const_stability(&mut self, def_id: DefId) {
1845 if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
1848 if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
1849 record!(self.tables.lookup_const_stability[def_id] <- stab)
1850 }
1851 }
1852 }
1853
1854 #[instrument(level = "debug", skip(self))]
1855 fn encode_default_body_stability(&mut self, def_id: DefId) {
1856 if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
1859 if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) {
1860 record!(self.tables.lookup_default_body_stability[def_id] <- stab)
1861 }
1862 }
1863 }
1864
1865 #[instrument(level = "debug", skip(self))]
1866 fn encode_deprecation(&mut self, def_id: DefId) {
1867 if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
1868 record!(self.tables.lookup_deprecation_entry[def_id] <- depr);
1869 }
1870 }
1871
1872 #[instrument(level = "debug", skip(self))]
1873 fn encode_info_for_macro(&mut self, def_id: LocalDefId) {
1874 let tcx = self.tcx;
1875
1876 let (_, macro_def, _) = tcx.hir_expect_item(def_id).expect_macro();
1877 self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules);
1878 record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
1879 }
1880
1881 fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
1882 empty_proc_macro!(self);
1883 let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1884 self.lazy_array(used_libraries.iter())
1885 }
1886
1887 fn encode_foreign_modules(&mut self) -> LazyArray<ForeignModule> {
1888 empty_proc_macro!(self);
1889 let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
1890 self.lazy_array(foreign_modules.iter().map(|(_, m)| m).cloned())
1891 }
1892
1893 fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
1894 let mut syntax_contexts: TableBuilder<_, _> = Default::default();
1895 let mut expn_data_table: TableBuilder<_, _> = Default::default();
1896 let mut expn_hash_table: TableBuilder<_, _> = Default::default();
1897
1898 self.hygiene_ctxt.encode(
1899 &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
1900 |(this, syntax_contexts, _, _), index, ctxt_data| {
1901 syntax_contexts.set_some(index, this.lazy(ctxt_data));
1902 },
1903 |(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
1904 if let Some(index) = index.as_local() {
1905 expn_data_table.set_some(index.as_raw(), this.lazy(expn_data));
1906 expn_hash_table.set_some(index.as_raw(), this.lazy(hash));
1907 }
1908 },
1909 );
1910
1911 (
1912 syntax_contexts.encode(&mut self.opaque),
1913 expn_data_table.encode(&mut self.opaque),
1914 expn_hash_table.encode(&mut self.opaque),
1915 )
1916 }
1917
1918 fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
1919 let is_proc_macro = self.tcx.crate_types().contains(&CrateType::ProcMacro);
1920 if is_proc_macro {
1921 let tcx = self.tcx;
1922 let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
1923 let stability = tcx.lookup_stability(CRATE_DEF_ID);
1924 let macros =
1925 self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
1926 for (i, span) in self.tcx.sess.psess.proc_macro_quoted_spans() {
1927 let span = self.lazy(span);
1928 self.tables.proc_macro_quoted_spans.set_some(i, span);
1929 }
1930
1931 self.tables.def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
1932 record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
1933 self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local());
1934 let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index);
1935 record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- vis);
1936 if let Some(stability) = stability {
1937 record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
1938 }
1939 self.encode_deprecation(LOCAL_CRATE.as_def_id());
1940 if let Some(res_map) = tcx.resolutions(()).doc_link_resolutions.get(&CRATE_DEF_ID) {
1941 record!(self.tables.doc_link_resolutions[LOCAL_CRATE.as_def_id()] <- res_map);
1942 }
1943 if let Some(traits) = tcx.resolutions(()).doc_link_traits_in_scope.get(&CRATE_DEF_ID) {
1944 record_array!(self.tables.doc_link_traits_in_scope[LOCAL_CRATE.as_def_id()] <- traits);
1945 }
1946
1947 for &proc_macro in &tcx.resolutions(()).proc_macros {
1951 let id = proc_macro;
1952 let proc_macro = tcx.local_def_id_to_hir_id(proc_macro);
1953 let mut name = tcx.hir_name(proc_macro);
1954 let span = tcx.hir_span(proc_macro);
1955 let attrs = tcx.hir_attrs(proc_macro);
1958 let macro_kind = if ast::attr::contains_name(attrs, sym::proc_macro) {
1959 MacroKind::Bang
1960 } else if ast::attr::contains_name(attrs, sym::proc_macro_attribute) {
1961 MacroKind::Attr
1962 } else if let Some(attr) = ast::attr::find_by_name(attrs, sym::proc_macro_derive) {
1963 name = attr.meta_item_list().unwrap()[0]
1965 .meta_item()
1966 .unwrap()
1967 .ident()
1968 .unwrap()
1969 .name;
1970 MacroKind::Derive
1971 } else {
1972 bug!("Unknown proc-macro type for item {:?}", id);
1973 };
1974
1975 let mut def_key = self.tcx.hir_def_key(id);
1976 def_key.disambiguated_data.data = DefPathData::MacroNs(name);
1977
1978 let def_id = id.to_def_id();
1979 self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
1980 self.tables.proc_macro.set_some(def_id.index, macro_kind);
1981 self.encode_attrs(id);
1982 record!(self.tables.def_keys[def_id] <- def_key);
1983 record!(self.tables.def_ident_span[def_id] <- span);
1984 record!(self.tables.def_span[def_id] <- span);
1985 record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
1986 if let Some(stability) = stability {
1987 record!(self.tables.lookup_stability[def_id] <- stability);
1988 }
1989 }
1990
1991 Some(ProcMacroData { proc_macro_decls_static, stability, macros })
1992 } else {
1993 None
1994 }
1995 }
1996
1997 fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
1998 empty_proc_macro!(self);
1999 self.lazy_array(
2000 self.tcx
2001 .debugger_visualizers(LOCAL_CRATE)
2002 .iter()
2003 .map(DebuggerVisualizerFile::path_erased),
2008 )
2009 }
2010
2011 fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
2012 empty_proc_macro!(self);
2013
2014 let deps = self
2015 .tcx
2016 .crates(())
2017 .iter()
2018 .map(|&cnum| {
2019 let dep = CrateDep {
2020 name: self.tcx.crate_name(cnum),
2021 hash: self.tcx.crate_hash(cnum),
2022 host_hash: self.tcx.crate_host_hash(cnum),
2023 kind: self.tcx.dep_kind(cnum),
2024 extra_filename: self.tcx.extra_filename(cnum).clone(),
2025 is_private: self.tcx.is_private_dep(cnum),
2026 };
2027 (cnum, dep)
2028 })
2029 .collect::<Vec<_>>();
2030
2031 {
2032 let mut expected_cnum = 1;
2034 for &(n, _) in &deps {
2035 assert_eq!(n, CrateNum::new(expected_cnum));
2036 expected_cnum += 1;
2037 }
2038 }
2039
2040 self.lazy_array(deps.iter().map(|(_, dep)| dep))
2045 }
2046
2047 fn encode_target_modifiers(&mut self) -> LazyArray<TargetModifier> {
2048 empty_proc_macro!(self);
2049 let tcx = self.tcx;
2050 self.lazy_array(tcx.sess.opts.gather_target_modifiers())
2051 }
2052
2053 fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
2054 empty_proc_macro!(self);
2055 let tcx = self.tcx;
2056 let lib_features = tcx.lib_features(LOCAL_CRATE);
2057 self.lazy_array(lib_features.to_sorted_vec())
2058 }
2059
2060 fn encode_stability_implications(&mut self) -> LazyArray<(Symbol, Symbol)> {
2061 empty_proc_macro!(self);
2062 let tcx = self.tcx;
2063 let implications = tcx.stability_implications(LOCAL_CRATE);
2064 let sorted = implications.to_sorted_stable_ord();
2065 self.lazy_array(sorted.into_iter().map(|(k, v)| (*k, *v)))
2066 }
2067
2068 fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
2069 empty_proc_macro!(self);
2070 let tcx = self.tcx;
2071 let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id;
2072 self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
2073 }
2074
2075 fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, LangItem)> {
2076 empty_proc_macro!(self);
2077 let lang_items = self.tcx.lang_items().iter();
2078 self.lazy_array(lang_items.filter_map(|(lang_item, def_id)| {
2079 def_id.as_local().map(|id| (id.local_def_index, lang_item))
2080 }))
2081 }
2082
2083 fn encode_lang_items_missing(&mut self) -> LazyArray<LangItem> {
2084 empty_proc_macro!(self);
2085 let tcx = self.tcx;
2086 self.lazy_array(&tcx.lang_items().missing)
2087 }
2088
2089 fn encode_stripped_cfg_items(&mut self) -> LazyArray<StrippedCfgItem<DefIndex>> {
2090 self.lazy_array(
2091 self.tcx
2092 .stripped_cfg_items(LOCAL_CRATE)
2093 .into_iter()
2094 .map(|item| item.clone().map_mod_id(|def_id| def_id.index)),
2095 )
2096 }
2097
2098 fn encode_traits(&mut self) -> LazyArray<DefIndex> {
2099 empty_proc_macro!(self);
2100 self.lazy_array(self.tcx.traits(LOCAL_CRATE).iter().map(|def_id| def_id.index))
2101 }
2102
2103 #[instrument(level = "debug", skip(self))]
2105 fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
2106 empty_proc_macro!(self);
2107 let tcx = self.tcx;
2108 let mut trait_impls: FxIndexMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
2109 FxIndexMap::default();
2110
2111 for id in tcx.hir_free_items() {
2112 let DefKind::Impl { of_trait } = tcx.def_kind(id.owner_id) else {
2113 continue;
2114 };
2115 let def_id = id.owner_id.to_def_id();
2116
2117 self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
2118
2119 if of_trait && let Some(header) = tcx.impl_trait_header(def_id) {
2120 record!(self.tables.impl_trait_header[def_id] <- header);
2121
2122 let trait_ref = header.trait_ref.instantiate_identity();
2123 let simplified_self_ty = fast_reject::simplify_type(
2124 self.tcx,
2125 trait_ref.self_ty(),
2126 TreatParams::InstantiateWithInfer,
2127 );
2128 trait_impls
2129 .entry(trait_ref.def_id)
2130 .or_default()
2131 .push((id.owner_id.def_id.local_def_index, simplified_self_ty));
2132
2133 let trait_def = tcx.trait_def(trait_ref.def_id);
2134 if let Ok(mut an) = trait_def.ancestors(tcx, def_id) {
2135 if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
2136 self.tables.impl_parent.set_some(def_id.index, parent.into());
2137 }
2138 }
2139
2140 if tcx.is_lang_item(trait_ref.def_id, LangItem::CoerceUnsized) {
2143 let coerce_unsized_info = tcx.coerce_unsized_info(def_id).unwrap();
2144 record!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info);
2145 }
2146 }
2147 }
2148
2149 let trait_impls: Vec<_> = trait_impls
2150 .into_iter()
2151 .map(|(trait_def_id, impls)| TraitImpls {
2152 trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
2153 impls: self.lazy_array(&impls),
2154 })
2155 .collect();
2156
2157 self.lazy_array(&trait_impls)
2158 }
2159
2160 #[instrument(level = "debug", skip(self))]
2161 fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
2162 empty_proc_macro!(self);
2163 let tcx = self.tcx;
2164
2165 let all_impls: Vec<_> = tcx
2166 .crate_inherent_impls(())
2167 .0
2168 .incoherent_impls
2169 .iter()
2170 .map(|(&simp, impls)| IncoherentImpls {
2171 self_ty: simp,
2172 impls: self.lazy_array(impls.iter().map(|def_id| def_id.local_def_index)),
2173 })
2174 .collect();
2175
2176 self.lazy_array(&all_impls)
2177 }
2178
2179 fn encode_exportable_items(&mut self) -> LazyArray<DefIndex> {
2180 empty_proc_macro!(self);
2181 self.lazy_array(self.tcx.exportable_items(LOCAL_CRATE).iter().map(|def_id| def_id.index))
2182 }
2183
2184 fn encode_stable_order_of_exportable_impls(&mut self) -> LazyArray<(DefIndex, usize)> {
2185 empty_proc_macro!(self);
2186 let stable_order_of_exportable_impls =
2187 self.tcx.stable_order_of_exportable_impls(LOCAL_CRATE);
2188 self.lazy_array(
2189 stable_order_of_exportable_impls.iter().map(|(def_id, idx)| (def_id.index, *idx)),
2190 )
2191 }
2192
2193 fn encode_exported_symbols(
2200 &mut self,
2201 exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)],
2202 ) -> LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)> {
2203 empty_proc_macro!(self);
2204 let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx));
2207
2208 self.lazy_array(
2209 exported_symbols
2210 .iter()
2211 .filter(|&(exported_symbol, _)| match *exported_symbol {
2212 ExportedSymbol::NoDefId(symbol_name) => symbol_name != metadata_symbol_name,
2213 _ => true,
2214 })
2215 .cloned(),
2216 )
2217 }
2218
2219 fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> {
2220 empty_proc_macro!(self);
2221 let formats = self.tcx.dependency_formats(());
2222 if let Some(arr) = formats.get(&CrateType::Dylib) {
2223 return self.lazy_array(arr.iter().skip(1 ).map(
2224 |slot| match *slot {
2225 Linkage::NotLinked | Linkage::IncludedFromDylib => None,
2226
2227 Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
2228 Linkage::Static => Some(LinkagePreference::RequireStatic),
2229 },
2230 ));
2231 }
2232 LazyArray::default()
2233 }
2234}
2235
2236fn prefetch_mir(tcx: TyCtxt<'_>) {
2239 if !tcx.sess.opts.output_types.should_codegen() {
2240 return;
2242 }
2243
2244 let reachable_set = tcx.reachable_set(());
2245 par_for_each_in(tcx.mir_keys(()), |&&def_id| {
2246 let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id);
2247
2248 if encode_const {
2249 tcx.ensure_done().mir_for_ctfe(def_id);
2250 }
2251 if encode_opt {
2252 tcx.ensure_done().optimized_mir(def_id);
2253 }
2254 if encode_opt || encode_const {
2255 tcx.ensure_done().promoted_mir(def_id);
2256 }
2257 })
2258}
2259
2260pub struct EncodedMetadata {
2284 full_metadata: Option<Mmap>,
2287 stub_metadata: Option<Vec<u8>>,
2290 _temp_dir: Option<MaybeTempDir>,
2293}
2294
2295impl EncodedMetadata {
2296 #[inline]
2297 pub fn from_path(
2298 path: PathBuf,
2299 stub_path: Option<PathBuf>,
2300 temp_dir: Option<MaybeTempDir>,
2301 ) -> std::io::Result<Self> {
2302 let file = std::fs::File::open(&path)?;
2303 let file_metadata = file.metadata()?;
2304 if file_metadata.len() == 0 {
2305 return Ok(Self { full_metadata: None, stub_metadata: None, _temp_dir: None });
2306 }
2307 let full_mmap = unsafe { Some(Mmap::map(file)?) };
2308
2309 let stub =
2310 if let Some(stub_path) = stub_path { Some(std::fs::read(stub_path)?) } else { None };
2311
2312 Ok(Self { full_metadata: full_mmap, stub_metadata: stub, _temp_dir: temp_dir })
2313 }
2314
2315 #[inline]
2316 pub fn full(&self) -> &[u8] {
2317 &self.full_metadata.as_deref().unwrap_or_default()
2318 }
2319
2320 #[inline]
2321 pub fn stub_or_full(&self) -> &[u8] {
2322 self.stub_metadata.as_deref().unwrap_or(self.full())
2323 }
2324}
2325
2326impl<S: Encoder> Encodable<S> for EncodedMetadata {
2327 fn encode(&self, s: &mut S) {
2328 self.stub_metadata.encode(s);
2329
2330 let slice = self.full();
2331 slice.encode(s)
2332 }
2333}
2334
2335impl<D: Decoder> Decodable<D> for EncodedMetadata {
2336 fn decode(d: &mut D) -> Self {
2337 let stub = <Option<Vec<u8>>>::decode(d);
2338
2339 let len = d.read_usize();
2340 let full_metadata = if len > 0 {
2341 let mut mmap = MmapMut::map_anon(len).unwrap();
2342 mmap.copy_from_slice(d.read_raw_bytes(len));
2343 Some(mmap.make_read_only().unwrap())
2344 } else {
2345 None
2346 };
2347
2348 Self { full_metadata, stub_metadata: stub, _temp_dir: None }
2349 }
2350}
2351
2352pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
2353 let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
2354
2355 tcx.dep_graph.assert_ignored();
2358
2359 if tcx.sess.threads() != 1 {
2360 join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
2364 }
2365
2366 with_encode_metadata_header(tcx, path, |ecx| {
2367 let root = ecx.encode_crate_root();
2370
2371 ecx.opaque.flush();
2373 tcx.prof.artifact_size(
2375 "crate_metadata",
2376 "crate_metadata",
2377 ecx.opaque.file().metadata().unwrap().len(),
2378 );
2379
2380 root.position.get()
2381 });
2382
2383 if let Some(ref_path) = ref_path {
2384 with_encode_metadata_header(tcx, ref_path, |ecx| {
2385 let header: LazyValue<CrateHeader> = ecx.lazy(CrateHeader {
2386 name: tcx.crate_name(LOCAL_CRATE),
2387 triple: tcx.sess.opts.target_triple.clone(),
2388 hash: tcx.crate_hash(LOCAL_CRATE),
2389 is_proc_macro_crate: false,
2390 is_stub: true,
2391 });
2392 header.position.get()
2393 });
2394 }
2395}
2396
2397fn with_encode_metadata_header(
2398 tcx: TyCtxt<'_>,
2399 path: &Path,
2400 f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize,
2401) {
2402 let mut encoder = opaque::FileEncoder::new(path)
2403 .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err }));
2404 encoder.emit_raw_bytes(METADATA_HEADER);
2405
2406 encoder.emit_raw_bytes(&0u64.to_le_bytes());
2408
2409 let source_map_files = tcx.sess.source_map().files();
2410 let source_file_cache = (Arc::clone(&source_map_files[0]), 0);
2411 let required_source_files = Some(FxIndexSet::default());
2412 drop(source_map_files);
2413
2414 let hygiene_ctxt = HygieneEncodeContext::default();
2415
2416 let mut ecx = EncodeContext {
2417 opaque: encoder,
2418 tcx,
2419 feat: tcx.features(),
2420 tables: Default::default(),
2421 lazy_state: LazyState::NoNode,
2422 span_shorthands: Default::default(),
2423 type_shorthands: Default::default(),
2424 predicate_shorthands: Default::default(),
2425 source_file_cache,
2426 interpret_allocs: Default::default(),
2427 required_source_files,
2428 is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro),
2429 hygiene_ctxt: &hygiene_ctxt,
2430 symbol_table: Default::default(),
2431 };
2432
2433 rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
2435
2436 let root_position = f(&mut ecx);
2437
2438 if let Err((path, err)) = ecx.opaque.finish() {
2442 tcx.dcx().emit_fatal(FailWriteFile { path: &path, err });
2443 }
2444
2445 let file = ecx.opaque.file();
2446 if let Err(err) = encode_root_position(file, root_position) {
2447 tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err });
2448 }
2449}
2450
2451fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> {
2452 let pos_before_seek = file.stream_position().unwrap();
2454
2455 let header = METADATA_HEADER.len();
2457 file.seek(std::io::SeekFrom::Start(header as u64))?;
2458 file.write_all(&pos.to_le_bytes())?;
2459
2460 file.seek(std::io::SeekFrom::Start(pos_before_seek))?;
2462 Ok(())
2463}
2464
2465pub(crate) fn provide(providers: &mut Providers) {
2466 *providers = Providers {
2467 doc_link_resolutions: |tcx, def_id| {
2468 tcx.resolutions(())
2469 .doc_link_resolutions
2470 .get(&def_id)
2471 .unwrap_or_else(|| span_bug!(tcx.def_span(def_id), "no resolutions for a doc link"))
2472 },
2473 doc_link_traits_in_scope: |tcx, def_id| {
2474 tcx.resolutions(()).doc_link_traits_in_scope.get(&def_id).unwrap_or_else(|| {
2475 span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link")
2476 })
2477 },
2478
2479 ..*providers
2480 }
2481}
2482
2483pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: LocalDefId) -> String {
2511 let value = body.value;
2512
2513 #[derive(PartialEq, Eq)]
2514 enum Classification {
2515 Literal,
2516 Simple,
2517 Complex,
2518 }
2519
2520 use Classification::*;
2521
2522 fn classify(expr: &hir::Expr<'_>) -> Classification {
2523 match &expr.kind {
2524 hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
2525 if matches!(expr.kind, hir::ExprKind::Lit(_)) { Literal } else { Complex }
2526 }
2527 hir::ExprKind::Lit(_) => Literal,
2528 hir::ExprKind::Tup([]) => Simple,
2529 hir::ExprKind::Block(hir::Block { stmts: [], expr: Some(expr), .. }, _) => {
2530 if classify(expr) == Complex { Complex } else { Simple }
2531 }
2532 hir::ExprKind::Path(hir::QPath::Resolved(_, hir::Path { segments, .. })) => {
2537 if segments.iter().all(|segment| segment.args.is_none()) { Simple } else { Complex }
2538 }
2539 hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => Simple,
2542 hir::ExprKind::Path(hir::QPath::LangItem(..)) => Simple,
2544 _ => Complex,
2545 }
2546 }
2547
2548 match classify(value) {
2549 Literal
2559 if !value.span.from_expansion()
2560 && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(value.span) =>
2561 {
2562 snippet
2563 }
2564
2565 Literal | Simple => id_to_string(&tcx, body.id().hir_id),
2568
2569 Complex => {
2573 if tcx.def_kind(def_id) == DefKind::AnonConst {
2574 "{ _ }".to_owned()
2575 } else {
2576 "_".to_owned()
2577 }
2578 }
2579 }
2580}