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