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