]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
auto merge of #19628 : jbranchaud/rust/add-string-as-string-doctest, r=steveklabnik
[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::ty::{lookup_item_type};
25 use middle::ty::{mod, Ty};
26 use middle::stability;
27 use middle;
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::{mod, 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 reexports2: &'a middle::resolve::ExportMap2,
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 reexports2: &'a middle::resolve::ExportMap2,
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).as_slice());
99 }
100
101 #[deriving(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::Polytype<'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.as_slice());
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).as_slice());
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.as_slice());
336         encode_repr_attrs(rbml_w, ecx, variant.node.attrs.as_slice());
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.as_slice(),
348                                                  index);
349                 encode_struct_fields(rbml_w, fields.as_slice(), 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<PathElem> + Clone>(rbml_w: &mut Encoder,
368                                                mut path: PI) {
369     rbml_w.start_tag(tag_path);
370     rbml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
371     for pe in path {
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: &middle::resolve::Export2,
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).as_slice());
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)).as_slice());
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: &middle::resolve::Export2)
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: &middle::resolve::Export2)
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: &middle::resolve::Export2) {
453     if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
454         let original_name = token::get_ident(item.ident);
455
456         let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
457             let (mut a, mut b) = (path, mod_path.clone());
458             loop {
459                 match (a.next(), b.next()) {
460                     (None, None) => return true,
461                     (None, _) | (_, None) => return false,
462                     (Some(x), Some(y)) => if x != y { return false },
463                 }
464             }
465         });
466
467         //
468         // We don't need to reexport static methods on items
469         // declared in the same module as our `pub use ...` since
470         // that's done when we encode the item itself.
471         //
472         // The only exception is when the reexport *changes* the
473         // name e.g. `pub use Foo = self::Bar` -- we have
474         // encoded metadata for static methods relative to Bar,
475         // but not yet for Foo.
476         //
477         if path_differs || original_name.get() != exp.name {
478             if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
479                 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
480                     debug!("(encode reexported static methods) {} [trait]",
481                            original_name);
482                 }
483             }
484             else {
485                 debug!("(encode reexported static methods) {} [base]",
486                        original_name);
487             }
488         }
489     }
490 }
491
492 /// Iterates through "auxiliary node IDs", which are node IDs that describe
493 /// top-level items that are sub-items of the given item. Specifically:
494 ///
495 /// * For newtype structs, iterates through the node ID of the constructor.
496 fn each_auxiliary_node_id(item: &ast::Item, callback: |NodeId| -> bool) -> bool {
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.reexports2.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).as_slice());
533                 rbml_w.end_tag();
534                 rbml_w.start_tag(tag_items_data_item_reexport_name);
535                 rbml_w.wr_str(exp.name.as_slice());
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)).as_slice());
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)).as_slice());
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)).as_slice());
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().as_slice());
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().as_slice());
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).as_slice());
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     rbml_w.end_tag();
807 }
808
809 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
810                                      rbml_w: &mut Encoder,
811                                      method_ty: &ty::Method<'tcx>) {
812     encode_def_id(rbml_w, method_ty.def_id);
813     encode_name(rbml_w, method_ty.name);
814     encode_generics(rbml_w, ecx, &method_ty.generics,
815                     tag_method_ty_generics);
816     encode_method_fty(ecx, rbml_w, &method_ty.fty);
817     encode_visibility(rbml_w, method_ty.vis);
818     encode_explicit_self(rbml_w, &method_ty.explicit_self);
819     match method_ty.explicit_self {
820         ty::StaticExplicitSelfCategory => {
821             encode_family(rbml_w, STATIC_METHOD_FAMILY);
822         }
823         _ => encode_family(rbml_w, METHOD_FAMILY)
824     }
825     encode_provided_source(rbml_w, method_ty.provided_source);
826 }
827
828 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
829                                     rbml_w: &mut Encoder,
830                                     m: &ty::Method<'tcx>,
831                                     impl_path: PathElems,
832                                     is_default_impl: bool,
833                                     parent_id: NodeId,
834                                     ast_item_opt: Option<&ast::ImplItem>) {
835
836     debug!("encode_info_for_method: {} {}", m.def_id,
837            token::get_name(m.name));
838     rbml_w.start_tag(tag_items_data_item);
839
840     encode_method_ty_fields(ecx, rbml_w, m);
841     encode_parent_item(rbml_w, local_def(parent_id));
842     encode_item_sort(rbml_w, 'r');
843
844     let stab = stability::lookup(ecx.tcx, m.def_id);
845     encode_stability(rbml_w, stab);
846
847     // The type for methods gets encoded twice, which is unfortunate.
848     let pty = lookup_item_type(ecx.tcx, m.def_id);
849     encode_bounds_and_type(rbml_w, ecx, &pty);
850
851     let elem = ast_map::PathName(m.name);
852     encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
853     match ast_item_opt {
854         Some(&ast::MethodImplItem(ref ast_method)) => {
855             encode_attributes(rbml_w, ast_method.attrs.as_slice());
856             let any_types = !pty.generics.types.is_empty();
857             if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
858                 encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
859                                                                ast_item_opt.unwrap()));
860             }
861             if !any_types {
862                 encode_symbol(ecx, rbml_w, m.def_id.node);
863             }
864             encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
865         }
866         Some(_) | None => {}
867     }
868
869     rbml_w.end_tag();
870 }
871
872 fn encode_info_for_associated_type(ecx: &EncodeContext,
873                                    rbml_w: &mut Encoder,
874                                    associated_type: &ty::AssociatedType,
875                                    impl_path: PathElems,
876                                    parent_id: NodeId,
877                                    typedef_opt: Option<P<ast::Typedef>>) {
878     debug!("encode_info_for_associated_type({},{})",
879            associated_type.def_id,
880            token::get_name(associated_type.name));
881
882     rbml_w.start_tag(tag_items_data_item);
883
884     encode_def_id(rbml_w, associated_type.def_id);
885     encode_name(rbml_w, associated_type.name);
886     encode_visibility(rbml_w, associated_type.vis);
887     encode_family(rbml_w, 'y');
888     encode_parent_item(rbml_w, local_def(parent_id));
889     encode_item_sort(rbml_w, 'r');
890
891     let stab = stability::lookup(ecx.tcx, associated_type.def_id);
892     encode_stability(rbml_w, stab);
893
894     let elem = ast_map::PathName(associated_type.name);
895     encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
896
897     match typedef_opt {
898         None => {}
899         Some(typedef) => {
900             encode_attributes(rbml_w, typedef.attrs.as_slice());
901             encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
902                                                          typedef.id));
903         }
904     }
905
906     rbml_w.end_tag();
907 }
908
909 fn encode_method_argument_names(rbml_w: &mut Encoder,
910                                 decl: &ast::FnDecl) {
911     rbml_w.start_tag(tag_method_argument_names);
912     for arg in decl.inputs.iter() {
913         rbml_w.start_tag(tag_method_argument_name);
914         if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
915             let name = token::get_ident(path1.node);
916             rbml_w.writer.write(name.get().as_bytes());
917         }
918         rbml_w.end_tag();
919     }
920     rbml_w.end_tag();
921 }
922
923 fn encode_repr_attrs(rbml_w: &mut Encoder,
924                      ecx: &EncodeContext,
925                      attrs: &[ast::Attribute]) {
926     let mut repr_attrs = Vec::new();
927     for attr in attrs.iter() {
928         repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
929                                                 attr).into_iter());
930     }
931     rbml_w.start_tag(tag_items_data_item_repr);
932     repr_attrs.encode(rbml_w);
933     rbml_w.end_tag();
934 }
935
936 fn encode_inlined_item(ecx: &EncodeContext,
937                        rbml_w: &mut Encoder,
938                        ii: InlinedItemRef) {
939     let mut eii = ecx.encode_inlined_item.borrow_mut();
940     let eii: &mut EncodeInlinedItem = &mut *eii;
941     (*eii)(ecx, rbml_w, ii)
942 }
943
944 const FN_FAMILY: char = 'f';
945 const STATIC_METHOD_FAMILY: char = 'F';
946 const METHOD_FAMILY: char = 'h';
947
948 fn should_inline(attrs: &[ast::Attribute]) -> bool {
949     use syntax::attr::*;
950     match find_inline_attr(attrs) {
951         InlineNone | InlineNever  => false,
952         InlineHint | InlineAlways => true
953     }
954 }
955
956 // Encodes the inherent implementations of a structure, enumeration, or trait.
957 fn encode_inherent_implementations(ecx: &EncodeContext,
958                                    rbml_w: &mut Encoder,
959                                    def_id: DefId) {
960     match ecx.tcx.inherent_impls.borrow().get(&def_id) {
961         None => {}
962         Some(implementations) => {
963             for &impl_def_id in implementations.iter() {
964                 rbml_w.start_tag(tag_items_data_item_inherent_impl);
965                 encode_def_id(rbml_w, impl_def_id);
966                 rbml_w.end_tag();
967             }
968         }
969     }
970 }
971
972 // Encodes the implementations of a trait defined in this crate.
973 fn encode_extension_implementations(ecx: &EncodeContext,
974                                     rbml_w: &mut Encoder,
975                                     trait_def_id: DefId) {
976     match ecx.tcx.trait_impls.borrow().get(&trait_def_id) {
977         None => {}
978         Some(implementations) => {
979             for &impl_def_id in implementations.borrow().iter() {
980                 rbml_w.start_tag(tag_items_data_item_extension_impl);
981                 encode_def_id(rbml_w, impl_def_id);
982                 rbml_w.end_tag();
983             }
984         }
985     }
986 }
987
988 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
989     stab_opt.map(|stab| {
990         rbml_w.start_tag(tag_items_data_item_stability);
991         stab.encode(rbml_w).unwrap();
992         rbml_w.end_tag();
993     });
994 }
995
996 fn encode_info_for_item(ecx: &EncodeContext,
997                         rbml_w: &mut Encoder,
998                         item: &ast::Item,
999                         index: &mut Vec<entry<i64>>,
1000                         path: PathElems,
1001                         vis: ast::Visibility) {
1002     let tcx = ecx.tcx;
1003
1004     fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
1005                     index: &mut Vec<entry<i64>>) {
1006         index.push(entry {
1007             val: item.id as i64,
1008             pos: rbml_w.writer.tell().unwrap(),
1009         });
1010     }
1011
1012     debug!("encoding info for item at {}",
1013            tcx.sess.codemap().span_to_string(item.span));
1014
1015     let def_id = local_def(item.id);
1016     let stab = stability::lookup(tcx, ast_util::local_def(item.id));
1017
1018     match item.node {
1019       ast::ItemStatic(_, m, _) => {
1020         add_to_index(item, rbml_w, index);
1021         rbml_w.start_tag(tag_items_data_item);
1022         encode_def_id(rbml_w, def_id);
1023         if m == ast::MutMutable {
1024             encode_family(rbml_w, 'b');
1025         } else {
1026             encode_family(rbml_w, 'c');
1027         }
1028         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1029         encode_symbol(ecx, rbml_w, item.id);
1030         encode_name(rbml_w, item.ident.name);
1031         encode_path(rbml_w, path);
1032         encode_visibility(rbml_w, vis);
1033         encode_stability(rbml_w, stab);
1034         encode_attributes(rbml_w, item.attrs.as_slice());
1035         rbml_w.end_tag();
1036       }
1037       ast::ItemConst(_, _) => {
1038         add_to_index(item, rbml_w, index);
1039         rbml_w.start_tag(tag_items_data_item);
1040         encode_def_id(rbml_w, def_id);
1041         encode_family(rbml_w, 'C');
1042         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1043         encode_name(rbml_w, item.ident.name);
1044         encode_path(rbml_w, path);
1045         encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1046         encode_visibility(rbml_w, vis);
1047         encode_stability(rbml_w, stab);
1048         rbml_w.end_tag();
1049       }
1050       ast::ItemFn(ref decl, _, _, ref generics, _) => {
1051         add_to_index(item, rbml_w, index);
1052         rbml_w.start_tag(tag_items_data_item);
1053         encode_def_id(rbml_w, def_id);
1054         encode_family(rbml_w, FN_FAMILY);
1055         let tps_len = generics.ty_params.len();
1056         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1057         encode_name(rbml_w, item.ident.name);
1058         encode_path(rbml_w, path);
1059         encode_attributes(rbml_w, item.attrs.as_slice());
1060         if tps_len > 0u || should_inline(item.attrs.as_slice()) {
1061             encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1062         }
1063         if tps_len == 0 {
1064             encode_symbol(ecx, rbml_w, item.id);
1065         }
1066         encode_visibility(rbml_w, vis);
1067         encode_stability(rbml_w, stab);
1068         encode_method_argument_names(rbml_w, &**decl);
1069         rbml_w.end_tag();
1070       }
1071       ast::ItemMod(ref m) => {
1072         add_to_index(item, rbml_w, index);
1073         encode_info_for_mod(ecx,
1074                             rbml_w,
1075                             m,
1076                             item.attrs.as_slice(),
1077                             item.id,
1078                             path,
1079                             item.ident,
1080                             item.vis);
1081       }
1082       ast::ItemForeignMod(ref fm) => {
1083         add_to_index(item, rbml_w, index);
1084         rbml_w.start_tag(tag_items_data_item);
1085         encode_def_id(rbml_w, def_id);
1086         encode_family(rbml_w, 'n');
1087         encode_name(rbml_w, item.ident.name);
1088         encode_path(rbml_w, path);
1089
1090         // Encode all the items in this module.
1091         for foreign_item in fm.items.iter() {
1092             rbml_w.start_tag(tag_mod_child);
1093             rbml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
1094             rbml_w.end_tag();
1095         }
1096         encode_visibility(rbml_w, vis);
1097         encode_stability(rbml_w, stab);
1098         rbml_w.end_tag();
1099       }
1100       ast::ItemTy(..) => {
1101         add_to_index(item, rbml_w, index);
1102         rbml_w.start_tag(tag_items_data_item);
1103         encode_def_id(rbml_w, def_id);
1104         encode_family(rbml_w, 'y');
1105         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1106         encode_name(rbml_w, item.ident.name);
1107         encode_path(rbml_w, path);
1108         encode_visibility(rbml_w, vis);
1109         encode_stability(rbml_w, stab);
1110         rbml_w.end_tag();
1111       }
1112       ast::ItemEnum(ref enum_definition, _) => {
1113         add_to_index(item, rbml_w, index);
1114
1115         rbml_w.start_tag(tag_items_data_item);
1116         encode_def_id(rbml_w, def_id);
1117         encode_family(rbml_w, 't');
1118         encode_item_variances(rbml_w, ecx, item.id);
1119         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1120         encode_name(rbml_w, item.ident.name);
1121         encode_attributes(rbml_w, item.attrs.as_slice());
1122         encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice());
1123         for v in (*enum_definition).variants.iter() {
1124             encode_variant_id(rbml_w, local_def(v.node.id));
1125         }
1126         encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1127         encode_path(rbml_w, path);
1128
1129         // Encode inherent implementations for this enumeration.
1130         encode_inherent_implementations(ecx, rbml_w, def_id);
1131
1132         encode_visibility(rbml_w, vis);
1133         encode_stability(rbml_w, stab);
1134         rbml_w.end_tag();
1135
1136         encode_enum_variant_info(ecx,
1137                                  rbml_w,
1138                                  item.id,
1139                                  (*enum_definition).variants.as_slice(),
1140                                  index);
1141       }
1142       ast::ItemStruct(ref struct_def, _) => {
1143         let fields = ty::lookup_struct_fields(tcx, def_id);
1144
1145         /* First, encode the fields
1146            These come first because we need to write them to make
1147            the index, and the index needs to be in the item for the
1148            class itself */
1149         let idx = encode_info_for_struct(ecx,
1150                                          rbml_w,
1151                                          fields.as_slice(),
1152                                          index);
1153
1154         /* Index the class*/
1155         add_to_index(item, rbml_w, index);
1156
1157         /* Now, make an item for the class itself */
1158         rbml_w.start_tag(tag_items_data_item);
1159         encode_def_id(rbml_w, def_id);
1160         encode_family(rbml_w, 'S');
1161         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1162
1163         encode_item_variances(rbml_w, ecx, item.id);
1164         encode_name(rbml_w, item.ident.name);
1165         encode_attributes(rbml_w, item.attrs.as_slice());
1166         encode_path(rbml_w, path.clone());
1167         encode_stability(rbml_w, stab);
1168         encode_visibility(rbml_w, vis);
1169         encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice());
1170
1171         /* Encode def_ids for each field and method
1172          for methods, write all the stuff get_trait_method
1173         needs to know*/
1174         encode_struct_fields(rbml_w, fields.as_slice(), def_id);
1175
1176         encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1177
1178         // Encode inherent implementations for this structure.
1179         encode_inherent_implementations(ecx, rbml_w, def_id);
1180
1181         /* Each class has its own index -- encode it */
1182         encode_index(rbml_w, idx, write_i64);
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.ident,
1189                                             ctor_id, index, def_id.node);
1190             }
1191             None => {}
1192         }
1193       }
1194       ast::ItemImpl(_, ref opt_trait, ref ty, ref ast_items) => {
1195         // We need to encode information about the default methods we
1196         // have inherited, so we drive this based on the impl structure.
1197         let impl_items = tcx.impl_items.borrow();
1198         let items = &(*impl_items)[def_id];
1199
1200         add_to_index(item, rbml_w, index);
1201         rbml_w.start_tag(tag_items_data_item);
1202         encode_def_id(rbml_w, def_id);
1203         encode_family(rbml_w, 'i');
1204         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1205         encode_name(rbml_w, item.ident.name);
1206         encode_attributes(rbml_w, item.attrs.as_slice());
1207         match ty.node {
1208             ast::TyPath(ref path, _) if path.segments
1209                                                         .len() == 1 => {
1210                 let ident = path.segments.last().unwrap().identifier;
1211                 encode_impl_type_basename(rbml_w, ident);
1212             }
1213             _ => {}
1214         }
1215         for &item_def_id in items.iter() {
1216             rbml_w.start_tag(tag_item_impl_item);
1217             match item_def_id {
1218                 ty::MethodTraitItemId(item_def_id) => {
1219                     encode_def_id(rbml_w, item_def_id);
1220                     encode_item_sort(rbml_w, 'r');
1221                 }
1222                 ty::TypeTraitItemId(item_def_id) => {
1223                     encode_def_id(rbml_w, item_def_id);
1224                     encode_item_sort(rbml_w, 't');
1225                 }
1226             }
1227             rbml_w.end_tag();
1228         }
1229         for ast_trait_ref in opt_trait.iter() {
1230             let trait_ref = ty::node_id_to_trait_ref(
1231                 tcx, ast_trait_ref.ref_id);
1232             encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
1233         }
1234         encode_path(rbml_w, path.clone());
1235         encode_stability(rbml_w, stab);
1236         rbml_w.end_tag();
1237
1238         // Iterate down the trait items, emitting them. We rely on the
1239         // assumption that all of the actually implemented trait items
1240         // appear first in the impl structure, in the same order they do
1241         // in the ast. This is a little sketchy.
1242         let num_implemented_methods = ast_items.len();
1243         for (i, &trait_item_def_id) in items.iter().enumerate() {
1244             let ast_item = if i < num_implemented_methods {
1245                 Some(&ast_items[i])
1246             } else {
1247                 None
1248             };
1249
1250             index.push(entry {
1251                 val: trait_item_def_id.def_id().node as i64,
1252                 pos: rbml_w.writer.tell().unwrap(),
1253             });
1254
1255             let trait_item_type =
1256                 ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
1257             match (trait_item_type, ast_item) {
1258                 (ty::MethodTraitItem(ref method_type),
1259                  Some(&ast::MethodImplItem(_))) => {
1260                     encode_info_for_method(ecx,
1261                                            rbml_w,
1262                                            &**method_type,
1263                                            path.clone(),
1264                                            false,
1265                                            item.id,
1266                                            ast_item)
1267                 }
1268                 (ty::MethodTraitItem(ref method_type), _) => {
1269                     encode_info_for_method(ecx,
1270                                            rbml_w,
1271                                            &**method_type,
1272                                            path.clone(),
1273                                            false,
1274                                            item.id,
1275                                            None)
1276                 }
1277                 (ty::TypeTraitItem(ref associated_type),
1278                  Some(&ast::TypeImplItem(ref typedef))) => {
1279                     encode_info_for_associated_type(ecx,
1280                                                     rbml_w,
1281                                                     &**associated_type,
1282                                                     path.clone(),
1283                                                     item.id,
1284                                                     Some((*typedef).clone()))
1285                 }
1286                 (ty::TypeTraitItem(ref associated_type), _) => {
1287                     encode_info_for_associated_type(ecx,
1288                                                     rbml_w,
1289                                                     &**associated_type,
1290                                                     path.clone(),
1291                                                     item.id,
1292                                                     None)
1293                 }
1294             }
1295         }
1296       }
1297       ast::ItemTrait(_, _, _, ref ms) => {
1298         add_to_index(item, rbml_w, index);
1299         rbml_w.start_tag(tag_items_data_item);
1300         encode_def_id(rbml_w, def_id);
1301         encode_family(rbml_w, 'I');
1302         encode_item_variances(rbml_w, ecx, item.id);
1303         let trait_def = ty::lookup_trait_def(tcx, def_id);
1304         encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
1305         encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1306         encode_name(rbml_w, item.ident.name);
1307         encode_attributes(rbml_w, item.attrs.as_slice());
1308         encode_visibility(rbml_w, vis);
1309         encode_stability(rbml_w, stab);
1310         for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
1311             rbml_w.start_tag(tag_item_trait_item);
1312             match method_def_id {
1313                 ty::MethodTraitItemId(method_def_id) => {
1314                     encode_def_id(rbml_w, method_def_id);
1315                     encode_item_sort(rbml_w, 'r');
1316                 }
1317                 ty::TypeTraitItemId(type_def_id) => {
1318                     encode_def_id(rbml_w, type_def_id);
1319                     encode_item_sort(rbml_w, 't');
1320                 }
1321             }
1322             rbml_w.end_tag();
1323
1324             rbml_w.start_tag(tag_mod_child);
1325             rbml_w.wr_str(def_to_string(method_def_id.def_id()).as_slice());
1326             rbml_w.end_tag();
1327         }
1328         encode_path(rbml_w, path.clone());
1329
1330         encode_bounds(rbml_w, ecx, &trait_def.bounds, tag_trait_def_bounds);
1331
1332         // Encode the implementations of this trait.
1333         encode_extension_implementations(ecx, rbml_w, def_id);
1334
1335         rbml_w.end_tag();
1336
1337         // Now output the trait item info for each trait item.
1338         let r = ty::trait_item_def_ids(tcx, def_id);
1339         for (i, &item_def_id) in r.iter().enumerate() {
1340             assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
1341
1342             index.push(entry {
1343                 val: item_def_id.def_id().node as i64,
1344                 pos: rbml_w.writer.tell().unwrap(),
1345             });
1346
1347             rbml_w.start_tag(tag_items_data_item);
1348
1349             encode_parent_item(rbml_w, def_id);
1350
1351             let stab = stability::lookup(tcx, item_def_id.def_id());
1352             encode_stability(rbml_w, stab);
1353
1354             let trait_item_type =
1355                 ty::impl_or_trait_item(tcx, item_def_id.def_id());
1356             let is_nonstatic_method;
1357             match trait_item_type {
1358                 ty::MethodTraitItem(method_ty) => {
1359                     let method_def_id = item_def_id.def_id();
1360
1361                     encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1362
1363                     let elem = ast_map::PathName(method_ty.name);
1364                     encode_path(rbml_w,
1365                                 path.clone().chain(Some(elem).into_iter()));
1366
1367                     match method_ty.explicit_self {
1368                         ty::StaticExplicitSelfCategory => {
1369                             encode_family(rbml_w,
1370                                           STATIC_METHOD_FAMILY);
1371                         }
1372                         _ => {
1373                             encode_family(rbml_w,
1374                                           METHOD_FAMILY);
1375                         }
1376                     }
1377                     let pty = ty::lookup_item_type(tcx,
1378                                                    method_def_id);
1379                     encode_bounds_and_type(rbml_w, ecx, &pty);
1380
1381                     is_nonstatic_method = method_ty.explicit_self !=
1382                         ty::StaticExplicitSelfCategory;
1383                 }
1384                 ty::TypeTraitItem(associated_type) => {
1385                     let elem = ast_map::PathName(associated_type.name);
1386                     encode_path(rbml_w,
1387                                 path.clone().chain(Some(elem).into_iter()));
1388
1389                     encode_family(rbml_w, 'y');
1390
1391                     is_nonstatic_method = false;
1392                 }
1393             }
1394
1395             encode_parent_sort(rbml_w, 't');
1396
1397             let trait_item = &ms[i];
1398             let encode_trait_item = |rbml_w: &mut Encoder| {
1399                 // If this is a static method, we've already
1400                 // encoded this.
1401                 if is_nonstatic_method {
1402                     // FIXME: I feel like there is something funny
1403                     // going on.
1404                     let pty = ty::lookup_item_type(tcx, item_def_id.def_id());
1405                     encode_bounds_and_type(rbml_w, ecx, &pty);
1406                 }
1407             };
1408             match trait_item {
1409                 &ast::RequiredMethod(ref m) => {
1410                     encode_attributes(rbml_w, m.attrs.as_slice());
1411                     encode_trait_item(rbml_w);
1412                     encode_item_sort(rbml_w, 'r');
1413                     encode_method_argument_names(rbml_w, &*m.decl);
1414                 }
1415
1416                 &ast::ProvidedMethod(ref m) => {
1417                     encode_attributes(rbml_w, m.attrs.as_slice());
1418                     encode_trait_item(rbml_w);
1419                     encode_item_sort(rbml_w, 'p');
1420                     encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
1421                     encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
1422                 }
1423
1424                 &ast::TypeTraitItem(ref associated_type) => {
1425                     encode_attributes(rbml_w,
1426                                       associated_type.attrs.as_slice());
1427                     encode_item_sort(rbml_w, 't');
1428                 }
1429             }
1430
1431             rbml_w.end_tag();
1432         }
1433
1434         // Encode inherent implementations for this trait.
1435         encode_inherent_implementations(ecx, rbml_w, def_id);
1436       }
1437       ast::ItemMac(..) => {
1438         // macros are encoded separately
1439       }
1440     }
1441 }
1442
1443 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1444                                 rbml_w: &mut Encoder,
1445                                 nitem: &ast::ForeignItem,
1446                                 index: &mut Vec<entry<i64>>,
1447                                 path: PathElems,
1448                                 abi: abi::Abi) {
1449     index.push(entry {
1450         val: nitem.id as i64,
1451         pos: rbml_w.writer.tell().unwrap(),
1452     });
1453
1454     rbml_w.start_tag(tag_items_data_item);
1455     encode_def_id(rbml_w, local_def(nitem.id));
1456     encode_visibility(rbml_w, nitem.vis);
1457     match nitem.node {
1458       ast::ForeignItemFn(..) => {
1459         encode_family(rbml_w, FN_FAMILY);
1460         encode_bounds_and_type(rbml_w, ecx,
1461                                &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1462         encode_name(rbml_w, nitem.ident.name);
1463         if abi == abi::RustIntrinsic {
1464             encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
1465         }
1466         encode_symbol(ecx, rbml_w, nitem.id);
1467       }
1468       ast::ForeignItemStatic(_, mutbl) => {
1469         if mutbl {
1470             encode_family(rbml_w, 'b');
1471         } else {
1472             encode_family(rbml_w, 'c');
1473         }
1474         encode_bounds_and_type(rbml_w, ecx,
1475                                &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1476         encode_symbol(ecx, rbml_w, nitem.id);
1477         encode_name(rbml_w, nitem.ident.name);
1478       }
1479     }
1480     encode_path(rbml_w, path);
1481     rbml_w.end_tag();
1482 }
1483
1484 fn my_visit_expr(_e: &ast::Expr) { }
1485
1486 fn my_visit_item(i: &ast::Item,
1487                  rbml_w: &mut Encoder,
1488                  ecx: &EncodeContext,
1489                  index: &mut Vec<entry<i64>>) {
1490     ecx.tcx.map.with_path(i.id, |path| {
1491         encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1492     });
1493 }
1494
1495 fn my_visit_foreign_item(ni: &ast::ForeignItem,
1496                          rbml_w: &mut Encoder,
1497                          ecx: &EncodeContext,
1498                          index: &mut Vec<entry<i64>>) {
1499     debug!("writing foreign item {}::{}",
1500             ecx.tcx.map.path_to_string(ni.id),
1501             token::get_ident(ni.ident));
1502
1503     let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1504     ecx.tcx.map.with_path(ni.id, |path| {
1505         encode_info_for_foreign_item(ecx, rbml_w,
1506                                      ni, index,
1507                                      path, abi);
1508     });
1509 }
1510
1511 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1512     rbml_w_for_visit_item: &'a mut Encoder<'b>,
1513     ecx: &'a EncodeContext<'c,'tcx>,
1514     index: &'a mut Vec<entry<i64>>,
1515 }
1516
1517 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1518     fn visit_expr(&mut self, ex: &ast::Expr) {
1519         visit::walk_expr(self, ex);
1520         my_visit_expr(ex);
1521     }
1522     fn visit_item(&mut self, i: &ast::Item) {
1523         visit::walk_item(self, i);
1524         my_visit_item(i,
1525                       self.rbml_w_for_visit_item,
1526                       self.ecx,
1527                       self.index);
1528     }
1529     fn visit_foreign_item(&mut self, ni: &ast::ForeignItem) {
1530         visit::walk_foreign_item(self, ni);
1531         my_visit_foreign_item(ni,
1532                               self.rbml_w_for_visit_item,
1533                               self.ecx,
1534                               self.index);
1535     }
1536 }
1537
1538 fn encode_info_for_items(ecx: &EncodeContext,
1539                          rbml_w: &mut Encoder,
1540                          krate: &ast::Crate)
1541                          -> Vec<entry<i64>> {
1542     let mut index = Vec::new();
1543     rbml_w.start_tag(tag_items_data);
1544     index.push(entry {
1545         val: ast::CRATE_NODE_ID as i64,
1546         pos: rbml_w.writer.tell().unwrap(),
1547     });
1548     encode_info_for_mod(ecx,
1549                         rbml_w,
1550                         &krate.module,
1551                         &[],
1552                         ast::CRATE_NODE_ID,
1553                         ast_map::Values([].iter()).chain(None),
1554                         syntax::parse::token::special_idents::invalid,
1555                         ast::Public);
1556
1557     visit::walk_crate(&mut EncodeVisitor {
1558         index: &mut index,
1559         ecx: ecx,
1560         rbml_w_for_visit_item: &mut *rbml_w,
1561     }, krate);
1562
1563     rbml_w.end_tag();
1564     index
1565 }
1566
1567
1568 // Path and definition ID indexing
1569
1570 fn encode_index<T: Hash>(rbml_w: &mut Encoder, index: Vec<entry<T>>,
1571                          write_fn: |&mut SeekableMemWriter, &T|) {
1572     let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1573     for elt in index.into_iter() {
1574         let h = hash::hash(&elt.val) as uint;
1575         buckets[h % 256].push(elt);
1576     }
1577
1578     rbml_w.start_tag(tag_index);
1579     let mut bucket_locs = Vec::new();
1580     rbml_w.start_tag(tag_index_buckets);
1581     for bucket in buckets.iter() {
1582         bucket_locs.push(rbml_w.writer.tell().unwrap());
1583         rbml_w.start_tag(tag_index_buckets_bucket);
1584         for elt in bucket.iter() {
1585             rbml_w.start_tag(tag_index_buckets_bucket_elt);
1586             assert!(elt.pos < 0xffff_ffff);
1587             {
1588                 let wr: &mut SeekableMemWriter = rbml_w.writer;
1589                 wr.write_be_u32(elt.pos as u32);
1590             }
1591             write_fn(rbml_w.writer, &elt.val);
1592             rbml_w.end_tag();
1593         }
1594         rbml_w.end_tag();
1595     }
1596     rbml_w.end_tag();
1597     rbml_w.start_tag(tag_index_table);
1598     for pos in bucket_locs.iter() {
1599         assert!(*pos < 0xffff_ffff);
1600         let wr: &mut SeekableMemWriter = rbml_w.writer;
1601         wr.write_be_u32(*pos as u32);
1602     }
1603     rbml_w.end_tag();
1604     rbml_w.end_tag();
1605 }
1606
1607 fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1608     let wr: &mut SeekableMemWriter = writer;
1609     assert!(n < 0x7fff_ffff);
1610     wr.write_be_u32(n as u32);
1611 }
1612
1613 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1614     match mi.node {
1615       ast::MetaWord(ref name) => {
1616         rbml_w.start_tag(tag_meta_item_word);
1617         rbml_w.start_tag(tag_meta_item_name);
1618         rbml_w.writer.write(name.get().as_bytes());
1619         rbml_w.end_tag();
1620         rbml_w.end_tag();
1621       }
1622       ast::MetaNameValue(ref name, ref value) => {
1623         match value.node {
1624           ast::LitStr(ref value, _) => {
1625             rbml_w.start_tag(tag_meta_item_name_value);
1626             rbml_w.start_tag(tag_meta_item_name);
1627             rbml_w.writer.write(name.get().as_bytes());
1628             rbml_w.end_tag();
1629             rbml_w.start_tag(tag_meta_item_value);
1630             rbml_w.writer.write(value.get().as_bytes());
1631             rbml_w.end_tag();
1632             rbml_w.end_tag();
1633           }
1634           _ => {/* FIXME (#623): encode other variants */ }
1635         }
1636       }
1637       ast::MetaList(ref name, ref items) => {
1638         rbml_w.start_tag(tag_meta_item_list);
1639         rbml_w.start_tag(tag_meta_item_name);
1640         rbml_w.writer.write(name.get().as_bytes());
1641         rbml_w.end_tag();
1642         for inner_item in items.iter() {
1643             encode_meta_item(rbml_w, &**inner_item);
1644         }
1645         rbml_w.end_tag();
1646       }
1647     }
1648 }
1649
1650 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1651     rbml_w.start_tag(tag_attributes);
1652     for attr in attrs.iter() {
1653         rbml_w.start_tag(tag_attribute);
1654         rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1655         encode_meta_item(rbml_w, &*attr.node.value);
1656         rbml_w.end_tag();
1657     }
1658     rbml_w.end_tag();
1659 }
1660
1661 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1662     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1663         // Pull the cnums and name,vers,hash out of cstore
1664         let mut deps = Vec::new();
1665         cstore.iter_crate_data(|key, val| {
1666             let dep = decoder::CrateDep {
1667                 cnum: key,
1668                 name: decoder::get_crate_name(val.data()),
1669                 hash: decoder::get_crate_hash(val.data()),
1670             };
1671             deps.push(dep);
1672         });
1673
1674         // Sort by cnum
1675         deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1676
1677         // Sanity-check the crate numbers
1678         let mut expected_cnum = 1;
1679         for n in deps.iter() {
1680             assert_eq!(n.cnum, expected_cnum);
1681             expected_cnum += 1;
1682         }
1683
1684         deps
1685     }
1686
1687     // We're just going to write a list of crate 'name-hash-version's, with
1688     // the assumption that they are numbered 1 to n.
1689     // FIXME (#2166): This is not nearly enough to support correct versioning
1690     // but is enough to get transitive crate dependencies working.
1691     rbml_w.start_tag(tag_crate_deps);
1692     let r = get_ordered_deps(cstore);
1693     for dep in r.iter() {
1694         encode_crate_dep(rbml_w, (*dep).clone());
1695     }
1696     rbml_w.end_tag();
1697 }
1698
1699 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1700     rbml_w.start_tag(tag_lang_items);
1701
1702     for (i, def_id) in ecx.tcx.lang_items.items() {
1703         for id in def_id.iter() {
1704             if id.krate == ast::LOCAL_CRATE {
1705                 rbml_w.start_tag(tag_lang_items_item);
1706
1707                 rbml_w.start_tag(tag_lang_items_item_id);
1708                 {
1709                     let wr: &mut SeekableMemWriter = rbml_w.writer;
1710                     wr.write_be_u32(i as u32);
1711                 }
1712                 rbml_w.end_tag();   // tag_lang_items_item_id
1713
1714                 rbml_w.start_tag(tag_lang_items_item_node_id);
1715                 {
1716                     let wr: &mut SeekableMemWriter = rbml_w.writer;
1717                     wr.write_be_u32(id.node as u32);
1718                 }
1719                 rbml_w.end_tag();   // tag_lang_items_item_node_id
1720
1721                 rbml_w.end_tag();   // tag_lang_items_item
1722             }
1723         }
1724     }
1725
1726     for i in ecx.tcx.lang_items.missing.iter() {
1727         rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1728     }
1729
1730     rbml_w.end_tag();   // tag_lang_items
1731 }
1732
1733 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1734     rbml_w.start_tag(tag_native_libraries);
1735
1736     for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1737                                .borrow().iter() {
1738         match kind {
1739             cstore::NativeStatic => {} // these libraries are not propagated
1740             cstore::NativeFramework | cstore::NativeUnknown => {
1741                 rbml_w.start_tag(tag_native_libraries_lib);
1742
1743                 rbml_w.start_tag(tag_native_libraries_kind);
1744                 rbml_w.writer.write_be_u32(kind as u32);
1745                 rbml_w.end_tag();
1746
1747                 rbml_w.start_tag(tag_native_libraries_name);
1748                 rbml_w.writer.write(lib.as_bytes());
1749                 rbml_w.end_tag();
1750
1751                 rbml_w.end_tag();
1752             }
1753         }
1754     }
1755
1756     rbml_w.end_tag();
1757 }
1758
1759 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1760     match ecx.tcx.sess.plugin_registrar_fn.get() {
1761         Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1762         None => {}
1763     }
1764 }
1765
1766 /// Given a span, write the text of that span into the output stream
1767 /// as an exported macro
1768 fn encode_macro_def(ecx: &EncodeContext,
1769                     rbml_w: &mut Encoder,
1770                     span: &syntax::codemap::Span) {
1771     let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1772         .expect("Unable to find source for macro");
1773     rbml_w.start_tag(tag_macro_def);
1774     rbml_w.wr_str(def.as_slice());
1775     rbml_w.end_tag();
1776 }
1777
1778 /// Serialize the text of the exported macros
1779 fn encode_macro_defs(ecx: &EncodeContext,
1780                      krate: &ast::Crate,
1781                      rbml_w: &mut Encoder) {
1782     rbml_w.start_tag(tag_exported_macros);
1783     for item in krate.exported_macros.iter() {
1784         encode_macro_def(ecx, rbml_w, &item.span);
1785     }
1786     rbml_w.end_tag();
1787 }
1788
1789 fn encode_unboxed_closures<'a>(
1790                            ecx: &'a EncodeContext,
1791                            rbml_w: &'a mut Encoder) {
1792     rbml_w.start_tag(tag_unboxed_closures);
1793     for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1794                                                     .unboxed_closures
1795                                                     .borrow()
1796                                                     .iter() {
1797         if unboxed_closure_id.krate != ast::LOCAL_CRATE {
1798             continue
1799         }
1800
1801         rbml_w.start_tag(tag_unboxed_closure);
1802         encode_def_id(rbml_w, *unboxed_closure_id);
1803         rbml_w.start_tag(tag_unboxed_closure_type);
1804         write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
1805         rbml_w.end_tag();
1806         encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
1807         rbml_w.end_tag();
1808     }
1809     rbml_w.end_tag();
1810 }
1811
1812 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
1813     struct StructFieldVisitor<'a, 'b:'a> {
1814         rbml_w: &'a mut Encoder<'b>,
1815     }
1816
1817     impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1818         fn visit_struct_field(&mut self, field: &ast::StructField) {
1819             self.rbml_w.start_tag(tag_struct_field);
1820             self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1821             encode_attributes(self.rbml_w, field.node.attrs.as_slice());
1822             self.rbml_w.end_tag();
1823         }
1824     }
1825
1826     rbml_w.start_tag(tag_struct_fields);
1827     visit::walk_crate(&mut StructFieldVisitor {
1828         rbml_w: rbml_w
1829     }, krate);
1830     rbml_w.end_tag();
1831 }
1832
1833
1834
1835 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1836     ecx: &'a EncodeContext<'b, 'tcx>,
1837     rbml_w: &'a mut Encoder<'c>,
1838 }
1839
1840 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1841     fn visit_item(&mut self, item: &ast::Item) {
1842         if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node {
1843             let def_map = &self.ecx.tcx.def_map;
1844             let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
1845             let def_id = trait_def.def_id();
1846
1847             // Load eagerly if this is an implementation of the Drop trait
1848             // or if the trait is not defined in this crate.
1849             if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1850                     def_id.krate != ast::LOCAL_CRATE {
1851                 self.rbml_w.start_tag(tag_impls_impl);
1852                 encode_def_id(self.rbml_w, local_def(item.id));
1853                 self.rbml_w.end_tag();
1854             }
1855         }
1856         visit::walk_item(self, item);
1857     }
1858 }
1859
1860 /// Encodes implementations that are eagerly loaded.
1861 ///
1862 /// None of this is necessary in theory; we can load all implementations
1863 /// lazily. However, in two cases the optimizations to lazily load
1864 /// implementations are not yet implemented. These two cases, which require us
1865 /// to load implementations eagerly, are:
1866 ///
1867 /// * Destructors (implementations of the Drop trait).
1868 ///
1869 /// * Implementations of traits not defined in this crate.
1870 fn encode_impls<'a>(ecx: &'a EncodeContext,
1871                     krate: &ast::Crate,
1872                     rbml_w: &'a mut Encoder) {
1873     rbml_w.start_tag(tag_impls);
1874
1875     {
1876         let mut visitor = ImplVisitor {
1877             ecx: ecx,
1878             rbml_w: rbml_w,
1879         };
1880         visit::walk_crate(&mut visitor, krate);
1881     }
1882
1883     rbml_w.end_tag();
1884 }
1885
1886 fn encode_misc_info(ecx: &EncodeContext,
1887                     krate: &ast::Crate,
1888                     rbml_w: &mut Encoder) {
1889     rbml_w.start_tag(tag_misc_info);
1890     rbml_w.start_tag(tag_misc_info_crate_items);
1891     for item in krate.module.items.iter() {
1892         rbml_w.start_tag(tag_mod_child);
1893         rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1894         rbml_w.end_tag();
1895
1896         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1897             rbml_w.start_tag(tag_mod_child);
1898             rbml_w.wr_str(def_to_string(local_def(
1899                         auxiliary_node_id)).as_slice());
1900             rbml_w.end_tag();
1901             true
1902         });
1903     }
1904
1905     // Encode reexports for the root module.
1906     encode_reexports(ecx, rbml_w, 0, ast_map::Values([].iter()).chain(None));
1907
1908     rbml_w.end_tag();
1909     rbml_w.end_tag();
1910 }
1911
1912 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1913     rbml_w.start_tag(tag_reachable_extern_fns);
1914
1915     for id in ecx.reachable.iter() {
1916         if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1917             if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1918                 if abi != abi::Rust && !generics.is_type_parameterized() {
1919                     rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1920                 }
1921             }
1922         }
1923     }
1924
1925     rbml_w.end_tag();
1926 }
1927
1928 fn encode_crate_dep(rbml_w: &mut Encoder,
1929                     dep: decoder::CrateDep) {
1930     rbml_w.start_tag(tag_crate_dep);
1931     rbml_w.start_tag(tag_crate_dep_crate_name);
1932     rbml_w.writer.write(dep.name.as_bytes());
1933     rbml_w.end_tag();
1934     rbml_w.start_tag(tag_crate_dep_hash);
1935     rbml_w.writer.write(dep.hash.as_str().as_bytes());
1936     rbml_w.end_tag();
1937     rbml_w.end_tag();
1938 }
1939
1940 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1941     rbml_w.start_tag(tag_crate_hash);
1942     rbml_w.writer.write(hash.as_str().as_bytes());
1943     rbml_w.end_tag();
1944 }
1945
1946 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1947     rbml_w.start_tag(tag_crate_crate_name);
1948     rbml_w.writer.write(crate_name.as_bytes());
1949     rbml_w.end_tag();
1950 }
1951
1952 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1953     rbml_w.start_tag(tag_crate_triple);
1954     rbml_w.writer.write(triple.as_bytes());
1955     rbml_w.end_tag();
1956 }
1957
1958 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
1959     rbml_w.start_tag(tag_dylib_dependency_formats);
1960     match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1961         Some(arr) => {
1962             let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1963                 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1964                     cstore::RequireDynamic => "d",
1965                     cstore::RequireStatic => "s",
1966                 })).to_string())
1967             }).collect::<Vec<String>>();
1968             rbml_w.writer.write(s.connect(",").as_bytes());
1969         }
1970         None => {}
1971     }
1972     rbml_w.end_tag();
1973 }
1974
1975 // NB: Increment this as you change the metadata encoding version.
1976 #[allow(non_upper_case_globals)]
1977 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
1978
1979 pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
1980     let mut wr = SeekableMemWriter::new();
1981     encode_metadata_inner(&mut wr, parms, krate);
1982     let mut v = wr.unwrap();
1983
1984     // And here we run into yet another obscure archive bug: in which metadata
1985     // loaded from archives may have trailing garbage bytes. Awhile back one of
1986     // our tests was failing sporadially on the OSX 64-bit builders (both nopt
1987     // and opt) by having rbml generate an out-of-bounds panic when looking at
1988     // metadata.
1989     //
1990     // Upon investigation it turned out that the metadata file inside of an rlib
1991     // (and ar archive) was being corrupted. Some compilations would generate a
1992     // metadata file which would end in a few extra bytes, while other
1993     // compilations would not have these extra bytes appended to the end. These
1994     // extra bytes were interpreted by rbml as an extra tag, so they ended up
1995     // being interpreted causing the out-of-bounds.
1996     //
1997     // The root cause of why these extra bytes were appearing was never
1998     // discovered, and in the meantime the solution we're employing is to insert
1999     // the length of the metadata to the start of the metadata. Later on this
2000     // will allow us to slice the metadata to the precise length that we just
2001     // generated regardless of trailing bytes that end up in it.
2002     let len = v.len() as u32;
2003     v.insert(0, (len >>  0) as u8);
2004     v.insert(0, (len >>  8) as u8);
2005     v.insert(0, (len >> 16) as u8);
2006     v.insert(0, (len >> 24) as u8);
2007     return v;
2008 }
2009
2010 fn encode_metadata_inner(wr: &mut SeekableMemWriter,
2011                          parms: EncodeParams,
2012                          krate: &ast::Crate) {
2013     struct Stats {
2014         attr_bytes: u64,
2015         dep_bytes: u64,
2016         lang_item_bytes: u64,
2017         native_lib_bytes: u64,
2018         plugin_registrar_fn_bytes: u64,
2019         macro_defs_bytes: u64,
2020         unboxed_closure_bytes: u64,
2021         impl_bytes: u64,
2022         misc_bytes: u64,
2023         item_bytes: u64,
2024         index_bytes: u64,
2025         zero_bytes: u64,
2026         total_bytes: u64,
2027     }
2028     let mut stats = Stats {
2029         attr_bytes: 0,
2030         dep_bytes: 0,
2031         lang_item_bytes: 0,
2032         native_lib_bytes: 0,
2033         plugin_registrar_fn_bytes: 0,
2034         macro_defs_bytes: 0,
2035         unboxed_closure_bytes: 0,
2036         impl_bytes: 0,
2037         misc_bytes: 0,
2038         item_bytes: 0,
2039         index_bytes: 0,
2040         zero_bytes: 0,
2041         total_bytes: 0,
2042     };
2043     let EncodeParams {
2044         item_symbols,
2045         diag,
2046         tcx,
2047         reexports2,
2048         cstore,
2049         encode_inlined_item,
2050         link_meta,
2051         reachable,
2052         ..
2053     } = parms;
2054     let ecx = EncodeContext {
2055         diag: diag,
2056         tcx: tcx,
2057         reexports2: reexports2,
2058         item_symbols: item_symbols,
2059         link_meta: link_meta,
2060         cstore: cstore,
2061         encode_inlined_item: RefCell::new(encode_inlined_item),
2062         type_abbrevs: RefCell::new(FnvHashMap::new()),
2063         reachable: reachable,
2064      };
2065
2066     let mut rbml_w = writer::Encoder::new(wr);
2067
2068     encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.as_slice());
2069     encode_crate_triple(&mut rbml_w,
2070                         tcx.sess
2071                            .opts
2072                            .target_triple
2073                            .as_slice());
2074     encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2075     encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2076
2077     let mut i = rbml_w.writer.tell().unwrap();
2078     encode_attributes(&mut rbml_w, krate.attrs.as_slice());
2079     stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
2080
2081     i = rbml_w.writer.tell().unwrap();
2082     encode_crate_deps(&mut rbml_w, ecx.cstore);
2083     stats.dep_bytes = rbml_w.writer.tell().unwrap() - i;
2084
2085     // Encode the language items.
2086     i = rbml_w.writer.tell().unwrap();
2087     encode_lang_items(&ecx, &mut rbml_w);
2088     stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i;
2089
2090     // Encode the native libraries used
2091     i = rbml_w.writer.tell().unwrap();
2092     encode_native_libraries(&ecx, &mut rbml_w);
2093     stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i;
2094
2095     // Encode the plugin registrar function
2096     i = rbml_w.writer.tell().unwrap();
2097     encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2098     stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
2099
2100     // Encode macro definitions
2101     i = rbml_w.writer.tell().unwrap();
2102     encode_macro_defs(&ecx, krate, &mut rbml_w);
2103     stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
2104
2105     // Encode the types of all unboxed closures in this crate.
2106     i = rbml_w.writer.tell().unwrap();
2107     encode_unboxed_closures(&ecx, &mut rbml_w);
2108     stats.unboxed_closure_bytes = rbml_w.writer.tell().unwrap() - i;
2109
2110     // Encode the def IDs of impls, for coherence checking.
2111     i = rbml_w.writer.tell().unwrap();
2112     encode_impls(&ecx, krate, &mut rbml_w);
2113     stats.impl_bytes = rbml_w.writer.tell().unwrap() - i;
2114
2115     // Encode miscellaneous info.
2116     i = rbml_w.writer.tell().unwrap();
2117     encode_misc_info(&ecx, krate, &mut rbml_w);
2118     encode_reachable_extern_fns(&ecx, &mut rbml_w);
2119     stats.misc_bytes = rbml_w.writer.tell().unwrap() - i;
2120
2121     // Encode and index the items.
2122     rbml_w.start_tag(tag_items);
2123     i = rbml_w.writer.tell().unwrap();
2124     let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2125     stats.item_bytes = rbml_w.writer.tell().unwrap() - i;
2126
2127     i = rbml_w.writer.tell().unwrap();
2128     encode_index(&mut rbml_w, items_index, write_i64);
2129     stats.index_bytes = rbml_w.writer.tell().unwrap() - i;
2130     rbml_w.end_tag();
2131
2132     encode_struct_field_attrs(&mut rbml_w, krate);
2133
2134     stats.total_bytes = rbml_w.writer.tell().unwrap();
2135
2136     if tcx.sess.meta_stats() {
2137         for e in rbml_w.writer.get_ref().iter() {
2138             if *e == 0 {
2139                 stats.zero_bytes += 1;
2140             }
2141         }
2142
2143         println!("metadata stats:");
2144         println!("       attribute bytes: {}", stats.attr_bytes);
2145         println!("             dep bytes: {}", stats.dep_bytes);
2146         println!("       lang item bytes: {}", stats.lang_item_bytes);
2147         println!("          native bytes: {}", stats.native_lib_bytes);
2148         println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2149         println!("       macro def bytes: {}", stats.macro_defs_bytes);
2150         println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
2151         println!("            impl bytes: {}", stats.impl_bytes);
2152         println!("            misc bytes: {}", stats.misc_bytes);
2153         println!("            item bytes: {}", stats.item_bytes);
2154         println!("           index bytes: {}", stats.index_bytes);
2155         println!("            zero bytes: {}", stats.zero_bytes);
2156         println!("           total bytes: {}", stats.total_bytes);
2157     }
2158 }
2159
2160 // Get the encoded string for a type
2161 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2162     let mut wr = SeekableMemWriter::new();
2163     tyencode::enc_ty(&mut wr, &tyencode::ctxt {
2164         diag: tcx.sess.diagnostic(),
2165         ds: def_to_string,
2166         tcx: tcx,
2167         abbrevs: &RefCell::new(FnvHashMap::new())
2168     }, t);
2169     String::from_utf8(wr.unwrap()).unwrap()
2170 }