]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/rmeta/encoder.rs
Require stable/unstable annotations for the constness of all stable functions with...
[rust.git] / src / librustc_metadata / rmeta / encoder.rs
1 use crate::rmeta::*;
2 use crate::rmeta::table::FixedSizeEncoding;
3
4 use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
5                             EncodedMetadata, ForeignModule};
6 use rustc::hir::def::CtorKind;
7 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
8 use rustc::hir::{GenericParamKind, AnonConst};
9 use rustc::hir::map::definitions::DefPathTable;
10 use rustc_data_structures::fingerprint::Fingerprint;
11 use rustc_index::vec::Idx;
12 use rustc::middle::dependency_format::Linkage;
13 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel,
14                                       metadata_symbol_name};
15 use rustc::middle::lang_items;
16 use rustc::mir::{self, interpret};
17 use rustc::traits::specialization_graph;
18 use rustc::ty::{self, Ty, TyCtxt, SymbolName};
19 use rustc::ty::codec::{self as ty_codec, TyEncoder};
20 use rustc::ty::layout::VariantIdx;
21
22 use rustc::session::config::{self, CrateType};
23 use rustc::util::nodemap::FxHashMap;
24
25 use rustc_data_structures::stable_hasher::StableHasher;
26 use rustc_data_structures::sync::Lrc;
27 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
28
29 use std::hash::Hash;
30 use std::num::NonZeroUsize;
31 use std::path::Path;
32 use std::u32;
33 use syntax::ast;
34 use syntax::attr;
35 use syntax::expand::is_proc_macro_attr;
36 use syntax::source_map::Spanned;
37 use syntax::symbol::{kw, sym, Ident, Symbol};
38 use syntax_pos::{self, FileName, SourceFile, Span};
39 use log::{debug, trace};
40
41 use rustc::hir::{self, PatKind};
42 use rustc::hir::itemlikevisit::ItemLikeVisitor;
43 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
44 use rustc::hir::intravisit;
45
46 struct EncodeContext<'tcx> {
47     opaque: opaque::Encoder,
48     tcx: TyCtxt<'tcx>,
49
50     per_def: PerDefTableBuilders<'tcx>,
51
52     lazy_state: LazyState,
53     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
54     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
55
56     interpret_allocs: FxHashMap<interpret::AllocId, usize>,
57     interpret_allocs_inverse: Vec<interpret::AllocId>,
58
59     // This is used to speed up Span encoding.
60     source_file_cache: Lrc<SourceFile>,
61 }
62
63 macro_rules! encoder_methods {
64     ($($name:ident($ty:ty);)*) => {
65         $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
66             self.opaque.$name(value)
67         })*
68     }
69 }
70
71 impl<'tcx> Encoder for EncodeContext<'tcx> {
72     type Error = <opaque::Encoder as Encoder>::Error;
73
74     fn emit_unit(&mut self) -> Result<(), Self::Error> {
75         Ok(())
76     }
77
78     encoder_methods! {
79         emit_usize(usize);
80         emit_u128(u128);
81         emit_u64(u64);
82         emit_u32(u32);
83         emit_u16(u16);
84         emit_u8(u8);
85
86         emit_isize(isize);
87         emit_i128(i128);
88         emit_i64(i64);
89         emit_i32(i32);
90         emit_i16(i16);
91         emit_i8(i8);
92
93         emit_bool(bool);
94         emit_f64(f64);
95         emit_f32(f32);
96         emit_char(char);
97         emit_str(&str);
98     }
99 }
100
101 impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
102     fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
103         self.emit_lazy_distance(*lazy)
104     }
105 }
106
107 impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
108     fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
109         self.emit_usize(lazy.meta)?;
110         if lazy.meta == 0 {
111             return Ok(());
112         }
113         self.emit_lazy_distance(*lazy)
114     }
115 }
116
117 impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>>> for EncodeContext<'tcx>
118     where Option<T>: FixedSizeEncoding,
119 {
120     fn specialized_encode(&mut self, lazy: &Lazy<Table<I, T>>) -> Result<(), Self::Error> {
121         self.emit_usize(lazy.meta)?;
122         self.emit_lazy_distance(*lazy)
123     }
124 }
125
126 impl<'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'tcx> {
127     #[inline]
128     fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
129         self.emit_u32(cnum.as_u32())
130     }
131 }
132
133 impl<'tcx> SpecializedEncoder<DefId> for EncodeContext<'tcx> {
134     #[inline]
135     fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
136         let DefId {
137             krate,
138             index,
139         } = *def_id;
140
141         krate.encode(self)?;
142         index.encode(self)
143     }
144 }
145
146 impl<'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'tcx> {
147     #[inline]
148     fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
149         self.emit_u32(def_index.as_u32())
150     }
151 }
152
153 impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
154     fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
155         if span.is_dummy() {
156             return TAG_INVALID_SPAN.encode(self)
157         }
158
159         let span = span.data();
160
161         // The Span infrastructure should make sure that this invariant holds:
162         debug_assert!(span.lo <= span.hi);
163
164         if !self.source_file_cache.contains(span.lo) {
165             let source_map = self.tcx.sess.source_map();
166             let source_file_index = source_map.lookup_source_file_idx(span.lo);
167             self.source_file_cache = source_map.files()[source_file_index].clone();
168         }
169
170         if !self.source_file_cache.contains(span.hi) {
171             // Unfortunately, macro expansion still sometimes generates Spans
172             // that malformed in this way.
173             return TAG_INVALID_SPAN.encode(self)
174         }
175
176         // HACK(eddyb) there's no way to indicate which crate a Span is coming
177         // from right now, so decoding would fail to find the SourceFile if
178         // it's not local to the crate the Span is found in.
179         if self.source_file_cache.is_imported() {
180             return TAG_INVALID_SPAN.encode(self)
181         }
182
183         TAG_VALID_SPAN.encode(self)?;
184         span.lo.encode(self)?;
185
186         // Encode length which is usually less than span.hi and profits more
187         // from the variable-length integer encoding that we use.
188         let len = span.hi - span.lo;
189         len.encode(self)
190
191         // Don't encode the expansion context.
192     }
193 }
194
195 impl SpecializedEncoder<Ident> for EncodeContext<'tcx> {
196     fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> {
197         // FIXME(jseyfried): intercrate hygiene
198         ident.name.encode(self)
199     }
200 }
201
202 impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
203     #[inline]
204     fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
205         self.specialized_encode(&def_id.to_def_id())
206     }
207 }
208
209 impl<'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'tcx> {
210     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
211         ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
212     }
213 }
214
215 impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
216     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
217         use std::collections::hash_map::Entry;
218         let index = match self.interpret_allocs.entry(*alloc_id) {
219             Entry::Occupied(e) => *e.get(),
220             Entry::Vacant(e) => {
221                 let idx = self.interpret_allocs_inverse.len();
222                 self.interpret_allocs_inverse.push(*alloc_id);
223                 e.insert(idx);
224                 idx
225             },
226         };
227
228         index.encode(self)
229     }
230 }
231
232 impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> {
233     fn specialized_encode(&mut self,
234                           predicates: &&'tcx [(ty::Predicate<'tcx>, Span)])
235                           -> Result<(), Self::Error> {
236         ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
237     }
238 }
239
240 impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
241     fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
242         f.encode_opaque(&mut self.opaque)
243     }
244 }
245
246 impl<'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx> {
247     fn specialized_encode(&mut self,
248                           _: &mir::ClearCrossCrate<T>)
249                           -> Result<(), Self::Error> {
250         Ok(())
251     }
252 }
253
254 impl<'tcx> TyEncoder for EncodeContext<'tcx> {
255     fn position(&self) -> usize {
256         self.opaque.position()
257     }
258 }
259
260 /// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
261 trait EncodeContentsForLazy<T: ?Sized + LazyMeta> {
262     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> T::Meta;
263 }
264
265 impl<T: Encodable> EncodeContentsForLazy<T> for &T {
266     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) {
267         self.encode(ecx).unwrap()
268     }
269 }
270
271 impl<T: Encodable> EncodeContentsForLazy<T> for T {
272     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) {
273         self.encode(ecx).unwrap()
274     }
275 }
276
277 impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I
278     where I: IntoIterator,
279           I::Item: EncodeContentsForLazy<T>,
280 {
281     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize {
282         self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
283     }
284 }
285
286 // Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
287 // normally need extra variables to avoid errors about multiple mutable borrows.
288 macro_rules! record {
289     ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
290         {
291             let value = $value;
292             let lazy = $self.lazy(value);
293             $self.$tables.$table.set($def_id.index, lazy);
294         }
295     }}
296 }
297
298 impl<'tcx> EncodeContext<'tcx> {
299     fn emit_lazy_distance<T: ?Sized + LazyMeta>(
300         &mut self,
301         lazy: Lazy<T>,
302     ) -> Result<(), <Self as Encoder>::Error> {
303         let min_end = lazy.position.get() + T::min_size(lazy.meta);
304         let distance = match self.lazy_state {
305             LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
306             LazyState::NodeStart(start) => {
307                 let start = start.get();
308                 assert!(min_end <= start);
309                 start - min_end
310             }
311             LazyState::Previous(last_min_end) => {
312                 assert!(
313                     last_min_end <= lazy.position,
314                     "make sure that the calls to `lazy*` \
315                     are in the same order as the metadata fields",
316                 );
317                 lazy.position.get() - last_min_end.get()
318             }
319         };
320         self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap());
321         self.emit_usize(distance)
322     }
323
324     fn lazy<T: ?Sized + LazyMeta>(
325         &mut self,
326         value: impl EncodeContentsForLazy<T>,
327     ) -> Lazy<T> {
328         let pos = NonZeroUsize::new(self.position()).unwrap();
329
330         assert_eq!(self.lazy_state, LazyState::NoNode);
331         self.lazy_state = LazyState::NodeStart(pos);
332         let meta = value.encode_contents_for_lazy(self);
333         self.lazy_state = LazyState::NoNode;
334
335         assert!(pos.get() + <T>::min_size(meta) <= self.position());
336
337         Lazy::from_position_and_meta(pos, meta)
338     }
339
340     fn encode_info_for_items(&mut self) {
341         let krate = self.tcx.hir().krate();
342         let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
343         self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis);
344         krate.visit_all_item_likes(&mut self.as_deep_visitor());
345         for macro_def in &krate.exported_macros {
346             self.visit_macro_def(macro_def);
347         }
348     }
349
350     fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
351         let definitions = self.tcx.hir().definitions();
352         self.lazy(definitions.def_path_table())
353     }
354
355     fn encode_source_map(&mut self) -> Lazy<[syntax_pos::SourceFile]> {
356         let source_map = self.tcx.sess.source_map();
357         let all_source_files = source_map.files();
358
359         let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone();
360
361         let adapted = all_source_files.iter()
362             .filter(|source_file| {
363                 // No need to re-export imported source_files, as any downstream
364                 // crate will import them from their original source.
365                 // FIXME(eddyb) the `Span` encoding should take that into account.
366                 !source_file.is_imported()
367             })
368             .map(|source_file| {
369                 match source_file.name {
370                     // This path of this SourceFile has been modified by
371                     // path-remapping, so we use it verbatim (and avoid
372                     // cloning the whole map in the process).
373                     _  if source_file.name_was_remapped => source_file.clone(),
374
375                     // Otherwise expand all paths to absolute paths because
376                     // any relative paths are potentially relative to a
377                     // wrong directory.
378                     FileName::Real(ref name) => {
379                         let mut adapted = (**source_file).clone();
380                         adapted.name = Path::new(&working_dir).join(name).into();
381                         adapted.name_hash = {
382                             let mut hasher: StableHasher = StableHasher::new();
383                             adapted.name.hash(&mut hasher);
384                             hasher.finish::<u128>()
385                         };
386                         Lrc::new(adapted)
387                     },
388
389                     // expanded code, not from a file
390                     _ => source_file.clone(),
391                 }
392             })
393             .collect::<Vec<_>>();
394
395         self.lazy(adapted.iter().map(|rc| &**rc))
396     }
397
398     fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
399         let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
400
401         let mut i = self.position();
402
403         let crate_deps = self.encode_crate_deps();
404         let dylib_dependency_formats = self.encode_dylib_dependency_formats();
405         let dep_bytes = self.position() - i;
406
407         // Encode the lib features.
408         i = self.position();
409         let lib_features = self.encode_lib_features();
410         let lib_feature_bytes = self.position() - i;
411
412         // Encode the language items.
413         i = self.position();
414         let lang_items = self.encode_lang_items();
415         let lang_items_missing = self.encode_lang_items_missing();
416         let lang_item_bytes = self.position() - i;
417
418         // Encode the diagnostic items.
419         i = self.position();
420         let diagnostic_items = self.encode_diagnostic_items();
421         let diagnostic_item_bytes = self.position() - i;
422
423         // Encode the native libraries used
424         i = self.position();
425         let native_libraries = self.encode_native_libraries();
426         let native_lib_bytes = self.position() - i;
427
428         let foreign_modules = self.encode_foreign_modules();
429
430         // Encode source_map
431         i = self.position();
432         let source_map = self.encode_source_map();
433         let source_map_bytes = self.position() - i;
434
435         // Encode DefPathTable
436         i = self.position();
437         let def_path_table = self.encode_def_path_table();
438         let def_path_table_bytes = self.position() - i;
439
440         // Encode the def IDs of impls, for coherence checking.
441         i = self.position();
442         let impls = self.encode_impls();
443         let impl_bytes = self.position() - i;
444
445         // Encode exported symbols info.
446         i = self.position();
447         let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
448         let exported_symbols = self.encode_exported_symbols(&exported_symbols);
449         let exported_symbols_bytes = self.position() - i;
450
451         let tcx = self.tcx;
452
453         // Encode the items.
454         i = self.position();
455         self.encode_info_for_items();
456         let item_bytes = self.position() - i;
457
458         // Encode the allocation index
459         let interpret_alloc_index = {
460             let mut interpret_alloc_index = Vec::new();
461             let mut n = 0;
462             trace!("beginning to encode alloc ids");
463             loop {
464                 let new_n = self.interpret_allocs_inverse.len();
465                 // if we have found new ids, serialize those, too
466                 if n == new_n {
467                     // otherwise, abort
468                     break;
469                 }
470                 trace!("encoding {} further alloc ids", new_n - n);
471                 for idx in n..new_n {
472                     let id = self.interpret_allocs_inverse[idx];
473                     let pos = self.position() as u32;
474                     interpret_alloc_index.push(pos);
475                     interpret::specialized_encode_alloc_id(
476                         self,
477                         tcx,
478                         id,
479                     ).unwrap();
480                 }
481                 n = new_n;
482             }
483             self.lazy(interpret_alloc_index)
484         };
485
486
487         i = self.position();
488         let per_def = self.per_def.encode(&mut self.opaque);
489         let per_def_bytes = self.position() - i;
490
491         // Encode the proc macro data
492         i = self.position();
493         let proc_macro_data = self.encode_proc_macros();
494         let proc_macro_data_bytes = self.position() - i;
495
496
497         let attrs = tcx.hir().krate_attrs();
498         let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator);
499
500         let root = self.lazy(CrateRoot {
501             name: tcx.crate_name(LOCAL_CRATE),
502             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
503             triple: tcx.sess.opts.target_triple.clone(),
504             hash: tcx.crate_hash(LOCAL_CRATE),
505             disambiguator: tcx.sess.local_crate_disambiguator(),
506             panic_strategy: tcx.sess.panic_strategy(),
507             edition: tcx.sess.edition(),
508             has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
509             has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
510             has_default_lib_allocator: has_default_lib_allocator,
511             plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index),
512             proc_macro_decls_static: if is_proc_macro {
513                 let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap();
514                 Some(id.index)
515             } else {
516                 None
517             },
518             proc_macro_data,
519             proc_macro_stability: if is_proc_macro {
520                 tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone())
521             } else {
522                 None
523             },
524             compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins),
525             needs_allocator: attr::contains_name(&attrs, sym::needs_allocator),
526             needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime),
527             no_builtins: attr::contains_name(&attrs, sym::no_builtins),
528             panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
529             profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
530             sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime),
531             symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
532
533             crate_deps,
534             dylib_dependency_formats,
535             lib_features,
536             lang_items,
537             diagnostic_items,
538             lang_items_missing,
539             native_libraries,
540             foreign_modules,
541             source_map,
542             def_path_table,
543             impls,
544             exported_symbols,
545             interpret_alloc_index,
546             per_def,
547         });
548
549         let total_bytes = self.position();
550
551         if self.tcx.sess.meta_stats() {
552             let mut zero_bytes = 0;
553             for e in self.opaque.data.iter() {
554                 if *e == 0 {
555                     zero_bytes += 1;
556                 }
557             }
558
559             println!("metadata stats:");
560             println!("             dep bytes: {}", dep_bytes);
561             println!("     lib feature bytes: {}", lib_feature_bytes);
562             println!("       lang item bytes: {}", lang_item_bytes);
563             println!(" diagnostic item bytes: {}", diagnostic_item_bytes);
564             println!("          native bytes: {}", native_lib_bytes);
565             println!("         source_map bytes: {}", source_map_bytes);
566             println!("            impl bytes: {}", impl_bytes);
567             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
568             println!("  def-path table bytes: {}", def_path_table_bytes);
569             println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
570             println!("            item bytes: {}", item_bytes);
571             println!("   per-def table bytes: {}", per_def_bytes);
572             println!("            zero bytes: {}", zero_bytes);
573             println!("           total bytes: {}", total_bytes);
574         }
575
576         root
577     }
578 }
579
580 impl EncodeContext<'tcx> {
581     fn encode_variances_of(&mut self, def_id: DefId) {
582         debug!("EncodeContext::encode_variances_of({:?})", def_id);
583         record!(self.per_def.variances[def_id] <- &self.tcx.variances_of(def_id)[..]);
584     }
585
586     fn encode_item_type(&mut self, def_id: DefId) {
587         debug!("EncodeContext::encode_item_type({:?})", def_id);
588         record!(self.per_def.ty[def_id] <- self.tcx.type_of(def_id));
589     }
590
591     fn encode_enum_variant_info(
592         &mut self,
593         enum_did: DefId,
594         index: VariantIdx,
595     ) {
596         let tcx = self.tcx;
597         let def = tcx.adt_def(enum_did);
598         let variant = &def.variants[index];
599         let def_id = variant.def_id;
600         debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
601
602         let data = VariantData {
603             ctor_kind: variant.ctor_kind,
604             discr: variant.discr,
605             ctor: variant.ctor_def_id.map(|did| did.index),
606         };
607
608         let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
609         let enum_vis = &tcx.hir().expect_item(enum_id).vis;
610
611         record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
612         record!(self.per_def.visibility[def_id] <-
613             ty::Visibility::from_hir(enum_vis, enum_id, self.tcx));
614         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
615         record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
616         record!(self.per_def.children[def_id] <- variant.fields.iter().map(|f| {
617             assert!(f.did.is_local());
618             f.did.index
619         }));
620         self.encode_stability(def_id);
621         self.encode_deprecation(def_id);
622         self.encode_item_type(def_id);
623         if variant.ctor_kind == CtorKind::Fn {
624             // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
625             if let Some(ctor_def_id) = variant.ctor_def_id {
626                 record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
627             }
628             // FIXME(eddyb) is this ever used?
629             self.encode_variances_of(def_id);
630         }
631         self.encode_generics(def_id);
632         self.encode_explicit_predicates(def_id);
633         self.encode_inferred_outlives(def_id);
634         self.encode_optimized_mir(def_id);
635         self.encode_promoted_mir(def_id);
636     }
637
638     fn encode_enum_variant_ctor(
639         &mut self,
640         enum_did: DefId,
641         index: VariantIdx,
642     ) {
643         let tcx = self.tcx;
644         let def = tcx.adt_def(enum_did);
645         let variant = &def.variants[index];
646         let def_id = variant.ctor_def_id.unwrap();
647         debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
648
649         // FIXME(eddyb) encode only the `CtorKind` for constructors.
650         let data = VariantData {
651             ctor_kind: variant.ctor_kind,
652             discr: variant.discr,
653             ctor: Some(def_id.index),
654         };
655
656         // Variant constructors have the same visibility as the parent enums, unless marked as
657         // non-exhaustive, in which case they are lowered to `pub(crate)`.
658         let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
659         let enum_vis = &tcx.hir().expect_item(enum_id).vis;
660         let mut ctor_vis = ty::Visibility::from_hir(enum_vis, enum_id, tcx);
661         if variant.is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public {
662             ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
663         }
664
665         record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
666         record!(self.per_def.visibility[def_id] <- ctor_vis);
667         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
668         self.encode_stability(def_id);
669         self.encode_deprecation(def_id);
670         self.encode_item_type(def_id);
671         if variant.ctor_kind == CtorKind::Fn {
672             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
673             self.encode_variances_of(def_id);
674         }
675         self.encode_generics(def_id);
676         self.encode_explicit_predicates(def_id);
677         self.encode_inferred_outlives(def_id);
678         self.encode_optimized_mir(def_id);
679         self.encode_promoted_mir(def_id);
680     }
681
682     fn encode_info_for_mod(
683         &mut self,
684         id: hir::HirId,
685         md: &hir::Mod,
686         attrs: &[ast::Attribute],
687         vis: &hir::Visibility,
688     ) {
689         let tcx = self.tcx;
690         let def_id = tcx.hir().local_def_id(id);
691         debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
692
693         let data = ModData {
694             reexports: match tcx.module_exports(def_id) {
695                 Some(exports) => self.lazy(exports),
696                 _ => Lazy::empty(),
697             },
698         };
699
700         record!(self.per_def.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
701         record!(self.per_def.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
702         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
703         record!(self.per_def.attributes[def_id] <- attrs);
704         record!(self.per_def.children[def_id] <- md.item_ids.iter().map(|item_id| {
705             tcx.hir().local_def_id(item_id.id).index
706         }));
707         self.encode_stability(def_id);
708         self.encode_deprecation(def_id);
709     }
710
711     fn encode_field(
712         &mut self,
713         adt_def_id: DefId,
714         variant_index: VariantIdx,
715         field_index: usize,
716     ) {
717         let tcx = self.tcx;
718         let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
719         let field = &variant.fields[field_index];
720
721         let def_id = field.did;
722         debug!("EncodeContext::encode_field({:?})", def_id);
723
724         let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
725         let variant_data = tcx.hir().expect_variant_data(variant_id);
726
727         record!(self.per_def.kind[def_id] <- EntryKind::Field);
728         record!(self.per_def.visibility[def_id] <- field.vis);
729         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
730         record!(self.per_def.attributes[def_id] <- &variant_data.fields()[field_index].attrs);
731         self.encode_stability(def_id);
732         self.encode_deprecation(def_id);
733         self.encode_item_type(def_id);
734         self.encode_generics(def_id);
735         self.encode_explicit_predicates(def_id);
736         self.encode_inferred_outlives(def_id);
737     }
738
739     fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) {
740         debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
741         let tcx = self.tcx;
742         let adt_def = tcx.adt_def(adt_def_id);
743         let variant = adt_def.non_enum_variant();
744
745         let data = VariantData {
746             ctor_kind: variant.ctor_kind,
747             discr: variant.discr,
748             ctor: Some(def_id.index),
749         };
750
751         let struct_id = tcx.hir().as_local_hir_id(adt_def_id).unwrap();
752         let struct_vis = &tcx.hir().expect_item(struct_id).vis;
753         let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
754         for field in &variant.fields {
755             if ctor_vis.is_at_least(field.vis, tcx) {
756                 ctor_vis = field.vis;
757             }
758         }
759
760         // If the structure is marked as non_exhaustive then lower the visibility
761         // to within the crate.
762         if adt_def.non_enum_variant().is_field_list_non_exhaustive() &&
763             ctor_vis == ty::Visibility::Public
764         {
765             ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
766         }
767
768         record!(self.per_def.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
769         record!(self.per_def.visibility[def_id] <- ctor_vis);
770         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
771         self.encode_stability(def_id);
772         self.encode_deprecation(def_id);
773         self.encode_item_type(def_id);
774         if variant.ctor_kind == CtorKind::Fn {
775             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
776             self.encode_variances_of(def_id);
777         }
778         self.encode_generics(def_id);
779         self.encode_explicit_predicates(def_id);
780         self.encode_inferred_outlives(def_id);
781         self.encode_optimized_mir(def_id);
782         self.encode_promoted_mir(def_id);
783     }
784
785     fn encode_generics(&mut self, def_id: DefId) {
786         debug!("EncodeContext::encode_generics({:?})", def_id);
787         record!(self.per_def.generics[def_id] <- self.tcx.generics_of(def_id));
788     }
789
790     fn encode_explicit_predicates(&mut self, def_id: DefId) {
791         debug!("EncodeContext::encode_explicit_predicates({:?})", def_id);
792         record!(self.per_def.explicit_predicates[def_id] <-
793             self.tcx.explicit_predicates_of(def_id));
794     }
795
796     fn encode_inferred_outlives(&mut self, def_id: DefId) {
797         debug!("EncodeContext::encode_inferred_outlives({:?})", def_id);
798         let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
799         if !inferred_outlives.is_empty() {
800             record!(self.per_def.inferred_outlives[def_id] <- inferred_outlives);
801         }
802     }
803
804     fn encode_super_predicates(&mut self, def_id: DefId) {
805         debug!("EncodeContext::encode_super_predicates({:?})", def_id);
806         record!(self.per_def.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
807     }
808
809     fn encode_info_for_trait_item(&mut self, def_id: DefId) {
810         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
811         let tcx = self.tcx;
812
813         let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
814         let ast_item = tcx.hir().expect_trait_item(hir_id);
815         let trait_item = tcx.associated_item(def_id);
816
817         let container = match trait_item.defaultness {
818             hir::Defaultness::Default { has_value: true } =>
819                 AssocContainer::TraitWithDefault,
820             hir::Defaultness::Default { has_value: false } =>
821                 AssocContainer::TraitRequired,
822             hir::Defaultness::Final =>
823                 span_bug!(ast_item.span, "traits cannot have final items"),
824         };
825
826         record!(self.per_def.kind[def_id] <- match trait_item.kind {
827             ty::AssocKind::Const => {
828                 let rendered =
829                     hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item));
830                 let rendered_const = self.lazy(RenderedConst(rendered));
831
832                 EntryKind::AssocConst(
833                     container,
834                     Default::default(),
835                     rendered_const,
836                 )
837             }
838             ty::AssocKind::Method => {
839                 let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind {
840                     let param_names = match *m {
841                         hir::TraitMethod::Required(ref names) => {
842                             self.encode_fn_param_names(names)
843                         }
844                         hir::TraitMethod::Provided(body) => {
845                             self.encode_fn_param_names_for_body(body)
846                         }
847                     };
848                     FnData {
849                         asyncness: m_sig.header.asyncness,
850                         constness: hir::Constness::NotConst,
851                         param_names,
852                     }
853                 } else {
854                     bug!()
855                 };
856                 EntryKind::Method(self.lazy(MethodData {
857                     fn_data,
858                     container,
859                     has_self: trait_item.method_has_self_argument,
860                 }))
861             }
862             ty::AssocKind::Type => EntryKind::AssocType(container),
863             ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"),
864         });
865         record!(self.per_def.visibility[def_id] <- trait_item.vis);
866         record!(self.per_def.span[def_id] <- ast_item.span);
867         record!(self.per_def.attributes[def_id] <- &ast_item.attrs);
868         self.encode_stability(def_id);
869         self.encode_const_stability(def_id);
870         self.encode_deprecation(def_id);
871         match trait_item.kind {
872             ty::AssocKind::Const |
873             ty::AssocKind::Method => {
874                 self.encode_item_type(def_id);
875             }
876             ty::AssocKind::Type => {
877                 if trait_item.defaultness.has_value() {
878                     self.encode_item_type(def_id);
879                 }
880             }
881             ty::AssocKind::OpaqueTy => unreachable!(),
882         }
883         if trait_item.kind == ty::AssocKind::Method {
884             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
885             self.encode_variances_of(def_id);
886         }
887         self.encode_generics(def_id);
888         self.encode_explicit_predicates(def_id);
889         self.encode_inferred_outlives(def_id);
890         self.encode_optimized_mir(def_id);
891         self.encode_promoted_mir(def_id);
892     }
893
894     fn metadata_output_only(&self) -> bool {
895         // MIR optimisation can be skipped when we're just interested in the metadata.
896         !self.tcx.sess.opts.output_types.should_codegen()
897     }
898
899     fn encode_info_for_impl_item(&mut self, def_id: DefId) {
900         debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
901         let tcx = self.tcx;
902
903         let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
904         let ast_item = self.tcx.hir().expect_impl_item(hir_id);
905         let impl_item = self.tcx.associated_item(def_id);
906
907         let container = match impl_item.defaultness {
908             hir::Defaultness::Default { has_value: true } => AssocContainer::ImplDefault,
909             hir::Defaultness::Final => AssocContainer::ImplFinal,
910             hir::Defaultness::Default { has_value: false } =>
911                 span_bug!(ast_item.span, "impl items always have values (currently)"),
912         };
913
914         record!(self.per_def.kind[def_id] <- match impl_item.kind {
915             ty::AssocKind::Const => {
916                 if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
917                     let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
918
919                     EntryKind::AssocConst(
920                         container,
921                         qualifs,
922                         self.encode_rendered_const_for_body(body_id))
923                 } else {
924                     bug!()
925                 }
926             }
927             ty::AssocKind::Method => {
928                 let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.kind {
929                     FnData {
930                         asyncness: sig.header.asyncness,
931                         constness: sig.header.constness,
932                         param_names: self.encode_fn_param_names_for_body(body),
933                     }
934                 } else {
935                     bug!()
936                 };
937                 EntryKind::Method(self.lazy(MethodData {
938                     fn_data,
939                     container,
940                     has_self: impl_item.method_has_self_argument,
941                 }))
942             }
943             ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container),
944             ty::AssocKind::Type => EntryKind::AssocType(container)
945         });
946         record!(self.per_def.visibility[def_id] <- impl_item.vis);
947         record!(self.per_def.span[def_id] <- ast_item.span);
948         record!(self.per_def.attributes[def_id] <- &ast_item.attrs);
949         self.encode_stability(def_id);
950         self.encode_const_stability(def_id);
951         self.encode_deprecation(def_id);
952         self.encode_item_type(def_id);
953         if impl_item.kind == ty::AssocKind::Method {
954             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
955             self.encode_variances_of(def_id);
956         }
957         self.encode_generics(def_id);
958         self.encode_explicit_predicates(def_id);
959         self.encode_inferred_outlives(def_id);
960         let mir = match ast_item.kind {
961             hir::ImplItemKind::Const(..) => true,
962             hir::ImplItemKind::Method(ref sig, _) => {
963                 let generics = self.tcx.generics_of(def_id);
964                 let needs_inline = (generics.requires_monomorphization(self.tcx) ||
965                                     tcx.codegen_fn_attrs(def_id).requests_inline()) &&
966                                     !self.metadata_output_only();
967                 let is_const_fn = sig.header.constness == hir::Constness::Const;
968                 let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
969                 needs_inline || is_const_fn || always_encode_mir
970             },
971             hir::ImplItemKind::OpaqueTy(..) |
972             hir::ImplItemKind::TyAlias(..) => false,
973         };
974         if mir {
975             self.encode_optimized_mir(def_id);
976             self.encode_promoted_mir(def_id);
977         }
978     }
979
980     fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId)
981                                     -> Lazy<[ast::Name]> {
982         self.tcx.dep_graph.with_ignore(|| {
983             let body = self.tcx.hir().body(body_id);
984             self.lazy(body.params.iter().map(|arg| {
985                 match arg.pat.kind {
986                     PatKind::Binding(_, _, ident, _) => ident.name,
987                     _ => kw::Invalid,
988                 }
989             }))
990         })
991     }
992
993     fn encode_fn_param_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Name]> {
994         self.lazy(param_names.iter().map(|ident| ident.name))
995     }
996
997     fn encode_optimized_mir(&mut self, def_id: DefId) {
998         debug!("EntryBuilder::encode_mir({:?})", def_id);
999         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
1000             record!(self.per_def.mir[def_id] <- self.tcx.optimized_mir(def_id));
1001         }
1002     }
1003
1004     fn encode_promoted_mir(&mut self, def_id: DefId) {
1005         debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
1006         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
1007             record!(self.per_def.promoted_mir[def_id] <- self.tcx.promoted_mir(def_id));
1008         }
1009     }
1010
1011     // Encodes the inherent implementations of a structure, enumeration, or trait.
1012     fn encode_inherent_implementations(&mut self, def_id: DefId) {
1013         debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
1014         let implementations = self.tcx.inherent_impls(def_id);
1015         if !implementations.is_empty() {
1016             record!(self.per_def.inherent_impls[def_id] <- implementations.iter().map(|&def_id| {
1017                 assert!(def_id.is_local());
1018                 def_id.index
1019             }));
1020         }
1021     }
1022
1023     fn encode_stability(&mut self, def_id: DefId) {
1024         debug!("EncodeContext::encode_stability({:?})", def_id);
1025         if let Some(stab) = self.tcx.lookup_stability(def_id) {
1026             record!(self.per_def.stability[def_id] <- stab)
1027         }
1028     }
1029
1030     fn encode_const_stability(&mut self, def_id: DefId) {
1031         debug!("EncodeContext::encode_const_stability({:?})", def_id);
1032         if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
1033             record!(self.per_def.const_stability[def_id] <- stab)
1034         }
1035     }
1036
1037     fn encode_deprecation(&mut self, def_id: DefId) {
1038         debug!("EncodeContext::encode_deprecation({:?})", def_id);
1039         if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
1040             record!(self.per_def.deprecation[def_id] <- depr);
1041         }
1042     }
1043
1044     fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> {
1045         let body = self.tcx.hir().body(body_id);
1046         let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_expr(&body.value));
1047         let rendered_const = &RenderedConst(rendered);
1048         self.lazy(rendered_const)
1049     }
1050
1051     fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) {
1052         let tcx = self.tcx;
1053
1054         debug!("EncodeContext::encode_info_for_item({:?})", def_id);
1055
1056         record!(self.per_def.kind[def_id] <- match item.kind {
1057             hir::ItemKind::Static(_, hir::Mutability::Mutable, _) => EntryKind::MutStatic,
1058             hir::ItemKind::Static(_, hir::Mutability::Immutable, _) => EntryKind::ImmStatic,
1059             hir::ItemKind::Const(_, body_id) => {
1060                 let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id);
1061                 EntryKind::Const(
1062                     qualifs,
1063                     self.encode_rendered_const_for_body(body_id)
1064                 )
1065             }
1066             hir::ItemKind::Fn(ref sig, .., body) => {
1067                 let data = FnData {
1068                     asyncness: sig.header.asyncness,
1069                     constness: sig.header.constness,
1070                     param_names: self.encode_fn_param_names_for_body(body),
1071                 };
1072
1073                 EntryKind::Fn(self.lazy(data))
1074             }
1075             hir::ItemKind::Mod(ref m) => {
1076                 return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis);
1077             }
1078             hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
1079             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
1080             hir::ItemKind::TyAlias(..) => EntryKind::Type,
1081             hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy,
1082             hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr),
1083             hir::ItemKind::Struct(ref struct_def, _) => {
1084                 let adt_def = self.tcx.adt_def(def_id);
1085                 let variant = adt_def.non_enum_variant();
1086
1087                 // Encode def_ids for each field and method
1088                 // for methods, write all the stuff get_trait_method
1089                 // needs to know
1090                 let ctor = struct_def.ctor_hir_id().map(|ctor_hir_id| {
1091                     self.tcx.hir().local_def_id(ctor_hir_id).index
1092                 });
1093
1094                 EntryKind::Struct(self.lazy(VariantData {
1095                     ctor_kind: variant.ctor_kind,
1096                     discr: variant.discr,
1097                     ctor,
1098                 }), adt_def.repr)
1099             }
1100             hir::ItemKind::Union(..) => {
1101                 let adt_def = self.tcx.adt_def(def_id);
1102                 let variant = adt_def.non_enum_variant();
1103
1104                 EntryKind::Union(self.lazy(VariantData {
1105                     ctor_kind: variant.ctor_kind,
1106                     discr: variant.discr,
1107                     ctor: None,
1108                 }), adt_def.repr)
1109             }
1110             hir::ItemKind::Impl(_, _, defaultness, ..) => {
1111                 let trait_ref = self.tcx.impl_trait_ref(def_id);
1112                 let polarity = self.tcx.impl_polarity(def_id);
1113                 let parent = if let Some(trait_ref) = trait_ref {
1114                     let trait_def = self.tcx.trait_def(trait_ref.def_id);
1115                     trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| {
1116                         match node {
1117                             specialization_graph::Node::Impl(parent) => Some(parent),
1118                             _ => None,
1119                         }
1120                     })
1121                 } else {
1122                     None
1123                 };
1124
1125                 // if this is an impl of `CoerceUnsized`, create its
1126                 // "unsized info", else just store None
1127                 let coerce_unsized_info =
1128                     trait_ref.and_then(|t| {
1129                         if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() {
1130                             Some(self.tcx.at(item.span).coerce_unsized_info(def_id))
1131                         } else {
1132                             None
1133                         }
1134                     });
1135
1136                 let data = ImplData {
1137                     polarity,
1138                     defaultness,
1139                     parent_impl: parent,
1140                     coerce_unsized_info,
1141                 };
1142
1143                 EntryKind::Impl(self.lazy(data))
1144             }
1145             hir::ItemKind::Trait(..) => {
1146                 let trait_def = self.tcx.trait_def(def_id);
1147                 let data = TraitData {
1148                     unsafety: trait_def.unsafety,
1149                     paren_sugar: trait_def.paren_sugar,
1150                     has_auto_impl: self.tcx.trait_is_auto(def_id),
1151                     is_marker: trait_def.is_marker,
1152                 };
1153
1154                 EntryKind::Trait(self.lazy(data))
1155             }
1156             hir::ItemKind::TraitAlias(..) => EntryKind::TraitAlias,
1157             hir::ItemKind::ExternCrate(_) |
1158             hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
1159         });
1160         record!(self.per_def.visibility[def_id] <-
1161             ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
1162         record!(self.per_def.span[def_id] <- item.span);
1163         record!(self.per_def.attributes[def_id] <- &item.attrs);
1164         // FIXME(eddyb) there should be a nicer way to do this.
1165         match item.kind {
1166             hir::ItemKind::ForeignMod(ref fm) => record!(self.per_def.children[def_id] <-
1167                 fm.items
1168                     .iter()
1169                     .map(|foreign_item| tcx.hir().local_def_id(
1170                         foreign_item.hir_id).index)
1171             ),
1172             hir::ItemKind::Enum(..) => record!(self.per_def.children[def_id] <-
1173                 self.tcx.adt_def(def_id).variants.iter().map(|v| {
1174                     assert!(v.def_id.is_local());
1175                     v.def_id.index
1176                 })
1177             ),
1178             hir::ItemKind::Struct(..) |
1179             hir::ItemKind::Union(..) => record!(self.per_def.children[def_id] <-
1180                 self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
1181                     assert!(f.did.is_local());
1182                     f.did.index
1183                 })
1184             ),
1185             hir::ItemKind::Impl(..) |
1186             hir::ItemKind::Trait(..) => {
1187                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
1188                 record!(self.per_def.children[def_id] <-
1189                     associated_item_def_ids.iter().map(|&def_id| {
1190                         assert!(def_id.is_local());
1191                         def_id.index
1192                     })
1193                 );
1194             }
1195             _ => {}
1196         }
1197         self.encode_stability(def_id);
1198         self.encode_const_stability(def_id);
1199         self.encode_deprecation(def_id);
1200         match item.kind {
1201             hir::ItemKind::Static(..) |
1202             hir::ItemKind::Const(..) |
1203             hir::ItemKind::Fn(..) |
1204             hir::ItemKind::TyAlias(..) |
1205             hir::ItemKind::OpaqueTy(..) |
1206             hir::ItemKind::Enum(..) |
1207             hir::ItemKind::Struct(..) |
1208             hir::ItemKind::Union(..) |
1209             hir::ItemKind::Impl(..) => self.encode_item_type(def_id),
1210             _ => {}
1211         }
1212         if let hir::ItemKind::Fn(..) = item.kind {
1213             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
1214         }
1215         if let hir::ItemKind::Impl(..) = item.kind {
1216             if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
1217                 record!(self.per_def.impl_trait_ref[def_id] <- trait_ref);
1218             }
1219         }
1220         self.encode_inherent_implementations(def_id);
1221         match item.kind {
1222             hir::ItemKind::Enum(..) |
1223             hir::ItemKind::Struct(..) |
1224             hir::ItemKind::Union(..) |
1225             hir::ItemKind::Fn(..) => self.encode_variances_of(def_id),
1226             _ => {}
1227         }
1228         match item.kind {
1229             hir::ItemKind::Static(..) |
1230             hir::ItemKind::Const(..) |
1231             hir::ItemKind::Fn(..) |
1232             hir::ItemKind::TyAlias(..) |
1233             hir::ItemKind::Enum(..) |
1234             hir::ItemKind::Struct(..) |
1235             hir::ItemKind::Union(..) |
1236             hir::ItemKind::Impl(..) |
1237             hir::ItemKind::OpaqueTy(..) |
1238             hir::ItemKind::Trait(..) |
1239             hir::ItemKind::TraitAlias(..) => {
1240                 self.encode_generics(def_id);
1241                 self.encode_explicit_predicates(def_id);
1242                 self.encode_inferred_outlives(def_id);
1243             }
1244             _ => {}
1245         }
1246         match item.kind {
1247             hir::ItemKind::Trait(..) |
1248             hir::ItemKind::TraitAlias(..) => {
1249                 self.encode_super_predicates(def_id);
1250             }
1251             _ => {}
1252         }
1253
1254         let mir = match item.kind {
1255             hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true,
1256             hir::ItemKind::Fn(ref sig, ..) => {
1257                 let generics = tcx.generics_of(def_id);
1258                 let needs_inline =
1259                     (generics.requires_monomorphization(tcx) ||
1260                         tcx.codegen_fn_attrs(def_id).requests_inline()) &&
1261                         !self.metadata_output_only();
1262                 let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
1263                 needs_inline || sig.header.constness == hir::Constness::Const || always_encode_mir
1264             }
1265             _ => false,
1266         };
1267         if mir {
1268             self.encode_optimized_mir(def_id);
1269             self.encode_promoted_mir(def_id);
1270         }
1271     }
1272
1273     /// Serialize the text of exported macros
1274     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) {
1275         use syntax::print::pprust;
1276         let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
1277         record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef {
1278             body: pprust::tts_to_string(macro_def.body.clone()),
1279             legacy: macro_def.legacy,
1280         })));
1281         record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
1282         record!(self.per_def.span[def_id] <- macro_def.span);
1283         record!(self.per_def.attributes[def_id] <- &macro_def.attrs);
1284         self.encode_stability(def_id);
1285         self.encode_deprecation(def_id);
1286     }
1287
1288     fn encode_info_for_generic_param(
1289         &mut self,
1290         def_id: DefId,
1291         kind: EntryKind<'tcx>,
1292         encode_type: bool,
1293     ) {
1294         record!(self.per_def.kind[def_id] <- kind);
1295         record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
1296         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
1297         if encode_type {
1298             self.encode_item_type(def_id);
1299         }
1300     }
1301
1302     fn encode_info_for_closure(&mut self, def_id: DefId) {
1303         debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
1304
1305         // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
1306         // including on the signature, which is inferred in `typeck_tables_of.
1307         let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
1308         let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id);
1309
1310         record!(self.per_def.kind[def_id] <- match ty.kind {
1311             ty::Generator(def_id, ..) => {
1312                 let layout = self.tcx.generator_layout(def_id);
1313                 let data = GeneratorData {
1314                     layout: layout.clone(),
1315                 };
1316                 EntryKind::Generator(self.lazy(data))
1317             }
1318
1319             ty::Closure(..) => EntryKind::Closure,
1320
1321             _ => bug!("closure that is neither generator nor closure"),
1322         });
1323         record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
1324         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
1325         record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
1326         self.encode_item_type(def_id);
1327         if let ty::Closure(def_id, substs) = ty.kind {
1328             record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx));
1329         }
1330         self.encode_generics(def_id);
1331         self.encode_optimized_mir(def_id);
1332         self.encode_promoted_mir(def_id);
1333     }
1334
1335     fn encode_info_for_anon_const(&mut self, def_id: DefId) {
1336         debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
1337         let id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
1338         let body_id = self.tcx.hir().body_owned_by(id);
1339         let const_data = self.encode_rendered_const_for_body(body_id);
1340         let qualifs = self.tcx.mir_const_qualif(def_id);
1341
1342         record!(self.per_def.kind[def_id] <- EntryKind::Const(qualifs, const_data));
1343         record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
1344         record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
1345         self.encode_item_type(def_id);
1346         self.encode_generics(def_id);
1347         self.encode_explicit_predicates(def_id);
1348         self.encode_inferred_outlives(def_id);
1349         self.encode_optimized_mir(def_id);
1350         self.encode_promoted_mir(def_id);
1351     }
1352
1353     fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> {
1354         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1355         self.lazy(used_libraries.iter().cloned())
1356     }
1357
1358     fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
1359         let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
1360         self.lazy(foreign_modules.iter().cloned())
1361     }
1362
1363     fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> {
1364         let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
1365         if is_proc_macro {
1366             let tcx = self.tcx;
1367             Some(self.lazy(tcx.hir().krate().items.values().filter_map(|item| {
1368                 if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) {
1369                     Some(item.hir_id.owner)
1370                 } else {
1371                     None
1372                 }
1373             })))
1374         } else {
1375             None
1376         }
1377     }
1378
1379     fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
1380         let crates = self.tcx.crates();
1381
1382         let mut deps = crates
1383             .iter()
1384             .map(|&cnum| {
1385                 let dep = CrateDep {
1386                     name: self.tcx.original_crate_name(cnum),
1387                     hash: self.tcx.crate_hash(cnum),
1388                     host_hash: self.tcx.crate_host_hash(cnum),
1389                     kind: self.tcx.dep_kind(cnum),
1390                     extra_filename: self.tcx.extra_filename(cnum),
1391                 };
1392                 (cnum, dep)
1393             })
1394             .collect::<Vec<_>>();
1395
1396         deps.sort_by_key(|&(cnum, _)| cnum);
1397
1398         {
1399             // Sanity-check the crate numbers
1400             let mut expected_cnum = 1;
1401             for &(n, _) in &deps {
1402                 assert_eq!(n, CrateNum::new(expected_cnum));
1403                 expected_cnum += 1;
1404             }
1405         }
1406
1407         // We're just going to write a list of crate 'name-hash-version's, with
1408         // the assumption that they are numbered 1 to n.
1409         // FIXME (#2166): This is not nearly enough to support correct versioning
1410         // but is enough to get transitive crate dependencies working.
1411         self.lazy(deps.iter().map(|&(_, ref dep)| dep))
1412     }
1413
1414     fn encode_lib_features(&mut self) -> Lazy<[(ast::Name, Option<ast::Name>)]> {
1415         let tcx = self.tcx;
1416         let lib_features = tcx.lib_features();
1417         self.lazy(lib_features.to_vec())
1418     }
1419
1420     fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
1421         let tcx = self.tcx;
1422         let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE);
1423         self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
1424     }
1425
1426     fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> {
1427         let tcx = self.tcx;
1428         let lang_items = tcx.lang_items();
1429         let lang_items = lang_items.items().iter();
1430         self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
1431             if let Some(def_id) = opt_def_id {
1432                 if def_id.is_local() {
1433                     return Some((def_id.index, i));
1434                 }
1435             }
1436             None
1437         }))
1438     }
1439
1440     fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
1441         let tcx = self.tcx;
1442         self.lazy(&tcx.lang_items().missing)
1443     }
1444
1445     /// Encodes an index, mapping each trait to its (local) implementations.
1446     fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
1447         debug!("EncodeContext::encode_impls()");
1448         let tcx = self.tcx;
1449         let mut visitor = ImplVisitor {
1450             tcx,
1451             impls: FxHashMap::default(),
1452         };
1453         tcx.hir().krate().visit_all_item_likes(&mut visitor);
1454
1455         let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
1456
1457         // Bring everything into deterministic order for hashing
1458         all_impls.sort_by_cached_key(|&(trait_def_id, _)| {
1459             tcx.def_path_hash(trait_def_id)
1460         });
1461
1462         let all_impls: Vec<_> = all_impls
1463             .into_iter()
1464             .map(|(trait_def_id, mut impls)| {
1465                 // Bring everything into deterministic order for hashing
1466                 impls.sort_by_cached_key(|&def_index| {
1467                     tcx.hir().definitions().def_path_hash(def_index)
1468                 });
1469
1470                 TraitImpls {
1471                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
1472                     impls: self.lazy(&impls),
1473                 }
1474             })
1475             .collect();
1476
1477         self.lazy(&all_impls)
1478     }
1479
1480     // Encodes all symbols exported from this crate into the metadata.
1481     //
1482     // This pass is seeded off the reachability list calculated in the
1483     // middle::reachable module but filters out items that either don't have a
1484     // symbol associated with them (they weren't translated) or if they're an FFI
1485     // definition (as that's not defined in this crate).
1486     fn encode_exported_symbols(&mut self,
1487                                exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)])
1488                                -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> {
1489         // The metadata symbol name is special. It should not show up in
1490         // downstream crates.
1491         let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
1492
1493         self.lazy(exported_symbols
1494             .iter()
1495             .filter(|&&(ref exported_symbol, _)| {
1496                 match *exported_symbol {
1497                     ExportedSymbol::NoDefId(symbol_name) => {
1498                         symbol_name != metadata_symbol_name
1499                     },
1500                     _ => true,
1501                 }
1502             })
1503             .cloned())
1504     }
1505
1506     fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
1507         let formats = self.tcx.dependency_formats(LOCAL_CRATE);
1508         for (ty, arr) in formats.iter() {
1509             if *ty != config::CrateType::Dylib {
1510                 continue;
1511             }
1512             return self.lazy(arr.iter().map(|slot| {
1513                 match *slot {
1514                     Linkage::NotLinked |
1515                     Linkage::IncludedFromDylib => None,
1516
1517                     Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
1518                     Linkage::Static => Some(LinkagePreference::RequireStatic),
1519                 }
1520             }));
1521         }
1522         Lazy::empty()
1523     }
1524
1525     fn encode_info_for_foreign_item(
1526         &mut self,
1527         def_id: DefId,
1528         nitem: &hir::ForeignItem,
1529     )  {
1530         let tcx = self.tcx;
1531
1532         debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id);
1533
1534         record!(self.per_def.kind[def_id] <- match nitem.kind {
1535             hir::ForeignItemKind::Fn(_, ref names, _) => {
1536                 let data = FnData {
1537                     asyncness: hir::IsAsync::NotAsync,
1538                     constness: if self.tcx.is_const_fn_raw(def_id) {
1539                         hir::Constness::Const
1540                     } else {
1541                         hir::Constness::NotConst
1542                     },
1543                     param_names: self.encode_fn_param_names(names),
1544                 };
1545                 EntryKind::ForeignFn(self.lazy(data))
1546             }
1547             hir::ForeignItemKind::Static(_, hir::Mutability::Mutable) =>
1548                 EntryKind::ForeignMutStatic,
1549             hir::ForeignItemKind::Static(_, hir::Mutability::Immutable) =>
1550                 EntryKind::ForeignImmStatic,
1551             hir::ForeignItemKind::Type => EntryKind::ForeignType,
1552         });
1553         record!(self.per_def.visibility[def_id] <-
1554             ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx));
1555         record!(self.per_def.span[def_id] <- nitem.span);
1556         record!(self.per_def.attributes[def_id] <- &nitem.attrs);
1557         self.encode_stability(def_id);
1558         self.encode_const_stability(def_id);
1559         self.encode_deprecation(def_id);
1560         self.encode_item_type(def_id);
1561         if let hir::ForeignItemKind::Fn(..) = nitem.kind {
1562             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
1563             self.encode_variances_of(def_id);
1564         }
1565         self.encode_generics(def_id);
1566         self.encode_explicit_predicates(def_id);
1567         self.encode_inferred_outlives(def_id);
1568     }
1569 }
1570
1571 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
1572 impl Visitor<'tcx> for EncodeContext<'tcx> {
1573     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1574         NestedVisitorMap::OnlyBodies(&self.tcx.hir())
1575     }
1576     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
1577         intravisit::walk_expr(self, ex);
1578         self.encode_info_for_expr(ex);
1579     }
1580     fn visit_anon_const(&mut self, c: &'tcx AnonConst) {
1581         intravisit::walk_anon_const(self, c);
1582         let def_id = self.tcx.hir().local_def_id(c.hir_id);
1583         self.encode_info_for_anon_const(def_id);
1584     }
1585     fn visit_item(&mut self, item: &'tcx hir::Item) {
1586         intravisit::walk_item(self, item);
1587         let def_id = self.tcx.hir().local_def_id(item.hir_id);
1588         match item.kind {
1589             hir::ItemKind::ExternCrate(_) |
1590             hir::ItemKind::Use(..) => {} // ignore these
1591             _ => self.encode_info_for_item(def_id, item),
1592         }
1593         self.encode_addl_info_for_item(item);
1594     }
1595     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
1596         intravisit::walk_foreign_item(self, ni);
1597         let def_id = self.tcx.hir().local_def_id(ni.hir_id);
1598         self.encode_info_for_foreign_item(def_id, ni);
1599     }
1600     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
1601         intravisit::walk_generics(self, generics);
1602         self.encode_info_for_generics(generics);
1603     }
1604     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
1605         self.encode_info_for_macro_def(macro_def);
1606     }
1607 }
1608
1609 impl EncodeContext<'tcx> {
1610     fn encode_fields(&mut self, adt_def_id: DefId) {
1611         let def = self.tcx.adt_def(adt_def_id);
1612         for (variant_index, variant) in def.variants.iter_enumerated() {
1613             for (field_index, _field) in variant.fields.iter().enumerate() {
1614                 // FIXME(eddyb) `adt_def_id` is leftover from incremental isolation,
1615                 // pass `def`, `variant` or `field` instead.
1616                 self.encode_field(adt_def_id, variant_index, field_index);
1617             }
1618         }
1619     }
1620
1621     fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
1622         for param in &generics.params {
1623             let def_id = self.tcx.hir().local_def_id(param.hir_id);
1624             match param.kind {
1625                 GenericParamKind::Lifetime { .. } => continue,
1626                 GenericParamKind::Type { ref default, .. } => {
1627                     self.encode_info_for_generic_param(
1628                         def_id,
1629                         EntryKind::TypeParam,
1630                         default.is_some(),
1631                     );
1632                 }
1633                 GenericParamKind::Const { .. } => {
1634                     self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true);
1635                 }
1636             }
1637         }
1638     }
1639
1640     fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
1641         match expr.kind {
1642             hir::ExprKind::Closure(..) => {
1643                 let def_id = self.tcx.hir().local_def_id(expr.hir_id);
1644                 self.encode_info_for_closure(def_id);
1645             }
1646             _ => {}
1647         }
1648     }
1649
1650     /// In some cases, along with the item itself, we also
1651     /// encode some sub-items. Usually we want some info from the item
1652     /// so it's easier to do that here then to wait until we would encounter
1653     /// normally in the visitor walk.
1654     fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
1655         let def_id = self.tcx.hir().local_def_id(item.hir_id);
1656         match item.kind {
1657             hir::ItemKind::Static(..) |
1658             hir::ItemKind::Const(..) |
1659             hir::ItemKind::Fn(..) |
1660             hir::ItemKind::Mod(..) |
1661             hir::ItemKind::ForeignMod(..) |
1662             hir::ItemKind::GlobalAsm(..) |
1663             hir::ItemKind::ExternCrate(..) |
1664             hir::ItemKind::Use(..) |
1665             hir::ItemKind::TyAlias(..) |
1666             hir::ItemKind::OpaqueTy(..) |
1667             hir::ItemKind::TraitAlias(..) => {
1668                 // no sub-item recording needed in these cases
1669             }
1670             hir::ItemKind::Enum(..) => {
1671                 self.encode_fields(def_id);
1672
1673                 let def = self.tcx.adt_def(def_id);
1674                 for (i, variant) in def.variants.iter_enumerated() {
1675                     // FIXME(eddyb) `def_id` is leftover from incremental isolation,
1676                     // pass `def` or `variant` instead.
1677                     self.encode_enum_variant_info(def_id, i);
1678
1679                     // FIXME(eddyb) `def_id` is leftover from incremental isolation,
1680                     // pass `def`, `variant` or `ctor_def_id` instead.
1681                     if let Some(_ctor_def_id) = variant.ctor_def_id {
1682                         self.encode_enum_variant_ctor(def_id, i);
1683                     }
1684                 }
1685             }
1686             hir::ItemKind::Struct(ref struct_def, _) => {
1687                 self.encode_fields(def_id);
1688
1689                 // If the struct has a constructor, encode it.
1690                 if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
1691                     let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
1692                     self.encode_struct_ctor(def_id, ctor_def_id);
1693                 }
1694             }
1695             hir::ItemKind::Union(..) => {
1696                 self.encode_fields(def_id);
1697             }
1698             hir::ItemKind::Impl(..) => {
1699                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
1700                     self.encode_info_for_impl_item(trait_item_def_id);
1701                 }
1702             }
1703             hir::ItemKind::Trait(..) => {
1704                 for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
1705                     self.encode_info_for_trait_item(item_def_id);
1706                 }
1707             }
1708         }
1709     }
1710 }
1711
1712 struct ImplVisitor<'tcx> {
1713     tcx: TyCtxt<'tcx>,
1714     impls: FxHashMap<DefId, Vec<DefIndex>>,
1715 }
1716
1717 impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
1718     fn visit_item(&mut self, item: &hir::Item) {
1719         if let hir::ItemKind::Impl(..) = item.kind {
1720             let impl_id = self.tcx.hir().local_def_id(item.hir_id);
1721             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
1722                 self.impls
1723                     .entry(trait_ref.def_id)
1724                     .or_default()
1725                     .push(impl_id.index);
1726             }
1727         }
1728     }
1729
1730     fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
1731
1732     fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
1733         // handled in `visit_item` above
1734     }
1735 }
1736
1737 // NOTE(eddyb) The following comment was preserved for posterity, even
1738 // though it's no longer relevant as EBML (which uses nested & tagged
1739 // "documents") was replaced with a scheme that can't go out of bounds.
1740 //
1741 // And here we run into yet another obscure archive bug: in which metadata
1742 // loaded from archives may have trailing garbage bytes. Awhile back one of
1743 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
1744 // and opt) by having ebml generate an out-of-bounds panic when looking at
1745 // metadata.
1746 //
1747 // Upon investigation it turned out that the metadata file inside of an rlib
1748 // (and ar archive) was being corrupted. Some compilations would generate a
1749 // metadata file which would end in a few extra bytes, while other
1750 // compilations would not have these extra bytes appended to the end. These
1751 // extra bytes were interpreted by ebml as an extra tag, so they ended up
1752 // being interpreted causing the out-of-bounds.
1753 //
1754 // The root cause of why these extra bytes were appearing was never
1755 // discovered, and in the meantime the solution we're employing is to insert
1756 // the length of the metadata to the start of the metadata. Later on this
1757 // will allow us to slice the metadata to the precise length that we just
1758 // generated regardless of trailing bytes that end up in it.
1759
1760 pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
1761     let mut encoder = opaque::Encoder::new(vec![]);
1762     encoder.emit_raw_bytes(METADATA_HEADER);
1763
1764     // Will be filled with the root position after encoding everything.
1765     encoder.emit_raw_bytes(&[0, 0, 0, 0]);
1766
1767     // Since encoding metadata is not in a query, and nothing is cached,
1768     // there's no need to do dep-graph tracking for any of it.
1769     let (root, mut result) = tcx.dep_graph.with_ignore(move || {
1770         let mut ecx = EncodeContext {
1771             opaque: encoder,
1772             tcx,
1773             per_def: Default::default(),
1774             lazy_state: LazyState::NoNode,
1775             type_shorthands: Default::default(),
1776             predicate_shorthands: Default::default(),
1777             source_file_cache: tcx.sess.source_map().files()[0].clone(),
1778             interpret_allocs: Default::default(),
1779             interpret_allocs_inverse: Default::default(),
1780         };
1781
1782         // Encode the rustc version string in a predictable location.
1783         rustc_version().encode(&mut ecx).unwrap();
1784
1785         // Encode all the entries and extra information in the crate,
1786         // culminating in the `CrateRoot` which points to all of it.
1787         let root = ecx.encode_crate_root();
1788         (root, ecx.opaque.into_inner())
1789     });
1790
1791     // Encode the root position.
1792     let header = METADATA_HEADER.len();
1793     let pos = root.position.get();
1794     result[header + 0] = (pos >> 24) as u8;
1795     result[header + 1] = (pos >> 16) as u8;
1796     result[header + 2] = (pos >> 8) as u8;
1797     result[header + 3] = (pos >> 0) as u8;
1798
1799     EncodedMetadata { raw_data: result }
1800 }