]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/encoder.rs
Rollup merge of #38649 - GuillaumeGomez:atomicint_docs, r=frewsxcv
[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 cstore;
12 use index::Index;
13 use schema::*;
14
15 use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
16 use rustc::hir::def;
17 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
18 use rustc::hir::map::definitions::DefPathTable;
19 use rustc::middle::dependency_format::Linkage;
20 use rustc::middle::lang_items;
21 use rustc::mir;
22 use rustc::traits::specialization_graph;
23 use rustc::ty::{self, Ty, TyCtxt};
24
25 use rustc::session::config::{self, CrateTypeProcMacro};
26 use rustc::util::nodemap::{FxHashMap, NodeSet};
27
28 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
29 use std::hash::Hash;
30 use std::intrinsics;
31 use std::io::prelude::*;
32 use std::io::Cursor;
33 use std::rc::Rc;
34 use std::u32;
35 use syntax::ast::{self, CRATE_NODE_ID};
36 use syntax::codemap::Spanned;
37 use syntax::attr;
38 use syntax::symbol::Symbol;
39 use syntax_pos;
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 use super::index_builder::{FromId, IndexBuilder, Untracked};
47
48 pub struct EncodeContext<'a, 'tcx: 'a> {
49     opaque: opaque::Encoder<'a>,
50     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
51     reexports: &'a def::ExportMap,
52     link_meta: &'a LinkMeta,
53     cstore: &'a cstore::CStore,
54     exported_symbols: &'a NodeSet,
55
56     lazy_state: LazyState,
57     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
58     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
59 }
60
61 macro_rules! encoder_methods {
62     ($($name:ident($ty:ty);)*) => {
63         $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
64             self.opaque.$name(value)
65         })*
66     }
67 }
68
69 impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
70     type Error = <opaque::Encoder<'a> as Encoder>::Error;
71
72     fn emit_nil(&mut self) -> Result<(), Self::Error> {
73         Ok(())
74     }
75
76     encoder_methods! {
77         emit_usize(usize);
78         emit_u64(u64);
79         emit_u32(u32);
80         emit_u16(u16);
81         emit_u8(u8);
82
83         emit_isize(isize);
84         emit_i64(i64);
85         emit_i32(i32);
86         emit_i16(i16);
87         emit_i8(i8);
88
89         emit_bool(bool);
90         emit_f64(f64);
91         emit_f32(f32);
92         emit_char(char);
93         emit_str(&str);
94     }
95 }
96
97 impl<'a, 'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'a, 'tcx> {
98     fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
99         self.emit_lazy_distance(lazy.position, Lazy::<T>::min_size())
100     }
101 }
102
103 impl<'a, 'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'a, 'tcx> {
104     fn specialized_encode(&mut self, seq: &LazySeq<T>) -> Result<(), Self::Error> {
105         self.emit_usize(seq.len)?;
106         if seq.len == 0 {
107             return Ok(());
108         }
109         self.emit_lazy_distance(seq.position, LazySeq::<T>::min_size(seq.len))
110     }
111 }
112
113 impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
114     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
115         self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands)
116     }
117 }
118
119 impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext<'a, 'tcx> {
120     fn specialized_encode(&mut self,
121                           predicates: &ty::GenericPredicates<'tcx>)
122                           -> Result<(), Self::Error> {
123         predicates.parent.encode(self)?;
124         predicates.predicates.len().encode(self)?;
125         for predicate in &predicates.predicates {
126             self.encode_with_shorthand(predicate, predicate, |ecx| &mut ecx.predicate_shorthands)?
127         }
128         Ok(())
129     }
130 }
131
132 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
133     pub fn position(&self) -> usize {
134         self.opaque.position()
135     }
136
137     fn emit_node<F: FnOnce(&mut Self, usize) -> R, R>(&mut self, f: F) -> R {
138         assert_eq!(self.lazy_state, LazyState::NoNode);
139         let pos = self.position();
140         self.lazy_state = LazyState::NodeStart(pos);
141         let r = f(self, pos);
142         self.lazy_state = LazyState::NoNode;
143         r
144     }
145
146     fn emit_lazy_distance(&mut self,
147                           position: usize,
148                           min_size: usize)
149                           -> Result<(), <Self as Encoder>::Error> {
150         let min_end = position + min_size;
151         let distance = match self.lazy_state {
152             LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
153             LazyState::NodeStart(start) => {
154                 assert!(min_end <= start);
155                 start - min_end
156             }
157             LazyState::Previous(last_min_end) => {
158                 assert!(last_min_end <= position);
159                 position - last_min_end
160             }
161         };
162         self.lazy_state = LazyState::Previous(min_end);
163         self.emit_usize(distance)
164     }
165
166     pub fn lazy<T: Encodable>(&mut self, value: &T) -> Lazy<T> {
167         self.emit_node(|ecx, pos| {
168             value.encode(ecx).unwrap();
169
170             assert!(pos + Lazy::<T>::min_size() <= ecx.position());
171             Lazy::with_position(pos)
172         })
173     }
174
175     fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
176         where I: IntoIterator<Item = T>,
177               T: Encodable
178     {
179         self.emit_node(|ecx, pos| {
180             let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count();
181
182             assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position());
183             LazySeq::with_position_and_length(pos, len)
184         })
185     }
186
187     fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
188         where I: IntoIterator<Item = &'b T>,
189               T: 'b + Encodable
190     {
191         self.emit_node(|ecx, pos| {
192             let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count();
193
194             assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position());
195             LazySeq::with_position_and_length(pos, len)
196         })
197     }
198
199     /// Encode the given value or a previously cached shorthand.
200     fn encode_with_shorthand<T, U, M>(&mut self,
201                                       value: &T,
202                                       variant: &U,
203                                       map: M)
204                                       -> Result<(), <Self as Encoder>::Error>
205         where M: for<'b> Fn(&'b mut Self) -> &'b mut FxHashMap<T, usize>,
206               T: Clone + Eq + Hash,
207               U: Encodable
208     {
209         let existing_shorthand = map(self).get(value).cloned();
210         if let Some(shorthand) = existing_shorthand {
211             return self.emit_usize(shorthand);
212         }
213
214         let start = self.position();
215         variant.encode(self)?;
216         let len = self.position() - start;
217
218         // The shorthand encoding uses the same usize as the
219         // discriminant, with an offset so they can't conflict.
220         let discriminant = unsafe { intrinsics::discriminant_value(variant) };
221         assert!(discriminant < SHORTHAND_OFFSET as u64);
222         let shorthand = start + SHORTHAND_OFFSET;
223
224         // Get the number of bits that leb128 could fit
225         // in the same space as the fully encoded type.
226         let leb128_bits = len * 7;
227
228         // Check that the shorthand is a not longer than the
229         // full encoding itself, i.e. it's an obvious win.
230         if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
231             map(self).insert(value.clone(), shorthand);
232         }
233
234         Ok(())
235     }
236
237     fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
238         let tcx = self.tcx;
239         self.lazy_seq(tcx.item_variances(def_id).iter().cloned())
240     }
241
242     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
243         let tcx = self.tcx;
244         self.lazy(&tcx.item_type(def_id))
245     }
246
247     /// Encode data for the given variant of the given ADT. The
248     /// index of the variant is untracked: this is ok because we
249     /// will have to lookup the adt-def by its id, and that gives us
250     /// the right to access any information in the adt-def (including,
251     /// e.g., the length of the various vectors).
252     fn encode_enum_variant_info(&mut self,
253                                 (enum_did, Untracked(index)): (DefId, Untracked<usize>))
254                                 -> Entry<'tcx> {
255         let tcx = self.tcx;
256         let def = tcx.lookup_adt_def(enum_did);
257         let variant = &def.variants[index];
258         let def_id = variant.did;
259
260         let data = VariantData {
261             ctor_kind: variant.ctor_kind,
262             disr: variant.disr_val.to_u64_unchecked(),
263             struct_ctor: None,
264         };
265
266         let enum_id = tcx.map.as_local_node_id(enum_did).unwrap();
267         let enum_vis = &tcx.map.expect_item(enum_id).vis;
268
269         Entry {
270             kind: EntryKind::Variant(self.lazy(&data)),
271             visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)),
272             span: self.lazy(&tcx.def_span(def_id)),
273             attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
274             children: self.lazy_seq(variant.fields.iter().map(|f| {
275                 assert!(f.did.is_local());
276                 f.did.index
277             })),
278             stability: self.encode_stability(def_id),
279             deprecation: self.encode_deprecation(def_id),
280
281             ty: Some(self.encode_item_type(def_id)),
282             inherent_impls: LazySeq::empty(),
283             variances: LazySeq::empty(),
284             generics: Some(self.encode_generics(def_id)),
285             predicates: Some(self.encode_predicates(def_id)),
286
287             ast: None,
288             mir: None,
289         }
290     }
291
292     fn encode_info_for_mod(&mut self,
293                            FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
294                                                                  &[ast::Attribute],
295                                                                  &hir::Visibility)>)
296                            -> Entry<'tcx> {
297         let tcx = self.tcx;
298         let def_id = tcx.map.local_def_id(id);
299
300         let data = ModData {
301             reexports: match self.reexports.get(&id) {
302                 Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
303                 _ => LazySeq::empty(),
304             },
305         };
306
307         Entry {
308             kind: EntryKind::Mod(self.lazy(&data)),
309             visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)),
310             span: self.lazy(&md.inner),
311             attributes: self.encode_attributes(attrs),
312             children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
313                 tcx.map.local_def_id(item_id.id).index
314             })),
315             stability: self.encode_stability(def_id),
316             deprecation: self.encode_deprecation(def_id),
317
318             ty: None,
319             inherent_impls: LazySeq::empty(),
320             variances: LazySeq::empty(),
321             generics: None,
322             predicates: None,
323
324             ast: None,
325             mir: None
326         }
327     }
328 }
329
330 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
331     fn encode_fields(&mut self, adt_def_id: DefId) {
332         let def = self.tcx.lookup_adt_def(adt_def_id);
333         for (variant_index, variant) in def.variants.iter().enumerate() {
334             for (field_index, field) in variant.fields.iter().enumerate() {
335                 self.record(field.did,
336                             EncodeContext::encode_field,
337                             (adt_def_id, Untracked((variant_index, field_index))));
338             }
339         }
340     }
341 }
342
343 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
344     /// Encode data for the given field of the given variant of the
345     /// given ADT. The indices of the variant/field are untracked:
346     /// this is ok because we will have to lookup the adt-def by its
347     /// id, and that gives us the right to access any information in
348     /// the adt-def (including, e.g., the length of the various
349     /// vectors).
350     fn encode_field(&mut self,
351                     (adt_def_id, Untracked((variant_index, field_index))): (DefId,
352                                                                             Untracked<(usize,
353                                                                                        usize)>))
354                     -> Entry<'tcx> {
355         let tcx = self.tcx;
356         let variant = &tcx.lookup_adt_def(adt_def_id).variants[variant_index];
357         let field = &variant.fields[field_index];
358
359         let def_id = field.did;
360         let variant_id = tcx.map.as_local_node_id(variant.did).unwrap();
361         let variant_data = tcx.map.expect_variant_data(variant_id);
362
363         Entry {
364             kind: EntryKind::Field,
365             visibility: self.lazy(&field.vis),
366             span: self.lazy(&tcx.def_span(def_id)),
367             attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
368             children: LazySeq::empty(),
369             stability: self.encode_stability(def_id),
370             deprecation: self.encode_deprecation(def_id),
371
372             ty: Some(self.encode_item_type(def_id)),
373             inherent_impls: LazySeq::empty(),
374             variances: LazySeq::empty(),
375             generics: Some(self.encode_generics(def_id)),
376             predicates: Some(self.encode_predicates(def_id)),
377
378             ast: None,
379             mir: None,
380         }
381     }
382
383     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
384         let tcx = self.tcx;
385         let variant = tcx.lookup_adt_def(adt_def_id).struct_variant();
386
387         let data = VariantData {
388             ctor_kind: variant.ctor_kind,
389             disr: variant.disr_val.to_u64_unchecked(),
390             struct_ctor: Some(def_id.index),
391         };
392
393         let struct_id = tcx.map.as_local_node_id(adt_def_id).unwrap();
394         let struct_vis = &tcx.map.expect_item(struct_id).vis;
395
396         Entry {
397             kind: EntryKind::Struct(self.lazy(&data)),
398             visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)),
399             span: self.lazy(&tcx.def_span(def_id)),
400             attributes: LazySeq::empty(),
401             children: LazySeq::empty(),
402             stability: self.encode_stability(def_id),
403             deprecation: self.encode_deprecation(def_id),
404
405             ty: Some(self.encode_item_type(def_id)),
406             inherent_impls: LazySeq::empty(),
407             variances: LazySeq::empty(),
408             generics: Some(self.encode_generics(def_id)),
409             predicates: Some(self.encode_predicates(def_id)),
410
411             ast: None,
412             mir: None,
413         }
414     }
415
416     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics<'tcx>> {
417         let tcx = self.tcx;
418         self.lazy(tcx.item_generics(def_id))
419     }
420
421     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
422         let tcx = self.tcx;
423         self.lazy(&tcx.item_predicates(def_id))
424     }
425
426     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
427         let tcx = self.tcx;
428
429         let node_id = tcx.map.as_local_node_id(def_id).unwrap();
430         let ast_item = tcx.map.expect_trait_item(node_id);
431         let trait_item = tcx.associated_item(def_id);
432
433         let container = match trait_item.defaultness {
434             hir::Defaultness::Default { has_value: true } =>
435                 AssociatedContainer::TraitWithDefault,
436             hir::Defaultness::Default { has_value: false } =>
437                 AssociatedContainer::TraitRequired,
438             hir::Defaultness::Final =>
439                 span_bug!(ast_item.span, "traits cannot have final items"),
440         };
441
442         let kind = match trait_item.kind {
443             ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
444             ty::AssociatedKind::Method => {
445                 let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
446                     let arg_names = match *m {
447                         hir::TraitMethod::Required(ref names) => {
448                             self.encode_fn_arg_names(names)
449                         }
450                         hir::TraitMethod::Provided(body) => {
451                             self.encode_fn_arg_names_for_body(body)
452                         }
453                     };
454                     FnData {
455                         constness: hir::Constness::NotConst,
456                         arg_names: arg_names
457                     }
458                 } else {
459                     bug!()
460                 };
461                 EntryKind::Method(self.lazy(&MethodData {
462                     fn_data: fn_data,
463                     container: container,
464                     has_self: trait_item.method_has_self_argument,
465                 }))
466             }
467             ty::AssociatedKind::Type => EntryKind::AssociatedType(container),
468         };
469
470         Entry {
471             kind: kind,
472             visibility: self.lazy(&trait_item.vis),
473             span: self.lazy(&ast_item.span),
474             attributes: self.encode_attributes(&ast_item.attrs),
475             children: LazySeq::empty(),
476             stability: self.encode_stability(def_id),
477             deprecation: self.encode_deprecation(def_id),
478
479             ty: match trait_item.kind {
480                 ty::AssociatedKind::Const |
481                 ty::AssociatedKind::Method => {
482                     Some(self.encode_item_type(def_id))
483                 }
484                 ty::AssociatedKind::Type => {
485                     if trait_item.defaultness.has_value() {
486                         Some(self.encode_item_type(def_id))
487                     } else {
488                         None
489                     }
490                 }
491             },
492             inherent_impls: LazySeq::empty(),
493             variances: LazySeq::empty(),
494             generics: Some(self.encode_generics(def_id)),
495             predicates: Some(self.encode_predicates(def_id)),
496
497             ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node {
498                 Some(self.encode_body(body))
499             } else {
500                 None
501             },
502             mir: self.encode_mir(def_id),
503         }
504     }
505
506     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
507         let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
508         let ast_item = self.tcx.map.expect_impl_item(node_id);
509         let impl_item = self.tcx.associated_item(def_id);
510
511         let container = match impl_item.defaultness {
512             hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault,
513             hir::Defaultness::Final => AssociatedContainer::ImplFinal,
514             hir::Defaultness::Default { has_value: false } =>
515                 span_bug!(ast_item.span, "impl items always have values (currently)"),
516         };
517
518         let kind = match impl_item.kind {
519             ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
520             ty::AssociatedKind::Method => {
521                 let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
522                     FnData {
523                         constness: sig.constness,
524                         arg_names: self.encode_fn_arg_names_for_body(body),
525                     }
526                 } else {
527                     bug!()
528                 };
529                 EntryKind::Method(self.lazy(&MethodData {
530                     fn_data: fn_data,
531                     container: container,
532                     has_self: impl_item.method_has_self_argument,
533                 }))
534             }
535             ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
536         };
537
538         let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node {
539             (Some(body), true)
540         } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
541             let generics = self.tcx.item_generics(def_id);
542             let types = generics.parent_types as usize + generics.types.len();
543             let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
544             let is_const_fn = sig.constness == hir::Constness::Const;
545             let ast = if is_const_fn { Some(body) } else { None };
546             let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
547             (ast, needs_inline || is_const_fn || always_encode_mir)
548         } else {
549             (None, false)
550         };
551
552         Entry {
553             kind: kind,
554             visibility: self.lazy(&impl_item.vis),
555             span: self.lazy(&ast_item.span),
556             attributes: self.encode_attributes(&ast_item.attrs),
557             children: LazySeq::empty(),
558             stability: self.encode_stability(def_id),
559             deprecation: self.encode_deprecation(def_id),
560
561             ty: Some(self.encode_item_type(def_id)),
562             inherent_impls: LazySeq::empty(),
563             variances: LazySeq::empty(),
564             generics: Some(self.encode_generics(def_id)),
565             predicates: Some(self.encode_predicates(def_id)),
566
567             ast: ast.map(|body| self.encode_body(body)),
568             mir: if mir { self.encode_mir(def_id) } else { None },
569         }
570     }
571
572     fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
573                                     -> LazySeq<ast::Name> {
574         let _ignore = self.tcx.dep_graph.in_ignore();
575         let body = self.tcx.map.body(body_id);
576         self.lazy_seq(body.arguments.iter().map(|arg| {
577             match arg.pat.node {
578                 PatKind::Binding(_, _, name, _) => name.node,
579                 _ => Symbol::intern("")
580             }
581         }))
582     }
583
584     fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
585                            -> LazySeq<ast::Name> {
586         self.lazy_seq(names.iter().map(|name| name.node))
587     }
588
589     fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
590         self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
591     }
592
593     // Encodes the inherent implementations of a structure, enumeration, or trait.
594     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
595         match self.tcx.inherent_impls.borrow().get(&def_id) {
596             None => LazySeq::empty(),
597             Some(implementations) => {
598                 self.lazy_seq(implementations.iter().map(|&def_id| {
599                     assert!(def_id.is_local());
600                     def_id.index
601                 }))
602             }
603         }
604     }
605
606     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
607         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
608     }
609
610     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
611         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
612     }
613
614     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
615         let tcx = self.tcx;
616
617         debug!("encoding info for item at {}",
618                tcx.sess.codemap().span_to_string(item.span));
619
620         let kind = match item.node {
621             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
622             hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
623             hir::ItemConst(..) => EntryKind::Const,
624             hir::ItemFn(_, _, constness, .., body) => {
625                 let data = FnData {
626                     constness: constness,
627                     arg_names: self.encode_fn_arg_names_for_body(body),
628                 };
629
630                 EntryKind::Fn(self.lazy(&data))
631             }
632             hir::ItemMod(ref m) => {
633                 return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
634             }
635             hir::ItemForeignMod(_) => EntryKind::ForeignMod,
636             hir::ItemTy(..) => EntryKind::Type,
637             hir::ItemEnum(..) => EntryKind::Enum,
638             hir::ItemStruct(ref struct_def, _) => {
639                 let variant = tcx.lookup_adt_def(def_id).struct_variant();
640
641                 // Encode def_ids for each field and method
642                 // for methods, write all the stuff get_trait_method
643                 // needs to know
644                 let struct_ctor = if !struct_def.is_struct() {
645                     Some(tcx.map.local_def_id(struct_def.id()).index)
646                 } else {
647                     None
648                 };
649                 EntryKind::Struct(self.lazy(&VariantData {
650                     ctor_kind: variant.ctor_kind,
651                     disr: variant.disr_val.to_u64_unchecked(),
652                     struct_ctor: struct_ctor,
653                 }))
654             }
655             hir::ItemUnion(..) => {
656                 let variant = tcx.lookup_adt_def(def_id).struct_variant();
657
658                 EntryKind::Union(self.lazy(&VariantData {
659                     ctor_kind: variant.ctor_kind,
660                     disr: variant.disr_val.to_u64_unchecked(),
661                     struct_ctor: None,
662                 }))
663             }
664             hir::ItemDefaultImpl(..) => {
665                 let data = ImplData {
666                     polarity: hir::ImplPolarity::Positive,
667                     parent_impl: None,
668                     coerce_unsized_kind: None,
669                     trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
670                 };
671
672                 EntryKind::DefaultImpl(self.lazy(&data))
673             }
674             hir::ItemImpl(_, polarity, ..) => {
675                 let trait_ref = tcx.impl_trait_ref(def_id);
676                 let parent = if let Some(trait_ref) = trait_ref {
677                     let trait_def = tcx.lookup_trait_def(trait_ref.def_id);
678                     trait_def.ancestors(def_id).skip(1).next().and_then(|node| {
679                         match node {
680                             specialization_graph::Node::Impl(parent) => Some(parent),
681                             _ => None,
682                         }
683                     })
684                 } else {
685                     None
686                 };
687
688                 let data = ImplData {
689                     polarity: polarity,
690                     parent_impl: parent,
691                     coerce_unsized_kind: tcx.custom_coerce_unsized_kinds
692                         .borrow()
693                         .get(&def_id)
694                         .cloned(),
695                     trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
696                 };
697
698                 EntryKind::Impl(self.lazy(&data))
699             }
700             hir::ItemTrait(..) => {
701                 let trait_def = tcx.lookup_trait_def(def_id);
702                 let data = TraitData {
703                     unsafety: trait_def.unsafety,
704                     paren_sugar: trait_def.paren_sugar,
705                     has_default_impl: tcx.trait_has_default_impl(def_id),
706                     super_predicates: self.lazy(&tcx.item_super_predicates(def_id)),
707                 };
708
709                 EntryKind::Trait(self.lazy(&data))
710             }
711             hir::ItemExternCrate(_) |
712             hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item),
713         };
714
715         Entry {
716             kind: kind,
717             visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)),
718             span: self.lazy(&item.span),
719             attributes: self.encode_attributes(&item.attrs),
720             children: match item.node {
721                 hir::ItemForeignMod(ref fm) => {
722                     self.lazy_seq(fm.items
723                         .iter()
724                         .map(|foreign_item| tcx.map.local_def_id(foreign_item.id).index))
725                 }
726                 hir::ItemEnum(..) => {
727                     let def = self.tcx.lookup_adt_def(def_id);
728                     self.lazy_seq(def.variants.iter().map(|v| {
729                         assert!(v.did.is_local());
730                         v.did.index
731                     }))
732                 }
733                 hir::ItemStruct(..) |
734                 hir::ItemUnion(..) => {
735                     let def = self.tcx.lookup_adt_def(def_id);
736                     self.lazy_seq(def.struct_variant().fields.iter().map(|f| {
737                         assert!(f.did.is_local());
738                         f.did.index
739                     }))
740                 }
741                 hir::ItemImpl(..) |
742                 hir::ItemTrait(..) => {
743                     self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| {
744                         assert!(def_id.is_local());
745                         def_id.index
746                     }))
747                 }
748                 _ => LazySeq::empty(),
749             },
750             stability: self.encode_stability(def_id),
751             deprecation: self.encode_deprecation(def_id),
752
753             ty: match item.node {
754                 hir::ItemStatic(..) |
755                 hir::ItemConst(..) |
756                 hir::ItemFn(..) |
757                 hir::ItemTy(..) |
758                 hir::ItemEnum(..) |
759                 hir::ItemStruct(..) |
760                 hir::ItemUnion(..) |
761                 hir::ItemImpl(..) => Some(self.encode_item_type(def_id)),
762                 _ => None,
763             },
764             inherent_impls: self.encode_inherent_implementations(def_id),
765             variances: match item.node {
766                 hir::ItemEnum(..) |
767                 hir::ItemStruct(..) |
768                 hir::ItemUnion(..) |
769                 hir::ItemTrait(..) => self.encode_item_variances(def_id),
770                 _ => LazySeq::empty(),
771             },
772             generics: match item.node {
773                 hir::ItemStatic(..) |
774                 hir::ItemConst(..) |
775                 hir::ItemFn(..) |
776                 hir::ItemTy(..) |
777                 hir::ItemEnum(..) |
778                 hir::ItemStruct(..) |
779                 hir::ItemUnion(..) |
780                 hir::ItemImpl(..) |
781                 hir::ItemTrait(..) => Some(self.encode_generics(def_id)),
782                 _ => None,
783             },
784             predicates: match item.node {
785                 hir::ItemStatic(..) |
786                 hir::ItemConst(..) |
787                 hir::ItemFn(..) |
788                 hir::ItemTy(..) |
789                 hir::ItemEnum(..) |
790                 hir::ItemStruct(..) |
791                 hir::ItemUnion(..) |
792                 hir::ItemImpl(..) |
793                 hir::ItemTrait(..) => Some(self.encode_predicates(def_id)),
794                 _ => None,
795             },
796
797             ast: match item.node {
798                 hir::ItemConst(_, body) |
799                 hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => {
800                     Some(self.encode_body(body))
801                 }
802                 _ => None,
803             },
804             mir: match item.node {
805                 hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => {
806                     self.encode_mir(def_id)
807                 }
808                 hir::ItemConst(..) => self.encode_mir(def_id),
809                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
810                     let tps_len = generics.ty_params.len();
811                     let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
812                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
813                     if needs_inline || constness == hir::Constness::Const || always_encode_mir {
814                         self.encode_mir(def_id)
815                     } else {
816                         None
817                     }
818                 }
819                 _ => None,
820             },
821         }
822     }
823
824     /// Serialize the text of exported macros
825     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> {
826         Entry {
827             kind: EntryKind::MacroDef(self.lazy(&MacroDef {
828                 body: ::syntax::print::pprust::tts_to_string(&macro_def.body)
829             })),
830             visibility: self.lazy(&ty::Visibility::Public),
831             span: self.lazy(&macro_def.span),
832
833             attributes: self.encode_attributes(&macro_def.attrs),
834             children: LazySeq::empty(),
835             stability: None,
836             deprecation: None,
837             ty: None,
838             inherent_impls: LazySeq::empty(),
839             variances: LazySeq::empty(),
840             generics: None,
841             predicates: None,
842             ast: None,
843             mir: None,
844         }
845     }
846 }
847
848 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
849     /// In some cases, along with the item itself, we also
850     /// encode some sub-items. Usually we want some info from the item
851     /// so it's easier to do that here then to wait until we would encounter
852     /// normally in the visitor walk.
853     fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
854         let def_id = self.tcx.map.local_def_id(item.id);
855         match item.node {
856             hir::ItemStatic(..) |
857             hir::ItemConst(..) |
858             hir::ItemFn(..) |
859             hir::ItemMod(..) |
860             hir::ItemForeignMod(..) |
861             hir::ItemExternCrate(..) |
862             hir::ItemUse(..) |
863             hir::ItemDefaultImpl(..) |
864             hir::ItemTy(..) => {
865                 // no sub-item recording needed in these cases
866             }
867             hir::ItemEnum(..) => {
868                 self.encode_fields(def_id);
869
870                 let def = self.tcx.lookup_adt_def(def_id);
871                 for (i, variant) in def.variants.iter().enumerate() {
872                     self.record(variant.did,
873                                 EncodeContext::encode_enum_variant_info,
874                                 (def_id, Untracked(i)));
875                 }
876             }
877             hir::ItemStruct(ref struct_def, _) => {
878                 self.encode_fields(def_id);
879
880                 // If the struct has a constructor, encode it.
881                 if !struct_def.is_struct() {
882                     let ctor_def_id = self.tcx.map.local_def_id(struct_def.id());
883                     self.record(ctor_def_id,
884                                 EncodeContext::encode_struct_ctor,
885                                 (def_id, ctor_def_id));
886                 }
887             }
888             hir::ItemUnion(..) => {
889                 self.encode_fields(def_id);
890             }
891             hir::ItemImpl(..) => {
892                 for &trait_item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
893                     self.record(trait_item_def_id,
894                                 EncodeContext::encode_info_for_impl_item,
895                                 trait_item_def_id);
896                 }
897             }
898             hir::ItemTrait(..) => {
899                 for &item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
900                     self.record(item_def_id,
901                                 EncodeContext::encode_info_for_trait_item,
902                                 item_def_id);
903                 }
904             }
905         }
906     }
907 }
908
909 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
910     fn encode_info_for_foreign_item(&mut self,
911                                     (def_id, nitem): (DefId, &hir::ForeignItem))
912                                     -> Entry<'tcx> {
913         let tcx = self.tcx;
914
915         debug!("writing foreign item {}", tcx.node_path_str(nitem.id));
916
917         let kind = match nitem.node {
918             hir::ForeignItemFn(_, ref names, _) => {
919                 let data = FnData {
920                     constness: hir::Constness::NotConst,
921                     arg_names: self.encode_fn_arg_names(names),
922                 };
923                 EntryKind::ForeignFn(self.lazy(&data))
924             }
925             hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic,
926             hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic,
927         };
928
929         Entry {
930             kind: kind,
931             visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
932             span: self.lazy(&nitem.span),
933             attributes: self.encode_attributes(&nitem.attrs),
934             children: LazySeq::empty(),
935             stability: self.encode_stability(def_id),
936             deprecation: self.encode_deprecation(def_id),
937
938             ty: Some(self.encode_item_type(def_id)),
939             inherent_impls: LazySeq::empty(),
940             variances: LazySeq::empty(),
941             generics: Some(self.encode_generics(def_id)),
942             predicates: Some(self.encode_predicates(def_id)),
943
944             ast: None,
945             mir: None,
946         }
947     }
948 }
949
950 struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
951     index: IndexBuilder<'a, 'b, 'tcx>,
952 }
953
954 impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
955     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
956         NestedVisitorMap::OnlyBodies(&self.index.tcx.map)
957     }
958     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
959         intravisit::walk_expr(self, ex);
960         self.index.encode_info_for_expr(ex);
961     }
962     fn visit_item(&mut self, item: &'tcx hir::Item) {
963         intravisit::walk_item(self, item);
964         let def_id = self.index.tcx.map.local_def_id(item.id);
965         match item.node {
966             hir::ItemExternCrate(_) |
967             hir::ItemUse(..) => (), // ignore these
968             _ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
969         }
970         self.index.encode_addl_info_for_item(item);
971     }
972     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
973         intravisit::walk_foreign_item(self, ni);
974         let def_id = self.index.tcx.map.local_def_id(ni.id);
975         self.index.record(def_id,
976                           EncodeContext::encode_info_for_foreign_item,
977                           (def_id, ni));
978     }
979     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
980         intravisit::walk_ty(self, ty);
981         self.index.encode_info_for_ty(ty);
982     }
983     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
984         let def_id = self.index.tcx.map.local_def_id(macro_def.id);
985         self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
986     }
987 }
988
989 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
990     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
991         if let hir::TyImplTrait(_) = ty.node {
992             let def_id = self.tcx.map.local_def_id(ty.id);
993             self.record(def_id, EncodeContext::encode_info_for_anon_ty, def_id);
994         }
995     }
996
997     fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
998         match expr.node {
999             hir::ExprClosure(..) => {
1000                 let def_id = self.tcx.map.local_def_id(expr.id);
1001                 self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
1002             }
1003             _ => {}
1004         }
1005     }
1006 }
1007
1008 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
1009     fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
1010         let tcx = self.tcx;
1011         Entry {
1012             kind: EntryKind::Type,
1013             visibility: self.lazy(&ty::Visibility::Public),
1014             span: self.lazy(&tcx.def_span(def_id)),
1015             attributes: LazySeq::empty(),
1016             children: LazySeq::empty(),
1017             stability: None,
1018             deprecation: None,
1019
1020             ty: Some(self.encode_item_type(def_id)),
1021             inherent_impls: LazySeq::empty(),
1022             variances: LazySeq::empty(),
1023             generics: Some(self.encode_generics(def_id)),
1024             predicates: Some(self.encode_predicates(def_id)),
1025
1026             ast: None,
1027             mir: None,
1028         }
1029     }
1030
1031     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
1032         let tcx = self.tcx;
1033
1034         let data = ClosureData {
1035             kind: tcx.closure_kind(def_id),
1036             ty: self.lazy(&tcx.tables().closure_tys[&def_id]),
1037         };
1038
1039         Entry {
1040             kind: EntryKind::Closure(self.lazy(&data)),
1041             visibility: self.lazy(&ty::Visibility::Public),
1042             span: self.lazy(&tcx.def_span(def_id)),
1043             attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
1044             children: LazySeq::empty(),
1045             stability: None,
1046             deprecation: None,
1047
1048             ty: Some(self.encode_item_type(def_id)),
1049             inherent_impls: LazySeq::empty(),
1050             variances: LazySeq::empty(),
1051             generics: Some(self.encode_generics(def_id)),
1052             predicates: None,
1053
1054             ast: None,
1055             mir: self.encode_mir(def_id),
1056         }
1057     }
1058
1059     fn encode_info_for_items(&mut self) -> Index {
1060         let krate = self.tcx.map.krate();
1061         let mut index = IndexBuilder::new(self);
1062         index.record(DefId::local(CRATE_DEF_INDEX),
1063                      EncodeContext::encode_info_for_mod,
1064                      FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
1065         let mut visitor = EncodeVisitor { index: index };
1066         krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
1067         for macro_def in &krate.exported_macros {
1068             visitor.visit_macro_def(macro_def);
1069         }
1070         visitor.index.into_items()
1071     }
1072
1073     fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
1074         self.lazy_seq_ref(attrs)
1075     }
1076
1077     fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
1078         fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
1079             // Pull the cnums and name,vers,hash out of cstore
1080             let mut deps = Vec::new();
1081             cstore.iter_crate_data(|cnum, val| {
1082                 deps.push((cnum, val.clone()));
1083             });
1084
1085             // Sort by cnum
1086             deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0));
1087
1088             // Sanity-check the crate numbers
1089             let mut expected_cnum = 1;
1090             for &(n, _) in &deps {
1091                 assert_eq!(n, CrateNum::new(expected_cnum));
1092                 expected_cnum += 1;
1093             }
1094
1095             deps
1096         }
1097
1098         // We're just going to write a list of crate 'name-hash-version's, with
1099         // the assumption that they are numbered 1 to n.
1100         // FIXME (#2166): This is not nearly enough to support correct versioning
1101         // but is enough to get transitive crate dependencies working.
1102         let deps = get_ordered_deps(self.cstore);
1103         self.lazy_seq(deps.iter().map(|&(_, ref dep)| {
1104             CrateDep {
1105                 name: dep.name(),
1106                 hash: dep.hash(),
1107                 kind: dep.dep_kind.get(),
1108             }
1109         }))
1110     }
1111
1112     fn encode_lang_items(&mut self) -> (LazySeq<(DefIndex, usize)>, LazySeq<lang_items::LangItem>) {
1113         let tcx = self.tcx;
1114         let lang_items = tcx.lang_items.items().iter();
1115         (self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
1116             if let Some(def_id) = opt_def_id {
1117                 if def_id.is_local() {
1118                     return Some((def_id.index, i));
1119                 }
1120             }
1121             None
1122         })),
1123          self.lazy_seq_ref(&tcx.lang_items.missing))
1124     }
1125
1126     fn encode_native_libraries(&mut self) -> LazySeq<NativeLibrary> {
1127         let used_libraries = self.tcx.sess.cstore.used_libraries();
1128         self.lazy_seq(used_libraries)
1129     }
1130
1131     fn encode_codemap(&mut self) -> LazySeq<syntax_pos::FileMap> {
1132         let codemap = self.tcx.sess.codemap();
1133         let all_filemaps = codemap.files.borrow();
1134         self.lazy_seq_ref(all_filemaps.iter()
1135             .filter(|filemap| {
1136                 // No need to re-export imported filemaps, as any downstream
1137                 // crate will import them from their original source.
1138                 !filemap.is_imported()
1139             })
1140             .map(|filemap| &**filemap))
1141     }
1142
1143     fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
1144         let definitions = self.tcx.map.definitions();
1145         self.lazy(definitions.def_path_table())
1146     }
1147 }
1148
1149 struct ImplVisitor<'a, 'tcx: 'a> {
1150     tcx: TyCtxt<'a, 'tcx, 'tcx>,
1151     impls: FxHashMap<DefId, Vec<DefIndex>>,
1152 }
1153
1154 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
1155     fn visit_item(&mut self, item: &hir::Item) {
1156         if let hir::ItemImpl(..) = item.node {
1157             let impl_id = self.tcx.map.local_def_id(item.id);
1158             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
1159                 self.impls
1160                     .entry(trait_ref.def_id)
1161                     .or_insert(vec![])
1162                     .push(impl_id.index);
1163             }
1164         }
1165     }
1166
1167     fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
1168
1169     fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
1170         // handled in `visit_item` above
1171     }
1172 }
1173
1174 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
1175     /// Encodes an index, mapping each trait to its (local) implementations.
1176     fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
1177         let mut visitor = ImplVisitor {
1178             tcx: self.tcx,
1179             impls: FxHashMap(),
1180         };
1181         self.tcx.map.krate().visit_all_item_likes(&mut visitor);
1182
1183         let all_impls: Vec<_> = visitor.impls
1184             .into_iter()
1185             .map(|(trait_def_id, impls)| {
1186                 TraitImpls {
1187                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
1188                     impls: self.lazy_seq(impls),
1189                 }
1190             })
1191             .collect();
1192
1193         self.lazy_seq(all_impls)
1194     }
1195
1196     // Encodes all symbols exported from this crate into the metadata.
1197     //
1198     // This pass is seeded off the reachability list calculated in the
1199     // middle::reachable module but filters out items that either don't have a
1200     // symbol associated with them (they weren't translated) or if they're an FFI
1201     // definition (as that's not defined in this crate).
1202     fn encode_exported_symbols(&mut self) -> LazySeq<DefIndex> {
1203         let exported_symbols = self.exported_symbols;
1204         let tcx = self.tcx;
1205         self.lazy_seq(exported_symbols.iter().map(|&id| tcx.map.local_def_id(id).index))
1206     }
1207
1208     fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreference>> {
1209         match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1210             Some(arr) => {
1211                 self.lazy_seq(arr.iter().map(|slot| {
1212                     match *slot {
1213                         Linkage::NotLinked |
1214                         Linkage::IncludedFromDylib => None,
1215
1216                         Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
1217                         Linkage::Static => Some(LinkagePreference::RequireStatic),
1218                     }
1219                 }))
1220             }
1221             None => LazySeq::empty(),
1222         }
1223     }
1224
1225     fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
1226         let mut i = self.position();
1227         let crate_deps = self.encode_crate_deps();
1228         let dylib_dependency_formats = self.encode_dylib_dependency_formats();
1229         let dep_bytes = self.position() - i;
1230
1231         // Encode the language items.
1232         i = self.position();
1233         let (lang_items, lang_items_missing) = self.encode_lang_items();
1234         let lang_item_bytes = self.position() - i;
1235
1236         // Encode the native libraries used
1237         i = self.position();
1238         let native_libraries = self.encode_native_libraries();
1239         let native_lib_bytes = self.position() - i;
1240
1241         // Encode codemap
1242         i = self.position();
1243         let codemap = self.encode_codemap();
1244         let codemap_bytes = self.position() - i;
1245
1246         // Encode DefPathTable
1247         i = self.position();
1248         let def_path_table = self.encode_def_path_table();
1249         let def_path_table_bytes = self.position() - i;
1250
1251         // Encode the def IDs of impls, for coherence checking.
1252         i = self.position();
1253         let impls = self.encode_impls();
1254         let impl_bytes = self.position() - i;
1255
1256         // Encode exported symbols info.
1257         i = self.position();
1258         let exported_symbols = self.encode_exported_symbols();
1259         let exported_symbols_bytes = self.position() - i;
1260
1261         // Encode and index the items.
1262         i = self.position();
1263         let items = self.encode_info_for_items();
1264         let item_bytes = self.position() - i;
1265
1266         i = self.position();
1267         let index = items.write_index(&mut self.opaque.cursor);
1268         let index_bytes = self.position() - i;
1269
1270         let tcx = self.tcx;
1271         let link_meta = self.link_meta;
1272         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
1273         let root = self.lazy(&CrateRoot {
1274             name: link_meta.crate_name,
1275             triple: tcx.sess.opts.target_triple.clone(),
1276             hash: link_meta.crate_hash,
1277             disambiguator: tcx.sess.local_crate_disambiguator(),
1278             panic_strategy: tcx.sess.panic_strategy(),
1279             plugin_registrar_fn: tcx.sess
1280                 .plugin_registrar_fn
1281                 .get()
1282                 .map(|id| tcx.map.local_def_id(id).index),
1283             macro_derive_registrar: if is_proc_macro {
1284                 let id = tcx.sess.derive_registrar_fn.get().unwrap();
1285                 Some(tcx.map.local_def_id(id).index)
1286             } else {
1287                 None
1288             },
1289
1290             crate_deps: crate_deps,
1291             dylib_dependency_formats: dylib_dependency_formats,
1292             lang_items: lang_items,
1293             lang_items_missing: lang_items_missing,
1294             native_libraries: native_libraries,
1295             codemap: codemap,
1296             def_path_table: def_path_table,
1297             impls: impls,
1298             exported_symbols: exported_symbols,
1299             index: index,
1300         });
1301
1302         let total_bytes = self.position();
1303
1304         if self.tcx.sess.meta_stats() {
1305             let mut zero_bytes = 0;
1306             for e in self.opaque.cursor.get_ref() {
1307                 if *e == 0 {
1308                     zero_bytes += 1;
1309                 }
1310             }
1311
1312             println!("metadata stats:");
1313             println!("             dep bytes: {}", dep_bytes);
1314             println!("       lang item bytes: {}", lang_item_bytes);
1315             println!("          native bytes: {}", native_lib_bytes);
1316             println!("         codemap bytes: {}", codemap_bytes);
1317             println!("            impl bytes: {}", impl_bytes);
1318             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
1319             println!("  def-path table bytes: {}", def_path_table_bytes);
1320             println!("            item bytes: {}", item_bytes);
1321             println!("           index bytes: {}", index_bytes);
1322             println!("            zero bytes: {}", zero_bytes);
1323             println!("           total bytes: {}", total_bytes);
1324         }
1325
1326         root
1327     }
1328 }
1329
1330 // NOTE(eddyb) The following comment was preserved for posterity, even
1331 // though it's no longer relevant as EBML (which uses nested & tagged
1332 // "documents") was replaced with a scheme that can't go out of bounds.
1333 //
1334 // And here we run into yet another obscure archive bug: in which metadata
1335 // loaded from archives may have trailing garbage bytes. Awhile back one of
1336 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
1337 // and opt) by having ebml generate an out-of-bounds panic when looking at
1338 // metadata.
1339 //
1340 // Upon investigation it turned out that the metadata file inside of an rlib
1341 // (and ar archive) was being corrupted. Some compilations would generate a
1342 // metadata file which would end in a few extra bytes, while other
1343 // compilations would not have these extra bytes appended to the end. These
1344 // extra bytes were interpreted by ebml as an extra tag, so they ended up
1345 // being interpreted causing the out-of-bounds.
1346 //
1347 // The root cause of why these extra bytes were appearing was never
1348 // discovered, and in the meantime the solution we're employing is to insert
1349 // the length of the metadata to the start of the metadata. Later on this
1350 // will allow us to slice the metadata to the precise length that we just
1351 // generated regardless of trailing bytes that end up in it.
1352
1353 pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1354                                  cstore: &cstore::CStore,
1355                                  reexports: &def::ExportMap,
1356                                  link_meta: &LinkMeta,
1357                                  exported_symbols: &NodeSet)
1358                                  -> Vec<u8> {
1359     let mut cursor = Cursor::new(vec![]);
1360     cursor.write_all(METADATA_HEADER).unwrap();
1361
1362     // Will be filed with the root position after encoding everything.
1363     cursor.write_all(&[0, 0, 0, 0]).unwrap();
1364
1365     let root = {
1366         let mut ecx = EncodeContext {
1367             opaque: opaque::Encoder::new(&mut cursor),
1368             tcx: tcx,
1369             reexports: reexports,
1370             link_meta: link_meta,
1371             cstore: cstore,
1372             exported_symbols: exported_symbols,
1373             lazy_state: LazyState::NoNode,
1374             type_shorthands: Default::default(),
1375             predicate_shorthands: Default::default(),
1376         };
1377
1378         // Encode the rustc version string in a predictable location.
1379         rustc_version().encode(&mut ecx).unwrap();
1380
1381         // Encode all the entries and extra information in the crate,
1382         // culminating in the `CrateRoot` which points to all of it.
1383         ecx.encode_crate_root()
1384     };
1385     let mut result = cursor.into_inner();
1386
1387     // Encode the root position.
1388     let header = METADATA_HEADER.len();
1389     let pos = root.position;
1390     result[header + 0] = (pos >> 24) as u8;
1391     result[header + 1] = (pos >> 16) as u8;
1392     result[header + 2] = (pos >> 8) as u8;
1393     result[header + 3] = (pos >> 0) as u8;
1394
1395     result
1396 }