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