]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
Use Names in path fragments and MacroDef
[rust.git] / src / librustc / metadata / encoder.rs
1 // Copyright 2012-2015 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 session::config;
18 use metadata::common::*;
19 use metadata::cstore;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use metadata::index::{self, IndexEntry};
23 use metadata::inline::InlinedItemRef;
24 use middle::def;
25 use middle::def_id::{DefId, LOCAL_CRATE};
26 use middle::dependency_format::Linkage;
27 use middle::stability;
28 use middle::ty::{self, Ty};
29 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
30
31 use serialize::Encodable;
32 use std::cell::RefCell;
33 use std::io::prelude::*;
34 use std::io::{Cursor, SeekFrom};
35 use std::rc::Rc;
36 use syntax::abi;
37 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
38 use syntax::attr;
39 use syntax::attr::AttrMetaMethods;
40 use syntax::diagnostic::SpanHandler;
41 use syntax::parse::token::special_idents;
42 use syntax;
43 use rbml::writer::Encoder;
44
45 use rustc_front::hir;
46 use rustc_front::visit::Visitor;
47 use rustc_front::visit;
48 use front::map::{LinkedPath, PathElem, PathElems};
49 use front::map as ast_map;
50
51 pub type EncodeInlinedItem<'a> =
52     Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
53
54 pub struct EncodeParams<'a, 'tcx: 'a> {
55     pub diag: &'a SpanHandler,
56     pub tcx: &'a ty::ctxt<'tcx>,
57     pub reexports: &'a def::ExportMap,
58     pub item_symbols: &'a RefCell<NodeMap<String>>,
59     pub link_meta: &'a LinkMeta,
60     pub cstore: &'a cstore::CStore,
61     pub encode_inlined_item: EncodeInlinedItem<'a>,
62     pub reachable: &'a NodeSet,
63 }
64
65 pub struct EncodeContext<'a, 'tcx: 'a> {
66     pub diag: &'a SpanHandler,
67     pub tcx: &'a ty::ctxt<'tcx>,
68     pub reexports: &'a def::ExportMap,
69     pub item_symbols: &'a RefCell<NodeMap<String>>,
70     pub link_meta: &'a LinkMeta,
71     pub cstore: &'a cstore::CStore,
72     pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
73     pub type_abbrevs: tyencode::abbrev_map<'tcx>,
74     pub reachable: &'a NodeSet,
75 }
76
77 fn encode_name(rbml_w: &mut Encoder, name: Name) {
78     rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
79 }
80
81 fn encode_impl_type_basename(rbml_w: &mut Encoder, name: Name) {
82     rbml_w.wr_tagged_str(tag_item_impl_type_basename, &name.as_str());
83 }
84
85 fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
86     rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
87 }
88
89 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
90                               ecx: &EncodeContext<'a, 'tcx>,
91                               trait_ref: ty::TraitRef<'tcx>,
92                               tag: usize) {
93     let ty_str_ctxt = &tyencode::ctxt {
94         diag: ecx.diag,
95         ds: def_to_string,
96         tcx: ecx.tcx,
97         abbrevs: &ecx.type_abbrevs
98     };
99
100     rbml_w.start_tag(tag);
101     tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
102     rbml_w.end_tag();
103 }
104
105 // Item info table encoding
106 fn encode_family(rbml_w: &mut Encoder, c: char) {
107     rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
108 }
109
110 pub fn def_to_u64(did: DefId) -> u64 {
111     (did.krate as u64) << 32 | (did.node as u64)
112 }
113
114 pub fn def_to_string(did: DefId) -> String {
115     format!("{}:{}", did.krate, did.node)
116 }
117
118 fn encode_item_variances(rbml_w: &mut Encoder,
119                          ecx: &EncodeContext,
120                          id: NodeId) {
121     let v = ecx.tcx.item_variances(DefId::local(id));
122     rbml_w.start_tag(tag_item_variances);
123     v.encode(rbml_w);
124     rbml_w.end_tag();
125 }
126
127 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
128                                              ecx: &EncodeContext<'a, 'tcx>,
129                                              id: NodeId) {
130     encode_bounds_and_type(rbml_w,
131                            ecx,
132                            &ecx.tcx.lookup_item_type(DefId::local(id)),
133                            &ecx.tcx.lookup_predicates(DefId::local(id)));
134 }
135
136 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
137                                     ecx: &EncodeContext<'a, 'tcx>,
138                                     scheme: &ty::TypeScheme<'tcx>,
139                                     predicates: &ty::GenericPredicates<'tcx>) {
140     encode_generics(rbml_w, ecx, &scheme.generics, &predicates, tag_item_generics);
141     encode_type(ecx, rbml_w, scheme.ty);
142 }
143
144 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
145     let id = def_to_u64(vid);
146     rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
147     rbml_w.wr_tagged_u64(tag_mod_child, id);
148 }
149
150 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
151                                     rbml_w: &mut Encoder,
152                                     closure_type: &ty::ClosureTy<'tcx>) {
153     let ty_str_ctxt = &tyencode::ctxt {
154         diag: ecx.diag,
155         ds: def_to_string,
156         tcx: ecx.tcx,
157         abbrevs: &ecx.type_abbrevs
158     };
159     tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
160 }
161
162 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
163                             rbml_w: &mut Encoder,
164                             typ: Ty<'tcx>) {
165     let ty_str_ctxt = &tyencode::ctxt {
166         diag: ecx.diag,
167         ds: def_to_string,
168         tcx: ecx.tcx,
169         abbrevs: &ecx.type_abbrevs
170     };
171     tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
172 }
173
174 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
175                                  rbml_w: &mut Encoder,
176                                 trait_ref: &ty::TraitRef<'tcx>) {
177     let ty_str_ctxt = &tyencode::ctxt {
178         diag: ecx.diag,
179         ds: def_to_string,
180         tcx: ecx.tcx,
181         abbrevs: &ecx.type_abbrevs
182     };
183     tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref);
184 }
185
186 pub fn write_region(ecx: &EncodeContext,
187                     rbml_w: &mut Encoder,
188                     r: ty::Region) {
189     let ty_str_ctxt = &tyencode::ctxt {
190         diag: ecx.diag,
191         ds: def_to_string,
192         tcx: ecx.tcx,
193         abbrevs: &ecx.type_abbrevs
194     };
195     tyencode::enc_region(rbml_w, ty_str_ctxt, r);
196 }
197
198 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
199                          rbml_w: &mut Encoder,
200                          typ: Ty<'tcx>) {
201     rbml_w.start_tag(tag_items_data_item_type);
202     write_type(ecx, rbml_w, typ);
203     rbml_w.end_tag();
204 }
205
206 fn encode_region(ecx: &EncodeContext,
207                  rbml_w: &mut Encoder,
208                  r: ty::Region) {
209     rbml_w.start_tag(tag_items_data_region);
210     write_region(ecx, rbml_w, r);
211     rbml_w.end_tag();
212 }
213
214 fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
215                                rbml_w: &mut Encoder,
216                                typ: &ty::BareFnTy<'tcx>) {
217     rbml_w.start_tag(tag_item_method_fty);
218
219     let ty_str_ctxt = &tyencode::ctxt {
220         diag: ecx.diag,
221         ds: def_to_string,
222         tcx: ecx.tcx,
223         abbrevs: &ecx.type_abbrevs
224     };
225     tyencode::enc_bare_fn_ty(rbml_w, ty_str_ctxt, typ);
226
227     rbml_w.end_tag();
228 }
229
230 fn encode_symbol(ecx: &EncodeContext,
231                  rbml_w: &mut Encoder,
232                  id: NodeId) {
233     match ecx.item_symbols.borrow().get(&id) {
234         Some(x) => {
235             debug!("encode_symbol(id={}, str={})", id, *x);
236             rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
237         }
238         None => {
239             ecx.diag.handler().bug(
240                 &format!("encode_symbol: id not found {}", id));
241         }
242     }
243 }
244
245 fn encode_disr_val(_: &EncodeContext,
246                    rbml_w: &mut Encoder,
247                    disr_val: ty::Disr) {
248     rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_string());
249 }
250
251 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
252     rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
253 }
254
255 fn encode_struct_fields(rbml_w: &mut Encoder,
256                         variant: ty::VariantDef,
257                         origin: DefId) {
258     for f in &variant.fields {
259         if f.name == special_idents::unnamed_field.name {
260             rbml_w.start_tag(tag_item_unnamed_field);
261         } else {
262             rbml_w.start_tag(tag_item_field);
263             encode_name(rbml_w, f.name);
264         }
265         encode_struct_field_family(rbml_w, f.vis);
266         encode_def_id(rbml_w, f.did);
267         rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
268         rbml_w.end_tag();
269     }
270 }
271
272 fn encode_enum_variant_info(ecx: &EncodeContext,
273                             rbml_w: &mut Encoder,
274                             id: NodeId,
275                             vis: hir::Visibility,
276                             index: &mut Vec<IndexEntry>) {
277     debug!("encode_enum_variant_info(id={})", id);
278
279     let mut disr_val = 0;
280     let def = ecx.tcx.lookup_adt_def(DefId::local(id));
281     for variant in &def.variants {
282         let vid = variant.did;
283         assert!(vid.is_local());
284
285         if let ty::VariantKind::Dict = variant.kind() {
286             // tuple-like enum variant fields aren't really items so
287             // don't try to encode them.
288             for field in &variant.fields {
289                 encode_field(ecx, rbml_w, field, index);
290             }
291         }
292
293         index.push(IndexEntry {
294             node: vid.node,
295             pos: rbml_w.mark_stable_position(),
296         });
297         rbml_w.start_tag(tag_items_data_item);
298         encode_def_id(rbml_w, vid);
299         encode_family(rbml_w, match variant.kind() {
300             ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
301             ty::VariantKind::Dict => 'V'
302         });
303         encode_name(rbml_w, variant.name);
304         encode_parent_item(rbml_w, DefId::local(id));
305         encode_visibility(rbml_w, vis);
306
307         let attrs = ecx.tcx.get_attrs(vid);
308         encode_attributes(rbml_w, &attrs);
309         encode_repr_attrs(rbml_w, ecx, &attrs);
310
311         let stab = stability::lookup(ecx.tcx, vid);
312         encode_stability(rbml_w, stab);
313
314         encode_struct_fields(rbml_w, variant, vid);
315
316         let specified_disr_val = variant.disr_val;
317         if specified_disr_val != disr_val {
318             encode_disr_val(ecx, rbml_w, specified_disr_val);
319             disr_val = specified_disr_val;
320         }
321         encode_bounds_and_type_for_item(rbml_w, ecx, vid.node);
322
323         ecx.tcx.map.with_path(vid.node, |path| encode_path(rbml_w, path));
324         rbml_w.end_tag();
325         disr_val = disr_val.wrapping_add(1);
326     }
327 }
328
329 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
330     let path = path.collect::<Vec<_>>();
331     rbml_w.start_tag(tag_path);
332     rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
333     for pe in &path {
334         let tag = match *pe {
335             ast_map::PathMod(_) => tag_path_elem_mod,
336             ast_map::PathName(_) => tag_path_elem_name
337         };
338         rbml_w.wr_tagged_str(tag, &pe.name().as_str());
339     }
340     rbml_w.end_tag();
341 }
342
343 fn encode_reexported_static_method(rbml_w: &mut Encoder,
344                                    exp: &def::Export,
345                                    method_def_id: DefId,
346                                    method_name: Name) {
347     debug!("(encode reexported static method) {}::{}",
348             exp.name, method_name);
349     rbml_w.start_tag(tag_items_data_item_reexport);
350     rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
351                          def_to_u64(method_def_id));
352     rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
353                          &format!("{}::{}", exp.name,
354                                             method_name));
355     rbml_w.end_tag();
356 }
357
358 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
359                                          rbml_w: &mut Encoder,
360                                          exp: &def::Export)
361                                          -> bool {
362     let impl_items = ecx.tcx.impl_items.borrow();
363     match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
364         Some(implementations) => {
365             for base_impl_did in implementations.iter() {
366                 for &method_did in impl_items.get(base_impl_did).unwrap() {
367                     let impl_item = ecx.tcx.impl_or_trait_item(method_did.def_id());
368                     if let ty::MethodTraitItem(ref m) = impl_item {
369                         encode_reexported_static_method(rbml_w,
370                                                         exp,
371                                                         m.def_id,
372                                                         m.name);
373                     }
374                 }
375             }
376
377             true
378         }
379         None => { false }
380     }
381 }
382
383 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
384                                           rbml_w: &mut Encoder,
385                                           exp: &def::Export)
386                                           -> bool {
387     match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
388         Some(trait_items) => {
389             for trait_item in trait_items.iter() {
390                 if let ty::MethodTraitItem(ref m) = *trait_item {
391                     encode_reexported_static_method(rbml_w,
392                                                     exp,
393                                                     m.def_id,
394                                                     m.name);
395                 }
396             }
397             true
398         }
399         None => { false }
400     }
401 }
402
403 fn encode_reexported_static_methods(ecx: &EncodeContext,
404                                     rbml_w: &mut Encoder,
405                                     mod_path: PathElems,
406                                     exp: &def::Export) {
407     if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
408         let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
409             let (mut a, mut b) = (path, mod_path.clone());
410             loop {
411                 match (a.next(), b.next()) {
412                     (None, None) => return true,
413                     (None, _) | (_, None) => return false,
414                     (Some(x), Some(y)) => if x != y { return false },
415                 }
416             }
417         });
418
419         //
420         // We don't need to reexport static methods on items
421         // declared in the same module as our `pub use ...` since
422         // that's done when we encode the item itself.
423         //
424         // The only exception is when the reexport *changes* the
425         // name e.g. `pub use Foo = self::Bar` -- we have
426         // encoded metadata for static methods relative to Bar,
427         // but not yet for Foo.
428         //
429         if path_differs || item.name != exp.name {
430             if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
431                 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
432                     debug!("(encode reexported static methods) {} [trait]",
433                            item.name);
434                 }
435             }
436             else {
437                 debug!("(encode reexported static methods) {} [base]",
438                        item.name);
439             }
440         }
441     }
442 }
443
444 /// Iterates through "auxiliary node IDs", which are node IDs that describe
445 /// top-level items that are sub-items of the given item. Specifically:
446 ///
447 /// * For newtype structs, iterates through the node ID of the constructor.
448 fn each_auxiliary_node_id<F>(item: &hir::Item, callback: F) -> bool where
449     F: FnOnce(NodeId) -> bool,
450 {
451     let mut continue_ = true;
452     match item.node {
453         hir::ItemStruct(ref struct_def, _) => {
454             // If this is a newtype struct, return the constructor.
455             match struct_def.ctor_id {
456                 Some(ctor_id) if !struct_def.fields.is_empty() &&
457                         struct_def.fields[0].node.kind.is_unnamed() => {
458                     continue_ = callback(ctor_id);
459                 }
460                 _ => {}
461             }
462         }
463         _ => {}
464     }
465
466     continue_
467 }
468
469 fn encode_reexports(ecx: &EncodeContext,
470                     rbml_w: &mut Encoder,
471                     id: NodeId,
472                     path: PathElems) {
473     debug!("(encoding info for module) encoding reexports for {}", id);
474     match ecx.reexports.get(&id) {
475         Some(exports) => {
476             debug!("(encoding info for module) found reexports for {}", id);
477             for exp in exports {
478                 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
479                         {}",
480                        exp.name,
481                        exp.def_id.krate,
482                        exp.def_id.node,
483                        id);
484                 rbml_w.start_tag(tag_items_data_item_reexport);
485                 rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
486                                      def_to_u64(exp.def_id));
487                 rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
488                                      &exp.name.as_str());
489                 rbml_w.end_tag();
490                 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
491             }
492         },
493         None => debug!("(encoding info for module) found no reexports for {}", id),
494     }
495 }
496
497 fn encode_info_for_mod(ecx: &EncodeContext,
498                        rbml_w: &mut Encoder,
499                        md: &hir::Mod,
500                        attrs: &[ast::Attribute],
501                        id: NodeId,
502                        path: PathElems,
503                        name: Name,
504                        vis: hir::Visibility) {
505     rbml_w.start_tag(tag_items_data_item);
506     encode_def_id(rbml_w, DefId::local(id));
507     encode_family(rbml_w, 'm');
508     encode_name(rbml_w, name);
509     debug!("(encoding info for module) encoding info for module ID {}", id);
510
511     // Encode info about all the module children.
512     for item in &md.items {
513         rbml_w.wr_tagged_u64(tag_mod_child,
514                              def_to_u64(DefId::local(item.id)));
515
516         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
517             rbml_w.wr_tagged_u64(tag_mod_child,
518                                  def_to_u64(DefId::local(auxiliary_node_id)));
519             true
520         });
521
522         if let hir::ItemImpl(..) = item.node {
523             let (ident, did) = (item.name, item.id);
524             debug!("(encoding info for module) ... encoding impl {} ({}/{})",
525                    ident,
526                    did, ecx.tcx.map.node_to_string(did));
527
528             rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(DefId::local(did)));
529         }
530     }
531
532     encode_path(rbml_w, path.clone());
533     encode_visibility(rbml_w, vis);
534
535     let stab = stability::lookup(ecx.tcx, DefId::local(id));
536     encode_stability(rbml_w, stab);
537
538     // Encode the reexports of this module, if this module is public.
539     if vis == hir::Public {
540         debug!("(encoding info for module) encoding reexports for {}", id);
541         encode_reexports(ecx, rbml_w, id, path);
542     }
543     encode_attributes(rbml_w, attrs);
544
545     rbml_w.end_tag();
546 }
547
548 fn encode_struct_field_family(rbml_w: &mut Encoder,
549                               visibility: hir::Visibility) {
550     encode_family(rbml_w, match visibility {
551         hir::Public => 'g',
552         hir::Inherited => 'N'
553     });
554 }
555
556 fn encode_visibility(rbml_w: &mut Encoder, visibility: hir::Visibility) {
557     let ch = match visibility {
558         hir::Public => 'y',
559         hir::Inherited => 'i',
560     };
561     rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
562 }
563
564 fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) {
565     rbml_w.start_tag(tag_items_data_item_constness);
566     let ch = match constness {
567         hir::Constness::Const => 'c',
568         hir::Constness::NotConst => 'n',
569     };
570     rbml_w.wr_str(&ch.to_string());
571     rbml_w.end_tag();
572 }
573
574 fn encode_explicit_self(rbml_w: &mut Encoder,
575                         explicit_self: &ty::ExplicitSelfCategory) {
576     let tag = tag_item_trait_method_explicit_self;
577
578     // Encode the base self type.
579     match *explicit_self {
580         ty::StaticExplicitSelfCategory => {
581             rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
582         }
583         ty::ByValueExplicitSelfCategory => {
584             rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
585         }
586         ty::ByBoxExplicitSelfCategory => {
587             rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
588         }
589         ty::ByReferenceExplicitSelfCategory(_, m) => {
590             // FIXME(#4846) encode custom lifetime
591             let ch = encode_mutability(m);
592             rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]);
593         }
594     }
595
596     fn encode_mutability(m: hir::Mutability) -> u8 {
597         match m {
598             hir::MutImmutable => 'i' as u8,
599             hir::MutMutable => 'm' as u8,
600         }
601     }
602 }
603
604 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
605     rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
606 }
607
608 fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
609     rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8);
610 }
611
612 fn encode_provided_source(rbml_w: &mut Encoder,
613                           source_opt: Option<DefId>) {
614     if let Some(source) = source_opt {
615         rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source));
616     }
617 }
618
619 fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
620                           rbml_w: &mut Encoder,
621                           field: ty::FieldDef<'tcx>,
622                           global_index: &mut Vec<IndexEntry>) {
623     let nm = field.name;
624     let id = field.did.node;
625
626     let pos = rbml_w.mark_stable_position();
627     global_index.push(IndexEntry {
628         node: id,
629         pos: pos,
630     });
631     rbml_w.start_tag(tag_items_data_item);
632     debug!("encode_field: encoding {} {}", nm, id);
633     encode_struct_field_family(rbml_w, field.vis);
634     encode_name(rbml_w, nm);
635     encode_bounds_and_type_for_item(rbml_w, ecx, id);
636     encode_def_id(rbml_w, DefId::local(id));
637
638     let stab = stability::lookup(ecx.tcx, field.did);
639     encode_stability(rbml_w, stab);
640
641     rbml_w.end_tag();
642 }
643
644 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
645                                rbml_w: &mut Encoder,
646                                name: Name,
647                                ctor_id: NodeId,
648                                index: &mut Vec<IndexEntry>,
649                                struct_id: NodeId) {
650     index.push(IndexEntry {
651         node: ctor_id,
652         pos: rbml_w.mark_stable_position(),
653     });
654
655     rbml_w.start_tag(tag_items_data_item);
656     encode_def_id(rbml_w, DefId::local(ctor_id));
657     encode_family(rbml_w, 'o');
658     encode_bounds_and_type_for_item(rbml_w, ecx, ctor_id);
659     encode_name(rbml_w, name);
660     ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
661     encode_parent_item(rbml_w, DefId::local(struct_id));
662
663     if ecx.item_symbols.borrow().contains_key(&ctor_id) {
664         encode_symbol(ecx, rbml_w, ctor_id);
665     }
666
667     let stab = stability::lookup(ecx.tcx, DefId::local(ctor_id));
668     encode_stability(rbml_w, stab);
669
670     // indicate that this is a tuple struct ctor, because downstream users will normally want
671     // the tuple struct definition, but without this there is no way for them to tell that
672     // they actually have a ctor rather than a normal function
673     rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]);
674
675     rbml_w.end_tag();
676 }
677
678 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
679                              ecx: &EncodeContext<'a, 'tcx>,
680                              generics: &ty::Generics<'tcx>,
681                              predicates: &ty::GenericPredicates<'tcx>,
682                              tag: usize)
683 {
684     rbml_w.start_tag(tag);
685
686     // Type parameters
687     let ty_str_ctxt = &tyencode::ctxt {
688         diag: ecx.diag,
689         ds: def_to_string,
690         tcx: ecx.tcx,
691         abbrevs: &ecx.type_abbrevs
692     };
693
694     for param in &generics.types {
695         rbml_w.start_tag(tag_type_param_def);
696         tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
697         rbml_w.end_tag();
698     }
699
700     // Region parameters
701     for param in &generics.regions {
702         rbml_w.start_tag(tag_region_param_def);
703
704         rbml_w.start_tag(tag_region_param_def_ident);
705         encode_name(rbml_w, param.name);
706         rbml_w.end_tag();
707
708         rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
709                              def_to_u64(param.def_id));
710
711         rbml_w.wr_tagged_u64(tag_region_param_def_space,
712                              param.space.to_uint() as u64);
713
714         rbml_w.wr_tagged_u64(tag_region_param_def_index,
715                              param.index as u64);
716
717         for &bound_region in &param.bounds {
718             encode_region(ecx, rbml_w, bound_region);
719         }
720
721         rbml_w.end_tag();
722     }
723
724     encode_predicates_in_current_doc(rbml_w, ecx, predicates);
725
726     rbml_w.end_tag();
727 }
728
729 fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
730                                              ecx: &EncodeContext<'a,'tcx>,
731                                              predicates: &ty::GenericPredicates<'tcx>)
732 {
733     let ty_str_ctxt = &tyencode::ctxt {
734         diag: ecx.diag,
735         ds: def_to_string,
736         tcx: ecx.tcx,
737         abbrevs: &ecx.type_abbrevs
738     };
739
740     for (space, _, predicate) in predicates.predicates.iter_enumerated() {
741         rbml_w.start_tag(tag_predicate);
742
743         rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
744
745         rbml_w.start_tag(tag_predicate_data);
746         tyencode::enc_predicate(rbml_w, ty_str_ctxt, predicate);
747         rbml_w.end_tag();
748
749         rbml_w.end_tag();
750     }
751 }
752
753 fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
754                               ecx: &EncodeContext<'a,'tcx>,
755                               predicates: &ty::GenericPredicates<'tcx>,
756                               tag: usize)
757 {
758     rbml_w.start_tag(tag);
759     encode_predicates_in_current_doc(rbml_w, ecx, predicates);
760     rbml_w.end_tag();
761 }
762
763 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
764                                      rbml_w: &mut Encoder,
765                                      method_ty: &ty::Method<'tcx>) {
766     encode_def_id(rbml_w, method_ty.def_id);
767     encode_name(rbml_w, method_ty.name);
768     encode_generics(rbml_w, ecx, &method_ty.generics, &method_ty.predicates,
769                     tag_method_ty_generics);
770     encode_method_fty(ecx, rbml_w, &method_ty.fty);
771     encode_visibility(rbml_w, method_ty.vis);
772     encode_explicit_self(rbml_w, &method_ty.explicit_self);
773     match method_ty.explicit_self {
774         ty::StaticExplicitSelfCategory => {
775             encode_family(rbml_w, STATIC_METHOD_FAMILY);
776         }
777         _ => encode_family(rbml_w, METHOD_FAMILY)
778     }
779     encode_provided_source(rbml_w, method_ty.provided_source);
780 }
781
782 fn encode_info_for_associated_const(ecx: &EncodeContext,
783                                     rbml_w: &mut Encoder,
784                                     associated_const: &ty::AssociatedConst,
785                                     impl_path: PathElems,
786                                     parent_id: NodeId,
787                                     impl_item_opt: Option<&hir::ImplItem>) {
788     debug!("encode_info_for_associated_const({:?},{:?})",
789            associated_const.def_id,
790            associated_const.name);
791
792     rbml_w.start_tag(tag_items_data_item);
793
794     encode_def_id(rbml_w, associated_const.def_id);
795     encode_name(rbml_w, associated_const.name);
796     encode_visibility(rbml_w, associated_const.vis);
797     encode_family(rbml_w, 'C');
798     encode_provided_source(rbml_w, associated_const.default);
799
800     encode_parent_item(rbml_w, DefId::local(parent_id));
801     encode_item_sort(rbml_w, 'C');
802
803     encode_bounds_and_type_for_item(rbml_w, ecx, associated_const.def_id.local_id());
804
805     let stab = stability::lookup(ecx.tcx, associated_const.def_id);
806     encode_stability(rbml_w, stab);
807
808     let elem = ast_map::PathName(associated_const.name);
809     encode_path(rbml_w, impl_path.chain(Some(elem)));
810
811     if let Some(ii) = impl_item_opt {
812         encode_attributes(rbml_w, &ii.attrs);
813         encode_inlined_item(ecx, rbml_w, InlinedItemRef::ImplItem(DefId::local(parent_id), ii));
814     }
815
816     rbml_w.end_tag();
817 }
818
819 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
820                                     rbml_w: &mut Encoder,
821                                     m: &ty::Method<'tcx>,
822                                     impl_path: PathElems,
823                                     is_default_impl: bool,
824                                     parent_id: NodeId,
825                                     impl_item_opt: Option<&hir::ImplItem>) {
826
827     debug!("encode_info_for_method: {:?} {:?}", m.def_id,
828            m.name);
829     rbml_w.start_tag(tag_items_data_item);
830
831     encode_method_ty_fields(ecx, rbml_w, m);
832     encode_parent_item(rbml_w, DefId::local(parent_id));
833     encode_item_sort(rbml_w, 'r');
834
835     let stab = stability::lookup(ecx.tcx, m.def_id);
836     encode_stability(rbml_w, stab);
837
838     // The type for methods gets encoded twice, which is unfortunate.
839     encode_bounds_and_type_for_item(rbml_w, ecx, m.def_id.local_id());
840
841     let elem = ast_map::PathName(m.name);
842     encode_path(rbml_w, impl_path.chain(Some(elem)));
843     if let Some(impl_item) = impl_item_opt {
844         if let hir::MethodImplItem(ref sig, _) = impl_item.node {
845             encode_attributes(rbml_w, &impl_item.attrs);
846             let scheme = ecx.tcx.lookup_item_type(m.def_id);
847             let any_types = !scheme.generics.types.is_empty();
848             let needs_inline = any_types || is_default_impl ||
849                                attr::requests_inline(&impl_item.attrs);
850             if needs_inline || sig.constness == hir::Constness::Const {
851                 encode_inlined_item(ecx, rbml_w, InlinedItemRef::ImplItem(DefId::local(parent_id),
852                                                                impl_item));
853             }
854             encode_constness(rbml_w, sig.constness);
855             if !any_types {
856                 encode_symbol(ecx, rbml_w, m.def_id.node);
857             }
858             encode_method_argument_names(rbml_w, &sig.decl);
859         }
860     }
861
862     rbml_w.end_tag();
863 }
864
865 fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
866                                              rbml_w: &mut Encoder,
867                                              associated_type: &ty::AssociatedType<'tcx>,
868                                              impl_path: PathElems,
869                                              parent_id: NodeId,
870                                              impl_item_opt: Option<&hir::ImplItem>) {
871     debug!("encode_info_for_associated_type({:?},{:?})",
872            associated_type.def_id,
873            associated_type.name);
874
875     rbml_w.start_tag(tag_items_data_item);
876
877     encode_def_id(rbml_w, associated_type.def_id);
878     encode_name(rbml_w, associated_type.name);
879     encode_visibility(rbml_w, associated_type.vis);
880     encode_family(rbml_w, 'y');
881     encode_parent_item(rbml_w, DefId::local(parent_id));
882     encode_item_sort(rbml_w, 't');
883
884     let stab = stability::lookup(ecx.tcx, associated_type.def_id);
885     encode_stability(rbml_w, stab);
886
887     let elem = ast_map::PathName(associated_type.name);
888     encode_path(rbml_w, impl_path.chain(Some(elem)));
889
890     if let Some(ii) = impl_item_opt {
891         encode_attributes(rbml_w, &ii.attrs);
892     } else {
893         encode_predicates(rbml_w, ecx,
894                           &ecx.tcx.lookup_predicates(associated_type.def_id),
895                           tag_item_generics);
896     }
897
898     if let Some(ty) = associated_type.ty {
899         encode_type(ecx, rbml_w, ty);
900     }
901
902     rbml_w.end_tag();
903 }
904
905 fn encode_method_argument_names(rbml_w: &mut Encoder,
906                                 decl: &hir::FnDecl) {
907     rbml_w.start_tag(tag_method_argument_names);
908     for arg in &decl.inputs {
909         let tag = tag_method_argument_name;
910         if let hir::PatIdent(_, ref path1, _) = arg.pat.node {
911             let name = path1.node.name.as_str();
912             rbml_w.wr_tagged_bytes(tag, name.as_bytes());
913         } else {
914             rbml_w.wr_tagged_bytes(tag, &[]);
915         }
916     }
917     rbml_w.end_tag();
918 }
919
920 fn encode_repr_attrs(rbml_w: &mut Encoder,
921                      ecx: &EncodeContext,
922                      attrs: &[ast::Attribute]) {
923     let mut repr_attrs = Vec::new();
924     for attr in attrs {
925         repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
926                                                 attr));
927     }
928     rbml_w.start_tag(tag_items_data_item_repr);
929     repr_attrs.encode(rbml_w);
930     rbml_w.end_tag();
931 }
932
933 fn encode_inlined_item(ecx: &EncodeContext,
934                        rbml_w: &mut Encoder,
935                        ii: InlinedItemRef) {
936     let mut eii = ecx.encode_inlined_item.borrow_mut();
937     let eii: &mut EncodeInlinedItem = &mut *eii;
938     eii(ecx, rbml_w, ii)
939 }
940
941 const FN_FAMILY: char = 'f';
942 const STATIC_METHOD_FAMILY: char = 'F';
943 const METHOD_FAMILY: char = 'h';
944
945 // Encodes the inherent implementations of a structure, enumeration, or trait.
946 fn encode_inherent_implementations(ecx: &EncodeContext,
947                                    rbml_w: &mut Encoder,
948                                    def_id: DefId) {
949     match ecx.tcx.inherent_impls.borrow().get(&def_id) {
950         None => {}
951         Some(implementations) => {
952             for &impl_def_id in implementations.iter() {
953                 rbml_w.start_tag(tag_items_data_item_inherent_impl);
954                 encode_def_id(rbml_w, impl_def_id);
955                 rbml_w.end_tag();
956             }
957         }
958     }
959 }
960
961 // Encodes the implementations of a trait defined in this crate.
962 fn encode_extension_implementations(ecx: &EncodeContext,
963                                     rbml_w: &mut Encoder,
964                                     trait_def_id: DefId) {
965     assert!(trait_def_id.is_local());
966     let def = ecx.tcx.lookup_trait_def(trait_def_id);
967
968     def.for_each_impl(ecx.tcx, |impl_def_id| {
969         rbml_w.start_tag(tag_items_data_item_extension_impl);
970         encode_def_id(rbml_w, impl_def_id);
971         rbml_w.end_tag();
972     });
973 }
974
975 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
976     stab_opt.map(|stab| {
977         rbml_w.start_tag(tag_items_data_item_stability);
978         stab.encode(rbml_w).unwrap();
979         rbml_w.end_tag();
980     });
981 }
982
983 fn encode_info_for_item(ecx: &EncodeContext,
984                         rbml_w: &mut Encoder,
985                         item: &hir::Item,
986                         index: &mut Vec<IndexEntry>,
987                         path: PathElems,
988                         vis: hir::Visibility) {
989     let tcx = ecx.tcx;
990
991     fn add_to_index(item: &hir::Item, rbml_w: &mut Encoder,
992                     index: &mut Vec<IndexEntry>) {
993         index.push(IndexEntry {
994             node: item.id,
995             pos: rbml_w.mark_stable_position(),
996         });
997     }
998
999     debug!("encoding info for item at {}",
1000            tcx.sess.codemap().span_to_string(item.span));
1001
1002     let def_id = DefId::local(item.id);
1003     let stab = stability::lookup(tcx, DefId::local(item.id));
1004
1005     match item.node {
1006       hir::ItemStatic(_, m, _) => {
1007         add_to_index(item, rbml_w, index);
1008         rbml_w.start_tag(tag_items_data_item);
1009         encode_def_id(rbml_w, def_id);
1010         if m == hir::MutMutable {
1011             encode_family(rbml_w, 'b');
1012         } else {
1013             encode_family(rbml_w, 'c');
1014         }
1015         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1016         encode_symbol(ecx, rbml_w, item.id);
1017         encode_name(rbml_w, item.name);
1018         encode_path(rbml_w, path);
1019         encode_visibility(rbml_w, vis);
1020         encode_stability(rbml_w, stab);
1021         encode_attributes(rbml_w, &item.attrs);
1022         rbml_w.end_tag();
1023       }
1024       hir::ItemConst(_, _) => {
1025         add_to_index(item, rbml_w, index);
1026         rbml_w.start_tag(tag_items_data_item);
1027         encode_def_id(rbml_w, def_id);
1028         encode_family(rbml_w, 'C');
1029         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1030         encode_name(rbml_w, item.name);
1031         encode_path(rbml_w, path);
1032         encode_attributes(rbml_w, &item.attrs);
1033         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1034         encode_visibility(rbml_w, vis);
1035         encode_stability(rbml_w, stab);
1036         rbml_w.end_tag();
1037       }
1038       hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
1039         add_to_index(item, rbml_w, index);
1040         rbml_w.start_tag(tag_items_data_item);
1041         encode_def_id(rbml_w, def_id);
1042         encode_family(rbml_w, FN_FAMILY);
1043         let tps_len = generics.ty_params.len();
1044         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1045         encode_name(rbml_w, item.name);
1046         encode_path(rbml_w, path);
1047         encode_attributes(rbml_w, &item.attrs);
1048         let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
1049         if needs_inline || constness == hir::Constness::Const {
1050             encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1051         }
1052         if tps_len == 0 {
1053             encode_symbol(ecx, rbml_w, item.id);
1054         }
1055         encode_constness(rbml_w, constness);
1056         encode_visibility(rbml_w, vis);
1057         encode_stability(rbml_w, stab);
1058         encode_method_argument_names(rbml_w, &**decl);
1059         rbml_w.end_tag();
1060       }
1061       hir::ItemMod(ref m) => {
1062         add_to_index(item, rbml_w, index);
1063         encode_info_for_mod(ecx,
1064                             rbml_w,
1065                             m,
1066                             &item.attrs,
1067                             item.id,
1068                             path,
1069                             item.name,
1070                             item.vis);
1071       }
1072       hir::ItemForeignMod(ref fm) => {
1073         add_to_index(item, rbml_w, index);
1074         rbml_w.start_tag(tag_items_data_item);
1075         encode_def_id(rbml_w, def_id);
1076         encode_family(rbml_w, 'n');
1077         encode_name(rbml_w, item.name);
1078         encode_path(rbml_w, path);
1079
1080         // Encode all the items in this module.
1081         for foreign_item in &fm.items {
1082             rbml_w.wr_tagged_u64(tag_mod_child,
1083                                  def_to_u64(DefId::local(foreign_item.id)));
1084         }
1085         encode_visibility(rbml_w, vis);
1086         encode_stability(rbml_w, stab);
1087         rbml_w.end_tag();
1088       }
1089       hir::ItemTy(..) => {
1090         add_to_index(item, rbml_w, index);
1091         rbml_w.start_tag(tag_items_data_item);
1092         encode_def_id(rbml_w, def_id);
1093         encode_family(rbml_w, 'y');
1094         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1095         encode_name(rbml_w, item.name);
1096         encode_path(rbml_w, path);
1097         encode_visibility(rbml_w, vis);
1098         encode_stability(rbml_w, stab);
1099         rbml_w.end_tag();
1100       }
1101       hir::ItemEnum(ref enum_definition, _) => {
1102         add_to_index(item, rbml_w, index);
1103
1104         rbml_w.start_tag(tag_items_data_item);
1105         encode_def_id(rbml_w, def_id);
1106         encode_family(rbml_w, 't');
1107         encode_item_variances(rbml_w, ecx, item.id);
1108         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1109         encode_name(rbml_w, item.name);
1110         encode_attributes(rbml_w, &item.attrs);
1111         encode_repr_attrs(rbml_w, ecx, &item.attrs);
1112         for v in &enum_definition.variants {
1113             encode_variant_id(rbml_w, DefId::local(v.node.id));
1114         }
1115         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1116         encode_path(rbml_w, path);
1117
1118         // Encode inherent implementations for this enumeration.
1119         encode_inherent_implementations(ecx, rbml_w, def_id);
1120
1121         encode_visibility(rbml_w, vis);
1122         encode_stability(rbml_w, stab);
1123         rbml_w.end_tag();
1124
1125         encode_enum_variant_info(ecx,
1126                                  rbml_w,
1127                                  item.id,
1128                                  vis,
1129                                  index);
1130       }
1131       hir::ItemStruct(ref struct_def, _) => {
1132         let def = ecx.tcx.lookup_adt_def(def_id);
1133         let variant = def.struct_variant();
1134
1135         for field in &variant.fields {
1136             encode_field(ecx, rbml_w, field, index);
1137         }
1138
1139         /* Index the class*/
1140         add_to_index(item, rbml_w, index);
1141
1142         /* Now, make an item for the class itself */
1143         rbml_w.start_tag(tag_items_data_item);
1144         encode_def_id(rbml_w, def_id);
1145         encode_family(rbml_w, 'S');
1146         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1147
1148         encode_item_variances(rbml_w, ecx, item.id);
1149         encode_name(rbml_w, item.name);
1150         encode_attributes(rbml_w, &item.attrs);
1151         encode_path(rbml_w, path.clone());
1152         encode_stability(rbml_w, stab);
1153         encode_visibility(rbml_w, vis);
1154         encode_repr_attrs(rbml_w, ecx, &item.attrs);
1155
1156         /* Encode def_ids for each field and method
1157          for methods, write all the stuff get_trait_method
1158         needs to know*/
1159         encode_struct_fields(rbml_w, variant, def_id);
1160
1161         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1162
1163         // Encode inherent implementations for this structure.
1164         encode_inherent_implementations(ecx, rbml_w, def_id);
1165
1166         rbml_w.end_tag();
1167
1168         // If this is a tuple-like struct, encode the type of the constructor.
1169         match struct_def.ctor_id {
1170             Some(ctor_id) => {
1171                 encode_info_for_struct_ctor(ecx, rbml_w, item.name,
1172                                             ctor_id, index, def_id.node);
1173             }
1174             None => {}
1175         }
1176       }
1177       hir::ItemDefaultImpl(unsafety, _) => {
1178           add_to_index(item, rbml_w, index);
1179           rbml_w.start_tag(tag_items_data_item);
1180           encode_def_id(rbml_w, def_id);
1181           encode_family(rbml_w, 'd');
1182           encode_name(rbml_w, item.name);
1183           encode_unsafety(rbml_w, unsafety);
1184
1185           let trait_ref = tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
1186           encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1187           rbml_w.end_tag();
1188       }
1189       hir::ItemImpl(unsafety, polarity, _, _, ref ty, ref ast_items) => {
1190         // We need to encode information about the default methods we
1191         // have inherited, so we drive this based on the impl structure.
1192         let impl_items = tcx.impl_items.borrow();
1193         let items = impl_items.get(&def_id).unwrap();
1194
1195         add_to_index(item, rbml_w, index);
1196         rbml_w.start_tag(tag_items_data_item);
1197         encode_def_id(rbml_w, def_id);
1198         encode_family(rbml_w, 'i');
1199         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1200         encode_name(rbml_w, item.name);
1201         encode_attributes(rbml_w, &item.attrs);
1202         encode_unsafety(rbml_w, unsafety);
1203         encode_polarity(rbml_w, polarity);
1204
1205         match tcx.custom_coerce_unsized_kinds.borrow().get(&DefId::local(item.id)) {
1206             Some(&kind) => {
1207                 rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1208                 kind.encode(rbml_w);
1209                 rbml_w.end_tag();
1210             }
1211             None => {}
1212         }
1213
1214         match ty.node {
1215             hir::TyPath(None, ref path) if path.segments.len() == 1 => {
1216                 let name = path.segments.last().unwrap().identifier.name;
1217                 encode_impl_type_basename(rbml_w, name);
1218             }
1219             _ => {}
1220         }
1221         for &item_def_id in items {
1222             rbml_w.start_tag(tag_item_impl_item);
1223             match item_def_id {
1224                 ty::ConstTraitItemId(item_def_id) => {
1225                     encode_def_id(rbml_w, item_def_id);
1226                     encode_item_sort(rbml_w, 'C');
1227                 }
1228                 ty::MethodTraitItemId(item_def_id) => {
1229                     encode_def_id(rbml_w, item_def_id);
1230                     encode_item_sort(rbml_w, 'r');
1231                 }
1232                 ty::TypeTraitItemId(item_def_id) => {
1233                     encode_def_id(rbml_w, item_def_id);
1234                     encode_item_sort(rbml_w, 't');
1235                 }
1236             }
1237             rbml_w.end_tag();
1238         }
1239         if let Some(trait_ref) = tcx.impl_trait_ref(DefId::local(item.id)) {
1240             encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1241         }
1242         encode_path(rbml_w, path.clone());
1243         encode_stability(rbml_w, stab);
1244         rbml_w.end_tag();
1245
1246         // Iterate down the trait items, emitting them. We rely on the
1247         // assumption that all of the actually implemented trait items
1248         // appear first in the impl structure, in the same order they do
1249         // in the ast. This is a little sketchy.
1250         let num_implemented_methods = ast_items.len();
1251         for (i, &trait_item_def_id) in items.iter().enumerate() {
1252             let ast_item = if i < num_implemented_methods {
1253                 Some(&*ast_items[i])
1254             } else {
1255                 None
1256             };
1257
1258             index.push(IndexEntry {
1259                 node: trait_item_def_id.def_id().node,
1260                 pos: rbml_w.mark_stable_position(),
1261             });
1262
1263             match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
1264                 ty::ConstTraitItem(ref associated_const) => {
1265                     encode_info_for_associated_const(ecx,
1266                                                      rbml_w,
1267                                                      &*associated_const,
1268                                                      path.clone(),
1269                                                      item.id,
1270                                                      ast_item)
1271                 }
1272                 ty::MethodTraitItem(ref method_type) => {
1273                     encode_info_for_method(ecx,
1274                                            rbml_w,
1275                                            &**method_type,
1276                                            path.clone(),
1277                                            false,
1278                                            item.id,
1279                                            ast_item)
1280                 }
1281                 ty::TypeTraitItem(ref associated_type) => {
1282                     encode_info_for_associated_type(ecx,
1283                                                     rbml_w,
1284                                                     &**associated_type,
1285                                                     path.clone(),
1286                                                     item.id,
1287                                                     ast_item)
1288                 }
1289             }
1290         }
1291       }
1292       hir::ItemTrait(_, _, _, ref ms) => {
1293         add_to_index(item, rbml_w, index);
1294         rbml_w.start_tag(tag_items_data_item);
1295         encode_def_id(rbml_w, def_id);
1296         encode_family(rbml_w, 'I');
1297         encode_item_variances(rbml_w, ecx, item.id);
1298         let trait_def = tcx.lookup_trait_def(def_id);
1299         let trait_predicates = tcx.lookup_predicates(def_id);
1300         encode_unsafety(rbml_w, trait_def.unsafety);
1301         encode_paren_sugar(rbml_w, trait_def.paren_sugar);
1302         encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
1303         encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
1304         encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates,
1305                         tag_item_generics);
1306         encode_predicates(rbml_w, ecx, &tcx.lookup_super_predicates(def_id),
1307                           tag_item_super_predicates);
1308         encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1309         encode_name(rbml_w, item.name);
1310         encode_attributes(rbml_w, &item.attrs);
1311         encode_visibility(rbml_w, vis);
1312         encode_stability(rbml_w, stab);
1313         for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
1314             rbml_w.start_tag(tag_item_trait_item);
1315             match method_def_id {
1316                 ty::ConstTraitItemId(const_def_id) => {
1317                     encode_def_id(rbml_w, const_def_id);
1318                     encode_item_sort(rbml_w, 'C');
1319                 }
1320                 ty::MethodTraitItemId(method_def_id) => {
1321                     encode_def_id(rbml_w, method_def_id);
1322                     encode_item_sort(rbml_w, 'r');
1323                 }
1324                 ty::TypeTraitItemId(type_def_id) => {
1325                     encode_def_id(rbml_w, type_def_id);
1326                     encode_item_sort(rbml_w, 't');
1327                 }
1328             }
1329             rbml_w.end_tag();
1330
1331             rbml_w.wr_tagged_u64(tag_mod_child,
1332                                  def_to_u64(method_def_id.def_id()));
1333         }
1334         encode_path(rbml_w, path.clone());
1335
1336         // Encode the implementations of this trait.
1337         encode_extension_implementations(ecx, rbml_w, def_id);
1338
1339         // Encode inherent implementations for this trait.
1340         encode_inherent_implementations(ecx, rbml_w, def_id);
1341
1342         rbml_w.end_tag();
1343
1344         // Now output the trait item info for each trait item.
1345         let r = tcx.trait_item_def_ids(def_id);
1346         for (i, &item_def_id) in r.iter().enumerate() {
1347             assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
1348
1349             index.push(IndexEntry {
1350                 node: item_def_id.def_id().node,
1351                 pos: rbml_w.mark_stable_position(),
1352             });
1353
1354             rbml_w.start_tag(tag_items_data_item);
1355
1356             encode_parent_item(rbml_w, def_id);
1357
1358             let stab = stability::lookup(tcx, item_def_id.def_id());
1359             encode_stability(rbml_w, stab);
1360
1361             let trait_item_type =
1362                 tcx.impl_or_trait_item(item_def_id.def_id());
1363             let is_nonstatic_method;
1364             match trait_item_type {
1365                 ty::ConstTraitItem(associated_const) => {
1366                     encode_name(rbml_w, associated_const.name);
1367                     encode_def_id(rbml_w, associated_const.def_id);
1368                     encode_visibility(rbml_w, associated_const.vis);
1369
1370                     encode_provided_source(rbml_w, associated_const.default);
1371
1372                     let elem = ast_map::PathName(associated_const.name);
1373                     encode_path(rbml_w,
1374                                 path.clone().chain(Some(elem)));
1375
1376                     encode_item_sort(rbml_w, 'C');
1377                     encode_family(rbml_w, 'C');
1378
1379                     encode_bounds_and_type_for_item(rbml_w, ecx,
1380                                                     associated_const.def_id.local_id());
1381
1382                     is_nonstatic_method = false;
1383                 }
1384                 ty::MethodTraitItem(method_ty) => {
1385                     let method_def_id = item_def_id.def_id();
1386
1387                     encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1388
1389                     let elem = ast_map::PathName(method_ty.name);
1390                     encode_path(rbml_w,
1391                                 path.clone().chain(Some(elem)));
1392
1393                     match method_ty.explicit_self {
1394                         ty::StaticExplicitSelfCategory => {
1395                             encode_family(rbml_w,
1396                                           STATIC_METHOD_FAMILY);
1397                         }
1398                         _ => {
1399                             encode_family(rbml_w,
1400                                           METHOD_FAMILY);
1401                         }
1402                     }
1403                     encode_bounds_and_type_for_item(rbml_w, ecx, method_def_id.local_id());
1404
1405                     is_nonstatic_method = method_ty.explicit_self !=
1406                         ty::StaticExplicitSelfCategory;
1407                 }
1408                 ty::TypeTraitItem(associated_type) => {
1409                     encode_name(rbml_w, associated_type.name);
1410                     encode_def_id(rbml_w, associated_type.def_id);
1411
1412                     let elem = ast_map::PathName(associated_type.name);
1413                     encode_path(rbml_w,
1414                                 path.clone().chain(Some(elem)));
1415
1416                     encode_item_sort(rbml_w, 't');
1417                     encode_family(rbml_w, 'y');
1418
1419                     if let Some(ty) = associated_type.ty {
1420                         encode_type(ecx, rbml_w, ty);
1421                     }
1422
1423                     is_nonstatic_method = false;
1424                 }
1425             }
1426
1427             encode_parent_sort(rbml_w, 't');
1428
1429             let trait_item = &*ms[i];
1430             encode_attributes(rbml_w, &trait_item.attrs);
1431             match trait_item.node {
1432                 hir::ConstTraitItem(_, _) => {
1433                     encode_inlined_item(ecx, rbml_w,
1434                                         InlinedItemRef::TraitItem(def_id, trait_item));
1435                 }
1436                 hir::MethodTraitItem(ref sig, ref body) => {
1437                     // If this is a static method, we've already
1438                     // encoded this.
1439                     if is_nonstatic_method {
1440                         // FIXME: I feel like there is something funny
1441                         // going on.
1442                         encode_bounds_and_type_for_item(rbml_w, ecx,
1443                             item_def_id.def_id().local_id());
1444                     }
1445
1446                     if body.is_some() {
1447                         encode_item_sort(rbml_w, 'p');
1448                         encode_inlined_item(ecx, rbml_w,
1449                                             InlinedItemRef::TraitItem(def_id, trait_item));
1450                     } else {
1451                         encode_item_sort(rbml_w, 'r');
1452                     }
1453                     encode_method_argument_names(rbml_w, &sig.decl);
1454                 }
1455
1456                 hir::TypeTraitItem(..) => {}
1457             }
1458
1459             rbml_w.end_tag();
1460         }
1461       }
1462       hir::ItemExternCrate(_) | hir::ItemUse(_) => {
1463         // these are encoded separately
1464       }
1465     }
1466 }
1467
1468 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1469                                 rbml_w: &mut Encoder,
1470                                 nitem: &hir::ForeignItem,
1471                                 index: &mut Vec<IndexEntry>,
1472                                 path: PathElems,
1473                                 abi: abi::Abi) {
1474     index.push(IndexEntry {
1475         node: nitem.id,
1476         pos: rbml_w.mark_stable_position(),
1477     });
1478
1479     rbml_w.start_tag(tag_items_data_item);
1480     encode_def_id(rbml_w, DefId::local(nitem.id));
1481     encode_visibility(rbml_w, nitem.vis);
1482     match nitem.node {
1483       hir::ForeignItemFn(ref fndecl, _) => {
1484         encode_family(rbml_w, FN_FAMILY);
1485         encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
1486         encode_name(rbml_w, nitem.name);
1487         if abi == abi::RustIntrinsic || abi == abi::PlatformIntrinsic {
1488             encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
1489         }
1490         encode_attributes(rbml_w, &*nitem.attrs);
1491         let stab = stability::lookup(ecx.tcx, DefId::local(nitem.id));
1492         encode_stability(rbml_w, stab);
1493         encode_symbol(ecx, rbml_w, nitem.id);
1494         encode_method_argument_names(rbml_w, &*fndecl);
1495       }
1496       hir::ForeignItemStatic(_, mutbl) => {
1497         if mutbl {
1498             encode_family(rbml_w, 'b');
1499         } else {
1500             encode_family(rbml_w, 'c');
1501         }
1502         encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
1503         encode_attributes(rbml_w, &*nitem.attrs);
1504         let stab = stability::lookup(ecx.tcx, DefId::local(nitem.id));
1505         encode_stability(rbml_w, stab);
1506         encode_symbol(ecx, rbml_w, nitem.id);
1507         encode_name(rbml_w, nitem.name);
1508       }
1509     }
1510     encode_path(rbml_w, path);
1511     rbml_w.end_tag();
1512 }
1513
1514 fn my_visit_expr(_e: &hir::Expr) { }
1515
1516 fn my_visit_item(i: &hir::Item,
1517                  rbml_w: &mut Encoder,
1518                  ecx: &EncodeContext,
1519                  index: &mut Vec<IndexEntry>) {
1520     ecx.tcx.map.with_path(i.id, |path| {
1521         encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1522     });
1523 }
1524
1525 fn my_visit_foreign_item(ni: &hir::ForeignItem,
1526                          rbml_w: &mut Encoder,
1527                          ecx: &EncodeContext,
1528                          index: &mut Vec<IndexEntry>) {
1529     debug!("writing foreign item {}::{}",
1530             ecx.tcx.map.path_to_string(ni.id),
1531             ni.name);
1532
1533     let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1534     ecx.tcx.map.with_path(ni.id, |path| {
1535         encode_info_for_foreign_item(ecx, rbml_w,
1536                                      ni, index,
1537                                      path, abi);
1538     });
1539 }
1540
1541 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1542     rbml_w_for_visit_item: &'a mut Encoder<'b>,
1543     ecx: &'a EncodeContext<'c,'tcx>,
1544     index: &'a mut Vec<IndexEntry>,
1545 }
1546
1547 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1548     fn visit_expr(&mut self, ex: &hir::Expr) {
1549         visit::walk_expr(self, ex);
1550         my_visit_expr(ex);
1551     }
1552     fn visit_item(&mut self, i: &hir::Item) {
1553         visit::walk_item(self, i);
1554         my_visit_item(i,
1555                       self.rbml_w_for_visit_item,
1556                       self.ecx,
1557                       self.index);
1558     }
1559     fn visit_foreign_item(&mut self, ni: &hir::ForeignItem) {
1560         visit::walk_foreign_item(self, ni);
1561         my_visit_foreign_item(ni,
1562                               self.rbml_w_for_visit_item,
1563                               self.ecx,
1564                               self.index);
1565     }
1566 }
1567
1568 fn encode_info_for_items(ecx: &EncodeContext,
1569                          rbml_w: &mut Encoder,
1570                          krate: &hir::Crate)
1571                          -> Vec<IndexEntry> {
1572     let mut index = Vec::new();
1573     rbml_w.start_tag(tag_items_data);
1574     index.push(IndexEntry {
1575         node: CRATE_NODE_ID,
1576         pos: rbml_w.mark_stable_position(),
1577     });
1578     encode_info_for_mod(ecx,
1579                         rbml_w,
1580                         &krate.module,
1581                         &[],
1582                         CRATE_NODE_ID,
1583                         [].iter().cloned().chain(LinkedPath::empty()),
1584                         syntax::parse::token::special_idents::invalid.name,
1585                         hir::Public);
1586
1587     visit::walk_crate(&mut EncodeVisitor {
1588         index: &mut index,
1589         ecx: ecx,
1590         rbml_w_for_visit_item: &mut *rbml_w,
1591     }, krate);
1592
1593     rbml_w.end_tag();
1594     index
1595 }
1596
1597
1598
1599
1600 fn encode_index(rbml_w: &mut Encoder, index: Vec<IndexEntry>)
1601 {
1602     rbml_w.start_tag(tag_index);
1603     index::write_index(index, rbml_w.writer);
1604     rbml_w.end_tag();
1605 }
1606
1607 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1608     match mi.node {
1609       ast::MetaWord(ref name) => {
1610         rbml_w.start_tag(tag_meta_item_word);
1611         rbml_w.wr_tagged_str(tag_meta_item_name, name);
1612         rbml_w.end_tag();
1613       }
1614       ast::MetaNameValue(ref name, ref value) => {
1615         match value.node {
1616           ast::LitStr(ref value, _) => {
1617             rbml_w.start_tag(tag_meta_item_name_value);
1618             rbml_w.wr_tagged_str(tag_meta_item_name, name);
1619             rbml_w.wr_tagged_str(tag_meta_item_value, value);
1620             rbml_w.end_tag();
1621           }
1622           _ => {/* FIXME (#623): encode other variants */ }
1623         }
1624       }
1625       ast::MetaList(ref name, ref items) => {
1626         rbml_w.start_tag(tag_meta_item_list);
1627         rbml_w.wr_tagged_str(tag_meta_item_name, name);
1628         for inner_item in items {
1629             encode_meta_item(rbml_w, &**inner_item);
1630         }
1631         rbml_w.end_tag();
1632       }
1633     }
1634 }
1635
1636 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1637     rbml_w.start_tag(tag_attributes);
1638     for attr in attrs {
1639         rbml_w.start_tag(tag_attribute);
1640         rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1641         encode_meta_item(rbml_w, &*attr.node.value);
1642         rbml_w.end_tag();
1643     }
1644     rbml_w.end_tag();
1645 }
1646
1647 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: hir::Unsafety) {
1648     let byte: u8 = match unsafety {
1649         hir::Unsafety::Normal => 0,
1650         hir::Unsafety::Unsafe => 1,
1651     };
1652     rbml_w.wr_tagged_u8(tag_unsafety, byte);
1653 }
1654
1655 fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) {
1656     let byte: u8 = if paren_sugar {1} else {0};
1657     rbml_w.wr_tagged_u8(tag_paren_sugar, byte);
1658 }
1659
1660 fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) {
1661     let byte: u8 = if is_defaulted {1} else {0};
1662     rbml_w.wr_tagged_u8(tag_defaulted_trait, byte);
1663 }
1664
1665 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) {
1666     rbml_w.start_tag(tag_associated_type_names);
1667     for &name in names {
1668         rbml_w.wr_tagged_str(tag_associated_type_name, &name.as_str());
1669     }
1670     rbml_w.end_tag();
1671 }
1672
1673 fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
1674     let byte: u8 = match polarity {
1675         hir::ImplPolarity::Positive => 0,
1676         hir::ImplPolarity::Negative => 1,
1677     };
1678     rbml_w.wr_tagged_u8(tag_polarity, byte);
1679 }
1680
1681 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1682     fn get_ordered_deps(cstore: &cstore::CStore)
1683                         -> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
1684         // Pull the cnums and name,vers,hash out of cstore
1685         let mut deps = Vec::new();
1686         cstore.iter_crate_data(|cnum, val| {
1687             deps.push((cnum, val.clone()));
1688         });
1689
1690         // Sort by cnum
1691         deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0));
1692
1693         // Sanity-check the crate numbers
1694         let mut expected_cnum = 1;
1695         for &(n, _) in &deps {
1696             assert_eq!(n, expected_cnum);
1697             expected_cnum += 1;
1698         }
1699
1700         deps
1701     }
1702
1703     // We're just going to write a list of crate 'name-hash-version's, with
1704     // the assumption that they are numbered 1 to n.
1705     // FIXME (#2166): This is not nearly enough to support correct versioning
1706     // but is enough to get transitive crate dependencies working.
1707     rbml_w.start_tag(tag_crate_deps);
1708     for (_cnum, dep) in get_ordered_deps(cstore) {
1709         encode_crate_dep(rbml_w, &dep);
1710     }
1711     rbml_w.end_tag();
1712 }
1713
1714 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1715     rbml_w.start_tag(tag_lang_items);
1716
1717     for (i, &def_id) in ecx.tcx.lang_items.items() {
1718         if let Some(id) = def_id {
1719             if id.is_local() {
1720                 rbml_w.start_tag(tag_lang_items_item);
1721                 rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
1722                 rbml_w.wr_tagged_u32(tag_lang_items_item_node_id, id.node as u32);
1723                 rbml_w.end_tag();
1724             }
1725         }
1726     }
1727
1728     for i in &ecx.tcx.lang_items.missing {
1729         rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1730     }
1731
1732     rbml_w.end_tag();   // tag_lang_items
1733 }
1734
1735 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1736     rbml_w.start_tag(tag_native_libraries);
1737
1738     for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1739                                .borrow().iter() {
1740         match kind {
1741             cstore::NativeStatic => {} // these libraries are not propagated
1742             cstore::NativeFramework | cstore::NativeUnknown => {
1743                 rbml_w.start_tag(tag_native_libraries_lib);
1744                 rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32);
1745                 rbml_w.wr_tagged_str(tag_native_libraries_name, lib);
1746                 rbml_w.end_tag();
1747             }
1748         }
1749     }
1750
1751     rbml_w.end_tag();
1752 }
1753
1754 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1755     match ecx.tcx.sess.plugin_registrar_fn.get() {
1756         Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1757         None => {}
1758     }
1759 }
1760
1761 fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1762     rbml_w.start_tag(tag_codemap);
1763     let codemap = ecx.tcx.sess.codemap();
1764
1765     for filemap in &codemap.files.borrow()[..] {
1766
1767         if filemap.lines.borrow().is_empty() || filemap.is_imported() {
1768             // No need to export empty filemaps, as they can't contain spans
1769             // that need translation.
1770             // Also no need to re-export imported filemaps, as any downstream
1771             // crate will import them from their original source.
1772             continue;
1773         }
1774
1775         rbml_w.start_tag(tag_codemap_filemap);
1776         filemap.encode(rbml_w);
1777         rbml_w.end_tag();
1778     }
1779
1780     rbml_w.end_tag();
1781 }
1782
1783 /// Serialize the text of the exported macros
1784 fn encode_macro_defs(rbml_w: &mut Encoder,
1785                      krate: &hir::Crate) {
1786     rbml_w.start_tag(tag_macro_defs);
1787     for def in &krate.exported_macros {
1788         rbml_w.start_tag(tag_macro_def);
1789
1790         encode_name(rbml_w, def.name);
1791         encode_attributes(rbml_w, &def.attrs);
1792
1793         rbml_w.wr_tagged_str(tag_macro_def_body,
1794                              &::syntax::print::pprust::tts_to_string(&def.body));
1795
1796         rbml_w.end_tag();
1797     }
1798     rbml_w.end_tag();
1799 }
1800
1801 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &hir::Crate) {
1802     struct StructFieldVisitor<'a, 'b:'a> {
1803         rbml_w: &'a mut Encoder<'b>,
1804     }
1805
1806     impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1807         fn visit_struct_field(&mut self, field: &hir::StructField) {
1808             self.rbml_w.start_tag(tag_struct_field);
1809             self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1810             encode_attributes(self.rbml_w, &field.node.attrs);
1811             self.rbml_w.end_tag();
1812         }
1813     }
1814
1815     rbml_w.start_tag(tag_struct_fields);
1816     visit::walk_crate(&mut StructFieldVisitor {
1817         rbml_w: rbml_w
1818     }, krate);
1819     rbml_w.end_tag();
1820 }
1821
1822
1823
1824 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1825     ecx: &'a EncodeContext<'b, 'tcx>,
1826     rbml_w: &'a mut Encoder<'c>,
1827 }
1828
1829 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1830     fn visit_item(&mut self, item: &hir::Item) {
1831         if let hir::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
1832             let def_id = self.ecx.tcx.def_map.borrow().get(&trait_ref.ref_id).unwrap().def_id();
1833
1834             // Load eagerly if this is an implementation of the Drop trait
1835             // or if the trait is not defined in this crate.
1836             if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1837                     def_id.krate != LOCAL_CRATE {
1838                 self.rbml_w.start_tag(tag_impls_impl);
1839                 encode_def_id(self.rbml_w, DefId::local(item.id));
1840                 self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
1841                 self.rbml_w.end_tag();
1842             }
1843         }
1844         visit::walk_item(self, item);
1845     }
1846 }
1847
1848 /// Encodes implementations that are eagerly loaded.
1849 ///
1850 /// None of this is necessary in theory; we can load all implementations
1851 /// lazily. However, in two cases the optimizations to lazily load
1852 /// implementations are not yet implemented. These two cases, which require us
1853 /// to load implementations eagerly, are:
1854 ///
1855 /// * Destructors (implementations of the Drop trait).
1856 ///
1857 /// * Implementations of traits not defined in this crate.
1858 fn encode_impls<'a>(ecx: &'a EncodeContext,
1859                     krate: &hir::Crate,
1860                     rbml_w: &'a mut Encoder) {
1861     rbml_w.start_tag(tag_impls);
1862
1863     {
1864         let mut visitor = ImplVisitor {
1865             ecx: ecx,
1866             rbml_w: rbml_w,
1867         };
1868         visit::walk_crate(&mut visitor, krate);
1869     }
1870
1871     rbml_w.end_tag();
1872 }
1873
1874 fn encode_misc_info(ecx: &EncodeContext,
1875                     krate: &hir::Crate,
1876                     rbml_w: &mut Encoder) {
1877     rbml_w.start_tag(tag_misc_info);
1878     rbml_w.start_tag(tag_misc_info_crate_items);
1879     for item in &krate.module.items {
1880         rbml_w.wr_tagged_u64(tag_mod_child,
1881                              def_to_u64(DefId::local(item.id)));
1882
1883         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1884             rbml_w.wr_tagged_u64(tag_mod_child,
1885                                  def_to_u64(DefId::local(auxiliary_node_id)));
1886             true
1887         });
1888     }
1889
1890     // Encode reexports for the root module.
1891     encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(LinkedPath::empty()));
1892
1893     rbml_w.end_tag();
1894     rbml_w.end_tag();
1895 }
1896
1897 // Encodes all reachable symbols in this crate into the metadata.
1898 //
1899 // This pass is seeded off the reachability list calculated in the
1900 // middle::reachable module but filters out items that either don't have a
1901 // symbol associated with them (they weren't translated) or if they're an FFI
1902 // definition (as that's not defined in this crate).
1903 fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1904     rbml_w.start_tag(tag_reachable_ids);
1905     for id in ecx.reachable {
1906         rbml_w.wr_tagged_u32(tag_reachable_id, *id);
1907     }
1908     rbml_w.end_tag();
1909 }
1910
1911 fn encode_crate_dep(rbml_w: &mut Encoder,
1912                     dep: &cstore::crate_metadata) {
1913     rbml_w.start_tag(tag_crate_dep);
1914     rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
1915     let hash = decoder::get_crate_hash(dep.data());
1916     rbml_w.wr_tagged_str(tag_crate_dep_hash, hash.as_str());
1917     rbml_w.wr_tagged_u8(tag_crate_dep_explicitly_linked,
1918                         dep.explicitly_linked.get() as u8);
1919     rbml_w.end_tag();
1920 }
1921
1922 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1923     rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
1924 }
1925
1926 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1927     rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
1928 }
1929
1930 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1931     rbml_w.wr_tagged_str(tag_crate_triple, triple);
1932 }
1933
1934 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
1935     let tag = tag_dylib_dependency_formats;
1936     match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1937         Some(arr) => {
1938             let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1939                 let kind = match *slot {
1940                     Linkage::NotLinked |
1941                     Linkage::IncludedFromDylib => return None,
1942                     Linkage::Dynamic => "d",
1943                     Linkage::Static => "s",
1944                 };
1945                 Some(format!("{}:{}", i + 1, kind))
1946             }).collect::<Vec<String>>();
1947             rbml_w.wr_tagged_str(tag, &s.join(","));
1948         }
1949         None => {
1950             rbml_w.wr_tagged_str(tag, "");
1951         }
1952     }
1953 }
1954
1955 // NB: Increment this as you change the metadata encoding version.
1956 #[allow(non_upper_case_globals)]
1957 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
1958
1959 pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
1960     let mut wr = Cursor::new(Vec::new());
1961     encode_metadata_inner(&mut wr, parms, krate);
1962
1963     // RBML compacts the encoded bytes whenever appropriate,
1964     // so there are some garbages left after the end of the data.
1965     let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as usize;
1966     let mut v = wr.into_inner();
1967     v.truncate(metalen);
1968     assert_eq!(v.len(), metalen);
1969
1970     // And here we run into yet another obscure archive bug: in which metadata
1971     // loaded from archives may have trailing garbage bytes. Awhile back one of
1972     // our tests was failing sporadically on the OSX 64-bit builders (both nopt
1973     // and opt) by having rbml generate an out-of-bounds panic when looking at
1974     // metadata.
1975     //
1976     // Upon investigation it turned out that the metadata file inside of an rlib
1977     // (and ar archive) was being corrupted. Some compilations would generate a
1978     // metadata file which would end in a few extra bytes, while other
1979     // compilations would not have these extra bytes appended to the end. These
1980     // extra bytes were interpreted by rbml as an extra tag, so they ended up
1981     // being interpreted causing the out-of-bounds.
1982     //
1983     // The root cause of why these extra bytes were appearing was never
1984     // discovered, and in the meantime the solution we're employing is to insert
1985     // the length of the metadata to the start of the metadata. Later on this
1986     // will allow us to slice the metadata to the precise length that we just
1987     // generated regardless of trailing bytes that end up in it.
1988     let len = v.len() as u32;
1989     v.insert(0, (len >>  0) as u8);
1990     v.insert(0, (len >>  8) as u8);
1991     v.insert(0, (len >> 16) as u8);
1992     v.insert(0, (len >> 24) as u8);
1993     return v;
1994 }
1995
1996 fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
1997                          parms: EncodeParams,
1998                          krate: &hir::Crate) {
1999     struct Stats {
2000         attr_bytes: u64,
2001         dep_bytes: u64,
2002         lang_item_bytes: u64,
2003         native_lib_bytes: u64,
2004         plugin_registrar_fn_bytes: u64,
2005         codemap_bytes: u64,
2006         macro_defs_bytes: u64,
2007         impl_bytes: u64,
2008         misc_bytes: u64,
2009         item_bytes: u64,
2010         index_bytes: u64,
2011         zero_bytes: u64,
2012         total_bytes: u64,
2013     }
2014     let mut stats = Stats {
2015         attr_bytes: 0,
2016         dep_bytes: 0,
2017         lang_item_bytes: 0,
2018         native_lib_bytes: 0,
2019         plugin_registrar_fn_bytes: 0,
2020         codemap_bytes: 0,
2021         macro_defs_bytes: 0,
2022         impl_bytes: 0,
2023         misc_bytes: 0,
2024         item_bytes: 0,
2025         index_bytes: 0,
2026         zero_bytes: 0,
2027         total_bytes: 0,
2028     };
2029     let EncodeParams {
2030         item_symbols,
2031         diag,
2032         tcx,
2033         reexports,
2034         cstore,
2035         encode_inlined_item,
2036         link_meta,
2037         reachable,
2038         ..
2039     } = parms;
2040     let ecx = EncodeContext {
2041         diag: diag,
2042         tcx: tcx,
2043         reexports: reexports,
2044         item_symbols: item_symbols,
2045         link_meta: link_meta,
2046         cstore: cstore,
2047         encode_inlined_item: RefCell::new(encode_inlined_item),
2048         type_abbrevs: RefCell::new(FnvHashMap()),
2049         reachable: reachable,
2050      };
2051
2052     let mut rbml_w = Encoder::new(wr);
2053
2054     encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
2055     encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
2056     encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2057     encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2058
2059     let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2060     encode_attributes(&mut rbml_w, &krate.attrs);
2061     stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2062
2063     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2064     encode_crate_deps(&mut rbml_w, ecx.cstore);
2065     stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2066
2067     // Encode the language items.
2068     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2069     encode_lang_items(&ecx, &mut rbml_w);
2070     stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2071
2072     // Encode the native libraries used
2073     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2074     encode_native_libraries(&ecx, &mut rbml_w);
2075     stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2076
2077     // Encode the plugin registrar function
2078     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2079     encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2080     stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2081
2082     // Encode codemap
2083     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2084     encode_codemap(&ecx, &mut rbml_w);
2085     stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2086
2087     // Encode macro definitions
2088     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2089     encode_macro_defs(&mut rbml_w, krate);
2090     stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2091
2092     // Encode the def IDs of impls, for coherence checking.
2093     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2094     encode_impls(&ecx, krate, &mut rbml_w);
2095     stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2096
2097     // Encode miscellaneous info.
2098     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2099     encode_misc_info(&ecx, krate, &mut rbml_w);
2100     encode_reachable(&ecx, &mut rbml_w);
2101     stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2102
2103     // Encode and index the items.
2104     rbml_w.start_tag(tag_items);
2105     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2106     let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2107     stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2108     rbml_w.end_tag();
2109
2110     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2111     encode_index(&mut rbml_w, items_index);
2112     stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2113
2114     encode_struct_field_attrs(&mut rbml_w, krate);
2115
2116     stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2117
2118     if tcx.sess.meta_stats() {
2119         for e in rbml_w.writer.get_ref() {
2120             if *e == 0 {
2121                 stats.zero_bytes += 1;
2122             }
2123         }
2124
2125         println!("metadata stats:");
2126         println!("       attribute bytes: {}", stats.attr_bytes);
2127         println!("             dep bytes: {}", stats.dep_bytes);
2128         println!("       lang item bytes: {}", stats.lang_item_bytes);
2129         println!("          native bytes: {}", stats.native_lib_bytes);
2130         println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2131         println!("         codemap bytes: {}", stats.codemap_bytes);
2132         println!("       macro def bytes: {}", stats.macro_defs_bytes);
2133         println!("            impl bytes: {}", stats.impl_bytes);
2134         println!("            misc bytes: {}", stats.misc_bytes);
2135         println!("            item bytes: {}", stats.item_bytes);
2136         println!("           index bytes: {}", stats.index_bytes);
2137         println!("            zero bytes: {}", stats.zero_bytes);
2138         println!("           total bytes: {}", stats.total_bytes);
2139     }
2140 }
2141
2142 // Get the encoded string for a type
2143 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2144     let mut wr = Cursor::new(Vec::new());
2145     tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
2146         diag: tcx.sess.diagnostic(),
2147         ds: def_to_string,
2148         tcx: tcx,
2149         abbrevs: &RefCell::new(FnvHashMap())
2150     }, t);
2151     String::from_utf8(wr.into_inner()).unwrap()
2152 }