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