]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
auto merge of #15726 : aturon/rust/macro-stability, r=alexcrichton
[rust.git] / src / librustc / metadata / encoder.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Metadata encoding
12
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
15
16 use back::svh::Svh;
17 use driver::config;
18 use metadata::common::*;
19 use metadata::cstore;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use middle::subst::VecPerParamSpace;
23 use middle::ty::{node_id_to_type, lookup_item_type};
24 use middle::astencode;
25 use middle::ty;
26 use middle::typeck;
27 use middle::stability;
28 use middle;
29 use util::nodemap::{NodeMap, NodeSet};
30
31 use serialize::Encodable;
32 use std::cell::RefCell;
33 use std::gc::Gc;
34 use std::hash::Hash;
35 use std::hash;
36 use std::io::MemWriter;
37 use std::mem;
38 use std::collections::HashMap;
39 use syntax::abi;
40 use syntax::ast::*;
41 use syntax::ast;
42 use syntax::ast_map::{PathElem, PathElems};
43 use syntax::ast_map;
44 use syntax::ast_util::*;
45 use syntax::ast_util;
46 use syntax::ast_util::PostExpansionMethod;
47 use syntax::attr;
48 use syntax::attr::AttrMetaMethods;
49 use syntax::diagnostic::SpanHandler;
50 use syntax::parse::token::special_idents;
51 use syntax::parse::token;
52 use syntax::visit::Visitor;
53 use syntax::visit;
54 use syntax;
55 use writer = serialize::ebml::writer;
56
57 /// A borrowed version of ast::InlinedItem.
58 pub enum InlinedItemRef<'a> {
59     IIItemRef(&'a ast::Item),
60     IIMethodRef(ast::DefId, bool, &'a ast::Method),
61     IIForeignRef(&'a ast::ForeignItem)
62 }
63
64 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
65
66 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
67                                   ebml_w: &mut Encoder,
68                                   ii: InlinedItemRef|: 'a;
69
70 pub struct EncodeParams<'a> {
71     pub diag: &'a SpanHandler,
72     pub tcx: &'a ty::ctxt,
73     pub reexports2: &'a middle::resolve::ExportMap2,
74     pub item_symbols: &'a RefCell<NodeMap<String>>,
75     pub non_inlineable_statics: &'a RefCell<NodeSet>,
76     pub link_meta: &'a LinkMeta,
77     pub cstore: &'a cstore::CStore,
78     pub encode_inlined_item: EncodeInlinedItem<'a>,
79     pub reachable: &'a NodeSet,
80 }
81
82 pub struct EncodeContext<'a> {
83     pub diag: &'a SpanHandler,
84     pub tcx: &'a ty::ctxt,
85     pub reexports2: &'a middle::resolve::ExportMap2,
86     pub item_symbols: &'a RefCell<NodeMap<String>>,
87     pub non_inlineable_statics: &'a RefCell<NodeSet>,
88     pub link_meta: &'a LinkMeta,
89     pub cstore: &'a cstore::CStore,
90     pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
91     pub type_abbrevs: tyencode::abbrev_map,
92     pub reachable: &'a NodeSet,
93 }
94
95 fn encode_name(ebml_w: &mut Encoder, name: Name) {
96     ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
97 }
98
99 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
100     ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
101 }
102
103 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
104     ebml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice());
105 }
106
107 #[deriving(Clone)]
108 struct entry<T> {
109     val: T,
110     pos: u64
111 }
112
113 fn encode_trait_ref(ebml_w: &mut Encoder,
114                     ecx: &EncodeContext,
115                     trait_ref: &ty::TraitRef,
116                     tag: uint) {
117     let ty_str_ctxt = &tyencode::ctxt {
118         diag: ecx.diag,
119         ds: def_to_string,
120         tcx: ecx.tcx,
121         abbrevs: &ecx.type_abbrevs
122     };
123
124     ebml_w.start_tag(tag);
125     tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
126     ebml_w.end_tag();
127 }
128
129 fn encode_impl_vtables(ebml_w: &mut Encoder,
130                        ecx: &EncodeContext,
131                        vtables: &typeck::vtable_res) {
132     ebml_w.start_tag(tag_item_impl_vtables);
133     astencode::encode_vtable_res(ecx, ebml_w, vtables);
134     ebml_w.end_tag();
135 }
136
137 // Item info table encoding
138 fn encode_family(ebml_w: &mut Encoder, c: char) {
139     ebml_w.start_tag(tag_items_data_item_family);
140     ebml_w.writer.write(&[c as u8]);
141     ebml_w.end_tag();
142 }
143
144 pub fn def_to_string(did: DefId) -> String {
145     format!("{}:{}", did.krate, did.node)
146 }
147
148 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
149                              ecx: &EncodeContext,
150                              params: &VecPerParamSpace<ty::TypeParameterDef>,
151                              tag: uint) {
152     let ty_str_ctxt = &tyencode::ctxt {
153         diag: ecx.diag,
154         ds: def_to_string,
155         tcx: ecx.tcx,
156         abbrevs: &ecx.type_abbrevs
157     };
158     for param in params.iter() {
159         ebml_w.start_tag(tag);
160         tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
161         ebml_w.end_tag();
162     }
163 }
164
165 fn encode_region_param_defs(ebml_w: &mut Encoder,
166                             params: &VecPerParamSpace<ty::RegionParameterDef>) {
167     for param in params.iter() {
168         ebml_w.start_tag(tag_region_param_def);
169
170         ebml_w.start_tag(tag_region_param_def_ident);
171         encode_name(ebml_w, param.name);
172         ebml_w.end_tag();
173
174         ebml_w.wr_tagged_str(tag_region_param_def_def_id,
175                              def_to_string(param.def_id).as_slice());
176
177         ebml_w.wr_tagged_u64(tag_region_param_def_space,
178                              param.space.to_uint() as u64);
179
180         ebml_w.wr_tagged_u64(tag_region_param_def_index,
181                              param.index as u64);
182
183         ebml_w.end_tag();
184     }
185 }
186
187 fn encode_item_variances(ebml_w: &mut Encoder,
188                          ecx: &EncodeContext,
189                          id: ast::NodeId) {
190     let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
191     ebml_w.start_tag(tag_item_variances);
192     v.encode(ebml_w);
193     ebml_w.end_tag();
194 }
195
196 fn encode_bounds_and_type(ebml_w: &mut Encoder,
197                           ecx: &EncodeContext,
198                           pty: &ty::Polytype) {
199     encode_ty_type_param_defs(ebml_w, ecx, &pty.generics.types,
200                               tag_items_data_item_ty_param_bounds);
201     encode_region_param_defs(ebml_w, &pty.generics.regions);
202     encode_type(ecx, ebml_w, pty.ty);
203 }
204
205 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
206     ebml_w.start_tag(tag_items_data_item_variant);
207     let s = def_to_string(vid);
208     ebml_w.writer.write(s.as_bytes());
209     ebml_w.end_tag();
210 }
211
212 pub fn write_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 == ty::StaticExplicitSelfCategory {
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 == ty::StaticExplicitSelfCategory {
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(ch.to_string().as_slice());
623     ebml_w.end_tag();
624 }
625
626 fn encode_explicit_self(ebml_w: &mut Encoder,
627                         explicit_self: &ty::ExplicitSelfCategory) {
628     ebml_w.start_tag(tag_item_trait_method_explicit_self);
629
630     // Encode the base self type.
631     match *explicit_self {
632         ty::StaticExplicitSelfCategory => {
633             ebml_w.writer.write(&[ 's' as u8 ]);
634         }
635         ty::ByValueExplicitSelfCategory => {
636             ebml_w.writer.write(&[ 'v' as u8 ]);
637         }
638         ty::ByBoxExplicitSelfCategory => {
639             ebml_w.writer.write(&[ '~' as u8 ]);
640         }
641         ty::ByReferenceExplicitSelfCategory(_, m) => {
642             // FIXME(#4846) encode custom lifetime
643             ebml_w.writer.write(&['&' as u8]);
644             encode_mutability(ebml_w, m);
645         }
646     }
647
648     ebml_w.end_tag();
649
650     fn encode_mutability(ebml_w: &mut Encoder,
651                          m: ast::Mutability) {
652         match m {
653             MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
654             MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
655         }
656     }
657 }
658
659 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
660     ebml_w.start_tag(tag_item_trait_method_sort);
661     ebml_w.writer.write(&[ sort as u8 ]);
662     ebml_w.end_tag();
663 }
664
665 fn encode_provided_source(ebml_w: &mut Encoder,
666                           source_opt: Option<DefId>) {
667     for source in source_opt.iter() {
668         ebml_w.start_tag(tag_item_method_provided_source);
669         let s = def_to_string(*source);
670         ebml_w.writer.write(s.as_bytes());
671         ebml_w.end_tag();
672     }
673 }
674
675 /* Returns an index of items in this class */
676 fn encode_info_for_struct(ecx: &EncodeContext,
677                           ebml_w: &mut Encoder,
678                           fields: &[ty::field_ty],
679                           global_index: &mut Vec<entry<i64>>)
680                           -> Vec<entry<i64>> {
681     /* Each class has its own index, since different classes
682        may have fields with the same name */
683     let mut index = Vec::new();
684     let tcx = ecx.tcx;
685      /* We encode both private and public fields -- need to include
686         private fields to get the offsets right */
687     for field in fields.iter() {
688         let nm = field.name;
689         let id = field.id.node;
690
691         index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
692         global_index.push(entry {
693             val: id as i64,
694             pos: ebml_w.writer.tell().unwrap(),
695         });
696         ebml_w.start_tag(tag_items_data_item);
697         debug!("encode_info_for_struct: doing {} {}",
698                token::get_name(nm), id);
699         encode_struct_field_family(ebml_w, field.vis);
700         encode_name(ebml_w, nm);
701         encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
702         encode_def_id(ebml_w, local_def(id));
703
704         let stab = stability::lookup(ecx.tcx, field.id);
705         encode_stability(ebml_w, stab);
706
707         ebml_w.end_tag();
708     }
709     index
710 }
711
712 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
713                                ebml_w: &mut Encoder,
714                                name: ast::Ident,
715                                ctor_id: NodeId,
716                                index: &mut Vec<entry<i64>>,
717                                struct_id: NodeId) {
718     index.push(entry {
719         val: ctor_id as i64,
720         pos: ebml_w.writer.tell().unwrap(),
721     });
722
723     ebml_w.start_tag(tag_items_data_item);
724     encode_def_id(ebml_w, local_def(ctor_id));
725     encode_family(ebml_w, 'f');
726     encode_bounds_and_type(ebml_w, ecx,
727                            &lookup_item_type(ecx.tcx, local_def(ctor_id)));
728     encode_name(ebml_w, name.name);
729     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
730     ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
731     encode_parent_item(ebml_w, local_def(struct_id));
732
733     if ecx.item_symbols.borrow().contains_key(&ctor_id) {
734         encode_symbol(ecx, ebml_w, ctor_id);
735     }
736
737     let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
738     encode_stability(ebml_w, stab);
739
740     // indicate that this is a tuple struct ctor, because downstream users will normally want
741     // the tuple struct definition, but without this there is no way for them to tell that
742     // they actually have a ctor rather than a normal function
743     ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
744     ebml_w.end_tag();
745
746     ebml_w.end_tag();
747 }
748
749 fn encode_method_ty_fields(ecx: &EncodeContext,
750                            ebml_w: &mut Encoder,
751                            method_ty: &ty::Method) {
752     encode_def_id(ebml_w, method_ty.def_id);
753     encode_name(ebml_w, method_ty.ident.name);
754     encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
755                               tag_item_method_tps);
756     encode_method_fty(ecx, ebml_w, &method_ty.fty);
757     encode_visibility(ebml_w, method_ty.vis);
758     encode_explicit_self(ebml_w, &method_ty.explicit_self);
759     let fn_style = method_ty.fty.fn_style;
760     match method_ty.explicit_self {
761         ty::StaticExplicitSelfCategory => {
762             encode_family(ebml_w, fn_style_static_method_family(fn_style));
763         }
764         _ => encode_family(ebml_w, style_fn_family(fn_style))
765     }
766     encode_provided_source(ebml_w, method_ty.provided_source);
767 }
768
769 fn encode_info_for_method(ecx: &EncodeContext,
770                           ebml_w: &mut Encoder,
771                           m: &ty::Method,
772                           impl_path: PathElems,
773                           is_default_impl: bool,
774                           parent_id: NodeId,
775                           ast_method_opt: Option<Gc<Method>>) {
776
777     debug!("encode_info_for_method: {:?} {}", m.def_id,
778            token::get_ident(m.ident));
779     ebml_w.start_tag(tag_items_data_item);
780
781     encode_method_ty_fields(ecx, ebml_w, m);
782     encode_parent_item(ebml_w, local_def(parent_id));
783
784     let stab = stability::lookup(ecx.tcx, m.def_id);
785     encode_stability(ebml_w, stab);
786
787     // The type for methods gets encoded twice, which is unfortunate.
788     let pty = lookup_item_type(ecx.tcx, m.def_id);
789     encode_bounds_and_type(ebml_w, ecx, &pty);
790
791     let elem = ast_map::PathName(m.ident.name);
792     encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
793     match ast_method_opt {
794         Some(ast_method) => {
795             encode_attributes(ebml_w, ast_method.attrs.as_slice())
796         }
797         None => ()
798     }
799
800     for &ast_method in ast_method_opt.iter() {
801         let any_types = !pty.generics.types.is_empty();
802         if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
803             encode_inlined_item(ecx, ebml_w,
804                                 IIMethodRef(local_def(parent_id), false,
805                                             &*ast_method));
806         } else {
807             encode_symbol(ecx, ebml_w, m.def_id.node);
808         }
809         encode_method_argument_names(ebml_w, &*ast_method.pe_fn_decl());
810     }
811
812     ebml_w.end_tag();
813 }
814
815 fn encode_method_argument_names(ebml_w: &mut Encoder,
816                                 decl: &ast::FnDecl) {
817     ebml_w.start_tag(tag_method_argument_names);
818     for arg in decl.inputs.iter() {
819         ebml_w.start_tag(tag_method_argument_name);
820         match arg.pat.node {
821             ast::PatIdent(_, ref path1, _) => {
822                 let name = token::get_ident(path1.node);
823                 ebml_w.writer.write(name.get().as_bytes());
824             }
825             _ => {}
826         }
827         ebml_w.end_tag();
828     }
829     ebml_w.end_tag();
830 }
831
832 fn encode_inlined_item(ecx: &EncodeContext,
833                        ebml_w: &mut Encoder,
834                        ii: InlinedItemRef) {
835     let mut eii = ecx.encode_inlined_item.borrow_mut();
836     let eii: &mut EncodeInlinedItem = &mut *eii;
837     (*eii)(ecx, ebml_w, ii)
838 }
839
840 fn style_fn_family(s: FnStyle) -> char {
841     match s {
842         UnsafeFn => 'u',
843         NormalFn => 'f',
844     }
845 }
846
847 fn fn_style_static_method_family(s: FnStyle) -> char {
848     match s {
849         UnsafeFn => 'U',
850         NormalFn => 'F',
851     }
852 }
853
854
855 fn should_inline(attrs: &[Attribute]) -> bool {
856     use syntax::attr::*;
857     match find_inline_attr(attrs) {
858         InlineNone | InlineNever  => false,
859         InlineHint | InlineAlways => true
860     }
861 }
862
863 // Encodes the inherent implementations of a structure, enumeration, or trait.
864 fn encode_inherent_implementations(ecx: &EncodeContext,
865                                    ebml_w: &mut Encoder,
866                                    def_id: DefId) {
867     match ecx.tcx.inherent_impls.borrow().find(&def_id) {
868         None => {}
869         Some(implementations) => {
870             for &impl_def_id in implementations.borrow().iter() {
871                 ebml_w.start_tag(tag_items_data_item_inherent_impl);
872                 encode_def_id(ebml_w, impl_def_id);
873                 ebml_w.end_tag();
874             }
875         }
876     }
877 }
878
879 // Encodes the implementations of a trait defined in this crate.
880 fn encode_extension_implementations(ecx: &EncodeContext,
881                                     ebml_w: &mut Encoder,
882                                     trait_def_id: DefId) {
883     match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
884         None => {}
885         Some(implementations) => {
886             for &impl_def_id in implementations.borrow().iter() {
887                 ebml_w.start_tag(tag_items_data_item_extension_impl);
888                 encode_def_id(ebml_w, impl_def_id);
889                 ebml_w.end_tag();
890             }
891         }
892     }
893 }
894
895 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
896     stab_opt.map(|stab| {
897         ebml_w.start_tag(tag_items_data_item_stability);
898         stab.encode(ebml_w).unwrap();
899         ebml_w.end_tag();
900     });
901 }
902
903 fn encode_info_for_item(ecx: &EncodeContext,
904                         ebml_w: &mut Encoder,
905                         item: &Item,
906                         index: &mut Vec<entry<i64>>,
907                         path: PathElems,
908                         vis: ast::Visibility) {
909     let tcx = ecx.tcx;
910
911     fn add_to_index(item: &Item, ebml_w: &Encoder,
912                     index: &mut Vec<entry<i64>>) {
913         index.push(entry {
914             val: item.id as i64,
915             pos: ebml_w.writer.tell().unwrap(),
916         });
917     }
918
919     debug!("encoding info for item at {}",
920            tcx.sess.codemap().span_to_string(item.span));
921
922     let def_id = local_def(item.id);
923     let stab = stability::lookup(tcx, ast_util::local_def(item.id));
924
925     match item.node {
926       ItemStatic(_, m, _) => {
927         add_to_index(item, ebml_w, index);
928         ebml_w.start_tag(tag_items_data_item);
929         encode_def_id(ebml_w, def_id);
930         if m == ast::MutMutable {
931             encode_family(ebml_w, 'b');
932         } else {
933             encode_family(ebml_w, 'c');
934         }
935         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
936         encode_symbol(ecx, ebml_w, item.id);
937         encode_name(ebml_w, item.ident.name);
938         encode_path(ebml_w, path);
939
940         let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
941
942         if inlineable {
943             encode_inlined_item(ecx, ebml_w, IIItemRef(item));
944         }
945         encode_visibility(ebml_w, vis);
946         encode_stability(ebml_w, stab);
947         ebml_w.end_tag();
948       }
949       ItemFn(ref decl, fn_style, _, ref generics, _) => {
950         add_to_index(item, ebml_w, index);
951         ebml_w.start_tag(tag_items_data_item);
952         encode_def_id(ebml_w, def_id);
953         encode_family(ebml_w, style_fn_family(fn_style));
954         let tps_len = generics.ty_params.len();
955         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
956         encode_name(ebml_w, item.ident.name);
957         encode_path(ebml_w, path);
958         encode_attributes(ebml_w, item.attrs.as_slice());
959         if tps_len > 0u || should_inline(item.attrs.as_slice()) {
960             encode_inlined_item(ecx, ebml_w, IIItemRef(item));
961         } else {
962             encode_symbol(ecx, ebml_w, item.id);
963         }
964         encode_visibility(ebml_w, vis);
965         encode_stability(ebml_w, stab);
966         encode_method_argument_names(ebml_w, &**decl);
967         ebml_w.end_tag();
968       }
969       ItemMod(ref m) => {
970         add_to_index(item, ebml_w, index);
971         encode_info_for_mod(ecx,
972                             ebml_w,
973                             m,
974                             item.attrs.as_slice(),
975                             item.id,
976                             path,
977                             item.ident,
978                             item.vis);
979       }
980       ItemForeignMod(ref fm) => {
981         add_to_index(item, ebml_w, index);
982         ebml_w.start_tag(tag_items_data_item);
983         encode_def_id(ebml_w, def_id);
984         encode_family(ebml_w, 'n');
985         encode_name(ebml_w, item.ident.name);
986         encode_path(ebml_w, path);
987
988         // Encode all the items in this module.
989         for foreign_item in fm.items.iter() {
990             ebml_w.start_tag(tag_mod_child);
991             ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
992             ebml_w.end_tag();
993         }
994         encode_visibility(ebml_w, vis);
995         encode_stability(ebml_w, stab);
996         ebml_w.end_tag();
997       }
998       ItemTy(..) => {
999         add_to_index(item, ebml_w, index);
1000         ebml_w.start_tag(tag_items_data_item);
1001         encode_def_id(ebml_w, def_id);
1002         encode_family(ebml_w, 'y');
1003         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1004         encode_name(ebml_w, item.ident.name);
1005         encode_path(ebml_w, path);
1006         encode_visibility(ebml_w, vis);
1007         encode_stability(ebml_w, stab);
1008         ebml_w.end_tag();
1009       }
1010       ItemEnum(ref enum_definition, ref generics) => {
1011         add_to_index(item, ebml_w, index);
1012
1013         ebml_w.start_tag(tag_items_data_item);
1014         encode_def_id(ebml_w, def_id);
1015         encode_family(ebml_w, 't');
1016         encode_item_variances(ebml_w, ecx, item.id);
1017         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1018         encode_name(ebml_w, item.ident.name);
1019         encode_attributes(ebml_w, item.attrs.as_slice());
1020         for v in (*enum_definition).variants.iter() {
1021             encode_variant_id(ebml_w, local_def(v.node.id));
1022         }
1023         encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1024         encode_path(ebml_w, path);
1025
1026         // Encode inherent implementations for this enumeration.
1027         encode_inherent_implementations(ecx, ebml_w, def_id);
1028
1029         encode_visibility(ebml_w, vis);
1030         encode_stability(ebml_w, stab);
1031         ebml_w.end_tag();
1032
1033         encode_enum_variant_info(ecx,
1034                                  ebml_w,
1035                                  item.id,
1036                                  (*enum_definition).variants.as_slice(),
1037                                  index,
1038                                  generics);
1039       }
1040       ItemStruct(struct_def, _) => {
1041         let fields = ty::lookup_struct_fields(tcx, def_id);
1042
1043         /* First, encode the fields
1044            These come first because we need to write them to make
1045            the index, and the index needs to be in the item for the
1046            class itself */
1047         let idx = encode_info_for_struct(ecx,
1048                                          ebml_w,
1049                                          fields.as_slice(),
1050                                          index);
1051
1052         /* Index the class*/
1053         add_to_index(item, ebml_w, index);
1054
1055         /* Now, make an item for the class itself */
1056         ebml_w.start_tag(tag_items_data_item);
1057         encode_def_id(ebml_w, def_id);
1058         encode_family(ebml_w, 'S');
1059         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1060
1061         encode_item_variances(ebml_w, ecx, item.id);
1062         encode_name(ebml_w, item.ident.name);
1063         encode_attributes(ebml_w, item.attrs.as_slice());
1064         encode_path(ebml_w, path.clone());
1065         encode_stability(ebml_w, stab);
1066         encode_visibility(ebml_w, vis);
1067
1068         /* Encode def_ids for each field and method
1069          for methods, write all the stuff get_trait_method
1070         needs to know*/
1071         encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1072
1073         encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1074
1075         // Encode inherent implementations for this structure.
1076         encode_inherent_implementations(ecx, ebml_w, def_id);
1077
1078         /* Each class has its own index -- encode it */
1079         encode_index(ebml_w, idx, write_i64);
1080         ebml_w.end_tag();
1081
1082         // If this is a tuple-like struct, encode the type of the constructor.
1083         match struct_def.ctor_id {
1084             Some(ctor_id) => {
1085                 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1086                                             ctor_id, index, def_id.node);
1087             }
1088             None => {}
1089         }
1090       }
1091       ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1092         // We need to encode information about the default methods we
1093         // have inherited, so we drive this based on the impl structure.
1094         let impl_methods = tcx.impl_methods.borrow();
1095         let methods = impl_methods.get(&def_id);
1096
1097         add_to_index(item, ebml_w, index);
1098         ebml_w.start_tag(tag_items_data_item);
1099         encode_def_id(ebml_w, def_id);
1100         encode_family(ebml_w, 'i');
1101         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1102         encode_name(ebml_w, item.ident.name);
1103         encode_attributes(ebml_w, item.attrs.as_slice());
1104         match ty.node {
1105             ast::TyPath(ref path, ref bounds, _) if path.segments
1106                                                         .len() == 1 => {
1107                 let ident = path.segments.last().unwrap().identifier;
1108                 assert!(bounds.is_none());
1109                 encode_impl_type_basename(ebml_w, ident);
1110             }
1111             _ => {}
1112         }
1113         for &method_def_id in methods.iter() {
1114             ebml_w.start_tag(tag_item_impl_method);
1115             let s = def_to_string(method_def_id);
1116             ebml_w.writer.write(s.as_bytes());
1117             ebml_w.end_tag();
1118         }
1119         for ast_trait_ref in opt_trait.iter() {
1120             let trait_ref = ty::node_id_to_trait_ref(
1121                 tcx, ast_trait_ref.ref_id);
1122             encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1123             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1124             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1125         }
1126         encode_path(ebml_w, path.clone());
1127         encode_stability(ebml_w, stab);
1128         ebml_w.end_tag();
1129
1130         // Iterate down the methods, emitting them. We rely on the
1131         // assumption that all of the actually implemented methods
1132         // appear first in the impl structure, in the same order they do
1133         // in the ast. This is a little sketchy.
1134         let num_implemented_methods = ast_methods.len();
1135         for (i, &method_def_id) in methods.iter().enumerate() {
1136             let ast_method = if i < num_implemented_methods {
1137                 Some(*ast_methods.get(i))
1138             } else { None };
1139
1140             index.push(entry {
1141                 val: method_def_id.node as i64,
1142                 pos: ebml_w.writer.tell().unwrap(),
1143             });
1144             encode_info_for_method(ecx,
1145                                    ebml_w,
1146                                    &*ty::method(tcx, method_def_id),
1147                                    path.clone(),
1148                                    false,
1149                                    item.id,
1150                                    ast_method)
1151         }
1152       }
1153       ItemTrait(_, _, ref super_traits, ref ms) => {
1154         add_to_index(item, ebml_w, index);
1155         ebml_w.start_tag(tag_items_data_item);
1156         encode_def_id(ebml_w, def_id);
1157         encode_family(ebml_w, 'I');
1158         encode_item_variances(ebml_w, ecx, item.id);
1159         let trait_def = ty::lookup_trait_def(tcx, def_id);
1160         encode_ty_type_param_defs(ebml_w, ecx,
1161                                   &trait_def.generics.types,
1162                                   tag_items_data_item_ty_param_bounds);
1163         encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1164         encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1165         encode_name(ebml_w, item.ident.name);
1166         encode_attributes(ebml_w, item.attrs.as_slice());
1167         encode_visibility(ebml_w, vis);
1168         encode_stability(ebml_w, stab);
1169         for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1170             ebml_w.start_tag(tag_item_trait_method);
1171             encode_def_id(ebml_w, method_def_id);
1172             ebml_w.end_tag();
1173
1174             ebml_w.start_tag(tag_mod_child);
1175             ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1176             ebml_w.end_tag();
1177         }
1178         encode_path(ebml_w, path.clone());
1179         // FIXME(#8559): This should use the tcx's supertrait cache instead of
1180         // reading the AST's list, because the former has already filtered out
1181         // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1182         for ast_trait_ref in super_traits.iter() {
1183             let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1184             encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1185         }
1186
1187         // Encode the implementations of this trait.
1188         encode_extension_implementations(ecx, ebml_w, def_id);
1189
1190         ebml_w.end_tag();
1191
1192         // Now output the method info for each method.
1193         let r = ty::trait_method_def_ids(tcx, def_id);
1194         for (i, &method_def_id) in r.iter().enumerate() {
1195             assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1196
1197             let method_ty = ty::method(tcx, method_def_id);
1198
1199             index.push(entry {
1200                 val: method_def_id.node as i64,
1201                 pos: ebml_w.writer.tell().unwrap(),
1202             });
1203
1204             ebml_w.start_tag(tag_items_data_item);
1205
1206             encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1207             encode_parent_item(ebml_w, def_id);
1208
1209             let stab = stability::lookup(tcx, method_def_id);
1210             encode_stability(ebml_w, stab);
1211
1212             let elem = ast_map::PathName(method_ty.ident.name);
1213             encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1214
1215             match method_ty.explicit_self {
1216                 ty::StaticExplicitSelfCategory => {
1217                     encode_family(ebml_w,
1218                                   fn_style_static_method_family(
1219                                       method_ty.fty.fn_style));
1220
1221                     let pty = ty::lookup_item_type(tcx, method_def_id);
1222                     encode_bounds_and_type(ebml_w, ecx, &pty);
1223                 }
1224
1225                 _ => {
1226                     encode_family(ebml_w,
1227                                   style_fn_family(
1228                                       method_ty.fty.fn_style));
1229                 }
1230             }
1231
1232             match ms.get(i) {
1233                 &Required(ref tm) => {
1234                     encode_attributes(ebml_w, tm.attrs.as_slice());
1235                     encode_method_sort(ebml_w, 'r');
1236                     encode_method_argument_names(ebml_w, &*tm.decl);
1237                 }
1238
1239                 &Provided(m) => {
1240                     encode_attributes(ebml_w, m.attrs.as_slice());
1241                     // If this is a static method, we've already encoded
1242                     // this.
1243                     if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
1244                         // FIXME: I feel like there is something funny going on.
1245                         let pty = ty::lookup_item_type(tcx, method_def_id);
1246                         encode_bounds_and_type(ebml_w, ecx, &pty);
1247                     }
1248                     encode_method_sort(ebml_w, 'p');
1249                     encode_inlined_item(ecx, ebml_w,
1250                                         IIMethodRef(def_id, true, &*m));
1251                     encode_method_argument_names(ebml_w, &*m.pe_fn_decl());
1252                 }
1253             }
1254
1255             ebml_w.end_tag();
1256         }
1257
1258         // Encode inherent implementations for this trait.
1259         encode_inherent_implementations(ecx, ebml_w, def_id);
1260       }
1261       ItemMac(..) => {
1262         // macros are encoded separately
1263       }
1264     }
1265 }
1266
1267 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1268                                 ebml_w: &mut Encoder,
1269                                 nitem: &ForeignItem,
1270                                 index: &mut Vec<entry<i64>>,
1271                                 path: PathElems,
1272                                 abi: abi::Abi) {
1273     index.push(entry {
1274         val: nitem.id as i64,
1275         pos: ebml_w.writer.tell().unwrap(),
1276     });
1277
1278     ebml_w.start_tag(tag_items_data_item);
1279     encode_def_id(ebml_w, local_def(nitem.id));
1280     match nitem.node {
1281       ForeignItemFn(..) => {
1282         encode_family(ebml_w, style_fn_family(NormalFn));
1283         encode_bounds_and_type(ebml_w, ecx,
1284                                &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1285         encode_name(ebml_w, nitem.ident.name);
1286         if abi == abi::RustIntrinsic {
1287             encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1288         } else {
1289             encode_symbol(ecx, ebml_w, nitem.id);
1290         }
1291       }
1292       ForeignItemStatic(_, mutbl) => {
1293         if mutbl {
1294             encode_family(ebml_w, 'b');
1295         } else {
1296             encode_family(ebml_w, 'c');
1297         }
1298         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1299         encode_symbol(ecx, ebml_w, nitem.id);
1300         encode_name(ebml_w, nitem.ident.name);
1301       }
1302     }
1303     encode_path(ebml_w, path);
1304     ebml_w.end_tag();
1305 }
1306
1307 fn my_visit_expr(_e: &Expr) { }
1308
1309 fn my_visit_item(i: &Item,
1310                  ebml_w: &mut Encoder,
1311                  ecx_ptr: *const int,
1312                  index: &mut Vec<entry<i64>>) {
1313     let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1314     // See above
1315     let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1316     ecx.tcx.map.with_path(i.id, |path| {
1317         encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1318     });
1319 }
1320
1321 fn my_visit_foreign_item(ni: &ForeignItem,
1322                          ebml_w: &mut Encoder,
1323                          ecx_ptr:*const int,
1324                          index: &mut Vec<entry<i64>>) {
1325     // See above
1326     let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1327     debug!("writing foreign item {}::{}",
1328             ecx.tcx.map.path_to_string(ni.id),
1329             token::get_ident(ni.ident));
1330
1331     let mut ebml_w = unsafe {
1332         ebml_w.unsafe_clone()
1333     };
1334     let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1335     ecx.tcx.map.with_path(ni.id, |path| {
1336         encode_info_for_foreign_item(ecx, &mut ebml_w,
1337                                      ni, index,
1338                                      path, abi);
1339     });
1340 }
1341
1342 struct EncodeVisitor<'a,'b> {
1343     ebml_w_for_visit_item: &'a mut Encoder<'b>,
1344     ecx_ptr:*const int,
1345     index: &'a mut Vec<entry<i64>>,
1346 }
1347
1348 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1349     fn visit_expr(&mut self, ex: &Expr, _: ()) {
1350         visit::walk_expr(self, ex, ());
1351         my_visit_expr(ex);
1352     }
1353     fn visit_item(&mut self, i: &Item, _: ()) {
1354         visit::walk_item(self, i, ());
1355         my_visit_item(i,
1356                       self.ebml_w_for_visit_item,
1357                       self.ecx_ptr,
1358                       self.index);
1359     }
1360     fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1361         visit::walk_foreign_item(self, ni, ());
1362         my_visit_foreign_item(ni,
1363                               self.ebml_w_for_visit_item,
1364                               self.ecx_ptr,
1365                               self.index);
1366     }
1367 }
1368
1369 fn encode_info_for_items(ecx: &EncodeContext,
1370                          ebml_w: &mut Encoder,
1371                          krate: &Crate)
1372                          -> Vec<entry<i64>> {
1373     let mut index = Vec::new();
1374     ebml_w.start_tag(tag_items_data);
1375     index.push(entry {
1376         val: CRATE_NODE_ID as i64,
1377         pos: ebml_w.writer.tell().unwrap(),
1378     });
1379     encode_info_for_mod(ecx,
1380                         ebml_w,
1381                         &krate.module,
1382                         &[],
1383                         CRATE_NODE_ID,
1384                         ast_map::Values([].iter()).chain(None),
1385                         syntax::parse::token::special_idents::invalid,
1386                         Public);
1387
1388     // See comment in `encode_side_tables_for_ii` in astencode
1389     let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1390     visit::walk_crate(&mut EncodeVisitor {
1391         index: &mut index,
1392         ecx_ptr: ecx_ptr,
1393         ebml_w_for_visit_item: &mut *ebml_w,
1394     }, krate, ());
1395
1396     ebml_w.end_tag();
1397     index
1398 }
1399
1400
1401 // Path and definition ID indexing
1402
1403 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1404                          write_fn: |&mut MemWriter, &T|) {
1405     let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1406     for elt in index.move_iter() {
1407         let h = hash::hash(&elt.val) as uint;
1408         buckets.get_mut(h % 256).push(elt);
1409     }
1410
1411     ebml_w.start_tag(tag_index);
1412     let mut bucket_locs = Vec::new();
1413     ebml_w.start_tag(tag_index_buckets);
1414     for bucket in buckets.iter() {
1415         bucket_locs.push(ebml_w.writer.tell().unwrap());
1416         ebml_w.start_tag(tag_index_buckets_bucket);
1417         for elt in bucket.iter() {
1418             ebml_w.start_tag(tag_index_buckets_bucket_elt);
1419             assert!(elt.pos < 0xffff_ffff);
1420             {
1421                 let wr: &mut MemWriter = ebml_w.writer;
1422                 wr.write_be_u32(elt.pos as u32);
1423             }
1424             write_fn(ebml_w.writer, &elt.val);
1425             ebml_w.end_tag();
1426         }
1427         ebml_w.end_tag();
1428     }
1429     ebml_w.end_tag();
1430     ebml_w.start_tag(tag_index_table);
1431     for pos in bucket_locs.iter() {
1432         assert!(*pos < 0xffff_ffff);
1433         let wr: &mut MemWriter = ebml_w.writer;
1434         wr.write_be_u32(*pos as u32);
1435     }
1436     ebml_w.end_tag();
1437     ebml_w.end_tag();
1438 }
1439
1440 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1441     let wr: &mut MemWriter = writer;
1442     assert!(n < 0x7fff_ffff);
1443     wr.write_be_u32(n as u32);
1444 }
1445
1446 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1447     match mi.node {
1448       MetaWord(ref name) => {
1449         ebml_w.start_tag(tag_meta_item_word);
1450         ebml_w.start_tag(tag_meta_item_name);
1451         ebml_w.writer.write(name.get().as_bytes());
1452         ebml_w.end_tag();
1453         ebml_w.end_tag();
1454       }
1455       MetaNameValue(ref name, ref value) => {
1456         match value.node {
1457           LitStr(ref value, _) => {
1458             ebml_w.start_tag(tag_meta_item_name_value);
1459             ebml_w.start_tag(tag_meta_item_name);
1460             ebml_w.writer.write(name.get().as_bytes());
1461             ebml_w.end_tag();
1462             ebml_w.start_tag(tag_meta_item_value);
1463             ebml_w.writer.write(value.get().as_bytes());
1464             ebml_w.end_tag();
1465             ebml_w.end_tag();
1466           }
1467           _ => {/* FIXME (#623): encode other variants */ }
1468         }
1469       }
1470       MetaList(ref name, ref items) => {
1471         ebml_w.start_tag(tag_meta_item_list);
1472         ebml_w.start_tag(tag_meta_item_name);
1473         ebml_w.writer.write(name.get().as_bytes());
1474         ebml_w.end_tag();
1475         for inner_item in items.iter() {
1476             encode_meta_item(ebml_w, *inner_item);
1477         }
1478         ebml_w.end_tag();
1479       }
1480     }
1481 }
1482
1483 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1484     ebml_w.start_tag(tag_attributes);
1485     for attr in attrs.iter() {
1486         ebml_w.start_tag(tag_attribute);
1487         encode_meta_item(ebml_w, attr.node.value);
1488         ebml_w.end_tag();
1489     }
1490     ebml_w.end_tag();
1491 }
1492
1493 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1494     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1495         // Pull the cnums and name,vers,hash out of cstore
1496         let mut deps = Vec::new();
1497         cstore.iter_crate_data(|key, val| {
1498             let dep = decoder::CrateDep {
1499                 cnum: key,
1500                 name: decoder::get_crate_name(val.data()),
1501                 hash: decoder::get_crate_hash(val.data()),
1502             };
1503             deps.push(dep);
1504         });
1505
1506         // Sort by cnum
1507         deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1508
1509         // Sanity-check the crate numbers
1510         let mut expected_cnum = 1;
1511         for n in deps.iter() {
1512             assert_eq!(n.cnum, expected_cnum);
1513             expected_cnum += 1;
1514         }
1515
1516         deps
1517     }
1518
1519     // We're just going to write a list of crate 'name-hash-version's, with
1520     // the assumption that they are numbered 1 to n.
1521     // FIXME (#2166): This is not nearly enough to support correct versioning
1522     // but is enough to get transitive crate dependencies working.
1523     ebml_w.start_tag(tag_crate_deps);
1524     let r = get_ordered_deps(cstore);
1525     for dep in r.iter() {
1526         encode_crate_dep(ebml_w, (*dep).clone());
1527     }
1528     ebml_w.end_tag();
1529 }
1530
1531 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1532     ebml_w.start_tag(tag_lang_items);
1533
1534     for (i, def_id) in ecx.tcx.lang_items.items() {
1535         for id in def_id.iter() {
1536             if id.krate == LOCAL_CRATE {
1537                 ebml_w.start_tag(tag_lang_items_item);
1538
1539                 ebml_w.start_tag(tag_lang_items_item_id);
1540                 {
1541                     let wr: &mut MemWriter = ebml_w.writer;
1542                     wr.write_be_u32(i as u32);
1543                 }
1544                 ebml_w.end_tag();   // tag_lang_items_item_id
1545
1546                 ebml_w.start_tag(tag_lang_items_item_node_id);
1547                 {
1548                     let wr: &mut MemWriter = ebml_w.writer;
1549                     wr.write_be_u32(id.node as u32);
1550                 }
1551                 ebml_w.end_tag();   // tag_lang_items_item_node_id
1552
1553                 ebml_w.end_tag();   // tag_lang_items_item
1554             }
1555         }
1556     }
1557
1558     for i in ecx.tcx.lang_items.missing.iter() {
1559         ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1560     }
1561
1562     ebml_w.end_tag();   // tag_lang_items
1563 }
1564
1565 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1566     ebml_w.start_tag(tag_native_libraries);
1567
1568     for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1569                                .borrow().iter() {
1570         match kind {
1571             cstore::NativeStatic => {} // these libraries are not propagated
1572             cstore::NativeFramework | cstore::NativeUnknown => {
1573                 ebml_w.start_tag(tag_native_libraries_lib);
1574
1575                 ebml_w.start_tag(tag_native_libraries_kind);
1576                 ebml_w.writer.write_be_u32(kind as u32);
1577                 ebml_w.end_tag();
1578
1579                 ebml_w.start_tag(tag_native_libraries_name);
1580                 ebml_w.writer.write(lib.as_bytes());
1581                 ebml_w.end_tag();
1582
1583                 ebml_w.end_tag();
1584             }
1585         }
1586     }
1587
1588     ebml_w.end_tag();
1589 }
1590
1591 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1592     match ecx.tcx.sess.plugin_registrar_fn.get() {
1593         Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1594         None => {}
1595     }
1596 }
1597
1598 /// Given a span, write the text of that span into the output stream
1599 /// as an exported macro
1600 fn encode_macro_def(ecx: &EncodeContext,
1601                     ebml_w: &mut Encoder,
1602                     span: &syntax::codemap::Span) {
1603     let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1604         .expect("Unable to find source for macro");
1605     ebml_w.start_tag(tag_macro_def);
1606     ebml_w.wr_str(def.as_slice());
1607     ebml_w.end_tag();
1608 }
1609
1610 /// Serialize the text of the exported macros
1611 fn encode_macro_defs(ecx: &EncodeContext,
1612                      krate: &Crate,
1613                      ebml_w: &mut Encoder) {
1614     ebml_w.start_tag(tag_exported_macros);
1615     for span in krate.exported_macros.iter() {
1616         encode_macro_def(ecx, ebml_w, span);
1617     }
1618     ebml_w.end_tag();
1619 }
1620
1621 struct ImplVisitor<'a,'b,'c> {
1622     ecx: &'a EncodeContext<'b>,
1623     ebml_w: &'a mut Encoder<'c>,
1624 }
1625
1626 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1627     fn visit_item(&mut self, item: &Item, _: ()) {
1628         match item.node {
1629             ItemImpl(_, Some(ref trait_ref), _, _) => {
1630                 let def_map = &self.ecx.tcx.def_map;
1631                 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1632                 let def_id = trait_def.def_id();
1633
1634                 // Load eagerly if this is an implementation of the Drop trait
1635                 // or if the trait is not defined in this crate.
1636                 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1637                         def_id.krate != LOCAL_CRATE {
1638                     self.ebml_w.start_tag(tag_impls_impl);
1639                     encode_def_id(self.ebml_w, local_def(item.id));
1640                     self.ebml_w.end_tag();
1641                 }
1642             }
1643             _ => {}
1644         }
1645         visit::walk_item(self, item, ());
1646     }
1647 }
1648
1649 /// Encodes implementations that are eagerly loaded.
1650 ///
1651 /// None of this is necessary in theory; we can load all implementations
1652 /// lazily. However, in two cases the optimizations to lazily load
1653 /// implementations are not yet implemented. These two cases, which require us
1654 /// to load implementations eagerly, are:
1655 ///
1656 /// * Destructors (implementations of the Drop trait).
1657 ///
1658 /// * Implementations of traits not defined in this crate.
1659 fn encode_impls<'a>(ecx: &'a EncodeContext,
1660                     krate: &Crate,
1661                     ebml_w: &'a mut Encoder) {
1662     ebml_w.start_tag(tag_impls);
1663
1664     {
1665         let mut visitor = ImplVisitor {
1666             ecx: ecx,
1667             ebml_w: ebml_w,
1668         };
1669         visit::walk_crate(&mut visitor, krate, ());
1670     }
1671
1672     ebml_w.end_tag();
1673 }
1674
1675 fn encode_misc_info(ecx: &EncodeContext,
1676                     krate: &Crate,
1677                     ebml_w: &mut Encoder) {
1678     ebml_w.start_tag(tag_misc_info);
1679     ebml_w.start_tag(tag_misc_info_crate_items);
1680     for &item in krate.module.items.iter() {
1681         ebml_w.start_tag(tag_mod_child);
1682         ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1683         ebml_w.end_tag();
1684
1685         each_auxiliary_node_id(item, |auxiliary_node_id| {
1686             ebml_w.start_tag(tag_mod_child);
1687             ebml_w.wr_str(def_to_string(local_def(
1688                         auxiliary_node_id)).as_slice());
1689             ebml_w.end_tag();
1690             true
1691         });
1692     }
1693
1694     // Encode reexports for the root module.
1695     encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1696
1697     ebml_w.end_tag();
1698     ebml_w.end_tag();
1699 }
1700
1701 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1702     ebml_w.start_tag(tag_reachable_extern_fns);
1703
1704     for id in ecx.reachable.iter() {
1705         match ecx.tcx.map.find(*id) {
1706             Some(ast_map::NodeItem(i)) => {
1707                 match i.node {
1708                     ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1709                         ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1710                     }
1711                     _ => {}
1712                 }
1713             }
1714             _ => {}
1715         }
1716     }
1717
1718     ebml_w.end_tag();
1719 }
1720
1721 fn encode_crate_dep(ebml_w: &mut Encoder,
1722                     dep: decoder::CrateDep) {
1723     ebml_w.start_tag(tag_crate_dep);
1724     ebml_w.start_tag(tag_crate_dep_crate_name);
1725     ebml_w.writer.write(dep.name.as_bytes());
1726     ebml_w.end_tag();
1727     ebml_w.start_tag(tag_crate_dep_hash);
1728     ebml_w.writer.write(dep.hash.as_str().as_bytes());
1729     ebml_w.end_tag();
1730     ebml_w.end_tag();
1731 }
1732
1733 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1734     ebml_w.start_tag(tag_crate_hash);
1735     ebml_w.writer.write(hash.as_str().as_bytes());
1736     ebml_w.end_tag();
1737 }
1738
1739 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1740     ebml_w.start_tag(tag_crate_crate_name);
1741     ebml_w.writer.write(crate_name.as_bytes());
1742     ebml_w.end_tag();
1743 }
1744
1745 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1746     ebml_w.start_tag(tag_crate_triple);
1747     ebml_w.writer.write(triple.as_bytes());
1748     ebml_w.end_tag();
1749 }
1750
1751 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1752     ebml_w.start_tag(tag_dylib_dependency_formats);
1753     match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1754         Some(arr) => {
1755             let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1756                 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1757                     cstore::RequireDynamic => "d",
1758                     cstore::RequireStatic => "s",
1759                 })).to_string())
1760             }).collect::<Vec<String>>();
1761             ebml_w.writer.write(s.connect(",").as_bytes());
1762         }
1763         None => {}
1764     }
1765     ebml_w.end_tag();
1766 }
1767
1768 // NB: Increment this as you change the metadata encoding version.
1769 pub static metadata_encoding_version : &'static [u8] =
1770     &[0x72, //'r' as u8,
1771       0x75, //'u' as u8,
1772       0x73, //'s' as u8,
1773       0x74, //'t' as u8,
1774       0, 0, 0, 1 ];
1775
1776 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1777     let mut wr = MemWriter::new();
1778     encode_metadata_inner(&mut wr, parms, krate);
1779     wr.unwrap().move_iter().collect()
1780 }
1781
1782 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1783     struct Stats {
1784         attr_bytes: u64,
1785         dep_bytes: u64,
1786         lang_item_bytes: u64,
1787         native_lib_bytes: u64,
1788         plugin_registrar_fn_bytes: u64,
1789         macro_defs_bytes: u64,
1790         impl_bytes: u64,
1791         misc_bytes: u64,
1792         item_bytes: u64,
1793         index_bytes: u64,
1794         zero_bytes: u64,
1795         total_bytes: u64,
1796     }
1797     let mut stats = Stats {
1798         attr_bytes: 0,
1799         dep_bytes: 0,
1800         lang_item_bytes: 0,
1801         native_lib_bytes: 0,
1802         plugin_registrar_fn_bytes: 0,
1803         macro_defs_bytes: 0,
1804         impl_bytes: 0,
1805         misc_bytes: 0,
1806         item_bytes: 0,
1807         index_bytes: 0,
1808         zero_bytes: 0,
1809         total_bytes: 0,
1810     };
1811     let EncodeParams {
1812         item_symbols,
1813         diag,
1814         tcx,
1815         reexports2,
1816         cstore,
1817         encode_inlined_item,
1818         link_meta,
1819         non_inlineable_statics,
1820         reachable,
1821         ..
1822     } = parms;
1823     let ecx = EncodeContext {
1824         diag: diag,
1825         tcx: tcx,
1826         reexports2: reexports2,
1827         item_symbols: item_symbols,
1828         non_inlineable_statics: non_inlineable_statics,
1829         link_meta: link_meta,
1830         cstore: cstore,
1831         encode_inlined_item: RefCell::new(encode_inlined_item),
1832         type_abbrevs: RefCell::new(HashMap::new()),
1833         reachable: reachable,
1834      };
1835
1836     let mut ebml_w = writer::Encoder::new(wr);
1837
1838     encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1839     encode_crate_triple(&mut ebml_w,
1840                         tcx.sess
1841                            .targ_cfg
1842                            .target_strs
1843                            .target_triple
1844                            .as_slice());
1845     encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1846     encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1847
1848     let mut i = ebml_w.writer.tell().unwrap();
1849     encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1850     stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1851
1852     i = ebml_w.writer.tell().unwrap();
1853     encode_crate_deps(&mut ebml_w, ecx.cstore);
1854     stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1855
1856     // Encode the language items.
1857     i = ebml_w.writer.tell().unwrap();
1858     encode_lang_items(&ecx, &mut ebml_w);
1859     stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1860
1861     // Encode the native libraries used
1862     i = ebml_w.writer.tell().unwrap();
1863     encode_native_libraries(&ecx, &mut ebml_w);
1864     stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1865
1866     // Encode the plugin registrar function
1867     i = ebml_w.writer.tell().unwrap();
1868     encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1869     stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1870
1871     // Encode macro definitions
1872     i = ebml_w.writer.tell().unwrap();
1873     encode_macro_defs(&ecx, krate, &mut ebml_w);
1874     stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1875
1876     // Encode the def IDs of impls, for coherence checking.
1877     i = ebml_w.writer.tell().unwrap();
1878     encode_impls(&ecx, krate, &mut ebml_w);
1879     stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1880
1881     // Encode miscellaneous info.
1882     i = ebml_w.writer.tell().unwrap();
1883     encode_misc_info(&ecx, krate, &mut ebml_w);
1884     encode_reachable_extern_fns(&ecx, &mut ebml_w);
1885     stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1886
1887     // Encode and index the items.
1888     ebml_w.start_tag(tag_items);
1889     i = ebml_w.writer.tell().unwrap();
1890     let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1891     stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1892
1893     i = ebml_w.writer.tell().unwrap();
1894     encode_index(&mut ebml_w, items_index, write_i64);
1895     stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1896     ebml_w.end_tag();
1897
1898     stats.total_bytes = ebml_w.writer.tell().unwrap();
1899
1900     if tcx.sess.meta_stats() {
1901         for e in ebml_w.writer.get_ref().iter() {
1902             if *e == 0 {
1903                 stats.zero_bytes += 1;
1904             }
1905         }
1906
1907         println!("metadata stats:");
1908         println!("       attribute bytes: {}", stats.attr_bytes);
1909         println!("             dep bytes: {}", stats.dep_bytes);
1910         println!("       lang item bytes: {}", stats.lang_item_bytes);
1911         println!("          native bytes: {}", stats.native_lib_bytes);
1912         println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1913         println!("       macro def bytes: {}", stats.macro_defs_bytes);
1914         println!("            impl bytes: {}", stats.impl_bytes);
1915         println!("            misc bytes: {}", stats.misc_bytes);
1916         println!("            item bytes: {}", stats.item_bytes);
1917         println!("           index bytes: {}", stats.index_bytes);
1918         println!("            zero bytes: {}", stats.zero_bytes);
1919         println!("           total bytes: {}", stats.total_bytes);
1920     }
1921 }
1922
1923 // Get the encoded string for a type
1924 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1925     let mut wr = MemWriter::new();
1926     tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1927         diag: tcx.sess.diagnostic(),
1928         ds: def_to_string,
1929         tcx: tcx,
1930         abbrevs: &RefCell::new(HashMap::new())
1931     }, t);
1932     String::from_utf8(wr.unwrap()).unwrap()
1933 }