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