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