1 use crate::rmeta
::table
::{FixedSizeEncoding, TableBuilder}
;
4 use rustc_data_structures
::fx
::{FxHashMap, FxIndexSet}
;
5 use rustc_data_structures
::stable_hasher
::StableHasher
;
6 use rustc_data_structures
::sync
::{join, par_iter, Lrc, ParallelIterator}
;
8 use rustc_hir
::def
::{CtorOf, DefKind}
;
9 use rustc_hir
::def_id
::{
10 CrateNum
, DefId
, DefIndex
, LocalDefId
, CRATE_DEF_ID
, CRATE_DEF_INDEX
, LOCAL_CRATE
,
12 use rustc_hir
::definitions
::DefPathData
;
13 use rustc_hir
::intravisit
::{self, NestedVisitorMap, Visitor}
;
14 use rustc_hir
::itemlikevisit
::ItemLikeVisitor
;
15 use rustc_hir
::lang_items
;
16 use rustc_hir
::{AnonConst, GenericParamKind}
;
17 use rustc_index
::bit_set
::GrowableBitSet
;
18 use rustc_index
::vec
::Idx
;
19 use rustc_middle
::hir
::map
::Map
;
20 use rustc_middle
::middle
::cstore
::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib}
;
21 use rustc_middle
::middle
::dependency_format
::Linkage
;
22 use rustc_middle
::middle
::exported_symbols
::{
23 metadata_symbol_name
, ExportedSymbol
, SymbolExportLevel
,
25 use rustc_middle
::mir
::interpret
;
26 use rustc_middle
::traits
::specialization_graph
;
27 use rustc_middle
::ty
::codec
::TyEncoder
;
28 use rustc_middle
::ty
::{self, SymbolName, Ty, TyCtxt}
;
29 use rustc_serialize
::{opaque, Encodable, Encoder}
;
30 use rustc_session
::config
::CrateType
;
31 use rustc_span
::symbol
::{sym, Ident, Symbol}
;
32 use rustc_span
::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext}
;
34 hygiene
::{ExpnIndex, HygieneEncodeContext, MacroKind}
,
37 use rustc_target
::abi
::VariantIdx
;
39 use std
::num
::NonZeroUsize
;
41 use tracing
::{debug, trace}
;
43 pub(super) struct EncodeContext
<'a
, 'tcx
> {
44 opaque
: opaque
::Encoder
,
46 feat
: &'tcx rustc_feature
::Features
,
48 tables
: TableBuilders
<'tcx
>,
50 lazy_state
: LazyState
,
51 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
52 predicate_shorthands
: FxHashMap
<ty
::PredicateKind
<'tcx
>, usize>,
54 interpret_allocs
: FxIndexSet
<interpret
::AllocId
>,
56 // This is used to speed up Span encoding.
57 // The `usize` is an index into the `MonotonicVec`
58 // that stores the `SourceFile`
59 source_file_cache
: (Lrc
<SourceFile
>, usize),
60 // The indices (into the `SourceMap`'s `MonotonicVec`)
61 // of all of the `SourceFiles` that we need to serialize.
62 // When we serialize a `Span`, we insert the index of its
63 // `SourceFile` into the `GrowableBitSet`.
65 // This needs to be a `GrowableBitSet` and not a
66 // regular `BitSet` because we may actually import new `SourceFiles`
67 // during metadata encoding, due to executing a query
68 // with a result containing a foreign `Span`.
69 required_source_files
: Option
<GrowableBitSet
<usize>>,
71 hygiene_ctxt
: &'a HygieneEncodeContext
,
74 /// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
75 /// This is useful for skipping the encoding of things that aren't needed
76 /// for proc-macro crates.
77 macro_rules
! empty_proc_macro
{
79 if $
self.is_proc_macro
{
85 macro_rules
! encoder_methods
{
86 ($
($name
:ident($ty
:ty
);)*) => {
87 $
(fn $
name(&mut self, value
: $ty
) -> Result
<(), Self::Error
> {
88 self.opaque
.$
name(value
)
93 impl<'a
, 'tcx
> Encoder
for EncodeContext
<'a
, 'tcx
> {
94 type Error
= <opaque
::Encoder
as Encoder
>::Error
;
97 fn emit_unit(&mut self) -> Result
<(), Self::Error
> {
121 emit_raw_bytes(&[u8]);
125 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> Encodable
<EncodeContext
<'a
, 'tcx
>>
128 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
129 e
.emit_lazy_distance(*self)
133 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> Encodable
<EncodeContext
<'a
, 'tcx
>>
136 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
137 e
.emit_usize(self.meta
)?
;
141 e
.emit_lazy_distance(*self)
145 impl<'a
, 'tcx
, I
: Idx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> Encodable
<EncodeContext
<'a
, 'tcx
>>
146 for Lazy
<Table
<I
, T
>>
148 Option
<T
>: FixedSizeEncoding
,
150 fn encode(&self, e
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
151 e
.emit_usize(self.meta
)?
;
152 e
.emit_lazy_distance(*self)
156 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for CrateNum
{
157 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
158 if *self != LOCAL_CRATE
&& s
.is_proc_macro
{
159 panic
!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
161 s
.emit_u32(self.as_u32())
165 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for DefIndex
{
166 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
167 s
.emit_u32(self.as_u32())
171 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnIndex
{
172 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
173 s
.emit_u32(self.as_u32())
177 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for SyntaxContext
{
178 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
179 rustc_span
::hygiene
::raw_encode_syntax_context(*self, &s
.hygiene_ctxt
, s
)
183 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for ExpnId
{
184 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
185 if self.krate
== LOCAL_CRATE
{
186 // We will only write details for local expansions. Non-local expansions will fetch
187 // data from the corresponding crate's metadata.
188 // FIXME(#43047) FIXME(#74731) We may eventually want to avoid relying on external
189 // metadata from proc-macro crates.
190 s
.hygiene_ctxt
.schedule_expn_data_for_encoding(*self);
192 self.krate
.encode(s
)?
;
193 self.local_id
.encode(s
)
197 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for Span
{
198 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
199 let span
= self.data();
201 // Don't serialize any `SyntaxContext`s from a proc-macro crate,
202 // since we don't load proc-macro dependencies during serialization.
203 // This means that any hygiene information from macros used *within*
204 // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
205 // definition) will be lost.
207 // This can show up in two ways:
209 // 1. Any hygiene information associated with identifier of
210 // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
211 // Since proc-macros can only be invoked from a different crate,
212 // real code should never need to care about this.
214 // 2. Using `Span::def_site` or `Span::mixed_site` will not
215 // include any hygiene information associated with the definition
216 // site. This means that a proc-macro cannot emit a `$crate`
217 // identifier which resolves to one of its dependencies,
218 // which also should never come up in practice.
220 // Additionally, this affects `Span::parent`, and any other
221 // span inspection APIs that would otherwise allow traversing
222 // the `SyntaxContexts` associated with a span.
224 // None of these user-visible effects should result in any
225 // cross-crate inconsistencies (getting one behavior in the same
226 // crate, and a different behavior in another crate) due to the
227 // limited surface that proc-macros can expose.
229 // IMPORTANT: If this is ever changed, be sure to update
230 // `rustc_span::hygiene::raw_encode_expn_id` to handle
231 // encoding `ExpnData` for proc-macro crates.
233 SyntaxContext
::root().encode(s
)?
;
235 span
.ctxt
.encode(s
)?
;
239 return TAG_PARTIAL_SPAN
.encode(s
);
242 // The Span infrastructure should make sure that this invariant holds:
243 debug_assert
!(span
.lo
<= span
.hi
);
245 if !s
.source_file_cache
.0.contains(span
.lo
) {
246 let source_map
= s
.tcx
.sess
.source_map();
247 let source_file_index
= source_map
.lookup_source_file_idx(span
.lo
);
248 s
.source_file_cache
=
249 (source_map
.files()[source_file_index
].clone(), source_file_index
);
252 if !s
.source_file_cache
.0.contains(span
.hi
) {
253 // Unfortunately, macro expansion still sometimes generates Spans
254 // that malformed in this way.
255 return TAG_PARTIAL_SPAN
.encode(s
);
258 let source_files
= s
.required_source_files
.as_mut().expect("Already encoded SourceMap!");
259 // Record the fact that we need to encode the data for this `SourceFile`
260 source_files
.insert(s
.source_file_cache
.1);
262 // There are two possible cases here:
263 // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
264 // crate we are writing metadata for. When the metadata for *this* crate gets
265 // deserialized, the deserializer will need to know which crate it originally came
266 // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
267 // be deserialized after the rest of the span data, which tells the deserializer
268 // which crate contains the source map information.
269 // 2. This span comes from our own crate. No special hamdling is needed - we just
270 // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
271 // our own source map information.
273 // If we're a proc-macro crate, we always treat this as a local `Span`.
274 // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata
275 // if we're a proc-macro crate.
276 // This allows us to avoid loading the dependencies of proc-macro crates: all of
277 // the information we need to decode `Span`s is stored in the proc-macro crate.
278 let (tag
, lo
, hi
) = if s
.source_file_cache
.0.is_imported
() && !s
.is_proc_macro
{
279 // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
280 // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
281 // are relative to the source map information for the 'foreign' crate whose CrateNum
282 // we write into the metadata. This allows `imported_source_files` to binary
283 // search through the 'foreign' crate's source map information, using the
284 // deserialized 'lo' and 'hi' values directly.
286 // All of this logic ensures that the final result of deserialization is a 'normal'
287 // Span that can be used without any additional trouble.
288 let external_start_pos
= {
289 // Introduce a new scope so that we drop the 'lock()' temporary
290 match &*s
.source_file_cache
.0.external_src
.lock() {
291 ExternalSource
::Foreign { original_start_pos, .. }
=> *original_start_pos
,
292 src
=> panic
!("Unexpected external source {:?}", src
),
295 let lo
= (span
.lo
- s
.source_file_cache
.0.start_pos
) + external_start_pos
;
296 let hi
= (span
.hi
- s
.source_file_cache
.0.start_pos
) + external_start_pos
;
298 (TAG_VALID_SPAN_FOREIGN
, lo
, hi
)
300 (TAG_VALID_SPAN_LOCAL
, span
.lo
, span
.hi
)
306 // Encode length which is usually less than span.hi and profits more
307 // from the variable-length integer encoding that we use.
311 if tag
== TAG_VALID_SPAN_FOREIGN
{
312 // This needs to be two lines to avoid holding the `s.source_file_cache`
313 // while calling `cnum.encode(s)`
314 let cnum
= s
.source_file_cache
.0.cnum
;
322 impl<'a
, 'tcx
> TyEncoder
<'tcx
> for EncodeContext
<'a
, 'tcx
> {
323 const CLEAR_CROSS_CRATE
: bool
= true;
325 fn position(&self) -> usize {
326 self.opaque
.position()
329 fn type_shorthands(&mut self) -> &mut FxHashMap
<Ty
<'tcx
>, usize> {
330 &mut self.type_shorthands
333 fn predicate_shorthands(&mut self) -> &mut FxHashMap
<ty
::PredicateKind
<'tcx
>, usize> {
334 &mut self.predicate_shorthands
339 alloc_id
: &rustc_middle
::mir
::interpret
::AllocId
,
340 ) -> Result
<(), Self::Error
> {
341 let (index
, _
) = self.interpret_allocs
.insert_full(*alloc_id
);
347 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for &'tcx
[mir
::abstract_const
::Node
<'tcx
>] {
348 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
353 impl<'a
, 'tcx
> Encodable
<EncodeContext
<'a
, 'tcx
>> for &'tcx
[(ty
::Predicate
<'tcx
>, Span
)] {
354 fn encode(&self, s
: &mut EncodeContext
<'a
, 'tcx
>) -> opaque
::EncodeResult
{
359 /// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
360 trait EncodeContentsForLazy
<'a
, 'tcx
, T
: ?Sized
+ LazyMeta
> {
361 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) -> T
::Meta
;
364 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> EncodeContentsForLazy
<'a
, 'tcx
, T
> for &T
{
365 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) {
366 self.encode(ecx
).unwrap()
370 impl<'a
, 'tcx
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> EncodeContentsForLazy
<'a
, 'tcx
, T
> for T
{
371 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) {
372 self.encode(ecx
).unwrap()
376 impl<'a
, 'tcx
, I
, T
: Encodable
<EncodeContext
<'a
, 'tcx
>>> EncodeContentsForLazy
<'a
, 'tcx
, [T
]> for I
379 I
::Item
: EncodeContentsForLazy
<'a
, 'tcx
, T
>,
381 fn encode_contents_for_lazy(self, ecx
: &mut EncodeContext
<'a
, 'tcx
>) -> usize {
382 self.into_iter().map(|value
| value
.encode_contents_for_lazy(ecx
)).count()
386 // Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
387 // normally need extra variables to avoid errors about multiple mutable borrows.
388 macro_rules
! record
{
389 ($
self:ident
.$tables
:ident
.$table
:ident
[$def_id
:expr
] <- $value
:expr
) => {{
392 let lazy
= $
self.lazy(value
);
393 $
self.$tables
.$table
.set($def_id
.index
, lazy
);
398 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
399 fn emit_lazy_distance
<T
: ?Sized
+ LazyMeta
>(
402 ) -> Result
<(), <Self as Encoder
>::Error
> {
403 let min_end
= lazy
.position
.get() + T
::min_size(lazy
.meta
);
404 let distance
= match self.lazy_state
{
405 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
406 LazyState
::NodeStart(start
) => {
407 let start
= start
.get();
408 assert
!(min_end
<= start
);
411 LazyState
::Previous(last_min_end
) => {
413 last_min_end
<= lazy
.position
,
414 "make sure that the calls to `lazy*` \
415 are in the same order as the metadata fields",
417 lazy
.position
.get() - last_min_end
.get()
420 self.lazy_state
= LazyState
::Previous(NonZeroUsize
::new(min_end
).unwrap());
421 self.emit_usize(distance
)
424 fn lazy
<T
: ?Sized
+ LazyMeta
>(
426 value
: impl EncodeContentsForLazy
<'a
, 'tcx
, T
>,
428 let pos
= NonZeroUsize
::new(self.position()).unwrap();
430 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
431 self.lazy_state
= LazyState
::NodeStart(pos
);
432 let meta
= value
.encode_contents_for_lazy(self);
433 self.lazy_state
= LazyState
::NoNode
;
435 assert
!(pos
.get() + <T
>::min_size(meta
) <= self.position());
437 Lazy
::from_position_and_meta(pos
, meta
)
440 fn encode_info_for_items(&mut self) {
441 let krate
= self.tcx
.hir().krate();
442 self.encode_info_for_mod(CRATE_DEF_ID
, krate
.module());
444 // Proc-macro crates only export proc-macro items, which are looked
445 // up using `proc_macro_data`
446 if self.is_proc_macro
{
450 krate
.visit_all_item_likes(&mut self.as_deep_visitor());
453 fn encode_def_path_table(&mut self) {
454 let table
= self.tcx
.resolutions(()).definitions
.def_path_table();
455 if self.is_proc_macro
{
456 for def_index
in std
::iter
::once(CRATE_DEF_INDEX
)
457 .chain(self.tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
))
459 let def_key
= self.lazy(table
.def_key(def_index
));
460 let def_path_hash
= self.lazy(table
.def_path_hash(def_index
));
461 self.tables
.def_keys
.set(def_index
, def_key
);
462 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
);
465 for (def_index
, def_key
, def_path_hash
) in table
.enumerated_keys_and_path_hashes() {
466 let def_key
= self.lazy(def_key
);
467 let def_path_hash
= self.lazy(def_path_hash
);
468 self.tables
.def_keys
.set(def_index
, def_key
);
469 self.tables
.def_path_hashes
.set(def_index
, def_path_hash
);
474 fn encode_source_map(&mut self) -> Lazy
<[rustc_span
::SourceFile
]> {
475 let source_map
= self.tcx
.sess
.source_map();
476 let all_source_files
= source_map
.files();
478 // By replacing the `Option` with `None`, we ensure that we can't
479 // accidentally serialize any more `Span`s after the source map encoding
481 let required_source_files
= self.required_source_files
.take().unwrap();
483 let adapted
= all_source_files
486 .filter(|(idx
, source_file
)| {
487 // Only serialize `SourceFile`s that were used
488 // during the encoding of a `Span`
489 required_source_files
.contains(*idx
) &&
490 // Don't serialize imported `SourceFile`s, unless
491 // we're in a proc-macro crate.
492 (!source_file
.is_imported() || self.is_proc_macro
)
494 .map(|(_
, source_file
)| {
495 let mut adapted
= match source_file
.name
{
496 FileName
::Real(ref realname
) => {
497 let mut adapted
= (**source_file
).clone();
498 adapted
.name
= FileName
::Real(match realname
{
499 RealFileName
::LocalPath(path_to_file
) => {
500 // Prepend path of working directory onto potentially
501 // relative paths, because they could become relative
502 // to a wrong directory.
503 // We include `working_dir` as part of the crate hash,
504 // so it's okay for us to use it as part of the encoded
506 let working_dir
= &self.tcx
.sess
.opts
.working_dir
;
508 RealFileName
::LocalPath(absolute
) => {
509 // Although neither working_dir or the file name were subject
510 // to path remapping, the concatenation between the two may
511 // be. Hence we need to do a remapping here.
512 let joined
= Path
::new(absolute
).join(path_to_file
);
513 let (joined
, remapped
) =
514 source_map
.path_mapping().map_prefix(joined
);
516 RealFileName
::Remapped
{
518 virtual_name
: joined
,
521 RealFileName
::LocalPath(joined
)
524 RealFileName
::Remapped { local_path: _, virtual_name }
=> {
525 // If working_dir has been remapped, then we emit
526 // Remapped variant as the expanded path won't be valid
527 RealFileName
::Remapped
{
529 virtual_name
: Path
::new(virtual_name
)
535 RealFileName
::Remapped { local_path: _, virtual_name }
=> {
536 RealFileName
::Remapped
{
537 // We do not want any local path to be exported into metadata
539 virtual_name
: virtual_name
.clone(),
543 adapted
.name_hash
= {
544 let mut hasher
: StableHasher
= StableHasher
::new();
545 adapted
.name
.hash(&mut hasher
);
546 hasher
.finish
::<u128
>()
551 // expanded code, not from a file
552 _
=> source_file
.clone(),
555 // We're serializing this `SourceFile` into our crate metadata,
556 // so mark it as coming from this crate.
557 // This also ensures that we don't try to deserialize the
558 // `CrateNum` for a proc-macro dependency - since proc macro
559 // dependencies aren't loaded when we deserialize a proc-macro,
560 // trying to remap the `CrateNum` would fail.
561 if self.is_proc_macro
{
562 Lrc
::make_mut(&mut adapted
).cnum
= LOCAL_CRATE
;
566 .collect
::<Vec
<_
>>();
568 self.lazy(adapted
.iter().map(|rc
| &**rc
))
571 fn encode_crate_root(&mut self) -> Lazy
<CrateRoot
<'tcx
>> {
572 let mut i
= self.position();
574 // Encode the crate deps
575 let crate_deps
= self.encode_crate_deps();
576 let dylib_dependency_formats
= self.encode_dylib_dependency_formats();
577 let dep_bytes
= self.position() - i
;
579 // Encode the lib features.
581 let lib_features
= self.encode_lib_features();
582 let lib_feature_bytes
= self.position() - i
;
584 // Encode the language items.
586 let lang_items
= self.encode_lang_items();
587 let lang_items_missing
= self.encode_lang_items_missing();
588 let lang_item_bytes
= self.position() - i
;
590 // Encode the diagnostic items.
592 let diagnostic_items
= self.encode_diagnostic_items();
593 let diagnostic_item_bytes
= self.position() - i
;
595 // Encode the native libraries used
597 let native_libraries
= self.encode_native_libraries();
598 let native_lib_bytes
= self.position() - i
;
600 let foreign_modules
= self.encode_foreign_modules();
602 // Encode DefPathTable
604 self.encode_def_path_table();
605 let def_path_table_bytes
= self.position() - i
;
607 // Encode the def IDs of impls, for coherence checking.
609 let impls
= self.encode_impls();
610 let impl_bytes
= self.position() - i
;
617 let mir_bytes
= self.position() - i
;
621 self.encode_def_ids();
622 self.encode_info_for_items();
623 let item_bytes
= self.position() - i
;
625 // Encode the allocation index
626 let interpret_alloc_index
= {
627 let mut interpret_alloc_index
= Vec
::new();
629 trace
!("beginning to encode alloc ids");
631 let new_n
= self.interpret_allocs
.len();
632 // if we have found new ids, serialize those, too
637 trace
!("encoding {} further alloc ids", new_n
- n
);
638 for idx
in n
..new_n
{
639 let id
= self.interpret_allocs
[idx
];
640 let pos
= self.position() as u32;
641 interpret_alloc_index
.push(pos
);
642 interpret
::specialized_encode_alloc_id(self, tcx
, id
).unwrap();
646 self.lazy(interpret_alloc_index
)
649 // Encode the proc macro data. This affects 'tables',
650 // so we need to do this before we encode the tables
652 let proc_macro_data
= self.encode_proc_macros();
653 let proc_macro_data_bytes
= self.position() - i
;
656 let tables
= self.tables
.encode(&mut self.opaque
);
657 let tables_bytes
= self.position() - i
;
659 // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
660 // this as late as possible to give the prefetching as much time as possible to complete.
662 let exported_symbols
= tcx
.exported_symbols(LOCAL_CRATE
);
663 let exported_symbols
= self.encode_exported_symbols(&exported_symbols
);
664 let exported_symbols_bytes
= self.position() - i
;
666 // Encode the hygiene data,
667 // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
668 // of encoding other items (e.g. `optimized_mir`) may cause us to load
669 // data from the incremental cache. If this causes us to deserialize a `Span`,
670 // then we may load additional `SyntaxContext`s into the global `HygieneData`.
671 // Therefore, we need to encode the hygiene data last to ensure that we encode
672 // any `SyntaxContext`s that might be used.
674 let (syntax_contexts
, expn_data
, expn_hashes
) = self.encode_hygiene();
675 let hygiene_bytes
= self.position() - i
;
677 // Encode source_map. This needs to be done last,
678 // since encoding `Span`s tells us which `SourceFiles` we actually
681 let source_map
= self.encode_source_map();
682 let source_map_bytes
= self.position() - i
;
684 let attrs
= tcx
.hir().krate_attrs();
685 let has_default_lib_allocator
= tcx
.sess
.contains_name(&attrs
, sym
::default_lib_allocator
);
687 let root
= self.lazy(CrateRoot
{
688 name
: tcx
.crate_name(LOCAL_CRATE
),
689 extra_filename
: tcx
.sess
.opts
.cg
.extra_filename
.clone(),
690 triple
: tcx
.sess
.opts
.target_triple
.clone(),
691 hash
: tcx
.crate_hash(LOCAL_CRATE
),
692 stable_crate_id
: tcx
.def_path_hash(LOCAL_CRATE
.as_def_id()).stable_crate_id(),
693 panic_strategy
: tcx
.sess
.panic_strategy(),
694 edition
: tcx
.sess
.edition(),
695 has_global_allocator
: tcx
.has_global_allocator(LOCAL_CRATE
),
696 has_panic_handler
: tcx
.has_panic_handler(LOCAL_CRATE
),
697 has_default_lib_allocator
,
699 compiler_builtins
: tcx
.sess
.contains_name(&attrs
, sym
::compiler_builtins
),
700 needs_allocator
: tcx
.sess
.contains_name(&attrs
, sym
::needs_allocator
),
701 needs_panic_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::needs_panic_runtime
),
702 no_builtins
: tcx
.sess
.contains_name(&attrs
, sym
::no_builtins
),
703 panic_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::panic_runtime
),
704 profiler_runtime
: tcx
.sess
.contains_name(&attrs
, sym
::profiler_runtime
),
705 symbol_mangling_version
: tcx
.sess
.opts
.debugging_opts
.get_symbol_mangling_version(),
708 dylib_dependency_formats
,
718 interpret_alloc_index
,
725 let total_bytes
= self.position();
727 if tcx
.sess
.meta_stats() {
728 let mut zero_bytes
= 0;
729 for e
in self.opaque
.data
.iter() {
735 eprintln
!("metadata stats:");
736 eprintln
!(" dep bytes: {}", dep_bytes
);
737 eprintln
!(" lib feature bytes: {}", lib_feature_bytes
);
738 eprintln
!(" lang item bytes: {}", lang_item_bytes
);
739 eprintln
!(" diagnostic item bytes: {}", diagnostic_item_bytes
);
740 eprintln
!(" native bytes: {}", native_lib_bytes
);
741 eprintln
!(" source_map bytes: {}", source_map_bytes
);
742 eprintln
!(" impl bytes: {}", impl_bytes
);
743 eprintln
!(" exp. symbols bytes: {}", exported_symbols_bytes
);
744 eprintln
!(" def-path table bytes: {}", def_path_table_bytes
);
745 eprintln
!(" proc-macro-data-bytes: {}", proc_macro_data_bytes
);
746 eprintln
!(" mir bytes: {}", mir_bytes
);
747 eprintln
!(" item bytes: {}", item_bytes
);
748 eprintln
!(" table bytes: {}", tables_bytes
);
749 eprintln
!(" hygiene bytes: {}", hygiene_bytes
);
750 eprintln
!(" zero bytes: {}", zero_bytes
);
751 eprintln
!(" total bytes: {}", total_bytes
);
758 fn should_encode_visibility(def_kind
: DefKind
) -> bool
{
768 | DefKind
::TraitAlias
775 | DefKind
::AssocConst
778 | DefKind
::ForeignMod
781 | DefKind
::Field
=> true,
783 | DefKind
::ConstParam
784 | DefKind
::LifetimeParam
789 | DefKind
::ExternCrate
=> false,
793 fn should_encode_stability(def_kind
: DefKind
) -> bool
{
802 | DefKind
::AssocConst
804 | DefKind
::ConstParam
808 | DefKind
::ForeignMod
815 | DefKind
::TraitAlias
817 | DefKind
::ForeignTy
=> true,
819 | DefKind
::LifetimeParam
824 | DefKind
::ExternCrate
=> false,
828 /// Whether we should encode MIR.
830 /// Computing, optimizing and encoding the MIR is a relatively expensive operation.
831 /// We want to avoid this work when not required. Therefore:
832 /// - we only compute `mir_for_ctfe` on items with const-eval semantics;
833 /// - we skip `optimized_mir` for check runs.
835 /// Return a pair, resp. for CTFE and for LLVM.
836 fn should_encode_mir(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
) -> (bool
, bool
) {
837 match tcx
.def_kind(def_id
) {
839 DefKind
::Ctor(_
, _
) => {
840 let mir_opt_base
= tcx
.sess
.opts
.output_types
.should_codegen()
841 || tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
845 DefKind
::AnonConst
| DefKind
::AssocConst
| DefKind
::Static
| DefKind
::Const
=> {
848 // Full-fledged functions
849 DefKind
::AssocFn
| DefKind
::Fn
=> {
850 let generics
= tcx
.generics_of(def_id
);
851 let needs_inline
= (generics
.requires_monomorphization(tcx
)
852 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
853 && tcx
.sess
.opts
.output_types
.should_codegen();
854 // Only check the presence of the `const` modifier.
855 let is_const_fn
= tcx
.is_const_fn_raw(def_id
.to_def_id());
856 let always_encode_mir
= tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
857 (is_const_fn
, needs_inline
|| always_encode_mir
)
859 // Closures can't be const fn.
860 DefKind
::Closure
=> {
861 let generics
= tcx
.generics_of(def_id
);
862 let needs_inline
= (generics
.requires_monomorphization(tcx
)
863 || tcx
.codegen_fn_attrs(def_id
).requests_inline())
864 && tcx
.sess
.opts
.output_types
.should_codegen();
865 let always_encode_mir
= tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
866 (false, needs_inline
|| always_encode_mir
)
868 // Generators require optimized MIR to compute layout.
869 DefKind
::Generator
=> (false, true),
870 // The others don't have MIR.
875 fn should_encode_variances(def_kind
: DefKind
) -> bool
{
883 | DefKind
::AssocFn
=> true,
887 | DefKind
::AssocConst
889 | DefKind
::ConstParam
892 | DefKind
::ForeignMod
897 | DefKind
::TraitAlias
901 | DefKind
::LifetimeParam
906 | DefKind
::ExternCrate
=> false,
910 fn should_encode_generics(def_kind
: DefKind
) -> bool
{
919 | DefKind
::TraitAlias
926 | DefKind
::AssocConst
933 | DefKind
::Generator
=> true,
935 | DefKind
::ForeignMod
936 | DefKind
::ConstParam
939 | DefKind
::LifetimeParam
941 | DefKind
::ExternCrate
=> false,
945 impl EncodeContext
<'a
, 'tcx
> {
946 fn encode_def_ids(&mut self) {
947 if self.is_proc_macro
{
952 for local_id
in hir
.iter_local_def_id() {
953 let def_id
= local_id
.to_def_id();
954 let def_kind
= tcx
.opt_def_kind(local_id
);
955 let def_kind
= if let Some(def_kind
) = def_kind { def_kind }
else { continue }
;
956 record
!(self.tables
.def_kind
[def_id
] <- match def_kind
{
957 // Replace Ctor by the enclosing object to avoid leaking details in children crates.
958 DefKind
::Ctor(CtorOf
::Struct
, _
) => DefKind
::Struct
,
959 DefKind
::Ctor(CtorOf
::Variant
, _
) => DefKind
::Variant
,
960 def_kind
=> def_kind
,
962 record
!(self.tables
.span
[def_id
] <- tcx
.def_span(def_id
));
963 record
!(self.tables
.attributes
[def_id
] <- tcx
.get_attrs(def_id
));
964 record
!(self.tables
.expn_that_defined
[def_id
] <- self.tcx
.expn_that_defined(def_id
));
965 if should_encode_visibility(def_kind
) {
966 record
!(self.tables
.visibility
[def_id
] <- self.tcx
.visibility(def_id
));
968 if should_encode_stability(def_kind
) {
969 self.encode_stability(def_id
);
970 self.encode_const_stability(def_id
);
971 self.encode_deprecation(def_id
);
973 if should_encode_variances(def_kind
) {
974 let v
= self.tcx
.variances_of(def_id
);
975 record
!(self.tables
.variances
[def_id
] <- v
);
977 if should_encode_generics(def_kind
) {
978 let g
= tcx
.generics_of(def_id
);
979 record
!(self.tables
.generics
[def_id
] <- g
);
980 record
!(self.tables
.explicit_predicates
[def_id
] <- self.tcx
.explicit_predicates_of(def_id
));
981 let inferred_outlives
= self.tcx
.inferred_outlives_of(def_id
);
982 if !inferred_outlives
.is_empty() {
983 record
!(self.tables
.inferred_outlives
[def_id
] <- inferred_outlives
);
986 if let DefKind
::Trait
| DefKind
::TraitAlias
= def_kind
{
987 record
!(self.tables
.super_predicates
[def_id
] <- self.tcx
.super_predicates_of(def_id
));
990 let inherent_impls
= tcx
.crate_inherent_impls(());
991 for (def_id
, implementations
) in inherent_impls
.inherent_impls
.iter() {
992 if implementations
.is_empty() {
995 record
!(self.tables
.inherent_impls
[def_id
.to_def_id()] <- implementations
.iter().map(|&def_id
| {
996 assert
!(def_id
.is_local());
1002 fn encode_item_type(&mut self, def_id
: DefId
) {
1003 debug
!("EncodeContext::encode_item_type({:?})", def_id
);
1004 record
!(self.tables
.ty
[def_id
] <- self.tcx
.type_of(def_id
));
1007 fn encode_enum_variant_info(&mut self, def
: &ty
::AdtDef
, index
: VariantIdx
) {
1009 let variant
= &def
.variants
[index
];
1010 let def_id
= variant
.def_id
;
1011 debug
!("EncodeContext::encode_enum_variant_info({:?})", def_id
);
1013 let data
= VariantData
{
1014 ctor_kind
: variant
.ctor_kind
,
1015 discr
: variant
.discr
,
1016 ctor
: variant
.ctor_def_id
.map(|did
| did
.index
),
1017 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1020 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Variant(self.lazy(data
)));
1021 record
!(self.tables
.children
[def_id
] <- variant
.fields
.iter().map(|f
| {
1022 assert
!(f
.did
.is_local());
1025 self.encode_ident_span(def_id
, variant
.ident
);
1026 self.encode_item_type(def_id
);
1027 if variant
.ctor_kind
== CtorKind
::Fn
{
1028 // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
1029 if let Some(ctor_def_id
) = variant
.ctor_def_id
{
1030 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(ctor_def_id
));
1035 fn encode_enum_variant_ctor(&mut self, def
: &ty
::AdtDef
, index
: VariantIdx
) {
1037 let variant
= &def
.variants
[index
];
1038 let def_id
= variant
.ctor_def_id
.unwrap();
1039 debug
!("EncodeContext::encode_enum_variant_ctor({:?})", def_id
);
1041 // FIXME(eddyb) encode only the `CtorKind` for constructors.
1042 let data
= VariantData
{
1043 ctor_kind
: variant
.ctor_kind
,
1044 discr
: variant
.discr
,
1045 ctor
: Some(def_id
.index
),
1046 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1049 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Variant(self.lazy(data
)));
1050 self.encode_item_type(def_id
);
1051 if variant
.ctor_kind
== CtorKind
::Fn
{
1052 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1056 fn encode_info_for_mod(&mut self, local_def_id
: LocalDefId
, md
: &hir
::Mod
<'_
>) {
1058 let def_id
= local_def_id
.to_def_id();
1059 debug
!("EncodeContext::encode_info_for_mod({:?})", def_id
);
1061 // If we are encoding a proc-macro crates, `encode_info_for_mod` will
1062 // only ever get called for the crate root. We still want to encode
1063 // the crate root for consistency with other crates (some of the resolver
1064 // code uses it). However, we skip encoding anything relating to child
1065 // items - we encode information about proc-macros later on.
1066 let reexports
= if !self.is_proc_macro
{
1067 match tcx
.module_exports(local_def_id
) {
1069 let hir
= self.tcx
.hir();
1073 .map(|export
| export
.map_id(|id
| hir
.local_def_id_to_hir_id(id
))),
1082 let data
= ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) }
;
1084 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Mod(self.lazy(data
)));
1085 if self.is_proc_macro
{
1086 record
!(self.tables
.children
[def_id
] <- &[]);
1088 record
!(self.tables
.children
[def_id
] <- md
.item_ids
.iter().map(|item_id
| {
1089 item_id
.def_id
.local_def_index
1096 adt_def
: &ty
::AdtDef
,
1097 variant_index
: VariantIdx
,
1100 let variant
= &adt_def
.variants
[variant_index
];
1101 let field
= &variant
.fields
[field_index
];
1103 let def_id
= field
.did
;
1104 debug
!("EncodeContext::encode_field({:?})", def_id
);
1106 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Field
);
1107 self.encode_ident_span(def_id
, field
.ident
);
1108 self.encode_item_type(def_id
);
1111 fn encode_struct_ctor(&mut self, adt_def
: &ty
::AdtDef
, def_id
: DefId
) {
1112 debug
!("EncodeContext::encode_struct_ctor({:?})", def_id
);
1114 let variant
= adt_def
.non_enum_variant();
1116 let data
= VariantData
{
1117 ctor_kind
: variant
.ctor_kind
,
1118 discr
: variant
.discr
,
1119 ctor
: Some(def_id
.index
),
1120 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1123 record
!(self.tables
.kind
[def_id
] <- EntryKind
::Struct(self.lazy(data
), adt_def
.repr
));
1124 self.encode_item_type(def_id
);
1125 if variant
.ctor_kind
== CtorKind
::Fn
{
1126 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1130 fn encode_explicit_item_bounds(&mut self, def_id
: DefId
) {
1131 debug
!("EncodeContext::encode_explicit_item_bounds({:?})", def_id
);
1132 let bounds
= self.tcx
.explicit_item_bounds(def_id
);
1133 if !bounds
.is_empty() {
1134 record
!(self.tables
.explicit_item_bounds
[def_id
] <- bounds
);
1138 fn encode_info_for_trait_item(&mut self, def_id
: DefId
) {
1139 debug
!("EncodeContext::encode_info_for_trait_item({:?})", def_id
);
1142 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
1143 let ast_item
= tcx
.hir().expect_trait_item(hir_id
);
1144 let trait_item
= tcx
.associated_item(def_id
);
1146 let container
= match trait_item
.defaultness
{
1147 hir
::Defaultness
::Default { has_value: true }
=> AssocContainer
::TraitWithDefault
,
1148 hir
::Defaultness
::Default { has_value: false }
=> AssocContainer
::TraitRequired
,
1149 hir
::Defaultness
::Final
=> span_bug
!(ast_item
.span
, "traits cannot have final items"),
1152 match trait_item
.kind
{
1153 ty
::AssocKind
::Const
=> {
1154 let rendered
= rustc_hir_pretty
::to_string(
1155 &(&self.tcx
.hir() as &dyn intravisit
::Map
<'_
>),
1156 |s
| s
.print_trait_item(ast_item
),
1158 let rendered_const
= self.lazy(RenderedConst(rendered
));
1160 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocConst(
1166 ty
::AssocKind
::Fn
=> {
1167 let fn_data
= if let hir
::TraitItemKind
::Fn(m_sig
, m
) = &ast_item
.kind
{
1168 let param_names
= match *m
{
1169 hir
::TraitFn
::Required(ref names
) => self.encode_fn_param_names(names
),
1170 hir
::TraitFn
::Provided(body
) => self.encode_fn_param_names_for_body(body
),
1173 asyncness
: m_sig
.header
.asyncness
,
1174 constness
: hir
::Constness
::NotConst
,
1180 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocFn(self.lazy(AssocFnData
{
1183 has_self
: trait_item
.fn_has_self_parameter
,
1186 ty
::AssocKind
::Type
=> {
1187 self.encode_explicit_item_bounds(def_id
);
1188 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocType(container
));
1191 self.encode_ident_span(def_id
, ast_item
.ident
);
1192 match trait_item
.kind
{
1193 ty
::AssocKind
::Const
| ty
::AssocKind
::Fn
=> {
1194 self.encode_item_type(def_id
);
1196 ty
::AssocKind
::Type
=> {
1197 if trait_item
.defaultness
.has_value() {
1198 self.encode_item_type(def_id
);
1202 if trait_item
.kind
== ty
::AssocKind
::Fn
{
1203 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1207 fn encode_info_for_impl_item(&mut self, def_id
: DefId
) {
1208 debug
!("EncodeContext::encode_info_for_impl_item({:?})", def_id
);
1211 let hir_id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
.expect_local());
1212 let ast_item
= self.tcx
.hir().expect_impl_item(hir_id
);
1213 let impl_item
= self.tcx
.associated_item(def_id
);
1215 let container
= match impl_item
.defaultness
{
1216 hir
::Defaultness
::Default { has_value: true }
=> AssocContainer
::ImplDefault
,
1217 hir
::Defaultness
::Final
=> AssocContainer
::ImplFinal
,
1218 hir
::Defaultness
::Default { has_value: false }
=> {
1219 span_bug
!(ast_item
.span
, "impl items always have values (currently)")
1223 match impl_item
.kind
{
1224 ty
::AssocKind
::Const
=> {
1225 if let hir
::ImplItemKind
::Const(_
, body_id
) = ast_item
.kind
{
1226 let qualifs
= self.tcx
.at(ast_item
.span
).mir_const_qualif(def_id
);
1228 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocConst(
1231 self.encode_rendered_const_for_body(body_id
))
1237 ty
::AssocKind
::Fn
=> {
1238 let fn_data
= if let hir
::ImplItemKind
::Fn(ref sig
, body
) = ast_item
.kind
{
1240 asyncness
: sig
.header
.asyncness
,
1241 // Can be inside `impl const Trait`, so using sig.header.constness is not reliable
1242 constness
: if self.tcx
.is_const_fn_raw(def_id
) {
1243 hir
::Constness
::Const
1245 hir
::Constness
::NotConst
1247 param_names
: self.encode_fn_param_names_for_body(body
),
1252 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocFn(self.lazy(AssocFnData
{
1255 has_self
: impl_item
.fn_has_self_parameter
,
1258 ty
::AssocKind
::Type
=> {
1259 record
!(self.tables
.kind
[def_id
] <- EntryKind
::AssocType(container
));
1262 self.encode_ident_span(def_id
, impl_item
.ident
);
1263 self.encode_item_type(def_id
);
1264 if impl_item
.kind
== ty
::AssocKind
::Fn
{
1265 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1269 fn encode_fn_param_names_for_body(&mut self, body_id
: hir
::BodyId
) -> Lazy
<[Ident
]> {
1270 self.lazy(self.tcx
.hir().body_param_names(body_id
))
1273 fn encode_fn_param_names(&mut self, param_names
: &[Ident
]) -> Lazy
<[Ident
]> {
1274 self.lazy(param_names
.iter())
1277 fn encode_mir(&mut self) {
1278 if self.is_proc_macro
{
1282 let mut keys_and_jobs
= self
1286 .filter_map(|&def_id
| {
1287 let (encode_const
, encode_opt
) = should_encode_mir(self.tcx
, def_id
);
1288 if encode_const
|| encode_opt
{
1289 Some((def_id
, encode_const
, encode_opt
))
1294 .collect
::<Vec
<_
>>();
1295 // Sort everything to ensure a stable order for diagnotics.
1296 keys_and_jobs
.sort_by_key(|&(def_id
, _
, _
)| def_id
);
1297 for (def_id
, encode_const
, encode_opt
) in keys_and_jobs
.into_iter() {
1298 debug_assert
!(encode_const
|| encode_opt
);
1300 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
1302 record
!(self.tables
.mir
[def_id
.to_def_id()] <- self.tcx
.optimized_mir(def_id
));
1305 record
!(self.tables
.mir_for_ctfe
[def_id
.to_def_id()] <- self.tcx
.mir_for_ctfe(def_id
));
1307 let abstract_const
= self.tcx
.mir_abstract_const(def_id
);
1308 if let Ok(Some(abstract_const
)) = abstract_const
{
1309 record
!(self.tables
.mir_abstract_consts
[def_id
.to_def_id()] <- abstract_const
);
1312 record
!(self.tables
.promoted_mir
[def_id
.to_def_id()] <- self.tcx
.promoted_mir(def_id
));
1314 let unused
= self.tcx
.unused_generic_params(def_id
);
1315 if !unused
.is_empty() {
1316 record
!(self.tables
.unused_generic_params
[def_id
.to_def_id()] <- unused
);
1321 fn encode_stability(&mut self, def_id
: DefId
) {
1322 debug
!("EncodeContext::encode_stability({:?})", def_id
);
1324 // The query lookup can take a measurable amount of time in crates with many items. Check if
1325 // the stability attributes are even enabled before using their queries.
1326 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.debugging_opts
.force_unstable_if_unmarked
{
1327 if let Some(stab
) = self.tcx
.lookup_stability(def_id
) {
1328 record
!(self.tables
.stability
[def_id
] <- stab
)
1333 fn encode_const_stability(&mut self, def_id
: DefId
) {
1334 debug
!("EncodeContext::encode_const_stability({:?})", def_id
);
1336 // The query lookup can take a measurable amount of time in crates with many items. Check if
1337 // the stability attributes are even enabled before using their queries.
1338 if self.feat
.staged_api
|| self.tcx
.sess
.opts
.debugging_opts
.force_unstable_if_unmarked
{
1339 if let Some(stab
) = self.tcx
.lookup_const_stability(def_id
) {
1340 record
!(self.tables
.const_stability
[def_id
] <- stab
)
1345 fn encode_deprecation(&mut self, def_id
: DefId
) {
1346 debug
!("EncodeContext::encode_deprecation({:?})", def_id
);
1347 if let Some(depr
) = self.tcx
.lookup_deprecation(def_id
) {
1348 record
!(self.tables
.deprecation
[def_id
] <- depr
);
1352 fn encode_rendered_const_for_body(&mut self, body_id
: hir
::BodyId
) -> Lazy
<RenderedConst
> {
1353 let hir
= self.tcx
.hir();
1354 let body
= hir
.body(body_id
);
1355 let rendered
= rustc_hir_pretty
::to_string(&(&hir
as &dyn intravisit
::Map
<'_
>), |s
| {
1356 s
.print_expr(&body
.value
)
1358 let rendered_const
= &RenderedConst(rendered
);
1359 self.lazy(rendered_const
)
1362 fn encode_info_for_item(&mut self, def_id
: DefId
, item
: &'tcx hir
::Item
<'tcx
>) {
1365 debug
!("EncodeContext::encode_info_for_item({:?})", def_id
);
1367 self.encode_ident_span(def_id
, item
.ident
);
1369 let entry_kind
= match item
.kind
{
1370 hir
::ItemKind
::Static(_
, hir
::Mutability
::Mut
, _
) => EntryKind
::MutStatic
,
1371 hir
::ItemKind
::Static(_
, hir
::Mutability
::Not
, _
) => EntryKind
::ImmStatic
,
1372 hir
::ItemKind
::Const(_
, body_id
) => {
1373 let qualifs
= self.tcx
.at(item
.span
).mir_const_qualif(def_id
);
1374 EntryKind
::Const(qualifs
, self.encode_rendered_const_for_body(body_id
))
1376 hir
::ItemKind
::Fn(ref sig
, .., body
) => {
1378 asyncness
: sig
.header
.asyncness
,
1379 constness
: sig
.header
.constness
,
1380 param_names
: self.encode_fn_param_names_for_body(body
),
1383 EntryKind
::Fn(self.lazy(data
))
1385 hir
::ItemKind
::Macro(ref macro_def
) => {
1386 EntryKind
::MacroDef(self.lazy(macro_def
.clone()))
1388 hir
::ItemKind
::Mod(ref m
) => {
1389 return self.encode_info_for_mod(item
.def_id
, m
);
1391 hir
::ItemKind
::ForeignMod { .. }
=> EntryKind
::ForeignMod
,
1392 hir
::ItemKind
::GlobalAsm(..) => EntryKind
::GlobalAsm
,
1393 hir
::ItemKind
::TyAlias(..) => EntryKind
::Type
,
1394 hir
::ItemKind
::OpaqueTy(..) => {
1395 self.encode_explicit_item_bounds(def_id
);
1398 hir
::ItemKind
::Enum(..) => EntryKind
::Enum(self.tcx
.adt_def(def_id
).repr
),
1399 hir
::ItemKind
::Struct(ref struct_def
, _
) => {
1400 let adt_def
= self.tcx
.adt_def(def_id
);
1401 let variant
= adt_def
.non_enum_variant();
1403 // Encode def_ids for each field and method
1404 // for methods, write all the stuff get_trait_method
1406 let ctor
= struct_def
1408 .map(|ctor_hir_id
| self.tcx
.hir().local_def_id(ctor_hir_id
).local_def_index
);
1411 self.lazy(VariantData
{
1412 ctor_kind
: variant
.ctor_kind
,
1413 discr
: variant
.discr
,
1415 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1420 hir
::ItemKind
::Union(..) => {
1421 let adt_def
= self.tcx
.adt_def(def_id
);
1422 let variant
= adt_def
.non_enum_variant();
1425 self.lazy(VariantData
{
1426 ctor_kind
: variant
.ctor_kind
,
1427 discr
: variant
.discr
,
1429 is_non_exhaustive
: variant
.is_field_list_non_exhaustive(),
1434 hir
::ItemKind
::Impl(hir
::Impl { defaultness, constness, .. }
) => {
1435 let trait_ref
= self.tcx
.impl_trait_ref(def_id
);
1436 let polarity
= self.tcx
.impl_polarity(def_id
);
1437 let parent
= if let Some(trait_ref
) = trait_ref
{
1438 let trait_def
= self.tcx
.trait_def(trait_ref
.def_id
);
1439 trait_def
.ancestors(self.tcx
, def_id
).ok().and_then(|mut an
| {
1440 an
.nth(1).and_then(|node
| match node
{
1441 specialization_graph
::Node
::Impl(parent
) => Some(parent
),
1449 // if this is an impl of `CoerceUnsized`, create its
1450 // "unsized info", else just store None
1451 let coerce_unsized_info
= trait_ref
.and_then(|t
| {
1452 if Some(t
.def_id
) == self.tcx
.lang_items().coerce_unsized_trait() {
1453 Some(self.tcx
.at(item
.span
).coerce_unsized_info(def_id
))
1459 let data
= ImplData
{
1463 parent_impl
: parent
,
1464 coerce_unsized_info
,
1467 EntryKind
::Impl(self.lazy(data
))
1469 hir
::ItemKind
::Trait(..) => {
1470 let trait_def
= self.tcx
.trait_def(def_id
);
1471 let data
= TraitData
{
1472 unsafety
: trait_def
.unsafety
,
1473 paren_sugar
: trait_def
.paren_sugar
,
1474 has_auto_impl
: self.tcx
.trait_is_auto(def_id
),
1475 is_marker
: trait_def
.is_marker
,
1476 skip_array_during_method_dispatch
: trait_def
.skip_array_during_method_dispatch
,
1477 specialization_kind
: trait_def
.specialization_kind
,
1480 EntryKind
::Trait(self.lazy(data
))
1482 hir
::ItemKind
::TraitAlias(..) => EntryKind
::TraitAlias
,
1483 hir
::ItemKind
::ExternCrate(_
) | hir
::ItemKind
::Use(..) => {
1484 bug
!("cannot encode info for item {:?}", item
)
1487 record
!(self.tables
.kind
[def_id
] <- entry_kind
);
1488 // FIXME(eddyb) there should be a nicer way to do this.
1490 hir
::ItemKind
::ForeignMod { items, .. }
=> record
!(self.tables
.children
[def_id
] <-
1493 .map(|foreign_item
| foreign_item
.id
.def_id
.local_def_index
)
1495 hir
::ItemKind
::Enum(..) => record
!(self.tables
.children
[def_id
] <-
1496 self.tcx
.adt_def(def_id
).variants
.iter().map(|v
| {
1497 assert
!(v
.def_id
.is_local());
1501 hir
::ItemKind
::Struct(..) | hir
::ItemKind
::Union(..) => {
1502 record
!(self.tables
.children
[def_id
] <-
1503 self.tcx
.adt_def(def_id
).non_enum_variant().fields
.iter().map(|f
| {
1504 assert
!(f
.did
.is_local());
1509 hir
::ItemKind
::Impl { .. }
| hir
::ItemKind
::Trait(..) => {
1510 let associated_item_def_ids
= self.tcx
.associated_item_def_ids(def_id
);
1511 record
!(self.tables
.children
[def_id
] <-
1512 associated_item_def_ids
.iter().map(|&def_id
| {
1513 assert
!(def_id
.is_local());
1521 hir
::ItemKind
::Static(..)
1522 | hir
::ItemKind
::Const(..)
1523 | hir
::ItemKind
::Fn(..)
1524 | hir
::ItemKind
::TyAlias(..)
1525 | hir
::ItemKind
::OpaqueTy(..)
1526 | hir
::ItemKind
::Enum(..)
1527 | hir
::ItemKind
::Struct(..)
1528 | hir
::ItemKind
::Union(..)
1529 | hir
::ItemKind
::Impl { .. }
=> self.encode_item_type(def_id
),
1532 if let hir
::ItemKind
::Fn(..) = item
.kind
{
1533 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1535 if let hir
::ItemKind
::Impl { .. }
= item
.kind
{
1536 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(def_id
) {
1537 record
!(self.tables
.impl_trait_ref
[def_id
] <- trait_ref
);
1542 fn encode_info_for_generic_param(&mut self, def_id
: DefId
, kind
: EntryKind
, encode_type
: bool
) {
1543 record
!(self.tables
.kind
[def_id
] <- kind
);
1545 self.encode_item_type(def_id
);
1549 fn encode_info_for_closure(&mut self, def_id
: LocalDefId
) {
1550 debug
!("EncodeContext::encode_info_for_closure({:?})", def_id
);
1552 // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
1553 // including on the signature, which is inferred in `typeck.
1554 let hir_id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
);
1555 let ty
= self.tcx
.typeck(def_id
).node_type(hir_id
);
1558 ty
::Generator(..) => {
1559 let data
= self.tcx
.generator_kind(def_id
).unwrap();
1560 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::Generator(data
));
1563 ty
::Closure(..) => {
1564 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::Closure
);
1567 _
=> bug
!("closure that is neither generator nor closure"),
1569 self.encode_item_type(def_id
.to_def_id());
1570 if let ty
::Closure(def_id
, substs
) = *ty
.kind() {
1571 record
!(self.tables
.fn_sig
[def_id
] <- substs
.as_closure().sig());
1575 fn encode_info_for_anon_const(&mut self, def_id
: LocalDefId
) {
1576 debug
!("EncodeContext::encode_info_for_anon_const({:?})", def_id
);
1577 let id
= self.tcx
.hir().local_def_id_to_hir_id(def_id
);
1578 let body_id
= self.tcx
.hir().body_owned_by(id
);
1579 let const_data
= self.encode_rendered_const_for_body(body_id
);
1580 let qualifs
= self.tcx
.mir_const_qualif(def_id
);
1582 record
!(self.tables
.kind
[def_id
.to_def_id()] <- EntryKind
::AnonConst(qualifs
, const_data
));
1583 self.encode_item_type(def_id
.to_def_id());
1586 fn encode_native_libraries(&mut self) -> Lazy
<[NativeLib
]> {
1587 empty_proc_macro
!(self);
1588 let used_libraries
= self.tcx
.native_libraries(LOCAL_CRATE
);
1589 self.lazy(used_libraries
.iter())
1592 fn encode_foreign_modules(&mut self) -> Lazy
<[ForeignModule
]> {
1593 empty_proc_macro
!(self);
1594 let foreign_modules
= self.tcx
.foreign_modules(LOCAL_CRATE
);
1595 self.lazy(foreign_modules
.iter().map(|(_
, m
)| m
).cloned())
1598 fn encode_hygiene(&mut self) -> (SyntaxContextTable
, ExpnDataTable
, ExpnHashTable
) {
1599 let mut syntax_contexts
: TableBuilder
<_
, _
> = Default
::default();
1600 let mut expn_data_table
: TableBuilder
<_
, _
> = Default
::default();
1601 let mut expn_hash_table
: TableBuilder
<_
, _
> = Default
::default();
1603 let _
: Result
<(), !> = self.hygiene_ctxt
.encode(
1604 &mut (&mut *self, &mut syntax_contexts
, &mut expn_data_table
, &mut expn_hash_table
),
1605 |(this
, syntax_contexts
, _
, _
), index
, ctxt_data
| {
1606 syntax_contexts
.set(index
, this
.lazy(ctxt_data
));
1609 |(this
, _
, expn_data_table
, expn_hash_table
), index
, expn_data
, hash
| {
1610 if let Some(index
) = index
.as_local() {
1611 expn_data_table
.set(index
.as_raw(), this
.lazy(expn_data
));
1612 expn_hash_table
.set(index
.as_raw(), this
.lazy(hash
));
1619 syntax_contexts
.encode(&mut self.opaque
),
1620 expn_data_table
.encode(&mut self.opaque
),
1621 expn_hash_table
.encode(&mut self.opaque
),
1625 fn encode_proc_macros(&mut self) -> Option
<ProcMacroData
> {
1626 let is_proc_macro
= self.tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
);
1629 let hir
= tcx
.hir();
1631 let proc_macro_decls_static
= tcx
.proc_macro_decls_static(()).unwrap().local_def_index
;
1632 let stability
= tcx
.lookup_stability(DefId
::local(CRATE_DEF_INDEX
)).copied();
1634 self.lazy(tcx
.resolutions(()).proc_macros
.iter().map(|p
| p
.local_def_index
));
1635 let spans
= self.tcx
.sess
.parse_sess
.proc_macro_quoted_spans();
1636 for (i
, span
) in spans
.into_iter().enumerate() {
1637 let span
= self.lazy(span
);
1638 self.tables
.proc_macro_quoted_spans
.set(i
, span
);
1641 record
!(self.tables
.def_kind
[LOCAL_CRATE
.as_def_id()] <- DefKind
::Mod
);
1642 record
!(self.tables
.span
[LOCAL_CRATE
.as_def_id()] <- tcx
.def_span(LOCAL_CRATE
.as_def_id()));
1643 record
!(self.tables
.attributes
[LOCAL_CRATE
.as_def_id()] <- tcx
.get_attrs(LOCAL_CRATE
.as_def_id()));
1644 record
!(self.tables
.visibility
[LOCAL_CRATE
.as_def_id()] <- tcx
.visibility(LOCAL_CRATE
.as_def_id()));
1645 if let Some(stability
) = stability
{
1646 record
!(self.tables
.stability
[LOCAL_CRATE
.as_def_id()] <- stability
);
1648 self.encode_deprecation(LOCAL_CRATE
.as_def_id());
1650 // Normally, this information is encoded when we walk the items
1651 // defined in this crate. However, we skip doing that for proc-macro crates,
1652 // so we manually encode just the information that we need
1653 for &proc_macro
in &tcx
.resolutions(()).proc_macros
{
1654 let id
= proc_macro
;
1655 let proc_macro
= hir
.local_def_id_to_hir_id(proc_macro
);
1656 let mut name
= hir
.name(proc_macro
);
1657 let span
= hir
.span(proc_macro
);
1658 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1659 // so downstream crates need access to them.
1660 let attrs
= hir
.attrs(proc_macro
);
1661 let macro_kind
= if tcx
.sess
.contains_name(attrs
, sym
::proc_macro
) {
1663 } else if tcx
.sess
.contains_name(attrs
, sym
::proc_macro_attribute
) {
1665 } else if let Some(attr
) = tcx
.sess
.find_by_name(attrs
, sym
::proc_macro_derive
) {
1666 // This unwrap chain should have been checked by the proc-macro harness.
1667 name
= attr
.meta_item_list().unwrap()[0]
1675 bug
!("Unknown proc-macro type for item {:?}", id
);
1678 let mut def_key
= self.tcx
.hir().def_key(id
);
1679 def_key
.disambiguated_data
.data
= DefPathData
::MacroNs(name
);
1681 let def_id
= id
.to_def_id();
1682 record
!(self.tables
.def_kind
[def_id
] <- DefKind
::Macro(macro_kind
));
1683 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ProcMacro(macro_kind
));
1684 record
!(self.tables
.attributes
[def_id
] <- attrs
);
1685 record
!(self.tables
.def_keys
[def_id
] <- def_key
);
1686 record
!(self.tables
.ident_span
[def_id
] <- span
);
1687 record
!(self.tables
.span
[def_id
] <- span
);
1688 record
!(self.tables
.visibility
[def_id
] <- ty
::Visibility
::Public
);
1689 if let Some(stability
) = stability
{
1690 record
!(self.tables
.stability
[def_id
] <- stability
);
1694 Some(ProcMacroData { proc_macro_decls_static, stability, macros }
)
1700 fn encode_crate_deps(&mut self) -> Lazy
<[CrateDep
]> {
1701 empty_proc_macro
!(self);
1702 let crates
= self.tcx
.crates(());
1704 let mut deps
= crates
1707 let dep
= CrateDep
{
1708 name
: self.tcx
.crate_name(cnum
),
1709 hash
: self.tcx
.crate_hash(cnum
),
1710 host_hash
: self.tcx
.crate_host_hash(cnum
),
1711 kind
: self.tcx
.dep_kind(cnum
),
1712 extra_filename
: self.tcx
.extra_filename(cnum
),
1716 .collect
::<Vec
<_
>>();
1718 deps
.sort_by_key(|&(cnum
, _
)| cnum
);
1721 // Sanity-check the crate numbers
1722 let mut expected_cnum
= 1;
1723 for &(n
, _
) in &deps
{
1724 assert_eq
!(n
, CrateNum
::new(expected_cnum
));
1729 // We're just going to write a list of crate 'name-hash-version's, with
1730 // the assumption that they are numbered 1 to n.
1731 // FIXME (#2166): This is not nearly enough to support correct versioning
1732 // but is enough to get transitive crate dependencies working.
1733 self.lazy(deps
.iter().map(|&(_
, ref dep
)| dep
))
1736 fn encode_lib_features(&mut self) -> Lazy
<[(Symbol
, Option
<Symbol
>)]> {
1737 empty_proc_macro
!(self);
1739 let lib_features
= tcx
.lib_features();
1740 self.lazy(lib_features
.to_vec())
1743 fn encode_diagnostic_items(&mut self) -> Lazy
<[(Symbol
, DefIndex
)]> {
1744 empty_proc_macro
!(self);
1746 let diagnostic_items
= tcx
.diagnostic_items(LOCAL_CRATE
);
1747 self.lazy(diagnostic_items
.iter().map(|(&name
, def_id
)| (name
, def_id
.index
)))
1750 fn encode_lang_items(&mut self) -> Lazy
<[(DefIndex
, usize)]> {
1751 empty_proc_macro
!(self);
1753 let lang_items
= tcx
.lang_items();
1754 let lang_items
= lang_items
.items().iter();
1755 self.lazy(lang_items
.enumerate().filter_map(|(i
, &opt_def_id
)| {
1756 if let Some(def_id
) = opt_def_id
{
1757 if def_id
.is_local() {
1758 return Some((def_id
.index
, i
));
1765 fn encode_lang_items_missing(&mut self) -> Lazy
<[lang_items
::LangItem
]> {
1766 empty_proc_macro
!(self);
1768 self.lazy(&tcx
.lang_items().missing
)
1771 /// Encodes an index, mapping each trait to its (local) implementations.
1772 fn encode_impls(&mut self) -> Lazy
<[TraitImpls
]> {
1773 empty_proc_macro
!(self);
1774 debug
!("EncodeContext::encode_impls()");
1776 let mut visitor
= ImplVisitor { tcx, impls: FxHashMap::default() }
;
1777 tcx
.hir().krate().visit_all_item_likes(&mut visitor
);
1779 let mut all_impls
: Vec
<_
> = visitor
.impls
.into_iter().collect();
1781 // Bring everything into deterministic order for hashing
1782 all_impls
.sort_by_cached_key(|&(trait_def_id
, _
)| tcx
.def_path_hash(trait_def_id
));
1784 let all_impls
: Vec
<_
> = all_impls
1786 .map(|(trait_def_id
, mut impls
)| {
1787 // Bring everything into deterministic order for hashing
1788 impls
.sort_by_cached_key(|&(index
, _
)| {
1789 tcx
.hir().def_path_hash(LocalDefId { local_def_index: index }
)
1793 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
1794 impls
: self.lazy(&impls
),
1799 self.lazy(&all_impls
)
1802 // Encodes all symbols exported from this crate into the metadata.
1804 // This pass is seeded off the reachability list calculated in the
1805 // middle::reachable module but filters out items that either don't have a
1806 // symbol associated with them (they weren't translated) or if they're an FFI
1807 // definition (as that's not defined in this crate).
1808 fn encode_exported_symbols(
1810 exported_symbols
: &[(ExportedSymbol
<'tcx
>, SymbolExportLevel
)],
1811 ) -> Lazy
<[(ExportedSymbol
<'tcx
>, SymbolExportLevel
)]> {
1812 empty_proc_macro
!(self);
1813 // The metadata symbol name is special. It should not show up in
1814 // downstream crates.
1815 let metadata_symbol_name
= SymbolName
::new(self.tcx
, &metadata_symbol_name(self.tcx
));
1820 .filter(|&&(ref exported_symbol
, _
)| match *exported_symbol
{
1821 ExportedSymbol
::NoDefId(symbol_name
) => symbol_name
!= metadata_symbol_name
,
1828 fn encode_dylib_dependency_formats(&mut self) -> Lazy
<[Option
<LinkagePreference
>]> {
1829 empty_proc_macro
!(self);
1830 let formats
= self.tcx
.dependency_formats(());
1831 for (ty
, arr
) in formats
.iter() {
1832 if *ty
!= CrateType
::Dylib
{
1835 return self.lazy(arr
.iter().map(|slot
| match *slot
{
1836 Linkage
::NotLinked
| Linkage
::IncludedFromDylib
=> None
,
1838 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
1839 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
1845 fn encode_info_for_foreign_item(&mut self, def_id
: DefId
, nitem
: &hir
::ForeignItem
<'_
>) {
1848 debug
!("EncodeContext::encode_info_for_foreign_item({:?})", def_id
);
1851 hir
::ForeignItemKind
::Fn(_
, ref names
, _
) => {
1853 asyncness
: hir
::IsAsync
::NotAsync
,
1854 constness
: if self.tcx
.is_const_fn_raw(def_id
) {
1855 hir
::Constness
::Const
1857 hir
::Constness
::NotConst
1859 param_names
: self.encode_fn_param_names(names
),
1861 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignFn(self.lazy(data
)));
1863 hir
::ForeignItemKind
::Static(_
, hir
::Mutability
::Mut
) => {
1864 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignMutStatic
);
1866 hir
::ForeignItemKind
::Static(_
, hir
::Mutability
::Not
) => {
1867 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignImmStatic
);
1869 hir
::ForeignItemKind
::Type
=> {
1870 record
!(self.tables
.kind
[def_id
] <- EntryKind
::ForeignType
);
1873 self.encode_ident_span(def_id
, nitem
.ident
);
1874 self.encode_item_type(def_id
);
1875 if let hir
::ForeignItemKind
::Fn(..) = nitem
.kind
{
1876 record
!(self.tables
.fn_sig
[def_id
] <- tcx
.fn_sig(def_id
));
1881 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
1882 impl Visitor
<'tcx
> for EncodeContext
<'a
, 'tcx
> {
1883 type Map
= Map
<'tcx
>;
1885 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
1886 NestedVisitorMap
::OnlyBodies(self.tcx
.hir())
1888 fn visit_expr(&mut self, ex
: &'tcx hir
::Expr
<'tcx
>) {
1889 intravisit
::walk_expr(self, ex
);
1890 self.encode_info_for_expr(ex
);
1892 fn visit_anon_const(&mut self, c
: &'tcx AnonConst
) {
1893 intravisit
::walk_anon_const(self, c
);
1894 let def_id
= self.tcx
.hir().local_def_id(c
.hir_id
);
1895 self.encode_info_for_anon_const(def_id
);
1897 fn visit_item(&mut self, item
: &'tcx hir
::Item
<'tcx
>) {
1898 intravisit
::walk_item(self, item
);
1900 hir
::ItemKind
::ExternCrate(_
) | hir
::ItemKind
::Use(..) => {}
// ignore these
1901 _
=> self.encode_info_for_item(item
.def_id
.to_def_id(), item
),
1903 self.encode_addl_info_for_item(item
);
1905 fn visit_foreign_item(&mut self, ni
: &'tcx hir
::ForeignItem
<'tcx
>) {
1906 intravisit
::walk_foreign_item(self, ni
);
1907 self.encode_info_for_foreign_item(ni
.def_id
.to_def_id(), ni
);
1909 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
<'tcx
>) {
1910 intravisit
::walk_generics(self, generics
);
1911 self.encode_info_for_generics(generics
);
1915 impl EncodeContext
<'a
, 'tcx
> {
1916 fn encode_fields(&mut self, adt_def
: &ty
::AdtDef
) {
1917 for (variant_index
, variant
) in adt_def
.variants
.iter_enumerated() {
1918 for (field_index
, _field
) in variant
.fields
.iter().enumerate() {
1919 self.encode_field(adt_def
, variant_index
, field_index
);
1924 fn encode_info_for_generics(&mut self, generics
: &hir
::Generics
<'tcx
>) {
1925 for param
in generics
.params
{
1926 let def_id
= self.tcx
.hir().local_def_id(param
.hir_id
);
1928 GenericParamKind
::Lifetime { .. }
=> continue,
1929 GenericParamKind
::Type { default, .. }
=> {
1930 self.encode_info_for_generic_param(
1932 EntryKind
::TypeParam
,
1936 GenericParamKind
::Const { ref default, .. }
=> {
1937 let def_id
= def_id
.to_def_id();
1938 self.encode_info_for_generic_param(def_id
, EntryKind
::ConstParam
, true);
1939 if default.is_some() {
1940 record
!(self.tables
.const_defaults
[def_id
] <- self.tcx
.const_param_default(def_id
))
1947 fn encode_info_for_expr(&mut self, expr
: &hir
::Expr
<'_
>) {
1948 if let hir
::ExprKind
::Closure(..) = expr
.kind
{
1949 let def_id
= self.tcx
.hir().local_def_id(expr
.hir_id
);
1950 self.encode_info_for_closure(def_id
);
1954 fn encode_ident_span(&mut self, def_id
: DefId
, ident
: Ident
) {
1955 record
!(self.tables
.ident_span
[def_id
] <- ident
.span
);
1958 /// In some cases, along with the item itself, we also
1959 /// encode some sub-items. Usually we want some info from the item
1960 /// so it's easier to do that here then to wait until we would encounter
1961 /// normally in the visitor walk.
1962 fn encode_addl_info_for_item(&mut self, item
: &hir
::Item
<'_
>) {
1964 hir
::ItemKind
::Static(..)
1965 | hir
::ItemKind
::Const(..)
1966 | hir
::ItemKind
::Fn(..)
1967 | hir
::ItemKind
::Macro(..)
1968 | hir
::ItemKind
::Mod(..)
1969 | hir
::ItemKind
::ForeignMod { .. }
1970 | hir
::ItemKind
::GlobalAsm(..)
1971 | hir
::ItemKind
::ExternCrate(..)
1972 | hir
::ItemKind
::Use(..)
1973 | hir
::ItemKind
::TyAlias(..)
1974 | hir
::ItemKind
::OpaqueTy(..)
1975 | hir
::ItemKind
::TraitAlias(..) => {
1976 // no sub-item recording needed in these cases
1978 hir
::ItemKind
::Enum(..) => {
1979 let def
= self.tcx
.adt_def(item
.def_id
.to_def_id());
1980 self.encode_fields(def
);
1982 for (i
, variant
) in def
.variants
.iter_enumerated() {
1983 self.encode_enum_variant_info(def
, i
);
1985 if let Some(_ctor_def_id
) = variant
.ctor_def_id
{
1986 self.encode_enum_variant_ctor(def
, i
);
1990 hir
::ItemKind
::Struct(ref struct_def
, _
) => {
1991 let def
= self.tcx
.adt_def(item
.def_id
.to_def_id());
1992 self.encode_fields(def
);
1994 // If the struct has a constructor, encode it.
1995 if let Some(ctor_hir_id
) = struct_def
.ctor_hir_id() {
1996 let ctor_def_id
= self.tcx
.hir().local_def_id(ctor_hir_id
);
1997 self.encode_struct_ctor(def
, ctor_def_id
.to_def_id());
2000 hir
::ItemKind
::Union(..) => {
2001 let def
= self.tcx
.adt_def(item
.def_id
.to_def_id());
2002 self.encode_fields(def
);
2004 hir
::ItemKind
::Impl { .. }
=> {
2005 for &trait_item_def_id
in
2006 self.tcx
.associated_item_def_ids(item
.def_id
.to_def_id()).iter()
2008 self.encode_info_for_impl_item(trait_item_def_id
);
2011 hir
::ItemKind
::Trait(..) => {
2012 for &item_def_id
in self.tcx
.associated_item_def_ids(item
.def_id
.to_def_id()).iter()
2014 self.encode_info_for_trait_item(item_def_id
);
2021 struct ImplVisitor
<'tcx
> {
2023 impls
: FxHashMap
<DefId
, Vec
<(DefIndex
, Option
<ty
::fast_reject
::SimplifiedType
>)>>,
2026 impl<'tcx
, 'v
> ItemLikeVisitor
<'v
> for ImplVisitor
<'tcx
> {
2027 fn visit_item(&mut self, item
: &hir
::Item
<'_
>) {
2028 if let hir
::ItemKind
::Impl { .. }
= item
.kind
{
2029 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(item
.def_id
.to_def_id()) {
2030 let simplified_self_ty
=
2031 ty
::fast_reject
::simplify_type(self.tcx
, trait_ref
.self_ty(), false);
2034 .entry(trait_ref
.def_id
)
2036 .push((item
.def_id
.local_def_index
, simplified_self_ty
));
2041 fn visit_trait_item(&mut self, _trait_item
: &'v hir
::TraitItem
<'v
>) {}
2043 fn visit_impl_item(&mut self, _impl_item
: &'v hir
::ImplItem
<'v
>) {
2044 // handled in `visit_item` above
2047 fn visit_foreign_item(&mut self, _foreign_item
: &'v hir
::ForeignItem
<'v
>) {}
2050 /// Used to prefetch queries which will be needed later by metadata encoding.
2051 /// Only a subset of the queries are actually prefetched to keep this code smaller.
2052 fn prefetch_mir(tcx
: TyCtxt
<'_
>) {
2053 if !tcx
.sess
.opts
.output_types
.should_codegen() {
2054 // We won't emit MIR, so don't prefetch it.
2058 par_iter(tcx
.mir_keys(())).for_each(|&def_id
| {
2059 let (encode_const
, encode_opt
) = should_encode_mir(tcx
, def_id
);
2062 tcx
.ensure().mir_for_ctfe(def_id
);
2065 tcx
.ensure().optimized_mir(def_id
);
2067 if encode_opt
|| encode_const
{
2068 tcx
.ensure().promoted_mir(def_id
);
2073 // NOTE(eddyb) The following comment was preserved for posterity, even
2074 // though it's no longer relevant as EBML (which uses nested & tagged
2075 // "documents") was replaced with a scheme that can't go out of bounds.
2077 // And here we run into yet another obscure archive bug: in which metadata
2078 // loaded from archives may have trailing garbage bytes. Awhile back one of
2079 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
2080 // and opt) by having ebml generate an out-of-bounds panic when looking at
2083 // Upon investigation it turned out that the metadata file inside of an rlib
2084 // (and ar archive) was being corrupted. Some compilations would generate a
2085 // metadata file which would end in a few extra bytes, while other
2086 // compilations would not have these extra bytes appended to the end. These
2087 // extra bytes were interpreted by ebml as an extra tag, so they ended up
2088 // being interpreted causing the out-of-bounds.
2090 // The root cause of why these extra bytes were appearing was never
2091 // discovered, and in the meantime the solution we're employing is to insert
2092 // the length of the metadata to the start of the metadata. Later on this
2093 // will allow us to slice the metadata to the precise length that we just
2094 // generated regardless of trailing bytes that end up in it.
2096 pub(super) fn encode_metadata(tcx
: TyCtxt
<'_
>) -> EncodedMetadata
{
2097 // Since encoding metadata is not in a query, and nothing is cached,
2098 // there's no need to do dep-graph tracking for any of it.
2099 tcx
.dep_graph
.assert_ignored();
2102 || encode_metadata_impl(tcx
),
2104 if tcx
.sess
.threads() == 1 {
2107 // Prefetch some queries used by metadata encoding.
2108 // This is not necessary for correctness, but is only done for performance reasons.
2109 // It can be removed if it turns out to cause trouble or be detrimental to performance.
2110 join(|| prefetch_mir(tcx
), || tcx
.exported_symbols(LOCAL_CRATE
));
2116 fn encode_metadata_impl(tcx
: TyCtxt
<'_
>) -> EncodedMetadata
{
2117 let mut encoder
= opaque
::Encoder
::new(vec
![]);
2118 encoder
.emit_raw_bytes(METADATA_HEADER
).unwrap();
2120 // Will be filled with the root position after encoding everything.
2121 encoder
.emit_raw_bytes(&[0, 0, 0, 0]).unwrap();
2123 let source_map_files
= tcx
.sess
.source_map().files();
2124 let source_file_cache
= (source_map_files
[0].clone(), 0);
2125 let required_source_files
= Some(GrowableBitSet
::with_capacity(source_map_files
.len()));
2126 drop(source_map_files
);
2128 let hygiene_ctxt
= HygieneEncodeContext
::default();
2130 let mut ecx
= EncodeContext
{
2133 feat
: tcx
.features(),
2134 tables
: Default
::default(),
2135 lazy_state
: LazyState
::NoNode
,
2136 type_shorthands
: Default
::default(),
2137 predicate_shorthands
: Default
::default(),
2139 interpret_allocs
: Default
::default(),
2140 required_source_files
,
2141 is_proc_macro
: tcx
.sess
.crate_types().contains(&CrateType
::ProcMacro
),
2142 hygiene_ctxt
: &hygiene_ctxt
,
2145 // Encode the rustc version string in a predictable location.
2146 rustc_version().encode(&mut ecx
).unwrap();
2148 // Encode all the entries and extra information in the crate,
2149 // culminating in the `CrateRoot` which points to all of it.
2150 let root
= ecx
.encode_crate_root();
2152 let mut result
= ecx
.opaque
.into_inner();
2154 // Encode the root position.
2155 let header
= METADATA_HEADER
.len();
2156 let pos
= root
.position
.get();
2157 result
[header
+ 0] = (pos
>> 24) as u8;
2158 result
[header
+ 1] = (pos
>> 16) as u8;
2159 result
[header
+ 2] = (pos
>> 8) as u8;
2160 result
[header
+ 3] = (pos
>> 0) as u8;
2162 EncodedMetadata { raw_data: result }