]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
rollup merge of #20518: nagisa/weighted-bool
[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> =
63     Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
64
65 pub struct EncodeParams<'a, 'tcx: 'a> {
66     pub diag: &'a SpanHandler,
67     pub tcx: &'a ty::ctxt<'tcx>,
68     pub reexports: &'a def::ExportMap,
69     pub item_symbols: &'a RefCell<NodeMap<String>>,
70     pub link_meta: &'a LinkMeta,
71     pub cstore: &'a cstore::CStore,
72     pub encode_inlined_item: EncodeInlinedItem<'a>,
73     pub reachable: &'a NodeSet,
74 }
75
76 pub struct EncodeContext<'a, 'tcx: 'a> {
77     pub diag: &'a SpanHandler,
78     pub tcx: &'a ty::ctxt<'tcx>,
79     pub reexports: &'a def::ExportMap,
80     pub item_symbols: &'a RefCell<NodeMap<String>>,
81     pub link_meta: &'a LinkMeta,
82     pub cstore: &'a cstore::CStore,
83     pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
84     pub type_abbrevs: tyencode::abbrev_map<'tcx>,
85     pub reachable: &'a NodeSet,
86 }
87
88 fn encode_name(rbml_w: &mut Encoder, name: ast::Name) {
89     rbml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
90 }
91
92 fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) {
93     rbml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
94 }
95
96 pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
97     rbml_w.wr_tagged_str(tag_def_id, def_to_string(id)[]);
98 }
99
100 #[derive(Clone)]
101 struct entry<T> {
102     val: T,
103     pos: u64
104 }
105
106 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
107                               ecx: &EncodeContext<'a, 'tcx>,
108                               trait_ref: &ty::TraitRef<'tcx>,
109                               tag: uint) {
110     let ty_str_ctxt = &tyencode::ctxt {
111         diag: ecx.diag,
112         ds: def_to_string,
113         tcx: ecx.tcx,
114         abbrevs: &ecx.type_abbrevs
115     };
116
117     rbml_w.start_tag(tag);
118     tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
119     rbml_w.end_tag();
120 }
121
122 // Item info table encoding
123 fn encode_family(rbml_w: &mut Encoder, c: char) {
124     rbml_w.start_tag(tag_items_data_item_family);
125     rbml_w.writer.write(&[c as u8]);
126     rbml_w.end_tag();
127 }
128
129 pub fn def_to_string(did: DefId) -> String {
130     format!("{}:{}", did.krate, did.node)
131 }
132
133 fn encode_item_variances(rbml_w: &mut Encoder,
134                          ecx: &EncodeContext,
135                          id: NodeId) {
136     let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
137     rbml_w.start_tag(tag_item_variances);
138     v.encode(rbml_w);
139     rbml_w.end_tag();
140 }
141
142 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
143                                     ecx: &EncodeContext<'a, 'tcx>,
144                                     pty: &ty::TypeScheme<'tcx>) {
145     encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics);
146     encode_type(ecx, rbml_w, pty.ty);
147 }
148
149 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
150     rbml_w.start_tag(tag_items_data_item_variant);
151     let s = def_to_string(vid);
152     rbml_w.writer.write(s.as_bytes());
153     rbml_w.end_tag();
154
155     rbml_w.start_tag(tag_mod_child);
156     rbml_w.wr_str(s[]);
157     rbml_w.end_tag();
158 }
159
160 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
161                                     rbml_w: &mut Encoder,
162                                     closure_type: &ty::ClosureTy<'tcx>) {
163     let ty_str_ctxt = &tyencode::ctxt {
164         diag: ecx.diag,
165         ds: def_to_string,
166         tcx: ecx.tcx,
167         abbrevs: &ecx.type_abbrevs
168     };
169     tyencode::enc_closure_ty(rbml_w.writer, ty_str_ctxt, closure_type);
170 }
171
172 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
173                             rbml_w: &mut Encoder,
174                             typ: Ty<'tcx>) {
175     let ty_str_ctxt = &tyencode::ctxt {
176         diag: ecx.diag,
177         ds: def_to_string,
178         tcx: ecx.tcx,
179         abbrevs: &ecx.type_abbrevs
180     };
181     tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ);
182 }
183
184 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
185                                  rbml_w: &mut Encoder,
186                                 trait_ref: &ty::TraitRef<'tcx>) {
187     let ty_str_ctxt = &tyencode::ctxt {
188         diag: ecx.diag,
189         ds: def_to_string,
190         tcx: ecx.tcx,
191         abbrevs: &ecx.type_abbrevs
192     };
193     tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
194 }
195
196 pub fn write_region(ecx: &EncodeContext,
197                     rbml_w: &mut Encoder,
198                     r: ty::Region) {
199     let ty_str_ctxt = &tyencode::ctxt {
200         diag: ecx.diag,
201         ds: def_to_string,
202         tcx: ecx.tcx,
203         abbrevs: &ecx.type_abbrevs
204     };
205     tyencode::enc_region(rbml_w.writer, ty_str_ctxt, r);
206 }
207
208 fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder,
209                            ecx: &EncodeContext<'a, 'tcx>,
210                            bounds: &ty::ParamBounds<'tcx>,
211                            tag: uint) {
212     rbml_w.start_tag(tag);
213
214     let ty_str_ctxt = &tyencode::ctxt { diag: ecx.diag,
215                                         ds: def_to_string,
216                                         tcx: ecx.tcx,
217                                         abbrevs: &ecx.type_abbrevs };
218     tyencode::enc_bounds(rbml_w.writer, ty_str_ctxt, bounds);
219
220     rbml_w.end_tag();
221 }
222
223 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
224                          rbml_w: &mut Encoder,
225                          typ: Ty<'tcx>) {
226     rbml_w.start_tag(tag_items_data_item_type);
227     write_type(ecx, rbml_w, typ);
228     rbml_w.end_tag();
229 }
230
231 fn encode_region(ecx: &EncodeContext,
232                  rbml_w: &mut Encoder,
233                  r: ty::Region) {
234     rbml_w.start_tag(tag_items_data_region);
235     write_region(ecx, rbml_w, r);
236     rbml_w.end_tag();
237 }
238
239 fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
240                                rbml_w: &mut Encoder,
241                                typ: &ty::BareFnTy<'tcx>) {
242     rbml_w.start_tag(tag_item_method_fty);
243
244     let ty_str_ctxt = &tyencode::ctxt {
245         diag: ecx.diag,
246         ds: def_to_string,
247         tcx: ecx.tcx,
248         abbrevs: &ecx.type_abbrevs
249     };
250     tyencode::enc_bare_fn_ty(rbml_w.writer, ty_str_ctxt, typ);
251
252     rbml_w.end_tag();
253 }
254
255 fn encode_symbol(ecx: &EncodeContext,
256                  rbml_w: &mut Encoder,
257                  id: NodeId) {
258     rbml_w.start_tag(tag_items_data_item_symbol);
259     match ecx.item_symbols.borrow().get(&id) {
260         Some(x) => {
261             debug!("encode_symbol(id={}, str={})", id, *x);
262             rbml_w.writer.write(x.as_bytes());
263         }
264         None => {
265             ecx.diag.handler().bug(
266                 format!("encode_symbol: id not found {}", id)[]);
267         }
268     }
269     rbml_w.end_tag();
270 }
271
272 fn encode_disr_val(_: &EncodeContext,
273                    rbml_w: &mut Encoder,
274                    disr_val: ty::Disr) {
275     rbml_w.start_tag(tag_disr_val);
276     let s = disr_val.to_string();
277     rbml_w.writer.write(s.as_bytes());
278     rbml_w.end_tag();
279 }
280
281 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
282     rbml_w.start_tag(tag_items_data_parent_item);
283     let s = def_to_string(id);
284     rbml_w.writer.write(s.as_bytes());
285     rbml_w.end_tag();
286 }
287
288 fn encode_struct_fields(rbml_w: &mut Encoder,
289                         fields: &[ty::field_ty],
290                         origin: DefId) {
291     for f in fields.iter() {
292         if f.name == special_idents::unnamed_field.name {
293             rbml_w.start_tag(tag_item_unnamed_field);
294         } else {
295             rbml_w.start_tag(tag_item_field);
296             encode_name(rbml_w, f.name);
297         }
298         encode_struct_field_family(rbml_w, f.vis);
299         encode_def_id(rbml_w, f.id);
300         rbml_w.start_tag(tag_item_field_origin);
301         let s = def_to_string(origin);
302         rbml_w.writer.write(s.as_bytes());
303         rbml_w.end_tag();
304         rbml_w.end_tag();
305     }
306 }
307
308 fn encode_enum_variant_info(ecx: &EncodeContext,
309                             rbml_w: &mut Encoder,
310                             id: NodeId,
311                             variants: &[P<ast::Variant>],
312                             index: &mut Vec<entry<i64>>) {
313     debug!("encode_enum_variant_info(id={})", id);
314
315     let mut disr_val = 0;
316     let mut i = 0;
317     let vi = ty::enum_variants(ecx.tcx,
318                                DefId { krate: ast::LOCAL_CRATE, node: id });
319     for variant in variants.iter() {
320         let def_id = local_def(variant.node.id);
321         index.push(entry {
322             val: variant.node.id as i64,
323             pos: rbml_w.writer.tell().unwrap(),
324         });
325         rbml_w.start_tag(tag_items_data_item);
326         encode_def_id(rbml_w, def_id);
327         match variant.node.kind {
328             ast::TupleVariantKind(_) => encode_family(rbml_w, 'v'),
329             ast::StructVariantKind(_) => encode_family(rbml_w, 'V')
330         }
331         encode_name(rbml_w, variant.node.name.name);
332         encode_parent_item(rbml_w, local_def(id));
333         encode_visibility(rbml_w, variant.node.vis);
334         encode_attributes(rbml_w, variant.node.attrs[]);
335         encode_repr_attrs(rbml_w, ecx, variant.node.attrs[]);
336
337         let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
338         encode_stability(rbml_w, stab);
339
340         match variant.node.kind {
341             ast::TupleVariantKind(_) => {},
342             ast::StructVariantKind(_) => {
343                 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
344                 let idx = encode_info_for_struct(ecx,
345                                                  rbml_w,
346                                                  fields[],
347                                                  index);
348                 encode_struct_fields(rbml_w, fields[], def_id);
349                 encode_index(rbml_w, idx, write_i64);
350             }
351         }
352         if (*vi)[i].disr_val != disr_val {
353             encode_disr_val(ecx, rbml_w, (*vi)[i].disr_val);
354             disr_val = (*vi)[i].disr_val;
355         }
356         encode_bounds_and_type(rbml_w, ecx,
357                                &lookup_item_type(ecx.tcx, def_id));
358
359         ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
360         rbml_w.end_tag();
361         disr_val += 1;
362         i += 1;
363     }
364 }
365
366 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
367     let path = path.collect::<Vec<_>>();
368     rbml_w.start_tag(tag_path);
369     rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
370     for pe in path.iter() {
371         let tag = match *pe {
372             ast_map::PathMod(_) => tag_path_elem_mod,
373             ast_map::PathName(_) => tag_path_elem_name
374         };
375         rbml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
376     }
377     rbml_w.end_tag();
378 }
379
380 fn encode_reexported_static_method(rbml_w: &mut Encoder,
381                                    exp: &def::Export,
382                                    method_def_id: DefId,
383                                    method_name: ast::Name) {
384     debug!("(encode reexported static method) {}::{}",
385             exp.name, token::get_name(method_name));
386     rbml_w.start_tag(tag_items_data_item_reexport);
387     rbml_w.start_tag(tag_items_data_item_reexport_def_id);
388     rbml_w.wr_str(def_to_string(method_def_id)[]);
389     rbml_w.end_tag();
390     rbml_w.start_tag(tag_items_data_item_reexport_name);
391     rbml_w.wr_str(format!("{}::{}",
392                           exp.name,
393                           token::get_name(method_name))[]);
394     rbml_w.end_tag();
395     rbml_w.end_tag();
396 }
397
398 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
399                                          rbml_w: &mut Encoder,
400                                          exp: &def::Export)
401                                          -> bool {
402     let impl_items = ecx.tcx.impl_items.borrow();
403     match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
404         Some(implementations) => {
405             for base_impl_did in implementations.iter() {
406                 for &method_did in (*impl_items)[*base_impl_did].iter() {
407                     let impl_item = ty::impl_or_trait_item(
408                         ecx.tcx,
409                         method_did.def_id());
410                     match impl_item {
411                         ty::MethodTraitItem(ref m) => {
412                             encode_reexported_static_method(rbml_w,
413                                                             exp,
414                                                             m.def_id,
415                                                             m.name);
416                         }
417                         ty::TypeTraitItem(_) => {}
418                     }
419                 }
420             }
421
422             true
423         }
424         None => { false }
425     }
426 }
427
428 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
429                                           rbml_w: &mut Encoder,
430                                           exp: &def::Export)
431                                           -> bool {
432     match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
433         Some(trait_items) => {
434             for trait_item in trait_items.iter() {
435                 if let ty::MethodTraitItem(ref m) = *trait_item {
436                     encode_reexported_static_method(rbml_w,
437                                                     exp,
438                                                     m.def_id,
439                                                     m.name);
440                 }
441             }
442             true
443         }
444         None => { false }
445     }
446 }
447
448 fn encode_reexported_static_methods(ecx: &EncodeContext,
449                                     rbml_w: &mut Encoder,
450                                     mod_path: PathElems,
451                                     exp: &def::Export) {
452     if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
453         let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
454             let (mut a, mut b) = (path, mod_path.clone());
455             loop {
456                 match (a.next(), b.next()) {
457                     (None, None) => return true,
458                     (None, _) | (_, None) => return false,
459                     (Some(x), Some(y)) => if x != y { return false },
460                 }
461             }
462         });
463
464         //
465         // We don't need to reexport static methods on items
466         // declared in the same module as our `pub use ...` since
467         // that's done when we encode the item itself.
468         //
469         // The only exception is when the reexport *changes* the
470         // name e.g. `pub use Foo = self::Bar` -- we have
471         // encoded metadata for static methods relative to Bar,
472         // but not yet for Foo.
473         //
474         if path_differs || item.ident.name != exp.name {
475             if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
476                 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
477                     debug!("(encode reexported static methods) {} [trait]",
478                            item.ident.name);
479                 }
480             }
481             else {
482                 debug!("(encode reexported static methods) {} [base]",
483                        item.ident.name);
484             }
485         }
486     }
487 }
488
489 /// Iterates through "auxiliary node IDs", which are node IDs that describe
490 /// top-level items that are sub-items of the given item. Specifically:
491 ///
492 /// * For newtype structs, iterates through the node ID of the constructor.
493 fn each_auxiliary_node_id<F>(item: &ast::Item, callback: F) -> bool where
494     F: FnOnce(NodeId) -> bool,
495 {
496     let mut continue_ = true;
497     match item.node {
498         ast::ItemStruct(ref struct_def, _) => {
499             // If this is a newtype struct, return the constructor.
500             match struct_def.ctor_id {
501                 Some(ctor_id) if struct_def.fields.len() > 0 &&
502                         struct_def.fields[0].node.kind.is_unnamed() => {
503                     continue_ = callback(ctor_id);
504                 }
505                 _ => {}
506             }
507         }
508         _ => {}
509     }
510
511     continue_
512 }
513
514 fn encode_reexports(ecx: &EncodeContext,
515                     rbml_w: &mut Encoder,
516                     id: NodeId,
517                     path: PathElems) {
518     debug!("(encoding info for module) encoding reexports for {}", id);
519     match ecx.reexports.get(&id) {
520         Some(ref exports) => {
521             debug!("(encoding info for module) found reexports for {}", id);
522             for exp in exports.iter() {
523                 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
524                         {}",
525                        exp.name,
526                        exp.def_id.krate,
527                        exp.def_id.node,
528                        id);
529                 rbml_w.start_tag(tag_items_data_item_reexport);
530                 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
531                 rbml_w.wr_str(def_to_string(exp.def_id)[]);
532                 rbml_w.end_tag();
533                 rbml_w.start_tag(tag_items_data_item_reexport_name);
534                 rbml_w.wr_str(exp.name.as_str());
535                 rbml_w.end_tag();
536                 rbml_w.end_tag();
537                 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
538             }
539         }
540         None => {
541             debug!("(encoding info for module) found no reexports for {}",
542                    id);
543         }
544     }
545 }
546
547 fn encode_info_for_mod(ecx: &EncodeContext,
548                        rbml_w: &mut Encoder,
549                        md: &ast::Mod,
550                        attrs: &[ast::Attribute],
551                        id: NodeId,
552                        path: PathElems,
553                        name: ast::Ident,
554                        vis: ast::Visibility) {
555     rbml_w.start_tag(tag_items_data_item);
556     encode_def_id(rbml_w, local_def(id));
557     encode_family(rbml_w, 'm');
558     encode_name(rbml_w, name.name);
559     debug!("(encoding info for module) encoding info for module ID {}", id);
560
561     // Encode info about all the module children.
562     for item in md.items.iter() {
563         rbml_w.start_tag(tag_mod_child);
564         rbml_w.wr_str(def_to_string(local_def(item.id))[]);
565         rbml_w.end_tag();
566
567         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
568             rbml_w.start_tag(tag_mod_child);
569             rbml_w.wr_str(def_to_string(local_def(
570                         auxiliary_node_id))[]);
571             rbml_w.end_tag();
572             true
573         });
574
575         if let ast::ItemImpl(..) = item.node {
576             let (ident, did) = (item.ident, item.id);
577             debug!("(encoding info for module) ... encoding impl {} ({}/{})",
578                    token::get_ident(ident),
579                    did, ecx.tcx.map.node_to_string(did));
580
581             rbml_w.start_tag(tag_mod_impl);
582             rbml_w.wr_str(def_to_string(local_def(did))[]);
583             rbml_w.end_tag();
584         }
585     }
586
587     encode_path(rbml_w, path.clone());
588     encode_visibility(rbml_w, vis);
589
590     let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
591     encode_stability(rbml_w, stab);
592
593     // Encode the reexports of this module, if this module is public.
594     if vis == ast::Public {
595         debug!("(encoding info for module) encoding reexports for {}", id);
596         encode_reexports(ecx, rbml_w, id, path);
597     }
598     encode_attributes(rbml_w, attrs);
599
600     rbml_w.end_tag();
601 }
602
603 fn encode_struct_field_family(rbml_w: &mut Encoder,
604                               visibility: ast::Visibility) {
605     encode_family(rbml_w, match visibility {
606         ast::Public => 'g',
607         ast::Inherited => 'N'
608     });
609 }
610
611 fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
612     rbml_w.start_tag(tag_items_data_item_visibility);
613     let ch = match visibility {
614         ast::Public => 'y',
615         ast::Inherited => 'i',
616     };
617     rbml_w.wr_str(ch.to_string()[]);
618     rbml_w.end_tag();
619 }
620
621 fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
622                                kind: ty::UnboxedClosureKind) {
623     rbml_w.start_tag(tag_unboxed_closure_kind);
624     let ch = match kind {
625         ty::FnUnboxedClosureKind => 'f',
626         ty::FnMutUnboxedClosureKind => 'm',
627         ty::FnOnceUnboxedClosureKind => 'o',
628     };
629     rbml_w.wr_str(ch.to_string()[]);
630     rbml_w.end_tag();
631 }
632
633 fn encode_explicit_self(rbml_w: &mut Encoder,
634                         explicit_self: &ty::ExplicitSelfCategory) {
635     rbml_w.start_tag(tag_item_trait_method_explicit_self);
636
637     // Encode the base self type.
638     match *explicit_self {
639         ty::StaticExplicitSelfCategory => {
640             rbml_w.writer.write(&[ 's' as u8 ]);
641         }
642         ty::ByValueExplicitSelfCategory => {
643             rbml_w.writer.write(&[ 'v' as u8 ]);
644         }
645         ty::ByBoxExplicitSelfCategory => {
646             rbml_w.writer.write(&[ '~' as u8 ]);
647         }
648         ty::ByReferenceExplicitSelfCategory(_, m) => {
649             // FIXME(#4846) encode custom lifetime
650             rbml_w.writer.write(&['&' as u8]);
651             encode_mutability(rbml_w, m);
652         }
653     }
654
655     rbml_w.end_tag();
656
657     fn encode_mutability(rbml_w: &mut Encoder,
658                          m: ast::Mutability) {
659         match m {
660             ast::MutImmutable => { rbml_w.writer.write(&[ 'i' as u8 ]); }
661             ast::MutMutable => { rbml_w.writer.write(&[ 'm' as u8 ]); }
662         }
663     }
664 }
665
666 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
667     rbml_w.start_tag(tag_item_trait_item_sort);
668     rbml_w.writer.write(&[ sort as u8 ]);
669     rbml_w.end_tag();
670 }
671
672 fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
673     rbml_w.start_tag(tag_item_trait_parent_sort);
674     rbml_w.writer.write(&[ sort as u8 ]);
675     rbml_w.end_tag();
676 }
677
678 fn encode_provided_source(rbml_w: &mut Encoder,
679                           source_opt: Option<DefId>) {
680     for source in source_opt.iter() {
681         rbml_w.start_tag(tag_item_method_provided_source);
682         let s = def_to_string(*source);
683         rbml_w.writer.write(s.as_bytes());
684         rbml_w.end_tag();
685     }
686 }
687
688 /* Returns an index of items in this class */
689 fn encode_info_for_struct(ecx: &EncodeContext,
690                           rbml_w: &mut Encoder,
691                           fields: &[ty::field_ty],
692                           global_index: &mut Vec<entry<i64>>)
693                           -> Vec<entry<i64>> {
694     /* Each class has its own index, since different classes
695        may have fields with the same name */
696     let mut index = Vec::new();
697      /* We encode both private and public fields -- need to include
698         private fields to get the offsets right */
699     for field in fields.iter() {
700         let nm = field.name;
701         let id = field.id.node;
702
703         index.push(entry {val: id as i64, pos: rbml_w.writer.tell().unwrap()});
704         global_index.push(entry {
705             val: id as i64,
706             pos: rbml_w.writer.tell().unwrap(),
707         });
708         rbml_w.start_tag(tag_items_data_item);
709         debug!("encode_info_for_struct: doing {} {}",
710                token::get_name(nm), id);
711         encode_struct_field_family(rbml_w, field.vis);
712         encode_name(rbml_w, nm);
713         encode_bounds_and_type(rbml_w, ecx,
714                                &lookup_item_type(ecx.tcx, local_def(id)));
715         encode_def_id(rbml_w, local_def(id));
716
717         let stab = stability::lookup(ecx.tcx, field.id);
718         encode_stability(rbml_w, stab);
719
720         rbml_w.end_tag();
721     }
722     index
723 }
724
725 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
726                                rbml_w: &mut Encoder,
727                                name: ast::Ident,
728                                ctor_id: NodeId,
729                                index: &mut Vec<entry<i64>>,
730                                struct_id: NodeId) {
731     index.push(entry {
732         val: ctor_id as i64,
733         pos: rbml_w.writer.tell().unwrap(),
734     });
735
736     rbml_w.start_tag(tag_items_data_item);
737     encode_def_id(rbml_w, local_def(ctor_id));
738     encode_family(rbml_w, 'o');
739     encode_bounds_and_type(rbml_w, ecx,
740                            &lookup_item_type(ecx.tcx, local_def(ctor_id)));
741     encode_name(rbml_w, name.name);
742     ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
743     encode_parent_item(rbml_w, local_def(struct_id));
744
745     if ecx.item_symbols.borrow().contains_key(&ctor_id) {
746         encode_symbol(ecx, rbml_w, ctor_id);
747     }
748
749     let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
750     encode_stability(rbml_w, stab);
751
752     // indicate that this is a tuple struct ctor, because downstream users will normally want
753     // the tuple struct definition, but without this there is no way for them to tell that
754     // they actually have a ctor rather than a normal function
755     rbml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
756     rbml_w.end_tag();
757
758     rbml_w.end_tag();
759 }
760
761 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
762                              ecx: &EncodeContext<'a, 'tcx>,
763                              generics: &ty::Generics<'tcx>,
764                              tag: uint)
765 {
766     rbml_w.start_tag(tag);
767
768     // Type parameters
769     let ty_str_ctxt = &tyencode::ctxt {
770         diag: ecx.diag,
771         ds: def_to_string,
772         tcx: ecx.tcx,
773         abbrevs: &ecx.type_abbrevs
774     };
775     for param in generics.types.iter() {
776         rbml_w.start_tag(tag_type_param_def);
777         tyencode::enc_type_param_def(rbml_w.writer, ty_str_ctxt, param);
778         rbml_w.end_tag();
779     }
780
781     // Region parameters
782     for param in generics.regions.iter() {
783         rbml_w.start_tag(tag_region_param_def);
784
785         rbml_w.start_tag(tag_region_param_def_ident);
786         encode_name(rbml_w, param.name);
787         rbml_w.end_tag();
788
789         rbml_w.wr_tagged_str(tag_region_param_def_def_id,
790                              def_to_string(param.def_id)[]);
791
792         rbml_w.wr_tagged_u64(tag_region_param_def_space,
793                              param.space.to_uint() as u64);
794
795         rbml_w.wr_tagged_u64(tag_region_param_def_index,
796                              param.index as u64);
797
798         for &bound_region in param.bounds.iter() {
799             encode_region(ecx, rbml_w, bound_region);
800         }
801
802         rbml_w.end_tag();
803     }
804
805     for (space, _, predicate) in generics.predicates.iter_enumerated() {
806         rbml_w.start_tag(tag_predicate);
807
808         rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
809
810         rbml_w.start_tag(tag_predicate_data);
811         tyencode::enc_predicate(rbml_w.writer, ty_str_ctxt, predicate);
812         rbml_w.end_tag();
813
814         rbml_w.end_tag();
815     }
816
817     rbml_w.end_tag();
818 }
819
820 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
821                                      rbml_w: &mut Encoder,
822                                      method_ty: &ty::Method<'tcx>) {
823     encode_def_id(rbml_w, method_ty.def_id);
824     encode_name(rbml_w, method_ty.name);
825     encode_generics(rbml_w, ecx, &method_ty.generics,
826                     tag_method_ty_generics);
827     encode_method_fty(ecx, rbml_w, &method_ty.fty);
828     encode_visibility(rbml_w, method_ty.vis);
829     encode_explicit_self(rbml_w, &method_ty.explicit_self);
830     match method_ty.explicit_self {
831         ty::StaticExplicitSelfCategory => {
832             encode_family(rbml_w, STATIC_METHOD_FAMILY);
833         }
834         _ => encode_family(rbml_w, METHOD_FAMILY)
835     }
836     encode_provided_source(rbml_w, method_ty.provided_source);
837 }
838
839 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
840                                     rbml_w: &mut Encoder,
841                                     m: &ty::Method<'tcx>,
842                                     impl_path: PathElems,
843                                     is_default_impl: bool,
844                                     parent_id: NodeId,
845                                     ast_item_opt: Option<&ast::ImplItem>) {
846
847     debug!("encode_info_for_method: {} {}", m.def_id,
848            token::get_name(m.name));
849     rbml_w.start_tag(tag_items_data_item);
850
851     encode_method_ty_fields(ecx, rbml_w, m);
852     encode_parent_item(rbml_w, local_def(parent_id));
853     encode_item_sort(rbml_w, 'r');
854
855     let stab = stability::lookup(ecx.tcx, m.def_id);
856     encode_stability(rbml_w, stab);
857
858     // The type for methods gets encoded twice, which is unfortunate.
859     let pty = lookup_item_type(ecx.tcx, m.def_id);
860     encode_bounds_and_type(rbml_w, ecx, &pty);
861
862     let elem = ast_map::PathName(m.name);
863     encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
864     match ast_item_opt {
865         Some(&ast::MethodImplItem(ref ast_method)) => {
866             encode_attributes(rbml_w, ast_method.attrs[]);
867             let any_types = !pty.generics.types.is_empty();
868             if any_types || is_default_impl || should_inline(ast_method.attrs[]) {
869                 encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
870                                                                ast_item_opt.unwrap()));
871             }
872             if !any_types {
873                 encode_symbol(ecx, rbml_w, m.def_id.node);
874             }
875             encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
876         }
877         Some(_) | None => {}
878     }
879
880     rbml_w.end_tag();
881 }
882
883 fn encode_info_for_associated_type(ecx: &EncodeContext,
884                                    rbml_w: &mut Encoder,
885                                    associated_type: &ty::AssociatedType,
886                                    impl_path: PathElems,
887                                    parent_id: NodeId,
888                                    typedef_opt: Option<P<ast::Typedef>>) {
889     debug!("encode_info_for_associated_type({},{})",
890            associated_type.def_id,
891            token::get_name(associated_type.name));
892
893     rbml_w.start_tag(tag_items_data_item);
894
895     encode_def_id(rbml_w, associated_type.def_id);
896     encode_name(rbml_w, associated_type.name);
897     encode_visibility(rbml_w, associated_type.vis);
898     encode_family(rbml_w, 'y');
899     encode_parent_item(rbml_w, local_def(parent_id));
900     encode_item_sort(rbml_w, 't');
901
902     let type_scheme = ty::lookup_item_type(ecx.tcx, associated_type.def_id);
903     encode_bounds_and_type(rbml_w, ecx, &type_scheme);
904
905     let stab = stability::lookup(ecx.tcx, associated_type.def_id);
906     encode_stability(rbml_w, stab);
907
908     let elem = ast_map::PathName(associated_type.name);
909     encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
910
911     match typedef_opt {
912         None => {}
913         Some(typedef) => {
914             encode_attributes(rbml_w, typedef.attrs[]);
915             encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
916                                                          typedef.id));
917         }
918     }
919
920     rbml_w.end_tag();
921 }
922
923 fn encode_method_argument_names(rbml_w: &mut Encoder,
924                                 decl: &ast::FnDecl) {
925     rbml_w.start_tag(tag_method_argument_names);
926     for arg in decl.inputs.iter() {
927         rbml_w.start_tag(tag_method_argument_name);
928         if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
929             let name = token::get_ident(path1.node);
930             rbml_w.writer.write(name.get().as_bytes());
931         }
932         rbml_w.end_tag();
933     }
934     rbml_w.end_tag();
935 }
936
937 fn encode_repr_attrs(rbml_w: &mut Encoder,
938                      ecx: &EncodeContext,
939                      attrs: &[ast::Attribute]) {
940     let mut repr_attrs = Vec::new();
941     for attr in attrs.iter() {
942         repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
943                                                 attr).into_iter());
944     }
945     rbml_w.start_tag(tag_items_data_item_repr);
946     repr_attrs.encode(rbml_w);
947     rbml_w.end_tag();
948 }
949
950 fn encode_inlined_item(ecx: &EncodeContext,
951                        rbml_w: &mut Encoder,
952                        ii: InlinedItemRef) {
953     let mut eii = ecx.encode_inlined_item.borrow_mut();
954     let eii: &mut EncodeInlinedItem = &mut *eii;
955     eii.call_mut((ecx, rbml_w, ii))
956 }
957
958 const FN_FAMILY: char = 'f';
959 const STATIC_METHOD_FAMILY: char = 'F';
960 const METHOD_FAMILY: char = 'h';
961
962 fn should_inline(attrs: &[ast::Attribute]) -> bool {
963     use syntax::attr::*;
964     match find_inline_attr(attrs) {
965         InlineNone | InlineNever  => false,
966         InlineHint | InlineAlways => true
967     }
968 }
969
970 // Encodes the inherent implementations of a structure, enumeration, or trait.
971 fn encode_inherent_implementations(ecx: &EncodeContext,
972                                    rbml_w: &mut Encoder,
973                                    def_id: DefId) {
974     match ecx.tcx.inherent_impls.borrow().get(&def_id) {
975         None => {}
976         Some(implementations) => {
977             for &impl_def_id in implementations.iter() {
978                 rbml_w.start_tag(tag_items_data_item_inherent_impl);
979                 encode_def_id(rbml_w, impl_def_id);
980                 rbml_w.end_tag();
981             }
982         }
983     }
984 }
985
986 // Encodes the implementations of a trait defined in this crate.
987 fn encode_extension_implementations(ecx: &EncodeContext,
988                                     rbml_w: &mut Encoder,
989                                     trait_def_id: DefId) {
990     match ecx.tcx.trait_impls.borrow().get(&trait_def_id) {
991         None => {}
992         Some(implementations) => {
993             for &impl_def_id in implementations.borrow().iter() {
994                 rbml_w.start_tag(tag_items_data_item_extension_impl);
995                 encode_def_id(rbml_w, impl_def_id);
996                 rbml_w.end_tag();
997             }
998         }
999     }
1000 }
1001
1002 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
1003     stab_opt.map(|stab| {
1004         rbml_w.start_tag(tag_items_data_item_stability);
1005         stab.encode(rbml_w).unwrap();
1006         rbml_w.end_tag();
1007     });
1008 }
1009
1010 fn encode_info_for_item(ecx: &EncodeContext,
1011                         rbml_w: &mut Encoder,
1012                         item: &ast::Item,
1013                         index: &mut Vec<entry<i64>>,
1014                         path: PathElems,
1015                         vis: ast::Visibility) {
1016     let tcx = ecx.tcx;
1017
1018     fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
1019                     index: &mut Vec<entry<i64>>) {
1020         index.push(entry {
1021             val: item.id as i64,
1022             pos: rbml_w.writer.tell().unwrap(),
1023         });
1024     }
1025
1026     debug!("encoding info for item at {}",
1027            tcx.sess.codemap().span_to_string(item.span));
1028
1029     let def_id = local_def(item.id);
1030     let stab = stability::lookup(tcx, ast_util::local_def(item.id));
1031
1032     match item.node {
1033       ast::ItemStatic(_, m, _) => {
1034         add_to_index(item, rbml_w, index);
1035         rbml_w.start_tag(tag_items_data_item);
1036         encode_def_id(rbml_w, def_id);
1037         if m == ast::MutMutable {
1038             encode_family(rbml_w, 'b');
1039         } else {
1040             encode_family(rbml_w, 'c');
1041         }
1042         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1043         encode_symbol(ecx, rbml_w, item.id);
1044         encode_name(rbml_w, item.ident.name);
1045         encode_path(rbml_w, path);
1046         encode_visibility(rbml_w, vis);
1047         encode_stability(rbml_w, stab);
1048         encode_attributes(rbml_w, item.attrs[]);
1049         rbml_w.end_tag();
1050       }
1051       ast::ItemConst(_, _) => {
1052         add_to_index(item, rbml_w, index);
1053         rbml_w.start_tag(tag_items_data_item);
1054         encode_def_id(rbml_w, def_id);
1055         encode_family(rbml_w, 'C');
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         encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1061         encode_visibility(rbml_w, vis);
1062         encode_stability(rbml_w, stab);
1063         rbml_w.end_tag();
1064       }
1065       ast::ItemFn(ref decl, _, _, ref generics, _) => {
1066         add_to_index(item, rbml_w, index);
1067         rbml_w.start_tag(tag_items_data_item);
1068         encode_def_id(rbml_w, def_id);
1069         encode_family(rbml_w, FN_FAMILY);
1070         let tps_len = generics.ty_params.len();
1071         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1072         encode_name(rbml_w, item.ident.name);
1073         encode_path(rbml_w, path);
1074         encode_attributes(rbml_w, item.attrs[]);
1075         if tps_len > 0u || should_inline(item.attrs[]) {
1076             encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1077         }
1078         if tps_len == 0 {
1079             encode_symbol(ecx, rbml_w, item.id);
1080         }
1081         encode_visibility(rbml_w, vis);
1082         encode_stability(rbml_w, stab);
1083         encode_method_argument_names(rbml_w, &**decl);
1084         rbml_w.end_tag();
1085       }
1086       ast::ItemMod(ref m) => {
1087         add_to_index(item, rbml_w, index);
1088         encode_info_for_mod(ecx,
1089                             rbml_w,
1090                             m,
1091                             item.attrs[],
1092                             item.id,
1093                             path,
1094                             item.ident,
1095                             item.vis);
1096       }
1097       ast::ItemForeignMod(ref fm) => {
1098         add_to_index(item, rbml_w, index);
1099         rbml_w.start_tag(tag_items_data_item);
1100         encode_def_id(rbml_w, def_id);
1101         encode_family(rbml_w, 'n');
1102         encode_name(rbml_w, item.ident.name);
1103         encode_path(rbml_w, path);
1104
1105         // Encode all the items in this module.
1106         for foreign_item in fm.items.iter() {
1107             rbml_w.start_tag(tag_mod_child);
1108             rbml_w.wr_str(def_to_string(local_def(foreign_item.id))[]);
1109             rbml_w.end_tag();
1110         }
1111         encode_visibility(rbml_w, vis);
1112         encode_stability(rbml_w, stab);
1113         rbml_w.end_tag();
1114       }
1115       ast::ItemTy(..) => {
1116         add_to_index(item, rbml_w, index);
1117         rbml_w.start_tag(tag_items_data_item);
1118         encode_def_id(rbml_w, def_id);
1119         encode_family(rbml_w, 'y');
1120         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1121         encode_name(rbml_w, item.ident.name);
1122         encode_path(rbml_w, path);
1123         encode_visibility(rbml_w, vis);
1124         encode_stability(rbml_w, stab);
1125         rbml_w.end_tag();
1126       }
1127       ast::ItemEnum(ref enum_definition, _) => {
1128         add_to_index(item, rbml_w, index);
1129
1130         rbml_w.start_tag(tag_items_data_item);
1131         encode_def_id(rbml_w, def_id);
1132         encode_family(rbml_w, 't');
1133         encode_item_variances(rbml_w, ecx, item.id);
1134         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1135         encode_name(rbml_w, item.ident.name);
1136         encode_attributes(rbml_w, item.attrs[]);
1137         encode_repr_attrs(rbml_w, ecx, item.attrs[]);
1138         for v in (*enum_definition).variants.iter() {
1139             encode_variant_id(rbml_w, local_def(v.node.id));
1140         }
1141         encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1142         encode_path(rbml_w, path);
1143
1144         // Encode inherent implementations for this enumeration.
1145         encode_inherent_implementations(ecx, rbml_w, def_id);
1146
1147         encode_visibility(rbml_w, vis);
1148         encode_stability(rbml_w, stab);
1149         rbml_w.end_tag();
1150
1151         encode_enum_variant_info(ecx,
1152                                  rbml_w,
1153                                  item.id,
1154                                  (*enum_definition).variants[],
1155                                  index);
1156       }
1157       ast::ItemStruct(ref struct_def, _) => {
1158         let fields = ty::lookup_struct_fields(tcx, def_id);
1159
1160         /* First, encode the fields
1161            These come first because we need to write them to make
1162            the index, and the index needs to be in the item for the
1163            class itself */
1164         let idx = encode_info_for_struct(ecx,
1165                                          rbml_w,
1166                                          fields[],
1167                                          index);
1168
1169         /* Index the class*/
1170         add_to_index(item, rbml_w, index);
1171
1172         /* Now, make an item for the class itself */
1173         rbml_w.start_tag(tag_items_data_item);
1174         encode_def_id(rbml_w, def_id);
1175         encode_family(rbml_w, 'S');
1176         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1177
1178         encode_item_variances(rbml_w, ecx, item.id);
1179         encode_name(rbml_w, item.ident.name);
1180         encode_attributes(rbml_w, item.attrs[]);
1181         encode_path(rbml_w, path.clone());
1182         encode_stability(rbml_w, stab);
1183         encode_visibility(rbml_w, vis);
1184         encode_repr_attrs(rbml_w, ecx, item.attrs[]);
1185
1186         /* Encode def_ids for each field and method
1187          for methods, write all the stuff get_trait_method
1188         needs to know*/
1189         encode_struct_fields(rbml_w, fields[], def_id);
1190
1191         encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1192
1193         // Encode inherent implementations for this structure.
1194         encode_inherent_implementations(ecx, rbml_w, def_id);
1195
1196         /* Each class has its own index -- encode it */
1197         encode_index(rbml_w, idx, write_i64);
1198         rbml_w.end_tag();
1199
1200         // If this is a tuple-like struct, encode the type of the constructor.
1201         match struct_def.ctor_id {
1202             Some(ctor_id) => {
1203                 encode_info_for_struct_ctor(ecx, rbml_w, item.ident,
1204                                             ctor_id, index, def_id.node);
1205             }
1206             None => {}
1207         }
1208       }
1209       ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
1210         // We need to encode information about the default methods we
1211         // have inherited, so we drive this based on the impl structure.
1212         let impl_items = tcx.impl_items.borrow();
1213         let items = &(*impl_items)[def_id];
1214
1215         add_to_index(item, rbml_w, index);
1216         rbml_w.start_tag(tag_items_data_item);
1217         encode_def_id(rbml_w, def_id);
1218         encode_family(rbml_w, 'i');
1219         encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1220         encode_name(rbml_w, item.ident.name);
1221         encode_attributes(rbml_w, item.attrs[]);
1222         encode_unsafety(rbml_w, unsafety);
1223         encode_polarity(rbml_w, polarity);
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_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
1708     let byte: u8 = match polarity {
1709         ast::ImplPolarity::Positive => 0,
1710         ast::ImplPolarity::Negative => 1,
1711     };
1712     rbml_w.wr_tagged_u8(tag_polarity, byte);
1713 }
1714
1715 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1716     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1717         // Pull the cnums and name,vers,hash out of cstore
1718         let mut deps = Vec::new();
1719         cstore.iter_crate_data(|key, val| {
1720             let dep = decoder::CrateDep {
1721                 cnum: key,
1722                 name: decoder::get_crate_name(val.data()),
1723                 hash: decoder::get_crate_hash(val.data()),
1724             };
1725             deps.push(dep);
1726         });
1727
1728         // Sort by cnum
1729         deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1730
1731         // Sanity-check the crate numbers
1732         let mut expected_cnum = 1;
1733         for n in deps.iter() {
1734             assert_eq!(n.cnum, expected_cnum);
1735             expected_cnum += 1;
1736         }
1737
1738         deps
1739     }
1740
1741     // We're just going to write a list of crate 'name-hash-version's, with
1742     // the assumption that they are numbered 1 to n.
1743     // FIXME (#2166): This is not nearly enough to support correct versioning
1744     // but is enough to get transitive crate dependencies working.
1745     rbml_w.start_tag(tag_crate_deps);
1746     let r = get_ordered_deps(cstore);
1747     for dep in r.iter() {
1748         encode_crate_dep(rbml_w, (*dep).clone());
1749     }
1750     rbml_w.end_tag();
1751 }
1752
1753 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1754     rbml_w.start_tag(tag_lang_items);
1755
1756     for (i, def_id) in ecx.tcx.lang_items.items() {
1757         for id in def_id.iter() {
1758             if id.krate == ast::LOCAL_CRATE {
1759                 rbml_w.start_tag(tag_lang_items_item);
1760
1761                 rbml_w.start_tag(tag_lang_items_item_id);
1762                 {
1763                     let wr: &mut SeekableMemWriter = rbml_w.writer;
1764                     wr.write_be_u32(i as u32);
1765                 }
1766                 rbml_w.end_tag();   // tag_lang_items_item_id
1767
1768                 rbml_w.start_tag(tag_lang_items_item_node_id);
1769                 {
1770                     let wr: &mut SeekableMemWriter = rbml_w.writer;
1771                     wr.write_be_u32(id.node as u32);
1772                 }
1773                 rbml_w.end_tag();   // tag_lang_items_item_node_id
1774
1775                 rbml_w.end_tag();   // tag_lang_items_item
1776             }
1777         }
1778     }
1779
1780     for i in ecx.tcx.lang_items.missing.iter() {
1781         rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1782     }
1783
1784     rbml_w.end_tag();   // tag_lang_items
1785 }
1786
1787 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1788     rbml_w.start_tag(tag_native_libraries);
1789
1790     for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1791                                .borrow().iter() {
1792         match kind {
1793             cstore::NativeStatic => {} // these libraries are not propagated
1794             cstore::NativeFramework | cstore::NativeUnknown => {
1795                 rbml_w.start_tag(tag_native_libraries_lib);
1796
1797                 rbml_w.start_tag(tag_native_libraries_kind);
1798                 rbml_w.writer.write_be_u32(kind as u32);
1799                 rbml_w.end_tag();
1800
1801                 rbml_w.start_tag(tag_native_libraries_name);
1802                 rbml_w.writer.write(lib.as_bytes());
1803                 rbml_w.end_tag();
1804
1805                 rbml_w.end_tag();
1806             }
1807         }
1808     }
1809
1810     rbml_w.end_tag();
1811 }
1812
1813 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1814     match ecx.tcx.sess.plugin_registrar_fn.get() {
1815         Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1816         None => {}
1817     }
1818 }
1819
1820 /// Given a span, write the text of that span into the output stream
1821 /// as an exported macro
1822 fn encode_macro_def(ecx: &EncodeContext,
1823                     rbml_w: &mut Encoder,
1824                     span: &syntax::codemap::Span) {
1825     let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1826         .expect("Unable to find source for macro");
1827     rbml_w.start_tag(tag_macro_def);
1828     rbml_w.wr_str(def[]);
1829     rbml_w.end_tag();
1830 }
1831
1832 /// Serialize the text of the exported macros
1833 fn encode_macro_defs(ecx: &EncodeContext,
1834                      krate: &ast::Crate,
1835                      rbml_w: &mut Encoder) {
1836     rbml_w.start_tag(tag_exported_macros);
1837     for item in krate.exported_macros.iter() {
1838         encode_macro_def(ecx, rbml_w, &item.span);
1839     }
1840     rbml_w.end_tag();
1841 }
1842
1843 fn encode_unboxed_closures<'a>(
1844                            ecx: &'a EncodeContext,
1845                            rbml_w: &'a mut Encoder) {
1846     rbml_w.start_tag(tag_unboxed_closures);
1847     for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1848                                                     .unboxed_closures
1849                                                     .borrow()
1850                                                     .iter() {
1851         if unboxed_closure_id.krate != ast::LOCAL_CRATE {
1852             continue
1853         }
1854
1855         rbml_w.start_tag(tag_unboxed_closure);
1856         encode_def_id(rbml_w, *unboxed_closure_id);
1857         rbml_w.start_tag(tag_unboxed_closure_type);
1858         write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
1859         rbml_w.end_tag();
1860         encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
1861         rbml_w.end_tag();
1862     }
1863     rbml_w.end_tag();
1864 }
1865
1866 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
1867     struct StructFieldVisitor<'a, 'b:'a> {
1868         rbml_w: &'a mut Encoder<'b>,
1869     }
1870
1871     impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1872         fn visit_struct_field(&mut self, field: &ast::StructField) {
1873             self.rbml_w.start_tag(tag_struct_field);
1874             self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1875             encode_attributes(self.rbml_w, field.node.attrs[]);
1876             self.rbml_w.end_tag();
1877         }
1878     }
1879
1880     rbml_w.start_tag(tag_struct_fields);
1881     visit::walk_crate(&mut StructFieldVisitor {
1882         rbml_w: rbml_w
1883     }, krate);
1884     rbml_w.end_tag();
1885 }
1886
1887
1888
1889 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1890     ecx: &'a EncodeContext<'b, 'tcx>,
1891     rbml_w: &'a mut Encoder<'c>,
1892 }
1893
1894 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1895     fn visit_item(&mut self, item: &ast::Item) {
1896         if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
1897             let def_map = &self.ecx.tcx.def_map;
1898             let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
1899             let def_id = trait_def.def_id();
1900
1901             // Load eagerly if this is an implementation of the Drop trait
1902             // or if the trait is not defined in this crate.
1903             if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1904                     def_id.krate != ast::LOCAL_CRATE {
1905                 self.rbml_w.start_tag(tag_impls_impl);
1906                 encode_def_id(self.rbml_w, local_def(item.id));
1907                 self.rbml_w.end_tag();
1908             }
1909         }
1910         visit::walk_item(self, item);
1911     }
1912 }
1913
1914 /// Encodes implementations that are eagerly loaded.
1915 ///
1916 /// None of this is necessary in theory; we can load all implementations
1917 /// lazily. However, in two cases the optimizations to lazily load
1918 /// implementations are not yet implemented. These two cases, which require us
1919 /// to load implementations eagerly, are:
1920 ///
1921 /// * Destructors (implementations of the Drop trait).
1922 ///
1923 /// * Implementations of traits not defined in this crate.
1924 fn encode_impls<'a>(ecx: &'a EncodeContext,
1925                     krate: &ast::Crate,
1926                     rbml_w: &'a mut Encoder) {
1927     rbml_w.start_tag(tag_impls);
1928
1929     {
1930         let mut visitor = ImplVisitor {
1931             ecx: ecx,
1932             rbml_w: rbml_w,
1933         };
1934         visit::walk_crate(&mut visitor, krate);
1935     }
1936
1937     rbml_w.end_tag();
1938 }
1939
1940 fn encode_misc_info(ecx: &EncodeContext,
1941                     krate: &ast::Crate,
1942                     rbml_w: &mut Encoder) {
1943     rbml_w.start_tag(tag_misc_info);
1944     rbml_w.start_tag(tag_misc_info_crate_items);
1945     for item in krate.module.items.iter() {
1946         rbml_w.start_tag(tag_mod_child);
1947         rbml_w.wr_str(def_to_string(local_def(item.id))[]);
1948         rbml_w.end_tag();
1949
1950         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1951             rbml_w.start_tag(tag_mod_child);
1952             rbml_w.wr_str(def_to_string(local_def(
1953                         auxiliary_node_id))[]);
1954             rbml_w.end_tag();
1955             true
1956         });
1957     }
1958
1959     // Encode reexports for the root module.
1960     encode_reexports(ecx, rbml_w, 0, ast_map::Values([].iter()).chain(None));
1961
1962     rbml_w.end_tag();
1963     rbml_w.end_tag();
1964 }
1965
1966 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1967     rbml_w.start_tag(tag_reachable_extern_fns);
1968
1969     for id in ecx.reachable.iter() {
1970         if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1971             if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1972                 if abi != abi::Rust && !generics.is_type_parameterized() {
1973                     rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1974                 }
1975             }
1976         }
1977     }
1978
1979     rbml_w.end_tag();
1980 }
1981
1982 fn encode_crate_dep(rbml_w: &mut Encoder,
1983                     dep: decoder::CrateDep) {
1984     rbml_w.start_tag(tag_crate_dep);
1985     rbml_w.start_tag(tag_crate_dep_crate_name);
1986     rbml_w.writer.write(dep.name.as_bytes());
1987     rbml_w.end_tag();
1988     rbml_w.start_tag(tag_crate_dep_hash);
1989     rbml_w.writer.write(dep.hash.as_str().as_bytes());
1990     rbml_w.end_tag();
1991     rbml_w.end_tag();
1992 }
1993
1994 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1995     rbml_w.start_tag(tag_crate_hash);
1996     rbml_w.writer.write(hash.as_str().as_bytes());
1997     rbml_w.end_tag();
1998 }
1999
2000 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
2001     rbml_w.start_tag(tag_crate_crate_name);
2002     rbml_w.writer.write(crate_name.as_bytes());
2003     rbml_w.end_tag();
2004 }
2005
2006 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
2007     rbml_w.start_tag(tag_crate_triple);
2008     rbml_w.writer.write(triple.as_bytes());
2009     rbml_w.end_tag();
2010 }
2011
2012 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
2013     rbml_w.start_tag(tag_dylib_dependency_formats);
2014     match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
2015         Some(arr) => {
2016             let s = arr.iter().enumerate().filter_map(|(i, slot)| {
2017                 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
2018                     cstore::RequireDynamic => "d",
2019                     cstore::RequireStatic => "s",
2020                 })).to_string())
2021             }).collect::<Vec<String>>();
2022             rbml_w.writer.write(s.connect(",").as_bytes());
2023         }
2024         None => {}
2025     }
2026     rbml_w.end_tag();
2027 }
2028
2029 // NB: Increment this as you change the metadata encoding version.
2030 #[allow(non_upper_case_globals)]
2031 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
2032
2033 pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
2034     let mut wr = SeekableMemWriter::new();
2035     encode_metadata_inner(&mut wr, parms, krate);
2036     let mut v = wr.unwrap();
2037
2038     // And here we run into yet another obscure archive bug: in which metadata
2039     // loaded from archives may have trailing garbage bytes. Awhile back one of
2040     // our tests was failing sporadially on the OSX 64-bit builders (both nopt
2041     // and opt) by having rbml generate an out-of-bounds panic when looking at
2042     // metadata.
2043     //
2044     // Upon investigation it turned out that the metadata file inside of an rlib
2045     // (and ar archive) was being corrupted. Some compilations would generate a
2046     // metadata file which would end in a few extra bytes, while other
2047     // compilations would not have these extra bytes appended to the end. These
2048     // extra bytes were interpreted by rbml as an extra tag, so they ended up
2049     // being interpreted causing the out-of-bounds.
2050     //
2051     // The root cause of why these extra bytes were appearing was never
2052     // discovered, and in the meantime the solution we're employing is to insert
2053     // the length of the metadata to the start of the metadata. Later on this
2054     // will allow us to slice the metadata to the precise length that we just
2055     // generated regardless of trailing bytes that end up in it.
2056     let len = v.len() as u32;
2057     v.insert(0, (len >>  0) as u8);
2058     v.insert(0, (len >>  8) as u8);
2059     v.insert(0, (len >> 16) as u8);
2060     v.insert(0, (len >> 24) as u8);
2061     return v;
2062 }
2063
2064 fn encode_metadata_inner(wr: &mut SeekableMemWriter,
2065                          parms: EncodeParams,
2066                          krate: &ast::Crate) {
2067     struct Stats {
2068         attr_bytes: u64,
2069         dep_bytes: u64,
2070         lang_item_bytes: u64,
2071         native_lib_bytes: u64,
2072         plugin_registrar_fn_bytes: u64,
2073         macro_defs_bytes: u64,
2074         unboxed_closure_bytes: u64,
2075         impl_bytes: u64,
2076         misc_bytes: u64,
2077         item_bytes: u64,
2078         index_bytes: u64,
2079         zero_bytes: u64,
2080         total_bytes: u64,
2081     }
2082     let mut stats = Stats {
2083         attr_bytes: 0,
2084         dep_bytes: 0,
2085         lang_item_bytes: 0,
2086         native_lib_bytes: 0,
2087         plugin_registrar_fn_bytes: 0,
2088         macro_defs_bytes: 0,
2089         unboxed_closure_bytes: 0,
2090         impl_bytes: 0,
2091         misc_bytes: 0,
2092         item_bytes: 0,
2093         index_bytes: 0,
2094         zero_bytes: 0,
2095         total_bytes: 0,
2096     };
2097     let EncodeParams {
2098         item_symbols,
2099         diag,
2100         tcx,
2101         reexports,
2102         cstore,
2103         encode_inlined_item,
2104         link_meta,
2105         reachable,
2106         ..
2107     } = parms;
2108     let ecx = EncodeContext {
2109         diag: diag,
2110         tcx: tcx,
2111         reexports: reexports,
2112         item_symbols: item_symbols,
2113         link_meta: link_meta,
2114         cstore: cstore,
2115         encode_inlined_item: RefCell::new(encode_inlined_item),
2116         type_abbrevs: RefCell::new(FnvHashMap::new()),
2117         reachable: reachable,
2118      };
2119
2120     let mut rbml_w = writer::Encoder::new(wr);
2121
2122     encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name[]);
2123     encode_crate_triple(&mut rbml_w,
2124                         tcx.sess
2125                            .opts
2126                            .target_triple
2127                            []);
2128     encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2129     encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2130
2131     let mut i = rbml_w.writer.tell().unwrap();
2132     encode_attributes(&mut rbml_w, krate.attrs[]);
2133     stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
2134
2135     i = rbml_w.writer.tell().unwrap();
2136     encode_crate_deps(&mut rbml_w, ecx.cstore);
2137     stats.dep_bytes = rbml_w.writer.tell().unwrap() - i;
2138
2139     // Encode the language items.
2140     i = rbml_w.writer.tell().unwrap();
2141     encode_lang_items(&ecx, &mut rbml_w);
2142     stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i;
2143
2144     // Encode the native libraries used
2145     i = rbml_w.writer.tell().unwrap();
2146     encode_native_libraries(&ecx, &mut rbml_w);
2147     stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i;
2148
2149     // Encode the plugin registrar function
2150     i = rbml_w.writer.tell().unwrap();
2151     encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2152     stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
2153
2154     // Encode macro definitions
2155     i = rbml_w.writer.tell().unwrap();
2156     encode_macro_defs(&ecx, krate, &mut rbml_w);
2157     stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
2158
2159     // Encode the types of all unboxed closures in this crate.
2160     i = rbml_w.writer.tell().unwrap();
2161     encode_unboxed_closures(&ecx, &mut rbml_w);
2162     stats.unboxed_closure_bytes = rbml_w.writer.tell().unwrap() - i;
2163
2164     // Encode the def IDs of impls, for coherence checking.
2165     i = rbml_w.writer.tell().unwrap();
2166     encode_impls(&ecx, krate, &mut rbml_w);
2167     stats.impl_bytes = rbml_w.writer.tell().unwrap() - i;
2168
2169     // Encode miscellaneous info.
2170     i = rbml_w.writer.tell().unwrap();
2171     encode_misc_info(&ecx, krate, &mut rbml_w);
2172     encode_reachable_extern_fns(&ecx, &mut rbml_w);
2173     stats.misc_bytes = rbml_w.writer.tell().unwrap() - i;
2174
2175     // Encode and index the items.
2176     rbml_w.start_tag(tag_items);
2177     i = rbml_w.writer.tell().unwrap();
2178     let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2179     stats.item_bytes = rbml_w.writer.tell().unwrap() - i;
2180
2181     i = rbml_w.writer.tell().unwrap();
2182     encode_index(&mut rbml_w, items_index, write_i64);
2183     stats.index_bytes = rbml_w.writer.tell().unwrap() - i;
2184     rbml_w.end_tag();
2185
2186     encode_struct_field_attrs(&mut rbml_w, krate);
2187
2188     stats.total_bytes = rbml_w.writer.tell().unwrap();
2189
2190     if tcx.sess.meta_stats() {
2191         for e in rbml_w.writer.get_ref().iter() {
2192             if *e == 0 {
2193                 stats.zero_bytes += 1;
2194             }
2195         }
2196
2197         println!("metadata stats:");
2198         println!("       attribute bytes: {}", stats.attr_bytes);
2199         println!("             dep bytes: {}", stats.dep_bytes);
2200         println!("       lang item bytes: {}", stats.lang_item_bytes);
2201         println!("          native bytes: {}", stats.native_lib_bytes);
2202         println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2203         println!("       macro def bytes: {}", stats.macro_defs_bytes);
2204         println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
2205         println!("            impl bytes: {}", stats.impl_bytes);
2206         println!("            misc bytes: {}", stats.misc_bytes);
2207         println!("            item bytes: {}", stats.item_bytes);
2208         println!("           index bytes: {}", stats.index_bytes);
2209         println!("            zero bytes: {}", stats.zero_bytes);
2210         println!("           total bytes: {}", stats.total_bytes);
2211     }
2212 }
2213
2214 // Get the encoded string for a type
2215 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2216     let mut wr = SeekableMemWriter::new();
2217     tyencode::enc_ty(&mut wr, &tyencode::ctxt {
2218         diag: tcx.sess.diagnostic(),
2219         ds: def_to_string,
2220         tcx: tcx,
2221         abbrevs: &RefCell::new(FnvHashMap::new())
2222     }, t);
2223     String::from_utf8(wr.unwrap()).unwrap()
2224 }