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