1 use crate::errors
::{FailCreateFileEncoder, FailWriteFile}
;
4 use rustc_ast
::Attribute
;
5 use rustc_data_structures
::fx
::FxIndexSet
;
6 use rustc_data_structures
::memmap
::{Mmap, MmapMut}
;
7 use rustc_data_structures
::sync
::{join, par_for_each_in, Lrc}
;
8 use rustc_data_structures
::temp_dir
::MaybeTempDir
;
10 use rustc_hir
::def_id
::{LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}
;
11 use rustc_hir
::definitions
::DefPathData
;
12 use rustc_hir_pretty
::id_to_string
;
13 use rustc_middle
::middle
::dependency_format
::Linkage
;
14 use rustc_middle
::middle
::exported_symbols
::metadata_symbol_name
;
15 use rustc_middle
::mir
::interpret
;
16 use rustc_middle
::query
::LocalCrate
;
17 use rustc_middle
::query
::Providers
;
18 use rustc_middle
::traits
::specialization_graph
;
19 use rustc_middle
::ty
::codec
::TyEncoder
;
20 use rustc_middle
::ty
::fast_reject
::{self, TreatParams}
;
21 use rustc_middle
::ty
::{AssocItemContainer, SymbolName}
;
22 use rustc_middle
::util
::common
::to_readable_str
;
23 use rustc_serialize
::{opaque, Decodable, Decoder, Encodable, Encoder}
;
24 use rustc_session
::config
::{CrateType, OptLevel}
;
25 use rustc_span
::hygiene
::HygieneEncodeContext
;
26 use rustc_span
::symbol
::sym
;
28 ExternalSource
, FileName
, SourceFile
, SpanData
, SpanEncoder
, StableSourceFileId
, SyntaxContext
,
30 use std
::borrow
::Borrow
;
31 use std
::collections
::hash_map
::Entry
;
33 use std
::io
::{Read, Seek, Write}
;
34 use std
::path
::{Path, PathBuf}
;
36 pub(super) struct EncodeContext
<'a
, 'tcx
> {
37 opaque
: opaque
::FileEncoder
,
39 feat
: &'tcx rustc_feature
::Features
,
40 tables
: TableBuilders
,
42 lazy_state
: LazyState
,
43 span_shorthands
: FxHashMap
<Span
, usize>,
44 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
45 predicate_shorthands
: FxHashMap
<ty
::PredicateKind
<'tcx
>, usize>,
47 interpret_allocs
: FxIndexSet
<interpret
::AllocId
>,
49 // This is used to speed up Span encoding.
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
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>>,
61 hygiene_ctxt
: &'a HygieneEncodeContext
,
62 symbol_table
: FxHashMap
<Symbol
, usize>,
65 /// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
66 /// This is useful for skipping the encoding of things that aren't needed
67 /// for proc-macro crates.
68 macro_rules
! empty_proc_macro
{
70 if $
self.is_proc_macro
{
71 return LazyArray
::default();
76 macro_rules
! encoder_methods
{
77 ($
($name
:ident($ty
:ty
);)*) => {
78 $
(fn $
name(&mut self, value
: $ty
) {
79 self.opaque
.$
name(value
)
84 impl<'a
, 'tcx
> Encoder
for EncodeContext
<'a
, 'tcx
> {
99 emit_raw_bytes(&[u8]);
103 impl<'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
);
109 impl<'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
)
118 impl<'a
, 'tcx
, I
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyTable
<I
, T
> {
119 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
120 e
.emit_usize(self.width
);
121 e
.emit_usize(self.len
);
122 e
.emit_lazy_distance(self.position
);
126 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnIndex
{
127 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
128 s
.emit_u32(self.as_u32());
132 impl<'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");
137 self.emit_u32(crate_num
.as_u32());
140 fn encode_def_index(&mut self, def_index
: DefIndex
) {
141 self.emit_u32(def_index
.as_u32());
144 fn encode_def_id(&mut self, def_id
: DefId
) {
145 def_id
.krate
.encode(self);
146 def_id
.index
.encode(self);
149 fn encode_syntax_context(&mut self, syntax_context
: SyntaxContext
) {
150 rustc_span
::hygiene
::raw_encode_syntax_context(syntax_context
, self.hygiene_ctxt
, self);
153 fn encode_expn_id(&mut self, expn_id
: ExpnId
) {
154 if expn_id
.krate
== LOCAL_CRATE
{
155 // We will only write details for local expansions. Non-local expansions will fetch
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.
159 self.hygiene_ctxt
.schedule_expn_data_for_encoding(expn_id
);
161 expn_id
.krate
.encode(self);
162 expn_id
.local_id
.encode(self);
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
{
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();
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();
190 Entry
::Vacant(v
) => {
191 let position
= self.opaque
.position();
193 // Data is encoded with a SpanTag prefix (see below).
194 span
.data().encode(self);
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());
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();
211 self.emit_str(symbol
.as_str());
213 Entry
::Occupied(o
) => {
215 self.emit_u8(SYMBOL_OFFSET
);
223 fn bytes_needed(n
: usize) -> usize {
224 (usize::BITS
- n
.leading_zeros()).div_ceil(u8::BITS
) as usize
227 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for SpanData
{
228 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
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.
235 // This can show up in two ways:
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.
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.
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.
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.
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.
260 let ctxt
= if s
.is_proc_macro { SyntaxContext::root() }
else { self.ctxt }
;
263 let tag
= SpanTag
::new(SpanKind
::Partial
, ctxt
, 0);
265 if tag
.context().is_none() {
271 // The Span infrastructure should make sure that this invariant holds:
272 debug_assert
!(self.lo
<= self.hi
);
274 if !s
.source_file_cache
.0.contains(self.lo
) {
275 let source_map
= s
.tcx
.sess
.source_map();
276 let source_file_index
= source_map
.lookup_source_file_idx(self.lo
);
277 s
.source_file_cache
=
278 (source_map
.files()[source_file_index
].clone(), source_file_index
);
280 let (ref source_file
, source_file_index
) = s
.source_file_cache
;
281 debug_assert
!(source_file
.contains(self.lo
));
283 if !source_file
.contains(self.hi
) {
284 // Unfortunately, macro expansion still sometimes generates Spans
285 // that malformed in this way.
286 let tag
= SpanTag
::new(SpanKind
::Partial
, ctxt
, 0);
288 if tag
.context().is_none() {
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.
301 // 2. This span comes from our own crate. No special handling is needed - we just
302 // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
303 // our own source map information.
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.
310 let (kind
, metadata_index
) = if source_file
.is_imported() && !s
.is_proc_macro
{
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
315 // search through the 'foreign' crate's source map information, using the
316 // deserialized 'lo' and 'hi' values directly.
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.
320 let metadata_index
= {
321 // Introduce a new scope so that we drop the 'read()' temporary
322 match &*source_file
.external_src
.read() {
323 ExternalSource
::Foreign { metadata_index, .. }
=> *metadata_index
,
324 src
=> panic
!("Unexpected external source {src:?}"),
328 (SpanKind
::Foreign
, metadata_index
)
330 // Record the fact that we need to encode the data for this `SourceFile`
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");
337 (SpanKind
::Local
, metadata_index
)
340 // Encode the start position relative to the file start, so we profit more from the
341 // variable-length integer encoding.
342 let lo
= self.lo
- source_file
.start_pos
;
344 // Encode length which is usually less than span.hi and profits more
345 // from the variable-length integer encoding that we use.
346 let len
= self.hi
- self.lo
;
348 let tag
= SpanTag
::new(kind
, ctxt
, len
.0 as usize);
350 if tag
.context().is_none() {
354 if tag
.length().is_none() {
358 // Encode the index of the `SourceFile` for the span, in order to make decoding faster.
359 metadata_index
.encode(s
);
361 if kind
== SpanKind
::Foreign
{
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
;
370 impl<'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);
377 impl<'a
, 'tcx
> TyEncoder
for EncodeContext
<'a
, 'tcx
> {
378 const CLEAR_CROSS_CRATE
: bool
= true;
380 type I
= TyCtxt
<'tcx
>;
382 fn position(&self) -> usize {
383 self.opaque
.position()
386 fn type_shorthands(&mut self) -> &mut FxHashMap
<Ty
<'tcx
>, usize> {
387 &mut self.type_shorthands
390 fn predicate_shorthands(&mut self) -> &mut FxHashMap
<ty
::PredicateKind
<'tcx
>, usize> {
391 &mut self.predicate_shorthands
394 fn encode_alloc_id(&mut self, alloc_id
: &rustc_middle
::mir
::interpret
::AllocId
) {
395 let (index
, _
) = self.interpret_allocs
.insert_full(*alloc_id
);
401 // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy($value))`, which would
402 // normally need extra variables to avoid errors about multiple mutable borrows.
403 macro_rules
! record
{
404 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
407 let lazy
= $
self.lazy(value
);
408 $
self.$tables
.$table
.set_some($def_id
.index
, lazy
);
413 // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would
414 // normally need extra variables to avoid errors about multiple mutable borrows.
415 macro_rules
! record_array
{
416 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
419 let lazy
= $
self.lazy_array(value
);
420 $
self.$tables
.$table
.set_some($def_id
.index
, lazy
);
425 macro_rules
! record_defaulted_array
{
426 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
429 let lazy
= $
self.lazy_array(value
);
430 $
self.$tables
.$table
.set($def_id
.index
, lazy
);
435 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
436 fn emit_lazy_distance(&mut self, position
: NonZero
<usize>) {
437 let pos
= position
.get();
438 let distance
= match self.lazy_state
{
439 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
440 LazyState
::NodeStart(start
) => {
441 let start
= start
.get();
442 assert
!(pos
<= start
);
445 LazyState
::Previous(last_pos
) => {
447 last_pos
<= position
,
448 "make sure that the calls to `lazy*` \
449 are in the same order as the metadata fields",
451 position
.get() - last_pos
.get()
454 self.lazy_state
= LazyState
::Previous(NonZero
::new(pos
).unwrap());
455 self.emit_usize(distance
);
458 fn lazy
<T
: ParameterizedOverTcx
, B
: Borrow
<T
::Value
<'tcx
>>>(&mut self, value
: B
) -> LazyValue
<T
>
460 T
::Value
<'tcx
>: Encodable
<EncodeContext
<'a
, 'tcx
>>,
462 let pos
= NonZero
::new(self.position()).unwrap();
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
;
469 assert
!(pos
.get() <= self.position());
471 LazyValue
::from_position(pos
)
474 fn lazy_array
<T
: ParameterizedOverTcx
, I
: IntoIterator
<Item
= B
>, B
: Borrow
<T
::Value
<'tcx
>>>(
479 T
::Value
<'tcx
>: Encodable
<EncodeContext
<'a
, 'tcx
>>,
481 let pos
= NonZero
::new(self.position()).unwrap();
483 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
484 self.lazy_state
= LazyState
::NodeStart(pos
);
485 let len
= values
.into_iter().map(|value
| value
.borrow().encode(self)).count();
486 self.lazy_state
= LazyState
::NoNode
;
488 assert
!(pos
.get() <= self.position());
490 LazyArray
::from_position_and_num_elems(pos
, len
)
493 fn encode_def_path_table(&mut self) {
494 let table
= self.tcx
.def_path_table();
495 if self.is_proc_macro
{
496 for def_index
in std
::iter
::once(CRATE_DEF_INDEX
)
497 .chain(self.tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
))
499 let def_key
= self.lazy(table
.def_key(def_index
));
500 let def_path_hash
= table
.def_path_hash(def_index
);
501 self.tables
.def_keys
.set_some(def_index
, def_key
);
502 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
.local_hash().as_u64());
505 for (def_index
, def_key
, def_path_hash
) in table
.enumerated_keys_and_path_hashes() {
506 let def_key
= self.lazy(def_key
);
507 self.tables
.def_keys
.set_some(def_index
, def_key
);
508 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
.local_hash().as_u64());
513 fn encode_def_path_hash_map(&mut self) -> LazyValue
<DefPathHashMapRef
<'
static>> {
514 self.lazy(DefPathHashMapRef
::BorrowedFromTcx(self.tcx
.def_path_hash_to_def_index_map()))
517 fn encode_source_map(&mut self) -> LazyTable
<u32, Option
<LazyValue
<rustc_span
::SourceFile
>>> {
518 let source_map
= self.tcx
.sess
.source_map();
519 let all_source_files
= source_map
.files();
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
524 let required_source_files
= self.required_source_files
.take().unwrap();
526 let working_directory
= &self.tcx
.sess
.opts
.working_dir
;
528 let mut adapted
= TableBuilder
::default();
530 let local_crate_stable_id
= self.tcx
.stable_crate_id(LOCAL_CRATE
);
532 // Only serialize `SourceFile`s that were used during the encoding of a `Span`.
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
);
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.
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.
548 let mut adapted_source_file
= (**source_file
).clone();
550 match source_file
.name
{
551 FileName
::Real(ref original_file_name
) => {
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(),
558 source_map
.path_mapping().to_local_embeddable_absolute_path(
559 original_file_name
.clone(),
564 adapted_source_file
.name
= FileName
::Real(adapted_file_name
);
567 // expanded code, not from a file
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
{
578 adapted_source_file
.cnum
= LOCAL_CRATE
;
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
,
589 let on_disk_index
: u32 =
590 on_disk_index
.try_into().expect("cannot export more than U32_MAX files");
591 adapted
.set_some(on_disk_index
, self.lazy(adapted_source_file
));
594 adapted
.encode(&mut self.opaque
)
597 fn encode_crate_root(&mut self) -> LazyValue
<CrateRoot
> {
599 let mut stats
: Vec
<(&'
static str, usize)> = Vec
::with_capacity(32);
602 ($label
:literal
, $f
:expr
) => {{
603 let orig_pos
= self.position();
605 stats
.push(($label
, self.position() - orig_pos
));
610 // We have already encoded some things. Get their combined size from the current position.
611 stats
.push(("preamble", self.position()));
613 let (crate_deps
, dylib_dependency_formats
) =
614 stat
!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
616 let lib_features
= stat
!("lib-features", || self.encode_lib_features());
618 let stability_implications
=
619 stat
!("stability-implications", || self.encode_stability_implications());
621 let (lang_items
, lang_items_missing
) = stat
!("lang-items", || {
622 (self.encode_lang_items(), self.encode_lang_items_missing())
625 let stripped_cfg_items
= stat
!("stripped-cfg-items", || self.encode_stripped_cfg_items());
627 let diagnostic_items
= stat
!("diagnostic-items", || self.encode_diagnostic_items());
629 let native_libraries
= stat
!("native-libs", || self.encode_native_libraries());
631 let foreign_modules
= stat
!("foreign-modules", || self.encode_foreign_modules());
633 _
= stat
!("def-path-table", || self.encode_def_path_table());
635 // Encode the def IDs of traits, for rustdoc and diagnostics.
636 let traits
= stat
!("traits", || self.encode_traits());
638 // Encode the def IDs of impls, for coherence checking.
639 let impls
= stat
!("impls", || self.encode_impls());
641 let incoherent_impls
= stat
!("incoherent-impls", || self.encode_incoherent_impls());
643 _
= stat
!("mir", || self.encode_mir());
645 _
= stat
!("def-ids", || self.encode_def_ids());
647 let interpret_alloc_index
= stat
!("interpret-alloc-index", || {
648 let mut interpret_alloc_index
= Vec
::new();
650 trace
!("beginning to encode alloc ids");
652 let new_n
= self.interpret_allocs
.len();
653 // if we have found new ids, serialize those, too
658 trace
!("encoding {} further alloc ids", new_n
- n
);
659 for idx
in n
..new_n
{
660 let id
= self.interpret_allocs
[idx
];
661 let pos
= self.position() as u64;
662 interpret_alloc_index
.push(pos
);
663 interpret
::specialized_encode_alloc_id(self, tcx
, id
);
667 self.lazy_array(interpret_alloc_index
)
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());
675 let tables
= stat
!("tables", || self.tables
.encode(&mut self.opaque
));
677 let debugger_visualizers
=
678 stat
!("debugger-visualizers", || self.encode_debugger_visualizers());
680 // Encode exported symbols info. This is prefetched in `encode_metadata`.
681 let exported_symbols
= stat
!("exported-symbols", || {
682 self.encode_exported_symbols(tcx
.exported_symbols(LOCAL_CRATE
))
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());
693 let def_path_hash_map
= stat
!("def-path-hash-map", || self.encode_def_path_hash_map());
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());
699 let root
= stat
!("final", || {
700 let attrs
= tcx
.hir().krate_attrs();
701 self.lazy(CrateRoot
{
702 header
: CrateHeader
{
703 name
: tcx
.crate_name(LOCAL_CRATE
),
704 triple
: tcx
.sess
.opts
.target_triple
.clone(),
705 hash
: tcx
.crate_hash(LOCAL_CRATE
),
706 is_proc_macro_crate
: proc_macro_data
.is_some(),
708 extra_filename
: tcx
.sess
.opts
.cg
.extra_filename
.clone(),
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
),
714 has_alloc_error_handler
: tcx
.has_alloc_error_handler(LOCAL_CRATE
),
715 has_panic_handler
: tcx
.has_panic_handler(LOCAL_CRATE
),
716 has_default_lib_allocator
: attr
::contains_name(attrs
, sym
::default_lib_allocator
),
718 debugger_visualizers
,
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
),
725 symbol_mangling_version
: tcx
.sess
.opts
.get_symbol_mangling_version(),
728 dylib_dependency_formats
,
730 stability_implications
,
742 interpret_alloc_index
,
751 let total_bytes
= self.position();
753 let computed_total_bytes
: usize = stats
.iter().map(|(_
, size
)| size
).sum();
754 assert_eq
!(total_bytes
, computed_total_bytes
);
756 if tcx
.sess
.opts
.unstable_opts
.meta_stats
{
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();
761 let mut zero_bytes
= 0;
762 self.opaque
.file().rewind().unwrap();
763 let file
= std
::io
::BufReader
::new(self.opaque
.file());
764 for e
in file
.bytes() {
769 assert_eq
!(self.opaque
.file().stream_position().unwrap(), pos_before_rewind
);
771 stats
.sort_by_key(|&(_
, usize)| usize);
773 let prefix
= "meta-stats";
774 let perc
= |bytes
| (bytes
* 100) as f64 / total_bytes
as f64;
776 eprintln
!("{prefix} METADATA STATS");
777 eprintln
!("{} {:<23}{:>10}", prefix
, "Section", "Size");
778 eprintln
!("{prefix} ----------------------------------------------------------------");
779 for (label
, size
) in stats
{
781 "{} {:<23}{:>10} ({:4.1}%)",
784 to_readable_str(size
),
788 eprintln
!("{prefix} ----------------------------------------------------------------");
790 "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
793 to_readable_str(total_bytes
),
796 eprintln
!("{prefix}");
803 struct AnalyzeAttrState
{
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.
812 /// Removing these superfluous attributes speeds up compilation by making the metadata smaller.
814 /// Note: the `is_exported` parameter is used to cache whether the given `DefId` has a public
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.
818 fn analyze_attr(attr
: &Attribute
, state
: &mut AnalyzeAttrState
) -> bool
{
819 let mut should_encode
= false;
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.
822 } else if attr
.doc_str().is_some() {
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
826 if state
.is_exported
{
827 should_encode
= true;
829 } else if attr
.has_name(sym
::doc
) {
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;
844 should_encode
= true;
849 fn should_encode_span(def_kind
: DefKind
) -> bool
{
859 | DefKind
::TraitAlias
862 | DefKind
::ConstParam
863 | DefKind
::LifetimeParam
866 | DefKind
::Static { .. }
869 | DefKind
::AssocConst
871 | DefKind
::ExternCrate
874 | DefKind
::InlineConst
877 | DefKind
::Impl { .. }
878 | DefKind
::Closure
=> true,
879 DefKind
::ForeignMod
| DefKind
::GlobalAsm
=> false,
883 fn should_encode_attrs(def_kind
: DefKind
) -> bool
{
893 | DefKind
::TraitAlias
897 | DefKind
::Static { nested: false, .. }
899 | DefKind
::AssocConst
902 | DefKind
::Impl { .. }
=> true,
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,
909 | DefKind
::ConstParam
911 | DefKind
::ExternCrate
913 | DefKind
::ForeignMod
915 | DefKind
::InlineConst
917 | DefKind
::LifetimeParam
918 | DefKind
::Static { nested: true, .. }
919 | DefKind
::GlobalAsm
=> false,
923 fn should_encode_expn_that_defined(def_kind
: DefKind
) -> bool
{
931 | DefKind
::Impl { .. }
=> true,
934 | DefKind
::TraitAlias
939 | DefKind
::ConstParam
940 | DefKind
::Static { .. }
943 | DefKind
::AssocConst
945 | DefKind
::ExternCrate
947 | DefKind
::ForeignMod
949 | DefKind
::InlineConst
952 | DefKind
::LifetimeParam
954 | DefKind
::Closure
=> false,
958 fn should_encode_visibility(def_kind
: DefKind
) -> bool
{
968 | DefKind
::TraitAlias
972 | DefKind
::Static { nested: false, .. }
975 | DefKind
::AssocConst
977 | DefKind
::Field
=> true,
979 | DefKind
::ForeignMod
981 | DefKind
::ConstParam
982 | DefKind
::LifetimeParam
984 | DefKind
::InlineConst
985 | DefKind
::Static { nested: true, .. }
988 | DefKind
::Impl { .. }
990 | DefKind
::ExternCrate
=> false,
994 fn should_encode_stability(def_kind
: DefKind
) -> bool
{
1003 | DefKind
::AssocConst
1005 | DefKind
::ConstParam
1006 | DefKind
::Static { .. }
1009 | DefKind
::ForeignMod
1014 | DefKind
::Impl { .. }
1016 | DefKind
::TraitAlias
1017 | DefKind
::Macro(..)
1018 | DefKind
::ForeignTy
=> true,
1020 | DefKind
::LifetimeParam
1021 | DefKind
::AnonConst
1022 | DefKind
::InlineConst
1023 | DefKind
::GlobalAsm
1025 | DefKind
::ExternCrate
=> false,
1029 /// Whether we should encode MIR. Return a pair, resp. for CTFE and for LLVM.
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.
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).
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:
1046 /// const fn f() -> usize { 0 }
1047 /// pub struct S { pub a: [usize; f()] }
1049 fn should_encode_mir(
1051 reachable_set
: &LocalDefIdSet
,
1054 match tcx
.def_kind(def_id
) {
1056 DefKind
::Ctor(_
, _
) => {
1057 let mir_opt_base
= tcx
.sess
.opts
.output_types
.should_codegen()
1058 || tcx
.sess
.opts
.unstable_opts
.always_encode_mir
;
1059 (true, mir_opt_base
)
1062 DefKind
::AnonConst
| DefKind
::InlineConst
| DefKind
::AssocConst
| DefKind
::Const
=> {
1065 // Coroutines require optimized MIR to compute layout.
1066 DefKind
::Closure
if tcx
.is_coroutine(def_id
.to_def_id()) => (false, true),
1067 // Full-fledged functions + closures
1068 DefKind
::AssocFn
| DefKind
::Fn
| DefKind
::Closure
=> {
1069 let generics
= tcx
.generics_of(def_id
);
1070 let mut opt
= tcx
.sess
.opts
.unstable_opts
.always_encode_mir
1071 || (tcx
.sess
.opts
.output_types
.should_codegen()
1072 && reachable_set
.contains(&def_id
)
1073 && (generics
.requires_monomorphization(tcx
)
1074 || tcx
.cross_crate_inlinable(def_id
)));
1075 if let Some(intrinsic
) = tcx
.intrinsic(def_id
) {
1076 opt
&= !intrinsic
.must_be_overridden
;
1078 // The function has a `const` modifier or is in a `#[const_trait]`.
1079 let is_const_fn
= tcx
.is_const_fn_raw(def_id
.to_def_id())
1080 || tcx
.is_const_default_method(def_id
.to_def_id());
1083 // The others don't have MIR.
1084 _
=> (false, false),
1088 fn should_encode_variances
<'tcx
>(tcx
: TyCtxt
<'tcx
>, def_id
: DefId
, def_kind
: DefKind
) -> bool
{
1097 | DefKind
::AssocFn
=> true,
1101 | DefKind
::AssocConst
1103 | DefKind
::ConstParam
1104 | DefKind
::Static { .. }
1106 | DefKind
::ForeignMod
1107 | DefKind
::Impl { .. }
1109 | DefKind
::TraitAlias
1110 | DefKind
::Macro(..)
1111 | DefKind
::ForeignTy
1113 | DefKind
::LifetimeParam
1114 | DefKind
::AnonConst
1115 | DefKind
::InlineConst
1116 | DefKind
::GlobalAsm
1118 | DefKind
::ExternCrate
=> false,
1119 DefKind
::TyAlias
=> tcx
.type_alias_is_lazy(def_id
),
1123 fn should_encode_generics(def_kind
: DefKind
) -> bool
{
1131 | DefKind
::ForeignTy
1132 | DefKind
::TraitAlias
1136 | DefKind
::Static { .. }
1139 | DefKind
::AssocConst
1140 | DefKind
::AnonConst
1141 | DefKind
::InlineConst
1143 | DefKind
::Impl { .. }
1146 | DefKind
::Closure
=> true,
1148 | DefKind
::ForeignMod
1149 | DefKind
::ConstParam
1150 | DefKind
::Macro(..)
1152 | DefKind
::LifetimeParam
1153 | DefKind
::GlobalAsm
1154 | DefKind
::ExternCrate
=> false,
1158 fn should_encode_type(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
, def_kind
: DefKind
) -> bool
{
1168 | DefKind
::Static { nested: false, .. }
1170 | DefKind
::ForeignTy
1171 | DefKind
::Impl { .. }
1173 | DefKind
::AssocConst
1175 | DefKind
::ConstParam
1176 | DefKind
::AnonConst
1177 | DefKind
::InlineConst
=> true,
1179 DefKind
::OpaqueTy
=> {
1180 let origin
= tcx
.opaque_type_origin(def_id
);
1181 if let hir
::OpaqueTyOrigin
::FnReturn(fn_def_id
)
1182 | hir
::OpaqueTyOrigin
::AsyncFn(fn_def_id
) = origin
1183 && let hir
::Node
::TraitItem(trait_item
) = tcx
.hir_node_by_def_id(fn_def_id
)
1184 && let (_
, hir
::TraitFn
::Required(..)) = trait_item
.expect_fn()
1192 DefKind
::AssocTy
=> {
1193 let assoc_item
= tcx
.associated_item(def_id
);
1194 match assoc_item
.container
{
1195 ty
::AssocItemContainer
::ImplContainer
=> true,
1196 ty
::AssocItemContainer
::TraitContainer
=> assoc_item
.defaultness(tcx
).has_value(),
1199 DefKind
::TyParam
=> {
1200 let hir
::Node
::GenericParam(param
) = tcx
.hir_node_by_def_id(def_id
) else { bug!() }
;
1201 let hir
::GenericParamKind
::Type { default, .. }
= param
.kind
else { bug!() }
;
1206 | DefKind
::TraitAlias
1208 | DefKind
::ForeignMod
1209 | DefKind
::Macro(..)
1210 | DefKind
::Static { nested: true, .. }
1212 | DefKind
::LifetimeParam
1213 | DefKind
::GlobalAsm
1214 | DefKind
::ExternCrate
=> false,
1218 fn should_encode_fn_sig(def_kind
: DefKind
) -> bool
{
1220 DefKind
::Fn
| DefKind
::AssocFn
| DefKind
::Ctor(_
, CtorKind
::Fn
) => true,
1228 | DefKind
::Static { .. }
1232 | DefKind
::ForeignTy
1233 | DefKind
::Impl { .. }
1234 | DefKind
::AssocConst
1236 | DefKind
::ConstParam
1237 | DefKind
::AnonConst
1238 | DefKind
::InlineConst
1242 | DefKind
::TraitAlias
1244 | DefKind
::ForeignMod
1245 | DefKind
::Macro(..)
1247 | DefKind
::LifetimeParam
1248 | DefKind
::GlobalAsm
1249 | DefKind
::ExternCrate
=> false,
1253 fn should_encode_constness(def_kind
: DefKind
) -> bool
{
1258 | DefKind
::Impl { of_trait: true }
1260 | DefKind
::Ctor(..) => true,
1267 | DefKind
::AssocConst
1268 | DefKind
::AnonConst
1269 | DefKind
::Static { .. }
1272 | DefKind
::Impl { of_trait: false }
1273 | DefKind
::ForeignTy
1274 | DefKind
::ConstParam
1275 | DefKind
::InlineConst
1279 | DefKind
::TraitAlias
1281 | DefKind
::ForeignMod
1282 | DefKind
::Macro(..)
1284 | DefKind
::LifetimeParam
1285 | DefKind
::GlobalAsm
1286 | DefKind
::ExternCrate
=> false,
1290 fn should_encode_const(def_kind
: DefKind
) -> bool
{
1292 DefKind
::Const
| DefKind
::AssocConst
| DefKind
::AnonConst
| DefKind
::InlineConst
=> true,
1301 | DefKind
::Static { .. }
1304 | DefKind
::ForeignTy
1305 | DefKind
::Impl { .. }
1308 | DefKind
::ConstParam
1312 | DefKind
::TraitAlias
1314 | DefKind
::ForeignMod
1315 | DefKind
::Macro(..)
1317 | DefKind
::LifetimeParam
1318 | DefKind
::GlobalAsm
1319 | DefKind
::ExternCrate
=> false,
1323 fn should_encode_fn_impl_trait_in_trait
<'tcx
>(tcx
: TyCtxt
<'tcx
>, def_id
: DefId
) -> bool
{
1324 if let Some(assoc_item
) = tcx
.opt_associated_item(def_id
)
1325 && assoc_item
.container
== ty
::AssocItemContainer
::TraitContainer
1326 && assoc_item
.kind
== ty
::AssocKind
::Fn
1334 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
1335 fn encode_attrs(&mut self, def_id
: LocalDefId
) {
1337 let mut state
= AnalyzeAttrState
{
1338 is_exported
: tcx
.effective_visibilities(()).is_exported(def_id
),
1339 is_doc_hidden
: false,
1343 .attrs(tcx
.local_def_id_to_hir_id(def_id
))
1345 .filter(|attr
| analyze_attr(attr
, &mut state
));
1347 record_array
!(self.tables
.attributes
[def_id
.to_def_id()] <- attr_iter
);
1349 let mut attr_flags
= AttrFlags
::empty();
1350 if state
.is_doc_hidden
{
1351 attr_flags
|= AttrFlags
::IS_DOC_HIDDEN
;
1353 self.tables
.attr_flags
.set(def_id
.local_def_index
, attr_flags
);
1356 fn encode_def_ids(&mut self) {
1357 self.encode_info_for_mod(CRATE_DEF_ID
);
1359 // Proc-macro crates only export proc-macro items, which are looked
1360 // up using `proc_macro_data`
1361 if self.is_proc_macro
{
1367 for local_id
in tcx
.iter_local_def_id() {
1368 let def_id
= local_id
.to_def_id();
1369 let def_kind
= tcx
.def_kind(local_id
);
1370 self.tables
.def_kind
.set_some(def_id
.index
, def_kind
);
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
);
1375 if should_encode_attrs(def_kind
) {
1376 self.encode_attrs(local_id
);
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
));
1381 if should_encode_span(def_kind
)
1382 && let Some(ident_span
) = tcx
.def_ident_span(def_id
)
1384 record
!(self.tables
.def_ident_span
[def_id
] <- ident_span
);
1386 if def_kind
.has_codegen_attrs() {
1387 record
!(self.tables
.codegen_fn_attrs
[def_id
] <- self.tcx
.codegen_fn_attrs(def_id
));
1389 if should_encode_visibility(def_kind
) {
1391 self.tcx
.local_visibility(local_id
).map_id(|def_id
| def_id
.local_def_index
);
1392 record
!(self.tables
.visibility
[def_id
] <- vis
);
1394 if should_encode_stability(def_kind
) {
1395 self.encode_stability(def_id
);
1396 self.encode_const_stability(def_id
);
1397 self.encode_default_body_stability(def_id
);
1398 self.encode_deprecation(def_id
);
1400 if should_encode_variances(tcx
, def_id
, def_kind
) {
1401 let v
= self.tcx
.variances_of(def_id
);
1402 record_array
!(self.tables
.variances_of
[def_id
] <- v
);
1404 if should_encode_fn_sig(def_kind
) {
1405 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1407 if should_encode_generics(def_kind
) {
1408 let g
= tcx
.generics_of(def_id
);
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
));
1411 let inferred_outlives
= self.tcx
.inferred_outlives_of(def_id
);
1412 record_defaulted_array
!(self.tables
.inferred_outlives_of
[def_id
] <- inferred_outlives
);
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);
1421 if should_encode_type(tcx
, local_id
, def_kind
) {
1422 record
!(self.tables
.type_of
[def_id
] <- self.tcx
.type_of(def_id
));
1424 if should_encode_constness(def_kind
) {
1425 self.tables
.constness
.set_some(def_id
.index
, self.tcx
.constness(def_id
));
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
));
1431 if let Some(name
) = tcx
.intrinsic(def_id
) {
1432 record
!(self.tables
.intrinsic
[def_id
] <- name
);
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);
1438 if let DefKind
::Trait
= def_kind
{
1439 record
!(self.tables
.trait_def
[def_id
] <- self.tcx
.trait_def(def_id
));
1440 record
!(self.tables
.super_predicates_of
[def_id
] <- self.tcx
.super_predicates_of(def_id
));
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
));
1446 if let DefKind
::TraitAlias
= def_kind
{
1447 record
!(self.tables
.trait_def
[def_id
] <- self.tcx
.trait_def(def_id
));
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
));
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());
1459 for &def_id
in associated_item_def_ids
{
1460 self.encode_info_for_assoc_item(def_id
);
1463 if def_kind
== DefKind
::Closure
1464 && let Some(coroutine_kind
) = self.tcx
.coroutine_kind(def_id
)
1466 self.tables
.coroutine_kind
.set(def_id
.index
, Some(coroutine_kind
))
1468 if def_kind
== DefKind
::Closure
1469 && tcx
.type_of(def_id
).skip_binder().is_coroutine_closure()
1472 .coroutine_for_closure
1473 .set_some(def_id
.index
, self.tcx
.coroutine_for_closure(def_id
).into());
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
);
1481 if let DefKind
::Enum
| DefKind
::Struct
| DefKind
::Union
= def_kind
{
1482 self.encode_info_for_adt(local_id
);
1484 if let DefKind
::Mod
= def_kind
{
1485 self.encode_info_for_mod(local_id
);
1487 if let DefKind
::Macro(_
) = def_kind
{
1488 self.encode_info_for_macro(local_id
);
1490 if let DefKind
::TyAlias
= def_kind
{
1493 .set(def_id
.index
, self.tcx
.type_alias_is_lazy(def_id
));
1495 if let DefKind
::OpaqueTy
= def_kind
{
1496 self.encode_explicit_item_bounds(def_id
);
1498 .is_type_alias_impl_trait
1499 .set(def_id
.index
, self.tcx
.is_type_alias_impl_trait(def_id
));
1501 if tcx
.impl_method_has_trait_impl_trait_tys(def_id
)
1502 && let Ok(table
) = self.tcx
.collect_return_position_impl_trait_in_trait_tys(def_id
)
1504 record
!(self.tables
.trait_impl_trait_tys
[def_id
] <- table
);
1506 if should_encode_fn_impl_trait_in_trait(tcx
, def_id
) {
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
);
1512 let inherent_impls
= tcx
.with_stable_hashing_context(|hcx
| {
1513 tcx
.crate_inherent_impls(()).unwrap().inherent_impls
.to_sorted(&hcx
, true)
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
| {
1517 assert
!(def_id
.is_local());
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
);
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
);
1531 #[instrument(level = "trace", skip(self))]
1532 fn encode_info_for_adt(&mut self, local_def_id
: LocalDefId
) {
1533 let def_id
= local_def_id
.to_def_id();
1535 let adt_def
= tcx
.adt_def(def_id
);
1536 record
!(self.tables
.repr_options
[def_id
] <- adt_def
.repr());
1538 let params_in_repr
= self.tcx
.params_in_repr(def_id
);
1539 record
!(self.tables
.params_in_repr
[def_id
] <- params_in_repr
);
1541 if adt_def
.is_enum() {
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
));
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.
1552 for (idx
, variant
) in adt_def
.variants().iter_enumerated() {
1553 let data
= VariantData
{
1554 discr
: variant
.discr
,
1556 ctor
: variant
.ctor
.map(|(kind
, def_id
)| (kind
, def_id
.index
)),
1557 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1559 record
!(self.tables
.variant_data
[variant
.def_id
] <- data
);
1561 record_array
!(self.tables
.associated_item_or_field_def_ids
[variant
.def_id
] <- variant
.fields
.iter().map(|f
| {
1562 assert
!(f
.did
.is_local());
1566 if let Some((CtorKind
::Fn
, ctor_def_id
)) = variant
.ctor
{
1567 let fn_sig
= tcx
.fn_sig(ctor_def_id
);
1568 // FIXME only encode signature for ctor_def_id
1569 record
!(self.tables
.fn_sig
[variant
.def_id
] <- fn_sig
);
1574 #[instrument(level = "debug", skip(self))]
1575 fn encode_info_for_mod(&mut self, local_def_id
: LocalDefId
) {
1577 let def_id
= local_def_id
.to_def_id();
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.
1584 if self.is_proc_macro
{
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
));
1588 let module_children
= tcx
.module_children_local(local_def_id
);
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
));
1594 record_defaulted_array
!(self.tables
.module_children_reexports
[def_id
] <-
1595 module_children
.iter().filter(|child
| !child
.reexport_chain
.is_empty()));
1599 fn encode_explicit_item_bounds(&mut self, def_id
: DefId
) {
1600 debug
!("EncodeContext::encode_explicit_item_bounds({:?})", def_id
);
1601 let bounds
= self.tcx
.explicit_item_bounds(def_id
).skip_binder();
1602 record_defaulted_array
!(self.tables
.explicit_item_bounds
[def_id
] <- bounds
);
1605 #[instrument(level = "debug", skip(self))]
1606 fn encode_info_for_assoc_item(&mut self, def_id
: DefId
) {
1608 let item
= tcx
.associated_item(def_id
);
1610 self.tables
.defaultness
.set_some(def_id
.index
, item
.defaultness(tcx
));
1611 self.tables
.assoc_container
.set_some(def_id
.index
, item
.container
);
1613 match item
.container
{
1614 AssocItemContainer
::TraitContainer
=> {
1615 if let ty
::AssocKind
::Type
= item
.kind
{
1616 self.encode_explicit_item_bounds(def_id
);
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());
1625 if let Some(rpitit_info
) = item
.opt_rpitit_info
{
1626 record
!(self.tables
.opt_rpitit_info
[def_id
] <- rpitit_info
);
1627 if matches
!(rpitit_info
, ty
::ImplTraitInTraitData
::Trait { .. }
) {
1629 self.tables
.assumed_wf_types_for_rpitit
[def_id
]
1630 <- self.tcx
.assumed_wf_types_for_rpitit(def_id
)
1636 fn encode_mir(&mut self) {
1637 if self.is_proc_macro
{
1642 let reachable_set
= tcx
.reachable_set(());
1644 let keys_and_jobs
= tcx
.mir_keys(()).iter().filter_map(|&def_id
| {
1645 let (encode_const
, encode_opt
) = should_encode_mir(tcx
, reachable_set
, def_id
);
1646 if encode_const
|| encode_opt { Some((def_id, encode_const, encode_opt)) }
else { None }
1648 for (def_id
, encode_const
, encode_opt
) in keys_and_jobs
{
1649 debug_assert
!(encode_const
|| encode_opt
);
1651 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
1653 record
!(self.tables
.optimized_mir
[def_id
.to_def_id()] <- tcx
.optimized_mir(def_id
));
1655 .cross_crate_inlinable
1656 .set(def_id
.to_def_id().index
, self.tcx
.cross_crate_inlinable(def_id
));
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
));
1660 if self.tcx
.is_coroutine(def_id
.to_def_id())
1661 && let Some(witnesses
) = tcx
.mir_coroutine_witnesses(def_id
)
1663 record
!(self.tables
.mir_coroutine_witnesses
[def_id
.to_def_id()] <- witnesses
);
1667 record
!(self.tables
.mir_for_ctfe
[def_id
.to_def_id()] <- tcx
.mir_for_ctfe(def_id
));
1669 // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
1670 let abstract_const
= tcx
.thir_abstract_const(def_id
);
1671 if let Ok(Some(abstract_const
)) = abstract_const
{
1672 record
!(self.tables
.thir_abstract_const
[def_id
.to_def_id()] <- abstract_const
);
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
{
1680 let const_data
= rendered_const(self.tcx
, body_id
);
1681 record
!(self.tables
.rendered_const
[def_id
.to_def_id()] <- const_data
);
1685 record
!(self.tables
.promoted_mir
[def_id
.to_def_id()] <- tcx
.promoted_mir(def_id
));
1687 if self.tcx
.is_coroutine(def_id
.to_def_id())
1688 && let Some(witnesses
) = tcx
.mir_coroutine_witnesses(def_id
)
1690 record
!(self.tables
.mir_coroutine_witnesses
[def_id
.to_def_id()] <- witnesses
);
1693 let instance
= ty
::InstanceDef
::Item(def_id
.to_def_id());
1694 let unused
= tcx
.unused_generic_params(instance
);
1695 self.tables
.unused_generic_params
.set(def_id
.local_def_index
, unused
);
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()
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()));
1714 #[instrument(level = "debug", skip(self))]
1715 fn encode_stability(&mut self, def_id
: DefId
) {
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.
1718 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.unstable_opts
.force_unstable_if_unmarked
{
1719 if let Some(stab
) = self.tcx
.lookup_stability(def_id
) {
1720 record
!(self.tables
.lookup_stability
[def_id
] <- stab
)
1725 #[instrument(level = "debug", skip(self))]
1726 fn encode_const_stability(&mut self, def_id
: DefId
) {
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.
1729 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.unstable_opts
.force_unstable_if_unmarked
{
1730 if let Some(stab
) = self.tcx
.lookup_const_stability(def_id
) {
1731 record
!(self.tables
.lookup_const_stability
[def_id
] <- stab
)
1736 #[instrument(level = "debug", skip(self))]
1737 fn encode_default_body_stability(&mut self, def_id
: DefId
) {
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
)
1747 #[instrument(level = "debug", skip(self))]
1748 fn encode_deprecation(&mut self, def_id
: DefId
) {
1749 if let Some(depr
) = self.tcx
.lookup_deprecation(def_id
) {
1750 record
!(self.tables
.lookup_deprecation_entry
[def_id
] <- depr
);
1754 #[instrument(level = "debug", skip(self))]
1755 fn encode_info_for_macro(&mut self, def_id
: LocalDefId
) {
1758 let hir
::ItemKind
::Macro(macro_def
, _
) = tcx
.hir().expect_item(def_id
).kind
else { bug!() }
;
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
);
1763 fn encode_native_libraries(&mut self) -> LazyArray
<NativeLib
> {
1764 empty_proc_macro
!(self);
1765 let used_libraries
= self.tcx
.native_libraries(LOCAL_CRATE
);
1766 self.lazy_array(used_libraries
.iter())
1769 fn encode_foreign_modules(&mut self) -> LazyArray
<ForeignModule
> {
1770 empty_proc_macro
!(self);
1771 let foreign_modules
= self.tcx
.foreign_modules(LOCAL_CRATE
);
1772 self.lazy_array(foreign_modules
.iter().map(|(_
, m
)| m
).cloned())
1775 fn encode_hygiene(&mut self) -> (SyntaxContextTable
, ExpnDataTable
, ExpnHashTable
) {
1776 let mut syntax_contexts
: TableBuilder
<_
, _
> = Default
::default();
1777 let mut expn_data_table
: TableBuilder
<_
, _
> = Default
::default();
1778 let mut expn_hash_table
: TableBuilder
<_
, _
> = Default
::default();
1780 self.hygiene_ctxt
.encode(
1781 &mut (&mut *self, &mut syntax_contexts
, &mut expn_data_table
, &mut expn_hash_table
),
1782 |(this
, syntax_contexts
, _
, _
), index
, ctxt_data
| {
1783 syntax_contexts
.set_some(index
, this
.lazy(ctxt_data
));
1785 |(this
, _
, expn_data_table
, expn_hash_table
), index
, expn_data
, hash
| {
1786 if let Some(index
) = index
.as_local() {
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
));
1794 syntax_contexts
.encode(&mut self.opaque
),
1795 expn_data_table
.encode(&mut self.opaque
),
1796 expn_hash_table
.encode(&mut self.opaque
),
1800 fn encode_proc_macros(&mut self) -> Option
<ProcMacroData
> {
1801 let is_proc_macro
= self.tcx
.crate_types().contains(&CrateType
::ProcMacro
);
1804 let hir
= tcx
.hir();
1806 let proc_macro_decls_static
= tcx
.proc_macro_decls_static(()).unwrap().local_def_index
;
1807 let stability
= tcx
.lookup_stability(CRATE_DEF_ID
);
1809 self.lazy_array(tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
));
1810 for (i
, span
) in self.tcx
.sess
.psess
.proc_macro_quoted_spans() {
1811 let span
= self.lazy(span
);
1812 self.tables
.proc_macro_quoted_spans
.set_some(i
, span
);
1815 self.tables
.def_kind
.set_some(LOCAL_CRATE
.as_def_id().index
, DefKind
::Mod
);
1816 record
!(self.tables
.def_span
[LOCAL_CRATE
.as_def_id()] <- tcx
.def_span(LOCAL_CRATE
.as_def_id()));
1817 self.encode_attrs(LOCAL_CRATE
.as_def_id().expect_local());
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
);
1820 if let Some(stability
) = stability
{
1821 record
!(self.tables
.lookup_stability
[LOCAL_CRATE
.as_def_id()] <- stability
);
1823 self.encode_deprecation(LOCAL_CRATE
.as_def_id());
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
);
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
);
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
1834 for &proc_macro
in &tcx
.resolutions(()).proc_macros
{
1835 let id
= proc_macro
;
1836 let proc_macro
= tcx
.local_def_id_to_hir_id(proc_macro
);
1837 let mut name
= hir
.name(proc_macro
);
1838 let span
= hir
.span(proc_macro
);
1839 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1840 // so downstream crates need access to them.
1841 let attrs
= hir
.attrs(proc_macro
);
1842 let macro_kind
= if attr
::contains_name(attrs
, sym
::proc_macro
) {
1844 } else if attr
::contains_name(attrs
, sym
::proc_macro_attribute
) {
1846 } else if let Some(attr
) = attr
::find_by_name(attrs
, sym
::proc_macro_derive
) {
1847 // This unwrap chain should have been checked by the proc-macro harness.
1848 name
= attr
.meta_item_list().unwrap()[0]
1856 bug
!("Unknown proc-macro type for item {:?}", id
);
1859 let mut def_key
= self.tcx
.hir().def_key(id
);
1860 def_key
.disambiguated_data
.data
= DefPathData
::MacroNs(name
);
1862 let def_id
= id
.to_def_id();
1863 self.tables
.def_kind
.set_some(def_id
.index
, DefKind
::Macro(macro_kind
));
1864 self.tables
.proc_macro
.set_some(def_id
.index
, macro_kind
);
1865 self.encode_attrs(id
);
1866 record
!(self.tables
.def_keys
[def_id
] <- def_key
);
1867 record
!(self.tables
.def_ident_span
[def_id
] <- span
);
1868 record
!(self.tables
.def_span
[def_id
] <- span
);
1869 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::Public
);
1870 if let Some(stability
) = stability
{
1871 record
!(self.tables
.lookup_stability
[def_id
] <- stability
);
1875 Some(ProcMacroData { proc_macro_decls_static, stability, macros }
)
1881 fn encode_debugger_visualizers(&mut self) -> LazyArray
<DebuggerVisualizerFile
> {
1882 empty_proc_macro
!(self);
1885 .debugger_visualizers(LOCAL_CRATE
)
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
),
1895 fn encode_crate_deps(&mut self) -> LazyArray
<CrateDep
> {
1896 empty_proc_macro
!(self);
1903 let dep
= CrateDep
{
1904 name
: self.tcx
.crate_name(cnum
),
1905 hash
: self.tcx
.crate_hash(cnum
),
1906 host_hash
: self.tcx
.crate_host_hash(cnum
),
1907 kind
: self.tcx
.dep_kind(cnum
),
1908 extra_filename
: self.tcx
.extra_filename(cnum
).clone(),
1909 is_private
: self.tcx
.is_private_dep(cnum
),
1913 .collect
::<Vec
<_
>>();
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
));
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.
1928 self.lazy_array(deps
.iter().map(|(_
, dep
)| dep
))
1931 fn encode_lib_features(&mut self) -> LazyArray
<(Symbol
, FeatureStability
)> {
1932 empty_proc_macro
!(self);
1934 let lib_features
= tcx
.lib_features(LOCAL_CRATE
);
1935 self.lazy_array(lib_features
.to_sorted_vec())
1938 fn encode_stability_implications(&mut self) -> LazyArray
<(Symbol
, Symbol
)> {
1939 empty_proc_macro
!(self);
1941 let implications
= tcx
.stability_implications(LOCAL_CRATE
);
1942 let sorted
= implications
.to_sorted_stable_ord();
1943 self.lazy_array(sorted
.into_iter().map(|(k
, v
)| (*k
, *v
)))
1946 fn encode_diagnostic_items(&mut self) -> LazyArray
<(Symbol
, DefIndex
)> {
1947 empty_proc_macro
!(self);
1949 let diagnostic_items
= &tcx
.diagnostic_items(LOCAL_CRATE
).name_to_id
;
1950 self.lazy_array(diagnostic_items
.iter().map(|(&name
, def_id
)| (name
, def_id
.index
)))
1953 fn encode_lang_items(&mut self) -> LazyArray
<(DefIndex
, LangItem
)> {
1954 empty_proc_macro
!(self);
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
))
1961 fn encode_lang_items_missing(&mut self) -> LazyArray
<LangItem
> {
1962 empty_proc_macro
!(self);
1964 self.lazy_array(&tcx
.lang_items().missing
)
1967 fn encode_stripped_cfg_items(&mut self) -> LazyArray
<StrippedCfgItem
<DefIndex
>> {
1970 .stripped_cfg_items(LOCAL_CRATE
)
1972 .map(|item
| item
.clone().map_mod_id(|def_id
| def_id
.index
)),
1976 fn encode_traits(&mut self) -> LazyArray
<DefIndex
> {
1977 empty_proc_macro
!(self);
1978 self.lazy_array(self.tcx
.traits(LOCAL_CRATE
).iter().map(|def_id
| def_id
.index
))
1981 /// Encodes an index, mapping each trait to its (local) implementations.
1982 #[instrument(level = "debug", skip(self))]
1983 fn encode_impls(&mut self) -> LazyArray
<TraitImpls
> {
1984 empty_proc_macro
!(self);
1986 let mut fx_hash_map
: FxHashMap
<DefId
, Vec
<(DefIndex
, Option
<SimplifiedType
>)>> =
1987 FxHashMap
::default();
1989 for id
in tcx
.hir().items() {
1990 let DefKind
::Impl { of_trait }
= tcx
.def_kind(id
.owner_id
) else {
1993 let def_id
= id
.owner_id
.to_def_id();
1995 self.tables
.defaultness
.set_some(def_id
.index
, tcx
.defaultness(def_id
));
1997 if of_trait
&& let Some(header
) = tcx
.impl_trait_header(def_id
) {
1998 record
!(self.tables
.impl_trait_header
[def_id
] <- header
);
2000 let trait_ref
= header
.trait_ref
.instantiate_identity();
2001 let simplified_self_ty
= fast_reject
::simplify_type(
2003 trait_ref
.self_ty(),
2004 TreatParams
::AsCandidateKey
,
2007 .entry(trait_ref
.def_id
)
2009 .push((id
.owner_id
.def_id
.local_def_index
, simplified_self_ty
));
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());
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() {
2021 let coerce_unsized_info
= tcx
.coerce_unsized_info(def_id
).unwrap();
2022 record
!(self.tables
.coerce_unsized_info
[def_id
] <- coerce_unsized_info
);
2027 let mut all_impls
: Vec
<_
> = fx_hash_map
.into_iter().collect();
2029 // Bring everything into deterministic order for hashing
2030 all_impls
.sort_by_cached_key(|&(trait_def_id
, _
)| tcx
.def_path_hash(trait_def_id
));
2032 let all_impls
: Vec
<_
> = all_impls
2034 .map(|(trait_def_id
, mut impls
)| {
2035 // Bring everything into deterministic order for hashing
2036 impls
.sort_by_cached_key(|&(index
, _
)| {
2037 tcx
.hir().def_path_hash(LocalDefId { local_def_index: index }
)
2041 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
2042 impls
: self.lazy_array(&impls
),
2047 self.lazy_array(&all_impls
)
2050 #[instrument(level = "debug", skip(self))]
2051 fn encode_incoherent_impls(&mut self) -> LazyArray
<IncoherentImpls
> {
2052 empty_proc_macro
!(self);
2054 let all_impls
= tcx
.with_stable_hashing_context(|hcx
| {
2055 tcx
.crate_inherent_impls(()).unwrap().incoherent_impls
.to_sorted(&hcx
, true)
2058 let all_impls
: Vec
<_
> = all_impls
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 }
)
2067 IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
2071 self.lazy_array(&all_impls
)
2074 // Encodes all symbols exported from this crate into the metadata.
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).
2080 fn encode_exported_symbols(
2082 exported_symbols
: &[(ExportedSymbol
<'tcx
>, SymbolExportInfo
)],
2083 ) -> LazyArray
<(ExportedSymbol
<'
static>, SymbolExportInfo
)> {
2084 empty_proc_macro
!(self);
2085 // The metadata symbol name is special. It should not show up in
2086 // downstream crates.
2087 let metadata_symbol_name
= SymbolName
::new(self.tcx
, &metadata_symbol_name(self.tcx
));
2092 .filter(|&(exported_symbol
, _
)| match *exported_symbol
{
2093 ExportedSymbol
::NoDefId(symbol_name
) => symbol_name
!= metadata_symbol_name
,
2100 fn encode_dylib_dependency_formats(&mut self) -> LazyArray
<Option
<LinkagePreference
>> {
2101 empty_proc_macro
!(self);
2102 let formats
= self.tcx
.dependency_formats(());
2103 for (ty
, arr
) in formats
.iter() {
2104 if *ty
!= CrateType
::Dylib
{
2107 return self.lazy_array(arr
.iter().map(|slot
| match *slot
{
2108 Linkage
::NotLinked
| Linkage
::IncludedFromDylib
=> None
,
2110 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
2111 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
2114 LazyArray
::default()
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.
2120 fn prefetch_mir(tcx
: TyCtxt
<'_
>) {
2121 if !tcx
.sess
.opts
.output_types
.should_codegen() {
2122 // We won't emit MIR, so don't prefetch it.
2126 let reachable_set
= tcx
.reachable_set(());
2127 par_for_each_in(tcx
.mir_keys(()), |&def_id
| {
2128 let (encode_const
, encode_opt
) = should_encode_mir(tcx
, reachable_set
, def_id
);
2131 tcx
.ensure_with_value().mir_for_ctfe(def_id
);
2134 tcx
.ensure_with_value().optimized_mir(def_id
);
2136 if encode_opt
|| encode_const
{
2137 tcx
.ensure_with_value().promoted_mir(def_id
);
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.
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
2148 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
2149 // and opt) by having ebml generate an out-of-bounds panic when looking at
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.
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.
2165 pub struct EncodedMetadata
{
2166 // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2168 // We need to carry MaybeTempDir to avoid deleting the temporary
2169 // directory while accessing the Mmap.
2170 _temp_dir
: Option
<MaybeTempDir
>,
2173 impl EncodedMetadata
{
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 }
);
2181 let mmap
= unsafe { Some(Mmap::map(file)?) }
;
2182 Ok(Self { mmap, _temp_dir: temp_dir }
)
2186 pub fn raw_data(&self) -> &[u8] {
2187 self.mmap
.as_deref().unwrap_or_default()
2191 impl<S
: Encoder
> Encodable
<S
> for EncodedMetadata
{
2192 fn encode(&self, s
: &mut S
) {
2193 let slice
= self.raw_data();
2198 impl<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();
2204 (&mut mmap
[..]).write(&[d
.read_u8()]).unwrap();
2206 mmap
.flush().unwrap();
2207 Some(mmap
.make_read_only().unwrap())
2212 Self { mmap, _temp_dir: None }
2216 pub fn encode_metadata(tcx
: TyCtxt
<'_
>, path
: &Path
) {
2217 let _prof_timer
= tcx
.prof
.verbose_generic_activity("generate_crate_metadata");
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();
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
));
2230 let mut encoder
= opaque
::FileEncoder
::new(path
)
2231 .unwrap_or_else(|err
| tcx
.dcx().emit_fatal(FailCreateFileEncoder { err }
));
2232 encoder
.emit_raw_bytes(METADATA_HEADER
);
2234 // Will be filled with the root position after encoding everything.
2235 encoder
.emit_raw_bytes(&0u64.to_le_bytes());
2237 let source_map_files
= tcx
.sess
.source_map().files();
2238 let source_file_cache
= (source_map_files
[0].clone(), 0);
2239 let required_source_files
= Some(FxIndexSet
::default());
2240 drop(source_map_files
);
2242 let hygiene_ctxt
= HygieneEncodeContext
::default();
2244 let mut ecx
= EncodeContext
{
2247 feat
: tcx
.features(),
2248 tables
: Default
::default(),
2249 lazy_state
: LazyState
::NoNode
,
2250 span_shorthands
: Default
::default(),
2251 type_shorthands
: Default
::default(),
2252 predicate_shorthands
: Default
::default(),
2254 interpret_allocs
: Default
::default(),
2255 required_source_files
,
2256 is_proc_macro
: tcx
.crate_types().contains(&CrateType
::ProcMacro
),
2257 hygiene_ctxt
: &hygiene_ctxt
,
2258 symbol_table
: Default
::default(),
2261 // Encode the rustc version string in a predictable location.
2262 rustc_version(tcx
.sess
.cfg_version
).encode(&mut ecx
);
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();
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() {
2272 tcx
.dcx().emit_fatal(FailWriteFile { path: &path, err }
);
2275 let file
= ecx
.opaque
.file();
2276 if let Err(err
) = encode_root_position(file
, root
.position
.get()) {
2277 tcx
.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }
);
2280 // Record metadata size for self-profiling
2281 tcx
.prof
.artifact_size("crate_metadata", "crate_metadata", file
.metadata().unwrap().len());
2284 fn encode_root_position(mut file
: &File
, pos
: usize) -> Result
<(), std
::io
::Error
> {
2285 // We will return to this position after writing the root position.
2286 let pos_before_seek
= file
.stream_position().unwrap();
2288 // Encode the root position.
2289 let header
= METADATA_HEADER
.len();
2290 file
.seek(std
::io
::SeekFrom
::Start(header
as u64))?
;
2291 file
.write_all(&pos
.to_le_bytes())?
;
2293 // Return to the position where we are before writing the root position.
2294 file
.seek(std
::io
::SeekFrom
::Start(pos_before_seek
))?
;
2298 pub fn provide(providers
: &mut Providers
) {
2299 *providers
= Providers
{
2300 doc_link_resolutions
: |tcx
, def_id
| {
2302 .doc_link_resolutions
2304 .unwrap_or_else(|| span_bug
!(tcx
.def_span(def_id
), "no resolutions for a doc link"))
2306 doc_link_traits_in_scope
: |tcx
, def_id
| {
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")
2311 traits
: |tcx
, LocalCrate
| {
2312 let mut traits
= Vec
::new();
2313 for id
in tcx
.hir().items() {
2314 if matches
!(tcx
.def_kind(id
.owner_id
), DefKind
::Trait
| DefKind
::TraitAlias
) {
2315 traits
.push(id
.owner_id
.to_def_id())
2319 // Bring everything into deterministic order.
2320 traits
.sort_by_cached_key(|&def_id
| tcx
.def_path_hash(def_id
));
2321 tcx
.arena
.alloc_slice(&traits
)
2323 trait_impls_in_crate
: |tcx
, LocalCrate
| {
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()
2329 trait_impls
.push(id
.owner_id
.to_def_id())
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
)
2342 /// Build a textual representation of an unevaluated constant expression.
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.
2350 /// * literals (optionally with a leading `-`)
2352 /// * blocks (`{ … }`) around simple expressions and
2353 /// * paths without arguments
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.
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.
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.
2369 pub fn rendered_const
<'tcx
>(tcx
: TyCtxt
<'tcx
>, body
: hir
::BodyId
) -> String
{
2370 let hir
= tcx
.hir();
2371 let value
= &hir
.body(body
).value
;
2373 #[derive(PartialEq, Eq)]
2374 enum Classification
{
2380 use Classification
::*;
2382 fn classify(expr
: &hir
::Expr
<'_
>) -> Classification
{
2384 hir
::ExprKind
::Unary(hir
::UnOp
::Neg
, expr
) => {
2385 if matches
!(expr
.kind
, hir
::ExprKind
::Lit(_
)) { Literal }
else { Complex }
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 }
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 }
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
,
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:
2413 // * hexadecimal notation
2415 // * character escapes
2417 // FIXME: This passes through `-/*spacer*/0` verbatim.
2419 if !value
.span
.from_expansion()
2420 && let Ok(snippet
) = tcx
.sess
.source_map().span_to_snippet(value
.span
) =>
2425 // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and
2426 // other formatting artifacts.
2427 Literal
| Simple
=> id_to_string(&hir
, body
.hir_id
),
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.
2433 if tcx
.def_kind(hir
.body_owner_def_id(body
).to_def_id()) == DefKind
::AnonConst
{