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