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