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.
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.
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
16 pub use self::InlinedItemRef::*;
20 use metadata::common::*;
22 use metadata::decoder;
23 use metadata::tyencode;
24 use middle::ty::{lookup_item_type};
25 use middle::ty::{mod, Ty};
26 use middle::stability;
28 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
30 use serialize::Encodable;
31 use std::cell::RefCell;
35 use syntax::ast::{mod, DefId, NodeId};
36 use syntax::ast_map::{PathElem, PathElems};
38 use syntax::ast_util::*;
41 use syntax::attr::AttrMetaMethods;
42 use syntax::diagnostic::SpanHandler;
43 use syntax::parse::token::special_idents;
44 use syntax::parse::token;
46 use syntax::visit::Visitor;
50 use rbml::io::SeekableMemWriter;
52 /// A borrowed version of `ast::InlinedItem`.
53 pub enum InlinedItemRef<'a> {
54 IIItemRef(&'a ast::Item),
55 IITraitItemRef(DefId, &'a ast::TraitItem),
56 IIImplItemRef(DefId, &'a ast::ImplItem),
57 IIForeignRef(&'a ast::ForeignItem)
60 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
62 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
64 ii: InlinedItemRef|: 'a;
66 pub struct EncodeParams<'a, 'tcx: 'a> {
67 pub diag: &'a SpanHandler,
68 pub tcx: &'a ty::ctxt<'tcx>,
69 pub reexports2: &'a middle::resolve::ExportMap2,
70 pub item_symbols: &'a RefCell<NodeMap<String>>,
71 pub link_meta: &'a LinkMeta,
72 pub cstore: &'a cstore::CStore,
73 pub encode_inlined_item: EncodeInlinedItem<'a>,
74 pub reachable: &'a NodeSet,
77 pub struct EncodeContext<'a, 'tcx: 'a> {
78 pub diag: &'a SpanHandler,
79 pub tcx: &'a ty::ctxt<'tcx>,
80 pub reexports2: &'a middle::resolve::ExportMap2,
81 pub item_symbols: &'a RefCell<NodeMap<String>>,
82 pub link_meta: &'a LinkMeta,
83 pub cstore: &'a cstore::CStore,
84 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
85 pub type_abbrevs: tyencode::abbrev_map<'tcx>,
86 pub reachable: &'a NodeSet,
89 fn encode_name(rbml_w: &mut Encoder, name: ast::Name) {
90 rbml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
93 fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) {
94 rbml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
97 pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
98 rbml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice());
107 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
108 ecx: &EncodeContext<'a, 'tcx>,
109 trait_ref: &ty::TraitRef<'tcx>,
111 let ty_str_ctxt = &tyencode::ctxt {
115 abbrevs: &ecx.type_abbrevs
118 rbml_w.start_tag(tag);
119 tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
123 // Item info table encoding
124 fn encode_family(rbml_w: &mut Encoder, c: char) {
125 rbml_w.start_tag(tag_items_data_item_family);
126 rbml_w.writer.write(&[c as u8]);
130 pub fn def_to_string(did: DefId) -> String {
131 format!("{}:{}", did.krate, did.node)
134 fn encode_item_variances(rbml_w: &mut Encoder,
137 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
138 rbml_w.start_tag(tag_item_variances);
143 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
144 ecx: &EncodeContext<'a, 'tcx>,
145 pty: &ty::Polytype<'tcx>) {
146 encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics);
147 encode_type(ecx, rbml_w, pty.ty);
150 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
151 rbml_w.start_tag(tag_items_data_item_variant);
152 let s = def_to_string(vid);
153 rbml_w.writer.write(s.as_bytes());
156 rbml_w.start_tag(tag_mod_child);
157 rbml_w.wr_str(s.as_slice());
161 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
162 rbml_w: &mut Encoder,
163 closure_type: &ty::ClosureTy<'tcx>) {
164 let ty_str_ctxt = &tyencode::ctxt {
168 abbrevs: &ecx.type_abbrevs
170 tyencode::enc_closure_ty(rbml_w.writer, ty_str_ctxt, closure_type);
173 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
174 rbml_w: &mut Encoder,
176 let ty_str_ctxt = &tyencode::ctxt {
180 abbrevs: &ecx.type_abbrevs
182 tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ);
185 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
186 rbml_w: &mut Encoder,
187 trait_ref: &ty::TraitRef<'tcx>) {
188 let ty_str_ctxt = &tyencode::ctxt {
192 abbrevs: &ecx.type_abbrevs
194 tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
197 pub fn write_region(ecx: &EncodeContext,
198 rbml_w: &mut Encoder,
200 let ty_str_ctxt = &tyencode::ctxt {
204 abbrevs: &ecx.type_abbrevs
206 tyencode::enc_region(rbml_w.writer, ty_str_ctxt, r);
209 fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder,
210 ecx: &EncodeContext<'a, 'tcx>,
211 bounds: &ty::ParamBounds<'tcx>,
213 rbml_w.start_tag(tag);
215 let ty_str_ctxt = &tyencode::ctxt { diag: ecx.diag,
218 abbrevs: &ecx.type_abbrevs };
219 tyencode::enc_bounds(rbml_w.writer, ty_str_ctxt, bounds);
224 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
225 rbml_w: &mut Encoder,
227 rbml_w.start_tag(tag_items_data_item_type);
228 write_type(ecx, rbml_w, typ);
232 fn encode_region(ecx: &EncodeContext,
233 rbml_w: &mut Encoder,
235 rbml_w.start_tag(tag_items_data_region);
236 write_region(ecx, rbml_w, r);
240 fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
241 rbml_w: &mut Encoder,
242 typ: &ty::BareFnTy<'tcx>) {
243 rbml_w.start_tag(tag_item_method_fty);
245 let ty_str_ctxt = &tyencode::ctxt {
249 abbrevs: &ecx.type_abbrevs
251 tyencode::enc_bare_fn_ty(rbml_w.writer, ty_str_ctxt, typ);
256 fn encode_symbol(ecx: &EncodeContext,
257 rbml_w: &mut Encoder,
259 rbml_w.start_tag(tag_items_data_item_symbol);
260 match ecx.item_symbols.borrow().get(&id) {
262 debug!("encode_symbol(id={}, str={})", id, *x);
263 rbml_w.writer.write(x.as_bytes());
266 ecx.diag.handler().bug(
267 format!("encode_symbol: id not found {}", id).as_slice());
273 fn encode_disr_val(_: &EncodeContext,
274 rbml_w: &mut Encoder,
275 disr_val: ty::Disr) {
276 rbml_w.start_tag(tag_disr_val);
277 let s = disr_val.to_string();
278 rbml_w.writer.write(s.as_bytes());
282 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
283 rbml_w.start_tag(tag_items_data_parent_item);
284 let s = def_to_string(id);
285 rbml_w.writer.write(s.as_bytes());
289 fn encode_struct_fields(rbml_w: &mut Encoder,
290 fields: &[ty::field_ty],
292 for f in fields.iter() {
293 if f.name == special_idents::unnamed_field.name {
294 rbml_w.start_tag(tag_item_unnamed_field);
296 rbml_w.start_tag(tag_item_field);
297 encode_name(rbml_w, f.name);
299 encode_struct_field_family(rbml_w, f.vis);
300 encode_def_id(rbml_w, f.id);
301 rbml_w.start_tag(tag_item_field_origin);
302 let s = def_to_string(origin);
303 rbml_w.writer.write(s.as_bytes());
309 fn encode_enum_variant_info(ecx: &EncodeContext,
310 rbml_w: &mut Encoder,
312 variants: &[P<ast::Variant>],
313 index: &mut Vec<entry<i64>>) {
314 debug!("encode_enum_variant_info(id={})", id);
316 let mut disr_val = 0;
318 let vi = ty::enum_variants(ecx.tcx,
319 DefId { krate: ast::LOCAL_CRATE, node: id });
320 for variant in variants.iter() {
321 let def_id = local_def(variant.node.id);
323 val: variant.node.id as i64,
324 pos: rbml_w.writer.tell().unwrap(),
326 rbml_w.start_tag(tag_items_data_item);
327 encode_def_id(rbml_w, def_id);
328 match variant.node.kind {
329 ast::TupleVariantKind(_) => encode_family(rbml_w, 'v'),
330 ast::StructVariantKind(_) => encode_family(rbml_w, 'V')
332 encode_name(rbml_w, variant.node.name.name);
333 encode_parent_item(rbml_w, local_def(id));
334 encode_visibility(rbml_w, variant.node.vis);
335 encode_attributes(rbml_w, variant.node.attrs.as_slice());
336 encode_repr_attrs(rbml_w, ecx, variant.node.attrs.as_slice());
338 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
339 encode_stability(rbml_w, stab);
341 match variant.node.kind {
342 ast::TupleVariantKind(_) => {},
343 ast::StructVariantKind(_) => {
344 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
345 let idx = encode_info_for_struct(ecx,
349 encode_struct_fields(rbml_w, fields.as_slice(), def_id);
350 encode_index(rbml_w, idx, write_i64);
353 if (*vi)[i].disr_val != disr_val {
354 encode_disr_val(ecx, rbml_w, (*vi)[i].disr_val);
355 disr_val = (*vi)[i].disr_val;
357 encode_bounds_and_type(rbml_w, ecx,
358 &lookup_item_type(ecx.tcx, def_id));
360 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
367 fn encode_path<PI: Iterator<PathElem> + Clone>(rbml_w: &mut Encoder,
369 rbml_w.start_tag(tag_path);
370 rbml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
373 ast_map::PathMod(_) => tag_path_elem_mod,
374 ast_map::PathName(_) => tag_path_elem_name
376 rbml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
381 fn encode_reexported_static_method(rbml_w: &mut Encoder,
382 exp: &middle::resolve::Export2,
383 method_def_id: DefId,
384 method_name: ast::Name) {
385 debug!("(encode reexported static method) {}::{}",
386 exp.name, token::get_name(method_name));
387 rbml_w.start_tag(tag_items_data_item_reexport);
388 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
389 rbml_w.wr_str(def_to_string(method_def_id).as_slice());
391 rbml_w.start_tag(tag_items_data_item_reexport_name);
392 rbml_w.wr_str(format!("{}::{}",
394 token::get_name(method_name)).as_slice());
399 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
400 rbml_w: &mut Encoder,
401 exp: &middle::resolve::Export2)
403 let impl_items = ecx.tcx.impl_items.borrow();
404 match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
405 Some(implementations) => {
406 for base_impl_did in implementations.iter() {
407 for &method_did in (*impl_items)[*base_impl_did].iter() {
408 let impl_item = ty::impl_or_trait_item(
410 method_did.def_id());
412 ty::MethodTraitItem(ref m) => {
413 encode_reexported_static_method(rbml_w,
418 ty::TypeTraitItem(_) => {}
429 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
430 rbml_w: &mut Encoder,
431 exp: &middle::resolve::Export2)
433 match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
434 Some(trait_items) => {
435 for trait_item in trait_items.iter() {
436 if let ty::MethodTraitItem(ref m) = *trait_item {
437 encode_reexported_static_method(rbml_w,
449 fn encode_reexported_static_methods(ecx: &EncodeContext,
450 rbml_w: &mut Encoder,
452 exp: &middle::resolve::Export2) {
453 if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
454 let original_name = token::get_ident(item.ident);
456 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
457 let (mut a, mut b) = (path, mod_path.clone());
459 match (a.next(), b.next()) {
460 (None, None) => return true,
461 (None, _) | (_, None) => return false,
462 (Some(x), Some(y)) => if x != y { return false },
468 // We don't need to reexport static methods on items
469 // declared in the same module as our `pub use ...` since
470 // that's done when we encode the item itself.
472 // The only exception is when the reexport *changes* the
473 // name e.g. `pub use Foo = self::Bar` -- we have
474 // encoded metadata for static methods relative to Bar,
475 // but not yet for Foo.
477 if path_differs || original_name.get() != exp.name {
478 if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
479 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
480 debug!("(encode reexported static methods) {} [trait]",
485 debug!("(encode reexported static methods) {} [base]",
492 /// Iterates through "auxiliary node IDs", which are node IDs that describe
493 /// top-level items that are sub-items of the given item. Specifically:
495 /// * For newtype structs, iterates through the node ID of the constructor.
496 fn each_auxiliary_node_id(item: &ast::Item, callback: |NodeId| -> bool) -> bool {
497 let mut continue_ = true;
499 ast::ItemStruct(ref struct_def, _) => {
500 // If this is a newtype struct, return the constructor.
501 match struct_def.ctor_id {
502 Some(ctor_id) if struct_def.fields.len() > 0 &&
503 struct_def.fields[0].node.kind.is_unnamed() => {
504 continue_ = callback(ctor_id);
515 fn encode_reexports(ecx: &EncodeContext,
516 rbml_w: &mut Encoder,
519 debug!("(encoding info for module) encoding reexports for {}", id);
520 match ecx.reexports2.get(&id) {
521 Some(ref exports) => {
522 debug!("(encoding info for module) found reexports for {}", id);
523 for exp in exports.iter() {
524 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
530 rbml_w.start_tag(tag_items_data_item_reexport);
531 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
532 rbml_w.wr_str(def_to_string(exp.def_id).as_slice());
534 rbml_w.start_tag(tag_items_data_item_reexport_name);
535 rbml_w.wr_str(exp.name.as_slice());
538 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
542 debug!("(encoding info for module) found no reexports for {}",
548 fn encode_info_for_mod(ecx: &EncodeContext,
549 rbml_w: &mut Encoder,
551 attrs: &[ast::Attribute],
555 vis: ast::Visibility) {
556 rbml_w.start_tag(tag_items_data_item);
557 encode_def_id(rbml_w, local_def(id));
558 encode_family(rbml_w, 'm');
559 encode_name(rbml_w, name.name);
560 debug!("(encoding info for module) encoding info for module ID {}", id);
562 // Encode info about all the module children.
563 for item in md.items.iter() {
564 rbml_w.start_tag(tag_mod_child);
565 rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
568 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
569 rbml_w.start_tag(tag_mod_child);
570 rbml_w.wr_str(def_to_string(local_def(
571 auxiliary_node_id)).as_slice());
576 if let ast::ItemImpl(..) = item.node {
577 let (ident, did) = (item.ident, item.id);
578 debug!("(encoding info for module) ... encoding impl {} ({}/{})",
579 token::get_ident(ident),
580 did, ecx.tcx.map.node_to_string(did));
582 rbml_w.start_tag(tag_mod_impl);
583 rbml_w.wr_str(def_to_string(local_def(did)).as_slice());
588 encode_path(rbml_w, path.clone());
589 encode_visibility(rbml_w, vis);
591 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
592 encode_stability(rbml_w, stab);
594 // Encode the reexports of this module, if this module is public.
595 if vis == ast::Public {
596 debug!("(encoding info for module) encoding reexports for {}", id);
597 encode_reexports(ecx, rbml_w, id, path);
599 encode_attributes(rbml_w, attrs);
604 fn encode_struct_field_family(rbml_w: &mut Encoder,
605 visibility: ast::Visibility) {
606 encode_family(rbml_w, match visibility {
608 ast::Inherited => 'N'
612 fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
613 rbml_w.start_tag(tag_items_data_item_visibility);
614 let ch = match visibility {
616 ast::Inherited => 'i',
618 rbml_w.wr_str(ch.to_string().as_slice());
622 fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
623 kind: ty::UnboxedClosureKind) {
624 rbml_w.start_tag(tag_unboxed_closure_kind);
625 let ch = match kind {
626 ty::FnUnboxedClosureKind => 'f',
627 ty::FnMutUnboxedClosureKind => 'm',
628 ty::FnOnceUnboxedClosureKind => 'o',
630 rbml_w.wr_str(ch.to_string().as_slice());
634 fn encode_explicit_self(rbml_w: &mut Encoder,
635 explicit_self: &ty::ExplicitSelfCategory) {
636 rbml_w.start_tag(tag_item_trait_method_explicit_self);
638 // Encode the base self type.
639 match *explicit_self {
640 ty::StaticExplicitSelfCategory => {
641 rbml_w.writer.write(&[ 's' as u8 ]);
643 ty::ByValueExplicitSelfCategory => {
644 rbml_w.writer.write(&[ 'v' as u8 ]);
646 ty::ByBoxExplicitSelfCategory => {
647 rbml_w.writer.write(&[ '~' as u8 ]);
649 ty::ByReferenceExplicitSelfCategory(_, m) => {
650 // FIXME(#4846) encode custom lifetime
651 rbml_w.writer.write(&['&' as u8]);
652 encode_mutability(rbml_w, m);
658 fn encode_mutability(rbml_w: &mut Encoder,
659 m: ast::Mutability) {
661 ast::MutImmutable => { rbml_w.writer.write(&[ 'i' as u8 ]); }
662 ast::MutMutable => { rbml_w.writer.write(&[ 'm' as u8 ]); }
667 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
668 rbml_w.start_tag(tag_item_trait_item_sort);
669 rbml_w.writer.write(&[ sort as u8 ]);
673 fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
674 rbml_w.start_tag(tag_item_trait_parent_sort);
675 rbml_w.writer.write(&[ sort as u8 ]);
679 fn encode_provided_source(rbml_w: &mut Encoder,
680 source_opt: Option<DefId>) {
681 for source in source_opt.iter() {
682 rbml_w.start_tag(tag_item_method_provided_source);
683 let s = def_to_string(*source);
684 rbml_w.writer.write(s.as_bytes());
689 /* Returns an index of items in this class */
690 fn encode_info_for_struct(ecx: &EncodeContext,
691 rbml_w: &mut Encoder,
692 fields: &[ty::field_ty],
693 global_index: &mut Vec<entry<i64>>)
695 /* Each class has its own index, since different classes
696 may have fields with the same name */
697 let mut index = Vec::new();
698 /* We encode both private and public fields -- need to include
699 private fields to get the offsets right */
700 for field in fields.iter() {
702 let id = field.id.node;
704 index.push(entry {val: id as i64, pos: rbml_w.writer.tell().unwrap()});
705 global_index.push(entry {
707 pos: rbml_w.writer.tell().unwrap(),
709 rbml_w.start_tag(tag_items_data_item);
710 debug!("encode_info_for_struct: doing {} {}",
711 token::get_name(nm), id);
712 encode_struct_field_family(rbml_w, field.vis);
713 encode_name(rbml_w, nm);
714 encode_bounds_and_type(rbml_w, ecx,
715 &lookup_item_type(ecx.tcx, local_def(id)));
716 encode_def_id(rbml_w, local_def(id));
718 let stab = stability::lookup(ecx.tcx, field.id);
719 encode_stability(rbml_w, stab);
726 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
727 rbml_w: &mut Encoder,
730 index: &mut Vec<entry<i64>>,
734 pos: rbml_w.writer.tell().unwrap(),
737 rbml_w.start_tag(tag_items_data_item);
738 encode_def_id(rbml_w, local_def(ctor_id));
739 encode_family(rbml_w, 'o');
740 encode_bounds_and_type(rbml_w, ecx,
741 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
742 encode_name(rbml_w, name.name);
743 ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
744 encode_parent_item(rbml_w, local_def(struct_id));
746 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
747 encode_symbol(ecx, rbml_w, ctor_id);
750 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
751 encode_stability(rbml_w, stab);
753 // indicate that this is a tuple struct ctor, because downstream users will normally want
754 // the tuple struct definition, but without this there is no way for them to tell that
755 // they actually have a ctor rather than a normal function
756 rbml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
762 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
763 ecx: &EncodeContext<'a, 'tcx>,
764 generics: &ty::Generics<'tcx>,
767 rbml_w.start_tag(tag);
770 let ty_str_ctxt = &tyencode::ctxt {
774 abbrevs: &ecx.type_abbrevs
776 for param in generics.types.iter() {
777 rbml_w.start_tag(tag_type_param_def);
778 tyencode::enc_type_param_def(rbml_w.writer, ty_str_ctxt, param);
783 for param in generics.regions.iter() {
784 rbml_w.start_tag(tag_region_param_def);
786 rbml_w.start_tag(tag_region_param_def_ident);
787 encode_name(rbml_w, param.name);
790 rbml_w.wr_tagged_str(tag_region_param_def_def_id,
791 def_to_string(param.def_id).as_slice());
793 rbml_w.wr_tagged_u64(tag_region_param_def_space,
794 param.space.to_uint() as u64);
796 rbml_w.wr_tagged_u64(tag_region_param_def_index,
799 for &bound_region in param.bounds.iter() {
800 encode_region(ecx, rbml_w, bound_region);
809 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
810 rbml_w: &mut Encoder,
811 method_ty: &ty::Method<'tcx>) {
812 encode_def_id(rbml_w, method_ty.def_id);
813 encode_name(rbml_w, method_ty.name);
814 encode_generics(rbml_w, ecx, &method_ty.generics,
815 tag_method_ty_generics);
816 encode_method_fty(ecx, rbml_w, &method_ty.fty);
817 encode_visibility(rbml_w, method_ty.vis);
818 encode_explicit_self(rbml_w, &method_ty.explicit_self);
819 match method_ty.explicit_self {
820 ty::StaticExplicitSelfCategory => {
821 encode_family(rbml_w, STATIC_METHOD_FAMILY);
823 _ => encode_family(rbml_w, METHOD_FAMILY)
825 encode_provided_source(rbml_w, method_ty.provided_source);
828 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
829 rbml_w: &mut Encoder,
830 m: &ty::Method<'tcx>,
831 impl_path: PathElems,
832 is_default_impl: bool,
834 ast_item_opt: Option<&ast::ImplItem>) {
836 debug!("encode_info_for_method: {} {}", m.def_id,
837 token::get_name(m.name));
838 rbml_w.start_tag(tag_items_data_item);
840 encode_method_ty_fields(ecx, rbml_w, m);
841 encode_parent_item(rbml_w, local_def(parent_id));
842 encode_item_sort(rbml_w, 'r');
844 let stab = stability::lookup(ecx.tcx, m.def_id);
845 encode_stability(rbml_w, stab);
847 // The type for methods gets encoded twice, which is unfortunate.
848 let pty = lookup_item_type(ecx.tcx, m.def_id);
849 encode_bounds_and_type(rbml_w, ecx, &pty);
851 let elem = ast_map::PathName(m.name);
852 encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
854 Some(&ast::MethodImplItem(ref ast_method)) => {
855 encode_attributes(rbml_w, ast_method.attrs.as_slice());
856 let any_types = !pty.generics.types.is_empty();
857 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
858 encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
859 ast_item_opt.unwrap()));
862 encode_symbol(ecx, rbml_w, m.def_id.node);
864 encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
872 fn encode_info_for_associated_type(ecx: &EncodeContext,
873 rbml_w: &mut Encoder,
874 associated_type: &ty::AssociatedType,
875 impl_path: PathElems,
877 typedef_opt: Option<P<ast::Typedef>>) {
878 debug!("encode_info_for_associated_type({},{})",
879 associated_type.def_id,
880 token::get_name(associated_type.name));
882 rbml_w.start_tag(tag_items_data_item);
884 encode_def_id(rbml_w, associated_type.def_id);
885 encode_name(rbml_w, associated_type.name);
886 encode_visibility(rbml_w, associated_type.vis);
887 encode_family(rbml_w, 'y');
888 encode_parent_item(rbml_w, local_def(parent_id));
889 encode_item_sort(rbml_w, 'r');
891 let stab = stability::lookup(ecx.tcx, associated_type.def_id);
892 encode_stability(rbml_w, stab);
894 let elem = ast_map::PathName(associated_type.name);
895 encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
900 encode_attributes(rbml_w, typedef.attrs.as_slice());
901 encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
909 fn encode_method_argument_names(rbml_w: &mut Encoder,
910 decl: &ast::FnDecl) {
911 rbml_w.start_tag(tag_method_argument_names);
912 for arg in decl.inputs.iter() {
913 rbml_w.start_tag(tag_method_argument_name);
914 if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
915 let name = token::get_ident(path1.node);
916 rbml_w.writer.write(name.get().as_bytes());
923 fn encode_repr_attrs(rbml_w: &mut Encoder,
925 attrs: &[ast::Attribute]) {
926 let mut repr_attrs = Vec::new();
927 for attr in attrs.iter() {
928 repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
931 rbml_w.start_tag(tag_items_data_item_repr);
932 repr_attrs.encode(rbml_w);
936 fn encode_inlined_item(ecx: &EncodeContext,
937 rbml_w: &mut Encoder,
938 ii: InlinedItemRef) {
939 let mut eii = ecx.encode_inlined_item.borrow_mut();
940 let eii: &mut EncodeInlinedItem = &mut *eii;
941 (*eii)(ecx, rbml_w, ii)
944 const FN_FAMILY: char = 'f';
945 const STATIC_METHOD_FAMILY: char = 'F';
946 const METHOD_FAMILY: char = 'h';
948 fn should_inline(attrs: &[ast::Attribute]) -> bool {
950 match find_inline_attr(attrs) {
951 InlineNone | InlineNever => false,
952 InlineHint | InlineAlways => true
956 // Encodes the inherent implementations of a structure, enumeration, or trait.
957 fn encode_inherent_implementations(ecx: &EncodeContext,
958 rbml_w: &mut Encoder,
960 match ecx.tcx.inherent_impls.borrow().get(&def_id) {
962 Some(implementations) => {
963 for &impl_def_id in implementations.iter() {
964 rbml_w.start_tag(tag_items_data_item_inherent_impl);
965 encode_def_id(rbml_w, impl_def_id);
972 // Encodes the implementations of a trait defined in this crate.
973 fn encode_extension_implementations(ecx: &EncodeContext,
974 rbml_w: &mut Encoder,
975 trait_def_id: DefId) {
976 match ecx.tcx.trait_impls.borrow().get(&trait_def_id) {
978 Some(implementations) => {
979 for &impl_def_id in implementations.borrow().iter() {
980 rbml_w.start_tag(tag_items_data_item_extension_impl);
981 encode_def_id(rbml_w, impl_def_id);
988 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
989 stab_opt.map(|stab| {
990 rbml_w.start_tag(tag_items_data_item_stability);
991 stab.encode(rbml_w).unwrap();
996 fn encode_info_for_item(ecx: &EncodeContext,
997 rbml_w: &mut Encoder,
999 index: &mut Vec<entry<i64>>,
1001 vis: ast::Visibility) {
1004 fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
1005 index: &mut Vec<entry<i64>>) {
1007 val: item.id as i64,
1008 pos: rbml_w.writer.tell().unwrap(),
1012 debug!("encoding info for item at {}",
1013 tcx.sess.codemap().span_to_string(item.span));
1015 let def_id = local_def(item.id);
1016 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
1019 ast::ItemStatic(_, m, _) => {
1020 add_to_index(item, rbml_w, index);
1021 rbml_w.start_tag(tag_items_data_item);
1022 encode_def_id(rbml_w, def_id);
1023 if m == ast::MutMutable {
1024 encode_family(rbml_w, 'b');
1026 encode_family(rbml_w, 'c');
1028 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1029 encode_symbol(ecx, rbml_w, item.id);
1030 encode_name(rbml_w, item.ident.name);
1031 encode_path(rbml_w, path);
1032 encode_visibility(rbml_w, vis);
1033 encode_stability(rbml_w, stab);
1034 encode_attributes(rbml_w, item.attrs.as_slice());
1037 ast::ItemConst(_, _) => {
1038 add_to_index(item, rbml_w, index);
1039 rbml_w.start_tag(tag_items_data_item);
1040 encode_def_id(rbml_w, def_id);
1041 encode_family(rbml_w, 'C');
1042 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1043 encode_name(rbml_w, item.ident.name);
1044 encode_path(rbml_w, path);
1045 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1046 encode_visibility(rbml_w, vis);
1047 encode_stability(rbml_w, stab);
1050 ast::ItemFn(ref decl, _, _, ref generics, _) => {
1051 add_to_index(item, rbml_w, index);
1052 rbml_w.start_tag(tag_items_data_item);
1053 encode_def_id(rbml_w, def_id);
1054 encode_family(rbml_w, FN_FAMILY);
1055 let tps_len = generics.ty_params.len();
1056 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1057 encode_name(rbml_w, item.ident.name);
1058 encode_path(rbml_w, path);
1059 encode_attributes(rbml_w, item.attrs.as_slice());
1060 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
1061 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1064 encode_symbol(ecx, rbml_w, item.id);
1066 encode_visibility(rbml_w, vis);
1067 encode_stability(rbml_w, stab);
1068 encode_method_argument_names(rbml_w, &**decl);
1071 ast::ItemMod(ref m) => {
1072 add_to_index(item, rbml_w, index);
1073 encode_info_for_mod(ecx,
1076 item.attrs.as_slice(),
1082 ast::ItemForeignMod(ref fm) => {
1083 add_to_index(item, rbml_w, index);
1084 rbml_w.start_tag(tag_items_data_item);
1085 encode_def_id(rbml_w, def_id);
1086 encode_family(rbml_w, 'n');
1087 encode_name(rbml_w, item.ident.name);
1088 encode_path(rbml_w, path);
1090 // Encode all the items in this module.
1091 for foreign_item in fm.items.iter() {
1092 rbml_w.start_tag(tag_mod_child);
1093 rbml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
1096 encode_visibility(rbml_w, vis);
1097 encode_stability(rbml_w, stab);
1100 ast::ItemTy(..) => {
1101 add_to_index(item, rbml_w, index);
1102 rbml_w.start_tag(tag_items_data_item);
1103 encode_def_id(rbml_w, def_id);
1104 encode_family(rbml_w, 'y');
1105 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1106 encode_name(rbml_w, item.ident.name);
1107 encode_path(rbml_w, path);
1108 encode_visibility(rbml_w, vis);
1109 encode_stability(rbml_w, stab);
1112 ast::ItemEnum(ref enum_definition, _) => {
1113 add_to_index(item, rbml_w, index);
1115 rbml_w.start_tag(tag_items_data_item);
1116 encode_def_id(rbml_w, def_id);
1117 encode_family(rbml_w, 't');
1118 encode_item_variances(rbml_w, ecx, item.id);
1119 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1120 encode_name(rbml_w, item.ident.name);
1121 encode_attributes(rbml_w, item.attrs.as_slice());
1122 encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice());
1123 for v in (*enum_definition).variants.iter() {
1124 encode_variant_id(rbml_w, local_def(v.node.id));
1126 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1127 encode_path(rbml_w, path);
1129 // Encode inherent implementations for this enumeration.
1130 encode_inherent_implementations(ecx, rbml_w, def_id);
1132 encode_visibility(rbml_w, vis);
1133 encode_stability(rbml_w, stab);
1136 encode_enum_variant_info(ecx,
1139 (*enum_definition).variants.as_slice(),
1142 ast::ItemStruct(ref struct_def, _) => {
1143 let fields = ty::lookup_struct_fields(tcx, def_id);
1145 /* First, encode the fields
1146 These come first because we need to write them to make
1147 the index, and the index needs to be in the item for the
1149 let idx = encode_info_for_struct(ecx,
1154 /* Index the class*/
1155 add_to_index(item, rbml_w, index);
1157 /* Now, make an item for the class itself */
1158 rbml_w.start_tag(tag_items_data_item);
1159 encode_def_id(rbml_w, def_id);
1160 encode_family(rbml_w, 'S');
1161 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1163 encode_item_variances(rbml_w, ecx, item.id);
1164 encode_name(rbml_w, item.ident.name);
1165 encode_attributes(rbml_w, item.attrs.as_slice());
1166 encode_path(rbml_w, path.clone());
1167 encode_stability(rbml_w, stab);
1168 encode_visibility(rbml_w, vis);
1169 encode_repr_attrs(rbml_w, ecx, item.attrs.as_slice());
1171 /* Encode def_ids for each field and method
1172 for methods, write all the stuff get_trait_method
1174 encode_struct_fields(rbml_w, fields.as_slice(), def_id);
1176 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1178 // Encode inherent implementations for this structure.
1179 encode_inherent_implementations(ecx, rbml_w, def_id);
1181 /* Each class has its own index -- encode it */
1182 encode_index(rbml_w, idx, write_i64);
1185 // If this is a tuple-like struct, encode the type of the constructor.
1186 match struct_def.ctor_id {
1188 encode_info_for_struct_ctor(ecx, rbml_w, item.ident,
1189 ctor_id, index, def_id.node);
1194 ast::ItemImpl(_, ref opt_trait, ref ty, ref ast_items) => {
1195 // We need to encode information about the default methods we
1196 // have inherited, so we drive this based on the impl structure.
1197 let impl_items = tcx.impl_items.borrow();
1198 let items = &(*impl_items)[def_id];
1200 add_to_index(item, rbml_w, index);
1201 rbml_w.start_tag(tag_items_data_item);
1202 encode_def_id(rbml_w, def_id);
1203 encode_family(rbml_w, 'i');
1204 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1205 encode_name(rbml_w, item.ident.name);
1206 encode_attributes(rbml_w, item.attrs.as_slice());
1208 ast::TyPath(ref path, _) if path.segments
1210 let ident = path.segments.last().unwrap().identifier;
1211 encode_impl_type_basename(rbml_w, ident);
1215 for &item_def_id in items.iter() {
1216 rbml_w.start_tag(tag_item_impl_item);
1218 ty::MethodTraitItemId(item_def_id) => {
1219 encode_def_id(rbml_w, item_def_id);
1220 encode_item_sort(rbml_w, 'r');
1222 ty::TypeTraitItemId(item_def_id) => {
1223 encode_def_id(rbml_w, item_def_id);
1224 encode_item_sort(rbml_w, 't');
1229 for ast_trait_ref in opt_trait.iter() {
1230 let trait_ref = ty::node_id_to_trait_ref(
1231 tcx, ast_trait_ref.ref_id);
1232 encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
1234 encode_path(rbml_w, path.clone());
1235 encode_stability(rbml_w, stab);
1238 // Iterate down the trait items, emitting them. We rely on the
1239 // assumption that all of the actually implemented trait items
1240 // appear first in the impl structure, in the same order they do
1241 // in the ast. This is a little sketchy.
1242 let num_implemented_methods = ast_items.len();
1243 for (i, &trait_item_def_id) in items.iter().enumerate() {
1244 let ast_item = if i < num_implemented_methods {
1251 val: trait_item_def_id.def_id().node as i64,
1252 pos: rbml_w.writer.tell().unwrap(),
1255 let trait_item_type =
1256 ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
1257 match (trait_item_type, ast_item) {
1258 (ty::MethodTraitItem(ref method_type),
1259 Some(&ast::MethodImplItem(_))) => {
1260 encode_info_for_method(ecx,
1268 (ty::MethodTraitItem(ref method_type), _) => {
1269 encode_info_for_method(ecx,
1277 (ty::TypeTraitItem(ref associated_type),
1278 Some(&ast::TypeImplItem(ref typedef))) => {
1279 encode_info_for_associated_type(ecx,
1284 Some((*typedef).clone()))
1286 (ty::TypeTraitItem(ref associated_type), _) => {
1287 encode_info_for_associated_type(ecx,
1297 ast::ItemTrait(_, _, _, ref ms) => {
1298 add_to_index(item, rbml_w, index);
1299 rbml_w.start_tag(tag_items_data_item);
1300 encode_def_id(rbml_w, def_id);
1301 encode_family(rbml_w, 'I');
1302 encode_item_variances(rbml_w, ecx, item.id);
1303 let trait_def = ty::lookup_trait_def(tcx, def_id);
1304 encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
1305 encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1306 encode_name(rbml_w, item.ident.name);
1307 encode_attributes(rbml_w, item.attrs.as_slice());
1308 encode_visibility(rbml_w, vis);
1309 encode_stability(rbml_w, stab);
1310 for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
1311 rbml_w.start_tag(tag_item_trait_item);
1312 match method_def_id {
1313 ty::MethodTraitItemId(method_def_id) => {
1314 encode_def_id(rbml_w, method_def_id);
1315 encode_item_sort(rbml_w, 'r');
1317 ty::TypeTraitItemId(type_def_id) => {
1318 encode_def_id(rbml_w, type_def_id);
1319 encode_item_sort(rbml_w, 't');
1324 rbml_w.start_tag(tag_mod_child);
1325 rbml_w.wr_str(def_to_string(method_def_id.def_id()).as_slice());
1328 encode_path(rbml_w, path.clone());
1330 encode_bounds(rbml_w, ecx, &trait_def.bounds, tag_trait_def_bounds);
1332 // Encode the implementations of this trait.
1333 encode_extension_implementations(ecx, rbml_w, def_id);
1337 // Now output the trait item info for each trait item.
1338 let r = ty::trait_item_def_ids(tcx, def_id);
1339 for (i, &item_def_id) in r.iter().enumerate() {
1340 assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
1343 val: item_def_id.def_id().node as i64,
1344 pos: rbml_w.writer.tell().unwrap(),
1347 rbml_w.start_tag(tag_items_data_item);
1349 encode_parent_item(rbml_w, def_id);
1351 let stab = stability::lookup(tcx, item_def_id.def_id());
1352 encode_stability(rbml_w, stab);
1354 let trait_item_type =
1355 ty::impl_or_trait_item(tcx, item_def_id.def_id());
1356 let is_nonstatic_method;
1357 match trait_item_type {
1358 ty::MethodTraitItem(method_ty) => {
1359 let method_def_id = item_def_id.def_id();
1361 encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1363 let elem = ast_map::PathName(method_ty.name);
1365 path.clone().chain(Some(elem).into_iter()));
1367 match method_ty.explicit_self {
1368 ty::StaticExplicitSelfCategory => {
1369 encode_family(rbml_w,
1370 STATIC_METHOD_FAMILY);
1373 encode_family(rbml_w,
1377 let pty = ty::lookup_item_type(tcx,
1379 encode_bounds_and_type(rbml_w, ecx, &pty);
1381 is_nonstatic_method = method_ty.explicit_self !=
1382 ty::StaticExplicitSelfCategory;
1384 ty::TypeTraitItem(associated_type) => {
1385 let elem = ast_map::PathName(associated_type.name);
1387 path.clone().chain(Some(elem).into_iter()));
1389 encode_family(rbml_w, 'y');
1391 is_nonstatic_method = false;
1395 encode_parent_sort(rbml_w, 't');
1397 let trait_item = &ms[i];
1398 let encode_trait_item = |rbml_w: &mut Encoder| {
1399 // If this is a static method, we've already
1401 if is_nonstatic_method {
1402 // FIXME: I feel like there is something funny
1404 let pty = ty::lookup_item_type(tcx, item_def_id.def_id());
1405 encode_bounds_and_type(rbml_w, ecx, &pty);
1409 &ast::RequiredMethod(ref m) => {
1410 encode_attributes(rbml_w, m.attrs.as_slice());
1411 encode_trait_item(rbml_w);
1412 encode_item_sort(rbml_w, 'r');
1413 encode_method_argument_names(rbml_w, &*m.decl);
1416 &ast::ProvidedMethod(ref m) => {
1417 encode_attributes(rbml_w, m.attrs.as_slice());
1418 encode_trait_item(rbml_w);
1419 encode_item_sort(rbml_w, 'p');
1420 encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
1421 encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
1424 &ast::TypeTraitItem(ref associated_type) => {
1425 encode_attributes(rbml_w,
1426 associated_type.attrs.as_slice());
1427 encode_item_sort(rbml_w, 't');
1434 // Encode inherent implementations for this trait.
1435 encode_inherent_implementations(ecx, rbml_w, def_id);
1437 ast::ItemMac(..) => {
1438 // macros are encoded separately
1443 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1444 rbml_w: &mut Encoder,
1445 nitem: &ast::ForeignItem,
1446 index: &mut Vec<entry<i64>>,
1450 val: nitem.id as i64,
1451 pos: rbml_w.writer.tell().unwrap(),
1454 rbml_w.start_tag(tag_items_data_item);
1455 encode_def_id(rbml_w, local_def(nitem.id));
1456 encode_visibility(rbml_w, nitem.vis);
1458 ast::ForeignItemFn(..) => {
1459 encode_family(rbml_w, FN_FAMILY);
1460 encode_bounds_and_type(rbml_w, ecx,
1461 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1462 encode_name(rbml_w, nitem.ident.name);
1463 if abi == abi::RustIntrinsic {
1464 encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
1466 encode_symbol(ecx, rbml_w, nitem.id);
1468 ast::ForeignItemStatic(_, mutbl) => {
1470 encode_family(rbml_w, 'b');
1472 encode_family(rbml_w, 'c');
1474 encode_bounds_and_type(rbml_w, ecx,
1475 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1476 encode_symbol(ecx, rbml_w, nitem.id);
1477 encode_name(rbml_w, nitem.ident.name);
1480 encode_path(rbml_w, path);
1484 fn my_visit_expr(_e: &ast::Expr) { }
1486 fn my_visit_item(i: &ast::Item,
1487 rbml_w: &mut Encoder,
1488 ecx: &EncodeContext,
1489 index: &mut Vec<entry<i64>>) {
1490 ecx.tcx.map.with_path(i.id, |path| {
1491 encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1495 fn my_visit_foreign_item(ni: &ast::ForeignItem,
1496 rbml_w: &mut Encoder,
1497 ecx: &EncodeContext,
1498 index: &mut Vec<entry<i64>>) {
1499 debug!("writing foreign item {}::{}",
1500 ecx.tcx.map.path_to_string(ni.id),
1501 token::get_ident(ni.ident));
1503 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1504 ecx.tcx.map.with_path(ni.id, |path| {
1505 encode_info_for_foreign_item(ecx, rbml_w,
1511 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1512 rbml_w_for_visit_item: &'a mut Encoder<'b>,
1513 ecx: &'a EncodeContext<'c,'tcx>,
1514 index: &'a mut Vec<entry<i64>>,
1517 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1518 fn visit_expr(&mut self, ex: &ast::Expr) {
1519 visit::walk_expr(self, ex);
1522 fn visit_item(&mut self, i: &ast::Item) {
1523 visit::walk_item(self, i);
1525 self.rbml_w_for_visit_item,
1529 fn visit_foreign_item(&mut self, ni: &ast::ForeignItem) {
1530 visit::walk_foreign_item(self, ni);
1531 my_visit_foreign_item(ni,
1532 self.rbml_w_for_visit_item,
1538 fn encode_info_for_items(ecx: &EncodeContext,
1539 rbml_w: &mut Encoder,
1541 -> Vec<entry<i64>> {
1542 let mut index = Vec::new();
1543 rbml_w.start_tag(tag_items_data);
1545 val: ast::CRATE_NODE_ID as i64,
1546 pos: rbml_w.writer.tell().unwrap(),
1548 encode_info_for_mod(ecx,
1553 ast_map::Values([].iter()).chain(None),
1554 syntax::parse::token::special_idents::invalid,
1557 visit::walk_crate(&mut EncodeVisitor {
1560 rbml_w_for_visit_item: &mut *rbml_w,
1568 // Path and definition ID indexing
1570 fn encode_index<T: Hash>(rbml_w: &mut Encoder, index: Vec<entry<T>>,
1571 write_fn: |&mut SeekableMemWriter, &T|) {
1572 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1573 for elt in index.into_iter() {
1574 let h = hash::hash(&elt.val) as uint;
1575 buckets[h % 256].push(elt);
1578 rbml_w.start_tag(tag_index);
1579 let mut bucket_locs = Vec::new();
1580 rbml_w.start_tag(tag_index_buckets);
1581 for bucket in buckets.iter() {
1582 bucket_locs.push(rbml_w.writer.tell().unwrap());
1583 rbml_w.start_tag(tag_index_buckets_bucket);
1584 for elt in bucket.iter() {
1585 rbml_w.start_tag(tag_index_buckets_bucket_elt);
1586 assert!(elt.pos < 0xffff_ffff);
1588 let wr: &mut SeekableMemWriter = rbml_w.writer;
1589 wr.write_be_u32(elt.pos as u32);
1591 write_fn(rbml_w.writer, &elt.val);
1597 rbml_w.start_tag(tag_index_table);
1598 for pos in bucket_locs.iter() {
1599 assert!(*pos < 0xffff_ffff);
1600 let wr: &mut SeekableMemWriter = rbml_w.writer;
1601 wr.write_be_u32(*pos as u32);
1607 fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1608 let wr: &mut SeekableMemWriter = writer;
1609 assert!(n < 0x7fff_ffff);
1610 wr.write_be_u32(n as u32);
1613 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1615 ast::MetaWord(ref name) => {
1616 rbml_w.start_tag(tag_meta_item_word);
1617 rbml_w.start_tag(tag_meta_item_name);
1618 rbml_w.writer.write(name.get().as_bytes());
1622 ast::MetaNameValue(ref name, ref value) => {
1624 ast::LitStr(ref value, _) => {
1625 rbml_w.start_tag(tag_meta_item_name_value);
1626 rbml_w.start_tag(tag_meta_item_name);
1627 rbml_w.writer.write(name.get().as_bytes());
1629 rbml_w.start_tag(tag_meta_item_value);
1630 rbml_w.writer.write(value.get().as_bytes());
1634 _ => {/* FIXME (#623): encode other variants */ }
1637 ast::MetaList(ref name, ref items) => {
1638 rbml_w.start_tag(tag_meta_item_list);
1639 rbml_w.start_tag(tag_meta_item_name);
1640 rbml_w.writer.write(name.get().as_bytes());
1642 for inner_item in items.iter() {
1643 encode_meta_item(rbml_w, &**inner_item);
1650 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1651 rbml_w.start_tag(tag_attributes);
1652 for attr in attrs.iter() {
1653 rbml_w.start_tag(tag_attribute);
1654 rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1655 encode_meta_item(rbml_w, &*attr.node.value);
1661 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1662 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1663 // Pull the cnums and name,vers,hash out of cstore
1664 let mut deps = Vec::new();
1665 cstore.iter_crate_data(|key, val| {
1666 let dep = decoder::CrateDep {
1668 name: decoder::get_crate_name(val.data()),
1669 hash: decoder::get_crate_hash(val.data()),
1675 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1677 // Sanity-check the crate numbers
1678 let mut expected_cnum = 1;
1679 for n in deps.iter() {
1680 assert_eq!(n.cnum, expected_cnum);
1687 // We're just going to write a list of crate 'name-hash-version's, with
1688 // the assumption that they are numbered 1 to n.
1689 // FIXME (#2166): This is not nearly enough to support correct versioning
1690 // but is enough to get transitive crate dependencies working.
1691 rbml_w.start_tag(tag_crate_deps);
1692 let r = get_ordered_deps(cstore);
1693 for dep in r.iter() {
1694 encode_crate_dep(rbml_w, (*dep).clone());
1699 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1700 rbml_w.start_tag(tag_lang_items);
1702 for (i, def_id) in ecx.tcx.lang_items.items() {
1703 for id in def_id.iter() {
1704 if id.krate == ast::LOCAL_CRATE {
1705 rbml_w.start_tag(tag_lang_items_item);
1707 rbml_w.start_tag(tag_lang_items_item_id);
1709 let wr: &mut SeekableMemWriter = rbml_w.writer;
1710 wr.write_be_u32(i as u32);
1712 rbml_w.end_tag(); // tag_lang_items_item_id
1714 rbml_w.start_tag(tag_lang_items_item_node_id);
1716 let wr: &mut SeekableMemWriter = rbml_w.writer;
1717 wr.write_be_u32(id.node as u32);
1719 rbml_w.end_tag(); // tag_lang_items_item_node_id
1721 rbml_w.end_tag(); // tag_lang_items_item
1726 for i in ecx.tcx.lang_items.missing.iter() {
1727 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1730 rbml_w.end_tag(); // tag_lang_items
1733 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1734 rbml_w.start_tag(tag_native_libraries);
1736 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1739 cstore::NativeStatic => {} // these libraries are not propagated
1740 cstore::NativeFramework | cstore::NativeUnknown => {
1741 rbml_w.start_tag(tag_native_libraries_lib);
1743 rbml_w.start_tag(tag_native_libraries_kind);
1744 rbml_w.writer.write_be_u32(kind as u32);
1747 rbml_w.start_tag(tag_native_libraries_name);
1748 rbml_w.writer.write(lib.as_bytes());
1759 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1760 match ecx.tcx.sess.plugin_registrar_fn.get() {
1761 Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1766 /// Given a span, write the text of that span into the output stream
1767 /// as an exported macro
1768 fn encode_macro_def(ecx: &EncodeContext,
1769 rbml_w: &mut Encoder,
1770 span: &syntax::codemap::Span) {
1771 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1772 .expect("Unable to find source for macro");
1773 rbml_w.start_tag(tag_macro_def);
1774 rbml_w.wr_str(def.as_slice());
1778 /// Serialize the text of the exported macros
1779 fn encode_macro_defs(ecx: &EncodeContext,
1781 rbml_w: &mut Encoder) {
1782 rbml_w.start_tag(tag_exported_macros);
1783 for item in krate.exported_macros.iter() {
1784 encode_macro_def(ecx, rbml_w, &item.span);
1789 fn encode_unboxed_closures<'a>(
1790 ecx: &'a EncodeContext,
1791 rbml_w: &'a mut Encoder) {
1792 rbml_w.start_tag(tag_unboxed_closures);
1793 for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1797 if unboxed_closure_id.krate != ast::LOCAL_CRATE {
1801 rbml_w.start_tag(tag_unboxed_closure);
1802 encode_def_id(rbml_w, *unboxed_closure_id);
1803 rbml_w.start_tag(tag_unboxed_closure_type);
1804 write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
1806 encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
1812 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
1813 struct StructFieldVisitor<'a, 'b:'a> {
1814 rbml_w: &'a mut Encoder<'b>,
1817 impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1818 fn visit_struct_field(&mut self, field: &ast::StructField) {
1819 self.rbml_w.start_tag(tag_struct_field);
1820 self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1821 encode_attributes(self.rbml_w, field.node.attrs.as_slice());
1822 self.rbml_w.end_tag();
1826 rbml_w.start_tag(tag_struct_fields);
1827 visit::walk_crate(&mut StructFieldVisitor {
1835 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1836 ecx: &'a EncodeContext<'b, 'tcx>,
1837 rbml_w: &'a mut Encoder<'c>,
1840 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1841 fn visit_item(&mut self, item: &ast::Item) {
1842 if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node {
1843 let def_map = &self.ecx.tcx.def_map;
1844 let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
1845 let def_id = trait_def.def_id();
1847 // Load eagerly if this is an implementation of the Drop trait
1848 // or if the trait is not defined in this crate.
1849 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1850 def_id.krate != ast::LOCAL_CRATE {
1851 self.rbml_w.start_tag(tag_impls_impl);
1852 encode_def_id(self.rbml_w, local_def(item.id));
1853 self.rbml_w.end_tag();
1856 visit::walk_item(self, item);
1860 /// Encodes implementations that are eagerly loaded.
1862 /// None of this is necessary in theory; we can load all implementations
1863 /// lazily. However, in two cases the optimizations to lazily load
1864 /// implementations are not yet implemented. These two cases, which require us
1865 /// to load implementations eagerly, are:
1867 /// * Destructors (implementations of the Drop trait).
1869 /// * Implementations of traits not defined in this crate.
1870 fn encode_impls<'a>(ecx: &'a EncodeContext,
1872 rbml_w: &'a mut Encoder) {
1873 rbml_w.start_tag(tag_impls);
1876 let mut visitor = ImplVisitor {
1880 visit::walk_crate(&mut visitor, krate);
1886 fn encode_misc_info(ecx: &EncodeContext,
1888 rbml_w: &mut Encoder) {
1889 rbml_w.start_tag(tag_misc_info);
1890 rbml_w.start_tag(tag_misc_info_crate_items);
1891 for item in krate.module.items.iter() {
1892 rbml_w.start_tag(tag_mod_child);
1893 rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1896 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1897 rbml_w.start_tag(tag_mod_child);
1898 rbml_w.wr_str(def_to_string(local_def(
1899 auxiliary_node_id)).as_slice());
1905 // Encode reexports for the root module.
1906 encode_reexports(ecx, rbml_w, 0, ast_map::Values([].iter()).chain(None));
1912 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1913 rbml_w.start_tag(tag_reachable_extern_fns);
1915 for id in ecx.reachable.iter() {
1916 if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1917 if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1918 if abi != abi::Rust && !generics.is_type_parameterized() {
1919 rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1928 fn encode_crate_dep(rbml_w: &mut Encoder,
1929 dep: decoder::CrateDep) {
1930 rbml_w.start_tag(tag_crate_dep);
1931 rbml_w.start_tag(tag_crate_dep_crate_name);
1932 rbml_w.writer.write(dep.name.as_bytes());
1934 rbml_w.start_tag(tag_crate_dep_hash);
1935 rbml_w.writer.write(dep.hash.as_str().as_bytes());
1940 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1941 rbml_w.start_tag(tag_crate_hash);
1942 rbml_w.writer.write(hash.as_str().as_bytes());
1946 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1947 rbml_w.start_tag(tag_crate_crate_name);
1948 rbml_w.writer.write(crate_name.as_bytes());
1952 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1953 rbml_w.start_tag(tag_crate_triple);
1954 rbml_w.writer.write(triple.as_bytes());
1958 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
1959 rbml_w.start_tag(tag_dylib_dependency_formats);
1960 match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1962 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1963 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1964 cstore::RequireDynamic => "d",
1965 cstore::RequireStatic => "s",
1967 }).collect::<Vec<String>>();
1968 rbml_w.writer.write(s.connect(",").as_bytes());
1975 // NB: Increment this as you change the metadata encoding version.
1976 #[allow(non_upper_case_globals)]
1977 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
1979 pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
1980 let mut wr = SeekableMemWriter::new();
1981 encode_metadata_inner(&mut wr, parms, krate);
1982 let mut v = wr.unwrap();
1984 // And here we run into yet another obscure archive bug: in which metadata
1985 // loaded from archives may have trailing garbage bytes. Awhile back one of
1986 // our tests was failing sporadially on the OSX 64-bit builders (both nopt
1987 // and opt) by having rbml generate an out-of-bounds panic when looking at
1990 // Upon investigation it turned out that the metadata file inside of an rlib
1991 // (and ar archive) was being corrupted. Some compilations would generate a
1992 // metadata file which would end in a few extra bytes, while other
1993 // compilations would not have these extra bytes appended to the end. These
1994 // extra bytes were interpreted by rbml as an extra tag, so they ended up
1995 // being interpreted causing the out-of-bounds.
1997 // The root cause of why these extra bytes were appearing was never
1998 // discovered, and in the meantime the solution we're employing is to insert
1999 // the length of the metadata to the start of the metadata. Later on this
2000 // will allow us to slice the metadata to the precise length that we just
2001 // generated regardless of trailing bytes that end up in it.
2002 let len = v.len() as u32;
2003 v.insert(0, (len >> 0) as u8);
2004 v.insert(0, (len >> 8) as u8);
2005 v.insert(0, (len >> 16) as u8);
2006 v.insert(0, (len >> 24) as u8);
2010 fn encode_metadata_inner(wr: &mut SeekableMemWriter,
2011 parms: EncodeParams,
2012 krate: &ast::Crate) {
2016 lang_item_bytes: u64,
2017 native_lib_bytes: u64,
2018 plugin_registrar_fn_bytes: u64,
2019 macro_defs_bytes: u64,
2020 unboxed_closure_bytes: u64,
2028 let mut stats = Stats {
2032 native_lib_bytes: 0,
2033 plugin_registrar_fn_bytes: 0,
2034 macro_defs_bytes: 0,
2035 unboxed_closure_bytes: 0,
2049 encode_inlined_item,
2054 let ecx = EncodeContext {
2057 reexports2: reexports2,
2058 item_symbols: item_symbols,
2059 link_meta: link_meta,
2061 encode_inlined_item: RefCell::new(encode_inlined_item),
2062 type_abbrevs: RefCell::new(FnvHashMap::new()),
2063 reachable: reachable,
2066 let mut rbml_w = writer::Encoder::new(wr);
2068 encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.as_slice());
2069 encode_crate_triple(&mut rbml_w,
2074 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2075 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2077 let mut i = rbml_w.writer.tell().unwrap();
2078 encode_attributes(&mut rbml_w, krate.attrs.as_slice());
2079 stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
2081 i = rbml_w.writer.tell().unwrap();
2082 encode_crate_deps(&mut rbml_w, ecx.cstore);
2083 stats.dep_bytes = rbml_w.writer.tell().unwrap() - i;
2085 // Encode the language items.
2086 i = rbml_w.writer.tell().unwrap();
2087 encode_lang_items(&ecx, &mut rbml_w);
2088 stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i;
2090 // Encode the native libraries used
2091 i = rbml_w.writer.tell().unwrap();
2092 encode_native_libraries(&ecx, &mut rbml_w);
2093 stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i;
2095 // Encode the plugin registrar function
2096 i = rbml_w.writer.tell().unwrap();
2097 encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2098 stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
2100 // Encode macro definitions
2101 i = rbml_w.writer.tell().unwrap();
2102 encode_macro_defs(&ecx, krate, &mut rbml_w);
2103 stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
2105 // Encode the types of all unboxed closures in this crate.
2106 i = rbml_w.writer.tell().unwrap();
2107 encode_unboxed_closures(&ecx, &mut rbml_w);
2108 stats.unboxed_closure_bytes = rbml_w.writer.tell().unwrap() - i;
2110 // Encode the def IDs of impls, for coherence checking.
2111 i = rbml_w.writer.tell().unwrap();
2112 encode_impls(&ecx, krate, &mut rbml_w);
2113 stats.impl_bytes = rbml_w.writer.tell().unwrap() - i;
2115 // Encode miscellaneous info.
2116 i = rbml_w.writer.tell().unwrap();
2117 encode_misc_info(&ecx, krate, &mut rbml_w);
2118 encode_reachable_extern_fns(&ecx, &mut rbml_w);
2119 stats.misc_bytes = rbml_w.writer.tell().unwrap() - i;
2121 // Encode and index the items.
2122 rbml_w.start_tag(tag_items);
2123 i = rbml_w.writer.tell().unwrap();
2124 let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2125 stats.item_bytes = rbml_w.writer.tell().unwrap() - i;
2127 i = rbml_w.writer.tell().unwrap();
2128 encode_index(&mut rbml_w, items_index, write_i64);
2129 stats.index_bytes = rbml_w.writer.tell().unwrap() - i;
2132 encode_struct_field_attrs(&mut rbml_w, krate);
2134 stats.total_bytes = rbml_w.writer.tell().unwrap();
2136 if tcx.sess.meta_stats() {
2137 for e in rbml_w.writer.get_ref().iter() {
2139 stats.zero_bytes += 1;
2143 println!("metadata stats:");
2144 println!(" attribute bytes: {}", stats.attr_bytes);
2145 println!(" dep bytes: {}", stats.dep_bytes);
2146 println!(" lang item bytes: {}", stats.lang_item_bytes);
2147 println!(" native bytes: {}", stats.native_lib_bytes);
2148 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2149 println!(" macro def bytes: {}", stats.macro_defs_bytes);
2150 println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
2151 println!(" impl bytes: {}", stats.impl_bytes);
2152 println!(" misc bytes: {}", stats.misc_bytes);
2153 println!(" item bytes: {}", stats.item_bytes);
2154 println!(" index bytes: {}", stats.index_bytes);
2155 println!(" zero bytes: {}", stats.zero_bytes);
2156 println!(" total bytes: {}", stats.total_bytes);
2160 // Get the encoded string for a type
2161 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2162 let mut wr = SeekableMemWriter::new();
2163 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
2164 diag: tcx.sess.diagnostic(),
2167 abbrevs: &RefCell::new(FnvHashMap::new())
2169 String::from_utf8(wr.unwrap()).unwrap()