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