]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/encoder.rs
888776eaa56105647b4846ec518241f41cf9f875
[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 // Metadata encoding
12
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
15
16 use common::*;
17 use cstore;
18 use decoder;
19 use tyencode;
20 use index::{self, IndexData};
21
22 use middle::cstore::{LOCAL_CRATE, CrateStore, InlinedItemRef, LinkMeta, tls};
23 use middle::def;
24 use middle::def_id::{CRATE_DEF_INDEX, DefId};
25 use middle::dependency_format::Linkage;
26 use middle::stability;
27 use middle::subst;
28 use middle::ty::{self, Ty};
29
30 use rustc::back::svh::Svh;
31 use rustc::front::map::{LinkedPath, PathElem, PathElems};
32 use rustc::front::map as ast_map;
33 use rustc::mir::repr::Mir;
34 use rustc::session::config;
35 use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet};
36
37 use serialize::Encodable;
38 use std::cell::RefCell;
39 use std::io::prelude::*;
40 use std::io::{Cursor, SeekFrom};
41 use std::rc::Rc;
42 use std::u32;
43 use syntax::abi;
44 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
45 use syntax::attr;
46 use syntax::attr::AttrMetaMethods;
47 use syntax::diagnostic::SpanHandler;
48 use syntax::parse::token::special_idents;
49 use syntax;
50 use rbml::writer::Encoder;
51
52 use rustc_front::hir;
53 use rustc_front::intravisit::Visitor;
54 use rustc_front::intravisit;
55
56 pub type EncodeInlinedItem<'a> =
57     Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
58
59 pub struct EncodeParams<'a, 'tcx: 'a> {
60     pub diag: &'a SpanHandler,
61     pub tcx: &'a ty::ctxt<'tcx>,
62     pub reexports: &'a def::ExportMap,
63     pub item_symbols: &'a RefCell<NodeMap<String>>,
64     pub link_meta: &'a LinkMeta,
65     pub cstore: &'a cstore::CStore,
66     pub encode_inlined_item: EncodeInlinedItem<'a>,
67     pub reachable: &'a NodeSet,
68     pub mir_map: &'a NodeMap<Mir<'tcx>>,
69 }
70
71 pub struct EncodeContext<'a, 'tcx: 'a> {
72     pub diag: &'a SpanHandler,
73     pub tcx: &'a ty::ctxt<'tcx>,
74     pub reexports: &'a def::ExportMap,
75     pub item_symbols: &'a RefCell<NodeMap<String>>,
76     pub link_meta: &'a LinkMeta,
77     pub cstore: &'a cstore::CStore,
78     pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
79     pub type_abbrevs: tyencode::abbrev_map<'tcx>,
80     pub reachable: &'a NodeSet,
81     pub mir_map: &'a NodeMap<Mir<'tcx>>,
82 }
83
84 impl<'a, 'tcx> EncodeContext<'a,'tcx> {
85     fn local_id(&self, def_id: DefId) -> NodeId {
86         self.tcx.map.as_local_node_id(def_id).unwrap()
87     }
88 }
89
90 /// "interned" entries referenced by id
91 #[derive(PartialEq, Eq, Hash)]
92 pub enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
93
94 struct CrateIndex<'tcx> {
95     items: IndexData,
96     xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
97 }
98
99 impl<'tcx> CrateIndex<'tcx> {
100     fn record(&mut self, id: DefId, rbml_w: &mut Encoder) {
101         let position = rbml_w.mark_stable_position();
102         self.items.record(id, position);
103     }
104
105     fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
106         let old_len = self.xrefs.len() as u32;
107         *self.xrefs.entry(xref).or_insert(old_len)
108     }
109 }
110
111 fn encode_name(rbml_w: &mut Encoder, name: Name) {
112     rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
113 }
114
115 fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
116     rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
117 }
118
119 /// For every DefId that we create a metadata item for, we include a
120 /// serialized copy of its DefKey, which allows us to recreate a path.
121 fn encode_def_id_and_key(ecx: &EncodeContext,
122                          rbml_w: &mut Encoder,
123                          def_id: DefId)
124 {
125     encode_def_id(rbml_w, def_id);
126     encode_def_key(ecx, rbml_w, def_id);
127 }
128
129 fn encode_def_key(ecx: &EncodeContext,
130                   rbml_w: &mut Encoder,
131                   def_id: DefId)
132 {
133     rbml_w.start_tag(tag_def_key);
134     let def_key = ecx.tcx.map.def_key(def_id);
135     def_key.encode(rbml_w);
136     rbml_w.end_tag();
137 }
138
139 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
140                               ecx: &EncodeContext<'a, 'tcx>,
141                               trait_ref: ty::TraitRef<'tcx>,
142                               tag: usize) {
143     let ty_str_ctxt = &tyencode::ctxt {
144         diag: ecx.diag,
145         ds: def_to_string,
146         tcx: ecx.tcx,
147         abbrevs: &ecx.type_abbrevs
148     };
149
150     rbml_w.start_tag(tag);
151     tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
152     rbml_w.end_tag();
153 }
154
155 // Item info table encoding
156 fn encode_family(rbml_w: &mut Encoder, c: char) {
157     rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
158 }
159
160 pub fn def_to_u64(did: DefId) -> u64 {
161     assert!(did.index.as_u32() < u32::MAX);
162     (did.krate as u64) << 32 | (did.index.as_usize() as u64)
163 }
164
165 pub fn def_to_string(did: DefId) -> String {
166     format!("{}:{}", did.krate, did.index.as_usize())
167 }
168
169 fn encode_item_variances(rbml_w: &mut Encoder,
170                          ecx: &EncodeContext,
171                          id: NodeId) {
172     let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id));
173     rbml_w.start_tag(tag_item_variances);
174     v.encode(rbml_w);
175     rbml_w.end_tag();
176 }
177
178 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
179                                              ecx: &EncodeContext<'a, 'tcx>,
180                                              index: &mut CrateIndex<'tcx>,
181                                              id: NodeId) {
182     encode_bounds_and_type(rbml_w,
183                            ecx,
184                            index,
185                            &ecx.tcx.lookup_item_type(ecx.tcx.map.local_def_id(id)),
186                            &ecx.tcx.lookup_predicates(ecx.tcx.map.local_def_id(id)));
187 }
188
189 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
190                                     ecx: &EncodeContext<'a, 'tcx>,
191                                     index: &mut CrateIndex<'tcx>,
192                                     scheme: &ty::TypeScheme<'tcx>,
193                                     predicates: &ty::GenericPredicates<'tcx>) {
194     encode_generics(rbml_w, ecx, index,
195                     &scheme.generics, &predicates, tag_item_generics);
196     encode_type(ecx, rbml_w, scheme.ty);
197 }
198
199 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
200     let id = def_to_u64(vid);
201     rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
202     rbml_w.wr_tagged_u64(tag_mod_child, id);
203 }
204
205 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
206                                     rbml_w: &mut Encoder,
207                                     closure_type: &ty::ClosureTy<'tcx>) {
208     let ty_str_ctxt = &tyencode::ctxt {
209         diag: ecx.diag,
210         ds: def_to_string,
211         tcx: ecx.tcx,
212         abbrevs: &ecx.type_abbrevs
213     };
214     tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
215 }
216
217 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
218                             rbml_w: &mut Encoder,
219                             typ: Ty<'tcx>) {
220     let ty_str_ctxt = &tyencode::ctxt {
221         diag: ecx.diag,
222         ds: def_to_string,
223         tcx: ecx.tcx,
224         abbrevs: &ecx.type_abbrevs
225     };
226     tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
227 }
228
229 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
230                                  rbml_w: &mut Encoder,
231                                 trait_ref: &ty::TraitRef<'tcx>) {
232     let ty_str_ctxt = &tyencode::ctxt {
233         diag: ecx.diag,
234         ds: def_to_string,
235         tcx: ecx.tcx,
236         abbrevs: &ecx.type_abbrevs
237     };
238     tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref);
239 }
240
241 pub fn write_region(ecx: &EncodeContext,
242                     rbml_w: &mut Encoder,
243                     r: ty::Region) {
244     let ty_str_ctxt = &tyencode::ctxt {
245         diag: ecx.diag,
246         ds: def_to_string,
247         tcx: ecx.tcx,
248         abbrevs: &ecx.type_abbrevs
249     };
250     tyencode::enc_region(rbml_w, ty_str_ctxt, r);
251 }
252
253 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
254                          rbml_w: &mut Encoder,
255                          typ: Ty<'tcx>) {
256     rbml_w.start_tag(tag_items_data_item_type);
257     write_type(ecx, rbml_w, typ);
258     rbml_w.end_tag();
259 }
260
261 fn encode_region(ecx: &EncodeContext,
262                  rbml_w: &mut Encoder,
263                  r: ty::Region) {
264     rbml_w.start_tag(tag_items_data_region);
265     write_region(ecx, rbml_w, r);
266     rbml_w.end_tag();
267 }
268
269 fn encode_symbol(ecx: &EncodeContext,
270                  rbml_w: &mut Encoder,
271                  id: NodeId) {
272     match ecx.item_symbols.borrow().get(&id) {
273         Some(x) => {
274             debug!("encode_symbol(id={}, str={})", id, *x);
275             rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
276         }
277         None => {
278             ecx.diag.handler().bug(
279                 &format!("encode_symbol: id not found {}", id));
280         }
281     }
282 }
283
284 fn encode_disr_val(_: &EncodeContext,
285                    rbml_w: &mut Encoder,
286                    disr_val: ty::Disr) {
287     rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_string());
288 }
289
290 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
291     rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
292 }
293
294 fn encode_struct_fields(rbml_w: &mut Encoder,
295                         variant: ty::VariantDef) {
296     for f in &variant.fields {
297         if f.name == special_idents::unnamed_field.name {
298             rbml_w.start_tag(tag_item_unnamed_field);
299         } else {
300             rbml_w.start_tag(tag_item_field);
301             encode_name(rbml_w, f.name);
302         }
303         encode_struct_field_family(rbml_w, f.vis);
304         encode_def_id(rbml_w, f.did);
305         rbml_w.end_tag();
306     }
307 }
308
309 fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
310                                       rbml_w: &mut Encoder,
311                                       id: NodeId,
312                                       vis: hir::Visibility,
313                                       index: &mut CrateIndex<'tcx>) {
314     debug!("encode_enum_variant_info(id={})", id);
315
316     let mut disr_val = 0;
317     let def = ecx.tcx.lookup_adt_def(ecx.tcx.map.local_def_id(id));
318     for variant in &def.variants {
319         let vid = variant.did;
320         let variant_node_id = ecx.local_id(vid);
321
322         if let ty::VariantKind::Struct = variant.kind() {
323             // tuple-like enum variant fields aren't really items so
324             // don't try to encode them.
325             for field in &variant.fields {
326                 encode_field(ecx, rbml_w, field, index);
327             }
328         }
329
330         index.record(vid, rbml_w);
331         rbml_w.start_tag(tag_items_data_item);
332         encode_def_id_and_key(ecx, rbml_w, vid);
333         encode_family(rbml_w, match variant.kind() {
334             ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
335             ty::VariantKind::Struct => 'V'
336         });
337         encode_name(rbml_w, variant.name);
338         encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(id));
339         encode_visibility(rbml_w, vis);
340
341         let attrs = ecx.tcx.get_attrs(vid);
342         encode_attributes(rbml_w, &attrs);
343         encode_repr_attrs(rbml_w, ecx, &attrs);
344
345         let stab = stability::lookup_stability(ecx.tcx, vid);
346         let depr = stability::lookup_deprecation(ecx.tcx, vid);
347         encode_stability(rbml_w, stab);
348         encode_deprecation(rbml_w, depr);
349
350         encode_struct_fields(rbml_w, variant);
351
352         let specified_disr_val = variant.disr_val;
353         if specified_disr_val != disr_val {
354             encode_disr_val(ecx, rbml_w, specified_disr_val);
355             disr_val = specified_disr_val;
356         }
357         encode_bounds_and_type_for_item(rbml_w, ecx, index, variant_node_id);
358
359         ecx.tcx.map.with_path(variant_node_id, |path| encode_path(rbml_w, path));
360         rbml_w.end_tag();
361         disr_val = disr_val.wrapping_add(1);
362     }
363 }
364
365 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
366     let path = path.collect::<Vec<_>>();
367     rbml_w.start_tag(tag_path);
368     rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
369     for pe in &path {
370         let tag = match *pe {
371             ast_map::PathMod(_) => tag_path_elem_mod,
372             ast_map::PathName(_) => tag_path_elem_name
373         };
374         rbml_w.wr_tagged_str(tag, &pe.name().as_str());
375     }
376     rbml_w.end_tag();
377 }
378
379 /// Iterates through "auxiliary node IDs", which are node IDs that describe
380 /// top-level items that are sub-items of the given item. Specifically:
381 ///
382 /// * For newtype structs, iterates through the node ID of the constructor.
383 fn each_auxiliary_node_id<F>(item: &hir::Item, callback: F) -> bool where
384     F: FnOnce(NodeId) -> bool,
385 {
386     let mut continue_ = true;
387     match item.node {
388         hir::ItemStruct(ref struct_def, _) => {
389             // If this is a newtype struct, return the constructor.
390             if struct_def.is_tuple() {
391                 continue_ = callback(struct_def.id());
392             }
393         }
394         _ => {}
395     }
396
397     continue_
398 }
399
400 fn encode_reexports(ecx: &EncodeContext,
401                     rbml_w: &mut Encoder,
402                     id: NodeId) {
403     debug!("(encoding info for module) encoding reexports for {}", id);
404     match ecx.reexports.get(&id) {
405         Some(exports) => {
406             debug!("(encoding info for module) found reexports for {}", id);
407             for exp in exports {
408                 debug!("(encoding info for module) reexport '{}' ({:?}) for \
409                         {}",
410                        exp.name,
411                        exp.def_id,
412                        id);
413                 rbml_w.start_tag(tag_items_data_item_reexport);
414                 rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
415                                      def_to_u64(exp.def_id));
416                 rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
417                                      &exp.name.as_str());
418                 rbml_w.end_tag();
419             }
420         },
421         None => debug!("(encoding info for module) found no reexports for {}", id),
422     }
423 }
424
425 fn encode_info_for_mod(ecx: &EncodeContext,
426                        rbml_w: &mut Encoder,
427                        md: &hir::Mod,
428                        attrs: &[ast::Attribute],
429                        id: NodeId,
430                        path: PathElems,
431                        name: Name,
432                        vis: hir::Visibility) {
433     rbml_w.start_tag(tag_items_data_item);
434     encode_def_id_and_key(ecx, rbml_w, ecx.tcx.map.local_def_id(id));
435     encode_family(rbml_w, 'm');
436     encode_name(rbml_w, name);
437     debug!("(encoding info for module) encoding info for module ID {}", id);
438
439     // Encode info about all the module children.
440     for item_id in &md.item_ids {
441         rbml_w.wr_tagged_u64(tag_mod_child,
442                              def_to_u64(ecx.tcx.map.local_def_id(item_id.id)));
443
444         let item = ecx.tcx.map.expect_item(item_id.id);
445         each_auxiliary_node_id(item, |auxiliary_node_id| {
446             rbml_w.wr_tagged_u64(tag_mod_child,
447                                  def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
448             true
449         });
450     }
451
452     encode_path(rbml_w, path.clone());
453     encode_visibility(rbml_w, vis);
454
455     let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(id));
456     let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(id));
457     encode_stability(rbml_w, stab);
458     encode_deprecation(rbml_w, depr);
459
460     // Encode the reexports of this module, if this module is public.
461     if vis == hir::Public {
462         debug!("(encoding info for module) encoding reexports for {}", id);
463         encode_reexports(ecx, rbml_w, id);
464     }
465     encode_attributes(rbml_w, attrs);
466
467     rbml_w.end_tag();
468 }
469
470 fn encode_struct_field_family(rbml_w: &mut Encoder,
471                               visibility: hir::Visibility) {
472     encode_family(rbml_w, match visibility {
473         hir::Public => 'g',
474         hir::Inherited => 'N'
475     });
476 }
477
478 fn encode_visibility(rbml_w: &mut Encoder, visibility: hir::Visibility) {
479     let ch = match visibility {
480         hir::Public => 'y',
481         hir::Inherited => 'i',
482     };
483     rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
484 }
485
486 fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) {
487     rbml_w.start_tag(tag_items_data_item_constness);
488     let ch = match constness {
489         hir::Constness::Const => 'c',
490         hir::Constness::NotConst => 'n',
491     };
492     rbml_w.wr_str(&ch.to_string());
493     rbml_w.end_tag();
494 }
495
496 fn encode_explicit_self(rbml_w: &mut Encoder,
497                         explicit_self: &ty::ExplicitSelfCategory) {
498     let tag = tag_item_trait_method_explicit_self;
499
500     // Encode the base self type.
501     match *explicit_self {
502         ty::StaticExplicitSelfCategory => {
503             rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
504         }
505         ty::ByValueExplicitSelfCategory => {
506             rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
507         }
508         ty::ByBoxExplicitSelfCategory => {
509             rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
510         }
511         ty::ByReferenceExplicitSelfCategory(_, m) => {
512             // FIXME(#4846) encode custom lifetime
513             let ch = encode_mutability(m);
514             rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]);
515         }
516     }
517
518     fn encode_mutability(m: hir::Mutability) -> u8 {
519         match m {
520             hir::MutImmutable => 'i' as u8,
521             hir::MutMutable => 'm' as u8,
522         }
523     }
524 }
525
526 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
527     rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
528 }
529
530 fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
531                           rbml_w: &mut Encoder,
532                           field: ty::FieldDef<'tcx>,
533                           index: &mut CrateIndex<'tcx>) {
534     let nm = field.name;
535     let id = ecx.local_id(field.did);
536
537     index.record(field.did, rbml_w);
538     rbml_w.start_tag(tag_items_data_item);
539     debug!("encode_field: encoding {} {}", nm, id);
540     encode_struct_field_family(rbml_w, field.vis);
541     encode_name(rbml_w, nm);
542     encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
543     encode_def_id_and_key(ecx, rbml_w, field.did);
544
545     let stab = stability::lookup_stability(ecx.tcx, field.did);
546     let depr = stability::lookup_deprecation(ecx.tcx, field.did);
547     encode_stability(rbml_w, stab);
548     encode_deprecation(rbml_w, depr);
549
550     rbml_w.end_tag();
551 }
552
553 fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
554                                          rbml_w: &mut Encoder,
555                                          name: Name,
556                                          ctor_id: NodeId,
557                                          index: &mut CrateIndex<'tcx>,
558                                          struct_id: NodeId) {
559     let ctor_def_id = ecx.tcx.map.local_def_id(ctor_id);
560
561     index.record(ctor_def_id, rbml_w);
562     rbml_w.start_tag(tag_items_data_item);
563     encode_def_id_and_key(ecx, rbml_w, ctor_def_id);
564     encode_family(rbml_w, 'o');
565     encode_bounds_and_type_for_item(rbml_w, ecx, index, ctor_id);
566     encode_name(rbml_w, name);
567     ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
568     encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id));
569
570     if ecx.item_symbols.borrow().contains_key(&ctor_id) {
571         encode_symbol(ecx, rbml_w, ctor_id);
572     }
573
574     let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
575     let depr= stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
576     encode_stability(rbml_w, stab);
577     encode_deprecation(rbml_w, depr);
578
579     // indicate that this is a tuple struct ctor, because downstream users will normally want
580     // the tuple struct definition, but without this there is no way for them to tell that
581     // they actually have a ctor rather than a normal function
582     rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]);
583
584     rbml_w.end_tag();
585 }
586
587 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
588                              ecx: &EncodeContext<'a, 'tcx>,
589                              index: &mut CrateIndex<'tcx>,
590                              generics: &ty::Generics<'tcx>,
591                              predicates: &ty::GenericPredicates<'tcx>,
592                              tag: usize)
593 {
594     rbml_w.start_tag(tag);
595
596     // Type parameters
597     let ty_str_ctxt = &tyencode::ctxt {
598         diag: ecx.diag,
599         ds: def_to_string,
600         tcx: ecx.tcx,
601         abbrevs: &ecx.type_abbrevs
602     };
603
604     for param in &generics.types {
605         rbml_w.start_tag(tag_type_param_def);
606         tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
607         rbml_w.end_tag();
608     }
609
610     // Region parameters
611     for param in &generics.regions {
612         rbml_w.start_tag(tag_region_param_def);
613
614         rbml_w.start_tag(tag_region_param_def_ident);
615         encode_name(rbml_w, param.name);
616         rbml_w.end_tag();
617
618         rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
619                              def_to_u64(param.def_id));
620
621         rbml_w.wr_tagged_u64(tag_region_param_def_space,
622                              param.space.to_uint() as u64);
623
624         rbml_w.wr_tagged_u64(tag_region_param_def_index,
625                              param.index as u64);
626
627         for &bound_region in &param.bounds {
628             encode_region(ecx, rbml_w, bound_region);
629         }
630
631         rbml_w.end_tag();
632     }
633
634     encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
635
636     rbml_w.end_tag();
637 }
638
639 fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
640                                              _ecx: &EncodeContext<'a,'tcx>,
641                                              index: &mut CrateIndex<'tcx>,
642                                              predicates: &ty::GenericPredicates<'tcx>)
643 {
644     for (space, _, predicate) in predicates.predicates.iter_enumerated() {
645         let tag = match space {
646             subst::TypeSpace => tag_type_predicate,
647             subst::SelfSpace => tag_self_predicate,
648             subst::FnSpace => tag_fn_predicate
649         };
650
651         rbml_w.wr_tagged_u32(tag,
652             index.add_xref(XRef::Predicate(predicate.clone())));
653     }
654 }
655
656 fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
657                               ecx: &EncodeContext<'a,'tcx>,
658                               index: &mut CrateIndex<'tcx>,
659                               predicates: &ty::GenericPredicates<'tcx>,
660                               tag: usize)
661 {
662     rbml_w.start_tag(tag);
663     encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
664     rbml_w.end_tag();
665 }
666
667 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
668                                      rbml_w: &mut Encoder,
669                                      index: &mut CrateIndex<'tcx>,
670                                      method_ty: &ty::Method<'tcx>) {
671     encode_def_id_and_key(ecx, rbml_w, method_ty.def_id);
672     encode_name(rbml_w, method_ty.name);
673     encode_generics(rbml_w, ecx, index,
674                     &method_ty.generics, &method_ty.predicates,
675                     tag_method_ty_generics);
676     encode_visibility(rbml_w, method_ty.vis);
677     encode_explicit_self(rbml_w, &method_ty.explicit_self);
678     match method_ty.explicit_self {
679         ty::StaticExplicitSelfCategory => {
680             encode_family(rbml_w, STATIC_METHOD_FAMILY);
681         }
682         _ => encode_family(rbml_w, METHOD_FAMILY)
683     }
684 }
685
686 fn encode_info_for_associated_const<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
687                                               rbml_w: &mut Encoder,
688                                               index: &mut CrateIndex<'tcx>,
689                                               associated_const: &ty::AssociatedConst,
690                                               impl_path: PathElems,
691                                               parent_id: NodeId,
692                                               impl_item_opt: Option<&hir::ImplItem>) {
693     debug!("encode_info_for_associated_const({:?},{:?})",
694            associated_const.def_id,
695            associated_const.name);
696
697     index.record(associated_const.def_id, rbml_w);
698     rbml_w.start_tag(tag_items_data_item);
699
700     encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
701     encode_name(rbml_w, associated_const.name);
702     encode_visibility(rbml_w, associated_const.vis);
703     encode_family(rbml_w, 'C');
704
705     encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
706     encode_item_sort(rbml_w, 'C');
707
708     encode_bounds_and_type_for_item(rbml_w, ecx, index,
709                                     ecx.local_id(associated_const.def_id));
710
711     let stab = stability::lookup_stability(ecx.tcx, associated_const.def_id);
712     let depr = stability::lookup_deprecation(ecx.tcx, associated_const.def_id);
713     encode_stability(rbml_w, stab);
714     encode_deprecation(rbml_w, depr);
715
716     let elem = ast_map::PathName(associated_const.name);
717     encode_path(rbml_w, impl_path.chain(Some(elem)));
718
719     if let Some(ii) = impl_item_opt {
720         encode_attributes(rbml_w, &ii.attrs);
721         encode_inlined_item(ecx,
722                             rbml_w,
723                             InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
724                                                      ii));
725     }
726
727     rbml_w.end_tag();
728 }
729
730 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
731                                     rbml_w: &mut Encoder,
732                                     index: &mut CrateIndex<'tcx>,
733                                     m: &ty::Method<'tcx>,
734                                     impl_path: PathElems,
735                                     is_default_impl: bool,
736                                     parent_id: NodeId,
737                                     impl_item_opt: Option<&hir::ImplItem>) {
738
739     debug!("encode_info_for_method: {:?} {:?}", m.def_id,
740            m.name);
741     index.record(m.def_id, rbml_w);
742     rbml_w.start_tag(tag_items_data_item);
743
744     encode_method_ty_fields(ecx, rbml_w, index, m);
745     encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
746     encode_item_sort(rbml_w, 'r');
747
748     let stab = stability::lookup_stability(ecx.tcx, m.def_id);
749     let depr = stability::lookup_deprecation(ecx.tcx, m.def_id);
750     encode_stability(rbml_w, stab);
751     encode_deprecation(rbml_w, depr);
752
753     let m_node_id = ecx.local_id(m.def_id);
754     encode_bounds_and_type_for_item(rbml_w, ecx, index, m_node_id);
755
756     let elem = ast_map::PathName(m.name);
757     encode_path(rbml_w, impl_path.chain(Some(elem)));
758     if let Some(impl_item) = impl_item_opt {
759         if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
760             encode_attributes(rbml_w, &impl_item.attrs);
761             let scheme = ecx.tcx.lookup_item_type(m.def_id);
762             let any_types = !scheme.generics.types.is_empty();
763             let needs_inline = any_types || is_default_impl ||
764                                attr::requests_inline(&impl_item.attrs);
765             if needs_inline || sig.constness == hir::Constness::Const {
766                 encode_inlined_item(ecx,
767                                     rbml_w,
768                                     InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
769                                                              impl_item));
770             }
771             encode_constness(rbml_w, sig.constness);
772             if !any_types {
773                 let m_id = ecx.local_id(m.def_id);
774                 encode_symbol(ecx, rbml_w, m_id);
775             }
776             encode_method_argument_names(rbml_w, &sig.decl);
777         }
778     }
779
780     rbml_w.end_tag();
781 }
782
783 fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
784                                              rbml_w: &mut Encoder,
785                                              index: &mut CrateIndex<'tcx>,
786                                              associated_type: &ty::AssociatedType<'tcx>,
787                                              impl_path: PathElems,
788                                              parent_id: NodeId,
789                                              impl_item_opt: Option<&hir::ImplItem>) {
790     debug!("encode_info_for_associated_type({:?},{:?})",
791            associated_type.def_id,
792            associated_type.name);
793
794     index.record(associated_type.def_id, rbml_w);
795     rbml_w.start_tag(tag_items_data_item);
796
797     encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
798     encode_name(rbml_w, associated_type.name);
799     encode_visibility(rbml_w, associated_type.vis);
800     encode_family(rbml_w, 'y');
801     encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
802     encode_item_sort(rbml_w, 't');
803
804     let stab = stability::lookup_stability(ecx.tcx, associated_type.def_id);
805     let depr = stability::lookup_deprecation(ecx.tcx, associated_type.def_id);
806     encode_stability(rbml_w, stab);
807     encode_deprecation(rbml_w, depr);
808
809     let elem = ast_map::PathName(associated_type.name);
810     encode_path(rbml_w, impl_path.chain(Some(elem)));
811
812     if let Some(ii) = impl_item_opt {
813         encode_attributes(rbml_w, &ii.attrs);
814     } else {
815         encode_predicates(rbml_w, ecx, index,
816                           &ecx.tcx.lookup_predicates(associated_type.def_id),
817                           tag_item_generics);
818     }
819
820     if let Some(ty) = associated_type.ty {
821         encode_type(ecx, rbml_w, ty);
822     }
823
824     rbml_w.end_tag();
825 }
826
827 fn encode_method_argument_names(rbml_w: &mut Encoder,
828                                 decl: &hir::FnDecl) {
829     rbml_w.start_tag(tag_method_argument_names);
830     for arg in &decl.inputs {
831         let tag = tag_method_argument_name;
832         if let hir::PatIdent(_, ref path1, _) = arg.pat.node {
833             let name = path1.node.name.as_str();
834             rbml_w.wr_tagged_bytes(tag, name.as_bytes());
835         } else {
836             rbml_w.wr_tagged_bytes(tag, &[]);
837         }
838     }
839     rbml_w.end_tag();
840 }
841
842 fn encode_repr_attrs(rbml_w: &mut Encoder,
843                      ecx: &EncodeContext,
844                      attrs: &[ast::Attribute]) {
845     let mut repr_attrs = Vec::new();
846     for attr in attrs {
847         repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
848                                                 attr));
849     }
850     rbml_w.start_tag(tag_items_data_item_repr);
851     repr_attrs.encode(rbml_w);
852     rbml_w.end_tag();
853 }
854
855 fn encode_inlined_item(ecx: &EncodeContext,
856                        rbml_w: &mut Encoder,
857                        ii: InlinedItemRef) {
858     let mut eii = ecx.encode_inlined_item.borrow_mut();
859     let eii: &mut EncodeInlinedItem = &mut *eii;
860     eii(ecx, rbml_w, ii);
861
862     encode_mir(ecx, rbml_w, ii);
863 }
864
865 fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, ii: InlinedItemRef) {
866     let id = match ii {
867         InlinedItemRef::Item(item) => item.id,
868         InlinedItemRef::TraitItem(_, trait_item) => trait_item.id,
869         InlinedItemRef::ImplItem(_, impl_item) => impl_item.id,
870         InlinedItemRef::Foreign(foreign_item) => foreign_item.id
871     };
872
873     if let Some(mir) = ecx.mir_map.get(&id) {
874         rbml_w.start_tag(tag_mir as usize);
875         Encodable::encode(mir, rbml_w).unwrap();
876         rbml_w.end_tag();
877     }
878 }
879
880 const FN_FAMILY: char = 'f';
881 const STATIC_METHOD_FAMILY: char = 'F';
882 const METHOD_FAMILY: char = 'h';
883
884 // Encodes the inherent implementations of a structure, enumeration, or trait.
885 fn encode_inherent_implementations(ecx: &EncodeContext,
886                                    rbml_w: &mut Encoder,
887                                    def_id: DefId) {
888     match ecx.tcx.inherent_impls.borrow().get(&def_id) {
889         None => {}
890         Some(implementations) => {
891             for &impl_def_id in implementations.iter() {
892                 rbml_w.start_tag(tag_items_data_item_inherent_impl);
893                 encode_def_id(rbml_w, impl_def_id);
894                 rbml_w.end_tag();
895             }
896         }
897     }
898 }
899
900 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
901     stab_opt.map(|stab| {
902         rbml_w.start_tag(tag_items_data_item_stability);
903         stab.encode(rbml_w).unwrap();
904         rbml_w.end_tag();
905     });
906 }
907
908 fn encode_deprecation(rbml_w: &mut Encoder, depr_opt: Option<attr::Deprecation>) {
909     depr_opt.map(|depr| {
910         rbml_w.start_tag(tag_items_data_item_deprecation);
911         depr.encode(rbml_w).unwrap();
912         rbml_w.end_tag();
913     });
914 }
915
916 fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
917                           rbml_w: &mut Encoder,
918                           xrefs: FnvHashMap<XRef<'tcx>, u32>)
919 {
920     let ty_str_ctxt = &tyencode::ctxt {
921         diag: ecx.diag,
922         ds: def_to_string,
923         tcx: ecx.tcx,
924         abbrevs: &ecx.type_abbrevs
925     };
926
927     let mut xref_positions = vec![0; xrefs.len()];
928     rbml_w.start_tag(tag_xref_data);
929     for (xref, id) in xrefs.into_iter() {
930         xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
931         match xref {
932             XRef::Predicate(p) => {
933                 tyencode::enc_predicate(rbml_w, ty_str_ctxt, &p)
934             }
935         }
936     }
937     rbml_w.end_tag();
938
939     rbml_w.start_tag(tag_xref_index);
940     index::write_dense_index(xref_positions, rbml_w.writer);
941     rbml_w.end_tag();
942 }
943
944 fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
945                                   rbml_w: &mut Encoder,
946                                   item: &hir::Item,
947                                   index: &mut CrateIndex<'tcx>,
948                                   path: PathElems,
949                                   vis: hir::Visibility) {
950     let tcx = ecx.tcx;
951
952     debug!("encoding info for item at {}",
953            tcx.sess.codemap().span_to_string(item.span));
954
955     let def_id = ecx.tcx.map.local_def_id(item.id);
956     let stab = stability::lookup_stability(tcx, ecx.tcx.map.local_def_id(item.id));
957     let depr = stability::lookup_deprecation(tcx, ecx.tcx.map.local_def_id(item.id));
958
959     match item.node {
960       hir::ItemStatic(_, m, _) => {
961         index.record(def_id, rbml_w);
962         rbml_w.start_tag(tag_items_data_item);
963         encode_def_id_and_key(ecx, rbml_w, def_id);
964         if m == hir::MutMutable {
965             encode_family(rbml_w, 'b');
966         } else {
967             encode_family(rbml_w, 'c');
968         }
969         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
970         encode_symbol(ecx, rbml_w, item.id);
971         encode_name(rbml_w, item.name);
972         encode_path(rbml_w, path);
973         encode_visibility(rbml_w, vis);
974         encode_stability(rbml_w, stab);
975         encode_deprecation(rbml_w, depr);
976         encode_attributes(rbml_w, &item.attrs);
977         rbml_w.end_tag();
978       }
979       hir::ItemConst(_, _) => {
980         index.record(def_id, rbml_w);
981         rbml_w.start_tag(tag_items_data_item);
982         encode_def_id_and_key(ecx, rbml_w, def_id);
983         encode_family(rbml_w, 'C');
984         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
985         encode_name(rbml_w, item.name);
986         encode_path(rbml_w, path);
987         encode_attributes(rbml_w, &item.attrs);
988         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
989         encode_visibility(rbml_w, vis);
990         encode_stability(rbml_w, stab);
991         encode_deprecation(rbml_w, depr);
992         rbml_w.end_tag();
993       }
994       hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
995         index.record(def_id, rbml_w);
996         rbml_w.start_tag(tag_items_data_item);
997         encode_def_id_and_key(ecx, rbml_w, def_id);
998         encode_family(rbml_w, FN_FAMILY);
999         let tps_len = generics.ty_params.len();
1000         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1001         encode_name(rbml_w, item.name);
1002         encode_path(rbml_w, path);
1003         encode_attributes(rbml_w, &item.attrs);
1004         let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
1005         if needs_inline || constness == hir::Constness::Const {
1006             encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1007         }
1008         if tps_len == 0 {
1009             encode_symbol(ecx, rbml_w, item.id);
1010         }
1011         encode_constness(rbml_w, constness);
1012         encode_visibility(rbml_w, vis);
1013         encode_stability(rbml_w, stab);
1014         encode_deprecation(rbml_w, depr);
1015         encode_method_argument_names(rbml_w, &**decl);
1016         rbml_w.end_tag();
1017       }
1018       hir::ItemMod(ref m) => {
1019         index.record(def_id, rbml_w);
1020         encode_info_for_mod(ecx,
1021                             rbml_w,
1022                             m,
1023                             &item.attrs,
1024                             item.id,
1025                             path,
1026                             item.name,
1027                             item.vis);
1028       }
1029       hir::ItemForeignMod(ref fm) => {
1030         index.record(def_id, rbml_w);
1031         rbml_w.start_tag(tag_items_data_item);
1032         encode_def_id_and_key(ecx, rbml_w, def_id);
1033         encode_family(rbml_w, 'n');
1034         encode_name(rbml_w, item.name);
1035         encode_path(rbml_w, path);
1036
1037         // Encode all the items in this module.
1038         for foreign_item in &fm.items {
1039             rbml_w.wr_tagged_u64(tag_mod_child,
1040                                  def_to_u64(ecx.tcx.map.local_def_id(foreign_item.id)));
1041         }
1042         encode_visibility(rbml_w, vis);
1043         encode_stability(rbml_w, stab);
1044         encode_deprecation(rbml_w, depr);
1045         rbml_w.end_tag();
1046       }
1047       hir::ItemTy(..) => {
1048         index.record(def_id, rbml_w);
1049         rbml_w.start_tag(tag_items_data_item);
1050         encode_def_id_and_key(ecx, rbml_w, def_id);
1051         encode_family(rbml_w, 'y');
1052         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1053         encode_name(rbml_w, item.name);
1054         encode_path(rbml_w, path);
1055         encode_visibility(rbml_w, vis);
1056         encode_stability(rbml_w, stab);
1057         encode_deprecation(rbml_w, depr);
1058         rbml_w.end_tag();
1059       }
1060       hir::ItemEnum(ref enum_definition, _) => {
1061         index.record(def_id, rbml_w);
1062
1063         rbml_w.start_tag(tag_items_data_item);
1064         encode_def_id_and_key(ecx, rbml_w, def_id);
1065         encode_family(rbml_w, 't');
1066         encode_item_variances(rbml_w, ecx, item.id);
1067         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1068         encode_name(rbml_w, item.name);
1069         encode_attributes(rbml_w, &item.attrs);
1070         encode_repr_attrs(rbml_w, ecx, &item.attrs);
1071         for v in &enum_definition.variants {
1072             encode_variant_id(rbml_w, ecx.tcx.map.local_def_id(v.node.data.id()));
1073         }
1074         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1075         encode_path(rbml_w, path);
1076
1077         // Encode inherent implementations for this enumeration.
1078         encode_inherent_implementations(ecx, rbml_w, def_id);
1079
1080         encode_visibility(rbml_w, vis);
1081         encode_stability(rbml_w, stab);
1082         encode_deprecation(rbml_w, depr);
1083         rbml_w.end_tag();
1084
1085         encode_enum_variant_info(ecx,
1086                                  rbml_w,
1087                                  item.id,
1088                                  vis,
1089                                  index);
1090       }
1091       hir::ItemStruct(ref struct_def, _) => {
1092         let def = ecx.tcx.lookup_adt_def(def_id);
1093         let variant = def.struct_variant();
1094
1095         /* Index the class*/
1096         index.record(def_id, rbml_w);
1097
1098         /* Now, make an item for the class itself */
1099         rbml_w.start_tag(tag_items_data_item);
1100         encode_def_id_and_key(ecx, rbml_w, def_id);
1101         encode_family(rbml_w, 'S');
1102         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1103
1104         encode_item_variances(rbml_w, ecx, item.id);
1105         encode_name(rbml_w, item.name);
1106         encode_attributes(rbml_w, &item.attrs);
1107         encode_path(rbml_w, path.clone());
1108         encode_stability(rbml_w, stab);
1109         encode_deprecation(rbml_w, depr);
1110         encode_visibility(rbml_w, vis);
1111         encode_repr_attrs(rbml_w, ecx, &item.attrs);
1112
1113         /* Encode def_ids for each field and method
1114          for methods, write all the stuff get_trait_method
1115         needs to know*/
1116         encode_struct_fields(rbml_w, variant);
1117
1118         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1119
1120         // Encode inherent implementations for this structure.
1121         encode_inherent_implementations(ecx, rbml_w, def_id);
1122
1123         if !struct_def.is_struct() {
1124             let ctor_did = ecx.tcx.map.local_def_id(struct_def.id());
1125             rbml_w.wr_tagged_u64(tag_items_data_item_struct_ctor,
1126                                  def_to_u64(ctor_did));
1127         }
1128
1129         rbml_w.end_tag();
1130
1131         for field in &variant.fields {
1132             encode_field(ecx, rbml_w, field, index);
1133         }
1134
1135         // If this is a tuple-like struct, encode the type of the constructor.
1136         if !struct_def.is_struct() {
1137             encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id(), index, item.id);
1138         }
1139       }
1140       hir::ItemDefaultImpl(unsafety, _) => {
1141           index.record(def_id, rbml_w);
1142           rbml_w.start_tag(tag_items_data_item);
1143           encode_def_id_and_key(ecx, rbml_w, def_id);
1144           encode_family(rbml_w, 'd');
1145           encode_name(rbml_w, item.name);
1146           encode_unsafety(rbml_w, unsafety);
1147
1148           let trait_ref = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)).unwrap();
1149           encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1150           rbml_w.end_tag();
1151       }
1152       hir::ItemImpl(unsafety, polarity, _, _, _, ref ast_items) => {
1153         // We need to encode information about the default methods we
1154         // have inherited, so we drive this based on the impl structure.
1155         let impl_items = tcx.impl_items.borrow();
1156         let items = impl_items.get(&def_id).unwrap();
1157
1158         index.record(def_id, rbml_w);
1159         rbml_w.start_tag(tag_items_data_item);
1160         encode_def_id_and_key(ecx, rbml_w, def_id);
1161         encode_family(rbml_w, 'i');
1162         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1163         encode_name(rbml_w, item.name);
1164         encode_attributes(rbml_w, &item.attrs);
1165         encode_unsafety(rbml_w, unsafety);
1166         encode_polarity(rbml_w, polarity);
1167
1168         match tcx.custom_coerce_unsized_kinds.borrow().get(&ecx.tcx.map.local_def_id(item.id)) {
1169             Some(&kind) => {
1170                 rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1171                 kind.encode(rbml_w);
1172                 rbml_w.end_tag();
1173             }
1174             None => {}
1175         }
1176
1177         for &item_def_id in items {
1178             rbml_w.start_tag(tag_item_impl_item);
1179             match item_def_id {
1180                 ty::ConstTraitItemId(item_def_id) => {
1181                     encode_def_id(rbml_w, item_def_id);
1182                     encode_item_sort(rbml_w, 'C');
1183                 }
1184                 ty::MethodTraitItemId(item_def_id) => {
1185                     encode_def_id(rbml_w, item_def_id);
1186                     encode_item_sort(rbml_w, 'r');
1187                 }
1188                 ty::TypeTraitItemId(item_def_id) => {
1189                     encode_def_id(rbml_w, item_def_id);
1190                     encode_item_sort(rbml_w, 't');
1191                 }
1192             }
1193             rbml_w.end_tag();
1194         }
1195         if let Some(trait_ref) = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)) {
1196             encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1197         }
1198         encode_path(rbml_w, path.clone());
1199         encode_stability(rbml_w, stab);
1200         encode_deprecation(rbml_w, depr);
1201         rbml_w.end_tag();
1202
1203         // Iterate down the trait items, emitting them. We rely on the
1204         // assumption that all of the actually implemented trait items
1205         // appear first in the impl structure, in the same order they do
1206         // in the ast. This is a little sketchy.
1207         let num_implemented_methods = ast_items.len();
1208         for (i, &trait_item_def_id) in items.iter().enumerate() {
1209             let ast_item = if i < num_implemented_methods {
1210                 Some(&ast_items[i])
1211             } else {
1212                 None
1213             };
1214
1215             match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
1216                 ty::ConstTraitItem(ref associated_const) => {
1217                     encode_info_for_associated_const(ecx,
1218                                                      rbml_w,
1219                                                      index,
1220                                                      &*associated_const,
1221                                                      path.clone(),
1222                                                      item.id,
1223                                                      ast_item)
1224                 }
1225                 ty::MethodTraitItem(ref method_type) => {
1226                     encode_info_for_method(ecx,
1227                                            rbml_w,
1228                                            index,
1229                                            &**method_type,
1230                                            path.clone(),
1231                                            false,
1232                                            item.id,
1233                                            ast_item)
1234                 }
1235                 ty::TypeTraitItem(ref associated_type) => {
1236                     encode_info_for_associated_type(ecx,
1237                                                     rbml_w,
1238                                                     index,
1239                                                     &**associated_type,
1240                                                     path.clone(),
1241                                                     item.id,
1242                                                     ast_item)
1243                 }
1244             }
1245         }
1246       }
1247       hir::ItemTrait(_, _, _, ref ms) => {
1248         index.record(def_id, rbml_w);
1249         rbml_w.start_tag(tag_items_data_item);
1250         encode_def_id_and_key(ecx, rbml_w, def_id);
1251         encode_family(rbml_w, 'I');
1252         encode_item_variances(rbml_w, ecx, item.id);
1253         let trait_def = tcx.lookup_trait_def(def_id);
1254         let trait_predicates = tcx.lookup_predicates(def_id);
1255         encode_unsafety(rbml_w, trait_def.unsafety);
1256         encode_paren_sugar(rbml_w, trait_def.paren_sugar);
1257         encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
1258         encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
1259         encode_generics(rbml_w, ecx, index,
1260                         &trait_def.generics, &trait_predicates,
1261                         tag_item_generics);
1262         encode_predicates(rbml_w, ecx, index,
1263                           &tcx.lookup_super_predicates(def_id),
1264                           tag_item_super_predicates);
1265         encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1266         encode_name(rbml_w, item.name);
1267         encode_attributes(rbml_w, &item.attrs);
1268         encode_visibility(rbml_w, vis);
1269         encode_stability(rbml_w, stab);
1270         encode_deprecation(rbml_w, depr);
1271         for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
1272             rbml_w.start_tag(tag_item_trait_item);
1273             match method_def_id {
1274                 ty::ConstTraitItemId(const_def_id) => {
1275                     encode_def_id(rbml_w, const_def_id);
1276                     encode_item_sort(rbml_w, 'C');
1277                 }
1278                 ty::MethodTraitItemId(method_def_id) => {
1279                     encode_def_id(rbml_w, method_def_id);
1280                     encode_item_sort(rbml_w, 'r');
1281                 }
1282                 ty::TypeTraitItemId(type_def_id) => {
1283                     encode_def_id(rbml_w, type_def_id);
1284                     encode_item_sort(rbml_w, 't');
1285                 }
1286             }
1287             rbml_w.end_tag();
1288
1289             rbml_w.wr_tagged_u64(tag_mod_child,
1290                                  def_to_u64(method_def_id.def_id()));
1291         }
1292         encode_path(rbml_w, path.clone());
1293
1294         // Encode inherent implementations for this trait.
1295         encode_inherent_implementations(ecx, rbml_w, def_id);
1296
1297         rbml_w.end_tag();
1298
1299         // Now output the trait item info for each trait item.
1300         let r = tcx.trait_item_def_ids(def_id);
1301         for (i, &item_def_id) in r.iter().enumerate() {
1302             assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
1303
1304             index.record(item_def_id.def_id(), rbml_w);
1305             rbml_w.start_tag(tag_items_data_item);
1306
1307             encode_parent_item(rbml_w, def_id);
1308
1309             let stab = stability::lookup_stability(tcx, item_def_id.def_id());
1310             let depr = stability::lookup_deprecation(tcx, item_def_id.def_id());
1311             encode_stability(rbml_w, stab);
1312             encode_deprecation(rbml_w, depr);
1313
1314             let trait_item_type =
1315                 tcx.impl_or_trait_item(item_def_id.def_id());
1316             let is_nonstatic_method;
1317             match trait_item_type {
1318                 ty::ConstTraitItem(associated_const) => {
1319                     encode_name(rbml_w, associated_const.name);
1320                     encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
1321                     encode_visibility(rbml_w, associated_const.vis);
1322
1323                     let elem = ast_map::PathName(associated_const.name);
1324                     encode_path(rbml_w,
1325                                 path.clone().chain(Some(elem)));
1326
1327                     encode_family(rbml_w, 'C');
1328
1329                     encode_bounds_and_type_for_item(rbml_w, ecx, index,
1330                                                     ecx.local_id(associated_const.def_id));
1331
1332                     is_nonstatic_method = false;
1333                 }
1334                 ty::MethodTraitItem(method_ty) => {
1335                     let method_def_id = item_def_id.def_id();
1336
1337                     encode_method_ty_fields(ecx, rbml_w, index, &*method_ty);
1338
1339                     let elem = ast_map::PathName(method_ty.name);
1340                     encode_path(rbml_w,
1341                                 path.clone().chain(Some(elem)));
1342
1343                     match method_ty.explicit_self {
1344                         ty::StaticExplicitSelfCategory => {
1345                             encode_family(rbml_w,
1346                                           STATIC_METHOD_FAMILY);
1347                         }
1348                         _ => {
1349                             encode_family(rbml_w,
1350                                           METHOD_FAMILY);
1351                         }
1352                     }
1353                     encode_bounds_and_type_for_item(rbml_w, ecx, index,
1354                                                     ecx.local_id(method_def_id));
1355
1356                     is_nonstatic_method = method_ty.explicit_self !=
1357                         ty::StaticExplicitSelfCategory;
1358                 }
1359                 ty::TypeTraitItem(associated_type) => {
1360                     encode_name(rbml_w, associated_type.name);
1361                     encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
1362
1363                     let elem = ast_map::PathName(associated_type.name);
1364                     encode_path(rbml_w,
1365                                 path.clone().chain(Some(elem)));
1366
1367                     encode_item_sort(rbml_w, 't');
1368                     encode_family(rbml_w, 'y');
1369
1370                     if let Some(ty) = associated_type.ty {
1371                         encode_type(ecx, rbml_w, ty);
1372                     }
1373
1374                     is_nonstatic_method = false;
1375                 }
1376             }
1377
1378             let trait_item = &ms[i];
1379             encode_attributes(rbml_w, &trait_item.attrs);
1380             match trait_item.node {
1381                 hir::ConstTraitItem(_, ref default) => {
1382                     if default.is_some() {
1383                         encode_item_sort(rbml_w, 'C');
1384                     } else {
1385                         encode_item_sort(rbml_w, 'c');
1386                     }
1387
1388                     encode_inlined_item(ecx, rbml_w,
1389                                         InlinedItemRef::TraitItem(def_id, trait_item));
1390                 }
1391                 hir::MethodTraitItem(ref sig, ref body) => {
1392                     // If this is a static method, we've already
1393                     // encoded this.
1394                     if is_nonstatic_method {
1395                         // FIXME: I feel like there is something funny
1396                         // going on.
1397                         encode_bounds_and_type_for_item(rbml_w, ecx, index,
1398                                                         ecx.local_id(item_def_id.def_id()));
1399                     }
1400
1401                     if body.is_some() {
1402                         encode_item_sort(rbml_w, 'p');
1403                         encode_inlined_item(ecx, rbml_w,
1404                                             InlinedItemRef::TraitItem(def_id, trait_item));
1405                     } else {
1406                         encode_item_sort(rbml_w, 'r');
1407                     }
1408                     encode_method_argument_names(rbml_w, &sig.decl);
1409                 }
1410
1411                 hir::TypeTraitItem(..) => {}
1412             }
1413
1414             rbml_w.end_tag();
1415         }
1416       }
1417       hir::ItemExternCrate(_) | hir::ItemUse(_) => {
1418         // these are encoded separately
1419       }
1420     }
1421 }
1422
1423 fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
1424                                           rbml_w: &mut Encoder,
1425                                           nitem: &hir::ForeignItem,
1426                                           index: &mut CrateIndex<'tcx>,
1427                                           path: PathElems,
1428                                           abi: abi::Abi) {
1429     let def_id = ecx.tcx.map.local_def_id(nitem.id);
1430
1431     index.record(def_id, rbml_w);
1432     rbml_w.start_tag(tag_items_data_item);
1433     encode_def_id_and_key(ecx, rbml_w, def_id);
1434     encode_visibility(rbml_w, nitem.vis);
1435     match nitem.node {
1436       hir::ForeignItemFn(ref fndecl, _) => {
1437         encode_family(rbml_w, FN_FAMILY);
1438         encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
1439         encode_name(rbml_w, nitem.name);
1440         if abi == abi::RustIntrinsic || abi == abi::PlatformIntrinsic {
1441             encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
1442         }
1443         encode_attributes(rbml_w, &*nitem.attrs);
1444         let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1445         let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1446         encode_stability(rbml_w, stab);
1447         encode_deprecation(rbml_w, depr);
1448         encode_symbol(ecx, rbml_w, nitem.id);
1449         encode_method_argument_names(rbml_w, &*fndecl);
1450       }
1451       hir::ForeignItemStatic(_, mutbl) => {
1452         if mutbl {
1453             encode_family(rbml_w, 'b');
1454         } else {
1455             encode_family(rbml_w, 'c');
1456         }
1457         encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
1458         encode_attributes(rbml_w, &*nitem.attrs);
1459         let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1460         let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1461         encode_stability(rbml_w, stab);
1462         encode_deprecation(rbml_w, depr);
1463         encode_symbol(ecx, rbml_w, nitem.id);
1464         encode_name(rbml_w, nitem.name);
1465       }
1466     }
1467     encode_path(rbml_w, path);
1468     rbml_w.end_tag();
1469 }
1470
1471 fn my_visit_expr(expr: &hir::Expr,
1472                  rbml_w: &mut Encoder,
1473                  ecx: &EncodeContext,
1474                  index: &mut CrateIndex) {
1475     match expr.node {
1476         hir::ExprClosure(..) => {
1477             let def_id = ecx.tcx.map.local_def_id(expr.id);
1478
1479             index.record(def_id, rbml_w);
1480
1481             rbml_w.start_tag(tag_items_data_item);
1482             encode_def_id_and_key(ecx, rbml_w, def_id);
1483
1484             rbml_w.start_tag(tag_items_closure_ty);
1485             write_closure_type(ecx, rbml_w, &ecx.tcx.tables.borrow().closure_tys[&def_id]);
1486             rbml_w.end_tag();
1487
1488             rbml_w.start_tag(tag_items_closure_kind);
1489             ecx.tcx.closure_kind(def_id).encode(rbml_w).unwrap();
1490             rbml_w.end_tag();
1491
1492             ecx.tcx.map.with_path(expr.id, |path| encode_path(rbml_w, path));
1493
1494             rbml_w.end_tag();
1495         }
1496         _ => { }
1497     }
1498 }
1499
1500 fn my_visit_item<'a, 'tcx>(i: &hir::Item,
1501                            rbml_w: &mut Encoder,
1502                            ecx: &EncodeContext<'a, 'tcx>,
1503                            index: &mut CrateIndex<'tcx>) {
1504     ecx.tcx.map.with_path(i.id, |path| {
1505         encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1506     });
1507 }
1508
1509 fn my_visit_foreign_item<'a, 'tcx>(ni: &hir::ForeignItem,
1510                                    rbml_w: &mut Encoder,
1511                                    ecx: &EncodeContext<'a, 'tcx>,
1512                                    index: &mut CrateIndex<'tcx>) {
1513     debug!("writing foreign item {}::{}",
1514             ecx.tcx.map.path_to_string(ni.id),
1515             ni.name);
1516
1517     let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1518     ecx.tcx.map.with_path(ni.id, |path| {
1519         encode_info_for_foreign_item(ecx, rbml_w,
1520                                      ni, index,
1521                                      path, abi);
1522     });
1523 }
1524
1525 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1526     rbml_w_for_visit_item: &'a mut Encoder<'b>,
1527     ecx: &'a EncodeContext<'c,'tcx>,
1528     index: &'a mut CrateIndex<'tcx>,
1529 }
1530
1531 impl<'a, 'b, 'c, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1532     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
1533         intravisit::walk_expr(self, ex);
1534         my_visit_expr(ex, self.rbml_w_for_visit_item, self.ecx, self.index);
1535     }
1536     fn visit_item(&mut self, i: &'tcx hir::Item) {
1537         intravisit::walk_item(self, i);
1538         my_visit_item(i, self.rbml_w_for_visit_item, self.ecx, self.index);
1539     }
1540     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
1541         intravisit::walk_foreign_item(self, ni);
1542         my_visit_foreign_item(ni, self.rbml_w_for_visit_item, self.ecx, self.index);
1543     }
1544 }
1545
1546 fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
1547                                    rbml_w: &mut Encoder)
1548                                    -> CrateIndex<'tcx> {
1549     let krate = ecx.tcx.map.krate();
1550
1551     let mut index = CrateIndex {
1552         items: IndexData::new(ecx.tcx.map.num_local_def_ids()),
1553         xrefs: FnvHashMap()
1554     };
1555     rbml_w.start_tag(tag_items_data);
1556
1557     index.record(DefId::local(CRATE_DEF_INDEX), rbml_w);
1558     encode_info_for_mod(ecx,
1559                         rbml_w,
1560                         &krate.module,
1561                         &[],
1562                         CRATE_NODE_ID,
1563                         [].iter().cloned().chain(LinkedPath::empty()),
1564                         syntax::parse::token::intern(&ecx.link_meta.crate_name),
1565                         hir::Public);
1566
1567     krate.visit_all_items(&mut EncodeVisitor {
1568         index: &mut index,
1569         ecx: ecx,
1570         rbml_w_for_visit_item: &mut *rbml_w,
1571     });
1572
1573     rbml_w.end_tag();
1574     index
1575 }
1576
1577 fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
1578     rbml_w.start_tag(tag_index);
1579     index.write_index(rbml_w.writer);
1580     rbml_w.end_tag();
1581 }
1582
1583 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1584     match mi.node {
1585       ast::MetaWord(ref name) => {
1586         rbml_w.start_tag(tag_meta_item_word);
1587         rbml_w.wr_tagged_str(tag_meta_item_name, name);
1588         rbml_w.end_tag();
1589       }
1590       ast::MetaNameValue(ref name, ref value) => {
1591         match value.node {
1592           ast::LitStr(ref value, _) => {
1593             rbml_w.start_tag(tag_meta_item_name_value);
1594             rbml_w.wr_tagged_str(tag_meta_item_name, name);
1595             rbml_w.wr_tagged_str(tag_meta_item_value, value);
1596             rbml_w.end_tag();
1597           }
1598           _ => {/* FIXME (#623): encode other variants */ }
1599         }
1600       }
1601       ast::MetaList(ref name, ref items) => {
1602         rbml_w.start_tag(tag_meta_item_list);
1603         rbml_w.wr_tagged_str(tag_meta_item_name, name);
1604         for inner_item in items {
1605             encode_meta_item(rbml_w, &**inner_item);
1606         }
1607         rbml_w.end_tag();
1608       }
1609     }
1610 }
1611
1612 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1613     rbml_w.start_tag(tag_attributes);
1614     for attr in attrs {
1615         rbml_w.start_tag(tag_attribute);
1616         rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1617         encode_meta_item(rbml_w, &*attr.node.value);
1618         rbml_w.end_tag();
1619     }
1620     rbml_w.end_tag();
1621 }
1622
1623 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: hir::Unsafety) {
1624     let byte: u8 = match unsafety {
1625         hir::Unsafety::Normal => 0,
1626         hir::Unsafety::Unsafe => 1,
1627     };
1628     rbml_w.wr_tagged_u8(tag_unsafety, byte);
1629 }
1630
1631 fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) {
1632     let byte: u8 = if paren_sugar {1} else {0};
1633     rbml_w.wr_tagged_u8(tag_paren_sugar, byte);
1634 }
1635
1636 fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) {
1637     let byte: u8 = if is_defaulted {1} else {0};
1638     rbml_w.wr_tagged_u8(tag_defaulted_trait, byte);
1639 }
1640
1641 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) {
1642     rbml_w.start_tag(tag_associated_type_names);
1643     for &name in names {
1644         rbml_w.wr_tagged_str(tag_associated_type_name, &name.as_str());
1645     }
1646     rbml_w.end_tag();
1647 }
1648
1649 fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
1650     let byte: u8 = match polarity {
1651         hir::ImplPolarity::Positive => 0,
1652         hir::ImplPolarity::Negative => 1,
1653     };
1654     rbml_w.wr_tagged_u8(tag_polarity, byte);
1655 }
1656
1657 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1658     fn get_ordered_deps(cstore: &cstore::CStore)
1659                         -> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
1660         // Pull the cnums and name,vers,hash out of cstore
1661         let mut deps = Vec::new();
1662         cstore.iter_crate_data(|cnum, val| {
1663             deps.push((cnum, val.clone()));
1664         });
1665
1666         // Sort by cnum
1667         deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0));
1668
1669         // Sanity-check the crate numbers
1670         let mut expected_cnum = 1;
1671         for &(n, _) in &deps {
1672             assert_eq!(n, expected_cnum);
1673             expected_cnum += 1;
1674         }
1675
1676         deps
1677     }
1678
1679     // We're just going to write a list of crate 'name-hash-version's, with
1680     // the assumption that they are numbered 1 to n.
1681     // FIXME (#2166): This is not nearly enough to support correct versioning
1682     // but is enough to get transitive crate dependencies working.
1683     rbml_w.start_tag(tag_crate_deps);
1684     for (_cnum, dep) in get_ordered_deps(cstore) {
1685         encode_crate_dep(rbml_w, &dep);
1686     }
1687     rbml_w.end_tag();
1688 }
1689
1690 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1691     rbml_w.start_tag(tag_lang_items);
1692
1693     for (i, &opt_def_id) in ecx.tcx.lang_items.items() {
1694         if let Some(def_id) = opt_def_id {
1695             if def_id.is_local() {
1696                 rbml_w.start_tag(tag_lang_items_item);
1697                 rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
1698                 rbml_w.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32());
1699                 rbml_w.end_tag();
1700             }
1701         }
1702     }
1703
1704     for i in &ecx.tcx.lang_items.missing {
1705         rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1706     }
1707
1708     rbml_w.end_tag();   // tag_lang_items
1709 }
1710
1711 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1712     rbml_w.start_tag(tag_native_libraries);
1713
1714     for &(ref lib, kind) in ecx.tcx.sess.cstore.used_libraries().iter() {
1715         match kind {
1716             cstore::NativeStatic => {} // these libraries are not propagated
1717             cstore::NativeFramework | cstore::NativeUnknown => {
1718                 rbml_w.start_tag(tag_native_libraries_lib);
1719                 rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32);
1720                 rbml_w.wr_tagged_str(tag_native_libraries_name, lib);
1721                 rbml_w.end_tag();
1722             }
1723         }
1724     }
1725
1726     rbml_w.end_tag();
1727 }
1728
1729 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1730     match ecx.tcx.sess.plugin_registrar_fn.get() {
1731         Some(id) => {
1732             let def_id = ecx.tcx.map.local_def_id(id);
1733             rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32());
1734         }
1735         None => {}
1736     }
1737 }
1738
1739 fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1740     rbml_w.start_tag(tag_codemap);
1741     let codemap = ecx.tcx.sess.codemap();
1742
1743     for filemap in &codemap.files.borrow()[..] {
1744
1745         if filemap.lines.borrow().is_empty() || filemap.is_imported() {
1746             // No need to export empty filemaps, as they can't contain spans
1747             // that need translation.
1748             // Also no need to re-export imported filemaps, as any downstream
1749             // crate will import them from their original source.
1750             continue;
1751         }
1752
1753         rbml_w.start_tag(tag_codemap_filemap);
1754         filemap.encode(rbml_w);
1755         rbml_w.end_tag();
1756     }
1757
1758     rbml_w.end_tag();
1759 }
1760
1761 /// Serialize the text of the exported macros
1762 fn encode_macro_defs(rbml_w: &mut Encoder,
1763                      krate: &hir::Crate) {
1764     rbml_w.start_tag(tag_macro_defs);
1765     for def in &krate.exported_macros {
1766         rbml_w.start_tag(tag_macro_def);
1767
1768         encode_name(rbml_w, def.name);
1769         encode_attributes(rbml_w, &def.attrs);
1770
1771         rbml_w.wr_tagged_str(tag_macro_def_body,
1772                              &::syntax::print::pprust::tts_to_string(&def.body));
1773
1774         rbml_w.end_tag();
1775     }
1776     rbml_w.end_tag();
1777 }
1778
1779 fn encode_struct_field_attrs(ecx: &EncodeContext,
1780                              rbml_w: &mut Encoder,
1781                              krate: &hir::Crate) {
1782     struct StructFieldVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1783         ecx: &'a EncodeContext<'b, 'tcx>,
1784         rbml_w: &'a mut Encoder<'c>,
1785     }
1786
1787     impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'c, 'tcx> {
1788         fn visit_struct_field(&mut self, field: &hir::StructField) {
1789             self.rbml_w.start_tag(tag_struct_field);
1790             let def_id = self.ecx.tcx.map.local_def_id(field.node.id);
1791             encode_def_id(self.rbml_w, def_id);
1792             encode_attributes(self.rbml_w, &field.node.attrs);
1793             self.rbml_w.end_tag();
1794         }
1795     }
1796
1797     rbml_w.start_tag(tag_struct_fields);
1798     krate.visit_all_items(&mut StructFieldVisitor { ecx: ecx, rbml_w: rbml_w });
1799     rbml_w.end_tag();
1800 }
1801
1802
1803
1804 struct ImplVisitor<'a, 'tcx:'a> {
1805     tcx: &'a ty::ctxt<'tcx>,
1806     impls: FnvHashMap<DefId, Vec<DefId>>
1807 }
1808
1809 impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> {
1810     fn visit_item(&mut self, item: &hir::Item) {
1811         if let hir::ItemImpl(..) = item.node {
1812             let impl_id = self.tcx.map.local_def_id(item.id);
1813             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
1814                 self.impls.entry(trait_ref.def_id)
1815                     .or_insert(vec![])
1816                     .push(impl_id);
1817             }
1818         }
1819     }
1820 }
1821
1822 /// Encodes an index, mapping each trait to its (local) implementations.
1823 fn encode_impls<'a>(ecx: &'a EncodeContext,
1824                     krate: &hir::Crate,
1825                     rbml_w: &'a mut Encoder) {
1826     let mut visitor = ImplVisitor {
1827         tcx: ecx.tcx,
1828         impls: FnvHashMap()
1829     };
1830     krate.visit_all_items(&mut visitor);
1831
1832     rbml_w.start_tag(tag_impls);
1833     for (trait_, trait_impls) in visitor.impls {
1834         rbml_w.start_tag(tag_impls_trait);
1835         encode_def_id(rbml_w, trait_);
1836         for impl_ in trait_impls {
1837             rbml_w.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_));
1838         }
1839         rbml_w.end_tag();
1840     }
1841     rbml_w.end_tag();
1842 }
1843
1844 fn encode_misc_info(ecx: &EncodeContext,
1845                     krate: &hir::Crate,
1846                     rbml_w: &mut Encoder) {
1847     rbml_w.start_tag(tag_misc_info);
1848     rbml_w.start_tag(tag_misc_info_crate_items);
1849     for item_id in &krate.module.item_ids {
1850         rbml_w.wr_tagged_u64(tag_mod_child,
1851                              def_to_u64(ecx.tcx.map.local_def_id(item_id.id)));
1852
1853         let item = ecx.tcx.map.expect_item(item_id.id);
1854         each_auxiliary_node_id(item, |auxiliary_node_id| {
1855             rbml_w.wr_tagged_u64(tag_mod_child,
1856                                  def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
1857             true
1858         });
1859     }
1860
1861     // Encode reexports for the root module.
1862     encode_reexports(ecx, rbml_w, 0);
1863
1864     rbml_w.end_tag();
1865     rbml_w.end_tag();
1866 }
1867
1868 // Encodes all reachable symbols in this crate into the metadata.
1869 //
1870 // This pass is seeded off the reachability list calculated in the
1871 // middle::reachable module but filters out items that either don't have a
1872 // symbol associated with them (they weren't translated) or if they're an FFI
1873 // definition (as that's not defined in this crate).
1874 fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1875     rbml_w.start_tag(tag_reachable_ids);
1876     for &id in ecx.reachable {
1877         let def_id = ecx.tcx.map.local_def_id(id);
1878         rbml_w.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32());
1879     }
1880     rbml_w.end_tag();
1881 }
1882
1883 fn encode_crate_dep(rbml_w: &mut Encoder,
1884                     dep: &cstore::crate_metadata) {
1885     rbml_w.start_tag(tag_crate_dep);
1886     rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
1887     let hash = decoder::get_crate_hash(dep.data());
1888     rbml_w.wr_tagged_str(tag_crate_dep_hash, hash.as_str());
1889     rbml_w.wr_tagged_u8(tag_crate_dep_explicitly_linked,
1890                         dep.explicitly_linked.get() as u8);
1891     rbml_w.end_tag();
1892 }
1893
1894 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1895     rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
1896 }
1897
1898 fn encode_rustc_version(rbml_w: &mut Encoder) {
1899     rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version());
1900 }
1901
1902 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1903     rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
1904 }
1905
1906 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1907     rbml_w.wr_tagged_str(tag_crate_triple, triple);
1908 }
1909
1910 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
1911     let tag = tag_dylib_dependency_formats;
1912     match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1913         Some(arr) => {
1914             let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1915                 let kind = match *slot {
1916                     Linkage::NotLinked |
1917                     Linkage::IncludedFromDylib => return None,
1918                     Linkage::Dynamic => "d",
1919                     Linkage::Static => "s",
1920                 };
1921                 Some(format!("{}:{}", i + 1, kind))
1922             }).collect::<Vec<String>>();
1923             rbml_w.wr_tagged_str(tag, &s.join(","));
1924         }
1925         None => {
1926             rbml_w.wr_tagged_str(tag, "");
1927         }
1928     }
1929 }
1930
1931 // NB: Increment this as you change the metadata encoding version.
1932 #[allow(non_upper_case_globals)]
1933 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
1934
1935 pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
1936     let EncodeParams {
1937         item_symbols,
1938         diag,
1939         tcx,
1940         reexports,
1941         cstore,
1942         encode_inlined_item,
1943         link_meta,
1944         reachable,
1945         mir_map,
1946         ..
1947     } = parms;
1948     let ecx = EncodeContext {
1949         diag: diag,
1950         tcx: tcx,
1951         reexports: reexports,
1952         item_symbols: item_symbols,
1953         link_meta: link_meta,
1954         cstore: cstore,
1955         encode_inlined_item: RefCell::new(encode_inlined_item),
1956         type_abbrevs: RefCell::new(FnvHashMap()),
1957         reachable: reachable,
1958         mir_map: mir_map,
1959     };
1960
1961     let mut wr = Cursor::new(Vec::new());
1962
1963     {
1964         let mut rbml_w = Encoder::new(&mut wr);
1965         tls::enter_encoding_context(&ecx, &mut rbml_w, |_, rbml_w| {
1966             encode_metadata_inner(rbml_w, &ecx, krate)
1967         });
1968     }
1969
1970     // RBML compacts the encoded bytes whenever appropriate,
1971     // so there are some garbages left after the end of the data.
1972     let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as usize;
1973     let mut v = wr.into_inner();
1974     v.truncate(metalen);
1975     assert_eq!(v.len(), metalen);
1976
1977     // And here we run into yet another obscure archive bug: in which metadata
1978     // loaded from archives may have trailing garbage bytes. Awhile back one of
1979     // our tests was failing sporadically on the OSX 64-bit builders (both nopt
1980     // and opt) by having rbml generate an out-of-bounds panic when looking at
1981     // metadata.
1982     //
1983     // Upon investigation it turned out that the metadata file inside of an rlib
1984     // (and ar archive) was being corrupted. Some compilations would generate a
1985     // metadata file which would end in a few extra bytes, while other
1986     // compilations would not have these extra bytes appended to the end. These
1987     // extra bytes were interpreted by rbml as an extra tag, so they ended up
1988     // being interpreted causing the out-of-bounds.
1989     //
1990     // The root cause of why these extra bytes were appearing was never
1991     // discovered, and in the meantime the solution we're employing is to insert
1992     // the length of the metadata to the start of the metadata. Later on this
1993     // will allow us to slice the metadata to the precise length that we just
1994     // generated regardless of trailing bytes that end up in it.
1995     let len = v.len() as u32;
1996     v.insert(0, (len >>  0) as u8);
1997     v.insert(0, (len >>  8) as u8);
1998     v.insert(0, (len >> 16) as u8);
1999     v.insert(0, (len >> 24) as u8);
2000     return v;
2001 }
2002
2003 fn encode_metadata_inner(rbml_w: &mut Encoder,
2004                          ecx: &EncodeContext,
2005                          krate: &hir::Crate) {
2006     struct Stats {
2007         attr_bytes: u64,
2008         dep_bytes: u64,
2009         lang_item_bytes: u64,
2010         native_lib_bytes: u64,
2011         plugin_registrar_fn_bytes: u64,
2012         codemap_bytes: u64,
2013         macro_defs_bytes: u64,
2014         impl_bytes: u64,
2015         misc_bytes: u64,
2016         item_bytes: u64,
2017         index_bytes: u64,
2018         xref_bytes: u64,
2019         zero_bytes: u64,
2020         total_bytes: u64,
2021     }
2022     let mut stats = Stats {
2023         attr_bytes: 0,
2024         dep_bytes: 0,
2025         lang_item_bytes: 0,
2026         native_lib_bytes: 0,
2027         plugin_registrar_fn_bytes: 0,
2028         codemap_bytes: 0,
2029         macro_defs_bytes: 0,
2030         impl_bytes: 0,
2031         misc_bytes: 0,
2032         item_bytes: 0,
2033         index_bytes: 0,
2034         xref_bytes: 0,
2035         zero_bytes: 0,
2036         total_bytes: 0,
2037     };
2038
2039     encode_rustc_version(rbml_w);
2040     encode_crate_name(rbml_w, &ecx.link_meta.crate_name);
2041     encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple);
2042     encode_hash(rbml_w, &ecx.link_meta.crate_hash);
2043     encode_dylib_dependency_formats(rbml_w, &ecx);
2044
2045     let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2046     encode_attributes(rbml_w, &krate.attrs);
2047     stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2048
2049     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2050     encode_crate_deps(rbml_w, ecx.cstore);
2051     stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2052
2053     // Encode the language items.
2054     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2055     encode_lang_items(&ecx, rbml_w);
2056     stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2057
2058     // Encode the native libraries used
2059     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2060     encode_native_libraries(&ecx, rbml_w);
2061     stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2062
2063     // Encode the plugin registrar function
2064     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2065     encode_plugin_registrar_fn(&ecx, rbml_w);
2066     stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2067
2068     // Encode codemap
2069     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2070     encode_codemap(&ecx, rbml_w);
2071     stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2072
2073     // Encode macro definitions
2074     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2075     encode_macro_defs(rbml_w, krate);
2076     stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2077
2078     // Encode the def IDs of impls, for coherence checking.
2079     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2080     encode_impls(&ecx, krate, rbml_w);
2081     stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2082
2083     // Encode miscellaneous info.
2084     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2085     encode_misc_info(&ecx, krate, rbml_w);
2086     encode_reachable(&ecx, rbml_w);
2087     stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2088
2089     // Encode and index the items.
2090     rbml_w.start_tag(tag_items);
2091     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2092     let index = encode_info_for_items(&ecx, rbml_w);
2093     stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2094     rbml_w.end_tag();
2095
2096     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2097     encode_item_index(rbml_w, index.items);
2098     stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2099
2100     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2101     encode_xrefs(&ecx, rbml_w, index.xrefs);
2102     stats.xref_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2103
2104     encode_struct_field_attrs(&ecx, rbml_w, krate);
2105
2106     stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2107
2108     if ecx.tcx.sess.meta_stats() {
2109         for e in rbml_w.writer.get_ref() {
2110             if *e == 0 {
2111                 stats.zero_bytes += 1;
2112             }
2113         }
2114
2115         println!("metadata stats:");
2116         println!("       attribute bytes: {}", stats.attr_bytes);
2117         println!("             dep bytes: {}", stats.dep_bytes);
2118         println!("       lang item bytes: {}", stats.lang_item_bytes);
2119         println!("          native bytes: {}", stats.native_lib_bytes);
2120         println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2121         println!("         codemap bytes: {}", stats.codemap_bytes);
2122         println!("       macro def bytes: {}", stats.macro_defs_bytes);
2123         println!("            impl bytes: {}", stats.impl_bytes);
2124         println!("            misc bytes: {}", stats.misc_bytes);
2125         println!("            item bytes: {}", stats.item_bytes);
2126         println!("           index bytes: {}", stats.index_bytes);
2127         println!("            xref bytes: {}", stats.xref_bytes);
2128         println!("            zero bytes: {}", stats.zero_bytes);
2129         println!("           total bytes: {}", stats.total_bytes);
2130     }
2131 }
2132
2133 // Get the encoded string for a type
2134 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec<u8> {
2135     let mut wr = Cursor::new(Vec::new());
2136     tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
2137         diag: tcx.sess.diagnostic(),
2138         ds: def_to_string,
2139         tcx: tcx,
2140         abbrevs: &RefCell::new(FnvHashMap())
2141     }, t);
2142     wr.into_inner()
2143 }