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