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