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)]
18 use metadata::common::*;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use middle::subst::VecPerParamSpace;
23 use middle::ty::{node_id_to_type, lookup_item_type};
24 use middle::astencode;
27 use middle::stability;
29 use util::io::SeekableMemWriter;
30 use util::nodemap::{NodeMap, NodeSet};
32 use serialize::Encodable;
33 use std::cell::RefCell;
38 use std::collections::HashMap;
42 use syntax::ast_map::{PathElem, PathElems};
44 use syntax::ast_util::*;
46 use syntax::ast_util::PostExpansionMethod;
48 use syntax::attr::AttrMetaMethods;
49 use syntax::diagnostic::SpanHandler;
50 use syntax::parse::token::special_idents;
51 use syntax::parse::token;
52 use syntax::visit::Visitor;
55 use writer = serialize::ebml::writer;
57 /// A borrowed version of ast::InlinedItem.
58 pub enum InlinedItemRef<'a> {
59 IIItemRef(&'a ast::Item),
60 IIMethodRef(ast::DefId, bool, &'a ast::Method),
61 IIForeignRef(&'a ast::ForeignItem)
64 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
66 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
68 ii: InlinedItemRef|: 'a;
70 pub struct EncodeParams<'a> {
71 pub diag: &'a SpanHandler,
72 pub tcx: &'a ty::ctxt,
73 pub reexports2: &'a middle::resolve::ExportMap2,
74 pub item_symbols: &'a RefCell<NodeMap<String>>,
75 pub non_inlineable_statics: &'a RefCell<NodeSet>,
76 pub link_meta: &'a LinkMeta,
77 pub cstore: &'a cstore::CStore,
78 pub encode_inlined_item: EncodeInlinedItem<'a>,
79 pub reachable: &'a NodeSet,
82 pub struct EncodeContext<'a> {
83 pub diag: &'a SpanHandler,
84 pub tcx: &'a ty::ctxt,
85 pub reexports2: &'a middle::resolve::ExportMap2,
86 pub item_symbols: &'a RefCell<NodeMap<String>>,
87 pub non_inlineable_statics: &'a RefCell<NodeSet>,
88 pub link_meta: &'a LinkMeta,
89 pub cstore: &'a cstore::CStore,
90 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
91 pub type_abbrevs: tyencode::abbrev_map,
92 pub reachable: &'a NodeSet,
95 fn encode_name(ebml_w: &mut Encoder, name: Name) {
96 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
99 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
100 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
103 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
104 ebml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice());
113 fn encode_trait_ref(ebml_w: &mut Encoder,
115 trait_ref: &ty::TraitRef,
117 let ty_str_ctxt = &tyencode::ctxt {
121 abbrevs: &ecx.type_abbrevs
124 ebml_w.start_tag(tag);
125 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
129 fn encode_impl_vtables(ebml_w: &mut Encoder,
131 vtables: &typeck::vtable_res) {
132 ebml_w.start_tag(tag_item_impl_vtables);
133 astencode::encode_vtable_res(ecx, ebml_w, vtables);
137 // Item info table encoding
138 fn encode_family(ebml_w: &mut Encoder, c: char) {
139 ebml_w.start_tag(tag_items_data_item_family);
140 ebml_w.writer.write(&[c as u8]);
144 pub fn def_to_string(did: DefId) -> String {
145 format!("{}:{}", did.krate, did.node)
148 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
150 params: &VecPerParamSpace<ty::TypeParameterDef>,
152 let ty_str_ctxt = &tyencode::ctxt {
156 abbrevs: &ecx.type_abbrevs
158 for param in params.iter() {
159 ebml_w.start_tag(tag);
160 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
165 fn encode_region_param_defs(ebml_w: &mut Encoder,
166 params: &VecPerParamSpace<ty::RegionParameterDef>) {
167 for param in params.iter() {
168 ebml_w.start_tag(tag_region_param_def);
170 ebml_w.start_tag(tag_region_param_def_ident);
171 encode_name(ebml_w, param.name);
174 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
175 def_to_string(param.def_id).as_slice());
177 ebml_w.wr_tagged_u64(tag_region_param_def_space,
178 param.space.to_uint() as u64);
180 ebml_w.wr_tagged_u64(tag_region_param_def_index,
187 fn encode_item_variances(ebml_w: &mut Encoder,
190 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
191 ebml_w.start_tag(tag_item_variances);
196 fn encode_bounds_and_type(ebml_w: &mut Encoder,
198 pty: &ty::Polytype) {
199 encode_ty_type_param_defs(ebml_w, ecx, &pty.generics.types,
200 tag_items_data_item_ty_param_bounds);
201 encode_region_param_defs(ebml_w, &pty.generics.regions);
202 encode_type(ecx, ebml_w, pty.ty);
205 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
206 ebml_w.start_tag(tag_items_data_item_variant);
207 let s = def_to_string(vid);
208 ebml_w.writer.write(s.as_bytes());
212 pub fn write_closure_type(ecx: &EncodeContext,
213 ebml_w: &mut Encoder,
214 closure_type: &ty::ClosureTy) {
215 let ty_str_ctxt = &tyencode::ctxt {
219 abbrevs: &ecx.type_abbrevs
221 tyencode::enc_closure_ty(ebml_w.writer, ty_str_ctxt, closure_type);
224 pub fn write_type(ecx: &EncodeContext,
225 ebml_w: &mut Encoder,
227 let ty_str_ctxt = &tyencode::ctxt {
231 abbrevs: &ecx.type_abbrevs
233 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
236 fn encode_type(ecx: &EncodeContext,
237 ebml_w: &mut Encoder,
239 ebml_w.start_tag(tag_items_data_item_type);
240 write_type(ecx, ebml_w, typ);
244 fn encode_method_fty(ecx: &EncodeContext,
245 ebml_w: &mut Encoder,
246 typ: &ty::BareFnTy) {
247 ebml_w.start_tag(tag_item_method_fty);
249 let ty_str_ctxt = &tyencode::ctxt {
253 abbrevs: &ecx.type_abbrevs
255 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
260 fn encode_symbol(ecx: &EncodeContext,
261 ebml_w: &mut Encoder,
263 ebml_w.start_tag(tag_items_data_item_symbol);
264 match ecx.item_symbols.borrow().find(&id) {
266 debug!("encode_symbol(id={:?}, str={})", id, *x);
267 ebml_w.writer.write(x.as_bytes());
270 ecx.diag.handler().bug(
271 format!("encode_symbol: id not found {}", id).as_slice());
277 fn encode_disr_val(_: &EncodeContext,
278 ebml_w: &mut Encoder,
279 disr_val: ty::Disr) {
280 ebml_w.start_tag(tag_disr_val);
281 let s = disr_val.to_string();
282 ebml_w.writer.write(s.as_bytes());
286 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
287 ebml_w.start_tag(tag_items_data_parent_item);
288 let s = def_to_string(id);
289 ebml_w.writer.write(s.as_bytes());
293 fn encode_struct_fields(ebml_w: &mut Encoder,
294 fields: &[ty::field_ty],
296 for f in fields.iter() {
297 if f.name == special_idents::unnamed_field.name {
298 ebml_w.start_tag(tag_item_unnamed_field);
300 ebml_w.start_tag(tag_item_field);
301 encode_name(ebml_w, f.name);
303 encode_struct_field_family(ebml_w, f.vis);
304 encode_def_id(ebml_w, f.id);
305 ebml_w.start_tag(tag_item_field_origin);
306 let s = def_to_string(origin);
307 ebml_w.writer.write(s.as_bytes());
313 fn encode_enum_variant_info(ecx: &EncodeContext,
314 ebml_w: &mut Encoder,
316 variants: &[P<Variant>],
317 index: &mut Vec<entry<i64>>) {
318 debug!("encode_enum_variant_info(id={:?})", id);
320 let mut disr_val = 0;
322 let vi = ty::enum_variants(ecx.tcx,
323 ast::DefId { krate: LOCAL_CRATE, node: id });
324 for variant in variants.iter() {
325 let def_id = local_def(variant.node.id);
327 val: variant.node.id as i64,
328 pos: ebml_w.writer.tell().unwrap(),
330 ebml_w.start_tag(tag_items_data_item);
331 encode_def_id(ebml_w, def_id);
332 match variant.node.kind {
333 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
334 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
336 encode_name(ebml_w, variant.node.name.name);
337 encode_parent_item(ebml_w, local_def(id));
338 encode_visibility(ebml_w, variant.node.vis);
339 encode_attributes(ebml_w, variant.node.attrs.as_slice());
341 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
342 encode_stability(ebml_w, stab);
344 match variant.node.kind {
345 ast::TupleVariantKind(_) => {},
346 ast::StructVariantKind(_) => {
347 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
348 let idx = encode_info_for_struct(ecx,
352 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
353 encode_index(ebml_w, idx, write_i64);
356 if vi.get(i).disr_val != disr_val {
357 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
358 disr_val = vi.get(i).disr_val;
360 encode_bounds_and_type(ebml_w, ecx,
361 &lookup_item_type(ecx.tcx, def_id));
363 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
370 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
372 ebml_w.start_tag(tag_path);
373 ebml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
376 ast_map::PathMod(_) => tag_path_elem_mod,
377 ast_map::PathName(_) => tag_path_elem_name
379 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
384 fn encode_reexported_static_method(ebml_w: &mut Encoder,
385 exp: &middle::resolve::Export2,
386 method_def_id: DefId,
387 method_ident: Ident) {
388 debug!("(encode reexported static method) {}::{}",
389 exp.name, token::get_ident(method_ident));
390 ebml_w.start_tag(tag_items_data_item_reexport);
391 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
392 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
394 ebml_w.start_tag(tag_items_data_item_reexport_name);
395 ebml_w.wr_str(format!("{}::{}",
397 token::get_ident(method_ident)).as_slice());
402 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
403 ebml_w: &mut Encoder,
404 exp: &middle::resolve::Export2)
406 let impl_methods = ecx.tcx.impl_methods.borrow();
407 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
408 Some(implementations) => {
409 for base_impl_did in implementations.borrow().iter() {
410 for &method_did in impl_methods.get(base_impl_did).iter() {
411 let m = ty::method(ecx.tcx, method_did);
412 if m.explicit_self == ty::StaticExplicitSelfCategory {
413 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
424 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
425 ebml_w: &mut Encoder,
426 exp: &middle::resolve::Export2)
428 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
430 for m in methods.iter() {
431 if m.explicit_self == ty::StaticExplicitSelfCategory {
432 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
442 fn encode_reexported_static_methods(ecx: &EncodeContext,
443 ebml_w: &mut Encoder,
445 exp: &middle::resolve::Export2) {
446 match ecx.tcx.map.find(exp.def_id.node) {
447 Some(ast_map::NodeItem(item)) => {
448 let original_name = token::get_ident(item.ident);
450 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
451 let (mut a, mut b) = (path, mod_path.clone());
453 match (a.next(), b.next()) {
454 (None, None) => return true,
455 (None, _) | (_, None) => return false,
456 (Some(x), Some(y)) => if x != y { return false },
462 // We don't need to reexport static methods on items
463 // declared in the same module as our `pub use ...` since
464 // that's done when we encode the item itself.
466 // The only exception is when the reexport *changes* the
467 // name e.g. `pub use Foo = self::Bar` -- we have
468 // encoded metadata for static methods relative to Bar,
469 // but not yet for Foo.
471 if path_differs || original_name.get() != exp.name.as_slice() {
472 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
473 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
474 debug!("(encode reexported static methods) {} \
480 debug!("(encode reexported static methods) {} [base]",
489 /// Iterates through "auxiliary node IDs", which are node IDs that describe
490 /// top-level items that are sub-items of the given item. Specifically:
492 /// * For enums, iterates through the node IDs of the variants.
494 /// * For newtype structs, iterates through the node ID of the constructor.
495 fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
496 let mut continue_ = true;
498 ItemEnum(ref enum_def, _) => {
499 for variant in enum_def.variants.iter() {
500 continue_ = callback(variant.node.id);
506 ItemStruct(struct_def, _) => {
507 // If this is a newtype struct, return the constructor.
508 match struct_def.ctor_id {
509 Some(ctor_id) if struct_def.fields.len() > 0 &&
510 struct_def.fields.get(0).node.kind.is_unnamed() => {
511 continue_ = callback(ctor_id);
522 fn encode_reexports(ecx: &EncodeContext,
523 ebml_w: &mut Encoder,
526 debug!("(encoding info for module) encoding reexports for {}", id);
527 match ecx.reexports2.borrow().find(&id) {
528 Some(ref exports) => {
529 debug!("(encoding info for module) found reexports for {}", id);
530 for exp in exports.iter() {
531 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
537 ebml_w.start_tag(tag_items_data_item_reexport);
538 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
539 ebml_w.wr_str(def_to_string(exp.def_id).as_slice());
541 ebml_w.start_tag(tag_items_data_item_reexport_name);
542 ebml_w.wr_str(exp.name.as_slice());
545 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
549 debug!("(encoding info for module) found no reexports for {}",
555 fn encode_info_for_mod(ecx: &EncodeContext,
556 ebml_w: &mut Encoder,
563 ebml_w.start_tag(tag_items_data_item);
564 encode_def_id(ebml_w, local_def(id));
565 encode_family(ebml_w, 'm');
566 encode_name(ebml_w, name.name);
567 debug!("(encoding info for module) encoding info for module ID {}", id);
569 // Encode info about all the module children.
570 for item in md.items.iter() {
571 ebml_w.start_tag(tag_mod_child);
572 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
575 each_auxiliary_node_id(*item, |auxiliary_node_id| {
576 ebml_w.start_tag(tag_mod_child);
577 ebml_w.wr_str(def_to_string(local_def(
578 auxiliary_node_id)).as_slice());
585 let (ident, did) = (item.ident, item.id);
586 debug!("(encoding info for module) ... encoding impl {} \
588 token::get_ident(ident),
589 did, ecx.tcx.map.node_to_string(did));
591 ebml_w.start_tag(tag_mod_impl);
592 ebml_w.wr_str(def_to_string(local_def(did)).as_slice());
599 encode_path(ebml_w, path.clone());
600 encode_visibility(ebml_w, vis);
602 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
603 encode_stability(ebml_w, stab);
605 // Encode the reexports of this module, if this module is public.
607 debug!("(encoding info for module) encoding reexports for {}", id);
608 encode_reexports(ecx, ebml_w, id, path);
610 encode_attributes(ebml_w, attrs);
615 fn encode_struct_field_family(ebml_w: &mut Encoder,
616 visibility: Visibility) {
617 encode_family(ebml_w, match visibility {
623 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
624 ebml_w.start_tag(tag_items_data_item_visibility);
625 let ch = match visibility {
629 ebml_w.wr_str(ch.to_string().as_slice());
633 fn encode_explicit_self(ebml_w: &mut Encoder,
634 explicit_self: &ty::ExplicitSelfCategory) {
635 ebml_w.start_tag(tag_item_trait_method_explicit_self);
637 // Encode the base self type.
638 match *explicit_self {
639 ty::StaticExplicitSelfCategory => {
640 ebml_w.writer.write(&[ 's' as u8 ]);
642 ty::ByValueExplicitSelfCategory => {
643 ebml_w.writer.write(&[ 'v' as u8 ]);
645 ty::ByBoxExplicitSelfCategory => {
646 ebml_w.writer.write(&[ '~' as u8 ]);
648 ty::ByReferenceExplicitSelfCategory(_, m) => {
649 // FIXME(#4846) encode custom lifetime
650 ebml_w.writer.write(&['&' as u8]);
651 encode_mutability(ebml_w, m);
657 fn encode_mutability(ebml_w: &mut Encoder,
658 m: ast::Mutability) {
660 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
661 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
666 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
667 ebml_w.start_tag(tag_item_trait_method_sort);
668 ebml_w.writer.write(&[ sort as u8 ]);
672 fn encode_provided_source(ebml_w: &mut Encoder,
673 source_opt: Option<DefId>) {
674 for source in source_opt.iter() {
675 ebml_w.start_tag(tag_item_method_provided_source);
676 let s = def_to_string(*source);
677 ebml_w.writer.write(s.as_bytes());
682 /* Returns an index of items in this class */
683 fn encode_info_for_struct(ecx: &EncodeContext,
684 ebml_w: &mut Encoder,
685 fields: &[ty::field_ty],
686 global_index: &mut Vec<entry<i64>>)
688 /* Each class has its own index, since different classes
689 may have fields with the same name */
690 let mut index = Vec::new();
692 /* We encode both private and public fields -- need to include
693 private fields to get the offsets right */
694 for field in fields.iter() {
696 let id = field.id.node;
698 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
699 global_index.push(entry {
701 pos: ebml_w.writer.tell().unwrap(),
703 ebml_w.start_tag(tag_items_data_item);
704 debug!("encode_info_for_struct: doing {} {}",
705 token::get_name(nm), id);
706 encode_struct_field_family(ebml_w, field.vis);
707 encode_name(ebml_w, nm);
708 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
709 encode_def_id(ebml_w, local_def(id));
711 let stab = stability::lookup(ecx.tcx, field.id);
712 encode_stability(ebml_w, stab);
719 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
720 ebml_w: &mut Encoder,
723 index: &mut Vec<entry<i64>>,
727 pos: ebml_w.writer.tell().unwrap(),
730 ebml_w.start_tag(tag_items_data_item);
731 encode_def_id(ebml_w, local_def(ctor_id));
732 encode_family(ebml_w, 'f');
733 encode_bounds_and_type(ebml_w, ecx,
734 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
735 encode_name(ebml_w, name.name);
736 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
737 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
738 encode_parent_item(ebml_w, local_def(struct_id));
740 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
741 encode_symbol(ecx, ebml_w, ctor_id);
744 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
745 encode_stability(ebml_w, stab);
747 // indicate that this is a tuple struct ctor, because downstream users will normally want
748 // the tuple struct definition, but without this there is no way for them to tell that
749 // they actually have a ctor rather than a normal function
750 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
756 fn encode_method_ty_fields(ecx: &EncodeContext,
757 ebml_w: &mut Encoder,
758 method_ty: &ty::Method) {
759 encode_def_id(ebml_w, method_ty.def_id);
760 encode_name(ebml_w, method_ty.ident.name);
761 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
762 tag_item_method_tps);
763 encode_method_fty(ecx, ebml_w, &method_ty.fty);
764 encode_visibility(ebml_w, method_ty.vis);
765 encode_explicit_self(ebml_w, &method_ty.explicit_self);
766 let fn_style = method_ty.fty.fn_style;
767 match method_ty.explicit_self {
768 ty::StaticExplicitSelfCategory => {
769 encode_family(ebml_w, fn_style_static_method_family(fn_style));
771 _ => encode_family(ebml_w, style_fn_family(fn_style))
773 encode_provided_source(ebml_w, method_ty.provided_source);
776 fn encode_info_for_method(ecx: &EncodeContext,
777 ebml_w: &mut Encoder,
779 impl_path: PathElems,
780 is_default_impl: bool,
782 ast_method_opt: Option<Gc<Method>>) {
784 debug!("encode_info_for_method: {:?} {}", m.def_id,
785 token::get_ident(m.ident));
786 ebml_w.start_tag(tag_items_data_item);
788 encode_method_ty_fields(ecx, ebml_w, m);
789 encode_parent_item(ebml_w, local_def(parent_id));
791 let stab = stability::lookup(ecx.tcx, m.def_id);
792 encode_stability(ebml_w, stab);
794 // The type for methods gets encoded twice, which is unfortunate.
795 let pty = lookup_item_type(ecx.tcx, m.def_id);
796 encode_bounds_and_type(ebml_w, ecx, &pty);
798 let elem = ast_map::PathName(m.ident.name);
799 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
800 match ast_method_opt {
801 Some(ast_method) => {
802 encode_attributes(ebml_w, ast_method.attrs.as_slice())
807 for &ast_method in ast_method_opt.iter() {
808 let any_types = !pty.generics.types.is_empty();
809 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
810 encode_inlined_item(ecx, ebml_w,
811 IIMethodRef(local_def(parent_id), false,
814 encode_symbol(ecx, ebml_w, m.def_id.node);
816 encode_method_argument_names(ebml_w, &*ast_method.pe_fn_decl());
822 fn encode_method_argument_names(ebml_w: &mut Encoder,
823 decl: &ast::FnDecl) {
824 ebml_w.start_tag(tag_method_argument_names);
825 for arg in decl.inputs.iter() {
826 ebml_w.start_tag(tag_method_argument_name);
828 ast::PatIdent(_, ref path1, _) => {
829 let name = token::get_ident(path1.node);
830 ebml_w.writer.write(name.get().as_bytes());
839 fn encode_inlined_item(ecx: &EncodeContext,
840 ebml_w: &mut Encoder,
841 ii: InlinedItemRef) {
842 let mut eii = ecx.encode_inlined_item.borrow_mut();
843 let eii: &mut EncodeInlinedItem = &mut *eii;
844 (*eii)(ecx, ebml_w, ii)
847 fn style_fn_family(s: FnStyle) -> char {
854 fn fn_style_static_method_family(s: FnStyle) -> char {
862 fn should_inline(attrs: &[Attribute]) -> bool {
864 match find_inline_attr(attrs) {
865 InlineNone | InlineNever => false,
866 InlineHint | InlineAlways => true
870 // Encodes the inherent implementations of a structure, enumeration, or trait.
871 fn encode_inherent_implementations(ecx: &EncodeContext,
872 ebml_w: &mut Encoder,
874 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
876 Some(implementations) => {
877 for &impl_def_id in implementations.borrow().iter() {
878 ebml_w.start_tag(tag_items_data_item_inherent_impl);
879 encode_def_id(ebml_w, impl_def_id);
886 // Encodes the implementations of a trait defined in this crate.
887 fn encode_extension_implementations(ecx: &EncodeContext,
888 ebml_w: &mut Encoder,
889 trait_def_id: DefId) {
890 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
892 Some(implementations) => {
893 for &impl_def_id in implementations.borrow().iter() {
894 ebml_w.start_tag(tag_items_data_item_extension_impl);
895 encode_def_id(ebml_w, impl_def_id);
902 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
903 stab_opt.map(|stab| {
904 ebml_w.start_tag(tag_items_data_item_stability);
905 stab.encode(ebml_w).unwrap();
910 fn encode_info_for_item(ecx: &EncodeContext,
911 ebml_w: &mut Encoder,
913 index: &mut Vec<entry<i64>>,
915 vis: ast::Visibility) {
918 fn add_to_index(item: &Item, ebml_w: &Encoder,
919 index: &mut Vec<entry<i64>>) {
922 pos: ebml_w.writer.tell().unwrap(),
926 debug!("encoding info for item at {}",
927 tcx.sess.codemap().span_to_string(item.span));
929 let def_id = local_def(item.id);
930 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
933 ItemStatic(_, m, _) => {
934 add_to_index(item, ebml_w, index);
935 ebml_w.start_tag(tag_items_data_item);
936 encode_def_id(ebml_w, def_id);
937 if m == ast::MutMutable {
938 encode_family(ebml_w, 'b');
940 encode_family(ebml_w, 'c');
942 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
943 encode_symbol(ecx, ebml_w, item.id);
944 encode_name(ebml_w, item.ident.name);
945 encode_path(ebml_w, path);
947 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
950 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
952 encode_visibility(ebml_w, vis);
953 encode_stability(ebml_w, stab);
956 ItemFn(ref decl, fn_style, _, ref generics, _) => {
957 add_to_index(item, ebml_w, index);
958 ebml_w.start_tag(tag_items_data_item);
959 encode_def_id(ebml_w, def_id);
960 encode_family(ebml_w, style_fn_family(fn_style));
961 let tps_len = generics.ty_params.len();
962 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
963 encode_name(ebml_w, item.ident.name);
964 encode_path(ebml_w, path);
965 encode_attributes(ebml_w, item.attrs.as_slice());
966 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
967 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
969 encode_symbol(ecx, ebml_w, item.id);
971 encode_visibility(ebml_w, vis);
972 encode_stability(ebml_w, stab);
973 encode_method_argument_names(ebml_w, &**decl);
977 add_to_index(item, ebml_w, index);
978 encode_info_for_mod(ecx,
981 item.attrs.as_slice(),
987 ItemForeignMod(ref fm) => {
988 add_to_index(item, ebml_w, index);
989 ebml_w.start_tag(tag_items_data_item);
990 encode_def_id(ebml_w, def_id);
991 encode_family(ebml_w, 'n');
992 encode_name(ebml_w, item.ident.name);
993 encode_path(ebml_w, path);
995 // Encode all the items in this module.
996 for foreign_item in fm.items.iter() {
997 ebml_w.start_tag(tag_mod_child);
998 ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
1001 encode_visibility(ebml_w, vis);
1002 encode_stability(ebml_w, stab);
1006 add_to_index(item, ebml_w, index);
1007 ebml_w.start_tag(tag_items_data_item);
1008 encode_def_id(ebml_w, def_id);
1009 encode_family(ebml_w, 'y');
1010 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1011 encode_name(ebml_w, item.ident.name);
1012 encode_path(ebml_w, path);
1013 encode_visibility(ebml_w, vis);
1014 encode_stability(ebml_w, stab);
1017 ItemEnum(ref enum_definition, _) => {
1018 add_to_index(item, ebml_w, index);
1020 ebml_w.start_tag(tag_items_data_item);
1021 encode_def_id(ebml_w, def_id);
1022 encode_family(ebml_w, 't');
1023 encode_item_variances(ebml_w, ecx, item.id);
1024 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1025 encode_name(ebml_w, item.ident.name);
1026 encode_attributes(ebml_w, item.attrs.as_slice());
1027 for v in (*enum_definition).variants.iter() {
1028 encode_variant_id(ebml_w, local_def(v.node.id));
1030 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1031 encode_path(ebml_w, path);
1033 // Encode inherent implementations for this enumeration.
1034 encode_inherent_implementations(ecx, ebml_w, def_id);
1036 encode_visibility(ebml_w, vis);
1037 encode_stability(ebml_w, stab);
1040 encode_enum_variant_info(ecx,
1043 (*enum_definition).variants.as_slice(),
1046 ItemStruct(struct_def, _) => {
1047 let fields = ty::lookup_struct_fields(tcx, def_id);
1049 /* First, encode the fields
1050 These come first because we need to write them to make
1051 the index, and the index needs to be in the item for the
1053 let idx = encode_info_for_struct(ecx,
1058 /* Index the class*/
1059 add_to_index(item, ebml_w, index);
1061 /* Now, make an item for the class itself */
1062 ebml_w.start_tag(tag_items_data_item);
1063 encode_def_id(ebml_w, def_id);
1064 encode_family(ebml_w, 'S');
1065 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1067 encode_item_variances(ebml_w, ecx, item.id);
1068 encode_name(ebml_w, item.ident.name);
1069 encode_attributes(ebml_w, item.attrs.as_slice());
1070 encode_path(ebml_w, path.clone());
1071 encode_stability(ebml_w, stab);
1072 encode_visibility(ebml_w, vis);
1074 /* Encode def_ids for each field and method
1075 for methods, write all the stuff get_trait_method
1077 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1079 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1081 // Encode inherent implementations for this structure.
1082 encode_inherent_implementations(ecx, ebml_w, def_id);
1084 /* Each class has its own index -- encode it */
1085 encode_index(ebml_w, idx, write_i64);
1088 // If this is a tuple-like struct, encode the type of the constructor.
1089 match struct_def.ctor_id {
1091 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1092 ctor_id, index, def_id.node);
1097 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1098 // We need to encode information about the default methods we
1099 // have inherited, so we drive this based on the impl structure.
1100 let impl_methods = tcx.impl_methods.borrow();
1101 let methods = impl_methods.get(&def_id);
1103 add_to_index(item, ebml_w, index);
1104 ebml_w.start_tag(tag_items_data_item);
1105 encode_def_id(ebml_w, def_id);
1106 encode_family(ebml_w, 'i');
1107 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1108 encode_name(ebml_w, item.ident.name);
1109 encode_attributes(ebml_w, item.attrs.as_slice());
1111 ast::TyPath(ref path, ref bounds, _) if path.segments
1113 let ident = path.segments.last().unwrap().identifier;
1114 assert!(bounds.is_none());
1115 encode_impl_type_basename(ebml_w, ident);
1119 for &method_def_id in methods.iter() {
1120 ebml_w.start_tag(tag_item_impl_method);
1121 let s = def_to_string(method_def_id);
1122 ebml_w.writer.write(s.as_bytes());
1125 for ast_trait_ref in opt_trait.iter() {
1126 let trait_ref = ty::node_id_to_trait_ref(
1127 tcx, ast_trait_ref.ref_id);
1128 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1129 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1130 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1132 encode_path(ebml_w, path.clone());
1133 encode_stability(ebml_w, stab);
1136 // Iterate down the methods, emitting them. We rely on the
1137 // assumption that all of the actually implemented methods
1138 // appear first in the impl structure, in the same order they do
1139 // in the ast. This is a little sketchy.
1140 let num_implemented_methods = ast_methods.len();
1141 for (i, &method_def_id) in methods.iter().enumerate() {
1142 let ast_method = if i < num_implemented_methods {
1143 Some(*ast_methods.get(i))
1147 val: method_def_id.node as i64,
1148 pos: ebml_w.writer.tell().unwrap(),
1150 encode_info_for_method(ecx,
1152 &*ty::method(tcx, method_def_id),
1159 ItemTrait(_, _, ref super_traits, ref ms) => {
1160 add_to_index(item, ebml_w, index);
1161 ebml_w.start_tag(tag_items_data_item);
1162 encode_def_id(ebml_w, def_id);
1163 encode_family(ebml_w, 'I');
1164 encode_item_variances(ebml_w, ecx, item.id);
1165 let trait_def = ty::lookup_trait_def(tcx, def_id);
1166 encode_ty_type_param_defs(ebml_w, ecx,
1167 &trait_def.generics.types,
1168 tag_items_data_item_ty_param_bounds);
1169 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1170 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1171 encode_name(ebml_w, item.ident.name);
1172 encode_attributes(ebml_w, item.attrs.as_slice());
1173 encode_visibility(ebml_w, vis);
1174 encode_stability(ebml_w, stab);
1175 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1176 ebml_w.start_tag(tag_item_trait_method);
1177 encode_def_id(ebml_w, method_def_id);
1180 ebml_w.start_tag(tag_mod_child);
1181 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1184 encode_path(ebml_w, path.clone());
1185 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1186 // reading the AST's list, because the former has already filtered out
1187 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1188 for ast_trait_ref in super_traits.iter() {
1189 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1190 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1193 // Encode the implementations of this trait.
1194 encode_extension_implementations(ecx, ebml_w, def_id);
1198 // Now output the method info for each method.
1199 let r = ty::trait_method_def_ids(tcx, def_id);
1200 for (i, &method_def_id) in r.iter().enumerate() {
1201 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1203 let method_ty = ty::method(tcx, method_def_id);
1206 val: method_def_id.node as i64,
1207 pos: ebml_w.writer.tell().unwrap(),
1210 ebml_w.start_tag(tag_items_data_item);
1212 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1213 encode_parent_item(ebml_w, def_id);
1215 let stab = stability::lookup(tcx, method_def_id);
1216 encode_stability(ebml_w, stab);
1218 let elem = ast_map::PathName(method_ty.ident.name);
1219 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1221 match method_ty.explicit_self {
1222 ty::StaticExplicitSelfCategory => {
1223 encode_family(ebml_w,
1224 fn_style_static_method_family(
1225 method_ty.fty.fn_style));
1227 let pty = ty::lookup_item_type(tcx, method_def_id);
1228 encode_bounds_and_type(ebml_w, ecx, &pty);
1232 encode_family(ebml_w,
1234 method_ty.fty.fn_style));
1239 &Required(ref tm) => {
1240 encode_attributes(ebml_w, tm.attrs.as_slice());
1241 encode_method_sort(ebml_w, 'r');
1242 encode_method_argument_names(ebml_w, &*tm.decl);
1246 encode_attributes(ebml_w, m.attrs.as_slice());
1247 // If this is a static method, we've already encoded
1249 if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
1250 // FIXME: I feel like there is something funny going on.
1251 let pty = ty::lookup_item_type(tcx, method_def_id);
1252 encode_bounds_and_type(ebml_w, ecx, &pty);
1254 encode_method_sort(ebml_w, 'p');
1255 encode_inlined_item(ecx, ebml_w,
1256 IIMethodRef(def_id, true, &*m));
1257 encode_method_argument_names(ebml_w, &*m.pe_fn_decl());
1264 // Encode inherent implementations for this trait.
1265 encode_inherent_implementations(ecx, ebml_w, def_id);
1268 // macros are encoded separately
1273 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1274 ebml_w: &mut Encoder,
1275 nitem: &ForeignItem,
1276 index: &mut Vec<entry<i64>>,
1280 val: nitem.id as i64,
1281 pos: ebml_w.writer.tell().unwrap(),
1284 ebml_w.start_tag(tag_items_data_item);
1285 encode_def_id(ebml_w, local_def(nitem.id));
1287 ForeignItemFn(..) => {
1288 encode_family(ebml_w, style_fn_family(NormalFn));
1289 encode_bounds_and_type(ebml_w, ecx,
1290 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1291 encode_name(ebml_w, nitem.ident.name);
1292 if abi == abi::RustIntrinsic {
1293 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1295 encode_symbol(ecx, ebml_w, nitem.id);
1298 ForeignItemStatic(_, mutbl) => {
1300 encode_family(ebml_w, 'b');
1302 encode_family(ebml_w, 'c');
1304 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1305 encode_symbol(ecx, ebml_w, nitem.id);
1306 encode_name(ebml_w, nitem.ident.name);
1309 encode_path(ebml_w, path);
1313 fn my_visit_expr(_e: &Expr) { }
1315 fn my_visit_item(i: &Item,
1316 ebml_w: &mut Encoder,
1317 ecx_ptr: *const int,
1318 index: &mut Vec<entry<i64>>) {
1319 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1321 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1322 ecx.tcx.map.with_path(i.id, |path| {
1323 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1327 fn my_visit_foreign_item(ni: &ForeignItem,
1328 ebml_w: &mut Encoder,
1330 index: &mut Vec<entry<i64>>) {
1332 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1333 debug!("writing foreign item {}::{}",
1334 ecx.tcx.map.path_to_string(ni.id),
1335 token::get_ident(ni.ident));
1337 let mut ebml_w = unsafe {
1338 ebml_w.unsafe_clone()
1340 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1341 ecx.tcx.map.with_path(ni.id, |path| {
1342 encode_info_for_foreign_item(ecx, &mut ebml_w,
1348 struct EncodeVisitor<'a,'b> {
1349 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1351 index: &'a mut Vec<entry<i64>>,
1354 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1355 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1356 visit::walk_expr(self, ex, ());
1359 fn visit_item(&mut self, i: &Item, _: ()) {
1360 visit::walk_item(self, i, ());
1362 self.ebml_w_for_visit_item,
1366 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1367 visit::walk_foreign_item(self, ni, ());
1368 my_visit_foreign_item(ni,
1369 self.ebml_w_for_visit_item,
1375 fn encode_info_for_items(ecx: &EncodeContext,
1376 ebml_w: &mut Encoder,
1378 -> Vec<entry<i64>> {
1379 let mut index = Vec::new();
1380 ebml_w.start_tag(tag_items_data);
1382 val: CRATE_NODE_ID as i64,
1383 pos: ebml_w.writer.tell().unwrap(),
1385 encode_info_for_mod(ecx,
1390 ast_map::Values([].iter()).chain(None),
1391 syntax::parse::token::special_idents::invalid,
1394 // See comment in `encode_side_tables_for_ii` in astencode
1395 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1396 visit::walk_crate(&mut EncodeVisitor {
1399 ebml_w_for_visit_item: &mut *ebml_w,
1407 // Path and definition ID indexing
1409 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1410 write_fn: |&mut SeekableMemWriter, &T|) {
1411 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1412 for elt in index.move_iter() {
1413 let h = hash::hash(&elt.val) as uint;
1414 buckets.get_mut(h % 256).push(elt);
1417 ebml_w.start_tag(tag_index);
1418 let mut bucket_locs = Vec::new();
1419 ebml_w.start_tag(tag_index_buckets);
1420 for bucket in buckets.iter() {
1421 bucket_locs.push(ebml_w.writer.tell().unwrap());
1422 ebml_w.start_tag(tag_index_buckets_bucket);
1423 for elt in bucket.iter() {
1424 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1425 assert!(elt.pos < 0xffff_ffff);
1427 let wr: &mut SeekableMemWriter = ebml_w.writer;
1428 wr.write_be_u32(elt.pos as u32);
1430 write_fn(ebml_w.writer, &elt.val);
1436 ebml_w.start_tag(tag_index_table);
1437 for pos in bucket_locs.iter() {
1438 assert!(*pos < 0xffff_ffff);
1439 let wr: &mut SeekableMemWriter = ebml_w.writer;
1440 wr.write_be_u32(*pos as u32);
1446 fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1447 let wr: &mut SeekableMemWriter = writer;
1448 assert!(n < 0x7fff_ffff);
1449 wr.write_be_u32(n as u32);
1452 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1454 MetaWord(ref name) => {
1455 ebml_w.start_tag(tag_meta_item_word);
1456 ebml_w.start_tag(tag_meta_item_name);
1457 ebml_w.writer.write(name.get().as_bytes());
1461 MetaNameValue(ref name, ref value) => {
1463 LitStr(ref value, _) => {
1464 ebml_w.start_tag(tag_meta_item_name_value);
1465 ebml_w.start_tag(tag_meta_item_name);
1466 ebml_w.writer.write(name.get().as_bytes());
1468 ebml_w.start_tag(tag_meta_item_value);
1469 ebml_w.writer.write(value.get().as_bytes());
1473 _ => {/* FIXME (#623): encode other variants */ }
1476 MetaList(ref name, ref items) => {
1477 ebml_w.start_tag(tag_meta_item_list);
1478 ebml_w.start_tag(tag_meta_item_name);
1479 ebml_w.writer.write(name.get().as_bytes());
1481 for inner_item in items.iter() {
1482 encode_meta_item(ebml_w, *inner_item);
1489 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1490 ebml_w.start_tag(tag_attributes);
1491 for attr in attrs.iter() {
1492 ebml_w.start_tag(tag_attribute);
1493 ebml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1494 encode_meta_item(ebml_w, attr.node.value);
1500 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1501 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1502 // Pull the cnums and name,vers,hash out of cstore
1503 let mut deps = Vec::new();
1504 cstore.iter_crate_data(|key, val| {
1505 let dep = decoder::CrateDep {
1507 name: decoder::get_crate_name(val.data()),
1508 hash: decoder::get_crate_hash(val.data()),
1514 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1516 // Sanity-check the crate numbers
1517 let mut expected_cnum = 1;
1518 for n in deps.iter() {
1519 assert_eq!(n.cnum, expected_cnum);
1526 // We're just going to write a list of crate 'name-hash-version's, with
1527 // the assumption that they are numbered 1 to n.
1528 // FIXME (#2166): This is not nearly enough to support correct versioning
1529 // but is enough to get transitive crate dependencies working.
1530 ebml_w.start_tag(tag_crate_deps);
1531 let r = get_ordered_deps(cstore);
1532 for dep in r.iter() {
1533 encode_crate_dep(ebml_w, (*dep).clone());
1538 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1539 ebml_w.start_tag(tag_lang_items);
1541 for (i, def_id) in ecx.tcx.lang_items.items() {
1542 for id in def_id.iter() {
1543 if id.krate == LOCAL_CRATE {
1544 ebml_w.start_tag(tag_lang_items_item);
1546 ebml_w.start_tag(tag_lang_items_item_id);
1548 let wr: &mut SeekableMemWriter = ebml_w.writer;
1549 wr.write_be_u32(i as u32);
1551 ebml_w.end_tag(); // tag_lang_items_item_id
1553 ebml_w.start_tag(tag_lang_items_item_node_id);
1555 let wr: &mut SeekableMemWriter = ebml_w.writer;
1556 wr.write_be_u32(id.node as u32);
1558 ebml_w.end_tag(); // tag_lang_items_item_node_id
1560 ebml_w.end_tag(); // tag_lang_items_item
1565 for i in ecx.tcx.lang_items.missing.iter() {
1566 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1569 ebml_w.end_tag(); // tag_lang_items
1572 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1573 ebml_w.start_tag(tag_native_libraries);
1575 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1578 cstore::NativeStatic => {} // these libraries are not propagated
1579 cstore::NativeFramework | cstore::NativeUnknown => {
1580 ebml_w.start_tag(tag_native_libraries_lib);
1582 ebml_w.start_tag(tag_native_libraries_kind);
1583 ebml_w.writer.write_be_u32(kind as u32);
1586 ebml_w.start_tag(tag_native_libraries_name);
1587 ebml_w.writer.write(lib.as_bytes());
1598 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1599 match ecx.tcx.sess.plugin_registrar_fn.get() {
1600 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1605 /// Given a span, write the text of that span into the output stream
1606 /// as an exported macro
1607 fn encode_macro_def(ecx: &EncodeContext,
1608 ebml_w: &mut Encoder,
1609 span: &syntax::codemap::Span) {
1610 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1611 .expect("Unable to find source for macro");
1612 ebml_w.start_tag(tag_macro_def);
1613 ebml_w.wr_str(def.as_slice());
1617 /// Serialize the text of the exported macros
1618 fn encode_macro_defs(ecx: &EncodeContext,
1620 ebml_w: &mut Encoder) {
1621 ebml_w.start_tag(tag_exported_macros);
1622 for item in krate.exported_macros.iter() {
1623 encode_macro_def(ecx, ebml_w, &item.span);
1628 fn encode_unboxed_closures<'a>(
1629 ecx: &'a EncodeContext,
1630 ebml_w: &'a mut Encoder) {
1631 ebml_w.start_tag(tag_unboxed_closures);
1632 for (unboxed_closure_id, unboxed_closure_type) in
1633 ecx.tcx.unboxed_closure_types.borrow().iter() {
1634 if unboxed_closure_id.krate != LOCAL_CRATE {
1638 ebml_w.start_tag(tag_unboxed_closure);
1639 encode_def_id(ebml_w, *unboxed_closure_id);
1640 ebml_w.start_tag(tag_unboxed_closure_type);
1641 write_closure_type(ecx, ebml_w, unboxed_closure_type);
1648 fn encode_struct_field_attrs(ebml_w: &mut Encoder, krate: &Crate) {
1649 struct StructFieldVisitor<'a, 'b> {
1650 ebml_w: &'a mut Encoder<'b>,
1653 impl<'a, 'b> Visitor<()> for StructFieldVisitor<'a, 'b> {
1654 fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
1655 self.ebml_w.start_tag(tag_struct_field);
1656 self.ebml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1657 encode_attributes(self.ebml_w, field.node.attrs.as_slice());
1658 self.ebml_w.end_tag();
1662 ebml_w.start_tag(tag_struct_fields);
1663 visit::walk_crate(&mut StructFieldVisitor {
1671 struct ImplVisitor<'a,'b,'c> {
1672 ecx: &'a EncodeContext<'b>,
1673 ebml_w: &'a mut Encoder<'c>,
1676 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1677 fn visit_item(&mut self, item: &Item, _: ()) {
1679 ItemImpl(_, Some(ref trait_ref), _, _) => {
1680 let def_map = &self.ecx.tcx.def_map;
1681 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1682 let def_id = trait_def.def_id();
1684 // Load eagerly if this is an implementation of the Drop trait
1685 // or if the trait is not defined in this crate.
1686 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1687 def_id.krate != LOCAL_CRATE {
1688 self.ebml_w.start_tag(tag_impls_impl);
1689 encode_def_id(self.ebml_w, local_def(item.id));
1690 self.ebml_w.end_tag();
1695 visit::walk_item(self, item, ());
1699 /// Encodes implementations that are eagerly loaded.
1701 /// None of this is necessary in theory; we can load all implementations
1702 /// lazily. However, in two cases the optimizations to lazily load
1703 /// implementations are not yet implemented. These two cases, which require us
1704 /// to load implementations eagerly, are:
1706 /// * Destructors (implementations of the Drop trait).
1708 /// * Implementations of traits not defined in this crate.
1709 fn encode_impls<'a>(ecx: &'a EncodeContext,
1711 ebml_w: &'a mut Encoder) {
1712 ebml_w.start_tag(tag_impls);
1715 let mut visitor = ImplVisitor {
1719 visit::walk_crate(&mut visitor, krate, ());
1725 fn encode_misc_info(ecx: &EncodeContext,
1727 ebml_w: &mut Encoder) {
1728 ebml_w.start_tag(tag_misc_info);
1729 ebml_w.start_tag(tag_misc_info_crate_items);
1730 for &item in krate.module.items.iter() {
1731 ebml_w.start_tag(tag_mod_child);
1732 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1735 each_auxiliary_node_id(item, |auxiliary_node_id| {
1736 ebml_w.start_tag(tag_mod_child);
1737 ebml_w.wr_str(def_to_string(local_def(
1738 auxiliary_node_id)).as_slice());
1744 // Encode reexports for the root module.
1745 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1751 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1752 ebml_w.start_tag(tag_reachable_extern_fns);
1754 for id in ecx.reachable.iter() {
1755 match ecx.tcx.map.find(*id) {
1756 Some(ast_map::NodeItem(i)) => {
1758 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1759 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1771 fn encode_crate_dep(ebml_w: &mut Encoder,
1772 dep: decoder::CrateDep) {
1773 ebml_w.start_tag(tag_crate_dep);
1774 ebml_w.start_tag(tag_crate_dep_crate_name);
1775 ebml_w.writer.write(dep.name.as_bytes());
1777 ebml_w.start_tag(tag_crate_dep_hash);
1778 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1783 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1784 ebml_w.start_tag(tag_crate_hash);
1785 ebml_w.writer.write(hash.as_str().as_bytes());
1789 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1790 ebml_w.start_tag(tag_crate_crate_name);
1791 ebml_w.writer.write(crate_name.as_bytes());
1795 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1796 ebml_w.start_tag(tag_crate_triple);
1797 ebml_w.writer.write(triple.as_bytes());
1801 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1802 ebml_w.start_tag(tag_dylib_dependency_formats);
1803 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1805 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1806 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1807 cstore::RequireDynamic => "d",
1808 cstore::RequireStatic => "s",
1810 }).collect::<Vec<String>>();
1811 ebml_w.writer.write(s.connect(",").as_bytes());
1818 // NB: Increment this as you change the metadata encoding version.
1819 pub static metadata_encoding_version : &'static [u8] =
1820 &[0x72, //'r' as u8,
1826 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1827 let mut wr = SeekableMemWriter::new();
1828 encode_metadata_inner(&mut wr, parms, krate);
1829 wr.unwrap().move_iter().collect()
1832 fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate: &Crate) {
1836 lang_item_bytes: u64,
1837 native_lib_bytes: u64,
1838 plugin_registrar_fn_bytes: u64,
1839 macro_defs_bytes: u64,
1840 unboxed_closure_bytes: u64,
1848 let mut stats = Stats {
1852 native_lib_bytes: 0,
1853 plugin_registrar_fn_bytes: 0,
1854 macro_defs_bytes: 0,
1855 unboxed_closure_bytes: 0,
1869 encode_inlined_item,
1871 non_inlineable_statics,
1875 let ecx = EncodeContext {
1878 reexports2: reexports2,
1879 item_symbols: item_symbols,
1880 non_inlineable_statics: non_inlineable_statics,
1881 link_meta: link_meta,
1883 encode_inlined_item: RefCell::new(encode_inlined_item),
1884 type_abbrevs: RefCell::new(HashMap::new()),
1885 reachable: reachable,
1888 let mut ebml_w = writer::Encoder::new(wr);
1890 encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1891 encode_crate_triple(&mut ebml_w,
1897 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1898 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1900 let mut i = ebml_w.writer.tell().unwrap();
1901 encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1902 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1904 i = ebml_w.writer.tell().unwrap();
1905 encode_crate_deps(&mut ebml_w, ecx.cstore);
1906 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1908 // Encode the language items.
1909 i = ebml_w.writer.tell().unwrap();
1910 encode_lang_items(&ecx, &mut ebml_w);
1911 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1913 // Encode the native libraries used
1914 i = ebml_w.writer.tell().unwrap();
1915 encode_native_libraries(&ecx, &mut ebml_w);
1916 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1918 // Encode the plugin registrar function
1919 i = ebml_w.writer.tell().unwrap();
1920 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1921 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1923 // Encode macro definitions
1924 i = ebml_w.writer.tell().unwrap();
1925 encode_macro_defs(&ecx, krate, &mut ebml_w);
1926 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1928 // Encode the types of all unboxed closures in this crate.
1929 i = ebml_w.writer.tell().unwrap();
1930 encode_unboxed_closures(&ecx, &mut ebml_w);
1931 stats.unboxed_closure_bytes = ebml_w.writer.tell().unwrap() - i;
1933 // Encode the def IDs of impls, for coherence checking.
1934 i = ebml_w.writer.tell().unwrap();
1935 encode_impls(&ecx, krate, &mut ebml_w);
1936 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1938 // Encode miscellaneous info.
1939 i = ebml_w.writer.tell().unwrap();
1940 encode_misc_info(&ecx, krate, &mut ebml_w);
1941 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1942 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1944 // Encode and index the items.
1945 ebml_w.start_tag(tag_items);
1946 i = ebml_w.writer.tell().unwrap();
1947 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1948 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1950 i = ebml_w.writer.tell().unwrap();
1951 encode_index(&mut ebml_w, items_index, write_i64);
1952 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1955 encode_struct_field_attrs(&mut ebml_w, krate);
1957 stats.total_bytes = ebml_w.writer.tell().unwrap();
1959 if tcx.sess.meta_stats() {
1960 for e in ebml_w.writer.get_ref().iter() {
1962 stats.zero_bytes += 1;
1966 println!("metadata stats:");
1967 println!(" attribute bytes: {}", stats.attr_bytes);
1968 println!(" dep bytes: {}", stats.dep_bytes);
1969 println!(" lang item bytes: {}", stats.lang_item_bytes);
1970 println!(" native bytes: {}", stats.native_lib_bytes);
1971 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1972 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1973 println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
1974 println!(" impl bytes: {}", stats.impl_bytes);
1975 println!(" misc bytes: {}", stats.misc_bytes);
1976 println!(" item bytes: {}", stats.item_bytes);
1977 println!(" index bytes: {}", stats.index_bytes);
1978 println!(" zero bytes: {}", stats.zero_bytes);
1979 println!(" total bytes: {}", stats.total_bytes);
1983 // Get the encoded string for a type
1984 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1985 let mut wr = SeekableMemWriter::new();
1986 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1987 diag: tcx.sess.diagnostic(),
1990 abbrevs: &RefCell::new(HashMap::new())
1992 String::from_utf8(wr.unwrap()).unwrap()