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