1 use crate::rmeta
::def_path_hash_map
::DefPathHashMapRef
;
2 use crate::rmeta
::table
::TableBuilder
;
5 use rustc_data_structures
::fingerprint
::Fingerprint
;
6 use rustc_data_structures
::fx
::{FxHashMap, FxIndexSet}
;
7 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher}
;
8 use rustc_data_structures
::sync
::{join, par_iter, Lrc, ParallelIterator}
;
10 use rustc_hir
::def
::DefKind
;
11 use rustc_hir
::def_id
::{
12 CrateNum
, DefId
, DefIndex
, LocalDefId
, CRATE_DEF_ID
, CRATE_DEF_INDEX
, LOCAL_CRATE
,
14 use rustc_hir
::definitions
::DefPathData
;
15 use rustc_hir
::intravisit
::{self, Visitor}
;
16 use rustc_hir
::lang_items
;
17 use rustc_hir
::{AnonConst, GenericParamKind}
;
18 use rustc_index
::bit_set
::GrowableBitSet
;
19 use rustc_middle
::hir
::nested_filter
;
20 use rustc_middle
::middle
::dependency_format
::Linkage
;
21 use rustc_middle
::middle
::exported_symbols
::{
22 metadata_symbol_name
, ExportedSymbol
, SymbolExportInfo
,
24 use rustc_middle
::mir
::interpret
;
25 use rustc_middle
::traits
::specialization_graph
;
26 use rustc_middle
::ty
::codec
::TyEncoder
;
27 use rustc_middle
::ty
::fast_reject
::{self, SimplifiedType, TreatParams}
;
28 use rustc_middle
::ty
::query
::Providers
;
29 use rustc_middle
::ty
::{self, SymbolName, Ty, TyCtxt}
;
30 use rustc_serialize
::opaque
::MemEncoder
;
31 use rustc_serialize
::{Encodable, Encoder}
;
32 use rustc_session
::config
::CrateType
;
33 use rustc_session
::cstore
::{ForeignModule, LinkagePreference, NativeLib}
;
34 use rustc_span
::hygiene
::{ExpnIndex, HygieneEncodeContext, MacroKind}
;
35 use rustc_span
::symbol
::{sym, Symbol}
;
37 self, DebuggerVisualizerFile
, ExternalSource
, FileName
, SourceFile
, Span
, SyntaxContext
,
39 use rustc_target
::abi
::VariantIdx
;
40 use std
::borrow
::Borrow
;
43 use std
::num
::NonZeroUsize
;
44 use tracing
::{debug, trace}
;
46 pub(super) struct EncodeContext
<'a
, 'tcx
> {
49 feat
: &'tcx rustc_feature
::Features
,
51 tables
: TableBuilders
,
53 lazy_state
: LazyState
,
54 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
55 predicate_shorthands
: FxHashMap
<ty
::PredicateKind
<'tcx
>, usize>,
57 interpret_allocs
: FxIndexSet
<interpret
::AllocId
>,
59 // This is used to speed up Span encoding.
60 // The `usize` is an index into the `MonotonicVec`
61 // that stores the `SourceFile`
62 source_file_cache
: (Lrc
<SourceFile
>, usize),
63 // The indices (into the `SourceMap`'s `MonotonicVec`)
64 // of all of the `SourceFiles` that we need to serialize.
65 // When we serialize a `Span`, we insert the index of its
66 // `SourceFile` into the `GrowableBitSet`.
68 // This needs to be a `GrowableBitSet` and not a
69 // regular `BitSet` because we may actually import new `SourceFiles`
70 // during metadata encoding, due to executing a query
71 // with a result containing a foreign `Span`.
72 required_source_files
: Option
<GrowableBitSet
<usize>>,
74 hygiene_ctxt
: &'a HygieneEncodeContext
,
77 /// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
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
::empty();
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
> {
117 emit_raw_bytes(&[u8]);
121 impl<'a
, 'tcx
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyValue
<T
> {
122 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
123 e
.emit_lazy_distance(self.position
);
127 impl<'a
, 'tcx
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyArray
<T
> {
128 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
129 e
.emit_usize(self.num_elems
);
130 if self.num_elems
> 0 {
131 e
.emit_lazy_distance(self.position
)
136 impl<'a
, 'tcx
, I
, T
> Encodable
<EncodeContext
<'a
, 'tcx
>> for LazyTable
<I
, T
> {
137 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) {
138 e
.emit_usize(self.encoded_size
);
139 e
.emit_lazy_distance(self.position
);
143 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for CrateNum
{
144 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
145 if *self != LOCAL_CRATE
&& s
.is_proc_macro
{
146 panic
!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
148 s
.emit_u32(self.as_u32());
152 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for DefIndex
{
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 ExpnIndex
{
159 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
160 s
.emit_u32(self.as_u32());
164 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for SyntaxContext
{
165 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
166 rustc_span
::hygiene
::raw_encode_syntax_context(*self, &s
.hygiene_ctxt
, s
);
170 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnId
{
171 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
172 if self.krate
== LOCAL_CRATE
{
173 // We will only write details for local expansions. Non-local expansions will fetch
174 // data from the corresponding crate's metadata.
175 // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
176 // metadata from proc-macro crates.
177 s
.hygiene_ctxt
.schedule_expn_data_for_encoding(*self);
179 self.krate
.encode(s
);
180 self.local_id
.encode(s
);
184 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for Span
{
185 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) {
186 let span
= self.data();
188 // Don't serialize any `SyntaxContext`s from a proc-macro crate,
189 // since we don't load proc-macro dependencies during serialization.
190 // This means that any hygiene information from macros used *within*
191 // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
192 // definition) will be lost.
194 // This can show up in two ways:
196 // 1. Any hygiene information associated with identifier of
197 // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
198 // Since proc-macros can only be invoked from a different crate,
199 // real code should never need to care about this.
201 // 2. Using `Span::def_site` or `Span::mixed_site` will not
202 // include any hygiene information associated with the definition
203 // site. This means that a proc-macro cannot emit a `$crate`
204 // identifier which resolves to one of its dependencies,
205 // which also should never come up in practice.
207 // Additionally, this affects `Span::parent`, and any other
208 // span inspection APIs that would otherwise allow traversing
209 // the `SyntaxContexts` associated with a span.
211 // None of these user-visible effects should result in any
212 // cross-crate inconsistencies (getting one behavior in the same
213 // crate, and a different behavior in another crate) due to the
214 // limited surface that proc-macros can expose.
216 // IMPORTANT: If this is ever changed, be sure to update
217 // `rustc_span::hygiene::raw_encode_expn_id` to handle
218 // encoding `ExpnData` for proc-macro crates.
220 SyntaxContext
::root().encode(s
);
226 return TAG_PARTIAL_SPAN
.encode(s
);
229 // The Span infrastructure should make sure that this invariant holds:
230 debug_assert
!(span
.lo
<= span
.hi
);
232 if !s
.source_file_cache
.0.contains(span
.lo
) {
233 let source_map
= s
.tcx
.sess
.source_map();
234 let source_file_index
= source_map
.lookup_source_file_idx(span
.lo
);
235 s
.source_file_cache
=
236 (source_map
.files()[source_file_index
].clone(), source_file_index
);
239 if !s
.source_file_cache
.0.contains(span
.hi
) {
240 // Unfortunately, macro expansion still sometimes generates Spans
241 // that malformed in this way.
242 return TAG_PARTIAL_SPAN
.encode(s
);
245 let source_files
= s
.required_source_files
.as_mut().expect("Already encoded SourceMap!");
246 // Record the fact that we need to encode the data for this `SourceFile`
247 source_files
.insert(s
.source_file_cache
.1);
249 // There are two possible cases here:
250 // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
251 // crate we are writing metadata for. When the metadata for *this* crate gets
252 // deserialized, the deserializer will need to know which crate it originally came
253 // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
254 // be deserialized after the rest of the span data, which tells the deserializer
255 // which crate contains the source map information.
256 // 2. This span comes from our own crate. No special handling is needed - we just
257 // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
258 // our own source map information.
260 // If we're a proc-macro crate, we always treat this as a local `Span`.
261 // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata
262 // if we're a proc-macro crate.
263 // This allows us to avoid loading the dependencies of proc-macro crates: all of
264 // the information we need to decode `Span`s is stored in the proc-macro crate.
265 let (tag
, lo
, hi
) = if s
.source_file_cache
.0.is_imported
() && !s
.is_proc_macro
{
266 // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
267 // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
268 // are relative to the source map information for the 'foreign' crate whose CrateNum
269 // we write into the metadata. This allows `imported_source_files` to binary
270 // search through the 'foreign' crate's source map information, using the
271 // deserialized 'lo' and 'hi' values directly.
273 // All of this logic ensures that the final result of deserialization is a 'normal'
274 // Span that can be used without any additional trouble.
275 let external_start_pos
= {
276 // Introduce a new scope so that we drop the 'lock()' temporary
277 match &*s
.source_file_cache
.0.external_src
.lock() {
278 ExternalSource
::Foreign { original_start_pos, .. }
=> *original_start_pos
,
279 src
=> panic
!("Unexpected external source {:?}", src
),
282 let lo
= (span
.lo
- s
.source_file_cache
.0.start_pos
) + external_start_pos
;
283 let hi
= (span
.hi
- s
.source_file_cache
.0.start_pos
) + external_start_pos
;
285 (TAG_VALID_SPAN_FOREIGN
, lo
, hi
)
287 (TAG_VALID_SPAN_LOCAL
, span
.lo
, span
.hi
)
293 // Encode length which is usually less than span.hi and profits more
294 // from the variable-length integer encoding that we use.
298 if tag
== TAG_VALID_SPAN_FOREIGN
{
299 // This needs to be two lines to avoid holding the `s.source_file_cache`
300 // while calling `cnum.encode(s)`
301 let cnum
= s
.source_file_cache
.0.cnum
;
307 impl<'a
, 'tcx
> TyEncoder
for EncodeContext
<'a
, 'tcx
> {
308 const CLEAR_CROSS_CRATE
: bool
= true;
310 type I
= TyCtxt
<'tcx
>;
312 fn position(&self) -> usize {
313 self.opaque
.position()
316 fn type_shorthands(&mut self) -> &mut FxHashMap
<Ty
<'tcx
>, usize> {
317 &mut self.type_shorthands
320 fn predicate_shorthands(&mut self) -> &mut FxHashMap
<ty
::PredicateKind
<'tcx
>, usize> {
321 &mut self.predicate_shorthands
324 fn encode_alloc_id(&mut self, alloc_id
: &rustc_middle
::mir
::interpret
::AllocId
) {
325 let (index
, _
) = self.interpret_allocs
.insert_full(*alloc_id
);
331 // Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
332 // normally need extra variables to avoid errors about multiple mutable borrows.
333 macro_rules
! record
{
334 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
337 let lazy
= $
self.lazy(value
);
338 $
self.$tables
.$table
.set($def_id
.index
, lazy
);
343 // Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
344 // normally need extra variables to avoid errors about multiple mutable borrows.
345 macro_rules
! record_array
{
346 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
349 let lazy
= $
self.lazy_array(value
);
350 $
self.$tables
.$table
.set($def_id
.index
, lazy
);
355 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
356 fn emit_lazy_distance(&mut self, position
: NonZeroUsize
) {
357 let pos
= position
.get();
358 let distance
= match self.lazy_state
{
359 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
360 LazyState
::NodeStart(start
) => {
361 let start
= start
.get();
362 assert
!(pos
<= start
);
365 LazyState
::Previous(last_pos
) => {
367 last_pos
<= position
,
368 "make sure that the calls to `lazy*` \
369 are in the same order as the metadata fields",
371 position
.get() - last_pos
.get()
374 self.lazy_state
= LazyState
::Previous(NonZeroUsize
::new(pos
).unwrap());
375 self.emit_usize(distance
);
378 fn lazy
<T
: ParameterizedOverTcx
, B
: Borrow
<T
::Value
<'tcx
>>>(&mut self, value
: B
) -> LazyValue
<T
>
380 T
::Value
<'tcx
>: Encodable
<EncodeContext
<'a
, 'tcx
>>,
382 let pos
= NonZeroUsize
::new(self.position()).unwrap();
384 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
385 self.lazy_state
= LazyState
::NodeStart(pos
);
386 value
.borrow().encode(self);
387 self.lazy_state
= LazyState
::NoNode
;
389 assert
!(pos
.get() <= self.position());
391 LazyValue
::from_position(pos
)
394 fn lazy_array
<T
: ParameterizedOverTcx
, I
: IntoIterator
<Item
= B
>, B
: Borrow
<T
::Value
<'tcx
>>>(
399 T
::Value
<'tcx
>: Encodable
<EncodeContext
<'a
, 'tcx
>>,
401 let pos
= NonZeroUsize
::new(self.position()).unwrap();
403 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
404 self.lazy_state
= LazyState
::NodeStart(pos
);
405 let len
= values
.into_iter().map(|value
| value
.borrow().encode(self)).count();
406 self.lazy_state
= LazyState
::NoNode
;
408 assert
!(pos
.get() <= self.position());
410 LazyArray
::from_position_and_num_elems(pos
, len
)
413 fn encode_info_for_items(&mut self) {
414 self.encode_info_for_mod(CRATE_DEF_ID
, self.tcx
.hir().root_module());
416 // Proc-macro crates only export proc-macro items, which are looked
417 // up using `proc_macro_data`
418 if self.is_proc_macro
{
422 self.tcx
.hir().deep_visit_all_item_likes(self);
425 fn encode_def_path_table(&mut self) {
426 let table
= self.tcx
.definitions_untracked().def_path_table();
427 if self.is_proc_macro
{
428 for def_index
in std
::iter
::once(CRATE_DEF_INDEX
)
429 .chain(self.tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
))
431 let def_key
= self.lazy(table
.def_key(def_index
));
432 let def_path_hash
= table
.def_path_hash(def_index
);
433 self.tables
.def_keys
.set(def_index
, def_key
);
434 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
);
437 for (def_index
, def_key
, def_path_hash
) in table
.enumerated_keys_and_path_hashes() {
438 let def_key
= self.lazy(def_key
);
439 self.tables
.def_keys
.set(def_index
, def_key
);
440 self.tables
.def_path_hashes
.set(def_index
, *def_path_hash
);
445 fn encode_def_path_hash_map(&mut self) -> LazyValue
<DefPathHashMapRef
<'
static>> {
446 self.lazy(DefPathHashMapRef
::BorrowedFromTcx(
447 self.tcx
.definitions_untracked().def_path_hash_to_def_index_map(),
451 fn encode_source_map(&mut self) -> LazyArray
<rustc_span
::SourceFile
> {
452 let source_map
= self.tcx
.sess
.source_map();
453 let all_source_files
= source_map
.files();
455 // By replacing the `Option` with `None`, we ensure that we can't
456 // accidentally serialize any more `Span`s after the source map encoding
458 let required_source_files
= self.required_source_files
.take().unwrap();
460 let working_directory
= &self.tcx
.sess
.opts
.working_dir
;
462 let adapted
= all_source_files
465 .filter(|(idx
, source_file
)| {
466 // Only serialize `SourceFile`s that were used
467 // during the encoding of a `Span`
468 required_source_files
.contains(*idx
) &&
469 // Don't serialize imported `SourceFile`s, unless
470 // we're in a proc-macro crate.
471 (!source_file
.is_imported() || self.is_proc_macro
)
473 .map(|(_
, source_file
)| {
474 // At export time we expand all source file paths to absolute paths because
475 // downstream compilation sessions can have a different compiler working
476 // directory, so relative paths from this or any other upstream crate
477 // won't be valid anymore.
479 // At this point we also erase the actual on-disk path and only keep
480 // the remapped version -- as is necessary for reproducible builds.
481 match source_file
.name
{
482 FileName
::Real(ref original_file_name
) => {
483 let adapted_file_name
=
484 source_map
.path_mapping().to_embeddable_absolute_path(
485 original_file_name
.clone(),
489 if adapted_file_name
!= *original_file_name
{
490 let mut adapted
: SourceFile
= (**source_file
).clone();
491 adapted
.name
= FileName
::Real(adapted_file_name
);
492 adapted
.name_hash
= {
493 let mut hasher
: StableHasher
= StableHasher
::new();
494 adapted
.name
.hash(&mut hasher
);
495 hasher
.finish
::<u128
>()
503 // expanded code, not from a file
504 _
=> source_file
.clone(),
507 .map(|mut source_file
| {
508 // We're serializing this `SourceFile` into our crate metadata,
509 // so mark it as coming from this crate.
510 // This also ensures that we don't try to deserialize the
511 // `CrateNum` for a proc-macro dependency - since proc macro
512 // dependencies aren't loaded when we deserialize a proc-macro,
513 // trying to remap the `CrateNum` would fail.
514 if self.is_proc_macro
{
515 Lrc
::make_mut(&mut source_file
).cnum
= LOCAL_CRATE
;
519 .collect
::<Vec
<_
>>();
521 self.lazy_array(adapted
.iter().map(|rc
| &**rc
))
524 fn encode_crate_root(&mut self) -> LazyValue
<CrateRoot
> {
527 let preamble_bytes
= self.position() - i
;
529 // Encode the crate deps
531 let crate_deps
= self.encode_crate_deps();
532 let dylib_dependency_formats
= self.encode_dylib_dependency_formats();
533 let dep_bytes
= self.position() - i
;
535 // Encode the lib features.
537 let lib_features
= self.encode_lib_features();
538 let lib_feature_bytes
= self.position() - i
;
540 // Encode the language items.
542 let lang_items
= self.encode_lang_items();
543 let lang_items_missing
= self.encode_lang_items_missing();
544 let lang_item_bytes
= self.position() - i
;
546 // Encode the diagnostic items.
548 let diagnostic_items
= self.encode_diagnostic_items();
549 let diagnostic_item_bytes
= self.position() - i
;
551 // Encode the native libraries used
553 let native_libraries
= self.encode_native_libraries();
554 let native_lib_bytes
= self.position() - i
;
557 let foreign_modules
= self.encode_foreign_modules();
558 let foreign_modules_bytes
= self.position() - i
;
560 // Encode DefPathTable
562 self.encode_def_path_table();
563 let def_path_table_bytes
= self.position() - i
;
565 // Encode the def IDs of traits, for rustdoc and diagnostics.
567 let traits
= self.encode_traits();
568 let traits_bytes
= self.position() - i
;
570 // Encode the def IDs of impls, for coherence checking.
572 let impls
= self.encode_impls();
573 let impls_bytes
= self.position() - i
;
576 let incoherent_impls
= self.encode_incoherent_impls();
577 let incoherent_impls_bytes
= self.position() - i
;
582 let mir_bytes
= self.position() - i
;
586 self.encode_def_ids();
587 self.encode_info_for_items();
588 let item_bytes
= self.position() - i
;
590 // Encode the allocation index
592 let interpret_alloc_index
= {
593 let mut interpret_alloc_index
= Vec
::new();
595 trace
!("beginning to encode alloc ids");
597 let new_n
= self.interpret_allocs
.len();
598 // if we have found new ids, serialize those, too
603 trace
!("encoding {} further alloc ids", new_n
- n
);
604 for idx
in n
..new_n
{
605 let id
= self.interpret_allocs
[idx
];
606 let pos
= self.position() as u32;
607 interpret_alloc_index
.push(pos
);
608 interpret
::specialized_encode_alloc_id(self, tcx
, id
);
612 self.lazy_array(interpret_alloc_index
)
614 let interpret_alloc_index_bytes
= self.position() - i
;
616 // Encode the proc macro data. This affects 'tables',
617 // so we need to do this before we encode the tables
619 let proc_macro_data
= self.encode_proc_macros();
620 let proc_macro_data_bytes
= self.position() - i
;
623 let tables
= self.tables
.encode(&mut self.opaque
);
624 let tables_bytes
= self.position() - i
;
627 let debugger_visualizers
= self.encode_debugger_visualizers();
628 let debugger_visualizers_bytes
= self.position() - i
;
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.
633 let exported_symbols
= tcx
.exported_symbols(LOCAL_CRATE
);
634 let exported_symbols
= self.encode_exported_symbols(&exported_symbols
);
635 let exported_symbols_bytes
= self.position() - i
;
637 // Encode the hygiene data,
638 // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
639 // of encoding other items (e.g. `optimized_mir`) may cause us to load
640 // data from the incremental cache. If this causes us to deserialize a `Span`,
641 // then we may load additional `SyntaxContext`s into the global `HygieneData`.
642 // Therefore, we need to encode the hygiene data last to ensure that we encode
643 // any `SyntaxContext`s that might be used.
645 let (syntax_contexts
, expn_data
, expn_hashes
) = self.encode_hygiene();
646 let hygiene_bytes
= self.position() - i
;
649 let def_path_hash_map
= self.encode_def_path_hash_map();
650 let def_path_hash_map_bytes
= self.position() - i
;
652 // Encode source_map. This needs to be done last,
653 // since encoding `Span`s tells us which `SourceFiles` we actually
656 let source_map
= self.encode_source_map();
657 let source_map_bytes
= self.position() - i
;
660 let attrs
= tcx
.hir().krate_attrs();
661 let has_default_lib_allocator
= tcx
.sess
.contains_name(&attrs
, sym
::default_lib_allocator
);
662 let root
= self.lazy(CrateRoot
{
663 name
: tcx
.crate_name(LOCAL_CRATE
),
664 extra_filename
: tcx
.sess
.opts
.cg
.extra_filename
.clone(),
665 triple
: tcx
.sess
.opts
.target_triple
.clone(),
666 hash
: tcx
.crate_hash(LOCAL_CRATE
),
667 stable_crate_id
: tcx
.def_path_hash(LOCAL_CRATE
.as_def_id()).stable_crate_id(),
668 panic_strategy
: tcx
.sess
.panic_strategy(),
669 panic_in_drop_strategy
: tcx
.sess
.opts
.debugging_opts
.panic_in_drop
,
670 edition
: tcx
.sess
.edition(),
671 has_global_allocator
: tcx
.has_global_allocator(LOCAL_CRATE
),
672 has_panic_handler
: tcx
.has_panic_handler(LOCAL_CRATE
),
673 has_default_lib_allocator
,
675 debugger_visualizers
,
676 compiler_builtins
: tcx
.sess
.contains_name(&attrs
, sym
::compiler_builtins
),
677 needs_allocator
: tcx
.sess
.contains_name(&attrs
, sym
::needs_allocator
),
678 needs_panic_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::needs_panic_runtime
),
679 no_builtins
: tcx
.sess
.contains_name(&attrs
, sym
::no_builtins
),
680 panic_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::panic_runtime
),
681 profiler_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::profiler_runtime
),
682 symbol_mangling_version
: tcx
.sess
.opts
.get_symbol_mangling_version(),
685 dylib_dependency_formats
,
697 interpret_alloc_index
,
704 let final_bytes
= self.position() - i
;
706 let total_bytes
= self.position();
708 let computed_total_bytes
= preamble_bytes
712 + diagnostic_item_bytes
714 + foreign_modules_bytes
715 + def_path_table_bytes
718 + incoherent_impls_bytes
721 + interpret_alloc_index_bytes
722 + proc_macro_data_bytes
724 + debugger_visualizers_bytes
725 + exported_symbols_bytes
727 + def_path_hash_map_bytes
730 assert_eq
!(total_bytes
, computed_total_bytes
);
732 if tcx
.sess
.meta_stats() {
733 let mut zero_bytes
= 0;
734 for e
in self.opaque
.data
.iter() {
740 let perc
= |bytes
| (bytes
* 100) as f64 / total_bytes
as f64;
741 let p
= |label
, bytes
| {
742 eprintln
!("{:>21}: {:>8} bytes ({:4.1}%)", label
, bytes
, perc(bytes
));
747 "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
752 p("preamble", preamble_bytes
);
754 p("lib feature", lib_feature_bytes
);
755 p("lang item", lang_item_bytes
);
756 p("diagnostic item", diagnostic_item_bytes
);
757 p("native lib", native_lib_bytes
);
758 p("foreign modules", foreign_modules_bytes
);
759 p("def-path table", def_path_table_bytes
);
760 p("traits", traits_bytes
);
761 p("impls", impls_bytes
);
762 p("incoherent_impls", incoherent_impls_bytes
);
764 p("item", item_bytes
);
765 p("interpret_alloc_index", interpret_alloc_index_bytes
);
766 p("proc-macro-data", proc_macro_data_bytes
);
767 p("tables", tables_bytes
);
768 p("debugger visualizers", debugger_visualizers_bytes
);
769 p("exported symbols", exported_symbols_bytes
);
770 p("hygiene", hygiene_bytes
);
771 p("def-path hashes", def_path_hash_map_bytes
);
772 p("source_map", source_map_bytes
);
773 p("final", final_bytes
);
781 fn should_encode_visibility(def_kind
: DefKind
) -> bool
{
791 | DefKind
::TraitAlias
795 | DefKind
::Static(..)
798 | DefKind
::AssocConst
801 | DefKind
::ForeignMod
804 | DefKind
::Field
=> true,
806 | DefKind
::ConstParam
807 | DefKind
::LifetimeParam
809 | DefKind
::InlineConst
813 | DefKind
::ExternCrate
=> false,
817 fn should_encode_stability(def_kind
: DefKind
) -> bool
{
826 | DefKind
::AssocConst
828 | DefKind
::ConstParam
829 | DefKind
::Static(..)
832 | DefKind
::ForeignMod
839 | DefKind
::TraitAlias
841 | DefKind
::ForeignTy
=> true,
843 | DefKind
::LifetimeParam
845 | DefKind
::InlineConst
849 | DefKind
::ExternCrate
=> false,
853 /// Whether we should encode MIR.
855 /// Computing, optimizing and encoding the MIR is a relatively expensive operation.
856 /// We want to avoid this work when not required. Therefore:
857 /// - we only compute `mir_for_ctfe` on items with const-eval semantics;
858 /// - we skip `optimized_mir` for check runs.
860 /// Return a pair, resp. for CTFE and for LLVM.
861 fn should_encode_mir(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
) -> (bool
, bool
) {
862 match tcx
.def_kind(def_id
) {
864 DefKind
::Ctor(_
, _
) => {
865 let mir_opt_base
= tcx
.sess
.opts
.output_types
.should_codegen()
866 || tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
871 | DefKind
::InlineConst
872 | DefKind
::AssocConst
873 | DefKind
::Static(..)
874 | DefKind
::Const
=> (true, false),
875 // Full-fledged functions
876 DefKind
::AssocFn
| DefKind
::Fn
=> {
877 let generics
= tcx
.generics_of(def_id
);
878 let needs_inline
= (generics
.requires_monomorphization(tcx
)
879 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
880 && tcx
.sess
.opts
.output_types
.should_codegen();
881 // The function has a `const` modifier or is in a `#[const_trait]`.
882 let is_const_fn
= tcx
.is_const_fn_raw(def_id
.to_def_id())
883 || tcx
.is_const_default_method(def_id
.to_def_id());
884 let always_encode_mir
= tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
885 (is_const_fn
, needs_inline
|| always_encode_mir
)
887 // Closures can't be const fn.
888 DefKind
::Closure
=> {
889 let generics
= tcx
.generics_of(def_id
);
890 let needs_inline
= (generics
.requires_monomorphization(tcx
)
891 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
892 && tcx
.sess
.opts
.output_types
.should_codegen();
893 let always_encode_mir
= tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
894 (false, needs_inline
|| always_encode_mir
)
896 // Generators require optimized MIR to compute layout.
897 DefKind
::Generator
=> (false, true),
898 // The others don't have MIR.
903 fn should_encode_variances(def_kind
: DefKind
) -> bool
{
911 | DefKind
::AssocFn
=> true,
915 | DefKind
::AssocConst
917 | DefKind
::ConstParam
918 | DefKind
::Static(..)
920 | DefKind
::ForeignMod
925 | DefKind
::TraitAlias
929 | DefKind
::LifetimeParam
931 | DefKind
::InlineConst
935 | DefKind
::ExternCrate
=> false,
939 fn should_encode_generics(def_kind
: DefKind
) -> bool
{
948 | DefKind
::TraitAlias
952 | DefKind
::Static(..)
955 | DefKind
::AssocConst
957 | DefKind
::InlineConst
963 | DefKind
::Generator
=> true,
965 | DefKind
::ForeignMod
966 | DefKind
::ConstParam
969 | DefKind
::LifetimeParam
971 | DefKind
::ExternCrate
=> false,
975 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
976 fn encode_attrs(&mut self, def_id
: LocalDefId
) {
980 .attrs(self.tcx
.hir().local_def_id_to_hir_id(def_id
))
982 .filter(|attr
| !rustc_feature
::is_builtin_only_local(attr
.name_or_empty()));
984 record_array
!(self.tables
.attributes
[def_id
.to_def_id()] <- attrs
.clone());
985 if attrs
.any(|attr
| attr
.may_have_doc_links()) {
986 self.tables
.may_have_doc_links
.set(def_id
.local_def_index
, ());
990 fn encode_def_ids(&mut self) {
991 if self.is_proc_macro
{
996 for local_id
in hir
.iter_local_def_id() {
997 let def_id
= local_id
.to_def_id();
998 let def_kind
= tcx
.opt_def_kind(local_id
);
999 let Some(def_kind
) = def_kind
else { continue }
;
1000 self.tables
.opt_def_kind
.set(def_id
.index
, def_kind
);
1001 record
!(self.tables
.def_span
[def_id
] <- tcx
.def_span(def_id
));
1002 self.encode_attrs(local_id
);
1003 record
!(self.tables
.expn_that_defined
[def_id
] <- self.tcx
.expn_that_defined(def_id
));
1004 if let Some(ident_span
) = tcx
.def_ident_span(def_id
) {
1005 record
!(self.tables
.def_ident_span
[def_id
] <- ident_span
);
1007 if def_kind
.has_codegen_attrs() {
1008 record
!(self.tables
.codegen_fn_attrs
[def_id
] <- self.tcx
.codegen_fn_attrs(def_id
));
1010 if should_encode_visibility(def_kind
) {
1011 record
!(self.tables
.visibility
[def_id
] <- self.tcx
.visibility(def_id
));
1013 if should_encode_stability(def_kind
) {
1014 self.encode_stability(def_id
);
1015 self.encode_const_stability(def_id
);
1016 self.encode_deprecation(def_id
);
1018 if should_encode_variances(def_kind
) {
1019 let v
= self.tcx
.variances_of(def_id
);
1020 record_array
!(self.tables
.variances_of
[def_id
] <- v
);
1022 if should_encode_generics(def_kind
) {
1023 let g
= tcx
.generics_of(def_id
);
1024 record
!(self.tables
.generics_of
[def_id
] <- g
);
1025 record
!(self.tables
.explicit_predicates_of
[def_id
] <- self.tcx
.explicit_predicates_of(def_id
));
1026 let inferred_outlives
= self.tcx
.inferred_outlives_of(def_id
);
1027 if !inferred_outlives
.is_empty() {
1028 record_array
!(self.tables
.inferred_outlives_of
[def_id
] <- inferred_outlives
);
1031 if let DefKind
::Trait
| DefKind
::TraitAlias
= def_kind
{
1032 record
!(self.tables
.super_predicates_of
[def_id
] <- self.tcx
.super_predicates_of(def_id
));
1035 let inherent_impls
= tcx
.crate_inherent_impls(());
1036 for (def_id
, implementations
) in inherent_impls
.inherent_impls
.iter() {
1037 if implementations
.is_empty() {
1040 record_array
!(self.tables
.inherent_impls
[def_id
.to_def_id()] <- implementations
.iter().map(|&def_id
| {
1041 assert
!(def_id
.is_local());
1047 fn encode_item_type(&mut self, def_id
: DefId
) {
1048 debug
!("EncodeContext::encode_item_type({:?})", def_id
);
1049 record
!(self.tables
.type_of
[def_id
] <- self.tcx
.type_of(def_id
));
1052 fn encode_enum_variant_info(&mut self, def
: ty
::AdtDef
<'tcx
>, index
: VariantIdx
) {
1054 let variant
= &def
.variant(index
);
1055 let def_id
= variant
.def_id
;
1056 debug
!("EncodeContext::encode_enum_variant_info({:?})", def_id
);
1058 let data
= VariantData
{
1059 ctor_kind
: variant
.ctor_kind
,
1060 discr
: variant
.discr
,
1061 ctor
: variant
.ctor_def_id
.map(|did
| did
.index
),
1062 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1065 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Variant(self.lazy(data
)));
1066 self.tables
.constness
.set(def_id
.index
, hir
::Constness
::Const
);
1067 record_array
!(self.tables
.children
[def_id
] <- variant
.fields
.iter().map(|f
| {
1068 assert
!(f
.did
.is_local());
1071 self.encode_item_type(def_id
);
1072 if variant
.ctor_kind
== CtorKind
::Fn
{
1073 // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
1074 if let Some(ctor_def_id
) = variant
.ctor_def_id
{
1075 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(ctor_def_id
));
1080 fn encode_enum_variant_ctor(&mut self, def
: ty
::AdtDef
<'tcx
>, index
: VariantIdx
) {
1082 let variant
= &def
.variant(index
);
1083 let def_id
= variant
.ctor_def_id
.unwrap();
1084 debug
!("EncodeContext::encode_enum_variant_ctor({:?})", def_id
);
1086 // FIXME(eddyb) encode only the `CtorKind` for constructors.
1087 let data
= VariantData
{
1088 ctor_kind
: variant
.ctor_kind
,
1089 discr
: variant
.discr
,
1090 ctor
: Some(def_id
.index
),
1091 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1094 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Variant(self.lazy(data
)));
1095 self.tables
.constness
.set(def_id
.index
, hir
::Constness
::Const
);
1096 self.encode_item_type(def_id
);
1097 if variant
.ctor_kind
== CtorKind
::Fn
{
1098 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1102 fn encode_info_for_mod(&mut self, local_def_id
: LocalDefId
, md
: &hir
::Mod
<'_
>) {
1104 let def_id
= local_def_id
.to_def_id();
1105 debug
!("EncodeContext::encode_info_for_mod({:?})", def_id
);
1107 // If we are encoding a proc-macro crates, `encode_info_for_mod` will
1108 // only ever get called for the crate root. We still want to encode
1109 // the crate root for consistency with other crates (some of the resolver
1110 // code uses it). However, we skip encoding anything relating to child
1111 // items - we encode information about proc-macros later on.
1112 let reexports
= if !self.is_proc_macro
{
1113 match tcx
.module_reexports(local_def_id
) {
1114 Some(exports
) => self.lazy_array(exports
),
1115 _
=> LazyArray
::empty(),
1121 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Mod(reexports
));
1122 if self.is_proc_macro
{
1123 // Encode this here because we don't do it in encode_def_ids.
1124 record
!(self.tables
.expn_that_defined
[def_id
] <- tcx
.expn_that_defined(local_def_id
));
1126 record_array
!(self.tables
.children
[def_id
] <- iter
::from_generator(|| {
1127 for item_id
in md
.item_ids
{
1128 match tcx
.hir().item(*item_id
).kind
{
1129 // Foreign items are planted into their parent modules
1130 // from name resolution point of view.
1131 hir
::ItemKind
::ForeignMod { items, .. }
=> {
1132 for foreign_item
in items
{
1133 yield foreign_item
.id
.def_id
.local_def_index
;
1136 // Only encode named non-reexport children, reexports are encoded
1137 // separately and unnamed items are not used by name resolution.
1138 hir
::ItemKind
::ExternCrate(..) => continue,
1139 _
if tcx
.def_key(item_id
.def_id
.to_def_id()).get_opt_name().is_some() => {
1140 yield item_id
.def_id
.local_def_index
;
1151 adt_def
: ty
::AdtDef
<'tcx
>,
1152 variant_index
: VariantIdx
,
1155 let variant
= &adt_def
.variant(variant_index
);
1156 let field
= &variant
.fields
[field_index
];
1158 let def_id
= field
.did
;
1159 debug
!("EncodeContext::encode_field({:?})", def_id
);
1161 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Field
);
1162 self.encode_item_type(def_id
);
1165 fn encode_struct_ctor(&mut self, adt_def
: ty
::AdtDef
<'tcx
>, def_id
: DefId
) {
1166 debug
!("EncodeContext::encode_struct_ctor({:?})", def_id
);
1168 let variant
= adt_def
.non_enum_variant();
1170 let data
= VariantData
{
1171 ctor_kind
: variant
.ctor_kind
,
1172 discr
: variant
.discr
,
1173 ctor
: Some(def_id
.index
),
1174 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1177 record
!(self.tables
.repr_options
[def_id
] <- adt_def
.repr());
1178 self.tables
.constness
.set(def_id
.index
, hir
::Constness
::Const
);
1179 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Struct(self.lazy(data
)));
1180 self.encode_item_type(def_id
);
1181 if variant
.ctor_kind
== CtorKind
::Fn
{
1182 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1186 fn encode_explicit_item_bounds(&mut self, def_id
: DefId
) {
1187 debug
!("EncodeContext::encode_explicit_item_bounds({:?})", def_id
);
1188 let bounds
= self.tcx
.explicit_item_bounds(def_id
);
1189 if !bounds
.is_empty() {
1190 record_array
!(self.tables
.explicit_item_bounds
[def_id
] <- bounds
);
1194 fn encode_info_for_trait_item(&mut self, def_id
: DefId
) {
1195 debug
!("EncodeContext::encode_info_for_trait_item({:?})", def_id
);
1198 let ast_item
= tcx
.hir().expect_trait_item(def_id
.expect_local());
1199 let trait_item
= tcx
.associated_item(def_id
);
1201 let container
= match trait_item
.defaultness
{
1202 hir
::Defaultness
::Default { has_value: true }
=> AssocContainer
::TraitWithDefault
,
1203 hir
::Defaultness
::Default { has_value: false }
=> AssocContainer
::TraitRequired
,
1204 hir
::Defaultness
::Final
=> span_bug
!(ast_item
.span
, "traits cannot have final items"),
1207 match trait_item
.kind
{
1208 ty
::AssocKind
::Const
=> {
1209 let rendered
= rustc_hir_pretty
::to_string(
1210 &(&self.tcx
.hir() as &dyn intravisit
::Map
<'_
>),
1211 |s
| s
.print_trait_item(ast_item
),
1214 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocConst(container
));
1215 record
!(self.tables
.mir_const_qualif
[def_id
] <- mir
::ConstQualifs
::default());
1216 record
!(self.tables
.rendered_const
[def_id
] <- rendered
);
1218 ty
::AssocKind
::Fn
=> {
1219 let hir
::TraitItemKind
::Fn(m_sig
, m
) = &ast_item
.kind
else { bug!() }
;
1221 hir
::TraitFn
::Required(ref names
) => {
1222 record_array
!(self.tables
.fn_arg_names
[def_id
] <- *names
)
1224 hir
::TraitFn
::Provided(body
) => {
1225 record_array
!(self.tables
.fn_arg_names
[def_id
] <- self.tcx
.hir().body_param_names(body
))
1228 self.tables
.asyncness
.set(def_id
.index
, m_sig
.header
.asyncness
);
1229 self.tables
.constness
.set(def_id
.index
, hir
::Constness
::NotConst
);
1230 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocFn(self.lazy(AssocFnData
{
1232 has_self
: trait_item
.fn_has_self_parameter
,
1235 ty
::AssocKind
::Type
=> {
1236 self.encode_explicit_item_bounds(def_id
);
1237 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocType(container
));
1240 match trait_item
.kind
{
1241 ty
::AssocKind
::Const
| ty
::AssocKind
::Fn
=> {
1242 self.encode_item_type(def_id
);
1244 ty
::AssocKind
::Type
=> {
1245 if trait_item
.defaultness
.has_value() {
1246 self.encode_item_type(def_id
);
1250 if trait_item
.kind
== ty
::AssocKind
::Fn
{
1251 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1255 fn encode_info_for_impl_item(&mut self, def_id
: DefId
) {
1256 debug
!("EncodeContext::encode_info_for_impl_item({:?})", def_id
);
1259 let ast_item
= self.tcx
.hir().expect_impl_item(def_id
.expect_local());
1260 let impl_item
= self.tcx
.associated_item(def_id
);
1262 let container
= match impl_item
.defaultness
{
1263 hir
::Defaultness
::Default { has_value: true }
=> AssocContainer
::ImplDefault
,
1264 hir
::Defaultness
::Final
=> AssocContainer
::ImplFinal
,
1265 hir
::Defaultness
::Default { has_value: false }
=> {
1266 span_bug
!(ast_item
.span
, "impl items always have values (currently)")
1270 match impl_item
.kind
{
1271 ty
::AssocKind
::Const
=> {
1272 if let hir
::ImplItemKind
::Const(_
, body_id
) = ast_item
.kind
{
1273 let qualifs
= self.tcx
.at(ast_item
.span
).mir_const_qualif(def_id
);
1274 let const_data
= self.encode_rendered_const_for_body(body_id
);
1276 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocConst(container
));
1277 record
!(self.tables
.mir_const_qualif
[def_id
] <- qualifs
);
1278 record
!(self.tables
.rendered_const
[def_id
] <- const_data
);
1283 ty
::AssocKind
::Fn
=> {
1284 let hir
::ImplItemKind
::Fn(ref sig
, body
) = ast_item
.kind
else { bug!() }
;
1285 self.tables
.asyncness
.set(def_id
.index
, sig
.header
.asyncness
);
1286 record_array
!(self.tables
.fn_arg_names
[def_id
] <- self.tcx
.hir().body_param_names(body
));
1287 // Can be inside `impl const Trait`, so using sig.header.constness is not reliable
1288 let constness
= if self.tcx
.is_const_fn_raw(def_id
) {
1289 hir
::Constness
::Const
1291 hir
::Constness
::NotConst
1293 self.tables
.constness
.set(def_id
.index
, constness
);
1294 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocFn(self.lazy(AssocFnData
{
1296 has_self
: impl_item
.fn_has_self_parameter
,
1299 ty
::AssocKind
::Type
=> {
1300 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocType(container
));
1303 self.encode_item_type(def_id
);
1304 if let Some(trait_item_def_id
) = impl_item
.trait_item_def_id
{
1305 self.tables
.trait_item_def_id
.set(def_id
.index
, trait_item_def_id
.into());
1307 if impl_item
.kind
== ty
::AssocKind
::Fn
{
1308 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1309 if tcx
.is_intrinsic(def_id
) {
1310 self.tables
.is_intrinsic
.set(def_id
.index
, ());
1315 fn encode_mir(&mut self) {
1316 if self.is_proc_macro
{
1320 let keys_and_jobs
= self
1324 .filter_map(|&def_id
| {
1325 let (encode_const
, encode_opt
) = should_encode_mir(self.tcx
, def_id
);
1326 if encode_const
|| encode_opt
{
1327 Some((def_id
, encode_const
, encode_opt
))
1332 .collect
::<Vec
<_
>>();
1333 for (def_id
, encode_const
, encode_opt
) in keys_and_jobs
.into_iter() {
1334 debug_assert
!(encode_const
|| encode_opt
);
1336 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
1338 record
!(self.tables
.optimized_mir
[def_id
.to_def_id()] <- self.tcx
.optimized_mir(def_id
));
1341 record
!(self.tables
.mir_for_ctfe
[def_id
.to_def_id()] <- self.tcx
.mir_for_ctfe(def_id
));
1343 // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
1344 let abstract_const
= self.tcx
.thir_abstract_const(def_id
);
1345 if let Ok(Some(abstract_const
)) = abstract_const
{
1346 record
!(self.tables
.thir_abstract_const
[def_id
.to_def_id()] <- abstract_const
);
1349 record
!(self.tables
.promoted_mir
[def_id
.to_def_id()] <- self.tcx
.promoted_mir(def_id
));
1352 ty
::InstanceDef
::Item(ty
::WithOptConstParam
::unknown(def_id
.to_def_id()));
1353 let unused
= self.tcx
.unused_generic_params(instance
);
1354 if !unused
.is_empty() {
1355 record
!(self.tables
.unused_generic_params
[def_id
.to_def_id()] <- unused
);
1360 fn encode_stability(&mut self, def_id
: DefId
) {
1361 debug
!("EncodeContext::encode_stability({:?})", def_id
);
1363 // The query lookup can take a measurable amount of time in crates with many items. Check if
1364 // the stability attributes are even enabled before using their queries.
1365 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.debugging_opts
.force_unstable_if_unmarked
{
1366 if let Some(stab
) = self.tcx
.lookup_stability(def_id
) {
1367 record
!(self.tables
.lookup_stability
[def_id
] <- stab
)
1372 fn encode_const_stability(&mut self, def_id
: DefId
) {
1373 debug
!("EncodeContext::encode_const_stability({:?})", def_id
);
1375 // The query lookup can take a measurable amount of time in crates with many items. Check if
1376 // the stability attributes are even enabled before using their queries.
1377 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.debugging_opts
.force_unstable_if_unmarked
{
1378 if let Some(stab
) = self.tcx
.lookup_const_stability(def_id
) {
1379 record
!(self.tables
.lookup_const_stability
[def_id
] <- stab
)
1384 fn encode_deprecation(&mut self, def_id
: DefId
) {
1385 debug
!("EncodeContext::encode_deprecation({:?})", def_id
);
1386 if let Some(depr
) = self.tcx
.lookup_deprecation(def_id
) {
1387 record
!(self.tables
.lookup_deprecation_entry
[def_id
] <- depr
);
1391 fn encode_rendered_const_for_body(&mut self, body_id
: hir
::BodyId
) -> String
{
1392 let hir
= self.tcx
.hir();
1393 let body
= hir
.body(body_id
);
1394 rustc_hir_pretty
::to_string(&(&hir
as &dyn intravisit
::Map
<'_
>), |s
| {
1395 s
.print_expr(&body
.value
)
1399 fn encode_info_for_item(&mut self, def_id
: DefId
, item
: &'tcx hir
::Item
<'tcx
>) {
1402 debug
!("EncodeContext::encode_info_for_item({:?})", def_id
);
1404 let entry_kind
= match item
.kind
{
1405 hir
::ItemKind
::Static(..) => EntryKind
::Static
,
1406 hir
::ItemKind
::Const(_
, body_id
) => {
1407 let qualifs
= self.tcx
.at(item
.span
).mir_const_qualif(def_id
);
1408 let const_data
= self.encode_rendered_const_for_body(body_id
);
1409 record
!(self.tables
.mir_const_qualif
[def_id
] <- qualifs
);
1410 record
!(self.tables
.rendered_const
[def_id
] <- const_data
);
1413 hir
::ItemKind
::Fn(ref sig
, .., body
) => {
1414 self.tables
.asyncness
.set(def_id
.index
, sig
.header
.asyncness
);
1415 record_array
!(self.tables
.fn_arg_names
[def_id
] <- self.tcx
.hir().body_param_names(body
));
1416 self.tables
.constness
.set(def_id
.index
, sig
.header
.constness
);
1419 hir
::ItemKind
::Macro(ref macro_def
, _
) => {
1420 EntryKind
::MacroDef(self.lazy(&*macro_def
.body
), macro_def
.macro_rules
)
1422 hir
::ItemKind
::Mod(ref m
) => {
1423 return self.encode_info_for_mod(item
.def_id
, m
);
1425 hir
::ItemKind
::ForeignMod { .. }
=> EntryKind
::ForeignMod
,
1426 hir
::ItemKind
::GlobalAsm(..) => EntryKind
::GlobalAsm
,
1427 hir
::ItemKind
::TyAlias(..) => EntryKind
::Type
,
1428 hir
::ItemKind
::OpaqueTy(..) => {
1429 self.encode_explicit_item_bounds(def_id
);
1432 hir
::ItemKind
::Enum(..) => {
1433 let adt_def
= self.tcx
.adt_def(def_id
);
1434 record
!(self.tables
.repr_options
[def_id
] <- adt_def
.repr());
1437 hir
::ItemKind
::Struct(ref struct_def
, _
) => {
1438 let adt_def
= self.tcx
.adt_def(def_id
);
1439 record
!(self.tables
.repr_options
[def_id
] <- adt_def
.repr());
1440 self.tables
.constness
.set(def_id
.index
, hir
::Constness
::Const
);
1442 // Encode def_ids for each field and method
1443 // for methods, write all the stuff get_trait_method
1445 let ctor
= struct_def
1447 .map(|ctor_hir_id
| self.tcx
.hir().local_def_id(ctor_hir_id
).local_def_index
);
1449 let variant
= adt_def
.non_enum_variant();
1450 EntryKind
::Struct(self.lazy(VariantData
{
1451 ctor_kind
: variant
.ctor_kind
,
1452 discr
: variant
.discr
,
1454 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1457 hir
::ItemKind
::Union(..) => {
1458 let adt_def
= self.tcx
.adt_def(def_id
);
1459 record
!(self.tables
.repr_options
[def_id
] <- adt_def
.repr());
1461 let variant
= adt_def
.non_enum_variant();
1462 EntryKind
::Union(self.lazy(VariantData
{
1463 ctor_kind
: variant
.ctor_kind
,
1464 discr
: variant
.discr
,
1466 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1469 hir
::ItemKind
::Impl(hir
::Impl { defaultness, constness, .. }
) => {
1470 self.tables
.impl_defaultness
.set(def_id
.index
, *defaultness
);
1471 self.tables
.constness
.set(def_id
.index
, *constness
);
1473 let trait_ref
= self.tcx
.impl_trait_ref(def_id
);
1474 if let Some(trait_ref
) = trait_ref
{
1475 let trait_def
= self.tcx
.trait_def(trait_ref
.def_id
);
1476 if let Some(mut an
) = trait_def
.ancestors(self.tcx
, def_id
).ok() {
1477 if let Some(specialization_graph
::Node
::Impl(parent
)) = an
.nth(1) {
1478 self.tables
.impl_parent
.set(def_id
.index
, parent
.into());
1482 // if this is an impl of `CoerceUnsized`, create its
1483 // "unsized info", else just store None
1484 if Some(trait_ref
.def_id
) == self.tcx
.lang_items().coerce_unsized_trait() {
1485 let coerce_unsized_info
=
1486 self.tcx
.at(item
.span
).coerce_unsized_info(def_id
);
1487 record
!(self.tables
.coerce_unsized_info
[def_id
] <- coerce_unsized_info
);
1491 let polarity
= self.tcx
.impl_polarity(def_id
);
1492 self.tables
.impl_polarity
.set(def_id
.index
, polarity
);
1496 hir
::ItemKind
::Trait(..) => {
1497 let trait_def
= self.tcx
.trait_def(def_id
);
1498 record
!(self.tables
.trait_def
[def_id
] <- trait_def
);
1502 hir
::ItemKind
::TraitAlias(..) => {
1503 let trait_def
= self.tcx
.trait_def(def_id
);
1504 record
!(self.tables
.trait_def
[def_id
] <- trait_def
);
1506 EntryKind
::TraitAlias
1508 hir
::ItemKind
::ExternCrate(_
) | hir
::ItemKind
::Use(..) => {
1509 bug
!("cannot encode info for item {:?}", item
)
1512 record
!(self.tables
.kind
[def_id
] <- entry_kind
);
1513 // FIXME(eddyb) there should be a nicer way to do this.
1515 hir
::ItemKind
::Enum(..) => record_array
!(self.tables
.children
[def_id
] <-
1516 self.tcx
.adt_def(def_id
).variants().iter().map(|v
| {
1517 assert
!(v
.def_id
.is_local());
1521 hir
::ItemKind
::Struct(..) | hir
::ItemKind
::Union(..) => {
1522 record_array
!(self.tables
.children
[def_id
] <-
1523 self.tcx
.adt_def(def_id
).non_enum_variant().fields
.iter().map(|f
| {
1524 assert
!(f
.did
.is_local());
1529 hir
::ItemKind
::Impl { .. }
| hir
::ItemKind
::Trait(..) => {
1530 let associated_item_def_ids
= self.tcx
.associated_item_def_ids(def_id
);
1531 record_array
!(self.tables
.children
[def_id
] <-
1532 associated_item_def_ids
.iter().map(|&def_id
| {
1533 assert
!(def_id
.is_local());
1541 hir
::ItemKind
::Static(..)
1542 | hir
::ItemKind
::Const(..)
1543 | hir
::ItemKind
::Fn(..)
1544 | hir
::ItemKind
::TyAlias(..)
1545 | hir
::ItemKind
::OpaqueTy(..)
1546 | hir
::ItemKind
::Enum(..)
1547 | hir
::ItemKind
::Struct(..)
1548 | hir
::ItemKind
::Union(..)
1549 | hir
::ItemKind
::Impl { .. }
=> self.encode_item_type(def_id
),
1552 if let hir
::ItemKind
::Fn(..) = item
.kind
{
1553 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1554 if tcx
.is_intrinsic(def_id
) {
1555 self.tables
.is_intrinsic
.set(def_id
.index
, ());
1558 if let hir
::ItemKind
::Impl { .. }
= item
.kind
{
1559 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(def_id
) {
1560 record
!(self.tables
.impl_trait_ref
[def_id
] <- trait_ref
);
1565 fn encode_info_for_generic_param(&mut self, def_id
: DefId
, kind
: EntryKind
, encode_type
: bool
) {
1566 record
!(self.tables
.kind
[def_id
] <- kind
);
1568 self.encode_item_type(def_id
);
1572 fn encode_info_for_closure(&mut self, hir_id
: hir
::HirId
) {
1573 let def_id
= self.tcx
.hir().local_def_id(hir_id
);
1574 debug
!("EncodeContext::encode_info_for_closure({:?})", def_id
);
1575 // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
1576 // including on the signature, which is inferred in `typeck.
1577 let typeck_result
: &'tcx ty
::TypeckResults
<'tcx
> = self.tcx
.typeck(def_id
);
1578 let ty
= typeck_result
.node_type(hir_id
);
1580 ty
::Generator(..) => {
1581 let data
= self.tcx
.generator_kind(def_id
).unwrap();
1582 let generator_diagnostic_data
= typeck_result
.get_generator_diagnostic_data();
1583 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::Generator
);
1584 record
!(self.tables
.generator_kind
[def_id
.to_def_id()] <- data
);
1585 record
!(self.tables
.generator_diagnostic_data
[def_id
.to_def_id()] <- generator_diagnostic_data
);
1588 ty
::Closure(..) => {
1589 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::Closure
);
1592 _
=> bug
!("closure that is neither generator nor closure"),
1594 self.encode_item_type(def_id
.to_def_id());
1595 if let ty
::Closure(def_id
, substs
) = *ty
.kind() {
1596 record
!(self.tables
.fn_sig
[def_id
] <- substs
.as_closure().sig());
1600 fn encode_info_for_anon_const(&mut self, id
: hir
::HirId
) {
1601 let def_id
= self.tcx
.hir().local_def_id(id
);
1602 debug
!("EncodeContext::encode_info_for_anon_const({:?})", def_id
);
1603 let body_id
= self.tcx
.hir().body_owned_by(id
);
1604 let const_data
= self.encode_rendered_const_for_body(body_id
);
1605 let qualifs
= self.tcx
.mir_const_qualif(def_id
);
1607 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::AnonConst
);
1608 record
!(self.tables
.mir_const_qualif
[def_id
.to_def_id()] <- qualifs
);
1609 record
!(self.tables
.rendered_const
[def_id
.to_def_id()] <- const_data
);
1610 self.encode_item_type(def_id
.to_def_id());
1613 fn encode_native_libraries(&mut self) -> LazyArray
<NativeLib
> {
1614 empty_proc_macro
!(self);
1615 let used_libraries
= self.tcx
.native_libraries(LOCAL_CRATE
);
1616 self.lazy_array(used_libraries
.iter())
1619 fn encode_foreign_modules(&mut self) -> LazyArray
<ForeignModule
> {
1620 empty_proc_macro
!(self);
1621 let foreign_modules
= self.tcx
.foreign_modules(LOCAL_CRATE
);
1622 self.lazy_array(foreign_modules
.iter().map(|(_
, m
)| m
).cloned())
1625 fn encode_hygiene(&mut self) -> (SyntaxContextTable
, ExpnDataTable
, ExpnHashTable
) {
1626 let mut syntax_contexts
: TableBuilder
<_
, _
> = Default
::default();
1627 let mut expn_data_table
: TableBuilder
<_
, _
> = Default
::default();
1628 let mut expn_hash_table
: TableBuilder
<_
, _
> = Default
::default();
1630 self.hygiene_ctxt
.encode(
1631 &mut (&mut *self, &mut syntax_contexts
, &mut expn_data_table
, &mut expn_hash_table
),
1632 |(this
, syntax_contexts
, _
, _
), index
, ctxt_data
| {
1633 syntax_contexts
.set(index
, this
.lazy(ctxt_data
));
1635 |(this
, _
, expn_data_table
, expn_hash_table
), index
, expn_data
, hash
| {
1636 if let Some(index
) = index
.as_local() {
1637 expn_data_table
.set(index
.as_raw(), this
.lazy(expn_data
));
1638 expn_hash_table
.set(index
.as_raw(), this
.lazy(hash
));
1644 syntax_contexts
.encode(&mut self.opaque
),
1645 expn_data_table
.encode(&mut self.opaque
),
1646 expn_hash_table
.encode(&mut self.opaque
),
1650 fn encode_proc_macros(&mut self) -> Option
<ProcMacroData
> {
1651 let is_proc_macro
= self.tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
);
1654 let hir
= tcx
.hir();
1656 let proc_macro_decls_static
= tcx
.proc_macro_decls_static(()).unwrap().local_def_index
;
1657 let stability
= tcx
.lookup_stability(CRATE_DEF_ID
);
1659 self.lazy_array(tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
));
1660 let spans
= self.tcx
.sess
.parse_sess
.proc_macro_quoted_spans();
1661 for (i
, span
) in spans
.into_iter().enumerate() {
1662 let span
= self.lazy(span
);
1663 self.tables
.proc_macro_quoted_spans
.set(i
, span
);
1666 self.tables
.opt_def_kind
.set(LOCAL_CRATE
.as_def_id().index
, DefKind
::Mod
);
1667 record
!(self.tables
.def_span
[LOCAL_CRATE
.as_def_id()] <- tcx
.def_span(LOCAL_CRATE
.as_def_id()));
1668 self.encode_attrs(LOCAL_CRATE
.as_def_id().expect_local());
1669 record
!(self.tables
.visibility
[LOCAL_CRATE
.as_def_id()] <- tcx
.visibility(LOCAL_CRATE
.as_def_id()));
1670 if let Some(stability
) = stability
{
1671 record
!(self.tables
.lookup_stability
[LOCAL_CRATE
.as_def_id()] <- stability
);
1673 self.encode_deprecation(LOCAL_CRATE
.as_def_id());
1675 // Normally, this information is encoded when we walk the items
1676 // defined in this crate. However, we skip doing that for proc-macro crates,
1677 // so we manually encode just the information that we need
1678 for &proc_macro
in &tcx
.resolutions(()).proc_macros
{
1679 let id
= proc_macro
;
1680 let proc_macro
= hir
.local_def_id_to_hir_id(proc_macro
);
1681 let mut name
= hir
.name(proc_macro
);
1682 let span
= hir
.span(proc_macro
);
1683 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1684 // so downstream crates need access to them.
1685 let attrs
= hir
.attrs(proc_macro
);
1686 let macro_kind
= if tcx
.sess
.contains_name(attrs
, sym
::proc_macro
) {
1688 } else if tcx
.sess
.contains_name(attrs
, sym
::proc_macro_attribute
) {
1690 } else if let Some(attr
) = tcx
.sess
.find_by_name(attrs
, sym
::proc_macro_derive
) {
1691 // This unwrap chain should have been checked by the proc-macro harness.
1692 name
= attr
.meta_item_list().unwrap()[0]
1700 bug
!("Unknown proc-macro type for item {:?}", id
);
1703 let mut def_key
= self.tcx
.hir().def_key(id
);
1704 def_key
.disambiguated_data
.data
= DefPathData
::MacroNs(name
);
1706 let def_id
= id
.to_def_id();
1707 self.tables
.opt_def_kind
.set(def_id
.index
, DefKind
::Macro(macro_kind
));
1708 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ProcMacro(macro_kind
));
1709 self.encode_attrs(id
);
1710 record
!(self.tables
.def_keys
[def_id
] <- def_key
);
1711 record
!(self.tables
.def_ident_span
[def_id
] <- span
);
1712 record
!(self.tables
.def_span
[def_id
] <- span
);
1713 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::Public
);
1714 if let Some(stability
) = stability
{
1715 record
!(self.tables
.lookup_stability
[def_id
] <- stability
);
1719 Some(ProcMacroData { proc_macro_decls_static, stability, macros }
)
1725 fn encode_debugger_visualizers(&mut self) -> LazyArray
<DebuggerVisualizerFile
> {
1726 empty_proc_macro
!(self);
1727 self.lazy_array(self.tcx
.debugger_visualizers(LOCAL_CRATE
).iter())
1730 fn encode_crate_deps(&mut self) -> LazyArray
<CrateDep
> {
1731 empty_proc_macro
!(self);
1738 let dep
= CrateDep
{
1739 name
: self.tcx
.crate_name(cnum
),
1740 hash
: self.tcx
.crate_hash(cnum
),
1741 host_hash
: self.tcx
.crate_host_hash(cnum
),
1742 kind
: self.tcx
.dep_kind(cnum
),
1743 extra_filename
: self.tcx
.extra_filename(cnum
).clone(),
1747 .collect
::<Vec
<_
>>();
1750 // Sanity-check the crate numbers
1751 let mut expected_cnum
= 1;
1752 for &(n
, _
) in &deps
{
1753 assert_eq
!(n
, CrateNum
::new(expected_cnum
));
1758 // We're just going to write a list of crate 'name-hash-version's, with
1759 // the assumption that they are numbered 1 to n.
1760 // FIXME (#2166): This is not nearly enough to support correct versioning
1761 // but is enough to get transitive crate dependencies working.
1762 self.lazy_array(deps
.iter().map(|&(_
, ref dep
)| dep
))
1765 fn encode_lib_features(&mut self) -> LazyArray
<(Symbol
, Option
<Symbol
>)> {
1766 empty_proc_macro
!(self);
1768 let lib_features
= tcx
.lib_features(());
1769 self.lazy_array(lib_features
.to_vec())
1772 fn encode_diagnostic_items(&mut self) -> LazyArray
<(Symbol
, DefIndex
)> {
1773 empty_proc_macro
!(self);
1775 let diagnostic_items
= &tcx
.diagnostic_items(LOCAL_CRATE
).name_to_id
;
1776 self.lazy_array(diagnostic_items
.iter().map(|(&name
, def_id
)| (name
, def_id
.index
)))
1779 fn encode_lang_items(&mut self) -> LazyArray
<(DefIndex
, usize)> {
1780 empty_proc_macro
!(self);
1782 let lang_items
= tcx
.lang_items();
1783 let lang_items
= lang_items
.items().iter();
1784 self.lazy_array(lang_items
.enumerate().filter_map(|(i
, &opt_def_id
)| {
1785 if let Some(def_id
) = opt_def_id
{
1786 if def_id
.is_local() {
1787 return Some((def_id
.index
, i
));
1794 fn encode_lang_items_missing(&mut self) -> LazyArray
<lang_items
::LangItem
> {
1795 empty_proc_macro
!(self);
1797 self.lazy_array(&tcx
.lang_items().missing
)
1800 fn encode_traits(&mut self) -> LazyArray
<DefIndex
> {
1801 empty_proc_macro
!(self);
1802 self.lazy_array(self.tcx
.traits_in_crate(LOCAL_CRATE
).iter().map(|def_id
| def_id
.index
))
1805 /// Encodes an index, mapping each trait to its (local) implementations.
1806 fn encode_impls(&mut self) -> LazyArray
<TraitImpls
> {
1807 debug
!("EncodeContext::encode_traits_and_impls()");
1808 empty_proc_macro
!(self);
1810 let mut fx_hash_map
: FxHashMap
<DefId
, Vec
<(DefIndex
, Option
<SimplifiedType
>)>> =
1811 FxHashMap
::default();
1813 for id
in tcx
.hir().items() {
1814 if matches
!(tcx
.def_kind(id
.def_id
), DefKind
::Impl
) {
1815 if let Some(trait_ref
) = tcx
.impl_trait_ref(id
.def_id
.to_def_id()) {
1816 let simplified_self_ty
= fast_reject
::simplify_type(
1818 trait_ref
.self_ty(),
1819 TreatParams
::AsInfer
,
1823 .entry(trait_ref
.def_id
)
1825 .push((id
.def_id
.local_def_index
, simplified_self_ty
));
1830 let mut all_impls
: Vec
<_
> = fx_hash_map
.into_iter().collect();
1832 // Bring everything into deterministic order for hashing
1833 all_impls
.sort_by_cached_key(|&(trait_def_id
, _
)| tcx
.def_path_hash(trait_def_id
));
1835 let all_impls
: Vec
<_
> = all_impls
1837 .map(|(trait_def_id
, mut impls
)| {
1838 // Bring everything into deterministic order for hashing
1839 impls
.sort_by_cached_key(|&(index
, _
)| {
1840 tcx
.hir().def_path_hash(LocalDefId { local_def_index: index }
)
1844 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
1845 impls
: self.lazy_array(&impls
),
1850 self.lazy_array(&all_impls
)
1853 fn encode_incoherent_impls(&mut self) -> LazyArray
<IncoherentImpls
> {
1854 debug
!("EncodeContext::encode_traits_and_impls()");
1855 empty_proc_macro
!(self);
1857 let mut ctx
= tcx
.create_stable_hashing_context();
1858 let mut all_impls
: Vec
<_
> = tcx
.crate_inherent_impls(()).incoherent_impls
.iter().collect();
1859 all_impls
.sort_by_cached_key(|&(&simp
, _
)| {
1860 let mut hasher
= StableHasher
::new();
1861 simp
.hash_stable(&mut ctx
, &mut hasher
);
1862 hasher
.finish
::<Fingerprint
>();
1864 let all_impls
: Vec
<_
> = all_impls
1866 .map(|(&simp
, impls
)| {
1867 let mut impls
: Vec
<_
> =
1868 impls
.into_iter().map(|def_id
| def_id
.local_def_index
).collect();
1869 impls
.sort_by_cached_key(|&local_def_index
| {
1870 tcx
.hir().def_path_hash(LocalDefId { local_def_index }
)
1873 IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
1877 self.lazy_array(&all_impls
)
1880 // Encodes all symbols exported from this crate into the metadata.
1882 // This pass is seeded off the reachability list calculated in the
1883 // middle::reachable module but filters out items that either don't have a
1884 // symbol associated with them (they weren't translated) or if they're an FFI
1885 // definition (as that's not defined in this crate).
1886 fn encode_exported_symbols(
1888 exported_symbols
: &[(ExportedSymbol
<'tcx
>, SymbolExportInfo
)],
1889 ) -> LazyArray
<(ExportedSymbol
<'
static>, SymbolExportInfo
)> {
1890 empty_proc_macro
!(self);
1891 // The metadata symbol name is special. It should not show up in
1892 // downstream crates.
1893 let metadata_symbol_name
= SymbolName
::new(self.tcx
, &metadata_symbol_name(self.tcx
));
1898 .filter(|&&(ref exported_symbol
, _
)| match *exported_symbol
{
1899 ExportedSymbol
::NoDefId(symbol_name
) => symbol_name
!= metadata_symbol_name
,
1906 fn encode_dylib_dependency_formats(&mut self) -> LazyArray
<Option
<LinkagePreference
>> {
1907 empty_proc_macro
!(self);
1908 let formats
= self.tcx
.dependency_formats(());
1909 for (ty
, arr
) in formats
.iter() {
1910 if *ty
!= CrateType
::Dylib
{
1913 return self.lazy_array(arr
.iter().map(|slot
| match *slot
{
1914 Linkage
::NotLinked
| Linkage
::IncludedFromDylib
=> None
,
1916 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
1917 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
1923 fn encode_info_for_foreign_item(&mut self, def_id
: DefId
, nitem
: &hir
::ForeignItem
<'_
>) {
1926 debug
!("EncodeContext::encode_info_for_foreign_item({:?})", def_id
);
1929 hir
::ForeignItemKind
::Fn(_
, ref names
, _
) => {
1930 self.tables
.asyncness
.set(def_id
.index
, hir
::IsAsync
::NotAsync
);
1931 record_array
!(self.tables
.fn_arg_names
[def_id
] <- *names
);
1932 let constness
= if self.tcx
.is_const_fn_raw(def_id
) {
1933 hir
::Constness
::Const
1935 hir
::Constness
::NotConst
1937 self.tables
.constness
.set(def_id
.index
, constness
);
1938 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignFn
);
1940 hir
::ForeignItemKind
::Static(..) => {
1941 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignStatic
);
1943 hir
::ForeignItemKind
::Type
=> {
1944 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignType
);
1947 self.encode_item_type(def_id
);
1948 if let hir
::ForeignItemKind
::Fn(..) = nitem
.kind
{
1949 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1950 if tcx
.is_intrinsic(def_id
) {
1951 self.tables
.is_intrinsic
.set(def_id
.index
, ());
1957 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
1958 impl<'a
, 'tcx
> Visitor
<'tcx
> for EncodeContext
<'a
, 'tcx
> {
1959 type NestedFilter
= nested_filter
::OnlyBodies
;
1961 fn nested_visit_map(&mut self) -> Self::Map
{
1964 fn visit_expr(&mut self, ex
: &'tcx hir
::Expr
<'tcx
>) {
1965 intravisit
::walk_expr(self, ex
);
1966 self.encode_info_for_expr(ex
);
1968 fn visit_anon_const(&mut self, c
: &'tcx AnonConst
) {
1969 intravisit
::walk_anon_const(self, c
);
1970 self.encode_info_for_anon_const(c
.hir_id
);
1972 fn visit_item(&mut self, item
: &'tcx hir
::Item
<'tcx
>) {
1973 intravisit
::walk_item(self, item
);
1975 hir
::ItemKind
::ExternCrate(_
) | hir
::ItemKind
::Use(..) => {}
// ignore these
1976 _
=> self.encode_info_for_item(item
.def_id
.to_def_id(), item
),
1978 self.encode_addl_info_for_item(item
);
1980 fn visit_foreign_item(&mut self, ni
: &'tcx hir
::ForeignItem
<'tcx
>) {
1981 intravisit
::walk_foreign_item(self, ni
);
1982 self.encode_info_for_foreign_item(ni
.def_id
.to_def_id(), ni
);
1984 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
<'tcx
>) {
1985 intravisit
::walk_generics(self, generics
);
1986 self.encode_info_for_generics(generics
);
1990 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
1991 fn encode_fields(&mut self, adt_def
: ty
::AdtDef
<'tcx
>) {
1992 for (variant_index
, variant
) in adt_def
.variants().iter_enumerated() {
1993 for (field_index
, _field
) in variant
.fields
.iter().enumerate() {
1994 self.encode_field(adt_def
, variant_index
, field_index
);
1999 fn encode_info_for_generics(&mut self, generics
: &hir
::Generics
<'tcx
>) {
2000 for param
in generics
.params
{
2001 let def_id
= self.tcx
.hir().local_def_id(param
.hir_id
);
2003 GenericParamKind
::Lifetime { .. }
=> continue,
2004 GenericParamKind
::Type { default, .. }
=> {
2005 self.encode_info_for_generic_param(
2007 EntryKind
::TypeParam
,
2011 GenericParamKind
::Const { ref default, .. }
=> {
2012 let def_id
= def_id
.to_def_id();
2013 self.encode_info_for_generic_param(def_id
, EntryKind
::ConstParam
, true);
2014 if default.is_some() {
2015 record
!(self.tables
.const_param_default
[def_id
] <- self.tcx
.const_param_default(def_id
))
2022 fn encode_info_for_expr(&mut self, expr
: &hir
::Expr
<'_
>) {
2023 if let hir
::ExprKind
::Closure { .. }
= expr
.kind
{
2024 self.encode_info_for_closure(expr
.hir_id
);
2028 /// In some cases, along with the item itself, we also
2029 /// encode some sub-items. Usually we want some info from the item
2030 /// so it's easier to do that here then to wait until we would encounter
2031 /// normally in the visitor walk.
2032 fn encode_addl_info_for_item(&mut self, item
: &hir
::Item
<'_
>) {
2034 hir
::ItemKind
::Static(..)
2035 | hir
::ItemKind
::Const(..)
2036 | hir
::ItemKind
::Fn(..)
2037 | hir
::ItemKind
::Macro(..)
2038 | hir
::ItemKind
::Mod(..)
2039 | hir
::ItemKind
::ForeignMod { .. }
2040 | hir
::ItemKind
::GlobalAsm(..)
2041 | hir
::ItemKind
::ExternCrate(..)
2042 | hir
::ItemKind
::Use(..)
2043 | hir
::ItemKind
::TyAlias(..)
2044 | hir
::ItemKind
::OpaqueTy(..)
2045 | hir
::ItemKind
::TraitAlias(..) => {
2046 // no sub-item recording needed in these cases
2048 hir
::ItemKind
::Enum(..) => {
2049 let def
= self.tcx
.adt_def(item
.def_id
.to_def_id());
2050 self.encode_fields(def
);
2052 for (i
, variant
) in def
.variants().iter_enumerated() {
2053 self.encode_enum_variant_info(def
, i
);
2055 if let Some(_ctor_def_id
) = variant
.ctor_def_id
{
2056 self.encode_enum_variant_ctor(def
, i
);
2060 hir
::ItemKind
::Struct(ref struct_def
, _
) => {
2061 let def
= self.tcx
.adt_def(item
.def_id
.to_def_id());
2062 self.encode_fields(def
);
2064 // If the struct has a constructor, encode it.
2065 if let Some(ctor_hir_id
) = struct_def
.ctor_hir_id() {
2066 let ctor_def_id
= self.tcx
.hir().local_def_id(ctor_hir_id
);
2067 self.encode_struct_ctor(def
, ctor_def_id
.to_def_id());
2070 hir
::ItemKind
::Union(..) => {
2071 let def
= self.tcx
.adt_def(item
.def_id
.to_def_id());
2072 self.encode_fields(def
);
2074 hir
::ItemKind
::Impl { .. }
=> {
2075 for &trait_item_def_id
in
2076 self.tcx
.associated_item_def_ids(item
.def_id
.to_def_id()).iter()
2078 self.encode_info_for_impl_item(trait_item_def_id
);
2081 hir
::ItemKind
::Trait(..) => {
2082 for &item_def_id
in self.tcx
.associated_item_def_ids(item
.def_id
.to_def_id()).iter()
2084 self.encode_info_for_trait_item(item_def_id
);
2091 /// Used to prefetch queries which will be needed later by metadata encoding.
2092 /// Only a subset of the queries are actually prefetched to keep this code smaller.
2093 fn prefetch_mir(tcx
: TyCtxt
<'_
>) {
2094 if !tcx
.sess
.opts
.output_types
.should_codegen() {
2095 // We won't emit MIR, so don't prefetch it.
2099 par_iter(tcx
.mir_keys(())).for_each(|&def_id
| {
2100 let (encode_const
, encode_opt
) = should_encode_mir(tcx
, def_id
);
2103 tcx
.ensure().mir_for_ctfe(def_id
);
2106 tcx
.ensure().optimized_mir(def_id
);
2108 if encode_opt
|| encode_const
{
2109 tcx
.ensure().promoted_mir(def_id
);
2114 // NOTE(eddyb) The following comment was preserved for posterity, even
2115 // though it's no longer relevant as EBML (which uses nested & tagged
2116 // "documents") was replaced with a scheme that can't go out of bounds.
2118 // And here we run into yet another obscure archive bug: in which metadata
2119 // loaded from archives may have trailing garbage bytes. Awhile back one of
2120 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
2121 // and opt) by having ebml generate an out-of-bounds panic when looking at
2124 // Upon investigation it turned out that the metadata file inside of an rlib
2125 // (and ar archive) was being corrupted. Some compilations would generate a
2126 // metadata file which would end in a few extra bytes, while other
2127 // compilations would not have these extra bytes appended to the end. These
2128 // extra bytes were interpreted by ebml as an extra tag, so they ended up
2129 // being interpreted causing the out-of-bounds.
2131 // The root cause of why these extra bytes were appearing was never
2132 // discovered, and in the meantime the solution we're employing is to insert
2133 // the length of the metadata to the start of the metadata. Later on this
2134 // will allow us to slice the metadata to the precise length that we just
2135 // generated regardless of trailing bytes that end up in it.
2137 #[derive(Encodable, Decodable)]
2138 pub struct EncodedMetadata
{
2142 impl EncodedMetadata
{
2144 pub fn new() -> EncodedMetadata
{
2145 EncodedMetadata { raw_data: Vec::new() }
2149 pub fn raw_data(&self) -> &[u8] {
2154 pub fn encode_metadata(tcx
: TyCtxt
<'_
>) -> EncodedMetadata
{
2155 let _prof_timer
= tcx
.prof
.verbose_generic_activity("generate_crate_metadata");
2157 // Since encoding metadata is not in a query, and nothing is cached,
2158 // there's no need to do dep-graph tracking for any of it.
2159 tcx
.dep_graph
.assert_ignored();
2162 || encode_metadata_impl(tcx
),
2164 if tcx
.sess
.threads() == 1 {
2167 // Prefetch some queries used by metadata encoding.
2168 // This is not necessary for correctness, but is only done for performance reasons.
2169 // It can be removed if it turns out to cause trouble or be detrimental to performance.
2170 join(|| prefetch_mir(tcx
), || tcx
.exported_symbols(LOCAL_CRATE
));
2176 fn encode_metadata_impl(tcx
: TyCtxt
<'_
>) -> EncodedMetadata
{
2177 let mut encoder
= MemEncoder
::new();
2178 encoder
.emit_raw_bytes(METADATA_HEADER
);
2180 // Will be filled with the root position after encoding everything.
2181 encoder
.emit_raw_bytes(&[0, 0, 0, 0]);
2183 let source_map_files
= tcx
.sess
.source_map().files();
2184 let source_file_cache
= (source_map_files
[0].clone(), 0);
2185 let required_source_files
= Some(GrowableBitSet
::with_capacity(source_map_files
.len()));
2186 drop(source_map_files
);
2188 let hygiene_ctxt
= HygieneEncodeContext
::default();
2190 let mut ecx
= EncodeContext
{
2193 feat
: tcx
.features(),
2194 tables
: Default
::default(),
2195 lazy_state
: LazyState
::NoNode
,
2196 type_shorthands
: Default
::default(),
2197 predicate_shorthands
: Default
::default(),
2199 interpret_allocs
: Default
::default(),
2200 required_source_files
,
2201 is_proc_macro
: tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
),
2202 hygiene_ctxt
: &hygiene_ctxt
,
2205 // Encode the rustc version string in a predictable location.
2206 rustc_version().encode(&mut ecx
);
2208 // Encode all the entries and extra information in the crate,
2209 // culminating in the `CrateRoot` which points to all of it.
2210 let root
= ecx
.encode_crate_root();
2212 let mut result
= ecx
.opaque
.finish();
2214 // Encode the root position.
2215 let header
= METADATA_HEADER
.len();
2216 let pos
= root
.position
.get();
2217 result
[header
+ 0] = (pos
>> 24) as u8;
2218 result
[header
+ 1] = (pos
>> 16) as u8;
2219 result
[header
+ 2] = (pos
>> 8) as u8;
2220 result
[header
+ 3] = (pos
>> 0) as u8;
2222 // Record metadata size for self-profiling
2223 tcx
.prof
.artifact_size("crate_metadata", "crate_metadata", result
.len() as u64);
2225 EncodedMetadata { raw_data: result }
2228 pub fn provide(providers
: &mut Providers
) {
2229 *providers
= Providers
{
2230 traits_in_crate
: |tcx
, cnum
| {
2231 assert_eq
!(cnum
, LOCAL_CRATE
);
2233 let mut traits
= Vec
::new();
2234 for id
in tcx
.hir().items() {
2235 if matches
!(tcx
.def_kind(id
.def_id
), DefKind
::Trait
| DefKind
::TraitAlias
) {
2236 traits
.push(id
.def_id
.to_def_id())
2240 // Bring everything into deterministic order.
2241 traits
.sort_by_cached_key(|&def_id
| tcx
.def_path_hash(def_id
));
2242 tcx
.arena
.alloc_slice(&traits
)