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