1 use crate::errors
::{FailCreateFileEncoder, FailSeekFile, FailWriteFile}
;
2 use crate::rmeta
::def_path_hash_map
::DefPathHashMapRef
;
3 use crate::rmeta
::table
::TableBuilder
;
6 use rustc_ast
::expand
::StrippedCfgItem
;
7 use rustc_ast
::Attribute
;
8 use rustc_data_structures
::fingerprint
::Fingerprint
;
9 use rustc_data_structures
::fx
::{FxHashMap, FxIndexSet}
;
10 use rustc_data_structures
::memmap
::{Mmap, MmapMut}
;
11 use rustc_data_structures
::stable_hasher
::{Hash128, HashStable, StableHasher}
;
12 use rustc_data_structures
::sync
::{join, par_for_each_in, Lrc}
;
13 use rustc_data_structures
::temp_dir
::MaybeTempDir
;
15 use rustc_hir
::def
::DefKind
;
16 use rustc_hir
::def_id
::{
17 CrateNum
, DefId
, DefIndex
, LocalDefId
, CRATE_DEF_ID
, CRATE_DEF_INDEX
, LOCAL_CRATE
,
19 use rustc_hir
::definitions
::DefPathData
;
20 use rustc_hir
::intravisit
;
21 use rustc_hir
::lang_items
::LangItem
;
22 use rustc_middle
::middle
::debugger_visualizer
::DebuggerVisualizerFile
;
23 use rustc_middle
::middle
::dependency_format
::Linkage
;
24 use rustc_middle
::middle
::exported_symbols
::{
25 metadata_symbol_name
, ExportedSymbol
, SymbolExportInfo
,
27 use rustc_middle
::mir
::interpret
;
28 use rustc_middle
::query
::LocalCrate
;
29 use rustc_middle
::query
::Providers
;
30 use rustc_middle
::traits
::specialization_graph
;
31 use rustc_middle
::ty
::codec
::TyEncoder
;
32 use rustc_middle
::ty
::fast_reject
::{self, SimplifiedType, TreatParams}
;
33 use rustc_middle
::ty
::{self, AssocItemContainer, SymbolName, Ty, TyCtxt}
;
34 use rustc_middle
::util
::common
::to_readable_str
;
35 use rustc_serialize
::{opaque, Decodable, Decoder, Encodable, Encoder}
;
36 use rustc_session
::config
::{CrateType, OptLevel}
;
37 use rustc_session
::cstore
::{ForeignModule, LinkagePreference, NativeLib}
;
38 use rustc_span
::hygiene
::{ExpnIndex, HygieneEncodeContext, MacroKind}
;
39 use rustc_span
::symbol
::{sym, Symbol}
;
40 use rustc_span
::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext}
;
41 use std
::borrow
::Borrow
;
42 use std
::collections
::hash_map
::Entry
;
44 use std
::io
::{Read, Seek, Write}
;
45 use std
::num
::NonZeroUsize
;
46 use std
::path
::{Path, PathBuf}
;
48 pub(super) struct EncodeContext
<'a
, 'tcx
> {
49 opaque
: opaque
::FileEncoder
,
51 feat
: &'tcx rustc_feature
::Features
,
53 tables
: TableBuilders
,
55 lazy_state
: LazyState
,
56 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
57 predicate_shorthands
: FxHashMap
<ty
::PredicateKind
<'tcx
>, usize>,
59 interpret_allocs
: FxIndexSet
<interpret
::AllocId
>,
61 // This is used to speed up Span encoding.
62 // The `usize` is an index into the `MonotonicVec`
63 // that stores the `SourceFile`
64 source_file_cache
: (Lrc
<SourceFile
>, usize),
65 // The indices (into the `SourceMap`'s `MonotonicVec`)
66 // of all of the `SourceFiles` that we need to serialize.
67 // When we serialize a `Span`, we insert the index of its
68 // `SourceFile` into the `FxIndexSet`.
69 // The order inside the `FxIndexSet` is used as on-disk
70 // order of `SourceFiles`, and encoded inside `Span`s.
71 required_source_files
: Option
<FxIndexSet
<usize>>,
73 hygiene_ctxt
: &'a HygieneEncodeContext
,
74 symbol_table
: FxHashMap
<Symbol
, usize>,
77 /// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
78 /// This is useful for skipping the encoding of things that aren't needed
79 /// for proc-macro crates.
80 macro_rules
! empty_proc_macro
{
82 if $
self.is_proc_macro
{
83 return LazyArray
::default();
88 macro_rules
! encoder_methods
{
89 ($
($name
:ident($ty
:ty
);)*) => {
90 $
(fn $
name(&mut self, value
: $ty
) {
91 self.opaque
.$
name(value
)
96 impl<'a
, 'tcx
> Encoder
for EncodeContext
<'a
, 'tcx
> {
111 emit_raw_bytes(&[u8]);
115 impl<'a
, 'tcx
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyValue
<T
> {
116 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
117 e
.emit_lazy_distance(self.position
);
121 impl<'a
, 'tcx
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyArray
<T
> {
122 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
123 e
.emit_usize(self.num_elems
);
124 if self.num_elems
> 0 {
125 e
.emit_lazy_distance(self.position
)
130 impl<'a
, 'tcx
, I
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyTable
<I
, T
> {
131 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
132 e
.emit_usize(self.encoded_size
);
133 e
.emit_lazy_distance(self.position
);
137 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for CrateNum
{
138 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
139 if *self != LOCAL_CRATE
&& s
.is_proc_macro
{
140 panic
!("Attempted to encode non-local CrateNum {self:?} for proc-macro crate");
142 s
.emit_u32(self.as_u32());
146 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for DefIndex
{
147 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
148 s
.emit_u32(self.as_u32());
152 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnIndex
{
153 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
154 s
.emit_u32(self.as_u32());
158 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for SyntaxContext
{
159 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
160 rustc_span
::hygiene
::raw_encode_syntax_context(*self, &s
.hygiene_ctxt
, s
);
164 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnId
{
165 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
166 if self.krate
== LOCAL_CRATE
{
167 // We will only write details for local expansions. Non-local expansions will fetch
168 // data from the corresponding crate's metadata.
169 // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
170 // metadata from proc-macro crates.
171 s
.hygiene_ctxt
.schedule_expn_data_for_encoding(*self);
173 self.krate
.encode(s
);
174 self.local_id
.encode(s
);
178 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for Span
{
179 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
180 let span
= self.data();
182 // Don't serialize any `SyntaxContext`s from a proc-macro crate,
183 // since we don't load proc-macro dependencies during serialization.
184 // This means that any hygiene information from macros used *within*
185 // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
186 // definition) will be lost.
188 // This can show up in two ways:
190 // 1. Any hygiene information associated with identifier of
191 // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
192 // Since proc-macros can only be invoked from a different crate,
193 // real code should never need to care about this.
195 // 2. Using `Span::def_site` or `Span::mixed_site` will not
196 // include any hygiene information associated with the definition
197 // site. This means that a proc-macro cannot emit a `$crate`
198 // identifier which resolves to one of its dependencies,
199 // which also should never come up in practice.
201 // Additionally, this affects `Span::parent`, and any other
202 // span inspection APIs that would otherwise allow traversing
203 // the `SyntaxContexts` associated with a span.
205 // None of these user-visible effects should result in any
206 // cross-crate inconsistencies (getting one behavior in the same
207 // crate, and a different behavior in another crate) due to the
208 // limited surface that proc-macros can expose.
210 // IMPORTANT: If this is ever changed, be sure to update
211 // `rustc_span::hygiene::raw_encode_expn_id` to handle
212 // encoding `ExpnData` for proc-macro crates.
214 SyntaxContext
::root().encode(s
);
220 return TAG_PARTIAL_SPAN
.encode(s
);
223 // The Span infrastructure should make sure that this invariant holds:
224 debug_assert
!(span
.lo
<= span
.hi
);
226 if !s
.source_file_cache
.0.contains(span
.lo
) {
227 let source_map
= s
.tcx
.sess
.source_map();
228 let source_file_index
= source_map
.lookup_source_file_idx(span
.lo
);
229 s
.source_file_cache
=
230 (source_map
.files()[source_file_index
].clone(), source_file_index
);
232 let (ref source_file
, source_file_index
) = s
.source_file_cache
;
233 debug_assert
!(source_file
.contains(span
.lo
));
235 if !source_file
.contains(span
.hi
) {
236 // Unfortunately, macro expansion still sometimes generates Spans
237 // that malformed in this way.
238 return TAG_PARTIAL_SPAN
.encode(s
);
241 // There are two possible cases here:
242 // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
243 // crate we are writing metadata for. When the metadata for *this* crate gets
244 // deserialized, the deserializer will need to know which crate it originally came
245 // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
246 // be deserialized after the rest of the span data, which tells the deserializer
247 // which crate contains the source map information.
248 // 2. This span comes from our own crate. No special handling is needed - we just
249 // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
250 // our own source map information.
252 // If we're a proc-macro crate, we always treat this as a local `Span`.
253 // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata
254 // if we're a proc-macro crate.
255 // This allows us to avoid loading the dependencies of proc-macro crates: all of
256 // the information we need to decode `Span`s is stored in the proc-macro crate.
257 let (tag
, metadata_index
) = if source_file
.is_imported() && !s
.is_proc_macro
{
258 // To simplify deserialization, we 'rebase' this span onto the crate it originally came
259 // from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'
260 // values are relative to the source map information for the 'foreign' crate whose
261 // CrateNum we write into the metadata. This allows `imported_source_files` to binary
262 // search through the 'foreign' crate's source map information, using the
263 // deserialized 'lo' and 'hi' values directly.
265 // All of this logic ensures that the final result of deserialization is a 'normal'
266 // Span that can be used without any additional trouble.
267 let metadata_index
= {
268 // Introduce a new scope so that we drop the 'lock()' temporary
269 match &*source_file
.external_src
.lock() {
270 ExternalSource
::Foreign { metadata_index, .. }
=> *metadata_index
,
271 src
=> panic
!("Unexpected external source {src:?}"),
275 (TAG_VALID_SPAN_FOREIGN
, metadata_index
)
277 // Record the fact that we need to encode the data for this `SourceFile`
279 s
.required_source_files
.as_mut().expect("Already encoded SourceMap!");
280 let (metadata_index
, _
) = source_files
.insert_full(source_file_index
);
281 let metadata_index
: u32 =
282 metadata_index
.try_into().expect("cannot export more than U32_MAX files");
284 (TAG_VALID_SPAN_LOCAL
, metadata_index
)
287 // Encode the start position relative to the file start, so we profit more from the
288 // variable-length integer encoding.
289 let lo
= span
.lo
- source_file
.start_pos
;
291 // Encode length which is usually less than span.hi and profits more
292 // from the variable-length integer encoding that we use.
293 let len
= span
.hi
- span
.lo
;
299 // Encode the index of the `SourceFile` for the span, in order to make decoding faster.
300 metadata_index
.encode(s
);
302 if tag
== TAG_VALID_SPAN_FOREIGN
{
303 // This needs to be two lines to avoid holding the `s.source_file_cache`
304 // while calling `cnum.encode(s)`
305 let cnum
= s
.source_file_cache
.0.cnum
;
311 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for Symbol
{
312 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
313 // if symbol preinterned, emit tag and symbol index
314 if self.is_preinterned() {
315 s
.opaque
.emit_u8(SYMBOL_PREINTERNED
);
316 s
.opaque
.emit_u32(self.as_u32());
318 // otherwise write it as string or as offset to it
319 match s
.symbol_table
.entry(*self) {
320 Entry
::Vacant(o
) => {
321 s
.opaque
.emit_u8(SYMBOL_STR
);
322 let pos
= s
.opaque
.position();
324 s
.emit_str(self.as_str());
326 Entry
::Occupied(o
) => {
328 s
.emit_u8(SYMBOL_OFFSET
);
336 impl<'a
, 'tcx
> TyEncoder
for EncodeContext
<'a
, 'tcx
> {
337 const CLEAR_CROSS_CRATE
: bool
= true;
339 type I
= TyCtxt
<'tcx
>;
341 fn position(&self) -> usize {
342 self.opaque
.position()
345 fn type_shorthands(&mut self) -> &mut FxHashMap
<Ty
<'tcx
>, usize> {
346 &mut self.type_shorthands
349 fn predicate_shorthands(&mut self) -> &mut FxHashMap
<ty
::PredicateKind
<'tcx
>, usize> {
350 &mut self.predicate_shorthands
353 fn encode_alloc_id(&mut self, alloc_id
: &rustc_middle
::mir
::interpret
::AllocId
) {
354 let (index
, _
) = self.interpret_allocs
.insert_full(*alloc_id
);
360 // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
361 // normally need extra variables to avoid errors about multiple mutable borrows.
362 macro_rules
! record
{
363 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
366 let lazy
= $
self.lazy(value
);
367 $
self.$tables
.$table
.set_some($def_id
.index
, lazy
);
372 // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
373 // normally need extra variables to avoid errors about multiple mutable borrows.
374 macro_rules
! record_array
{
375 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
378 let lazy
= $
self.lazy_array(value
);
379 $
self.$tables
.$table
.set_some($def_id
.index
, lazy
);
384 macro_rules
! record_defaulted_array
{
385 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
388 let lazy
= $
self.lazy_array(value
);
389 $
self.$tables
.$table
.set($def_id
.index
, lazy
);
394 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
395 fn emit_lazy_distance(&mut self, position
: NonZeroUsize
) {
396 let pos
= position
.get();
397 let distance
= match self.lazy_state
{
398 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
399 LazyState
::NodeStart(start
) => {
400 let start
= start
.get();
401 assert
!(pos
<= start
);
404 LazyState
::Previous(last_pos
) => {
406 last_pos
<= position
,
407 "make sure that the calls to `lazy*` \
408 are in the same order as the metadata fields",
410 position
.get() - last_pos
.get()
413 self.lazy_state
= LazyState
::Previous(NonZeroUsize
::new(pos
).unwrap());
414 self.emit_usize(distance
);
417 fn lazy
<T
: ParameterizedOverTcx
, B
: Borrow
<T
::Value
<'tcx
>>>(&mut self, value
: B
) -> LazyValue
<T
>
419 T
::Value
<'tcx
>: Encodable
<EncodeContext
<'a
, 'tcx
>>,
421 let pos
= NonZeroUsize
::new(self.position()).unwrap();
423 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
424 self.lazy_state
= LazyState
::NodeStart(pos
);
425 value
.borrow().encode(self);
426 self.lazy_state
= LazyState
::NoNode
;
428 assert
!(pos
.get() <= self.position());
430 LazyValue
::from_position(pos
)
433 fn lazy_array
<T
: ParameterizedOverTcx
, I
: IntoIterator
<Item
= B
>, B
: Borrow
<T
::Value
<'tcx
>>>(
438 T
::Value
<'tcx
>: Encodable
<EncodeContext
<'a
, 'tcx
>>,
440 let pos
= NonZeroUsize
::new(self.position()).unwrap();
442 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
443 self.lazy_state
= LazyState
::NodeStart(pos
);
444 let len
= values
.into_iter().map(|value
| value
.borrow().encode(self)).count();
445 self.lazy_state
= LazyState
::NoNode
;
447 assert
!(pos
.get() <= self.position());
449 LazyArray
::from_position_and_num_elems(pos
, len
)
452 fn encode_def_path_table(&mut self) {
453 let table
= self.tcx
.def_path_table();
454 if self.is_proc_macro
{
455 for def_index
in std
::iter
::once(CRATE_DEF_INDEX
)
456 .chain(self.tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
))
458 let def_key
= self.lazy(table
.def_key(def_index
));
459 let def_path_hash
= table
.def_path_hash(def_index
);
460 self.tables
.def_keys
.set_some(def_index
, def_key
);
461 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
);
464 for (def_index
, def_key
, def_path_hash
) in table
.enumerated_keys_and_path_hashes() {
465 let def_key
= self.lazy(def_key
);
466 self.tables
.def_keys
.set_some(def_index
, def_key
);
467 self.tables
.def_path_hashes
.set(def_index
, *def_path_hash
);
472 fn encode_def_path_hash_map(&mut self) -> LazyValue
<DefPathHashMapRef
<'
static>> {
473 self.lazy(DefPathHashMapRef
::BorrowedFromTcx(self.tcx
.def_path_hash_to_def_index_map()))
476 fn encode_source_map(&mut self) -> LazyTable
<u32, Option
<LazyValue
<rustc_span
::SourceFile
>>> {
477 let source_map
= self.tcx
.sess
.source_map();
478 let all_source_files
= source_map
.files();
480 // By replacing the `Option` with `None`, we ensure that we can't
481 // accidentally serialize any more `Span`s after the source map encoding
483 let required_source_files
= self.required_source_files
.take().unwrap();
485 let working_directory
= &self.tcx
.sess
.opts
.working_dir
;
487 let mut adapted
= TableBuilder
::default();
489 // Only serialize `SourceFile`s that were used during the encoding of a `Span`.
491 // The order in which we encode source files is important here: the on-disk format for
492 // `Span` contains the index of the corresponding `SourceFile`.
493 for (on_disk_index
, &source_file_index
) in required_source_files
.iter().enumerate() {
494 let source_file
= &all_source_files
[source_file_index
];
495 // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate.
496 assert
!(!source_file
.is_imported() || self.is_proc_macro
);
498 // At export time we expand all source file paths to absolute paths because
499 // downstream compilation sessions can have a different compiler working
500 // directory, so relative paths from this or any other upstream crate
501 // won't be valid anymore.
503 // At this point we also erase the actual on-disk path and only keep
504 // the remapped version -- as is necessary for reproducible builds.
505 let mut source_file
= match source_file
.name
{
506 FileName
::Real(ref original_file_name
) => {
507 let adapted_file_name
= source_map
509 .to_embeddable_absolute_path(original_file_name
.clone(), working_directory
);
511 if adapted_file_name
!= *original_file_name
{
512 let mut adapted
: SourceFile
= (**source_file
).clone();
513 adapted
.name
= FileName
::Real(adapted_file_name
);
514 adapted
.name_hash
= {
515 let mut hasher
: StableHasher
= StableHasher
::new();
516 adapted
.name
.hash(&mut hasher
);
517 hasher
.finish
::<Hash128
>()
525 // expanded code, not from a file
526 _
=> source_file
.clone(),
529 // We're serializing this `SourceFile` into our crate metadata,
530 // so mark it as coming from this crate.
531 // This also ensures that we don't try to deserialize the
532 // `CrateNum` for a proc-macro dependency - since proc macro
533 // dependencies aren't loaded when we deserialize a proc-macro,
534 // trying to remap the `CrateNum` would fail.
535 if self.is_proc_macro
{
536 Lrc
::make_mut(&mut source_file
).cnum
= LOCAL_CRATE
;
539 let on_disk_index
: u32 =
540 on_disk_index
.try_into().expect("cannot export more than U32_MAX files");
541 adapted
.set_some(on_disk_index
, self.lazy(source_file
));
544 adapted
.encode(&mut self.opaque
)
547 fn encode_crate_root(&mut self) -> LazyValue
<CrateRoot
> {
549 let mut stats
: Vec
<(&'
static str, usize)> = Vec
::with_capacity(32);
552 ($label
:literal
, $f
:expr
) => {{
553 let orig_pos
= self.position();
555 stats
.push(($label
, self.position() - orig_pos
));
560 // We have already encoded some things. Get their combined size from the current position.
561 stats
.push(("preamble", self.position()));
563 let (crate_deps
, dylib_dependency_formats
) =
564 stat
!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
566 let lib_features
= stat
!("lib-features", || self.encode_lib_features());
568 let stability_implications
=
569 stat
!("stability-implications", || self.encode_stability_implications());
571 let (lang_items
, lang_items_missing
) = stat
!("lang-items", || {
572 (self.encode_lang_items(), self.encode_lang_items_missing())
575 let stripped_cfg_items
= stat
!("stripped-cfg-items", || self.encode_stripped_cfg_items());
577 let diagnostic_items
= stat
!("diagnostic-items", || self.encode_diagnostic_items());
579 let native_libraries
= stat
!("native-libs", || self.encode_native_libraries());
581 let foreign_modules
= stat
!("foreign-modules", || self.encode_foreign_modules());
583 _
= stat
!("def-path-table", || self.encode_def_path_table());
585 // Encode the def IDs of traits, for rustdoc and diagnostics.
586 let traits
= stat
!("traits", || self.encode_traits());
588 // Encode the def IDs of impls, for coherence checking.
589 let impls
= stat
!("impls", || self.encode_impls());
591 let incoherent_impls
= stat
!("incoherent-impls", || self.encode_incoherent_impls());
593 _
= stat
!("mir", || self.encode_mir());
595 _
= stat
!("def-ids", || self.encode_def_ids());
597 let interpret_alloc_index
= stat
!("interpret-alloc-index", || {
598 let mut interpret_alloc_index
= Vec
::new();
600 trace
!("beginning to encode alloc ids");
602 let new_n
= self.interpret_allocs
.len();
603 // if we have found new ids, serialize those, too
608 trace
!("encoding {} further alloc ids", new_n
- n
);
609 for idx
in n
..new_n
{
610 let id
= self.interpret_allocs
[idx
];
611 let pos
= self.position() as u32;
612 interpret_alloc_index
.push(pos
);
613 interpret
::specialized_encode_alloc_id(self, tcx
, id
);
617 self.lazy_array(interpret_alloc_index
)
620 // Encode the proc macro data. This affects `tables`, so we need to do this before we
621 // encode the tables. This overwrites def_keys, so it must happen after
622 // encode_def_path_table.
623 let proc_macro_data
= stat
!("proc-macro-data", || self.encode_proc_macros());
625 let tables
= stat
!("tables", || self.tables
.encode(&mut self.opaque
));
627 let debugger_visualizers
=
628 stat
!("debugger-visualizers", || self.encode_debugger_visualizers());
630 // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
631 // this as late as possible to give the prefetching as much time as possible to complete.
632 let exported_symbols
= stat
!("exported-symbols", || {
633 self.encode_exported_symbols(&tcx
.exported_symbols(LOCAL_CRATE
))
636 // Encode the hygiene data.
637 // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
638 // process of encoding other items (e.g. `optimized_mir`) may cause us to load data from
639 // the incremental cache. If this causes us to deserialize a `Span`, then we may load
640 // additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
641 // the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
642 let (syntax_contexts
, expn_data
, expn_hashes
) = stat
!("hygiene", || self.encode_hygiene());
644 let def_path_hash_map
= stat
!("def-path-hash-map", || self.encode_def_path_hash_map());
646 // Encode source_map. This needs to be done last, because encoding `Span`s tells us which
647 // `SourceFiles` we actually need to encode.
648 let source_map
= stat
!("source-map", || self.encode_source_map());
650 let root
= stat
!("final", || {
651 let attrs
= tcx
.hir().krate_attrs();
652 self.lazy(CrateRoot
{
653 header
: CrateHeader
{
654 name
: tcx
.crate_name(LOCAL_CRATE
),
655 triple
: tcx
.sess
.opts
.target_triple
.clone(),
656 hash
: tcx
.crate_hash(LOCAL_CRATE
),
657 is_proc_macro_crate
: proc_macro_data
.is_some(),
659 extra_filename
: tcx
.sess
.opts
.cg
.extra_filename
.clone(),
660 stable_crate_id
: tcx
.def_path_hash(LOCAL_CRATE
.as_def_id()).stable_crate_id(),
661 required_panic_strategy
: tcx
.required_panic_strategy(LOCAL_CRATE
),
662 panic_in_drop_strategy
: tcx
.sess
.opts
.unstable_opts
.panic_in_drop
,
663 edition
: tcx
.sess
.edition(),
664 has_global_allocator
: tcx
.has_global_allocator(LOCAL_CRATE
),
665 has_alloc_error_handler
: tcx
.has_alloc_error_handler(LOCAL_CRATE
),
666 has_panic_handler
: tcx
.has_panic_handler(LOCAL_CRATE
),
667 has_default_lib_allocator
: attr
::contains_name(&attrs
, sym
::default_lib_allocator
),
669 debugger_visualizers
,
670 compiler_builtins
: attr
::contains_name(&attrs
, sym
::compiler_builtins
),
671 needs_allocator
: attr
::contains_name(&attrs
, sym
::needs_allocator
),
672 needs_panic_runtime
: attr
::contains_name(&attrs
, sym
::needs_panic_runtime
),
673 no_builtins
: attr
::contains_name(&attrs
, sym
::no_builtins
),
674 panic_runtime
: attr
::contains_name(&attrs
, sym
::panic_runtime
),
675 profiler_runtime
: attr
::contains_name(&attrs
, sym
::profiler_runtime
),
676 symbol_mangling_version
: tcx
.sess
.opts
.get_symbol_mangling_version(),
679 dylib_dependency_formats
,
681 stability_implications
,
693 interpret_alloc_index
,
702 let total_bytes
= self.position();
704 let computed_total_bytes
: usize = stats
.iter().map(|(_
, size
)| size
).sum();
705 assert_eq
!(total_bytes
, computed_total_bytes
);
707 if tcx
.sess
.opts
.unstable_opts
.meta_stats
{
710 // Rewind and re-read all the metadata to count the zero bytes we wrote.
711 let pos_before_rewind
= self.opaque
.file().stream_position().unwrap();
712 let mut zero_bytes
= 0;
713 self.opaque
.file().rewind().unwrap();
714 let file
= std
::io
::BufReader
::new(self.opaque
.file());
715 for e
in file
.bytes() {
720 assert_eq
!(self.opaque
.file().stream_position().unwrap(), pos_before_rewind
);
722 stats
.sort_by_key(|&(_
, usize)| usize);
724 let prefix
= "meta-stats";
725 let perc
= |bytes
| (bytes
* 100) as f64 / total_bytes
as f64;
727 eprintln
!("{prefix} METADATA STATS");
728 eprintln
!("{} {:<23}{:>10}", prefix
, "Section", "Size");
729 eprintln
!("{prefix} ----------------------------------------------------------------");
730 for (label
, size
) in stats
{
732 "{} {:<23}{:>10} ({:4.1}%)",
735 to_readable_str(size
),
739 eprintln
!("{prefix} ----------------------------------------------------------------");
741 "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
744 to_readable_str(total_bytes
),
747 eprintln
!("{prefix}");
754 struct AnalyzeAttrState
{
759 /// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
760 /// useful in downstream crates. Local-only attributes are an obvious example, but some
761 /// rustdoc-specific attributes can equally be of use while documenting the current crate only.
763 /// Removing these superfluous attributes speeds up compilation by making the metadata smaller.
765 /// Note: the `is_exported` parameter is used to cache whether the given `DefId` has a public
766 /// visibility: this is a piece of data that can be computed once per defid, and not once per
767 /// attribute. Some attributes would only be usable downstream if they are public.
769 fn analyze_attr(attr
: &Attribute
, state
: &mut AnalyzeAttrState
) -> bool
{
770 let mut should_encode
= false;
771 if rustc_feature
::is_builtin_only_local(attr
.name_or_empty()) {
772 // Attributes marked local-only don't need to be encoded for downstream crates.
773 } else if attr
.doc_str().is_some() {
774 // We keep all doc comments reachable to rustdoc because they might be "imported" into
775 // downstream crates if they use `#[doc(inline)]` to copy an item's documentation into
777 if state
.is_exported
{
778 should_encode
= true;
780 } else if attr
.has_name(sym
::doc
) {
781 // If this is a `doc` attribute that doesn't have anything except maybe `inline` (as in
782 // `#[doc(inline)]`), then we can remove it. It won't be inlinable in downstream crates.
783 if let Some(item_list
) = attr
.meta_item_list() {
784 for item
in item_list
{
785 if !item
.has_name(sym
::inline
) {
786 should_encode
= true;
787 if item
.has_name(sym
::hidden
) {
788 state
.is_doc_hidden
= true;
795 should_encode
= true;
800 fn should_encode_span(def_kind
: DefKind
) -> bool
{
810 | DefKind
::TraitAlias
813 | DefKind
::ConstParam
814 | DefKind
::LifetimeParam
820 | DefKind
::AssocConst
822 | DefKind
::ExternCrate
825 | DefKind
::InlineConst
827 | DefKind
::ImplTraitPlaceholder
829 | DefKind
::Impl { .. }
831 | DefKind
::Generator
=> true,
832 DefKind
::ForeignMod
| DefKind
::GlobalAsm
=> false,
836 fn should_encode_attrs(def_kind
: DefKind
) -> bool
{
846 | DefKind
::TraitAlias
852 | DefKind
::AssocConst
855 | DefKind
::Impl { .. }
=> true,
856 // Tools may want to be able to detect their tool lints on
857 // closures from upstream crates, too. This is used by
858 // https://github.com/model-checking/kani and is not a performance
859 // or maintenance issue for us.
860 DefKind
::Closure
=> true,
862 | DefKind
::ConstParam
864 | DefKind
::ExternCrate
866 | DefKind
::ForeignMod
868 | DefKind
::InlineConst
870 | DefKind
::ImplTraitPlaceholder
871 | DefKind
::LifetimeParam
873 | DefKind
::Generator
=> false,
877 fn should_encode_expn_that_defined(def_kind
: DefKind
) -> bool
{
885 | DefKind
::Impl { .. }
=> true,
888 | DefKind
::TraitAlias
893 | DefKind
::ConstParam
897 | DefKind
::AssocConst
899 | DefKind
::ExternCrate
901 | DefKind
::ForeignMod
903 | DefKind
::InlineConst
905 | DefKind
::ImplTraitPlaceholder
907 | DefKind
::LifetimeParam
910 | DefKind
::Generator
=> false,
914 fn should_encode_visibility(def_kind
: DefKind
) -> bool
{
924 | DefKind
::TraitAlias
928 | DefKind
::Static(..)
931 | DefKind
::AssocConst
933 | DefKind
::Field
=> true,
935 | DefKind
::ForeignMod
937 | DefKind
::ConstParam
938 | DefKind
::LifetimeParam
940 | DefKind
::InlineConst
942 | DefKind
::ImplTraitPlaceholder
944 | DefKind
::Impl { .. }
947 | DefKind
::ExternCrate
=> false,
951 fn should_encode_stability(def_kind
: DefKind
) -> bool
{
960 | DefKind
::AssocConst
962 | DefKind
::ConstParam
963 | DefKind
::Static(..)
966 | DefKind
::ForeignMod
969 | DefKind
::ImplTraitPlaceholder
972 | DefKind
::Impl { .. }
974 | DefKind
::TraitAlias
976 | DefKind
::ForeignTy
=> true,
978 | DefKind
::LifetimeParam
980 | DefKind
::InlineConst
984 | DefKind
::ExternCrate
=> false,
988 /// Whether we should encode MIR.
990 /// Computing, optimizing and encoding the MIR is a relatively expensive operation.
991 /// We want to avoid this work when not required. Therefore:
992 /// - we only compute `mir_for_ctfe` on items with const-eval semantics;
993 /// - we skip `optimized_mir` for check runs.
995 /// Return a pair, resp. for CTFE and for LLVM.
996 fn should_encode_mir(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
) -> (bool
, bool
) {
997 match tcx
.def_kind(def_id
) {
999 DefKind
::Ctor(_
, _
) => {
1000 let mir_opt_base
= tcx
.sess
.opts
.output_types
.should_codegen()
1001 || tcx
.sess
.opts
.unstable_opts
.always_encode_mir
;
1002 (true, mir_opt_base
)
1006 | DefKind
::InlineConst
1007 | DefKind
::AssocConst
1008 | DefKind
::Static(..)
1009 | DefKind
::Const
=> (true, false),
1010 // Full-fledged functions + closures
1011 DefKind
::AssocFn
| DefKind
::Fn
| DefKind
::Closure
=> {
1012 let generics
= tcx
.generics_of(def_id
);
1013 let needs_inline
= (generics
.requires_monomorphization(tcx
)
1014 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
1015 && tcx
.sess
.opts
.output_types
.should_codegen();
1016 // The function has a `const` modifier or is in a `#[const_trait]`.
1017 let is_const_fn
= tcx
.is_const_fn_raw(def_id
.to_def_id())
1018 || tcx
.is_const_default_method(def_id
.to_def_id());
1019 let always_encode_mir
= tcx
.sess
.opts
.unstable_opts
.always_encode_mir
;
1020 (is_const_fn
, needs_inline
|| always_encode_mir
)
1022 // Generators require optimized MIR to compute layout.
1023 DefKind
::Generator
=> (false, true),
1024 // The others don't have MIR.
1025 _
=> (false, false),
1029 fn should_encode_variances(def_kind
: DefKind
) -> bool
{
1036 | DefKind
::ImplTraitPlaceholder
1039 | DefKind
::AssocFn
=> true,
1043 | DefKind
::AssocConst
1045 | DefKind
::ConstParam
1046 | DefKind
::Static(..)
1048 | DefKind
::ForeignMod
1050 | DefKind
::Impl { .. }
1052 | DefKind
::TraitAlias
1053 | DefKind
::Macro(..)
1054 | DefKind
::ForeignTy
1056 | DefKind
::LifetimeParam
1057 | DefKind
::AnonConst
1058 | DefKind
::InlineConst
1059 | DefKind
::GlobalAsm
1061 | DefKind
::Generator
1062 | DefKind
::ExternCrate
=> false,
1066 fn should_encode_generics(def_kind
: DefKind
) -> bool
{
1074 | DefKind
::ForeignTy
1075 | DefKind
::TraitAlias
1079 | DefKind
::Static(..)
1082 | DefKind
::AssocConst
1083 | DefKind
::AnonConst
1084 | DefKind
::InlineConst
1086 | DefKind
::ImplTraitPlaceholder
1087 | DefKind
::Impl { .. }
1091 | DefKind
::Generator
=> true,
1093 | DefKind
::ForeignMod
1094 | DefKind
::ConstParam
1095 | DefKind
::Macro(..)
1097 | DefKind
::LifetimeParam
1098 | DefKind
::GlobalAsm
1099 | DefKind
::ExternCrate
=> false,
1103 fn should_encode_type(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
, def_kind
: DefKind
) -> bool
{
1113 | DefKind
::Static(..)
1115 | DefKind
::ForeignTy
1116 | DefKind
::Impl { .. }
1118 | DefKind
::AssocConst
1120 | DefKind
::Generator
1121 | DefKind
::ConstParam
1122 | DefKind
::AnonConst
1123 | DefKind
::InlineConst
=> true,
1125 DefKind
::OpaqueTy
=> {
1126 let origin
= tcx
.opaque_type_origin(def_id
);
1127 if let hir
::OpaqueTyOrigin
::FnReturn(fn_def_id
) | hir
::OpaqueTyOrigin
::AsyncFn(fn_def_id
) = origin
1128 && let hir
::Node
::TraitItem(trait_item
) = tcx
.hir().get_by_def_id(fn_def_id
)
1129 && let (_
, hir
::TraitFn
::Required(..)) = trait_item
.expect_fn()
1137 DefKind
::ImplTraitPlaceholder
=> {
1138 let parent_def_id
= tcx
.impl_trait_in_trait_parent_fn(def_id
.to_def_id());
1139 let assoc_item
= tcx
.associated_item(parent_def_id
);
1140 match assoc_item
.container
{
1141 // Always encode an RPIT in an impl fn, since it always has a body
1142 ty
::AssocItemContainer
::ImplContainer
=> true,
1143 ty
::AssocItemContainer
::TraitContainer
=> {
1144 // Encode an RPIT for a trait only if the trait has a default body
1145 assoc_item
.defaultness(tcx
).has_value()
1150 DefKind
::AssocTy
=> {
1151 let assoc_item
= tcx
.associated_item(def_id
);
1152 match assoc_item
.container
{
1153 ty
::AssocItemContainer
::ImplContainer
=> true,
1154 // Always encode RPITITs, since we need to be able to project
1155 // from an RPITIT associated item to an opaque when installing
1156 // the default projection predicates in default trait methods
1158 ty
::AssocItemContainer
::TraitContainer
=> {
1159 assoc_item
.defaultness(tcx
).has_value() || assoc_item
.opt_rpitit_info
.is_some()
1163 DefKind
::TyParam
=> {
1164 let hir
::Node
::GenericParam(param
) = tcx
.hir().get_by_def_id(def_id
) else { bug!() }
;
1165 let hir
::GenericParamKind
::Type { default, .. }
= param
.kind
else { bug!() }
;
1170 | DefKind
::TraitAlias
1172 | DefKind
::ForeignMod
1173 | DefKind
::Macro(..)
1175 | DefKind
::LifetimeParam
1176 | DefKind
::GlobalAsm
1177 | DefKind
::ExternCrate
=> false,
1181 fn should_encode_fn_sig(def_kind
: DefKind
) -> bool
{
1183 DefKind
::Fn
| DefKind
::AssocFn
| DefKind
::Ctor(_
, CtorKind
::Fn
) => true,
1191 | DefKind
::Static(..)
1195 | DefKind
::ImplTraitPlaceholder
1196 | DefKind
::ForeignTy
1197 | DefKind
::Impl { .. }
1198 | DefKind
::AssocConst
1200 | DefKind
::Generator
1201 | DefKind
::ConstParam
1202 | DefKind
::AnonConst
1203 | DefKind
::InlineConst
1207 | DefKind
::TraitAlias
1209 | DefKind
::ForeignMod
1210 | DefKind
::Macro(..)
1212 | DefKind
::LifetimeParam
1213 | DefKind
::GlobalAsm
1214 | DefKind
::ExternCrate
=> false,
1218 fn should_encode_constness(def_kind
: DefKind
) -> bool
{
1223 | DefKind
::Impl { of_trait: true }
1225 | DefKind
::Ctor(..) => true,
1232 | DefKind
::AssocConst
1233 | DefKind
::AnonConst
1234 | DefKind
::Static(..)
1237 | DefKind
::Impl { of_trait: false }
1238 | DefKind
::ImplTraitPlaceholder
1239 | DefKind
::ForeignTy
1240 | DefKind
::Generator
1241 | DefKind
::ConstParam
1242 | DefKind
::InlineConst
1246 | DefKind
::TraitAlias
1248 | DefKind
::ForeignMod
1249 | DefKind
::Macro(..)
1251 | DefKind
::LifetimeParam
1252 | DefKind
::GlobalAsm
1253 | DefKind
::ExternCrate
=> false,
1257 fn should_encode_const(def_kind
: DefKind
) -> bool
{
1259 DefKind
::Const
| DefKind
::AssocConst
| DefKind
::AnonConst
| DefKind
::InlineConst
=> true,
1268 | DefKind
::Static(..)
1271 | DefKind
::ImplTraitPlaceholder
1272 | DefKind
::ForeignTy
1273 | DefKind
::Impl { .. }
1276 | DefKind
::Generator
1277 | DefKind
::ConstParam
1281 | DefKind
::TraitAlias
1283 | DefKind
::ForeignMod
1284 | DefKind
::Macro(..)
1286 | DefKind
::LifetimeParam
1287 | DefKind
::GlobalAsm
1288 | DefKind
::ExternCrate
=> false,
1292 // We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
1294 fn should_encode_fn_impl_trait_in_trait
<'tcx
>(tcx
: TyCtxt
<'tcx
>, def_id
: DefId
) -> bool
{
1295 if tcx
.lower_impl_trait_in_trait_to_assoc_ty()
1296 && let Some(assoc_item
) = tcx
.opt_associated_item(def_id
)
1297 && assoc_item
.container
== ty
::AssocItemContainer
::TraitContainer
1298 && assoc_item
.kind
== ty
::AssocKind
::Fn
1306 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
1307 fn encode_attrs(&mut self, def_id
: LocalDefId
) {
1309 let mut state
= AnalyzeAttrState
{
1310 is_exported
: tcx
.effective_visibilities(()).is_exported(def_id
),
1311 is_doc_hidden
: false,
1314 .opt_local_def_id_to_hir_id(def_id
)
1315 .map_or(Default
::default(), |hir_id
| tcx
.hir().attrs(hir_id
))
1317 .filter(|attr
| analyze_attr(attr
, &mut state
));
1319 record_array
!(self.tables
.attributes
[def_id
.to_def_id()] <- attr_iter
);
1321 let mut attr_flags
= AttrFlags
::empty();
1322 if state
.is_doc_hidden
{
1323 attr_flags
|= AttrFlags
::IS_DOC_HIDDEN
;
1325 self.tables
.attr_flags
.set(def_id
.local_def_index
, attr_flags
);
1328 fn encode_def_ids(&mut self) {
1329 self.encode_info_for_mod(CRATE_DEF_ID
);
1331 // Proc-macro crates only export proc-macro items, which are looked
1332 // up using `proc_macro_data`
1333 if self.is_proc_macro
{
1339 for local_id
in tcx
.iter_local_def_id() {
1340 let def_id
= local_id
.to_def_id();
1341 let def_kind
= tcx
.opt_def_kind(local_id
);
1342 let Some(def_kind
) = def_kind
else { continue }
;
1343 self.tables
.opt_def_kind
.set_some(def_id
.index
, def_kind
);
1344 if should_encode_span(def_kind
) {
1345 let def_span
= tcx
.def_span(local_id
);
1346 record
!(self.tables
.def_span
[def_id
] <- def_span
);
1348 if should_encode_attrs(def_kind
) {
1349 self.encode_attrs(local_id
);
1351 if should_encode_expn_that_defined(def_kind
) {
1352 record
!(self.tables
.expn_that_defined
[def_id
] <- self.tcx
.expn_that_defined(def_id
));
1354 if should_encode_span(def_kind
) && let Some(ident_span
) = tcx
.def_ident_span(def_id
) {
1355 record
!(self.tables
.def_ident_span
[def_id
] <- ident_span
);
1357 if def_kind
.has_codegen_attrs() {
1358 record
!(self.tables
.codegen_fn_attrs
[def_id
] <- self.tcx
.codegen_fn_attrs(def_id
));
1360 if should_encode_visibility(def_kind
) {
1362 self.tcx
.local_visibility(local_id
).map_id(|def_id
| def_id
.local_def_index
);
1363 record
!(self.tables
.visibility
[def_id
] <- vis
);
1365 if should_encode_stability(def_kind
) {
1366 self.encode_stability(def_id
);
1367 self.encode_const_stability(def_id
);
1368 self.encode_default_body_stability(def_id
);
1369 self.encode_deprecation(def_id
);
1371 if should_encode_variances(def_kind
) {
1372 let v
= self.tcx
.variances_of(def_id
);
1373 record_array
!(self.tables
.variances_of
[def_id
] <- v
);
1375 if should_encode_fn_sig(def_kind
) {
1376 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1378 if should_encode_generics(def_kind
) {
1379 let g
= tcx
.generics_of(def_id
);
1380 record
!(self.tables
.generics_of
[def_id
] <- g
);
1381 record
!(self.tables
.explicit_predicates_of
[def_id
] <- self.tcx
.explicit_predicates_of(def_id
));
1382 let inferred_outlives
= self.tcx
.inferred_outlives_of(def_id
);
1383 record_defaulted_array
!(self.tables
.inferred_outlives_of
[def_id
] <- inferred_outlives
);
1385 for param
in &g
.params
{
1386 if let ty
::GenericParamDefKind
::Const { has_default: true, .. }
= param
.kind
{
1387 let default = self.tcx
.const_param_default(param
.def_id
);
1388 record
!(self.tables
.const_param_default
[param
.def_id
] <- default);
1392 if should_encode_type(tcx
, local_id
, def_kind
) {
1393 record
!(self.tables
.type_of
[def_id
] <- self.tcx
.type_of(def_id
));
1395 if should_encode_constness(def_kind
) {
1396 self.tables
.constness
.set_some(def_id
.index
, self.tcx
.constness(def_id
));
1398 if let DefKind
::Fn
| DefKind
::AssocFn
= def_kind
{
1399 self.tables
.asyncness
.set_some(def_id
.index
, tcx
.asyncness(def_id
));
1400 record_array
!(self.tables
.fn_arg_names
[def_id
] <- tcx
.fn_arg_names(def_id
));
1401 self.tables
.is_intrinsic
.set(def_id
.index
, tcx
.is_intrinsic(def_id
));
1403 if let DefKind
::TyParam
= def_kind
{
1404 let default = self.tcx
.object_lifetime_default(def_id
);
1405 record
!(self.tables
.object_lifetime_default
[def_id
] <- default);
1407 if let DefKind
::Trait
= def_kind
{
1408 record
!(self.tables
.trait_def
[def_id
] <- self.tcx
.trait_def(def_id
));
1409 record
!(self.tables
.super_predicates_of
[def_id
] <- self.tcx
.super_predicates_of(def_id
));
1411 let module_children
= self.tcx
.module_children_local(local_id
);
1412 record_array
!(self.tables
.module_children_non_reexports
[def_id
] <-
1413 module_children
.iter().map(|child
| child
.res
.def_id().index
));
1415 if let DefKind
::TraitAlias
= def_kind
{
1416 record
!(self.tables
.trait_def
[def_id
] <- self.tcx
.trait_def(def_id
));
1417 record
!(self.tables
.super_predicates_of
[def_id
] <- self.tcx
.super_predicates_of(def_id
));
1418 record
!(self.tables
.implied_predicates_of
[def_id
] <- self.tcx
.implied_predicates_of(def_id
));
1420 if let DefKind
::Trait
| DefKind
::Impl { .. }
= def_kind
{
1421 let associated_item_def_ids
= self.tcx
.associated_item_def_ids(def_id
);
1422 record_array
!(self.tables
.associated_item_or_field_def_ids
[def_id
] <-
1423 associated_item_def_ids
.iter().map(|&def_id
| {
1424 assert
!(def_id
.is_local());
1428 for &def_id
in associated_item_def_ids
{
1429 self.encode_info_for_assoc_item(def_id
);
1432 if let DefKind
::Generator
= def_kind
{
1433 self.encode_info_for_generator(local_id
);
1435 if let DefKind
::Enum
| DefKind
::Struct
| DefKind
::Union
= def_kind
{
1436 self.encode_info_for_adt(local_id
);
1438 if let DefKind
::Mod
= def_kind
{
1439 self.encode_info_for_mod(local_id
);
1441 if let DefKind
::Macro(_
) = def_kind
{
1442 self.encode_info_for_macro(local_id
);
1444 if let DefKind
::OpaqueTy
= def_kind
{
1445 self.encode_explicit_item_bounds(def_id
);
1447 .is_type_alias_impl_trait
1448 .set(def_id
.index
, self.tcx
.is_type_alias_impl_trait(def_id
));
1450 if let DefKind
::ImplTraitPlaceholder
= def_kind
{
1451 self.encode_explicit_item_bounds(def_id
);
1453 if tcx
.impl_method_has_trait_impl_trait_tys(def_id
)
1454 && let Ok(table
) = self.tcx
.collect_return_position_impl_trait_in_trait_tys(def_id
)
1456 record
!(self.tables
.trait_impl_trait_tys
[def_id
] <- table
);
1458 if should_encode_fn_impl_trait_in_trait(tcx
, def_id
) {
1459 let table
= tcx
.associated_types_for_impl_traits_in_associated_fn(def_id
);
1460 record_defaulted_array
!(self.tables
.associated_types_for_impl_traits_in_associated_fn
[def_id
] <- table
);
1464 let inherent_impls
= tcx
.with_stable_hashing_context(|hcx
| {
1465 tcx
.crate_inherent_impls(()).inherent_impls
.to_sorted(&hcx
, true)
1467 for (def_id
, impls
) in inherent_impls
{
1468 record_defaulted_array
!(self.tables
.inherent_impls
[def_id
.to_def_id()] <- impls
.iter().map(|def_id
| {
1469 assert
!(def_id
.is_local());
1474 for (def_id
, res_map
) in &tcx
.resolutions(()).doc_link_resolutions
{
1475 record
!(self.tables
.doc_link_resolutions
[def_id
.to_def_id()] <- res_map
);
1478 for (def_id
, traits
) in &tcx
.resolutions(()).doc_link_traits_in_scope
{
1479 record_array
!(self.tables
.doc_link_traits_in_scope
[def_id
.to_def_id()] <- traits
);
1483 #[instrument(level = "trace", skip(self))]
1484 fn encode_info_for_adt(&mut self, local_def_id
: LocalDefId
) {
1485 let def_id
= local_def_id
.to_def_id();
1487 let adt_def
= tcx
.adt_def(def_id
);
1488 record
!(self.tables
.repr_options
[def_id
] <- adt_def
.repr());
1490 let params_in_repr
= self.tcx
.params_in_repr(def_id
);
1491 record
!(self.tables
.params_in_repr
[def_id
] <- params_in_repr
);
1493 if adt_def
.is_enum() {
1494 let module_children
= tcx
.module_children_local(local_def_id
);
1495 record_array
!(self.tables
.module_children_non_reexports
[def_id
] <-
1496 module_children
.iter().map(|child
| child
.res
.def_id().index
));
1498 // For non-enum, there is only one variant, and its def_id is the adt's.
1499 debug_assert_eq
!(adt_def
.variants().len(), 1);
1500 debug_assert_eq
!(adt_def
.non_enum_variant().def_id
, def_id
);
1501 // Therefore, the loop over variants will encode its fields as the adt's children.
1504 for (idx
, variant
) in adt_def
.variants().iter_enumerated() {
1505 let data
= VariantData
{
1506 discr
: variant
.discr
,
1508 ctor
: variant
.ctor
.map(|(kind
, def_id
)| (kind
, def_id
.index
)),
1509 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1511 record
!(self.tables
.variant_data
[variant
.def_id
] <- data
);
1513 record_array
!(self.tables
.associated_item_or_field_def_ids
[variant
.def_id
] <- variant
.fields
.iter().map(|f
| {
1514 assert
!(f
.did
.is_local());
1518 if let Some((CtorKind
::Fn
, ctor_def_id
)) = variant
.ctor
{
1519 let fn_sig
= tcx
.fn_sig(ctor_def_id
);
1520 // FIXME only encode signature for ctor_def_id
1521 record
!(self.tables
.fn_sig
[variant
.def_id
] <- fn_sig
);
1526 #[instrument(level = "debug", skip(self))]
1527 fn encode_info_for_mod(&mut self, local_def_id
: LocalDefId
) {
1529 let def_id
= local_def_id
.to_def_id();
1531 // If we are encoding a proc-macro crates, `encode_info_for_mod` will
1532 // only ever get called for the crate root. We still want to encode
1533 // the crate root for consistency with other crates (some of the resolver
1534 // code uses it). However, we skip encoding anything relating to child
1535 // items - we encode information about proc-macros later on.
1536 if self.is_proc_macro
{
1537 // Encode this here because we don't do it in encode_def_ids.
1538 record
!(self.tables
.expn_that_defined
[def_id
] <- tcx
.expn_that_defined(local_def_id
));
1540 let module_children
= tcx
.module_children_local(local_def_id
);
1542 record_array
!(self.tables
.module_children_non_reexports
[def_id
] <-
1543 module_children
.iter().filter(|child
| child
.reexport_chain
.is_empty())
1544 .map(|child
| child
.res
.def_id().index
));
1546 record_defaulted_array
!(self.tables
.module_children_reexports
[def_id
] <-
1547 module_children
.iter().filter(|child
| !child
.reexport_chain
.is_empty()));
1551 fn encode_explicit_item_bounds(&mut self, def_id
: DefId
) {
1552 debug
!("EncodeContext::encode_explicit_item_bounds({:?})", def_id
);
1553 let bounds
= self.tcx
.explicit_item_bounds(def_id
).skip_binder();
1554 record_defaulted_array
!(self.tables
.explicit_item_bounds
[def_id
] <- bounds
);
1557 #[instrument(level = "debug", skip(self))]
1558 fn encode_info_for_assoc_item(&mut self, def_id
: DefId
) {
1560 let item
= tcx
.associated_item(def_id
);
1562 self.tables
.defaultness
.set_some(def_id
.index
, item
.defaultness(tcx
));
1563 self.tables
.assoc_container
.set_some(def_id
.index
, item
.container
);
1565 match item
.container
{
1566 AssocItemContainer
::TraitContainer
=> {
1567 if let ty
::AssocKind
::Type
= item
.kind
{
1568 self.encode_explicit_item_bounds(def_id
);
1571 AssocItemContainer
::ImplContainer
=> {
1572 if let Some(trait_item_def_id
) = item
.trait_item_def_id
{
1573 self.tables
.trait_item_def_id
.set_some(def_id
.index
, trait_item_def_id
.into());
1577 if let Some(rpitit_info
) = item
.opt_rpitit_info
{
1578 record
!(self.tables
.opt_rpitit_info
[def_id
] <- rpitit_info
);
1582 fn encode_mir(&mut self) {
1583 if self.is_proc_macro
{
1589 let keys_and_jobs
= tcx
.mir_keys(()).iter().filter_map(|&def_id
| {
1590 let (encode_const
, encode_opt
) = should_encode_mir(tcx
, def_id
);
1591 if encode_const
|| encode_opt { Some((def_id, encode_const, encode_opt)) }
else { None }
1593 for (def_id
, encode_const
, encode_opt
) in keys_and_jobs
{
1594 debug_assert
!(encode_const
|| encode_opt
);
1596 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
1598 record
!(self.tables
.optimized_mir
[def_id
.to_def_id()] <- tcx
.optimized_mir(def_id
));
1599 record
!(self.tables
.closure_saved_names_of_captured_variables
[def_id
.to_def_id()]
1600 <- tcx
.closure_saved_names_of_captured_variables(def_id
));
1602 if tcx
.sess
.opts
.unstable_opts
.drop_tracking_mir
1603 && let DefKind
::Generator
= self.tcx
.def_kind(def_id
)
1604 && let Some(witnesses
) = tcx
.mir_generator_witnesses(def_id
)
1606 record
!(self.tables
.mir_generator_witnesses
[def_id
.to_def_id()] <- witnesses
);
1610 record
!(self.tables
.mir_for_ctfe
[def_id
.to_def_id()] <- tcx
.mir_for_ctfe(def_id
));
1612 // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
1613 let abstract_const
= tcx
.thir_abstract_const(def_id
);
1614 if let Ok(Some(abstract_const
)) = abstract_const
{
1615 record
!(self.tables
.thir_abstract_const
[def_id
.to_def_id()] <- abstract_const
);
1618 if should_encode_const(tcx
.def_kind(def_id
)) {
1619 let qualifs
= tcx
.mir_const_qualif(def_id
);
1620 record
!(self.tables
.mir_const_qualif
[def_id
.to_def_id()] <- qualifs
);
1621 let body_id
= tcx
.hir().maybe_body_owned_by(def_id
);
1622 if let Some(body_id
) = body_id
{
1623 let const_data
= self.encode_rendered_const_for_body(body_id
);
1624 record
!(self.tables
.rendered_const
[def_id
.to_def_id()] <- const_data
);
1628 record
!(self.tables
.promoted_mir
[def_id
.to_def_id()] <- tcx
.promoted_mir(def_id
));
1630 let instance
= ty
::InstanceDef
::Item(def_id
.to_def_id());
1631 let unused
= tcx
.unused_generic_params(instance
);
1632 self.tables
.unused_generic_params
.set(def_id
.local_def_index
, unused
);
1635 // Encode all the deduced parameter attributes for everything that has MIR, even for items
1636 // that can't be inlined. But don't if we aren't optimizing in non-incremental mode, to
1637 // save the query traffic.
1638 if tcx
.sess
.opts
.output_types
.should_codegen()
1639 && tcx
.sess
.opts
.optimize
!= OptLevel
::No
1640 && tcx
.sess
.opts
.incremental
.is_none()
1642 for &local_def_id
in tcx
.mir_keys(()) {
1643 if let DefKind
::AssocFn
| DefKind
::Fn
= tcx
.def_kind(local_def_id
) {
1644 record_array
!(self.tables
.deduced_param_attrs
[local_def_id
.to_def_id()] <-
1645 self.tcx
.deduced_param_attrs(local_def_id
.to_def_id()));
1651 #[instrument(level = "debug", skip(self))]
1652 fn encode_stability(&mut self, def_id
: DefId
) {
1653 // The query lookup can take a measurable amount of time in crates with many items. Check if
1654 // the stability attributes are even enabled before using their queries.
1655 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.unstable_opts
.force_unstable_if_unmarked
{
1656 if let Some(stab
) = self.tcx
.lookup_stability(def_id
) {
1657 record
!(self.tables
.lookup_stability
[def_id
] <- stab
)
1662 #[instrument(level = "debug", skip(self))]
1663 fn encode_const_stability(&mut self, def_id
: DefId
) {
1664 // The query lookup can take a measurable amount of time in crates with many items. Check if
1665 // the stability attributes are even enabled before using their queries.
1666 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.unstable_opts
.force_unstable_if_unmarked
{
1667 if let Some(stab
) = self.tcx
.lookup_const_stability(def_id
) {
1668 record
!(self.tables
.lookup_const_stability
[def_id
] <- stab
)
1673 #[instrument(level = "debug", skip(self))]
1674 fn encode_default_body_stability(&mut self, def_id
: DefId
) {
1675 // The query lookup can take a measurable amount of time in crates with many items. Check if
1676 // the stability attributes are even enabled before using their queries.
1677 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.unstable_opts
.force_unstable_if_unmarked
{
1678 if let Some(stab
) = self.tcx
.lookup_default_body_stability(def_id
) {
1679 record
!(self.tables
.lookup_default_body_stability
[def_id
] <- stab
)
1684 #[instrument(level = "debug", skip(self))]
1685 fn encode_deprecation(&mut self, def_id
: DefId
) {
1686 if let Some(depr
) = self.tcx
.lookup_deprecation(def_id
) {
1687 record
!(self.tables
.lookup_deprecation_entry
[def_id
] <- depr
);
1691 fn encode_rendered_const_for_body(&mut self, body_id
: hir
::BodyId
) -> String
{
1692 let hir
= self.tcx
.hir();
1693 let body
= hir
.body(body_id
);
1694 rustc_hir_pretty
::to_string(&(&hir
as &dyn intravisit
::Map
<'_
>), |s
| {
1695 s
.print_expr(&body
.value
)
1699 #[instrument(level = "debug", skip(self))]
1700 fn encode_info_for_macro(&mut self, def_id
: LocalDefId
) {
1703 let hir
::ItemKind
::Macro(ref macro_def
, _
) = tcx
.hir().expect_item(def_id
).kind
else { bug!() }
;
1704 self.tables
.is_macro_rules
.set(def_id
.local_def_index
, macro_def
.macro_rules
);
1705 record
!(self.tables
.macro_definition
[def_id
.to_def_id()] <- &*macro_def
.body
);
1708 #[instrument(level = "debug", skip(self))]
1709 fn encode_info_for_generator(&mut self, def_id
: LocalDefId
) {
1710 let typeck_result
: &'tcx ty
::TypeckResults
<'tcx
> = self.tcx
.typeck(def_id
);
1711 let data
= self.tcx
.generator_kind(def_id
).unwrap();
1712 let generator_diagnostic_data
= typeck_result
.get_generator_diagnostic_data();
1713 record
!(self.tables
.generator_kind
[def_id
.to_def_id()] <- data
);
1714 record
!(self.tables
.generator_diagnostic_data
[def_id
.to_def_id()] <- generator_diagnostic_data
);
1717 fn encode_native_libraries(&mut self) -> LazyArray
<NativeLib
> {
1718 empty_proc_macro
!(self);
1719 let used_libraries
= self.tcx
.native_libraries(LOCAL_CRATE
);
1720 self.lazy_array(used_libraries
.iter())
1723 fn encode_foreign_modules(&mut self) -> LazyArray
<ForeignModule
> {
1724 empty_proc_macro
!(self);
1725 let foreign_modules
= self.tcx
.foreign_modules(LOCAL_CRATE
);
1726 self.lazy_array(foreign_modules
.iter().map(|(_
, m
)| m
).cloned())
1729 fn encode_hygiene(&mut self) -> (SyntaxContextTable
, ExpnDataTable
, ExpnHashTable
) {
1730 let mut syntax_contexts
: TableBuilder
<_
, _
> = Default
::default();
1731 let mut expn_data_table
: TableBuilder
<_
, _
> = Default
::default();
1732 let mut expn_hash_table
: TableBuilder
<_
, _
> = Default
::default();
1734 self.hygiene_ctxt
.encode(
1735 &mut (&mut *self, &mut syntax_contexts
, &mut expn_data_table
, &mut expn_hash_table
),
1736 |(this
, syntax_contexts
, _
, _
), index
, ctxt_data
| {
1737 syntax_contexts
.set_some(index
, this
.lazy(ctxt_data
));
1739 |(this
, _
, expn_data_table
, expn_hash_table
), index
, expn_data
, hash
| {
1740 if let Some(index
) = index
.as_local() {
1741 expn_data_table
.set_some(index
.as_raw(), this
.lazy(expn_data
));
1742 expn_hash_table
.set_some(index
.as_raw(), this
.lazy(hash
));
1748 syntax_contexts
.encode(&mut self.opaque
),
1749 expn_data_table
.encode(&mut self.opaque
),
1750 expn_hash_table
.encode(&mut self.opaque
),
1754 fn encode_proc_macros(&mut self) -> Option
<ProcMacroData
> {
1755 let is_proc_macro
= self.tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
);
1758 let hir
= tcx
.hir();
1760 let proc_macro_decls_static
= tcx
.proc_macro_decls_static(()).unwrap().local_def_index
;
1761 let stability
= tcx
.lookup_stability(CRATE_DEF_ID
);
1763 self.lazy_array(tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
));
1764 for (i
, span
) in self.tcx
.sess
.parse_sess
.proc_macro_quoted_spans() {
1765 let span
= self.lazy(span
);
1766 self.tables
.proc_macro_quoted_spans
.set_some(i
, span
);
1769 self.tables
.opt_def_kind
.set_some(LOCAL_CRATE
.as_def_id().index
, DefKind
::Mod
);
1770 record
!(self.tables
.def_span
[LOCAL_CRATE
.as_def_id()] <- tcx
.def_span(LOCAL_CRATE
.as_def_id()));
1771 self.encode_attrs(LOCAL_CRATE
.as_def_id().expect_local());
1772 let vis
= tcx
.local_visibility(CRATE_DEF_ID
).map_id(|def_id
| def_id
.local_def_index
);
1773 record
!(self.tables
.visibility
[LOCAL_CRATE
.as_def_id()] <- vis
);
1774 if let Some(stability
) = stability
{
1775 record
!(self.tables
.lookup_stability
[LOCAL_CRATE
.as_def_id()] <- stability
);
1777 self.encode_deprecation(LOCAL_CRATE
.as_def_id());
1778 if let Some(res_map
) = tcx
.resolutions(()).doc_link_resolutions
.get(&CRATE_DEF_ID
) {
1779 record
!(self.tables
.doc_link_resolutions
[LOCAL_CRATE
.as_def_id()] <- res_map
);
1781 if let Some(traits
) = tcx
.resolutions(()).doc_link_traits_in_scope
.get(&CRATE_DEF_ID
) {
1782 record_array
!(self.tables
.doc_link_traits_in_scope
[LOCAL_CRATE
.as_def_id()] <- traits
);
1785 // Normally, this information is encoded when we walk the items
1786 // defined in this crate. However, we skip doing that for proc-macro crates,
1787 // so we manually encode just the information that we need
1788 for &proc_macro
in &tcx
.resolutions(()).proc_macros
{
1789 let id
= proc_macro
;
1790 let proc_macro
= hir
.local_def_id_to_hir_id(proc_macro
);
1791 let mut name
= hir
.name(proc_macro
);
1792 let span
= hir
.span(proc_macro
);
1793 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1794 // so downstream crates need access to them.
1795 let attrs
= hir
.attrs(proc_macro
);
1796 let macro_kind
= if attr
::contains_name(attrs
, sym
::proc_macro
) {
1798 } else if attr
::contains_name(attrs
, sym
::proc_macro_attribute
) {
1800 } else if let Some(attr
) = attr
::find_by_name(attrs
, sym
::proc_macro_derive
) {
1801 // This unwrap chain should have been checked by the proc-macro harness.
1802 name
= attr
.meta_item_list().unwrap()[0]
1810 bug
!("Unknown proc-macro type for item {:?}", id
);
1813 let mut def_key
= self.tcx
.hir().def_key(id
);
1814 def_key
.disambiguated_data
.data
= DefPathData
::MacroNs(name
);
1816 let def_id
= id
.to_def_id();
1817 self.tables
.opt_def_kind
.set_some(def_id
.index
, DefKind
::Macro(macro_kind
));
1818 self.tables
.proc_macro
.set_some(def_id
.index
, macro_kind
);
1819 self.encode_attrs(id
);
1820 record
!(self.tables
.def_keys
[def_id
] <- def_key
);
1821 record
!(self.tables
.def_ident_span
[def_id
] <- span
);
1822 record
!(self.tables
.def_span
[def_id
] <- span
);
1823 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::Public
);
1824 if let Some(stability
) = stability
{
1825 record
!(self.tables
.lookup_stability
[def_id
] <- stability
);
1829 Some(ProcMacroData { proc_macro_decls_static, stability, macros }
)
1835 fn encode_debugger_visualizers(&mut self) -> LazyArray
<DebuggerVisualizerFile
> {
1836 empty_proc_macro
!(self);
1839 .debugger_visualizers(LOCAL_CRATE
)
1841 // Erase the path since it may contain privacy sensitive data
1842 // that we don't want to end up in crate metadata.
1843 // The path is only needed for the local crate because of
1844 // `--emit dep-info`.
1845 .map(DebuggerVisualizerFile
::path_erased
),
1849 fn encode_crate_deps(&mut self) -> LazyArray
<CrateDep
> {
1850 empty_proc_macro
!(self);
1857 let dep
= CrateDep
{
1858 name
: self.tcx
.crate_name(cnum
),
1859 hash
: self.tcx
.crate_hash(cnum
),
1860 host_hash
: self.tcx
.crate_host_hash(cnum
),
1861 kind
: self.tcx
.dep_kind(cnum
),
1862 extra_filename
: self.tcx
.extra_filename(cnum
).clone(),
1863 is_private
: self.tcx
.is_private_dep(cnum
),
1867 .collect
::<Vec
<_
>>();
1870 // Sanity-check the crate numbers
1871 let mut expected_cnum
= 1;
1872 for &(n
, _
) in &deps
{
1873 assert_eq
!(n
, CrateNum
::new(expected_cnum
));
1878 // We're just going to write a list of crate 'name-hash-version's, with
1879 // the assumption that they are numbered 1 to n.
1880 // FIXME (#2166): This is not nearly enough to support correct versioning
1881 // but is enough to get transitive crate dependencies working.
1882 self.lazy_array(deps
.iter().map(|(_
, dep
)| dep
))
1885 fn encode_lib_features(&mut self) -> LazyArray
<(Symbol
, Option
<Symbol
>)> {
1886 empty_proc_macro
!(self);
1888 let lib_features
= tcx
.lib_features(());
1889 self.lazy_array(lib_features
.to_vec())
1892 fn encode_stability_implications(&mut self) -> LazyArray
<(Symbol
, Symbol
)> {
1893 empty_proc_macro
!(self);
1895 let implications
= tcx
.stability_implications(LOCAL_CRATE
);
1896 self.lazy_array(implications
.iter().map(|(k
, v
)| (*k
, *v
)))
1899 fn encode_diagnostic_items(&mut self) -> LazyArray
<(Symbol
, DefIndex
)> {
1900 empty_proc_macro
!(self);
1902 let diagnostic_items
= &tcx
.diagnostic_items(LOCAL_CRATE
).name_to_id
;
1903 self.lazy_array(diagnostic_items
.iter().map(|(&name
, def_id
)| (name
, def_id
.index
)))
1906 fn encode_lang_items(&mut self) -> LazyArray
<(DefIndex
, LangItem
)> {
1907 empty_proc_macro
!(self);
1908 let lang_items
= self.tcx
.lang_items().iter();
1909 self.lazy_array(lang_items
.filter_map(|(lang_item
, def_id
)| {
1910 def_id
.as_local().map(|id
| (id
.local_def_index
, lang_item
))
1914 fn encode_lang_items_missing(&mut self) -> LazyArray
<LangItem
> {
1915 empty_proc_macro
!(self);
1917 self.lazy_array(&tcx
.lang_items().missing
)
1920 fn encode_stripped_cfg_items(&mut self) -> LazyArray
<StrippedCfgItem
<DefIndex
>> {
1923 .stripped_cfg_items(LOCAL_CRATE
)
1925 .map(|item
| item
.clone().map_mod_id(|def_id
| def_id
.index
)),
1929 fn encode_traits(&mut self) -> LazyArray
<DefIndex
> {
1930 empty_proc_macro
!(self);
1931 self.lazy_array(self.tcx
.traits(LOCAL_CRATE
).iter().map(|def_id
| def_id
.index
))
1934 /// Encodes an index, mapping each trait to its (local) implementations.
1935 #[instrument(level = "debug", skip(self))]
1936 fn encode_impls(&mut self) -> LazyArray
<TraitImpls
> {
1937 empty_proc_macro
!(self);
1939 let mut fx_hash_map
: FxHashMap
<DefId
, Vec
<(DefIndex
, Option
<SimplifiedType
>)>> =
1940 FxHashMap
::default();
1942 for id
in tcx
.hir().items() {
1943 let DefKind
::Impl { of_trait }
= tcx
.def_kind(id
.owner_id
) else { continue; }
;
1944 let def_id
= id
.owner_id
.to_def_id();
1946 self.tables
.defaultness
.set_some(def_id
.index
, tcx
.defaultness(def_id
));
1947 self.tables
.impl_polarity
.set_some(def_id
.index
, tcx
.impl_polarity(def_id
));
1949 if of_trait
&& let Some(trait_ref
) = tcx
.impl_trait_ref(def_id
) {
1950 record
!(self.tables
.impl_trait_ref
[def_id
] <- trait_ref
);
1952 let trait_ref
= trait_ref
.subst_identity();
1953 let simplified_self_ty
=
1954 fast_reject
::simplify_type(self.tcx
, trait_ref
.self_ty(), TreatParams
::AsCandidateKey
);
1956 .entry(trait_ref
.def_id
)
1958 .push((id
.owner_id
.def_id
.local_def_index
, simplified_self_ty
));
1960 let trait_def
= tcx
.trait_def(trait_ref
.def_id
);
1961 if let Some(mut an
) = trait_def
.ancestors(tcx
, def_id
).ok() {
1962 if let Some(specialization_graph
::Node
::Impl(parent
)) = an
.nth(1) {
1963 self.tables
.impl_parent
.set_some(def_id
.index
, parent
.into());
1967 // if this is an impl of `CoerceUnsized`, create its
1968 // "unsized info", else just store None
1969 if Some(trait_ref
.def_id
) == tcx
.lang_items().coerce_unsized_trait() {
1970 let coerce_unsized_info
= tcx
.coerce_unsized_info(def_id
);
1971 record
!(self.tables
.coerce_unsized_info
[def_id
] <- coerce_unsized_info
);
1976 let mut all_impls
: Vec
<_
> = fx_hash_map
.into_iter().collect();
1978 // Bring everything into deterministic order for hashing
1979 all_impls
.sort_by_cached_key(|&(trait_def_id
, _
)| tcx
.def_path_hash(trait_def_id
));
1981 let all_impls
: Vec
<_
> = all_impls
1983 .map(|(trait_def_id
, mut impls
)| {
1984 // Bring everything into deterministic order for hashing
1985 impls
.sort_by_cached_key(|&(index
, _
)| {
1986 tcx
.hir().def_path_hash(LocalDefId { local_def_index: index }
)
1990 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
1991 impls
: self.lazy_array(&impls
),
1996 self.lazy_array(&all_impls
)
1999 #[instrument(level = "debug", skip(self))]
2000 fn encode_incoherent_impls(&mut self) -> LazyArray
<IncoherentImpls
> {
2001 empty_proc_macro
!(self);
2003 let mut all_impls
: Vec
<_
> = tcx
.crate_inherent_impls(()).incoherent_impls
.iter().collect();
2004 tcx
.with_stable_hashing_context(|mut ctx
| {
2005 all_impls
.sort_by_cached_key(|&(&simp
, _
)| {
2006 let mut hasher
= StableHasher
::new();
2007 simp
.hash_stable(&mut ctx
, &mut hasher
);
2008 hasher
.finish
::<Fingerprint
>()
2011 let all_impls
: Vec
<_
> = all_impls
2013 .map(|(&simp
, impls
)| {
2014 let mut impls
: Vec
<_
> =
2015 impls
.into_iter().map(|def_id
| def_id
.local_def_index
).collect();
2016 impls
.sort_by_cached_key(|&local_def_index
| {
2017 tcx
.hir().def_path_hash(LocalDefId { local_def_index }
)
2020 IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
2024 self.lazy_array(&all_impls
)
2027 // Encodes all symbols exported from this crate into the metadata.
2029 // This pass is seeded off the reachability list calculated in the
2030 // middle::reachable module but filters out items that either don't have a
2031 // symbol associated with them (they weren't translated) or if they're an FFI
2032 // definition (as that's not defined in this crate).
2033 fn encode_exported_symbols(
2035 exported_symbols
: &[(ExportedSymbol
<'tcx
>, SymbolExportInfo
)],
2036 ) -> LazyArray
<(ExportedSymbol
<'
static>, SymbolExportInfo
)> {
2037 empty_proc_macro
!(self);
2038 // The metadata symbol name is special. It should not show up in
2039 // downstream crates.
2040 let metadata_symbol_name
= SymbolName
::new(self.tcx
, &metadata_symbol_name(self.tcx
));
2045 .filter(|&(exported_symbol
, _
)| match *exported_symbol
{
2046 ExportedSymbol
::NoDefId(symbol_name
) => symbol_name
!= metadata_symbol_name
,
2053 fn encode_dylib_dependency_formats(&mut self) -> LazyArray
<Option
<LinkagePreference
>> {
2054 empty_proc_macro
!(self);
2055 let formats
= self.tcx
.dependency_formats(());
2056 for (ty
, arr
) in formats
.iter() {
2057 if *ty
!= CrateType
::Dylib
{
2060 return self.lazy_array(arr
.iter().map(|slot
| match *slot
{
2061 Linkage
::NotLinked
| Linkage
::IncludedFromDylib
=> None
,
2063 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
2064 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
2067 LazyArray
::default()
2071 /// Used to prefetch queries which will be needed later by metadata encoding.
2072 /// Only a subset of the queries are actually prefetched to keep this code smaller.
2073 fn prefetch_mir(tcx
: TyCtxt
<'_
>) {
2074 if !tcx
.sess
.opts
.output_types
.should_codegen() {
2075 // We won't emit MIR, so don't prefetch it.
2079 par_for_each_in(tcx
.mir_keys(()), |&def_id
| {
2080 let (encode_const
, encode_opt
) = should_encode_mir(tcx
, def_id
);
2083 tcx
.ensure_with_value().mir_for_ctfe(def_id
);
2086 tcx
.ensure_with_value().optimized_mir(def_id
);
2088 if encode_opt
|| encode_const
{
2089 tcx
.ensure_with_value().promoted_mir(def_id
);
2094 // NOTE(eddyb) The following comment was preserved for posterity, even
2095 // though it's no longer relevant as EBML (which uses nested & tagged
2096 // "documents") was replaced with a scheme that can't go out of bounds.
2098 // And here we run into yet another obscure archive bug: in which metadata
2099 // loaded from archives may have trailing garbage bytes. Awhile back one of
2100 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
2101 // and opt) by having ebml generate an out-of-bounds panic when looking at
2104 // Upon investigation it turned out that the metadata file inside of an rlib
2105 // (and ar archive) was being corrupted. Some compilations would generate a
2106 // metadata file which would end in a few extra bytes, while other
2107 // compilations would not have these extra bytes appended to the end. These
2108 // extra bytes were interpreted by ebml as an extra tag, so they ended up
2109 // being interpreted causing the out-of-bounds.
2111 // The root cause of why these extra bytes were appearing was never
2112 // discovered, and in the meantime the solution we're employing is to insert
2113 // the length of the metadata to the start of the metadata. Later on this
2114 // will allow us to slice the metadata to the precise length that we just
2115 // generated regardless of trailing bytes that end up in it.
2117 pub struct EncodedMetadata
{
2118 // The declaration order matters because `mmap` should be dropped before `_temp_dir`.
2120 // We need to carry MaybeTempDir to avoid deleting the temporary
2121 // directory while accessing the Mmap.
2122 _temp_dir
: Option
<MaybeTempDir
>,
2125 impl EncodedMetadata
{
2127 pub fn from_path(path
: PathBuf
, temp_dir
: Option
<MaybeTempDir
>) -> std
::io
::Result
<Self> {
2128 let file
= std
::fs
::File
::open(&path
)?
;
2129 let file_metadata
= file
.metadata()?
;
2130 if file_metadata
.len() == 0 {
2131 return Ok(Self { mmap: None, _temp_dir: None }
);
2133 let mmap
= unsafe { Some(Mmap::map(file)?) }
;
2134 Ok(Self { mmap, _temp_dir: temp_dir }
)
2138 pub fn raw_data(&self) -> &[u8] {
2139 self.mmap
.as_deref().unwrap_or_default()
2143 impl<S
: Encoder
> Encodable
<S
> for EncodedMetadata
{
2144 fn encode(&self, s
: &mut S
) {
2145 let slice
= self.raw_data();
2150 impl<D
: Decoder
> Decodable
<D
> for EncodedMetadata
{
2151 fn decode(d
: &mut D
) -> Self {
2152 let len
= d
.read_usize();
2153 let mmap
= if len
> 0 {
2154 let mut mmap
= MmapMut
::map_anon(len
).unwrap();
2156 (&mut mmap
[..]).write(&[d
.read_u8()]).unwrap();
2158 mmap
.flush().unwrap();
2159 Some(mmap
.make_read_only().unwrap())
2164 Self { mmap, _temp_dir: None }
2168 pub fn encode_metadata(tcx
: TyCtxt
<'_
>, path
: &Path
) {
2169 let _prof_timer
= tcx
.prof
.verbose_generic_activity("generate_crate_metadata");
2171 // Since encoding metadata is not in a query, and nothing is cached,
2172 // there's no need to do dep-graph tracking for any of it.
2173 tcx
.dep_graph
.assert_ignored();
2176 || encode_metadata_impl(tcx
, path
),
2178 if tcx
.sess
.threads() == 1 {
2181 // Prefetch some queries used by metadata encoding.
2182 // This is not necessary for correctness, but is only done for performance reasons.
2183 // It can be removed if it turns out to cause trouble or be detrimental to performance.
2184 join(|| prefetch_mir(tcx
), || tcx
.exported_symbols(LOCAL_CRATE
));
2189 fn encode_metadata_impl(tcx
: TyCtxt
<'_
>, path
: &Path
) {
2190 let mut encoder
= opaque
::FileEncoder
::new(path
)
2191 .unwrap_or_else(|err
| tcx
.sess
.emit_fatal(FailCreateFileEncoder { err }
));
2192 encoder
.emit_raw_bytes(METADATA_HEADER
);
2194 // Will be filled with the root position after encoding everything.
2195 encoder
.emit_raw_bytes(&[0, 0, 0, 0]);
2197 let source_map_files
= tcx
.sess
.source_map().files();
2198 let source_file_cache
= (source_map_files
[0].clone(), 0);
2199 let required_source_files
= Some(FxIndexSet
::default());
2200 drop(source_map_files
);
2202 let hygiene_ctxt
= HygieneEncodeContext
::default();
2204 let mut ecx
= EncodeContext
{
2207 feat
: tcx
.features(),
2208 tables
: Default
::default(),
2209 lazy_state
: LazyState
::NoNode
,
2210 type_shorthands
: Default
::default(),
2211 predicate_shorthands
: Default
::default(),
2213 interpret_allocs
: Default
::default(),
2214 required_source_files
,
2215 is_proc_macro
: tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
),
2216 hygiene_ctxt
: &hygiene_ctxt
,
2217 symbol_table
: Default
::default(),
2220 // Encode the rustc version string in a predictable location.
2221 rustc_version(tcx
.sess
.cfg_version
).encode(&mut ecx
);
2223 // Encode all the entries and extra information in the crate,
2224 // culminating in the `CrateRoot` which points to all of it.
2225 let root
= ecx
.encode_crate_root();
2229 let mut file
= ecx
.opaque
.file();
2230 // We will return to this position after writing the root position.
2231 let pos_before_seek
= file
.stream_position().unwrap();
2233 // Encode the root position.
2234 let header
= METADATA_HEADER
.len();
2235 file
.seek(std
::io
::SeekFrom
::Start(header
as u64))
2236 .unwrap_or_else(|err
| tcx
.sess
.emit_fatal(FailSeekFile { err }
));
2237 let pos
= root
.position
.get();
2238 file
.write_all(&[(pos
>> 24) as u8, (pos
>> 16) as u8, (pos
>> 8) as u8, (pos
>> 0) as u8])
2239 .unwrap_or_else(|err
| tcx
.sess
.emit_fatal(FailWriteFile { err }
));
2241 // Return to the position where we are before writing the root position.
2242 file
.seek(std
::io
::SeekFrom
::Start(pos_before_seek
)).unwrap();
2244 // Record metadata size for self-profiling
2245 tcx
.prof
.artifact_size(
2248 file
.metadata().unwrap().len() as u64,
2252 pub fn provide(providers
: &mut Providers
) {
2253 *providers
= Providers
{
2254 doc_link_resolutions
: |tcx
, def_id
| {
2256 .doc_link_resolutions
2258 .expect("no resolutions for a doc link")
2260 doc_link_traits_in_scope
: |tcx
, def_id
| {
2262 .doc_link_traits_in_scope
2264 .expect("no traits in scope for a doc link")
2266 traits
: |tcx
, LocalCrate
| {
2267 let mut traits
= Vec
::new();
2268 for id
in tcx
.hir().items() {
2269 if matches
!(tcx
.def_kind(id
.owner_id
), DefKind
::Trait
| DefKind
::TraitAlias
) {
2270 traits
.push(id
.owner_id
.to_def_id())
2274 // Bring everything into deterministic order.
2275 traits
.sort_by_cached_key(|&def_id
| tcx
.def_path_hash(def_id
));
2276 tcx
.arena
.alloc_slice(&traits
)
2278 trait_impls_in_crate
: |tcx
, LocalCrate
| {
2279 let mut trait_impls
= Vec
::new();
2280 for id
in tcx
.hir().items() {
2281 if matches
!(tcx
.def_kind(id
.owner_id
), DefKind
::Impl { .. }
)
2282 && tcx
.impl_trait_ref(id
.owner_id
).is_some()
2284 trait_impls
.push(id
.owner_id
.to_def_id())
2288 // Bring everything into deterministic order.
2289 trait_impls
.sort_by_cached_key(|&def_id
| tcx
.def_path_hash(def_id
));
2290 tcx
.arena
.alloc_slice(&trait_impls
)