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