]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
auto merge of #14320 : kballard/rust/fix_stdlib_inject_attrs, r=alexcrichton
[rust.git] / src / librustc / metadata / encoder.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Metadata encoding
12
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
15
16 use back::svh::Svh;
17 use driver::config;
18 use metadata::common::*;
19 use metadata::cstore;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use middle::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));
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)));
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));
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));
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(
1440             attr::mk_name_value_item_str(
1441                 InternedString::new("crate_id"),
1442                 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1443     }
1444
1445     let mut attrs = Vec::new();
1446     for attr in krate.attrs.iter() {
1447         if !attr.name().equiv(&("crate_id")) {
1448             attrs.push(*attr);
1449         }
1450     }
1451     attrs.push(synthesize_crateid_attr(ecx));
1452
1453     attrs
1454 }
1455
1456 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1457     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1458         // Pull the cnums and name,vers,hash out of cstore
1459         let mut deps = Vec::new();
1460         cstore.iter_crate_data(|key, val| {
1461             let dep = decoder::CrateDep {
1462                 cnum: key,
1463                 crate_id: decoder::get_crate_id(val.data()),
1464                 hash: decoder::get_crate_hash(val.data())
1465             };
1466             deps.push(dep);
1467         });
1468
1469         // Sort by cnum
1470         deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1471
1472         // Sanity-check the crate numbers
1473         let mut expected_cnum = 1;
1474         for n in deps.iter() {
1475             assert_eq!(n.cnum, expected_cnum);
1476             expected_cnum += 1;
1477         }
1478
1479         deps
1480     }
1481
1482     // We're just going to write a list of crate 'name-hash-version's, with
1483     // the assumption that they are numbered 1 to n.
1484     // FIXME (#2166): This is not nearly enough to support correct versioning
1485     // but is enough to get transitive crate dependencies working.
1486     ebml_w.start_tag(tag_crate_deps);
1487     let r = get_ordered_deps(cstore);
1488     for dep in r.iter() {
1489         encode_crate_dep(ebml_w, (*dep).clone());
1490     }
1491     ebml_w.end_tag();
1492 }
1493
1494 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1495     ebml_w.start_tag(tag_lang_items);
1496
1497     for (i, def_id) in ecx.tcx.lang_items.items() {
1498         for id in def_id.iter() {
1499             if id.krate == LOCAL_CRATE {
1500                 ebml_w.start_tag(tag_lang_items_item);
1501
1502                 ebml_w.start_tag(tag_lang_items_item_id);
1503                 {
1504                     let wr: &mut MemWriter = ebml_w.writer;
1505                     wr.write_be_u32(i as u32);
1506                 }
1507                 ebml_w.end_tag();   // tag_lang_items_item_id
1508
1509                 ebml_w.start_tag(tag_lang_items_item_node_id);
1510                 {
1511                     let wr: &mut MemWriter = ebml_w.writer;
1512                     wr.write_be_u32(id.node as u32);
1513                 }
1514                 ebml_w.end_tag();   // tag_lang_items_item_node_id
1515
1516                 ebml_w.end_tag();   // tag_lang_items_item
1517             }
1518         }
1519     }
1520
1521     for i in ecx.tcx.lang_items.missing.iter() {
1522         ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1523     }
1524
1525     ebml_w.end_tag();   // tag_lang_items
1526 }
1527
1528 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1529     ebml_w.start_tag(tag_native_libraries);
1530
1531     for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1532                                .borrow().iter() {
1533         match kind {
1534             cstore::NativeStatic => {} // these libraries are not propagated
1535             cstore::NativeFramework | cstore::NativeUnknown => {
1536                 ebml_w.start_tag(tag_native_libraries_lib);
1537
1538                 ebml_w.start_tag(tag_native_libraries_kind);
1539                 ebml_w.writer.write_be_u32(kind as u32);
1540                 ebml_w.end_tag();
1541
1542                 ebml_w.start_tag(tag_native_libraries_name);
1543                 ebml_w.writer.write(lib.as_bytes());
1544                 ebml_w.end_tag();
1545
1546                 ebml_w.end_tag();
1547             }
1548         }
1549     }
1550
1551     ebml_w.end_tag();
1552 }
1553
1554 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1555     match ecx.tcx.sess.macro_registrar_fn.get() {
1556         Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
1557         None => {}
1558     }
1559 }
1560
1561 struct MacroDefVisitor<'a, 'b, 'c> {
1562     ecx: &'a EncodeContext<'b>,
1563     ebml_w: &'a mut Encoder<'c>
1564 }
1565
1566 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1567     fn visit_item(&mut self, item: &Item, _: ()) {
1568         match item.node {
1569             ItemMac(..) => {
1570                 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1571                     .expect("Unable to find source for macro");
1572                 self.ebml_w.start_tag(tag_macro_def);
1573                 self.ebml_w.wr_str(def.as_slice());
1574                 self.ebml_w.end_tag();
1575             }
1576             _ => {}
1577         }
1578         visit::walk_item(self, item, ());
1579     }
1580 }
1581
1582 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1583                          krate: &Crate,
1584                          ebml_w: &'a mut Encoder) {
1585     ebml_w.start_tag(tag_exported_macros);
1586     {
1587         let mut visitor = MacroDefVisitor {
1588             ecx: ecx,
1589             ebml_w: ebml_w,
1590         };
1591         visit::walk_crate(&mut visitor, krate, ());
1592     }
1593     ebml_w.end_tag();
1594 }
1595
1596 struct ImplVisitor<'a,'b,'c> {
1597     ecx: &'a EncodeContext<'b>,
1598     ebml_w: &'a mut Encoder<'c>,
1599 }
1600
1601 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1602     fn visit_item(&mut self, item: &Item, _: ()) {
1603         match item.node {
1604             ItemImpl(_, Some(ref trait_ref), _, _) => {
1605                 let def_map = &self.ecx.tcx.def_map;
1606                 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1607                 let def_id = ast_util::def_id_of_def(trait_def);
1608
1609                 // Load eagerly if this is an implementation of the Drop trait
1610                 // or if the trait is not defined in this crate.
1611                 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1612                         def_id.krate != LOCAL_CRATE {
1613                     self.ebml_w.start_tag(tag_impls_impl);
1614                     encode_def_id(self.ebml_w, local_def(item.id));
1615                     self.ebml_w.end_tag();
1616                 }
1617             }
1618             _ => {}
1619         }
1620         visit::walk_item(self, item, ());
1621     }
1622 }
1623
1624 /// Encodes implementations that are eagerly loaded.
1625 ///
1626 /// None of this is necessary in theory; we can load all implementations
1627 /// lazily. However, in two cases the optimizations to lazily load
1628 /// implementations are not yet implemented. These two cases, which require us
1629 /// to load implementations eagerly, are:
1630 ///
1631 /// * Destructors (implementations of the Drop trait).
1632 ///
1633 /// * Implementations of traits not defined in this crate.
1634 fn encode_impls<'a>(ecx: &'a EncodeContext,
1635                     krate: &Crate,
1636                     ebml_w: &'a mut Encoder) {
1637     ebml_w.start_tag(tag_impls);
1638
1639     {
1640         let mut visitor = ImplVisitor {
1641             ecx: ecx,
1642             ebml_w: ebml_w,
1643         };
1644         visit::walk_crate(&mut visitor, krate, ());
1645     }
1646
1647     ebml_w.end_tag();
1648 }
1649
1650 fn encode_misc_info(ecx: &EncodeContext,
1651                     krate: &Crate,
1652                     ebml_w: &mut Encoder) {
1653     ebml_w.start_tag(tag_misc_info);
1654     ebml_w.start_tag(tag_misc_info_crate_items);
1655     for &item in krate.module.items.iter() {
1656         ebml_w.start_tag(tag_mod_child);
1657         ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
1658         ebml_w.end_tag();
1659
1660         each_auxiliary_node_id(item, |auxiliary_node_id| {
1661             ebml_w.start_tag(tag_mod_child);
1662             ebml_w.wr_str(def_to_str(local_def(
1663                         auxiliary_node_id)).as_slice());
1664             ebml_w.end_tag();
1665             true
1666         });
1667     }
1668
1669     // Encode reexports for the root module.
1670     encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1671
1672     ebml_w.end_tag();
1673     ebml_w.end_tag();
1674 }
1675
1676 fn encode_crate_dep(ebml_w: &mut Encoder,
1677                     dep: decoder::CrateDep) {
1678     ebml_w.start_tag(tag_crate_dep);
1679     ebml_w.start_tag(tag_crate_dep_crateid);
1680     ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1681     ebml_w.end_tag();
1682     ebml_w.start_tag(tag_crate_dep_hash);
1683     ebml_w.writer.write(dep.hash.as_str().as_bytes());
1684     ebml_w.end_tag();
1685     ebml_w.end_tag();
1686 }
1687
1688 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1689     ebml_w.start_tag(tag_crate_hash);
1690     ebml_w.writer.write(hash.as_str().as_bytes());
1691     ebml_w.end_tag();
1692 }
1693
1694 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1695     ebml_w.start_tag(tag_crate_crateid);
1696     ebml_w.writer.write(crate_id.to_str().as_bytes());
1697     ebml_w.end_tag();
1698 }
1699
1700 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1701     ebml_w.start_tag(tag_crate_triple);
1702     ebml_w.writer.write(triple.as_bytes());
1703     ebml_w.end_tag();
1704 }
1705
1706 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1707     ebml_w.start_tag(tag_dylib_dependency_formats);
1708     match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1709         Some(arr) => {
1710             let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1711                 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1712                     cstore::RequireDynamic => "d",
1713                     cstore::RequireStatic => "s",
1714                 })).to_strbuf())
1715             }).collect::<Vec<StrBuf>>();
1716             ebml_w.writer.write(s.connect(",").as_bytes());
1717         }
1718         None => {}
1719     }
1720     ebml_w.end_tag();
1721 }
1722
1723 // NB: Increment this as you change the metadata encoding version.
1724 pub static metadata_encoding_version : &'static [u8] =
1725     &[0x72, //'r' as u8,
1726       0x75, //'u' as u8,
1727       0x73, //'s' as u8,
1728       0x74, //'t' as u8,
1729       0, 0, 0, 1 ];
1730
1731 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1732     let mut wr = MemWriter::new();
1733     encode_metadata_inner(&mut wr, parms, krate);
1734     wr.unwrap().move_iter().collect()
1735 }
1736
1737 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1738     struct Stats {
1739         attr_bytes: u64,
1740         dep_bytes: u64,
1741         lang_item_bytes: u64,
1742         native_lib_bytes: u64,
1743         macro_registrar_fn_bytes: u64,
1744         macro_defs_bytes: u64,
1745         impl_bytes: u64,
1746         misc_bytes: u64,
1747         item_bytes: u64,
1748         index_bytes: u64,
1749         zero_bytes: u64,
1750         total_bytes: u64,
1751     }
1752     let mut stats = Stats {
1753         attr_bytes: 0,
1754         dep_bytes: 0,
1755         lang_item_bytes: 0,
1756         native_lib_bytes: 0,
1757         macro_registrar_fn_bytes: 0,
1758         macro_defs_bytes: 0,
1759         impl_bytes: 0,
1760         misc_bytes: 0,
1761         item_bytes: 0,
1762         index_bytes: 0,
1763         zero_bytes: 0,
1764         total_bytes: 0,
1765     };
1766     let EncodeParams {
1767         item_symbols,
1768         diag,
1769         tcx,
1770         reexports2,
1771         cstore,
1772         encode_inlined_item,
1773         link_meta,
1774         non_inlineable_statics,
1775         ..
1776     } = parms;
1777     let ecx = EncodeContext {
1778         diag: diag,
1779         tcx: tcx,
1780         reexports2: reexports2,
1781         item_symbols: item_symbols,
1782         non_inlineable_statics: non_inlineable_statics,
1783         link_meta: link_meta,
1784         cstore: cstore,
1785         encode_inlined_item: RefCell::new(encode_inlined_item),
1786         type_abbrevs: RefCell::new(HashMap::new()),
1787      };
1788
1789     let mut ebml_w = writer::Encoder(wr);
1790
1791     encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1792     encode_crate_triple(&mut ebml_w,
1793                         tcx.sess
1794                            .targ_cfg
1795                            .target_strs
1796                            .target_triple
1797                            .as_slice());
1798     encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1799     encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1800
1801     let mut i = ebml_w.writer.tell().unwrap();
1802     let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1803     encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1804     stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1805
1806     i = ebml_w.writer.tell().unwrap();
1807     encode_crate_deps(&mut ebml_w, ecx.cstore);
1808     stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1809
1810     // Encode the language items.
1811     i = ebml_w.writer.tell().unwrap();
1812     encode_lang_items(&ecx, &mut ebml_w);
1813     stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1814
1815     // Encode the native libraries used
1816     i = ebml_w.writer.tell().unwrap();
1817     encode_native_libraries(&ecx, &mut ebml_w);
1818     stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1819
1820     // Encode the macro registrar function
1821     i = ebml_w.writer.tell().unwrap();
1822     encode_macro_registrar_fn(&ecx, &mut ebml_w);
1823     stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1824
1825     // Encode macro definitions
1826     i = ebml_w.writer.tell().unwrap();
1827     encode_macro_defs(&ecx, krate, &mut ebml_w);
1828     stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1829
1830     // Encode the def IDs of impls, for coherence checking.
1831     i = ebml_w.writer.tell().unwrap();
1832     encode_impls(&ecx, krate, &mut ebml_w);
1833     stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1834
1835     // Encode miscellaneous info.
1836     i = ebml_w.writer.tell().unwrap();
1837     encode_misc_info(&ecx, krate, &mut ebml_w);
1838     stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1839
1840     // Encode and index the items.
1841     ebml_w.start_tag(tag_items);
1842     i = ebml_w.writer.tell().unwrap();
1843     let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1844     stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1845
1846     i = ebml_w.writer.tell().unwrap();
1847     encode_index(&mut ebml_w, items_index, write_i64);
1848     stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1849     ebml_w.end_tag();
1850
1851     stats.total_bytes = ebml_w.writer.tell().unwrap();
1852
1853     if tcx.sess.meta_stats() {
1854         for e in ebml_w.writer.get_ref().iter() {
1855             if *e == 0 {
1856                 stats.zero_bytes += 1;
1857             }
1858         }
1859
1860         println!("metadata stats:");
1861         println!("      attribute bytes: {}", stats.attr_bytes);
1862         println!("            dep bytes: {}", stats.dep_bytes);
1863         println!("      lang item bytes: {}", stats.lang_item_bytes);
1864         println!("         native bytes: {}", stats.native_lib_bytes);
1865         println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
1866         println!("      macro def bytes: {}", stats.macro_defs_bytes);
1867         println!("           impl bytes: {}", stats.impl_bytes);
1868         println!("           misc bytes: {}", stats.misc_bytes);
1869         println!("           item bytes: {}", stats.item_bytes);
1870         println!("          index bytes: {}", stats.index_bytes);
1871         println!("           zero bytes: {}", stats.zero_bytes);
1872         println!("          total bytes: {}", stats.total_bytes);
1873     }
1874 }
1875
1876 // Get the encoded string for a type
1877 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> StrBuf {
1878     let mut wr = MemWriter::new();
1879     tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1880         diag: tcx.sess.diagnostic(),
1881         ds: def_to_str,
1882         tcx: tcx,
1883         abbrevs: &RefCell::new(HashMap::new())
1884     }, t);
1885     str::from_utf8_owned(wr.get_ref().to_owned()).unwrap().to_strbuf()
1886 }