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