1 use crate::rmeta
::table
::{FixedSizeEncoding, TableBuilder}
;
5 use rustc_data_structures
::fingerprint
::{Fingerprint, FingerprintEncoder}
;
6 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet, FxIndexSet}
;
7 use rustc_data_structures
::stable_hasher
::StableHasher
;
8 use rustc_data_structures
::sync
::{join, Lrc}
;
10 use rustc_hir
::def
::CtorKind
;
11 use rustc_hir
::def_id
::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}
;
12 use rustc_hir
::intravisit
::{self, NestedVisitorMap, Visitor}
;
13 use rustc_hir
::itemlikevisit
::{ItemLikeVisitor, ParItemLikeVisitor}
;
14 use rustc_hir
::lang_items
;
15 use rustc_hir
::{AnonConst, GenericParamKind}
;
16 use rustc_index
::bit_set
::GrowableBitSet
;
17 use rustc_index
::vec
::Idx
;
18 use rustc_middle
::hir
::map
::Map
;
19 use rustc_middle
::middle
::cstore
::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib}
;
20 use rustc_middle
::middle
::dependency_format
::Linkage
;
21 use rustc_middle
::middle
::exported_symbols
::{
22 metadata_symbol_name
, ExportedSymbol
, SymbolExportLevel
,
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
::{self, SymbolName, Ty, TyCtxt}
;
28 use rustc_serialize
::{opaque, Encodable, Encoder}
;
29 use rustc_session
::config
::CrateType
;
30 use rustc_span
::hygiene
::{ExpnDataEncodeMode, HygieneEncodeContext}
;
31 use rustc_span
::source_map
::Spanned
;
32 use rustc_span
::symbol
::{sym, Ident, Symbol}
;
33 use rustc_span
::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext}
;
34 use rustc_target
::abi
::VariantIdx
;
36 use std
::num
::NonZeroUsize
;
38 use tracing
::{debug, trace}
;
40 pub(super) struct EncodeContext
<'a
, 'tcx
> {
41 opaque
: opaque
::Encoder
,
43 feat
: &'tcx rustc_feature
::Features
,
45 tables
: TableBuilders
<'tcx
>,
47 lazy_state
: LazyState
,
48 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
49 predicate_shorthands
: FxHashMap
<ty
::Predicate
<'tcx
>, usize>,
51 interpret_allocs
: FxIndexSet
<interpret
::AllocId
>,
53 // This is used to speed up Span encoding.
54 // The `usize` is an index into the `MonotonicVec`
55 // that stores the `SourceFile`
56 source_file_cache
: (Lrc
<SourceFile
>, usize),
57 // The indices (into the `SourceMap`'s `MonotonicVec`)
58 // of all of the `SourceFiles` that we need to serialize.
59 // When we serialize a `Span`, we insert the index of its
60 // `SourceFile` into the `GrowableBitSet`.
62 // This needs to be a `GrowableBitSet` and not a
63 // regular `BitSet` because we may actually import new `SourceFiles`
64 // during metadata encoding, due to executing a query
65 // with a result containing a foreign `Span`.
66 required_source_files
: Option
<GrowableBitSet
<usize>>,
68 hygiene_ctxt
: &'a HygieneEncodeContext
,
71 /// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
72 /// This is useful for skipping the encoding of things that aren't needed
73 /// for proc-macro crates.
74 macro_rules
! empty_proc_macro
{
76 if $
self.is_proc_macro
{
82 macro_rules
! encoder_methods
{
83 ($
($name
:ident($ty
:ty
);)*) => {
84 $
(fn $
name(&mut self, value
: $ty
) -> Result
<(), Self::Error
> {
85 self.opaque
.$
name(value
)
90 impl<'a
, 'tcx
> Encoder
for EncodeContext
<'a
, 'tcx
> {
91 type Error
= <opaque
::Encoder
as Encoder
>::Error
;
94 fn emit_unit(&mut self) -> Result
<(), Self::Error
> {
121 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> Encodable
<EncodeContext
<'a
, 'tcx
>>
124 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
125 e
.emit_lazy_distance(*self)
129 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> Encodable
<EncodeContext
<'a
, 'tcx
>>
132 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
133 e
.emit_usize(self.meta
)?
;
137 e
.emit_lazy_distance(*self)
141 impl<'a
, 'tcx
, I
: Idx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> Encodable
<EncodeContext
<'a
, 'tcx
>>
142 for Lazy
<Table
<I
, T
>>
144 Option
<T
>: FixedSizeEncoding
,
146 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
147 e
.emit_usize(self.meta
)?
;
148 e
.emit_lazy_distance(*self)
152 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for CrateNum
{
153 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
154 if *self != LOCAL_CRATE
&& s
.is_proc_macro
{
155 panic
!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
157 s
.emit_u32(self.as_u32())
161 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for DefIndex
{
162 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
163 s
.emit_u32(self.as_u32())
167 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for SyntaxContext
{
168 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
169 rustc_span
::hygiene
::raw_encode_syntax_context(*self, &s
.hygiene_ctxt
, s
)
173 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnId
{
174 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
175 rustc_span
::hygiene
::raw_encode_expn_id(
178 ExpnDataEncodeMode
::Metadata
,
184 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for Span
{
185 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
186 if *self == rustc_span
::DUMMY_SP
{
187 return TAG_INVALID_SPAN
.encode(s
);
190 let span
= self.data();
192 // The Span infrastructure should make sure that this invariant holds:
193 debug_assert
!(span
.lo
<= span
.hi
);
195 if !s
.source_file_cache
.0.contains(span
.lo
) {
196 let source_map
= s
.tcx
.sess
.source_map();
197 let source_file_index
= source_map
.lookup_source_file_idx(span
.lo
);
198 s
.source_file_cache
=
199 (source_map
.files()[source_file_index
].clone(), source_file_index
);
202 if !s
.source_file_cache
.0.contains(span
.hi
) {
203 // Unfortunately, macro expansion still sometimes generates Spans
204 // that malformed in this way.
205 return TAG_INVALID_SPAN
.encode(s
);
208 let source_files
= s
.required_source_files
.as_mut().expect("Already encoded SourceMap!");
209 // Record the fact that we need to encode the data for this `SourceFile`
210 source_files
.insert(s
.source_file_cache
.1);
212 // There are two possible cases here:
213 // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
214 // crate we are writing metadata for. When the metadata for *this* crate gets
215 // deserialized, the deserializer will need to know which crate it originally came
216 // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
217 // be deserialized after the rest of the span data, which tells the deserializer
218 // which crate contains the source map information.
219 // 2. This span comes from our own crate. No special hamdling is needed - we just
220 // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
221 // our own source map information.
223 // If we're a proc-macro crate, we always treat this as a local `Span`.
224 // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata
225 // if we're a proc-macro crate.
226 // This allows us to avoid loading the dependencies of proc-macro crates: all of
227 // the information we need to decode `Span`s is stored in the proc-macro crate.
228 let (tag
, lo
, hi
) = if s
.source_file_cache
.0.is_imported
() && !s
.is_proc_macro
{
229 // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
230 // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
231 // are relative to the source map information for the 'foreign' crate whose CrateNum
232 // we write into the metadata. This allows `imported_source_files` to binary
233 // search through the 'foreign' crate's source map information, using the
234 // deserialized 'lo' and 'hi' values directly.
236 // All of this logic ensures that the final result of deserialization is a 'normal'
237 // Span that can be used without any additional trouble.
238 let external_start_pos
= {
239 // Introduce a new scope so that we drop the 'lock()' temporary
240 match &*s
.source_file_cache
.0.external_src
.lock() {
241 ExternalSource
::Foreign { original_start_pos, .. }
=> *original_start_pos
,
242 src
=> panic
!("Unexpected external source {:?}", src
),
245 let lo
= (span
.lo
- s
.source_file_cache
.0.start_pos
) + external_start_pos
;
246 let hi
= (span
.hi
- s
.source_file_cache
.0.start_pos
) + external_start_pos
;
248 (TAG_VALID_SPAN_FOREIGN
, lo
, hi
)
250 (TAG_VALID_SPAN_LOCAL
, span
.lo
, span
.hi
)
256 // Encode length which is usually less than span.hi and profits more
257 // from the variable-length integer encoding that we use.
261 // Don't serialize any `SyntaxContext`s from a proc-macro crate,
262 // since we don't load proc-macro dependencies during serialization.
263 // This means that any hygiene information from macros used *within*
264 // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
265 // definition) will be lost.
267 // This can show up in two ways:
269 // 1. Any hygiene information associated with identifier of
270 // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
271 // Since proc-macros can only be invoked from a different crate,
272 // real code should never need to care about this.
274 // 2. Using `Span::def_site` or `Span::mixed_site` will not
275 // include any hygiene information associated with the definition
276 // site. This means that a proc-macro cannot emit a `$crate`
277 // identifier which resolves to one of its dependencies,
278 // which also should never come up in practice.
280 // Additionally, this affects `Span::parent`, and any other
281 // span inspection APIs that would otherwise allow traversing
282 // the `SyntaxContexts` associated with a span.
284 // None of these user-visible effects should result in any
285 // cross-crate inconsistencies (getting one behavior in the same
286 // crate, and a different behavior in another crate) due to the
287 // limited surface that proc-macros can expose.
289 // IMPORTANT: If this is ever changed, be sure to update
290 // `rustc_span::hygiene::raw_encode_expn_id` to handle
291 // encoding `ExpnData` for proc-macro crates.
293 SyntaxContext
::root().encode(s
)?
;
295 span
.ctxt
.encode(s
)?
;
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
;
309 impl<'a
, 'tcx
> FingerprintEncoder
for EncodeContext
<'a
, 'tcx
> {
310 fn encode_fingerprint(&mut self, f
: &Fingerprint
) -> Result
<(), Self::Error
> {
311 f
.encode_opaque(&mut self.opaque
)
315 impl<'a
, 'tcx
> TyEncoder
<'tcx
> for EncodeContext
<'a
, 'tcx
> {
316 const CLEAR_CROSS_CRATE
: bool
= true;
318 fn position(&self) -> usize {
319 self.opaque
.position()
322 fn tcx(&self) -> TyCtxt
<'tcx
> {
326 fn type_shorthands(&mut self) -> &mut FxHashMap
<Ty
<'tcx
>, usize> {
327 &mut self.type_shorthands
330 fn predicate_shorthands(&mut self) -> &mut FxHashMap
<rustc_middle
::ty
::Predicate
<'tcx
>, usize> {
331 &mut self.predicate_shorthands
336 alloc_id
: &rustc_middle
::mir
::interpret
::AllocId
,
337 ) -> Result
<(), Self::Error
> {
338 let (index
, _
) = self.interpret_allocs
.insert_full(*alloc_id
);
344 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for &'tcx
[mir
::abstract_const
::Node
<'tcx
>] {
345 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
350 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for &'tcx
[(ty
::Predicate
<'tcx
>, Span
)] {
351 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
356 /// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
357 trait EncodeContentsForLazy
<'a
, 'tcx
, T
: ?Sized
+ LazyMeta
> {
358 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) -> T
::Meta
;
361 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> EncodeContentsForLazy
<'a
, 'tcx
, T
> for &T
{
362 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) {
363 self.encode(ecx
).unwrap()
367 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> EncodeContentsForLazy
<'a
, 'tcx
, T
> for T
{
368 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) {
369 self.encode(ecx
).unwrap()
373 impl<'a
, 'tcx
, I
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> EncodeContentsForLazy
<'a
, 'tcx
, [T
]> for I
376 I
::Item
: EncodeContentsForLazy
<'a
, 'tcx
, T
>,
378 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) -> usize {
379 self.into_iter().map(|value
| value
.encode_contents_for_lazy(ecx
)).count()
383 // Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
384 // normally need extra variables to avoid errors about multiple mutable borrows.
385 macro_rules
! record
{
386 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
389 let lazy
= $
self.lazy(value
);
390 $
self.$tables
.$table
.set($def_id
.index
, lazy
);
395 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
396 fn emit_lazy_distance
<T
: ?Sized
+ LazyMeta
>(
399 ) -> Result
<(), <Self as Encoder
>::Error
> {
400 let min_end
= lazy
.position
.get() + T
::min_size(lazy
.meta
);
401 let distance
= match self.lazy_state
{
402 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
403 LazyState
::NodeStart(start
) => {
404 let start
= start
.get();
405 assert
!(min_end
<= start
);
408 LazyState
::Previous(last_min_end
) => {
410 last_min_end
<= lazy
.position
,
411 "make sure that the calls to `lazy*` \
412 are in the same order as the metadata fields",
414 lazy
.position
.get() - last_min_end
.get()
417 self.lazy_state
= LazyState
::Previous(NonZeroUsize
::new(min_end
).unwrap());
418 self.emit_usize(distance
)
421 fn lazy
<T
: ?Sized
+ LazyMeta
>(
423 value
: impl EncodeContentsForLazy
<'a
, 'tcx
, T
>,
425 let pos
= NonZeroUsize
::new(self.position()).unwrap();
427 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
428 self.lazy_state
= LazyState
::NodeStart(pos
);
429 let meta
= value
.encode_contents_for_lazy(self);
430 self.lazy_state
= LazyState
::NoNode
;
432 assert
!(pos
.get() + <T
>::min_size(meta
) <= self.position());
434 Lazy
::from_position_and_meta(pos
, meta
)
437 fn encode_info_for_items(&mut self) {
438 let krate
= self.tcx
.hir().krate();
439 let vis
= Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }
;
440 self.encode_info_for_mod(hir
::CRATE_HIR_ID
, &krate
.item
.module
, &krate
.item
.attrs
, &vis
);
442 // Proc-macro crates only export proc-macro items, which are looked
443 // up using `proc_macro_data`
444 if self.is_proc_macro
{
448 krate
.visit_all_item_likes(&mut self.as_deep_visitor());
449 for macro_def
in krate
.exported_macros
{
450 self.visit_macro_def(macro_def
);
454 fn encode_def_path_table(&mut self) {
455 let table
= self.tcx
.hir().definitions().def_path_table();
456 if self.is_proc_macro
{
457 for def_index
in std
::iter
::once(CRATE_DEF_INDEX
)
458 .chain(self.tcx
.hir().krate().proc_macros
.iter().map(|p
| p
.owner
.local_def_index
))
460 let def_key
= self.lazy(table
.def_key(def_index
));
461 let def_path_hash
= self.lazy(table
.def_path_hash(def_index
));
462 self.tables
.def_keys
.set(def_index
, def_key
);
463 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
);
466 for (def_index
, def_key
, def_path_hash
) in table
.enumerated_keys_and_path_hashes() {
467 let def_key
= self.lazy(def_key
);
468 let def_path_hash
= self.lazy(def_path_hash
);
469 self.tables
.def_keys
.set(def_index
, def_key
);
470 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
);
475 fn encode_source_map(&mut self) -> Lazy
<[rustc_span
::SourceFile
]> {
476 let source_map
= self.tcx
.sess
.source_map();
477 let all_source_files
= source_map
.files();
479 let (working_dir
, _cwd_remapped
) = self.tcx
.sess
.working_dir
.clone();
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 adapted
= all_source_files
488 .filter(|(idx
, source_file
)| {
489 // Only serialize `SourceFile`s that were used
490 // during the encoding of a `Span`
491 required_source_files
.contains(*idx
) &&
492 // Don't serialize imported `SourceFile`s, unless
493 // we're in a proc-macro crate.
494 (!source_file
.is_imported() || self.is_proc_macro
)
496 .map(|(_
, source_file
)| {
497 let mut adapted
= match source_file
.name
{
498 // This path of this SourceFile has been modified by
499 // path-remapping, so we use it verbatim (and avoid
500 // cloning the whole map in the process).
501 _
if source_file
.name_was_remapped
=> source_file
.clone(),
503 // Otherwise expand all paths to absolute paths because
504 // any relative paths are potentially relative to a
506 FileName
::Real(ref name
) => {
507 let name
= name
.stable_name();
508 let mut adapted
= (**source_file
).clone();
509 adapted
.name
= Path
::new(&working_dir
).join(name
).into();
510 adapted
.name_hash
= {
511 let mut hasher
: StableHasher
= StableHasher
::new();
512 adapted
.name
.hash(&mut hasher
);
513 hasher
.finish
::<u128
>()
518 // expanded code, not from a file
519 _
=> source_file
.clone(),
522 // We're serializing this `SourceFile` into our crate metadata,
523 // so mark it as coming from this crate.
524 // This also ensures that we don't try to deserialize the
525 // `CrateNum` for a proc-macro dependency - since proc macro
526 // dependencies aren't loaded when we deserialize a proc-macro,
527 // trying to remap the `CrateNum` would fail.
528 if self.is_proc_macro
{
529 Lrc
::make_mut(&mut adapted
).cnum
= LOCAL_CRATE
;
533 .collect
::<Vec
<_
>>();
535 self.lazy(adapted
.iter().map(|rc
| &**rc
))
538 fn encode_crate_root(&mut self) -> Lazy
<CrateRoot
<'tcx
>> {
539 let mut i
= self.position();
541 // Encode the crate deps
542 let crate_deps
= self.encode_crate_deps();
543 let dylib_dependency_formats
= self.encode_dylib_dependency_formats();
544 let dep_bytes
= self.position() - i
;
546 // Encode the lib features.
548 let lib_features
= self.encode_lib_features();
549 let lib_feature_bytes
= self.position() - i
;
551 // Encode the language items.
553 let lang_items
= self.encode_lang_items();
554 let lang_items_missing
= self.encode_lang_items_missing();
555 let lang_item_bytes
= self.position() - i
;
557 // Encode the diagnostic items.
559 let diagnostic_items
= self.encode_diagnostic_items();
560 let diagnostic_item_bytes
= self.position() - i
;
562 // Encode the native libraries used
564 let native_libraries
= self.encode_native_libraries();
565 let native_lib_bytes
= self.position() - i
;
567 let foreign_modules
= self.encode_foreign_modules();
569 // Encode DefPathTable
571 self.encode_def_path_table();
572 let def_path_table_bytes
= self.position() - i
;
574 // Encode the def IDs of impls, for coherence checking.
576 let impls
= self.encode_impls();
577 let impl_bytes
= self.position() - i
;
583 self.encode_info_for_items();
584 let item_bytes
= self.position() - i
;
586 // Encode the allocation index
587 let interpret_alloc_index
= {
588 let mut interpret_alloc_index
= Vec
::new();
590 trace
!("beginning to encode alloc ids");
592 let new_n
= self.interpret_allocs
.len();
593 // if we have found new ids, serialize those, too
598 trace
!("encoding {} further alloc ids", new_n
- n
);
599 for idx
in n
..new_n
{
600 let id
= self.interpret_allocs
[idx
];
601 let pos
= self.position() as u32;
602 interpret_alloc_index
.push(pos
);
603 interpret
::specialized_encode_alloc_id(self, tcx
, id
).unwrap();
607 self.lazy(interpret_alloc_index
)
610 // Encode the proc macro data. This affects 'tables',
611 // so we need to do this before we encode the tables
613 let proc_macro_data
= self.encode_proc_macros();
614 let proc_macro_data_bytes
= self.position() - i
;
617 let tables
= self.tables
.encode(&mut self.opaque
);
618 let tables_bytes
= self.position() - i
;
620 // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
621 // this as late as possible to give the prefetching as much time as possible to complete.
623 let exported_symbols
= tcx
.exported_symbols(LOCAL_CRATE
);
624 let exported_symbols
= self.encode_exported_symbols(&exported_symbols
);
625 let exported_symbols_bytes
= self.position() - i
;
627 // Encode the hygiene data,
628 // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
629 // of encoding other items (e.g. `optimized_mir`) may cause us to load
630 // data from the incremental cache. If this causes us to deserialize a `Span`,
631 // then we may load additional `SyntaxContext`s into the global `HygieneData`.
632 // Therefore, we need to encode the hygiene data last to ensure that we encode
633 // any `SyntaxContext`s that might be used.
635 let (syntax_contexts
, expn_data
) = self.encode_hygiene();
636 let hygiene_bytes
= self.position() - i
;
638 // Encode source_map. This needs to be done last,
639 // since encoding `Span`s tells us which `SourceFiles` we actually
642 let source_map
= self.encode_source_map();
643 let source_map_bytes
= self.position() - i
;
645 let attrs
= tcx
.hir().krate_attrs();
646 let has_default_lib_allocator
= tcx
.sess
.contains_name(&attrs
, sym
::default_lib_allocator
);
648 let root
= self.lazy(CrateRoot
{
649 name
: tcx
.crate_name(LOCAL_CRATE
),
650 extra_filename
: tcx
.sess
.opts
.cg
.extra_filename
.clone(),
651 triple
: tcx
.sess
.opts
.target_triple
.clone(),
652 hash
: tcx
.crate_hash(LOCAL_CRATE
),
653 disambiguator
: tcx
.sess
.local_crate_disambiguator(),
654 panic_strategy
: tcx
.sess
.panic_strategy(),
655 edition
: tcx
.sess
.edition(),
656 has_global_allocator
: tcx
.has_global_allocator(LOCAL_CRATE
),
657 has_panic_handler
: tcx
.has_panic_handler(LOCAL_CRATE
),
658 has_default_lib_allocator
,
659 plugin_registrar_fn
: tcx
.plugin_registrar_fn(LOCAL_CRATE
).map(|id
| id
.index
),
661 compiler_builtins
: tcx
.sess
.contains_name(&attrs
, sym
::compiler_builtins
),
662 needs_allocator
: tcx
.sess
.contains_name(&attrs
, sym
::needs_allocator
),
663 needs_panic_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::needs_panic_runtime
),
664 no_builtins
: tcx
.sess
.contains_name(&attrs
, sym
::no_builtins
),
665 panic_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::panic_runtime
),
666 profiler_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::profiler_runtime
),
667 symbol_mangling_version
: tcx
.sess
.opts
.debugging_opts
.symbol_mangling_version
,
670 dylib_dependency_formats
,
680 interpret_alloc_index
,
686 let total_bytes
= self.position();
688 if tcx
.sess
.meta_stats() {
689 let mut zero_bytes
= 0;
690 for e
in self.opaque
.data
.iter() {
696 println
!("metadata stats:");
697 println
!(" dep bytes: {}", dep_bytes
);
698 println
!(" lib feature bytes: {}", lib_feature_bytes
);
699 println
!(" lang item bytes: {}", lang_item_bytes
);
700 println
!(" diagnostic item bytes: {}", diagnostic_item_bytes
);
701 println
!(" native bytes: {}", native_lib_bytes
);
702 println
!(" source_map bytes: {}", source_map_bytes
);
703 println
!(" impl bytes: {}", impl_bytes
);
704 println
!(" exp. symbols bytes: {}", exported_symbols_bytes
);
705 println
!(" def-path table bytes: {}", def_path_table_bytes
);
706 println
!(" proc-macro-data-bytes: {}", proc_macro_data_bytes
);
707 println
!(" item bytes: {}", item_bytes
);
708 println
!(" table bytes: {}", tables_bytes
);
709 println
!(" hygiene bytes: {}", hygiene_bytes
);
710 println
!(" zero bytes: {}", zero_bytes
);
711 println
!(" total bytes: {}", total_bytes
);
718 impl EncodeContext
<'a
, 'tcx
> {
719 fn encode_variances_of(&mut self, def_id
: DefId
) {
720 debug
!("EncodeContext::encode_variances_of({:?})", def_id
);
721 record
!(self.tables
.variances
[def_id
] <- &self.tcx
.variances_of(def_id
)[..]);
724 fn encode_item_type(&mut self, def_id
: DefId
) {
725 debug
!("EncodeContext::encode_item_type({:?})", def_id
);
726 record
!(self.tables
.ty
[def_id
] <- self.tcx
.type_of(def_id
));
729 fn encode_enum_variant_info(&mut self, def
: &ty
::AdtDef
, index
: VariantIdx
) {
731 let variant
= &def
.variants
[index
];
732 let def_id
= variant
.def_id
;
733 debug
!("EncodeContext::encode_enum_variant_info({:?})", def_id
);
735 let data
= VariantData
{
736 ctor_kind
: variant
.ctor_kind
,
737 discr
: variant
.discr
,
738 ctor
: variant
.ctor_def_id
.map(|did
| did
.index
),
739 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
742 let enum_id
= tcx
.hir().local_def_id_to_hir_id(def
.did
.expect_local());
743 let enum_vis
= &tcx
.hir().expect_item(enum_id
).vis
;
745 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Variant(self.lazy(data
)));
746 record
!(self.tables
.visibility
[def_id
] <-
747 ty
::Visibility
::from_hir(enum_vis
, enum_id
, self.tcx
));
748 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
749 record
!(self.tables
.attributes
[def_id
] <- &self.tcx
.get_attrs(def_id
)[..]);
750 record
!(self.tables
.children
[def_id
] <- variant
.fields
.iter().map(|f
| {
751 assert
!(f
.did
.is_local());
754 self.encode_ident_span(def_id
, variant
.ident
);
755 self.encode_stability(def_id
);
756 self.encode_deprecation(def_id
);
757 self.encode_item_type(def_id
);
758 if variant
.ctor_kind
== CtorKind
::Fn
{
759 // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
760 if let Some(ctor_def_id
) = variant
.ctor_def_id
{
761 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(ctor_def_id
));
763 // FIXME(eddyb) is this ever used?
764 self.encode_variances_of(def_id
);
766 self.encode_generics(def_id
);
767 self.encode_explicit_predicates(def_id
);
768 self.encode_inferred_outlives(def_id
);
769 self.encode_optimized_mir(def_id
.expect_local());
770 self.encode_promoted_mir(def_id
.expect_local());
773 fn encode_enum_variant_ctor(&mut self, def
: &ty
::AdtDef
, index
: VariantIdx
) {
775 let variant
= &def
.variants
[index
];
776 let def_id
= variant
.ctor_def_id
.unwrap();
777 debug
!("EncodeContext::encode_enum_variant_ctor({:?})", def_id
);
779 // FIXME(eddyb) encode only the `CtorKind` for constructors.
780 let data
= VariantData
{
781 ctor_kind
: variant
.ctor_kind
,
782 discr
: variant
.discr
,
783 ctor
: Some(def_id
.index
),
784 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
787 // Variant constructors have the same visibility as the parent enums, unless marked as
788 // non-exhaustive, in which case they are lowered to `pub(crate)`.
789 let enum_id
= tcx
.hir().local_def_id_to_hir_id(def
.did
.expect_local());
790 let enum_vis
= &tcx
.hir().expect_item(enum_id
).vis
;
791 let mut ctor_vis
= ty
::Visibility
::from_hir(enum_vis
, enum_id
, tcx
);
792 if variant
.is_field_list_non_exhaustive() && ctor_vis
== ty
::Visibility
::Public
{
793 ctor_vis
= ty
::Visibility
::Restricted(DefId
::local(CRATE_DEF_INDEX
));
796 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Variant(self.lazy(data
)));
797 record
!(self.tables
.visibility
[def_id
] <- ctor_vis
);
798 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
799 self.encode_stability(def_id
);
800 self.encode_deprecation(def_id
);
801 self.encode_item_type(def_id
);
802 if variant
.ctor_kind
== CtorKind
::Fn
{
803 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
804 self.encode_variances_of(def_id
);
806 self.encode_generics(def_id
);
807 self.encode_explicit_predicates(def_id
);
808 self.encode_inferred_outlives(def_id
);
809 self.encode_optimized_mir(def_id
.expect_local());
810 self.encode_promoted_mir(def_id
.expect_local());
813 fn encode_info_for_mod(
817 attrs
: &[ast
::Attribute
],
818 vis
: &hir
::Visibility
<'_
>,
821 let local_def_id
= tcx
.hir().local_def_id(id
);
822 let def_id
= local_def_id
.to_def_id();
823 debug
!("EncodeContext::encode_info_for_mod({:?})", def_id
);
825 // If we are encoding a proc-macro crates, `encode_info_for_mod` will
826 // only ever get called for the crate root. We still want to encode
827 // the crate root for consistency with other crates (some of the resolver
828 // code uses it). However, we skip encoding anything relating to child
829 // items - we encode information about proc-macros later on.
830 let reexports
= if !self.is_proc_macro
{
831 match tcx
.module_exports(local_def_id
) {
833 let hir
= self.tcx
.hir();
837 .map(|export
| export
.map_id(|id
| hir
.local_def_id_to_hir_id(id
))),
848 expansion
: tcx
.hir().definitions().expansion_that_defined(local_def_id
),
851 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Mod(self.lazy(data
)));
852 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::from_hir(vis
, id
, self.tcx
));
853 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
854 record
!(self.tables
.attributes
[def_id
] <- attrs
);
855 if self.is_proc_macro
{
856 record
!(self.tables
.children
[def_id
] <- &[]);
858 record
!(self.tables
.children
[def_id
] <- md
.item_ids
.iter().map(|item_id
| {
859 tcx
.hir().local_def_id(item_id
.id
).local_def_index
862 self.encode_stability(def_id
);
863 self.encode_deprecation(def_id
);
868 adt_def
: &ty
::AdtDef
,
869 variant_index
: VariantIdx
,
873 let variant
= &adt_def
.variants
[variant_index
];
874 let field
= &variant
.fields
[field_index
];
876 let def_id
= field
.did
;
877 debug
!("EncodeContext::encode_field({:?})", def_id
);
879 let variant_id
= tcx
.hir().local_def_id_to_hir_id(variant
.def_id
.expect_local());
880 let variant_data
= tcx
.hir().expect_variant_data(variant_id
);
882 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Field
);
883 record
!(self.tables
.visibility
[def_id
] <- field
.vis
);
884 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
885 record
!(self.tables
.attributes
[def_id
] <- variant_data
.fields()[field_index
].attrs
);
886 self.encode_ident_span(def_id
, field
.ident
);
887 self.encode_stability(def_id
);
888 self.encode_deprecation(def_id
);
889 self.encode_item_type(def_id
);
890 self.encode_generics(def_id
);
891 self.encode_explicit_predicates(def_id
);
892 self.encode_inferred_outlives(def_id
);
895 fn encode_struct_ctor(&mut self, adt_def
: &ty
::AdtDef
, def_id
: DefId
) {
896 debug
!("EncodeContext::encode_struct_ctor({:?})", def_id
);
898 let variant
= adt_def
.non_enum_variant();
900 let data
= VariantData
{
901 ctor_kind
: variant
.ctor_kind
,
902 discr
: variant
.discr
,
903 ctor
: Some(def_id
.index
),
904 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
907 let struct_id
= tcx
.hir().local_def_id_to_hir_id(adt_def
.did
.expect_local());
908 let struct_vis
= &tcx
.hir().expect_item(struct_id
).vis
;
909 let mut ctor_vis
= ty
::Visibility
::from_hir(struct_vis
, struct_id
, tcx
);
910 for field
in &variant
.fields
{
911 if ctor_vis
.is_at_least(field
.vis
, tcx
) {
912 ctor_vis
= field
.vis
;
916 // If the structure is marked as non_exhaustive then lower the visibility
917 // to within the crate.
918 if adt_def
.non_enum_variant().is_field_list_non_exhaustive()
919 && ctor_vis
== ty
::Visibility
::Public
921 ctor_vis
= ty
::Visibility
::Restricted(DefId
::local(CRATE_DEF_INDEX
));
924 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Struct(self.lazy(data
), adt_def
.repr
));
925 record
!(self.tables
.visibility
[def_id
] <- ctor_vis
);
926 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
927 self.encode_stability(def_id
);
928 self.encode_deprecation(def_id
);
929 self.encode_item_type(def_id
);
930 if variant
.ctor_kind
== CtorKind
::Fn
{
931 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
932 self.encode_variances_of(def_id
);
934 self.encode_generics(def_id
);
935 self.encode_explicit_predicates(def_id
);
936 self.encode_inferred_outlives(def_id
);
937 self.encode_optimized_mir(def_id
.expect_local());
938 self.encode_promoted_mir(def_id
.expect_local());
941 fn encode_generics(&mut self, def_id
: DefId
) {
942 debug
!("EncodeContext::encode_generics({:?})", def_id
);
943 record
!(self.tables
.generics
[def_id
] <- self.tcx
.generics_of(def_id
));
946 fn encode_explicit_predicates(&mut self, def_id
: DefId
) {
947 debug
!("EncodeContext::encode_explicit_predicates({:?})", def_id
);
948 record
!(self.tables
.explicit_predicates
[def_id
] <-
949 self.tcx
.explicit_predicates_of(def_id
));
952 fn encode_inferred_outlives(&mut self, def_id
: DefId
) {
953 debug
!("EncodeContext::encode_inferred_outlives({:?})", def_id
);
954 let inferred_outlives
= self.tcx
.inferred_outlives_of(def_id
);
955 if !inferred_outlives
.is_empty() {
956 record
!(self.tables
.inferred_outlives
[def_id
] <- inferred_outlives
);
960 fn encode_super_predicates(&mut self, def_id
: DefId
) {
961 debug
!("EncodeContext::encode_super_predicates({:?})", def_id
);
962 record
!(self.tables
.super_predicates
[def_id
] <- self.tcx
.super_predicates_of(def_id
));
965 fn encode_info_for_trait_item(&mut self, def_id
: DefId
) {
966 debug
!("EncodeContext::encode_info_for_trait_item({:?})", def_id
);
969 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
970 let ast_item
= tcx
.hir().expect_trait_item(hir_id
);
971 let trait_item
= tcx
.associated_item(def_id
);
973 let container
= match trait_item
.defaultness
{
974 hir
::Defaultness
::Default { has_value: true }
=> AssocContainer
::TraitWithDefault
,
975 hir
::Defaultness
::Default { has_value: false }
=> AssocContainer
::TraitRequired
,
976 hir
::Defaultness
::Final
=> span_bug
!(ast_item
.span
, "traits cannot have final items"),
979 record
!(self.tables
.kind
[def_id
] <- match trait_item
.kind
{
980 ty
::AssocKind
::Const
=> {
981 let rendered
= rustc_hir_pretty
::to_string(
982 &(&self.tcx
.hir() as &dyn intravisit
::Map
<'_
>),
983 |s
| s
.print_trait_item(ast_item
)
985 let rendered_const
= self.lazy(RenderedConst(rendered
));
987 EntryKind
::AssocConst(
993 ty
::AssocKind
::Fn
=> {
994 let fn_data
= if let hir
::TraitItemKind
::Fn(m_sig
, m
) = &ast_item
.kind
{
995 let param_names
= match *m
{
996 hir
::TraitFn
::Required(ref names
) => {
997 self.encode_fn_param_names(names
)
999 hir
::TraitFn
::Provided(body
) => {
1000 self.encode_fn_param_names_for_body(body
)
1004 asyncness
: m_sig
.header
.asyncness
,
1005 constness
: hir
::Constness
::NotConst
,
1011 EntryKind
::AssocFn(self.lazy(AssocFnData
{
1014 has_self
: trait_item
.fn_has_self_parameter
,
1017 ty
::AssocKind
::Type
=> EntryKind
::AssocType(container
),
1019 record
!(self.tables
.visibility
[def_id
] <- trait_item
.vis
);
1020 record
!(self.tables
.span
[def_id
] <- ast_item
.span
);
1021 record
!(self.tables
.attributes
[def_id
] <- ast_item
.attrs
);
1022 self.encode_ident_span(def_id
, ast_item
.ident
);
1023 self.encode_stability(def_id
);
1024 self.encode_const_stability(def_id
);
1025 self.encode_deprecation(def_id
);
1026 match trait_item
.kind
{
1027 ty
::AssocKind
::Const
| ty
::AssocKind
::Fn
=> {
1028 self.encode_item_type(def_id
);
1030 ty
::AssocKind
::Type
=> {
1031 if trait_item
.defaultness
.has_value() {
1032 self.encode_item_type(def_id
);
1036 if trait_item
.kind
== ty
::AssocKind
::Fn
{
1037 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1038 self.encode_variances_of(def_id
);
1040 self.encode_generics(def_id
);
1041 self.encode_explicit_predicates(def_id
);
1042 self.encode_inferred_outlives(def_id
);
1044 // This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
1045 self.encode_optimized_mir(def_id
.expect_local());
1046 self.encode_promoted_mir(def_id
.expect_local());
1049 fn metadata_output_only(&self) -> bool
{
1050 // MIR optimisation can be skipped when we're just interested in the metadata.
1051 !self.tcx
.sess
.opts
.output_types
.should_codegen()
1054 fn encode_info_for_impl_item(&mut self, def_id
: DefId
) {
1055 debug
!("EncodeContext::encode_info_for_impl_item({:?})", def_id
);
1058 let hir_id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
1059 let ast_item
= self.tcx
.hir().expect_impl_item(hir_id
);
1060 let impl_item
= self.tcx
.associated_item(def_id
);
1062 let container
= match impl_item
.defaultness
{
1063 hir
::Defaultness
::Default { has_value: true }
=> AssocContainer
::ImplDefault
,
1064 hir
::Defaultness
::Final
=> AssocContainer
::ImplFinal
,
1065 hir
::Defaultness
::Default { has_value: false }
=> {
1066 span_bug
!(ast_item
.span
, "impl items always have values (currently)")
1070 record
!(self.tables
.kind
[def_id
] <- match impl_item
.kind
{
1071 ty
::AssocKind
::Const
=> {
1072 if let hir
::ImplItemKind
::Const(_
, body_id
) = ast_item
.kind
{
1073 let qualifs
= self.tcx
.at(ast_item
.span
).mir_const_qualif(def_id
);
1075 EntryKind
::AssocConst(
1078 self.encode_rendered_const_for_body(body_id
))
1083 ty
::AssocKind
::Fn
=> {
1084 let fn_data
= if let hir
::ImplItemKind
::Fn(ref sig
, body
) = ast_item
.kind
{
1086 asyncness
: sig
.header
.asyncness
,
1087 constness
: sig
.header
.constness
,
1088 param_names
: self.encode_fn_param_names_for_body(body
),
1093 EntryKind
::AssocFn(self.lazy(AssocFnData
{
1096 has_self
: impl_item
.fn_has_self_parameter
,
1099 ty
::AssocKind
::Type
=> EntryKind
::AssocType(container
)
1101 record
!(self.tables
.visibility
[def_id
] <- impl_item
.vis
);
1102 record
!(self.tables
.span
[def_id
] <- ast_item
.span
);
1103 record
!(self.tables
.attributes
[def_id
] <- ast_item
.attrs
);
1104 self.encode_ident_span(def_id
, impl_item
.ident
);
1105 self.encode_stability(def_id
);
1106 self.encode_const_stability(def_id
);
1107 self.encode_deprecation(def_id
);
1108 self.encode_item_type(def_id
);
1109 if impl_item
.kind
== ty
::AssocKind
::Fn
{
1110 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1111 self.encode_variances_of(def_id
);
1113 self.encode_generics(def_id
);
1114 self.encode_explicit_predicates(def_id
);
1115 self.encode_inferred_outlives(def_id
);
1117 // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.
1119 let mir
= match ast_item
.kind
{
1120 hir
::ImplItemKind
::Const(..) => true,
1121 hir
::ImplItemKind
::Fn(ref sig
, _
) => {
1122 let generics
= self.tcx
.generics_of(def_id
);
1123 let needs_inline
= (generics
.requires_monomorphization(self.tcx
)
1124 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
1125 && !self.metadata_output_only();
1126 let is_const_fn
= sig
.header
.constness
== hir
::Constness
::Const
;
1127 let always_encode_mir
= self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
1128 needs_inline
|| is_const_fn
|| always_encode_mir
1130 hir
::ImplItemKind
::TyAlias(..) => false,
1133 self.encode_optimized_mir(def_id
.expect_local());
1134 self.encode_promoted_mir(def_id
.expect_local());
1138 fn encode_fn_param_names_for_body(&mut self, body_id
: hir
::BodyId
) -> Lazy
<[Ident
]> {
1139 self.lazy(self.tcx
.hir().body_param_names(body_id
))
1142 fn encode_fn_param_names(&mut self, param_names
: &[Ident
]) -> Lazy
<[Ident
]> {
1143 self.lazy(param_names
.iter())
1146 fn encode_optimized_mir(&mut self, def_id
: LocalDefId
) {
1147 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
1148 if self.tcx
.mir_keys(LOCAL_CRATE
).contains(&def_id
) {
1149 record
!(self.tables
.mir
[def_id
.to_def_id()] <- self.tcx
.optimized_mir(def_id
));
1151 let unused
= self.tcx
.unused_generic_params(def_id
);
1152 if !unused
.is_empty() {
1153 record
!(self.tables
.unused_generic_params
[def_id
.to_def_id()] <- unused
);
1156 let abstract_const
= self.tcx
.mir_abstract_const(def_id
);
1157 if let Ok(Some(abstract_const
)) = abstract_const
{
1158 record
!(self.tables
.mir_abstract_consts
[def_id
.to_def_id()] <- abstract_const
);
1163 fn encode_promoted_mir(&mut self, def_id
: LocalDefId
) {
1164 debug
!("EncodeContext::encode_promoted_mir({:?})", def_id
);
1165 if self.tcx
.mir_keys(LOCAL_CRATE
).contains(&def_id
) {
1166 record
!(self.tables
.promoted_mir
[def_id
.to_def_id()] <- self.tcx
.promoted_mir(def_id
));
1170 // Encodes the inherent implementations of a structure, enumeration, or trait.
1171 fn encode_inherent_implementations(&mut self, def_id
: DefId
) {
1172 debug
!("EncodeContext::encode_inherent_implementations({:?})", def_id
);
1173 let implementations
= self.tcx
.inherent_impls(def_id
);
1174 if !implementations
.is_empty() {
1175 record
!(self.tables
.inherent_impls
[def_id
] <- implementations
.iter().map(|&def_id
| {
1176 assert
!(def_id
.is_local());
1182 fn encode_stability(&mut self, def_id
: DefId
) {
1183 debug
!("EncodeContext::encode_stability({:?})", def_id
);
1185 // The query lookup can take a measurable amount of time in crates with many items. Check if
1186 // the stability attributes are even enabled before using their queries.
1187 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.debugging_opts
.force_unstable_if_unmarked
{
1188 if let Some(stab
) = self.tcx
.lookup_stability(def_id
) {
1189 record
!(self.tables
.stability
[def_id
] <- stab
)
1194 fn encode_const_stability(&mut self, def_id
: DefId
) {
1195 debug
!("EncodeContext::encode_const_stability({:?})", def_id
);
1197 // The query lookup can take a measurable amount of time in crates with many items. Check if
1198 // the stability attributes are even enabled before using their queries.
1199 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.debugging_opts
.force_unstable_if_unmarked
{
1200 if let Some(stab
) = self.tcx
.lookup_const_stability(def_id
) {
1201 record
!(self.tables
.const_stability
[def_id
] <- stab
)
1206 fn encode_deprecation(&mut self, def_id
: DefId
) {
1207 debug
!("EncodeContext::encode_deprecation({:?})", def_id
);
1208 if let Some(depr
) = self.tcx
.lookup_deprecation(def_id
) {
1209 record
!(self.tables
.deprecation
[def_id
] <- depr
);
1213 fn encode_rendered_const_for_body(&mut self, body_id
: hir
::BodyId
) -> Lazy
<RenderedConst
> {
1214 let hir
= self.tcx
.hir();
1215 let body
= hir
.body(body_id
);
1216 let rendered
= rustc_hir_pretty
::to_string(&(&hir
as &dyn intravisit
::Map
<'_
>), |s
| {
1217 s
.print_expr(&body
.value
)
1219 let rendered_const
= &RenderedConst(rendered
);
1220 self.lazy(rendered_const
)
1223 fn encode_info_for_item(&mut self, def_id
: DefId
, item
: &'tcx hir
::Item
<'tcx
>) {
1226 debug
!("EncodeContext::encode_info_for_item({:?})", def_id
);
1228 self.encode_ident_span(def_id
, item
.ident
);
1230 record
!(self.tables
.kind
[def_id
] <- match item
.kind
{
1231 hir
::ItemKind
::Static(_
, hir
::Mutability
::Mut
, _
) => EntryKind
::MutStatic
,
1232 hir
::ItemKind
::Static(_
, hir
::Mutability
::Not
, _
) => EntryKind
::ImmStatic
,
1233 hir
::ItemKind
::Const(_
, body_id
) => {
1234 let qualifs
= self.tcx
.at(item
.span
).mir_const_qualif(def_id
);
1237 self.encode_rendered_const_for_body(body_id
)
1240 hir
::ItemKind
::Fn(ref sig
, .., body
) => {
1242 asyncness
: sig
.header
.asyncness
,
1243 constness
: sig
.header
.constness
,
1244 param_names
: self.encode_fn_param_names_for_body(body
),
1247 EntryKind
::Fn(self.lazy(data
))
1249 hir
::ItemKind
::Mod(ref m
) => {
1250 return self.encode_info_for_mod(item
.hir_id
, m
, &item
.attrs
, &item
.vis
);
1252 hir
::ItemKind
::ForeignMod(_
) => EntryKind
::ForeignMod
,
1253 hir
::ItemKind
::GlobalAsm(..) => EntryKind
::GlobalAsm
,
1254 hir
::ItemKind
::TyAlias(..) => EntryKind
::Type
,
1255 hir
::ItemKind
::OpaqueTy(..) => EntryKind
::OpaqueTy
,
1256 hir
::ItemKind
::Enum(..) => EntryKind
::Enum(self.tcx
.adt_def(def_id
).repr
),
1257 hir
::ItemKind
::Struct(ref struct_def
, _
) => {
1258 let adt_def
= self.tcx
.adt_def(def_id
);
1259 let variant
= adt_def
.non_enum_variant();
1261 // Encode def_ids for each field and method
1262 // for methods, write all the stuff get_trait_method
1264 let ctor
= struct_def
.ctor_hir_id().map(|ctor_hir_id
| {
1265 self.tcx
.hir().local_def_id(ctor_hir_id
).local_def_index
1268 EntryKind
::Struct(self.lazy(VariantData
{
1269 ctor_kind
: variant
.ctor_kind
,
1270 discr
: variant
.discr
,
1272 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1275 hir
::ItemKind
::Union(..) => {
1276 let adt_def
= self.tcx
.adt_def(def_id
);
1277 let variant
= adt_def
.non_enum_variant();
1279 EntryKind
::Union(self.lazy(VariantData
{
1280 ctor_kind
: variant
.ctor_kind
,
1281 discr
: variant
.discr
,
1283 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1286 hir
::ItemKind
::Impl { defaultness, .. }
=> {
1287 let trait_ref
= self.tcx
.impl_trait_ref(def_id
);
1288 let polarity
= self.tcx
.impl_polarity(def_id
);
1289 let parent
= if let Some(trait_ref
) = trait_ref
{
1290 let trait_def
= self.tcx
.trait_def(trait_ref
.def_id
);
1291 trait_def
.ancestors(self.tcx
, def_id
).ok()
1292 .and_then(|mut an
| an
.nth(1).and_then(|node
| {
1294 specialization_graph
::Node
::Impl(parent
) => Some(parent
),
1302 // if this is an impl of `CoerceUnsized`, create its
1303 // "unsized info", else just store None
1304 let coerce_unsized_info
=
1305 trait_ref
.and_then(|t
| {
1306 if Some(t
.def_id
) == self.tcx
.lang_items().coerce_unsized_trait() {
1307 Some(self.tcx
.at(item
.span
).coerce_unsized_info(def_id
))
1313 let data
= ImplData
{
1316 parent_impl
: parent
,
1317 coerce_unsized_info
,
1320 EntryKind
::Impl(self.lazy(data
))
1322 hir
::ItemKind
::Trait(..) => {
1323 let trait_def
= self.tcx
.trait_def(def_id
);
1324 let data
= TraitData
{
1325 unsafety
: trait_def
.unsafety
,
1326 paren_sugar
: trait_def
.paren_sugar
,
1327 has_auto_impl
: self.tcx
.trait_is_auto(def_id
),
1328 is_marker
: trait_def
.is_marker
,
1329 specialization_kind
: trait_def
.specialization_kind
,
1332 EntryKind
::Trait(self.lazy(data
))
1334 hir
::ItemKind
::TraitAlias(..) => EntryKind
::TraitAlias
,
1335 hir
::ItemKind
::ExternCrate(_
) |
1336 hir
::ItemKind
::Use(..) => bug
!("cannot encode info for item {:?}", item
),
1338 record
!(self.tables
.visibility
[def_id
] <-
1339 ty
::Visibility
::from_hir(&item
.vis
, item
.hir_id
, tcx
));
1340 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
1341 record
!(self.tables
.attributes
[def_id
] <- item
.attrs
);
1342 // FIXME(eddyb) there should be a nicer way to do this.
1344 hir
::ItemKind
::ForeignMod(ref fm
) => record
!(self.tables
.children
[def_id
] <-
1347 .map(|foreign_item
| tcx
.hir().local_def_id(
1348 foreign_item
.hir_id
).local_def_index
)
1350 hir
::ItemKind
::Enum(..) => record
!(self.tables
.children
[def_id
] <-
1351 self.tcx
.adt_def(def_id
).variants
.iter().map(|v
| {
1352 assert
!(v
.def_id
.is_local());
1356 hir
::ItemKind
::Struct(..) | hir
::ItemKind
::Union(..) => {
1357 record
!(self.tables
.children
[def_id
] <-
1358 self.tcx
.adt_def(def_id
).non_enum_variant().fields
.iter().map(|f
| {
1359 assert
!(f
.did
.is_local());
1364 hir
::ItemKind
::Impl { .. }
| hir
::ItemKind
::Trait(..) => {
1365 let associated_item_def_ids
= self.tcx
.associated_item_def_ids(def_id
);
1366 record
!(self.tables
.children
[def_id
] <-
1367 associated_item_def_ids
.iter().map(|&def_id
| {
1368 assert
!(def_id
.is_local());
1375 self.encode_stability(def_id
);
1376 self.encode_const_stability(def_id
);
1377 self.encode_deprecation(def_id
);
1379 hir
::ItemKind
::Static(..)
1380 | hir
::ItemKind
::Const(..)
1381 | hir
::ItemKind
::Fn(..)
1382 | hir
::ItemKind
::TyAlias(..)
1383 | hir
::ItemKind
::OpaqueTy(..)
1384 | hir
::ItemKind
::Enum(..)
1385 | hir
::ItemKind
::Struct(..)
1386 | hir
::ItemKind
::Union(..)
1387 | hir
::ItemKind
::Impl { .. }
=> self.encode_item_type(def_id
),
1390 if let hir
::ItemKind
::Fn(..) = item
.kind
{
1391 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1393 if let hir
::ItemKind
::Impl { .. }
= item
.kind
{
1394 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(def_id
) {
1395 record
!(self.tables
.impl_trait_ref
[def_id
] <- trait_ref
);
1398 self.encode_inherent_implementations(def_id
);
1400 hir
::ItemKind
::Enum(..)
1401 | hir
::ItemKind
::Struct(..)
1402 | hir
::ItemKind
::Union(..)
1403 | hir
::ItemKind
::Fn(..) => self.encode_variances_of(def_id
),
1407 hir
::ItemKind
::Static(..)
1408 | hir
::ItemKind
::Const(..)
1409 | hir
::ItemKind
::Fn(..)
1410 | hir
::ItemKind
::TyAlias(..)
1411 | hir
::ItemKind
::Enum(..)
1412 | hir
::ItemKind
::Struct(..)
1413 | hir
::ItemKind
::Union(..)
1414 | hir
::ItemKind
::Impl { .. }
1415 | hir
::ItemKind
::OpaqueTy(..)
1416 | hir
::ItemKind
::Trait(..)
1417 | hir
::ItemKind
::TraitAlias(..) => {
1418 self.encode_generics(def_id
);
1419 self.encode_explicit_predicates(def_id
);
1420 self.encode_inferred_outlives(def_id
);
1425 hir
::ItemKind
::Trait(..) | hir
::ItemKind
::TraitAlias(..) => {
1426 self.encode_super_predicates(def_id
);
1431 // The following part should be kept in sync with `PrefetchVisitor.visit_item`.
1433 let mir
= match item
.kind
{
1434 hir
::ItemKind
::Static(..) | hir
::ItemKind
::Const(..) => true,
1435 hir
::ItemKind
::Fn(ref sig
, ..) => {
1436 let generics
= tcx
.generics_of(def_id
);
1437 let needs_inline
= (generics
.requires_monomorphization(tcx
)
1438 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
1439 && !self.metadata_output_only();
1440 let always_encode_mir
= self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
1441 needs_inline
|| sig
.header
.constness
== hir
::Constness
::Const
|| always_encode_mir
1446 self.encode_optimized_mir(def_id
.expect_local());
1447 self.encode_promoted_mir(def_id
.expect_local());
1451 /// Serialize the text of exported macros
1452 fn encode_info_for_macro_def(&mut self, macro_def
: &hir
::MacroDef
<'_
>) {
1453 let def_id
= self.tcx
.hir().local_def_id(macro_def
.hir_id
).to_def_id();
1454 record
!(self.tables
.kind
[def_id
] <- EntryKind
::MacroDef(self.lazy(macro_def
.ast
.clone())));
1455 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::Public
);
1456 record
!(self.tables
.span
[def_id
] <- macro_def
.span
);
1457 record
!(self.tables
.attributes
[def_id
] <- macro_def
.attrs
);
1458 self.encode_ident_span(def_id
, macro_def
.ident
);
1459 self.encode_stability(def_id
);
1460 self.encode_deprecation(def_id
);
1463 fn encode_info_for_generic_param(&mut self, def_id
: DefId
, kind
: EntryKind
, encode_type
: bool
) {
1464 record
!(self.tables
.kind
[def_id
] <- kind
);
1465 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::Public
);
1466 record
!(self.tables
.span
[def_id
] <- self.tcx
.def_span(def_id
));
1468 self.encode_item_type(def_id
);
1472 fn encode_info_for_closure(&mut self, def_id
: LocalDefId
) {
1473 debug
!("EncodeContext::encode_info_for_closure({:?})", def_id
);
1475 // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
1476 // including on the signature, which is inferred in `typeck.
1477 let hir_id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
);
1478 let ty
= self.tcx
.typeck(def_id
).node_type(hir_id
);
1480 record
!(self.tables
.kind
[def_id
.to_def_id()] <- match ty
.kind() {
1481 ty
::Generator(..) => {
1482 let data
= self.tcx
.generator_kind(def_id
).unwrap();
1483 EntryKind
::Generator(data
)
1486 ty
::Closure(..) => EntryKind
::Closure
,
1488 _
=> bug
!("closure that is neither generator nor closure"),
1490 record
!(self.tables
.visibility
[def_id
.to_def_id()] <- ty
::Visibility
::Public
);
1491 record
!(self.tables
.span
[def_id
.to_def_id()] <- self.tcx
.def_span(def_id
));
1492 record
!(self.tables
.attributes
[def_id
.to_def_id()] <- &self.tcx
.get_attrs(def_id
.to_def_id())[..]);
1493 self.encode_item_type(def_id
.to_def_id());
1494 if let ty
::Closure(def_id
, substs
) = *ty
.kind() {
1495 record
!(self.tables
.fn_sig
[def_id
] <- substs
.as_closure().sig());
1497 self.encode_generics(def_id
.to_def_id());
1498 self.encode_optimized_mir(def_id
);
1499 self.encode_promoted_mir(def_id
);
1502 fn encode_info_for_anon_const(&mut self, def_id
: LocalDefId
) {
1503 debug
!("EncodeContext::encode_info_for_anon_const({:?})", def_id
);
1504 let id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
);
1505 let body_id
= self.tcx
.hir().body_owned_by(id
);
1506 let const_data
= self.encode_rendered_const_for_body(body_id
);
1507 let qualifs
= self.tcx
.mir_const_qualif(def_id
);
1509 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::AnonConst(qualifs
, const_data
));
1510 record
!(self.tables
.visibility
[def_id
.to_def_id()] <- ty
::Visibility
::Public
);
1511 record
!(self.tables
.span
[def_id
.to_def_id()] <- self.tcx
.def_span(def_id
));
1512 self.encode_item_type(def_id
.to_def_id());
1513 self.encode_generics(def_id
.to_def_id());
1514 self.encode_explicit_predicates(def_id
.to_def_id());
1515 self.encode_inferred_outlives(def_id
.to_def_id());
1516 self.encode_optimized_mir(def_id
);
1517 self.encode_promoted_mir(def_id
);
1520 fn encode_native_libraries(&mut self) -> Lazy
<[NativeLib
]> {
1521 empty_proc_macro
!(self);
1522 let used_libraries
= self.tcx
.native_libraries(LOCAL_CRATE
);
1523 self.lazy(used_libraries
.iter().cloned())
1526 fn encode_foreign_modules(&mut self) -> Lazy
<[ForeignModule
]> {
1527 empty_proc_macro
!(self);
1528 let foreign_modules
= self.tcx
.foreign_modules(LOCAL_CRATE
);
1529 self.lazy(foreign_modules
.iter().cloned())
1532 fn encode_hygiene(&mut self) -> (SyntaxContextTable
, ExpnDataTable
) {
1533 let mut syntax_contexts
: TableBuilder
<_
, _
> = Default
::default();
1534 let mut expn_data_table
: TableBuilder
<_
, _
> = Default
::default();
1536 let _
: Result
<(), !> = self.hygiene_ctxt
.encode(
1537 &mut (&mut *self, &mut syntax_contexts
, &mut expn_data_table
),
1538 |(this
, syntax_contexts
, _
), index
, ctxt_data
| {
1539 syntax_contexts
.set(index
, this
.lazy(ctxt_data
));
1542 |(this
, _
, expn_data_table
), index
, expn_data
| {
1543 expn_data_table
.set(index
, this
.lazy(expn_data
));
1548 (syntax_contexts
.encode(&mut self.opaque
), expn_data_table
.encode(&mut self.opaque
))
1551 fn encode_proc_macros(&mut self) -> Option
<ProcMacroData
> {
1552 let is_proc_macro
= self.tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
);
1555 let hir
= tcx
.hir();
1557 let proc_macro_decls_static
= tcx
.proc_macro_decls_static(LOCAL_CRATE
).unwrap().index
;
1558 let stability
= tcx
.lookup_stability(DefId
::local(CRATE_DEF_INDEX
)).copied();
1559 let macros
= self.lazy(hir
.krate().proc_macros
.iter().map(|p
| p
.owner
.local_def_index
));
1561 // Normally, this information is encoded when we walk the items
1562 // defined in this crate. However, we skip doing that for proc-macro crates,
1563 // so we manually encode just the information that we need
1564 for proc_macro
in &hir
.krate().proc_macros
{
1565 let id
= proc_macro
.owner
.local_def_index
;
1566 let span
= self.lazy(hir
.span(*proc_macro
));
1567 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1568 // so downstream crates need access to them.
1569 let attrs
= self.lazy(hir
.attrs(*proc_macro
));
1570 self.tables
.span
.set(id
, span
);
1571 self.tables
.attributes
.set(id
, attrs
);
1574 Some(ProcMacroData { proc_macro_decls_static, stability, macros }
)
1580 fn encode_crate_deps(&mut self) -> Lazy
<[CrateDep
]> {
1581 empty_proc_macro
!(self);
1582 let crates
= self.tcx
.crates();
1584 let mut deps
= crates
1587 let dep
= CrateDep
{
1588 name
: self.tcx
.original_crate_name(cnum
),
1589 hash
: self.tcx
.crate_hash(cnum
),
1590 host_hash
: self.tcx
.crate_host_hash(cnum
),
1591 kind
: self.tcx
.dep_kind(cnum
),
1592 extra_filename
: self.tcx
.extra_filename(cnum
),
1596 .collect
::<Vec
<_
>>();
1598 deps
.sort_by_key(|&(cnum
, _
)| cnum
);
1601 // Sanity-check the crate numbers
1602 let mut expected_cnum
= 1;
1603 for &(n
, _
) in &deps
{
1604 assert_eq
!(n
, CrateNum
::new(expected_cnum
));
1609 // We're just going to write a list of crate 'name-hash-version's, with
1610 // the assumption that they are numbered 1 to n.
1611 // FIXME (#2166): This is not nearly enough to support correct versioning
1612 // but is enough to get transitive crate dependencies working.
1613 self.lazy(deps
.iter().map(|&(_
, ref dep
)| dep
))
1616 fn encode_lib_features(&mut self) -> Lazy
<[(Symbol
, Option
<Symbol
>)]> {
1617 empty_proc_macro
!(self);
1619 let lib_features
= tcx
.lib_features();
1620 self.lazy(lib_features
.to_vec())
1623 fn encode_diagnostic_items(&mut self) -> Lazy
<[(Symbol
, DefIndex
)]> {
1624 empty_proc_macro
!(self);
1626 let diagnostic_items
= tcx
.diagnostic_items(LOCAL_CRATE
);
1627 self.lazy(diagnostic_items
.iter().map(|(&name
, def_id
)| (name
, def_id
.index
)))
1630 fn encode_lang_items(&mut self) -> Lazy
<[(DefIndex
, usize)]> {
1631 empty_proc_macro
!(self);
1633 let lang_items
= tcx
.lang_items();
1634 let lang_items
= lang_items
.items().iter();
1635 self.lazy(lang_items
.enumerate().filter_map(|(i
, &opt_def_id
)| {
1636 if let Some(def_id
) = opt_def_id
{
1637 if def_id
.is_local() {
1638 return Some((def_id
.index
, i
));
1645 fn encode_lang_items_missing(&mut self) -> Lazy
<[lang_items
::LangItem
]> {
1646 empty_proc_macro
!(self);
1648 self.lazy(&tcx
.lang_items().missing
)
1651 /// Encodes an index, mapping each trait to its (local) implementations.
1652 fn encode_impls(&mut self) -> Lazy
<[TraitImpls
]> {
1653 empty_proc_macro
!(self);
1654 debug
!("EncodeContext::encode_impls()");
1656 let mut visitor
= ImplVisitor { tcx, impls: FxHashMap::default() }
;
1657 tcx
.hir().krate().visit_all_item_likes(&mut visitor
);
1659 let mut all_impls
: Vec
<_
> = visitor
.impls
.into_iter().collect();
1661 // Bring everything into deterministic order for hashing
1662 all_impls
.sort_by_cached_key(|&(trait_def_id
, _
)| tcx
.def_path_hash(trait_def_id
));
1664 let all_impls
: Vec
<_
> = all_impls
1666 .map(|(trait_def_id
, mut impls
)| {
1667 // Bring everything into deterministic order for hashing
1668 impls
.sort_by_cached_key(|&(index
, _
)| {
1669 tcx
.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }
)
1673 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
1674 impls
: self.lazy(&impls
),
1679 self.lazy(&all_impls
)
1682 // Encodes all symbols exported from this crate into the metadata.
1684 // This pass is seeded off the reachability list calculated in the
1685 // middle::reachable module but filters out items that either don't have a
1686 // symbol associated with them (they weren't translated) or if they're an FFI
1687 // definition (as that's not defined in this crate).
1688 fn encode_exported_symbols(
1690 exported_symbols
: &[(ExportedSymbol
<'tcx
>, SymbolExportLevel
)],
1691 ) -> Lazy
<[(ExportedSymbol
<'tcx
>, SymbolExportLevel
)]> {
1692 empty_proc_macro
!(self);
1693 // The metadata symbol name is special. It should not show up in
1694 // downstream crates.
1695 let metadata_symbol_name
= SymbolName
::new(self.tcx
, &metadata_symbol_name(self.tcx
));
1700 .filter(|&&(ref exported_symbol
, _
)| match *exported_symbol
{
1701 ExportedSymbol
::NoDefId(symbol_name
) => symbol_name
!= metadata_symbol_name
,
1708 fn encode_dylib_dependency_formats(&mut self) -> Lazy
<[Option
<LinkagePreference
>]> {
1709 empty_proc_macro
!(self);
1710 let formats
= self.tcx
.dependency_formats(LOCAL_CRATE
);
1711 for (ty
, arr
) in formats
.iter() {
1712 if *ty
!= CrateType
::Dylib
{
1715 return self.lazy(arr
.iter().map(|slot
| match *slot
{
1716 Linkage
::NotLinked
| Linkage
::IncludedFromDylib
=> None
,
1718 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
1719 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
1725 fn encode_info_for_foreign_item(&mut self, def_id
: DefId
, nitem
: &hir
::ForeignItem
<'_
>) {
1728 debug
!("EncodeContext::encode_info_for_foreign_item({:?})", def_id
);
1730 record
!(self.tables
.kind
[def_id
] <- match nitem
.kind
{
1731 hir
::ForeignItemKind
::Fn(_
, ref names
, _
) => {
1733 asyncness
: hir
::IsAsync
::NotAsync
,
1734 constness
: if self.tcx
.is_const_fn_raw(def_id
) {
1735 hir
::Constness
::Const
1737 hir
::Constness
::NotConst
1739 param_names
: self.encode_fn_param_names(names
),
1741 EntryKind
::ForeignFn(self.lazy(data
))
1743 hir
::ForeignItemKind
::Static(_
, hir
::Mutability
::Mut
) => EntryKind
::ForeignMutStatic
,
1744 hir
::ForeignItemKind
::Static(_
, hir
::Mutability
::Not
) => EntryKind
::ForeignImmStatic
,
1745 hir
::ForeignItemKind
::Type
=> EntryKind
::ForeignType
,
1747 record
!(self.tables
.visibility
[def_id
] <-
1748 ty
::Visibility
::from_hir(&nitem
.vis
, nitem
.hir_id
, self.tcx
));
1749 record
!(self.tables
.span
[def_id
] <- nitem
.span
);
1750 record
!(self.tables
.attributes
[def_id
] <- nitem
.attrs
);
1751 self.encode_ident_span(def_id
, nitem
.ident
);
1752 self.encode_stability(def_id
);
1753 self.encode_const_stability(def_id
);
1754 self.encode_deprecation(def_id
);
1755 self.encode_item_type(def_id
);
1756 self.encode_inherent_implementations(def_id
);
1757 if let hir
::ForeignItemKind
::Fn(..) = nitem
.kind
{
1758 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1759 self.encode_variances_of(def_id
);
1761 self.encode_generics(def_id
);
1762 self.encode_explicit_predicates(def_id
);
1763 self.encode_inferred_outlives(def_id
);
1767 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
1768 impl Visitor
<'tcx
> for EncodeContext
<'a
, 'tcx
> {
1769 type Map
= Map
<'tcx
>;
1771 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
1772 NestedVisitorMap
::OnlyBodies(self.tcx
.hir())
1774 fn visit_expr(&mut self, ex
: &'tcx hir
::Expr
<'tcx
>) {
1775 intravisit
::walk_expr(self, ex
);
1776 self.encode_info_for_expr(ex
);
1778 fn visit_anon_const(&mut self, c
: &'tcx AnonConst
) {
1779 intravisit
::walk_anon_const(self, c
);
1780 let def_id
= self.tcx
.hir().local_def_id(c
.hir_id
);
1781 self.encode_info_for_anon_const(def_id
);
1783 fn visit_item(&mut self, item
: &'tcx hir
::Item
<'tcx
>) {
1784 intravisit
::walk_item(self, item
);
1785 let def_id
= self.tcx
.hir().local_def_id(item
.hir_id
);
1787 hir
::ItemKind
::ExternCrate(_
) | hir
::ItemKind
::Use(..) => {}
// ignore these
1788 _
=> self.encode_info_for_item(def_id
.to_def_id(), item
),
1790 self.encode_addl_info_for_item(item
);
1792 fn visit_foreign_item(&mut self, ni
: &'tcx hir
::ForeignItem
<'tcx
>) {
1793 intravisit
::walk_foreign_item(self, ni
);
1794 let def_id
= self.tcx
.hir().local_def_id(ni
.hir_id
);
1795 self.encode_info_for_foreign_item(def_id
.to_def_id(), ni
);
1797 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
<'tcx
>) {
1798 intravisit
::walk_generics(self, generics
);
1799 self.encode_info_for_generics(generics
);
1801 fn visit_macro_def(&mut self, macro_def
: &'tcx hir
::MacroDef
<'tcx
>) {
1802 self.encode_info_for_macro_def(macro_def
);
1806 impl EncodeContext
<'a
, 'tcx
> {
1807 fn encode_fields(&mut self, adt_def
: &ty
::AdtDef
) {
1808 for (variant_index
, variant
) in adt_def
.variants
.iter_enumerated() {
1809 for (field_index
, _field
) in variant
.fields
.iter().enumerate() {
1810 self.encode_field(adt_def
, variant_index
, field_index
);
1815 fn encode_info_for_generics(&mut self, generics
: &hir
::Generics
<'tcx
>) {
1816 for param
in generics
.params
{
1817 let def_id
= self.tcx
.hir().local_def_id(param
.hir_id
);
1819 GenericParamKind
::Lifetime { .. }
=> continue,
1820 GenericParamKind
::Type { ref default, .. }
=> {
1821 self.encode_info_for_generic_param(
1823 EntryKind
::TypeParam
,
1826 if default.is_some() {
1827 self.encode_stability(def_id
.to_def_id());
1830 GenericParamKind
::Const { .. }
=> {
1831 self.encode_info_for_generic_param(
1833 EntryKind
::ConstParam
,
1836 // FIXME(const_generics:defaults)
1842 fn encode_info_for_expr(&mut self, expr
: &hir
::Expr
<'_
>) {
1843 if let hir
::ExprKind
::Closure(..) = expr
.kind
{
1844 let def_id
= self.tcx
.hir().local_def_id(expr
.hir_id
);
1845 self.encode_info_for_closure(def_id
);
1849 fn encode_ident_span(&mut self, def_id
: DefId
, ident
: Ident
) {
1850 record
!(self.tables
.ident_span
[def_id
] <- ident
.span
);
1853 /// In some cases, along with the item itself, we also
1854 /// encode some sub-items. Usually we want some info from the item
1855 /// so it's easier to do that here then to wait until we would encounter
1856 /// normally in the visitor walk.
1857 fn encode_addl_info_for_item(&mut self, item
: &hir
::Item
<'_
>) {
1858 let def_id
= self.tcx
.hir().local_def_id(item
.hir_id
);
1860 hir
::ItemKind
::Static(..)
1861 | hir
::ItemKind
::Const(..)
1862 | hir
::ItemKind
::Fn(..)
1863 | hir
::ItemKind
::Mod(..)
1864 | hir
::ItemKind
::ForeignMod(..)
1865 | hir
::ItemKind
::GlobalAsm(..)
1866 | hir
::ItemKind
::ExternCrate(..)
1867 | hir
::ItemKind
::Use(..)
1868 | hir
::ItemKind
::TyAlias(..)
1869 | hir
::ItemKind
::OpaqueTy(..)
1870 | hir
::ItemKind
::TraitAlias(..) => {
1871 // no sub-item recording needed in these cases
1873 hir
::ItemKind
::Enum(..) => {
1874 let def
= self.tcx
.adt_def(def_id
.to_def_id());
1875 self.encode_fields(def
);
1877 for (i
, variant
) in def
.variants
.iter_enumerated() {
1878 self.encode_enum_variant_info(def
, i
);
1880 if let Some(_ctor_def_id
) = variant
.ctor_def_id
{
1881 self.encode_enum_variant_ctor(def
, i
);
1885 hir
::ItemKind
::Struct(ref struct_def
, _
) => {
1886 let def
= self.tcx
.adt_def(def_id
.to_def_id());
1887 self.encode_fields(def
);
1889 // If the struct has a constructor, encode it.
1890 if let Some(ctor_hir_id
) = struct_def
.ctor_hir_id() {
1891 let ctor_def_id
= self.tcx
.hir().local_def_id(ctor_hir_id
);
1892 self.encode_struct_ctor(def
, ctor_def_id
.to_def_id());
1895 hir
::ItemKind
::Union(..) => {
1896 let def
= self.tcx
.adt_def(def_id
.to_def_id());
1897 self.encode_fields(def
);
1899 hir
::ItemKind
::Impl { .. }
=> {
1900 for &trait_item_def_id
in
1901 self.tcx
.associated_item_def_ids(def_id
.to_def_id()).iter()
1903 self.encode_info_for_impl_item(trait_item_def_id
);
1906 hir
::ItemKind
::Trait(..) => {
1907 for &item_def_id
in self.tcx
.associated_item_def_ids(def_id
.to_def_id()).iter() {
1908 self.encode_info_for_trait_item(item_def_id
);
1915 struct ImplVisitor
<'tcx
> {
1917 impls
: FxHashMap
<DefId
, Vec
<(DefIndex
, Option
<ty
::fast_reject
::SimplifiedType
>)>>,
1920 impl<'tcx
, 'v
> ItemLikeVisitor
<'v
> for ImplVisitor
<'tcx
> {
1921 fn visit_item(&mut self, item
: &hir
::Item
<'_
>) {
1922 if let hir
::ItemKind
::Impl { .. }
= item
.kind
{
1923 let impl_id
= self.tcx
.hir().local_def_id(item
.hir_id
);
1924 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(impl_id
.to_def_id()) {
1925 let simplified_self_ty
=
1926 ty
::fast_reject
::simplify_type(self.tcx
, trait_ref
.self_ty(), false);
1929 .entry(trait_ref
.def_id
)
1931 .push((impl_id
.local_def_index
, simplified_self_ty
));
1936 fn visit_trait_item(&mut self, _trait_item
: &'v hir
::TraitItem
<'v
>) {}
1938 fn visit_impl_item(&mut self, _impl_item
: &'v hir
::ImplItem
<'v
>) {
1939 // handled in `visit_item` above
1943 /// Used to prefetch queries which will be needed later by metadata encoding.
1944 /// Only a subset of the queries are actually prefetched to keep this code smaller.
1945 struct PrefetchVisitor
<'tcx
> {
1947 mir_keys
: &'tcx FxHashSet
<LocalDefId
>,
1950 impl<'tcx
> PrefetchVisitor
<'tcx
> {
1951 fn prefetch_mir(&self, def_id
: LocalDefId
) {
1952 if self.mir_keys
.contains(&def_id
) {
1953 self.tcx
.ensure().optimized_mir(def_id
);
1954 self.tcx
.ensure().promoted_mir(def_id
);
1959 impl<'tcx
, 'v
> ParItemLikeVisitor
<'v
> for PrefetchVisitor
<'tcx
> {
1960 fn visit_item(&self, item
: &hir
::Item
<'_
>) {
1961 // This should be kept in sync with `encode_info_for_item`.
1964 hir
::ItemKind
::Static(..) | hir
::ItemKind
::Const(..) => {
1965 self.prefetch_mir(tcx
.hir().local_def_id(item
.hir_id
))
1967 hir
::ItemKind
::Fn(ref sig
, ..) => {
1968 let def_id
= tcx
.hir().local_def_id(item
.hir_id
);
1969 let generics
= tcx
.generics_of(def_id
.to_def_id());
1970 let needs_inline
= generics
.requires_monomorphization(tcx
)
1971 || tcx
.codegen_fn_attrs(def_id
.to_def_id()).requests_inline();
1972 if needs_inline
|| sig
.header
.constness
== hir
::Constness
::Const
{
1973 self.prefetch_mir(def_id
)
1980 fn visit_trait_item(&self, trait_item
: &'v hir
::TraitItem
<'v
>) {
1981 // This should be kept in sync with `encode_info_for_trait_item`.
1982 self.prefetch_mir(self.tcx
.hir().local_def_id(trait_item
.hir_id
));
1985 fn visit_impl_item(&self, impl_item
: &'v hir
::ImplItem
<'v
>) {
1986 // This should be kept in sync with `encode_info_for_impl_item`.
1988 match impl_item
.kind
{
1989 hir
::ImplItemKind
::Const(..) => {
1990 self.prefetch_mir(tcx
.hir().local_def_id(impl_item
.hir_id
))
1992 hir
::ImplItemKind
::Fn(ref sig
, _
) => {
1993 let def_id
= tcx
.hir().local_def_id(impl_item
.hir_id
);
1994 let generics
= tcx
.generics_of(def_id
.to_def_id());
1995 let needs_inline
= generics
.requires_monomorphization(tcx
)
1996 || tcx
.codegen_fn_attrs(def_id
.to_def_id()).requests_inline();
1997 let is_const_fn
= sig
.header
.constness
== hir
::Constness
::Const
;
1998 if needs_inline
|| is_const_fn
{
1999 self.prefetch_mir(def_id
)
2002 hir
::ImplItemKind
::TyAlias(..) => (),
2007 // NOTE(eddyb) The following comment was preserved for posterity, even
2008 // though it's no longer relevant as EBML (which uses nested & tagged
2009 // "documents") was replaced with a scheme that can't go out of bounds.
2011 // And here we run into yet another obscure archive bug: in which metadata
2012 // loaded from archives may have trailing garbage bytes. Awhile back one of
2013 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
2014 // and opt) by having ebml generate an out-of-bounds panic when looking at
2017 // Upon investigation it turned out that the metadata file inside of an rlib
2018 // (and ar archive) was being corrupted. Some compilations would generate a
2019 // metadata file which would end in a few extra bytes, while other
2020 // compilations would not have these extra bytes appended to the end. These
2021 // extra bytes were interpreted by ebml as an extra tag, so they ended up
2022 // being interpreted causing the out-of-bounds.
2024 // The root cause of why these extra bytes were appearing was never
2025 // discovered, and in the meantime the solution we're employing is to insert
2026 // the length of the metadata to the start of the metadata. Later on this
2027 // will allow us to slice the metadata to the precise length that we just
2028 // generated regardless of trailing bytes that end up in it.
2030 pub(super) fn encode_metadata(tcx
: TyCtxt
<'_
>) -> EncodedMetadata
{
2031 // Since encoding metadata is not in a query, and nothing is cached,
2032 // there's no need to do dep-graph tracking for any of it.
2033 tcx
.dep_graph
.assert_ignored();
2036 || encode_metadata_impl(tcx
),
2038 if tcx
.sess
.threads() == 1 {
2041 // Prefetch some queries used by metadata encoding.
2042 // This is not necessary for correctness, but is only done for performance reasons.
2043 // It can be removed if it turns out to cause trouble or be detrimental to performance.
2046 if !tcx
.sess
.opts
.output_types
.should_codegen() {
2047 // We won't emit MIR, so don't prefetch it.
2050 tcx
.hir().krate().par_visit_all_item_likes(&PrefetchVisitor
{
2052 mir_keys
: tcx
.mir_keys(LOCAL_CRATE
),
2055 || tcx
.exported_symbols(LOCAL_CRATE
),
2062 fn encode_metadata_impl(tcx
: TyCtxt
<'_
>) -> EncodedMetadata
{
2063 let mut encoder
= opaque
::Encoder
::new(vec
![]);
2064 encoder
.emit_raw_bytes(METADATA_HEADER
);
2066 // Will be filled with the root position after encoding everything.
2067 encoder
.emit_raw_bytes(&[0, 0, 0, 0]);
2069 let source_map_files
= tcx
.sess
.source_map().files();
2070 let hygiene_ctxt
= HygieneEncodeContext
::default();
2072 let mut ecx
= EncodeContext
{
2075 feat
: tcx
.features(),
2076 tables
: Default
::default(),
2077 lazy_state
: LazyState
::NoNode
,
2078 type_shorthands
: Default
::default(),
2079 predicate_shorthands
: Default
::default(),
2080 source_file_cache
: (source_map_files
[0].clone(), 0),
2081 interpret_allocs
: Default
::default(),
2082 required_source_files
: Some(GrowableBitSet
::with_capacity(source_map_files
.len())),
2083 is_proc_macro
: tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
),
2084 hygiene_ctxt
: &hygiene_ctxt
,
2086 drop(source_map_files
);
2088 // Encode the rustc version string in a predictable location.
2089 rustc_version().encode(&mut ecx
).unwrap();
2091 // Encode all the entries and extra information in the crate,
2092 // culminating in the `CrateRoot` which points to all of it.
2093 let root
= ecx
.encode_crate_root();
2095 let mut result
= ecx
.opaque
.into_inner();
2097 // Encode the root position.
2098 let header
= METADATA_HEADER
.len();
2099 let pos
= root
.position
.get();
2100 result
[header
+ 0] = (pos
>> 24) as u8;
2101 result
[header
+ 1] = (pos
>> 16) as u8;
2102 result
[header
+ 2] = (pos
>> 8) as u8;
2103 result
[header
+ 3] = (pos
>> 0) as u8;
2105 EncodedMetadata { raw_data: result }