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