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::nodemap::{NodeMap, NodeSet};
31 use serialize::Encodable;
32 use std::cell::RefCell;
36 use std::io::MemWriter;
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, MemWriter>;
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 generics: &ast::Generics) {
319 debug!("encode_enum_variant_info(id={:?})", id);
321 let mut disr_val = 0;
323 let vi = ty::enum_variants(ecx.tcx,
324 ast::DefId { krate: LOCAL_CRATE, node: id });
325 for variant in variants.iter() {
326 let def_id = local_def(variant.node.id);
328 val: variant.node.id as i64,
329 pos: ebml_w.writer.tell().unwrap(),
331 ebml_w.start_tag(tag_items_data_item);
332 encode_def_id(ebml_w, def_id);
333 match variant.node.kind {
334 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
335 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
337 encode_name(ebml_w, variant.node.name.name);
338 encode_parent_item(ebml_w, local_def(id));
339 encode_visibility(ebml_w, variant.node.vis);
340 encode_attributes(ebml_w, variant.node.attrs.as_slice());
342 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
343 encode_stability(ebml_w, stab);
345 match variant.node.kind {
346 ast::TupleVariantKind(ref args)
347 if args.len() > 0 && generics.ty_params.len() == 0 => {
348 encode_symbol(ecx, ebml_w, variant.node.id);
350 ast::TupleVariantKind(_) => {},
351 ast::StructVariantKind(_) => {
352 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
353 let idx = encode_info_for_struct(ecx,
357 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
358 encode_index(ebml_w, idx, write_i64);
361 if vi.get(i).disr_val != disr_val {
362 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
363 disr_val = vi.get(i).disr_val;
365 encode_bounds_and_type(ebml_w, ecx,
366 &lookup_item_type(ecx.tcx, def_id));
368 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
375 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
377 ebml_w.start_tag(tag_path);
378 ebml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
381 ast_map::PathMod(_) => tag_path_elem_mod,
382 ast_map::PathName(_) => tag_path_elem_name
384 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
389 fn encode_reexported_static_method(ebml_w: &mut Encoder,
390 exp: &middle::resolve::Export2,
391 method_def_id: DefId,
392 method_ident: Ident) {
393 debug!("(encode reexported static method) {}::{}",
394 exp.name, token::get_ident(method_ident));
395 ebml_w.start_tag(tag_items_data_item_reexport);
396 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
397 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
399 ebml_w.start_tag(tag_items_data_item_reexport_name);
400 ebml_w.wr_str(format!("{}::{}",
402 token::get_ident(method_ident)).as_slice());
407 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
408 ebml_w: &mut Encoder,
409 exp: &middle::resolve::Export2)
411 let impl_methods = ecx.tcx.impl_methods.borrow();
412 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
413 Some(implementations) => {
414 for base_impl_did in implementations.borrow().iter() {
415 for &method_did in impl_methods.get(base_impl_did).iter() {
416 let m = ty::method(ecx.tcx, method_did);
417 if m.explicit_self == ty::StaticExplicitSelfCategory {
418 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
429 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
430 ebml_w: &mut Encoder,
431 exp: &middle::resolve::Export2)
433 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
435 for m in methods.iter() {
436 if m.explicit_self == ty::StaticExplicitSelfCategory {
437 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
447 fn encode_reexported_static_methods(ecx: &EncodeContext,
448 ebml_w: &mut Encoder,
450 exp: &middle::resolve::Export2) {
451 match ecx.tcx.map.find(exp.def_id.node) {
452 Some(ast_map::NodeItem(item)) => {
453 let original_name = token::get_ident(item.ident);
455 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
456 let (mut a, mut b) = (path, mod_path.clone());
458 match (a.next(), b.next()) {
459 (None, None) => return true,
460 (None, _) | (_, None) => return false,
461 (Some(x), Some(y)) => if x != y { return false },
467 // We don't need to reexport static methods on items
468 // declared in the same module as our `pub use ...` since
469 // that's done when we encode the item itself.
471 // The only exception is when the reexport *changes* the
472 // name e.g. `pub use Foo = self::Bar` -- we have
473 // encoded metadata for static methods relative to Bar,
474 // but not yet for Foo.
476 if path_differs || original_name.get() != exp.name.as_slice() {
477 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
478 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
479 debug!("(encode reexported static methods) {} \
485 debug!("(encode reexported static methods) {} [base]",
494 /// Iterates through "auxiliary node IDs", which are node IDs that describe
495 /// top-level items that are sub-items of the given item. Specifically:
497 /// * For enums, iterates through the node IDs of the variants.
499 /// * For newtype structs, iterates through the node ID of the constructor.
500 fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
501 let mut continue_ = true;
503 ItemEnum(ref enum_def, _) => {
504 for variant in enum_def.variants.iter() {
505 continue_ = callback(variant.node.id);
511 ItemStruct(struct_def, _) => {
512 // If this is a newtype struct, return the constructor.
513 match struct_def.ctor_id {
514 Some(ctor_id) if struct_def.fields.len() > 0 &&
515 struct_def.fields.get(0).node.kind.is_unnamed() => {
516 continue_ = callback(ctor_id);
527 fn encode_reexports(ecx: &EncodeContext,
528 ebml_w: &mut Encoder,
531 debug!("(encoding info for module) encoding reexports for {}", id);
532 match ecx.reexports2.borrow().find(&id) {
533 Some(ref exports) => {
534 debug!("(encoding info for module) found reexports for {}", id);
535 for exp in exports.iter() {
536 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
542 ebml_w.start_tag(tag_items_data_item_reexport);
543 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
544 ebml_w.wr_str(def_to_string(exp.def_id).as_slice());
546 ebml_w.start_tag(tag_items_data_item_reexport_name);
547 ebml_w.wr_str(exp.name.as_slice());
550 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
554 debug!("(encoding info for module) found no reexports for {}",
560 fn encode_info_for_mod(ecx: &EncodeContext,
561 ebml_w: &mut Encoder,
568 ebml_w.start_tag(tag_items_data_item);
569 encode_def_id(ebml_w, local_def(id));
570 encode_family(ebml_w, 'm');
571 encode_name(ebml_w, name.name);
572 debug!("(encoding info for module) encoding info for module ID {}", id);
574 // Encode info about all the module children.
575 for item in md.items.iter() {
576 ebml_w.start_tag(tag_mod_child);
577 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
580 each_auxiliary_node_id(*item, |auxiliary_node_id| {
581 ebml_w.start_tag(tag_mod_child);
582 ebml_w.wr_str(def_to_string(local_def(
583 auxiliary_node_id)).as_slice());
590 let (ident, did) = (item.ident, item.id);
591 debug!("(encoding info for module) ... encoding impl {} \
593 token::get_ident(ident),
594 did, ecx.tcx.map.node_to_string(did));
596 ebml_w.start_tag(tag_mod_impl);
597 ebml_w.wr_str(def_to_string(local_def(did)).as_slice());
604 encode_path(ebml_w, path.clone());
605 encode_visibility(ebml_w, vis);
607 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
608 encode_stability(ebml_w, stab);
610 // Encode the reexports of this module, if this module is public.
612 debug!("(encoding info for module) encoding reexports for {}", id);
613 encode_reexports(ecx, ebml_w, id, path);
615 encode_attributes(ebml_w, attrs);
620 fn encode_struct_field_family(ebml_w: &mut Encoder,
621 visibility: Visibility) {
622 encode_family(ebml_w, match visibility {
628 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
629 ebml_w.start_tag(tag_items_data_item_visibility);
630 let ch = match visibility {
634 ebml_w.wr_str(ch.to_string().as_slice());
638 fn encode_explicit_self(ebml_w: &mut Encoder,
639 explicit_self: &ty::ExplicitSelfCategory) {
640 ebml_w.start_tag(tag_item_trait_method_explicit_self);
642 // Encode the base self type.
643 match *explicit_self {
644 ty::StaticExplicitSelfCategory => {
645 ebml_w.writer.write(&[ 's' as u8 ]);
647 ty::ByValueExplicitSelfCategory => {
648 ebml_w.writer.write(&[ 'v' as u8 ]);
650 ty::ByBoxExplicitSelfCategory => {
651 ebml_w.writer.write(&[ '~' as u8 ]);
653 ty::ByReferenceExplicitSelfCategory(_, m) => {
654 // FIXME(#4846) encode custom lifetime
655 ebml_w.writer.write(&['&' as u8]);
656 encode_mutability(ebml_w, m);
662 fn encode_mutability(ebml_w: &mut Encoder,
663 m: ast::Mutability) {
665 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
666 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
671 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
672 ebml_w.start_tag(tag_item_trait_method_sort);
673 ebml_w.writer.write(&[ sort as u8 ]);
677 fn encode_provided_source(ebml_w: &mut Encoder,
678 source_opt: Option<DefId>) {
679 for source in source_opt.iter() {
680 ebml_w.start_tag(tag_item_method_provided_source);
681 let s = def_to_string(*source);
682 ebml_w.writer.write(s.as_bytes());
687 /* Returns an index of items in this class */
688 fn encode_info_for_struct(ecx: &EncodeContext,
689 ebml_w: &mut Encoder,
690 fields: &[ty::field_ty],
691 global_index: &mut Vec<entry<i64>>)
693 /* Each class has its own index, since different classes
694 may have fields with the same name */
695 let mut index = Vec::new();
697 /* We encode both private and public fields -- need to include
698 private fields to get the offsets right */
699 for field in fields.iter() {
701 let id = field.id.node;
703 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
704 global_index.push(entry {
706 pos: ebml_w.writer.tell().unwrap(),
708 ebml_w.start_tag(tag_items_data_item);
709 debug!("encode_info_for_struct: doing {} {}",
710 token::get_name(nm), id);
711 encode_struct_field_family(ebml_w, field.vis);
712 encode_name(ebml_w, nm);
713 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
714 encode_def_id(ebml_w, local_def(id));
716 let stab = stability::lookup(ecx.tcx, field.id);
717 encode_stability(ebml_w, stab);
724 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
725 ebml_w: &mut Encoder,
728 index: &mut Vec<entry<i64>>,
732 pos: ebml_w.writer.tell().unwrap(),
735 ebml_w.start_tag(tag_items_data_item);
736 encode_def_id(ebml_w, local_def(ctor_id));
737 encode_family(ebml_w, 'f');
738 encode_bounds_and_type(ebml_w, ecx,
739 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
740 encode_name(ebml_w, name.name);
741 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
742 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
743 encode_parent_item(ebml_w, local_def(struct_id));
745 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
746 encode_symbol(ecx, ebml_w, ctor_id);
749 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
750 encode_stability(ebml_w, stab);
752 // indicate that this is a tuple struct ctor, because downstream users will normally want
753 // the tuple struct definition, but without this there is no way for them to tell that
754 // they actually have a ctor rather than a normal function
755 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
761 fn encode_method_ty_fields(ecx: &EncodeContext,
762 ebml_w: &mut Encoder,
763 method_ty: &ty::Method) {
764 encode_def_id(ebml_w, method_ty.def_id);
765 encode_name(ebml_w, method_ty.ident.name);
766 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
767 tag_item_method_tps);
768 encode_method_fty(ecx, ebml_w, &method_ty.fty);
769 encode_visibility(ebml_w, method_ty.vis);
770 encode_explicit_self(ebml_w, &method_ty.explicit_self);
771 let fn_style = method_ty.fty.fn_style;
772 match method_ty.explicit_self {
773 ty::StaticExplicitSelfCategory => {
774 encode_family(ebml_w, fn_style_static_method_family(fn_style));
776 _ => encode_family(ebml_w, style_fn_family(fn_style))
778 encode_provided_source(ebml_w, method_ty.provided_source);
781 fn encode_info_for_method(ecx: &EncodeContext,
782 ebml_w: &mut Encoder,
784 impl_path: PathElems,
785 is_default_impl: bool,
787 ast_method_opt: Option<Gc<Method>>) {
789 debug!("encode_info_for_method: {:?} {}", m.def_id,
790 token::get_ident(m.ident));
791 ebml_w.start_tag(tag_items_data_item);
793 encode_method_ty_fields(ecx, ebml_w, m);
794 encode_parent_item(ebml_w, local_def(parent_id));
796 let stab = stability::lookup(ecx.tcx, m.def_id);
797 encode_stability(ebml_w, stab);
799 // The type for methods gets encoded twice, which is unfortunate.
800 let pty = lookup_item_type(ecx.tcx, m.def_id);
801 encode_bounds_and_type(ebml_w, ecx, &pty);
803 let elem = ast_map::PathName(m.ident.name);
804 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
805 match ast_method_opt {
806 Some(ast_method) => {
807 encode_attributes(ebml_w, ast_method.attrs.as_slice())
812 for &ast_method in ast_method_opt.iter() {
813 let any_types = !pty.generics.types.is_empty();
814 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
815 encode_inlined_item(ecx, ebml_w,
816 IIMethodRef(local_def(parent_id), false,
819 encode_symbol(ecx, ebml_w, m.def_id.node);
821 encode_method_argument_names(ebml_w, &*ast_method.pe_fn_decl());
827 fn encode_method_argument_names(ebml_w: &mut Encoder,
828 decl: &ast::FnDecl) {
829 ebml_w.start_tag(tag_method_argument_names);
830 for arg in decl.inputs.iter() {
831 ebml_w.start_tag(tag_method_argument_name);
833 ast::PatIdent(_, ref path1, _) => {
834 let name = token::get_ident(path1.node);
835 ebml_w.writer.write(name.get().as_bytes());
844 fn encode_inlined_item(ecx: &EncodeContext,
845 ebml_w: &mut Encoder,
846 ii: InlinedItemRef) {
847 let mut eii = ecx.encode_inlined_item.borrow_mut();
848 let eii: &mut EncodeInlinedItem = &mut *eii;
849 (*eii)(ecx, ebml_w, ii)
852 fn style_fn_family(s: FnStyle) -> char {
859 fn fn_style_static_method_family(s: FnStyle) -> char {
867 fn should_inline(attrs: &[Attribute]) -> bool {
869 match find_inline_attr(attrs) {
870 InlineNone | InlineNever => false,
871 InlineHint | InlineAlways => true
875 // Encodes the inherent implementations of a structure, enumeration, or trait.
876 fn encode_inherent_implementations(ecx: &EncodeContext,
877 ebml_w: &mut Encoder,
879 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
881 Some(implementations) => {
882 for &impl_def_id in implementations.borrow().iter() {
883 ebml_w.start_tag(tag_items_data_item_inherent_impl);
884 encode_def_id(ebml_w, impl_def_id);
891 // Encodes the implementations of a trait defined in this crate.
892 fn encode_extension_implementations(ecx: &EncodeContext,
893 ebml_w: &mut Encoder,
894 trait_def_id: DefId) {
895 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
897 Some(implementations) => {
898 for &impl_def_id in implementations.borrow().iter() {
899 ebml_w.start_tag(tag_items_data_item_extension_impl);
900 encode_def_id(ebml_w, impl_def_id);
907 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
908 stab_opt.map(|stab| {
909 ebml_w.start_tag(tag_items_data_item_stability);
910 stab.encode(ebml_w).unwrap();
915 fn encode_info_for_item(ecx: &EncodeContext,
916 ebml_w: &mut Encoder,
918 index: &mut Vec<entry<i64>>,
920 vis: ast::Visibility) {
923 fn add_to_index(item: &Item, ebml_w: &Encoder,
924 index: &mut Vec<entry<i64>>) {
927 pos: ebml_w.writer.tell().unwrap(),
931 debug!("encoding info for item at {}",
932 tcx.sess.codemap().span_to_string(item.span));
934 let def_id = local_def(item.id);
935 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
938 ItemStatic(_, m, _) => {
939 add_to_index(item, ebml_w, index);
940 ebml_w.start_tag(tag_items_data_item);
941 encode_def_id(ebml_w, def_id);
942 if m == ast::MutMutable {
943 encode_family(ebml_w, 'b');
945 encode_family(ebml_w, 'c');
947 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
948 encode_symbol(ecx, ebml_w, item.id);
949 encode_name(ebml_w, item.ident.name);
950 encode_path(ebml_w, path);
952 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
955 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
957 encode_visibility(ebml_w, vis);
958 encode_stability(ebml_w, stab);
961 ItemFn(ref decl, fn_style, _, ref generics, _) => {
962 add_to_index(item, ebml_w, index);
963 ebml_w.start_tag(tag_items_data_item);
964 encode_def_id(ebml_w, def_id);
965 encode_family(ebml_w, style_fn_family(fn_style));
966 let tps_len = generics.ty_params.len();
967 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
968 encode_name(ebml_w, item.ident.name);
969 encode_path(ebml_w, path);
970 encode_attributes(ebml_w, item.attrs.as_slice());
971 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
972 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
974 encode_symbol(ecx, ebml_w, item.id);
976 encode_visibility(ebml_w, vis);
977 encode_stability(ebml_w, stab);
978 encode_method_argument_names(ebml_w, &**decl);
982 add_to_index(item, ebml_w, index);
983 encode_info_for_mod(ecx,
986 item.attrs.as_slice(),
992 ItemForeignMod(ref fm) => {
993 add_to_index(item, ebml_w, index);
994 ebml_w.start_tag(tag_items_data_item);
995 encode_def_id(ebml_w, def_id);
996 encode_family(ebml_w, 'n');
997 encode_name(ebml_w, item.ident.name);
998 encode_path(ebml_w, path);
1000 // Encode all the items in this module.
1001 for foreign_item in fm.items.iter() {
1002 ebml_w.start_tag(tag_mod_child);
1003 ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
1006 encode_visibility(ebml_w, vis);
1007 encode_stability(ebml_w, stab);
1011 add_to_index(item, ebml_w, index);
1012 ebml_w.start_tag(tag_items_data_item);
1013 encode_def_id(ebml_w, def_id);
1014 encode_family(ebml_w, 'y');
1015 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1016 encode_name(ebml_w, item.ident.name);
1017 encode_path(ebml_w, path);
1018 encode_visibility(ebml_w, vis);
1019 encode_stability(ebml_w, stab);
1022 ItemEnum(ref enum_definition, ref generics) => {
1023 add_to_index(item, ebml_w, index);
1025 ebml_w.start_tag(tag_items_data_item);
1026 encode_def_id(ebml_w, def_id);
1027 encode_family(ebml_w, 't');
1028 encode_item_variances(ebml_w, ecx, item.id);
1029 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1030 encode_name(ebml_w, item.ident.name);
1031 encode_attributes(ebml_w, item.attrs.as_slice());
1032 for v in (*enum_definition).variants.iter() {
1033 encode_variant_id(ebml_w, local_def(v.node.id));
1035 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1036 encode_path(ebml_w, path);
1038 // Encode inherent implementations for this enumeration.
1039 encode_inherent_implementations(ecx, ebml_w, def_id);
1041 encode_visibility(ebml_w, vis);
1042 encode_stability(ebml_w, stab);
1045 encode_enum_variant_info(ecx,
1048 (*enum_definition).variants.as_slice(),
1052 ItemStruct(struct_def, _) => {
1053 let fields = ty::lookup_struct_fields(tcx, def_id);
1055 /* First, encode the fields
1056 These come first because we need to write them to make
1057 the index, and the index needs to be in the item for the
1059 let idx = encode_info_for_struct(ecx,
1064 /* Index the class*/
1065 add_to_index(item, ebml_w, index);
1067 /* Now, make an item for the class itself */
1068 ebml_w.start_tag(tag_items_data_item);
1069 encode_def_id(ebml_w, def_id);
1070 encode_family(ebml_w, 'S');
1071 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1073 encode_item_variances(ebml_w, ecx, item.id);
1074 encode_name(ebml_w, item.ident.name);
1075 encode_attributes(ebml_w, item.attrs.as_slice());
1076 encode_path(ebml_w, path.clone());
1077 encode_stability(ebml_w, stab);
1078 encode_visibility(ebml_w, vis);
1080 /* Encode def_ids for each field and method
1081 for methods, write all the stuff get_trait_method
1083 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1085 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1087 // Encode inherent implementations for this structure.
1088 encode_inherent_implementations(ecx, ebml_w, def_id);
1090 /* Each class has its own index -- encode it */
1091 encode_index(ebml_w, idx, write_i64);
1094 // If this is a tuple-like struct, encode the type of the constructor.
1095 match struct_def.ctor_id {
1097 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1098 ctor_id, index, def_id.node);
1103 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1104 // We need to encode information about the default methods we
1105 // have inherited, so we drive this based on the impl structure.
1106 let impl_methods = tcx.impl_methods.borrow();
1107 let methods = impl_methods.get(&def_id);
1109 add_to_index(item, ebml_w, index);
1110 ebml_w.start_tag(tag_items_data_item);
1111 encode_def_id(ebml_w, def_id);
1112 encode_family(ebml_w, 'i');
1113 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1114 encode_name(ebml_w, item.ident.name);
1115 encode_attributes(ebml_w, item.attrs.as_slice());
1117 ast::TyPath(ref path, ref bounds, _) if path.segments
1119 let ident = path.segments.last().unwrap().identifier;
1120 assert!(bounds.is_none());
1121 encode_impl_type_basename(ebml_w, ident);
1125 for &method_def_id in methods.iter() {
1126 ebml_w.start_tag(tag_item_impl_method);
1127 let s = def_to_string(method_def_id);
1128 ebml_w.writer.write(s.as_bytes());
1131 for ast_trait_ref in opt_trait.iter() {
1132 let trait_ref = ty::node_id_to_trait_ref(
1133 tcx, ast_trait_ref.ref_id);
1134 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1135 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1136 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1138 encode_path(ebml_w, path.clone());
1139 encode_stability(ebml_w, stab);
1142 // Iterate down the methods, emitting them. We rely on the
1143 // assumption that all of the actually implemented methods
1144 // appear first in the impl structure, in the same order they do
1145 // in the ast. This is a little sketchy.
1146 let num_implemented_methods = ast_methods.len();
1147 for (i, &method_def_id) in methods.iter().enumerate() {
1148 let ast_method = if i < num_implemented_methods {
1149 Some(*ast_methods.get(i))
1153 val: method_def_id.node as i64,
1154 pos: ebml_w.writer.tell().unwrap(),
1156 encode_info_for_method(ecx,
1158 &*ty::method(tcx, method_def_id),
1165 ItemTrait(_, _, ref super_traits, ref ms) => {
1166 add_to_index(item, ebml_w, index);
1167 ebml_w.start_tag(tag_items_data_item);
1168 encode_def_id(ebml_w, def_id);
1169 encode_family(ebml_w, 'I');
1170 encode_item_variances(ebml_w, ecx, item.id);
1171 let trait_def = ty::lookup_trait_def(tcx, def_id);
1172 encode_ty_type_param_defs(ebml_w, ecx,
1173 &trait_def.generics.types,
1174 tag_items_data_item_ty_param_bounds);
1175 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1176 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1177 encode_name(ebml_w, item.ident.name);
1178 encode_attributes(ebml_w, item.attrs.as_slice());
1179 encode_visibility(ebml_w, vis);
1180 encode_stability(ebml_w, stab);
1181 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1182 ebml_w.start_tag(tag_item_trait_method);
1183 encode_def_id(ebml_w, method_def_id);
1186 ebml_w.start_tag(tag_mod_child);
1187 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1190 encode_path(ebml_w, path.clone());
1191 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1192 // reading the AST's list, because the former has already filtered out
1193 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1194 for ast_trait_ref in super_traits.iter() {
1195 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1196 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1199 // Encode the implementations of this trait.
1200 encode_extension_implementations(ecx, ebml_w, def_id);
1204 // Now output the method info for each method.
1205 let r = ty::trait_method_def_ids(tcx, def_id);
1206 for (i, &method_def_id) in r.iter().enumerate() {
1207 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1209 let method_ty = ty::method(tcx, method_def_id);
1212 val: method_def_id.node as i64,
1213 pos: ebml_w.writer.tell().unwrap(),
1216 ebml_w.start_tag(tag_items_data_item);
1218 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1219 encode_parent_item(ebml_w, def_id);
1221 let stab = stability::lookup(tcx, method_def_id);
1222 encode_stability(ebml_w, stab);
1224 let elem = ast_map::PathName(method_ty.ident.name);
1225 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1227 match method_ty.explicit_self {
1228 ty::StaticExplicitSelfCategory => {
1229 encode_family(ebml_w,
1230 fn_style_static_method_family(
1231 method_ty.fty.fn_style));
1233 let pty = ty::lookup_item_type(tcx, method_def_id);
1234 encode_bounds_and_type(ebml_w, ecx, &pty);
1238 encode_family(ebml_w,
1240 method_ty.fty.fn_style));
1245 &Required(ref tm) => {
1246 encode_attributes(ebml_w, tm.attrs.as_slice());
1247 encode_method_sort(ebml_w, 'r');
1248 encode_method_argument_names(ebml_w, &*tm.decl);
1252 encode_attributes(ebml_w, m.attrs.as_slice());
1253 // If this is a static method, we've already encoded
1255 if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
1256 // FIXME: I feel like there is something funny going on.
1257 let pty = ty::lookup_item_type(tcx, method_def_id);
1258 encode_bounds_and_type(ebml_w, ecx, &pty);
1260 encode_method_sort(ebml_w, 'p');
1261 encode_inlined_item(ecx, ebml_w,
1262 IIMethodRef(def_id, true, &*m));
1263 encode_method_argument_names(ebml_w, &*m.pe_fn_decl());
1270 // Encode inherent implementations for this trait.
1271 encode_inherent_implementations(ecx, ebml_w, def_id);
1274 // macros are encoded separately
1279 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1280 ebml_w: &mut Encoder,
1281 nitem: &ForeignItem,
1282 index: &mut Vec<entry<i64>>,
1286 val: nitem.id as i64,
1287 pos: ebml_w.writer.tell().unwrap(),
1290 ebml_w.start_tag(tag_items_data_item);
1291 encode_def_id(ebml_w, local_def(nitem.id));
1293 ForeignItemFn(..) => {
1294 encode_family(ebml_w, style_fn_family(NormalFn));
1295 encode_bounds_and_type(ebml_w, ecx,
1296 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1297 encode_name(ebml_w, nitem.ident.name);
1298 if abi == abi::RustIntrinsic {
1299 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1301 encode_symbol(ecx, ebml_w, nitem.id);
1304 ForeignItemStatic(_, mutbl) => {
1306 encode_family(ebml_w, 'b');
1308 encode_family(ebml_w, 'c');
1310 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1311 encode_symbol(ecx, ebml_w, nitem.id);
1312 encode_name(ebml_w, nitem.ident.name);
1315 encode_path(ebml_w, path);
1319 fn my_visit_expr(_e: &Expr) { }
1321 fn my_visit_item(i: &Item,
1322 ebml_w: &mut Encoder,
1323 ecx_ptr: *const int,
1324 index: &mut Vec<entry<i64>>) {
1325 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1327 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1328 ecx.tcx.map.with_path(i.id, |path| {
1329 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1333 fn my_visit_foreign_item(ni: &ForeignItem,
1334 ebml_w: &mut Encoder,
1336 index: &mut Vec<entry<i64>>) {
1338 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1339 debug!("writing foreign item {}::{}",
1340 ecx.tcx.map.path_to_string(ni.id),
1341 token::get_ident(ni.ident));
1343 let mut ebml_w = unsafe {
1344 ebml_w.unsafe_clone()
1346 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1347 ecx.tcx.map.with_path(ni.id, |path| {
1348 encode_info_for_foreign_item(ecx, &mut ebml_w,
1354 struct EncodeVisitor<'a,'b> {
1355 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1357 index: &'a mut Vec<entry<i64>>,
1360 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1361 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1362 visit::walk_expr(self, ex, ());
1365 fn visit_item(&mut self, i: &Item, _: ()) {
1366 visit::walk_item(self, i, ());
1368 self.ebml_w_for_visit_item,
1372 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1373 visit::walk_foreign_item(self, ni, ());
1374 my_visit_foreign_item(ni,
1375 self.ebml_w_for_visit_item,
1381 fn encode_info_for_items(ecx: &EncodeContext,
1382 ebml_w: &mut Encoder,
1384 -> Vec<entry<i64>> {
1385 let mut index = Vec::new();
1386 ebml_w.start_tag(tag_items_data);
1388 val: CRATE_NODE_ID as i64,
1389 pos: ebml_w.writer.tell().unwrap(),
1391 encode_info_for_mod(ecx,
1396 ast_map::Values([].iter()).chain(None),
1397 syntax::parse::token::special_idents::invalid,
1400 // See comment in `encode_side_tables_for_ii` in astencode
1401 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1402 visit::walk_crate(&mut EncodeVisitor {
1405 ebml_w_for_visit_item: &mut *ebml_w,
1413 // Path and definition ID indexing
1415 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1416 write_fn: |&mut MemWriter, &T|) {
1417 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1418 for elt in index.move_iter() {
1419 let h = hash::hash(&elt.val) as uint;
1420 buckets.get_mut(h % 256).push(elt);
1423 ebml_w.start_tag(tag_index);
1424 let mut bucket_locs = Vec::new();
1425 ebml_w.start_tag(tag_index_buckets);
1426 for bucket in buckets.iter() {
1427 bucket_locs.push(ebml_w.writer.tell().unwrap());
1428 ebml_w.start_tag(tag_index_buckets_bucket);
1429 for elt in bucket.iter() {
1430 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1431 assert!(elt.pos < 0xffff_ffff);
1433 let wr: &mut MemWriter = ebml_w.writer;
1434 wr.write_be_u32(elt.pos as u32);
1436 write_fn(ebml_w.writer, &elt.val);
1442 ebml_w.start_tag(tag_index_table);
1443 for pos in bucket_locs.iter() {
1444 assert!(*pos < 0xffff_ffff);
1445 let wr: &mut MemWriter = ebml_w.writer;
1446 wr.write_be_u32(*pos as u32);
1452 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1453 let wr: &mut MemWriter = writer;
1454 assert!(n < 0x7fff_ffff);
1455 wr.write_be_u32(n as u32);
1458 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1460 MetaWord(ref name) => {
1461 ebml_w.start_tag(tag_meta_item_word);
1462 ebml_w.start_tag(tag_meta_item_name);
1463 ebml_w.writer.write(name.get().as_bytes());
1467 MetaNameValue(ref name, ref value) => {
1469 LitStr(ref value, _) => {
1470 ebml_w.start_tag(tag_meta_item_name_value);
1471 ebml_w.start_tag(tag_meta_item_name);
1472 ebml_w.writer.write(name.get().as_bytes());
1474 ebml_w.start_tag(tag_meta_item_value);
1475 ebml_w.writer.write(value.get().as_bytes());
1479 _ => {/* FIXME (#623): encode other variants */ }
1482 MetaList(ref name, ref items) => {
1483 ebml_w.start_tag(tag_meta_item_list);
1484 ebml_w.start_tag(tag_meta_item_name);
1485 ebml_w.writer.write(name.get().as_bytes());
1487 for inner_item in items.iter() {
1488 encode_meta_item(ebml_w, *inner_item);
1495 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1496 ebml_w.start_tag(tag_attributes);
1497 for attr in attrs.iter() {
1498 ebml_w.start_tag(tag_attribute);
1499 encode_meta_item(ebml_w, attr.node.value);
1505 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1506 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1507 // Pull the cnums and name,vers,hash out of cstore
1508 let mut deps = Vec::new();
1509 cstore.iter_crate_data(|key, val| {
1510 let dep = decoder::CrateDep {
1512 name: decoder::get_crate_name(val.data()),
1513 hash: decoder::get_crate_hash(val.data()),
1519 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1521 // Sanity-check the crate numbers
1522 let mut expected_cnum = 1;
1523 for n in deps.iter() {
1524 assert_eq!(n.cnum, expected_cnum);
1531 // We're just going to write a list of crate 'name-hash-version's, with
1532 // the assumption that they are numbered 1 to n.
1533 // FIXME (#2166): This is not nearly enough to support correct versioning
1534 // but is enough to get transitive crate dependencies working.
1535 ebml_w.start_tag(tag_crate_deps);
1536 let r = get_ordered_deps(cstore);
1537 for dep in r.iter() {
1538 encode_crate_dep(ebml_w, (*dep).clone());
1543 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1544 ebml_w.start_tag(tag_lang_items);
1546 for (i, def_id) in ecx.tcx.lang_items.items() {
1547 for id in def_id.iter() {
1548 if id.krate == LOCAL_CRATE {
1549 ebml_w.start_tag(tag_lang_items_item);
1551 ebml_w.start_tag(tag_lang_items_item_id);
1553 let wr: &mut MemWriter = ebml_w.writer;
1554 wr.write_be_u32(i as u32);
1556 ebml_w.end_tag(); // tag_lang_items_item_id
1558 ebml_w.start_tag(tag_lang_items_item_node_id);
1560 let wr: &mut MemWriter = ebml_w.writer;
1561 wr.write_be_u32(id.node as u32);
1563 ebml_w.end_tag(); // tag_lang_items_item_node_id
1565 ebml_w.end_tag(); // tag_lang_items_item
1570 for i in ecx.tcx.lang_items.missing.iter() {
1571 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1574 ebml_w.end_tag(); // tag_lang_items
1577 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1578 ebml_w.start_tag(tag_native_libraries);
1580 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1583 cstore::NativeStatic => {} // these libraries are not propagated
1584 cstore::NativeFramework | cstore::NativeUnknown => {
1585 ebml_w.start_tag(tag_native_libraries_lib);
1587 ebml_w.start_tag(tag_native_libraries_kind);
1588 ebml_w.writer.write_be_u32(kind as u32);
1591 ebml_w.start_tag(tag_native_libraries_name);
1592 ebml_w.writer.write(lib.as_bytes());
1603 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1604 match ecx.tcx.sess.plugin_registrar_fn.get() {
1605 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1610 /// Given a span, write the text of that span into the output stream
1611 /// as an exported macro
1612 fn encode_macro_def(ecx: &EncodeContext,
1613 ebml_w: &mut Encoder,
1614 span: &syntax::codemap::Span) {
1615 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1616 .expect("Unable to find source for macro");
1617 ebml_w.start_tag(tag_macro_def);
1618 ebml_w.wr_str(def.as_slice());
1622 /// Serialize the text of the exported macros
1623 fn encode_macro_defs(ecx: &EncodeContext,
1625 ebml_w: &mut Encoder) {
1626 ebml_w.start_tag(tag_exported_macros);
1627 for span in krate.exported_macros.iter() {
1628 encode_macro_def(ecx, ebml_w, span);
1633 fn encode_unboxed_closures<'a>(
1634 ecx: &'a EncodeContext,
1635 ebml_w: &'a mut Encoder) {
1636 ebml_w.start_tag(tag_unboxed_closures);
1637 for (unboxed_closure_id, unboxed_closure_type) in
1638 ecx.tcx.unboxed_closure_types.borrow().iter() {
1639 if unboxed_closure_id.krate != LOCAL_CRATE {
1643 ebml_w.start_tag(tag_unboxed_closure);
1644 encode_def_id(ebml_w, *unboxed_closure_id);
1645 ebml_w.start_tag(tag_unboxed_closure_type);
1646 write_closure_type(ecx, ebml_w, unboxed_closure_type);
1653 struct ImplVisitor<'a,'b,'c> {
1654 ecx: &'a EncodeContext<'b>,
1655 ebml_w: &'a mut Encoder<'c>,
1658 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1659 fn visit_item(&mut self, item: &Item, _: ()) {
1661 ItemImpl(_, Some(ref trait_ref), _, _) => {
1662 let def_map = &self.ecx.tcx.def_map;
1663 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1664 let def_id = trait_def.def_id();
1666 // Load eagerly if this is an implementation of the Drop trait
1667 // or if the trait is not defined in this crate.
1668 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1669 def_id.krate != LOCAL_CRATE {
1670 self.ebml_w.start_tag(tag_impls_impl);
1671 encode_def_id(self.ebml_w, local_def(item.id));
1672 self.ebml_w.end_tag();
1677 visit::walk_item(self, item, ());
1681 /// Encodes implementations that are eagerly loaded.
1683 /// None of this is necessary in theory; we can load all implementations
1684 /// lazily. However, in two cases the optimizations to lazily load
1685 /// implementations are not yet implemented. These two cases, which require us
1686 /// to load implementations eagerly, are:
1688 /// * Destructors (implementations of the Drop trait).
1690 /// * Implementations of traits not defined in this crate.
1691 fn encode_impls<'a>(ecx: &'a EncodeContext,
1693 ebml_w: &'a mut Encoder) {
1694 ebml_w.start_tag(tag_impls);
1697 let mut visitor = ImplVisitor {
1701 visit::walk_crate(&mut visitor, krate, ());
1707 fn encode_misc_info(ecx: &EncodeContext,
1709 ebml_w: &mut Encoder) {
1710 ebml_w.start_tag(tag_misc_info);
1711 ebml_w.start_tag(tag_misc_info_crate_items);
1712 for &item in krate.module.items.iter() {
1713 ebml_w.start_tag(tag_mod_child);
1714 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1717 each_auxiliary_node_id(item, |auxiliary_node_id| {
1718 ebml_w.start_tag(tag_mod_child);
1719 ebml_w.wr_str(def_to_string(local_def(
1720 auxiliary_node_id)).as_slice());
1726 // Encode reexports for the root module.
1727 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1733 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1734 ebml_w.start_tag(tag_reachable_extern_fns);
1736 for id in ecx.reachable.iter() {
1737 match ecx.tcx.map.find(*id) {
1738 Some(ast_map::NodeItem(i)) => {
1740 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1741 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1753 fn encode_crate_dep(ebml_w: &mut Encoder,
1754 dep: decoder::CrateDep) {
1755 ebml_w.start_tag(tag_crate_dep);
1756 ebml_w.start_tag(tag_crate_dep_crate_name);
1757 ebml_w.writer.write(dep.name.as_bytes());
1759 ebml_w.start_tag(tag_crate_dep_hash);
1760 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1765 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1766 ebml_w.start_tag(tag_crate_hash);
1767 ebml_w.writer.write(hash.as_str().as_bytes());
1771 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1772 ebml_w.start_tag(tag_crate_crate_name);
1773 ebml_w.writer.write(crate_name.as_bytes());
1777 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1778 ebml_w.start_tag(tag_crate_triple);
1779 ebml_w.writer.write(triple.as_bytes());
1783 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1784 ebml_w.start_tag(tag_dylib_dependency_formats);
1785 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1787 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1788 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1789 cstore::RequireDynamic => "d",
1790 cstore::RequireStatic => "s",
1792 }).collect::<Vec<String>>();
1793 ebml_w.writer.write(s.connect(",").as_bytes());
1800 // NB: Increment this as you change the metadata encoding version.
1801 pub static metadata_encoding_version : &'static [u8] =
1802 &[0x72, //'r' as u8,
1808 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1809 let mut wr = MemWriter::new();
1810 encode_metadata_inner(&mut wr, parms, krate);
1811 wr.unwrap().move_iter().collect()
1814 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1818 lang_item_bytes: u64,
1819 native_lib_bytes: u64,
1820 plugin_registrar_fn_bytes: u64,
1821 macro_defs_bytes: u64,
1822 unboxed_closure_bytes: u64,
1830 let mut stats = Stats {
1834 native_lib_bytes: 0,
1835 plugin_registrar_fn_bytes: 0,
1836 macro_defs_bytes: 0,
1837 unboxed_closure_bytes: 0,
1851 encode_inlined_item,
1853 non_inlineable_statics,
1857 let ecx = EncodeContext {
1860 reexports2: reexports2,
1861 item_symbols: item_symbols,
1862 non_inlineable_statics: non_inlineable_statics,
1863 link_meta: link_meta,
1865 encode_inlined_item: RefCell::new(encode_inlined_item),
1866 type_abbrevs: RefCell::new(HashMap::new()),
1867 reachable: reachable,
1870 let mut ebml_w = writer::Encoder::new(wr);
1872 encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1873 encode_crate_triple(&mut ebml_w,
1879 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1880 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1882 let mut i = ebml_w.writer.tell().unwrap();
1883 encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1884 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1886 i = ebml_w.writer.tell().unwrap();
1887 encode_crate_deps(&mut ebml_w, ecx.cstore);
1888 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1890 // Encode the language items.
1891 i = ebml_w.writer.tell().unwrap();
1892 encode_lang_items(&ecx, &mut ebml_w);
1893 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1895 // Encode the native libraries used
1896 i = ebml_w.writer.tell().unwrap();
1897 encode_native_libraries(&ecx, &mut ebml_w);
1898 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1900 // Encode the plugin registrar function
1901 i = ebml_w.writer.tell().unwrap();
1902 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1903 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1905 // Encode macro definitions
1906 i = ebml_w.writer.tell().unwrap();
1907 encode_macro_defs(&ecx, krate, &mut ebml_w);
1908 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1910 // Encode the types of all unboxed closures in this crate.
1911 i = ebml_w.writer.tell().unwrap();
1912 encode_unboxed_closures(&ecx, &mut ebml_w);
1913 stats.unboxed_closure_bytes = ebml_w.writer.tell().unwrap() - i;
1915 // Encode the def IDs of impls, for coherence checking.
1916 i = ebml_w.writer.tell().unwrap();
1917 encode_impls(&ecx, krate, &mut ebml_w);
1918 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1920 // Encode miscellaneous info.
1921 i = ebml_w.writer.tell().unwrap();
1922 encode_misc_info(&ecx, krate, &mut ebml_w);
1923 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1924 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1926 // Encode and index the items.
1927 ebml_w.start_tag(tag_items);
1928 i = ebml_w.writer.tell().unwrap();
1929 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1930 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1932 i = ebml_w.writer.tell().unwrap();
1933 encode_index(&mut ebml_w, items_index, write_i64);
1934 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1937 stats.total_bytes = ebml_w.writer.tell().unwrap();
1939 if tcx.sess.meta_stats() {
1940 for e in ebml_w.writer.get_ref().iter() {
1942 stats.zero_bytes += 1;
1946 println!("metadata stats:");
1947 println!(" attribute bytes: {}", stats.attr_bytes);
1948 println!(" dep bytes: {}", stats.dep_bytes);
1949 println!(" lang item bytes: {}", stats.lang_item_bytes);
1950 println!(" native bytes: {}", stats.native_lib_bytes);
1951 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1952 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1953 println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
1954 println!(" impl bytes: {}", stats.impl_bytes);
1955 println!(" misc bytes: {}", stats.misc_bytes);
1956 println!(" item bytes: {}", stats.item_bytes);
1957 println!(" index bytes: {}", stats.index_bytes);
1958 println!(" zero bytes: {}", stats.zero_bytes);
1959 println!(" total bytes: {}", stats.total_bytes);
1963 // Get the encoded string for a type
1964 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1965 let mut wr = MemWriter::new();
1966 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1967 diag: tcx.sess.diagnostic(),
1970 abbrevs: &RefCell::new(HashMap::new())
1972 String::from_utf8(wr.unwrap()).unwrap()