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::ty::{node_id_to_type, lookup_item_type};
23 use middle::astencode;
27 use util::nodemap::{NodeMap, NodeSet};
29 use serialize::Encodable;
31 use std::cell::RefCell;
34 use std::io::MemWriter;
36 use collections::HashMap;
40 use syntax::ast_map::{PathElem, PathElems};
42 use syntax::ast_util::*;
44 use syntax::attr::AttrMetaMethods;
46 use syntax::crateid::CrateId;
47 use syntax::diagnostic::SpanHandler;
48 use syntax::parse::token::InternedString;
49 use syntax::parse::token::special_idents;
50 use syntax::parse::token;
51 use syntax::visit::Visitor;
54 use writer = serialize::ebml::writer;
56 /// A borrowed version of ast::InlinedItem.
57 pub enum InlinedItemRef<'a> {
58 IIItemRef(&'a ast::Item),
59 IIMethodRef(ast::DefId, bool, &'a ast::Method),
60 IIForeignRef(&'a ast::ForeignItem)
63 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
65 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
67 ii: InlinedItemRef|: 'a;
69 pub struct EncodeParams<'a> {
70 pub diag: &'a SpanHandler,
71 pub tcx: &'a ty::ctxt,
72 pub reexports2: &'a middle::resolve::ExportMap2,
73 pub item_symbols: &'a RefCell<NodeMap<StrBuf>>,
74 pub non_inlineable_statics: &'a RefCell<NodeSet>,
75 pub link_meta: &'a LinkMeta,
76 pub cstore: &'a cstore::CStore,
77 pub encode_inlined_item: EncodeInlinedItem<'a>,
80 pub struct EncodeContext<'a> {
81 pub diag: &'a SpanHandler,
82 pub tcx: &'a ty::ctxt,
83 pub reexports2: &'a middle::resolve::ExportMap2,
84 pub item_symbols: &'a RefCell<NodeMap<StrBuf>>,
85 pub non_inlineable_statics: &'a RefCell<NodeSet>,
86 pub link_meta: &'a LinkMeta,
87 pub cstore: &'a cstore::CStore,
88 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
89 pub type_abbrevs: tyencode::abbrev_map,
92 fn encode_name(ebml_w: &mut Encoder, name: Name) {
93 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
96 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
97 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
100 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
101 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id).as_slice());
110 fn encode_trait_ref(ebml_w: &mut Encoder,
112 trait_ref: &ty::TraitRef,
114 let ty_str_ctxt = &tyencode::ctxt {
118 abbrevs: &ecx.type_abbrevs
121 ebml_w.start_tag(tag);
122 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
126 fn encode_impl_vtables(ebml_w: &mut Encoder,
128 vtables: &typeck::impl_res) {
129 ebml_w.start_tag(tag_item_impl_vtables);
130 astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
131 astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
135 // Item info table encoding
136 fn encode_family(ebml_w: &mut Encoder, c: char) {
137 ebml_w.start_tag(tag_items_data_item_family);
138 ebml_w.writer.write(&[c as u8]);
142 pub fn def_to_str(did: DefId) -> StrBuf {
143 format_strbuf!("{}:{}", did.krate, did.node)
146 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
148 params: &[ty::TypeParameterDef],
150 let ty_str_ctxt = &tyencode::ctxt {
154 abbrevs: &ecx.type_abbrevs
156 for param in params.iter() {
157 ebml_w.start_tag(tag);
158 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
163 fn encode_region_param_defs(ebml_w: &mut Encoder,
164 params: &[ty::RegionParameterDef]) {
165 for param in params.iter() {
166 ebml_w.start_tag(tag_region_param_def);
168 ebml_w.start_tag(tag_region_param_def_ident);
169 encode_name(ebml_w, param.name);
172 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
173 def_to_str(param.def_id).as_slice());
179 fn encode_item_variances(ebml_w: &mut Encoder,
182 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
183 ebml_w.start_tag(tag_item_variances);
188 fn encode_bounds_and_type(ebml_w: &mut Encoder,
190 tpt: &ty::ty_param_bounds_and_ty) {
191 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
192 tag_items_data_item_ty_param_bounds);
193 encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
194 encode_type(ecx, ebml_w, tpt.ty);
197 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
198 ebml_w.start_tag(tag_items_data_item_variant);
199 let s = def_to_str(vid);
200 ebml_w.writer.write(s.as_bytes());
204 pub fn write_type(ecx: &EncodeContext,
205 ebml_w: &mut Encoder,
207 let ty_str_ctxt = &tyencode::ctxt {
211 abbrevs: &ecx.type_abbrevs
213 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
216 fn encode_type(ecx: &EncodeContext,
217 ebml_w: &mut Encoder,
219 ebml_w.start_tag(tag_items_data_item_type);
220 write_type(ecx, ebml_w, typ);
224 fn encode_method_fty(ecx: &EncodeContext,
225 ebml_w: &mut Encoder,
226 typ: &ty::BareFnTy) {
227 ebml_w.start_tag(tag_item_method_fty);
229 let ty_str_ctxt = &tyencode::ctxt {
233 abbrevs: &ecx.type_abbrevs
235 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
240 fn encode_symbol(ecx: &EncodeContext,
241 ebml_w: &mut Encoder,
243 ebml_w.start_tag(tag_items_data_item_symbol);
244 match ecx.item_symbols.borrow().find(&id) {
246 debug!("encode_symbol(id={:?}, str={})", id, *x);
247 ebml_w.writer.write(x.as_bytes());
250 ecx.diag.handler().bug(
251 format!("encode_symbol: id not found {}", id));
257 fn encode_disr_val(_: &EncodeContext,
258 ebml_w: &mut Encoder,
259 disr_val: ty::Disr) {
260 ebml_w.start_tag(tag_disr_val);
261 let s = disr_val.to_str();
262 ebml_w.writer.write(s.as_bytes());
266 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
267 ebml_w.start_tag(tag_items_data_parent_item);
268 let s = def_to_str(id);
269 ebml_w.writer.write(s.as_bytes());
273 fn encode_struct_fields(ebml_w: &mut Encoder,
274 fields: &[ty::field_ty],
276 for f in fields.iter() {
277 if f.name == special_idents::unnamed_field.name {
278 ebml_w.start_tag(tag_item_unnamed_field);
280 ebml_w.start_tag(tag_item_field);
281 encode_name(ebml_w, f.name);
283 encode_struct_field_family(ebml_w, f.vis);
284 encode_def_id(ebml_w, f.id);
285 ebml_w.start_tag(tag_item_field_origin);
286 let s = def_to_str(origin);
287 ebml_w.writer.write(s.as_bytes());
293 fn encode_enum_variant_info(ecx: &EncodeContext,
294 ebml_w: &mut Encoder,
296 variants: &[P<Variant>],
297 index: &mut Vec<entry<i64>>,
298 generics: &ast::Generics) {
299 debug!("encode_enum_variant_info(id={:?})", id);
301 let mut disr_val = 0;
303 let vi = ty::enum_variants(ecx.tcx,
304 ast::DefId { krate: LOCAL_CRATE, node: id });
305 for variant in variants.iter() {
306 let def_id = local_def(variant.node.id);
308 val: variant.node.id as i64,
309 pos: ebml_w.writer.tell().unwrap(),
311 ebml_w.start_tag(tag_items_data_item);
312 encode_def_id(ebml_w, def_id);
313 match variant.node.kind {
314 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
315 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
317 encode_name(ebml_w, variant.node.name.name);
318 encode_parent_item(ebml_w, local_def(id));
319 encode_visibility(ebml_w, variant.node.vis);
320 encode_attributes(ebml_w, variant.node.attrs.as_slice());
321 match variant.node.kind {
322 ast::TupleVariantKind(ref args)
323 if args.len() > 0 && generics.ty_params.len() == 0 => {
324 encode_symbol(ecx, ebml_w, variant.node.id);
326 ast::TupleVariantKind(_) => {},
327 ast::StructVariantKind(_) => {
328 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
329 let idx = encode_info_for_struct(ecx,
333 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
334 encode_index(ebml_w, idx, write_i64);
337 if vi.get(i).disr_val != disr_val {
338 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
339 disr_val = vi.get(i).disr_val;
341 encode_bounds_and_type(ebml_w, ecx,
342 &lookup_item_type(ecx.tcx, def_id));
344 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
351 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
353 ebml_w.start_tag(tag_path);
354 ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
357 ast_map::PathMod(_) => tag_path_elem_mod,
358 ast_map::PathName(_) => tag_path_elem_name
360 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
365 fn encode_reexported_static_method(ebml_w: &mut Encoder,
366 exp: &middle::resolve::Export2,
367 method_def_id: DefId,
368 method_ident: Ident) {
369 debug!("(encode reexported static method) {}::{}",
370 exp.name, token::get_ident(method_ident));
371 ebml_w.start_tag(tag_items_data_item_reexport);
372 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
373 ebml_w.wr_str(def_to_str(method_def_id).as_slice());
375 ebml_w.start_tag(tag_items_data_item_reexport_name);
376 ebml_w.wr_str(format!("{}::{}",
378 token::get_ident(method_ident)));
383 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
384 ebml_w: &mut Encoder,
385 exp: &middle::resolve::Export2)
387 let impl_methods = ecx.tcx.impl_methods.borrow();
388 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
389 Some(implementations) => {
390 for base_impl_did in implementations.borrow().iter() {
391 for &method_did in impl_methods.get(base_impl_did).iter() {
392 let m = ty::method(ecx.tcx, method_did);
393 if m.explicit_self == ast::SelfStatic {
394 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
405 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
406 ebml_w: &mut Encoder,
407 exp: &middle::resolve::Export2)
409 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
411 for m in methods.iter() {
412 if m.explicit_self == ast::SelfStatic {
413 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
423 fn encode_reexported_static_methods(ecx: &EncodeContext,
424 ebml_w: &mut Encoder,
426 exp: &middle::resolve::Export2) {
427 match ecx.tcx.map.find(exp.def_id.node) {
428 Some(ast_map::NodeItem(item)) => {
429 let original_name = token::get_ident(item.ident);
431 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
432 let (mut a, mut b) = (path, mod_path.clone());
434 match (a.next(), b.next()) {
435 (None, None) => return true,
436 (None, _) | (_, None) => return false,
437 (Some(x), Some(y)) => if x != y { return false },
443 // We don't need to reexport static methods on items
444 // declared in the same module as our `pub use ...` since
445 // that's done when we encode the item itself.
447 // The only exception is when the reexport *changes* the
448 // name e.g. `pub use Foo = self::Bar` -- we have
449 // encoded metadata for static methods relative to Bar,
450 // but not yet for Foo.
452 if path_differs || original_name.get() != exp.name.as_slice() {
453 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
454 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
455 debug!("(encode reexported static methods) {} \
461 debug!("(encode reexported static methods) {} [base]",
470 /// Iterates through "auxiliary node IDs", which are node IDs that describe
471 /// top-level items that are sub-items of the given item. Specifically:
473 /// * For enums, iterates through the node IDs of the variants.
475 /// * For newtype structs, iterates through the node ID of the constructor.
476 fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
477 let mut continue_ = true;
479 ItemEnum(ref enum_def, _) => {
480 for variant in enum_def.variants.iter() {
481 continue_ = callback(variant.node.id);
487 ItemStruct(struct_def, _) => {
488 // If this is a newtype struct, return the constructor.
489 match struct_def.ctor_id {
490 Some(ctor_id) if struct_def.fields.len() > 0 &&
491 struct_def.fields.get(0).node.kind.is_unnamed() => {
492 continue_ = callback(ctor_id);
503 fn encode_reexports(ecx: &EncodeContext,
504 ebml_w: &mut Encoder,
507 debug!("(encoding info for module) encoding reexports for {}", id);
508 match ecx.reexports2.borrow().find(&id) {
509 Some(ref exports) => {
510 debug!("(encoding info for module) found reexports for {}", id);
511 for exp in exports.iter() {
512 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
518 ebml_w.start_tag(tag_items_data_item_reexport);
519 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
520 ebml_w.wr_str(def_to_str(exp.def_id).as_slice());
522 ebml_w.start_tag(tag_items_data_item_reexport_name);
523 ebml_w.wr_str(exp.name.as_slice());
526 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
530 debug!("(encoding info for module) found no reexports for {}",
536 fn encode_info_for_mod(ecx: &EncodeContext,
537 ebml_w: &mut Encoder,
543 ebml_w.start_tag(tag_items_data_item);
544 encode_def_id(ebml_w, local_def(id));
545 encode_family(ebml_w, 'm');
546 encode_name(ebml_w, name.name);
547 debug!("(encoding info for module) encoding info for module ID {}", id);
549 // Encode info about all the module children.
550 for item in md.items.iter() {
551 ebml_w.start_tag(tag_mod_child);
552 ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
555 each_auxiliary_node_id(*item, |auxiliary_node_id| {
556 ebml_w.start_tag(tag_mod_child);
557 ebml_w.wr_str(def_to_str(local_def(
558 auxiliary_node_id)).as_slice());
565 let (ident, did) = (item.ident, item.id);
566 debug!("(encoding info for module) ... encoding impl {} \
568 token::get_ident(ident),
569 did, ecx.tcx.map.node_to_str(did));
571 ebml_w.start_tag(tag_mod_impl);
572 ebml_w.wr_str(def_to_str(local_def(did)).as_slice());
579 encode_path(ebml_w, path.clone());
580 encode_visibility(ebml_w, vis);
582 // Encode the reexports of this module, if this module is public.
584 debug!("(encoding info for module) encoding reexports for {}", id);
585 encode_reexports(ecx, ebml_w, id, path);
591 fn encode_struct_field_family(ebml_w: &mut Encoder,
592 visibility: Visibility) {
593 encode_family(ebml_w, match visibility {
599 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
600 ebml_w.start_tag(tag_items_data_item_visibility);
601 let ch = match visibility {
605 ebml_w.wr_str(str::from_char(ch));
609 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
610 ebml_w.start_tag(tag_item_trait_method_explicit_self);
612 // Encode the base self type.
613 match explicit_self {
614 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
615 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
616 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
617 SelfRegion(_, m) => {
618 // FIXME(#4846) encode custom lifetime
619 ebml_w.writer.write(&['&' as u8]);
620 encode_mutability(ebml_w, m);
626 fn encode_mutability(ebml_w: &mut Encoder,
627 m: ast::Mutability) {
629 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
630 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
635 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
636 ebml_w.start_tag(tag_item_trait_method_sort);
637 ebml_w.writer.write(&[ sort as u8 ]);
641 fn encode_provided_source(ebml_w: &mut Encoder,
642 source_opt: Option<DefId>) {
643 for source in source_opt.iter() {
644 ebml_w.start_tag(tag_item_method_provided_source);
645 let s = def_to_str(*source);
646 ebml_w.writer.write(s.as_bytes());
651 /* Returns an index of items in this class */
652 fn encode_info_for_struct(ecx: &EncodeContext,
653 ebml_w: &mut Encoder,
654 fields: &[ty::field_ty],
655 global_index: &mut Vec<entry<i64>>)
657 /* Each class has its own index, since different classes
658 may have fields with the same name */
659 let mut index = Vec::new();
661 /* We encode both private and public fields -- need to include
662 private fields to get the offsets right */
663 for field in fields.iter() {
665 let id = field.id.node;
667 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
668 global_index.push(entry {
670 pos: ebml_w.writer.tell().unwrap(),
672 ebml_w.start_tag(tag_items_data_item);
673 debug!("encode_info_for_struct: doing {} {}",
674 token::get_name(nm), id);
675 encode_struct_field_family(ebml_w, field.vis);
676 encode_name(ebml_w, nm);
677 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
678 encode_def_id(ebml_w, local_def(id));
684 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
685 ebml_w: &mut Encoder,
688 index: &mut Vec<entry<i64>>,
692 pos: ebml_w.writer.tell().unwrap(),
695 ebml_w.start_tag(tag_items_data_item);
696 encode_def_id(ebml_w, local_def(ctor_id));
697 encode_family(ebml_w, 'f');
698 encode_bounds_and_type(ebml_w, ecx,
699 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
700 encode_name(ebml_w, name.name);
701 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
702 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
703 encode_parent_item(ebml_w, local_def(struct_id));
705 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
706 encode_symbol(ecx, ebml_w, ctor_id);
709 // indicate that this is a tuple struct ctor, because downstream users will normally want
710 // the tuple struct definition, but without this there is no way for them to tell that
711 // they actually have a ctor rather than a normal function
712 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
718 fn encode_method_ty_fields(ecx: &EncodeContext,
719 ebml_w: &mut Encoder,
720 method_ty: &ty::Method) {
721 encode_def_id(ebml_w, method_ty.def_id);
722 encode_name(ebml_w, method_ty.ident.name);
723 encode_ty_type_param_defs(ebml_w, ecx,
724 method_ty.generics.type_param_defs(),
725 tag_item_method_tps);
726 encode_method_fty(ecx, ebml_w, &method_ty.fty);
727 encode_visibility(ebml_w, method_ty.vis);
728 encode_explicit_self(ebml_w, method_ty.explicit_self);
729 let fn_style = method_ty.fty.fn_style;
730 match method_ty.explicit_self {
732 encode_family(ebml_w, fn_style_static_method_family(fn_style));
734 _ => encode_family(ebml_w, style_fn_family(fn_style))
736 encode_provided_source(ebml_w, method_ty.provided_source);
739 fn encode_info_for_method(ecx: &EncodeContext,
740 ebml_w: &mut Encoder,
742 impl_path: PathElems,
743 is_default_impl: bool,
745 ast_method_opt: Option<@Method>) {
747 debug!("encode_info_for_method: {:?} {}", m.def_id,
748 token::get_ident(m.ident));
749 ebml_w.start_tag(tag_items_data_item);
751 encode_method_ty_fields(ecx, ebml_w, m);
752 encode_parent_item(ebml_w, local_def(parent_id));
754 // The type for methods gets encoded twice, which is unfortunate.
755 let tpt = lookup_item_type(ecx.tcx, m.def_id);
756 encode_bounds_and_type(ebml_w, ecx, &tpt);
758 let elem = ast_map::PathName(m.ident.name);
759 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
760 match ast_method_opt {
761 Some(ast_method) => {
762 encode_attributes(ebml_w, ast_method.attrs.as_slice())
767 for &ast_method in ast_method_opt.iter() {
768 let num_params = tpt.generics.type_param_defs().len();
769 if num_params > 0u ||
771 should_inline(ast_method.attrs.as_slice()) {
772 encode_inlined_item(ecx, ebml_w,
773 IIMethodRef(local_def(parent_id), false, ast_method));
775 encode_symbol(ecx, ebml_w, m.def_id.node);
782 fn encode_inlined_item(ecx: &EncodeContext,
783 ebml_w: &mut Encoder,
784 ii: InlinedItemRef) {
785 let mut eii = ecx.encode_inlined_item.borrow_mut();
786 let eii: &mut EncodeInlinedItem = &mut *eii;
787 (*eii)(ecx, ebml_w, ii)
790 fn style_fn_family(s: FnStyle) -> char {
797 fn fn_style_static_method_family(s: FnStyle) -> char {
805 fn should_inline(attrs: &[Attribute]) -> bool {
807 match find_inline_attr(attrs) {
808 InlineNone | InlineNever => false,
809 InlineHint | InlineAlways => true
813 // Encodes the inherent implementations of a structure, enumeration, or trait.
814 fn encode_inherent_implementations(ecx: &EncodeContext,
815 ebml_w: &mut Encoder,
817 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
819 Some(implementations) => {
820 for &impl_def_id in implementations.borrow().iter() {
821 ebml_w.start_tag(tag_items_data_item_inherent_impl);
822 encode_def_id(ebml_w, impl_def_id);
829 // Encodes the implementations of a trait defined in this crate.
830 fn encode_extension_implementations(ecx: &EncodeContext,
831 ebml_w: &mut Encoder,
832 trait_def_id: DefId) {
833 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
835 Some(implementations) => {
836 for &impl_def_id in implementations.borrow().iter() {
837 ebml_w.start_tag(tag_items_data_item_extension_impl);
838 encode_def_id(ebml_w, impl_def_id);
845 fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
846 ebml_w.start_tag(tag_items_data_item_sized);
847 let ch = match sized {
851 ebml_w.wr_str(str::from_char(ch));
855 fn encode_info_for_item(ecx: &EncodeContext,
856 ebml_w: &mut Encoder,
858 index: &mut Vec<entry<i64>>,
860 vis: ast::Visibility) {
863 fn add_to_index(item: &Item, ebml_w: &Encoder,
864 index: &mut Vec<entry<i64>>) {
867 pos: ebml_w.writer.tell().unwrap(),
871 debug!("encoding info for item at {}",
872 ecx.tcx.sess.codemap().span_to_str(item.span));
874 let def_id = local_def(item.id);
876 ItemStatic(_, m, _) => {
877 add_to_index(item, ebml_w, index);
878 ebml_w.start_tag(tag_items_data_item);
879 encode_def_id(ebml_w, def_id);
880 if m == ast::MutMutable {
881 encode_family(ebml_w, 'b');
883 encode_family(ebml_w, 'c');
885 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
886 encode_symbol(ecx, ebml_w, item.id);
887 encode_name(ebml_w, item.ident.name);
888 encode_path(ebml_w, path);
890 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
893 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
895 encode_visibility(ebml_w, vis);
898 ItemFn(_, fn_style, _, ref generics, _) => {
899 add_to_index(item, ebml_w, index);
900 ebml_w.start_tag(tag_items_data_item);
901 encode_def_id(ebml_w, def_id);
902 encode_family(ebml_w, style_fn_family(fn_style));
903 let tps_len = generics.ty_params.len();
904 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
905 encode_name(ebml_w, item.ident.name);
906 encode_path(ebml_w, path);
907 encode_attributes(ebml_w, item.attrs.as_slice());
908 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
909 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
911 encode_symbol(ecx, ebml_w, item.id);
913 encode_visibility(ebml_w, vis);
917 add_to_index(item, ebml_w, index);
918 encode_info_for_mod(ecx,
926 ItemForeignMod(ref fm) => {
927 add_to_index(item, ebml_w, index);
928 ebml_w.start_tag(tag_items_data_item);
929 encode_def_id(ebml_w, def_id);
930 encode_family(ebml_w, 'n');
931 encode_name(ebml_w, item.ident.name);
932 encode_path(ebml_w, path);
934 // Encode all the items in this module.
935 for foreign_item in fm.items.iter() {
936 ebml_w.start_tag(tag_mod_child);
937 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)).as_slice());
940 encode_visibility(ebml_w, vis);
944 add_to_index(item, ebml_w, index);
945 ebml_w.start_tag(tag_items_data_item);
946 encode_def_id(ebml_w, def_id);
947 encode_family(ebml_w, 'y');
948 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
949 encode_name(ebml_w, item.ident.name);
950 encode_path(ebml_w, path);
951 encode_visibility(ebml_w, vis);
954 ItemEnum(ref enum_definition, ref generics) => {
955 add_to_index(item, ebml_w, index);
957 ebml_w.start_tag(tag_items_data_item);
958 encode_def_id(ebml_w, def_id);
959 encode_family(ebml_w, 't');
960 encode_item_variances(ebml_w, ecx, item.id);
961 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
962 encode_name(ebml_w, item.ident.name);
963 encode_attributes(ebml_w, item.attrs.as_slice());
964 for v in (*enum_definition).variants.iter() {
965 encode_variant_id(ebml_w, local_def(v.node.id));
967 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
968 encode_path(ebml_w, path);
970 // Encode inherent implementations for this enumeration.
971 encode_inherent_implementations(ecx, ebml_w, def_id);
973 encode_visibility(ebml_w, vis);
976 encode_enum_variant_info(ecx,
979 (*enum_definition).variants.as_slice(),
983 ItemStruct(struct_def, _) => {
984 let fields = ty::lookup_struct_fields(tcx, def_id);
986 /* First, encode the fields
987 These come first because we need to write them to make
988 the index, and the index needs to be in the item for the
990 let idx = encode_info_for_struct(ecx,
996 add_to_index(item, ebml_w, index);
998 /* Now, make an item for the class itself */
999 ebml_w.start_tag(tag_items_data_item);
1000 encode_def_id(ebml_w, def_id);
1001 encode_family(ebml_w, 'S');
1002 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1004 encode_item_variances(ebml_w, ecx, item.id);
1005 encode_name(ebml_w, item.ident.name);
1006 encode_attributes(ebml_w, item.attrs.as_slice());
1007 encode_path(ebml_w, path.clone());
1008 encode_visibility(ebml_w, vis);
1010 /* Encode def_ids for each field and method
1011 for methods, write all the stuff get_trait_method
1013 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1015 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1017 // Encode inherent implementations for this structure.
1018 encode_inherent_implementations(ecx, ebml_w, def_id);
1020 /* Each class has its own index -- encode it */
1021 encode_index(ebml_w, idx, write_i64);
1024 // If this is a tuple-like struct, encode the type of the constructor.
1025 match struct_def.ctor_id {
1027 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1028 ctor_id, index, def_id.node);
1033 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1034 // We need to encode information about the default methods we
1035 // have inherited, so we drive this based on the impl structure.
1036 let impl_methods = tcx.impl_methods.borrow();
1037 let methods = impl_methods.get(&def_id);
1039 add_to_index(item, ebml_w, index);
1040 ebml_w.start_tag(tag_items_data_item);
1041 encode_def_id(ebml_w, def_id);
1042 encode_family(ebml_w, 'i');
1043 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1044 encode_name(ebml_w, item.ident.name);
1045 encode_attributes(ebml_w, item.attrs.as_slice());
1047 ast::TyPath(ref path, ref bounds, _) if path.segments
1049 assert!(bounds.is_none());
1050 encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
1054 for &method_def_id in methods.iter() {
1055 ebml_w.start_tag(tag_item_impl_method);
1056 let s = def_to_str(method_def_id);
1057 ebml_w.writer.write(s.as_bytes());
1060 for ast_trait_ref in opt_trait.iter() {
1061 let trait_ref = ty::node_id_to_trait_ref(
1062 tcx, ast_trait_ref.ref_id);
1063 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1064 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1065 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1067 encode_path(ebml_w, path.clone());
1070 // Iterate down the methods, emitting them. We rely on the
1071 // assumption that all of the actually implemented methods
1072 // appear first in the impl structure, in the same order they do
1073 // in the ast. This is a little sketchy.
1074 let num_implemented_methods = ast_methods.len();
1075 for (i, &method_def_id) in methods.iter().enumerate() {
1076 let ast_method = if i < num_implemented_methods {
1077 Some(*ast_methods.get(i))
1081 val: method_def_id.node as i64,
1082 pos: ebml_w.writer.tell().unwrap(),
1084 encode_info_for_method(ecx,
1086 &*ty::method(tcx, method_def_id),
1093 ItemTrait(_, sized, ref super_traits, ref ms) => {
1094 add_to_index(item, ebml_w, index);
1095 ebml_w.start_tag(tag_items_data_item);
1096 encode_def_id(ebml_w, def_id);
1097 encode_family(ebml_w, 'I');
1098 encode_item_variances(ebml_w, ecx, item.id);
1099 let trait_def = ty::lookup_trait_def(tcx, def_id);
1100 encode_ty_type_param_defs(ebml_w, ecx,
1101 trait_def.generics.type_param_defs(),
1102 tag_items_data_item_ty_param_bounds);
1103 encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
1104 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1105 encode_name(ebml_w, item.ident.name);
1106 encode_attributes(ebml_w, item.attrs.as_slice());
1107 // When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
1108 // should no longer need this ugly little hack either.
1109 encode_sized(ebml_w, sized);
1110 encode_visibility(ebml_w, vis);
1111 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1112 ebml_w.start_tag(tag_item_trait_method);
1113 encode_def_id(ebml_w, method_def_id);
1116 ebml_w.start_tag(tag_mod_child);
1117 ebml_w.wr_str(def_to_str(method_def_id).as_slice());
1120 encode_path(ebml_w, path.clone());
1121 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1122 // reading the AST's list, because the former has already filtered out
1123 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1124 for ast_trait_ref in super_traits.iter() {
1125 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1126 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1129 // Encode the implementations of this trait.
1130 encode_extension_implementations(ecx, ebml_w, def_id);
1134 // Now output the method info for each method.
1135 let r = ty::trait_method_def_ids(tcx, def_id);
1136 for (i, &method_def_id) in r.iter().enumerate() {
1137 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1139 let method_ty = ty::method(tcx, method_def_id);
1142 val: method_def_id.node as i64,
1143 pos: ebml_w.writer.tell().unwrap(),
1146 ebml_w.start_tag(tag_items_data_item);
1148 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1150 encode_parent_item(ebml_w, def_id);
1152 let elem = ast_map::PathName(method_ty.ident.name);
1153 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1155 match method_ty.explicit_self {
1157 encode_family(ebml_w,
1158 fn_style_static_method_family(
1159 method_ty.fty.fn_style));
1161 let tpt = ty::lookup_item_type(tcx, method_def_id);
1162 encode_bounds_and_type(ebml_w, ecx, &tpt);
1166 encode_family(ebml_w,
1168 method_ty.fty.fn_style));
1173 &Required(ref tm) => {
1174 encode_attributes(ebml_w, tm.attrs.as_slice());
1175 encode_method_sort(ebml_w, 'r');
1179 encode_attributes(ebml_w, m.attrs.as_slice());
1180 // If this is a static method, we've already encoded
1182 if method_ty.explicit_self != SelfStatic {
1183 // FIXME: I feel like there is something funny going on.
1184 let tpt = ty::lookup_item_type(tcx, method_def_id);
1185 encode_bounds_and_type(ebml_w, ecx, &tpt);
1187 encode_method_sort(ebml_w, 'p');
1188 encode_inlined_item(ecx, ebml_w,
1189 IIMethodRef(def_id, true, m));
1196 // Encode inherent implementations for this trait.
1197 encode_inherent_implementations(ecx, ebml_w, def_id);
1200 // macros are encoded separately
1205 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1206 ebml_w: &mut Encoder,
1207 nitem: &ForeignItem,
1208 index: &mut Vec<entry<i64>>,
1212 val: nitem.id as i64,
1213 pos: ebml_w.writer.tell().unwrap(),
1216 ebml_w.start_tag(tag_items_data_item);
1217 encode_def_id(ebml_w, local_def(nitem.id));
1219 ForeignItemFn(..) => {
1220 encode_family(ebml_w, style_fn_family(NormalFn));
1221 encode_bounds_and_type(ebml_w, ecx,
1222 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1223 encode_name(ebml_w, nitem.ident.name);
1224 if abi == abi::RustIntrinsic {
1225 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1227 encode_symbol(ecx, ebml_w, nitem.id);
1230 ForeignItemStatic(_, mutbl) => {
1232 encode_family(ebml_w, 'b');
1234 encode_family(ebml_w, 'c');
1236 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1237 encode_symbol(ecx, ebml_w, nitem.id);
1238 encode_name(ebml_w, nitem.ident.name);
1241 encode_path(ebml_w, path);
1245 fn my_visit_expr(_e: &Expr) { }
1247 fn my_visit_item(i: &Item,
1248 ebml_w: &mut Encoder,
1250 index: &mut Vec<entry<i64>>) {
1251 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1253 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1254 ecx.tcx.map.with_path(i.id, |path| {
1255 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1259 fn my_visit_foreign_item(ni: &ForeignItem,
1260 ebml_w: &mut Encoder,
1262 index: &mut Vec<entry<i64>>) {
1264 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1265 debug!("writing foreign item {}::{}",
1266 ecx.tcx.map.path_to_str(ni.id),
1267 token::get_ident(ni.ident));
1269 let mut ebml_w = unsafe {
1270 ebml_w.unsafe_clone()
1272 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1273 ecx.tcx.map.with_path(ni.id, |path| {
1274 encode_info_for_foreign_item(ecx, &mut ebml_w,
1280 struct EncodeVisitor<'a,'b> {
1281 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1283 index: &'a mut Vec<entry<i64>>,
1286 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1287 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1288 visit::walk_expr(self, ex, ());
1291 fn visit_item(&mut self, i: &Item, _: ()) {
1292 visit::walk_item(self, i, ());
1294 self.ebml_w_for_visit_item,
1298 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1299 visit::walk_foreign_item(self, ni, ());
1300 my_visit_foreign_item(ni,
1301 self.ebml_w_for_visit_item,
1307 fn encode_info_for_items(ecx: &EncodeContext,
1308 ebml_w: &mut Encoder,
1310 -> Vec<entry<i64>> {
1311 let mut index = Vec::new();
1312 ebml_w.start_tag(tag_items_data);
1314 val: CRATE_NODE_ID as i64,
1315 pos: ebml_w.writer.tell().unwrap(),
1317 encode_info_for_mod(ecx,
1321 ast_map::Values([].iter()).chain(None),
1322 syntax::parse::token::special_idents::invalid,
1325 // See comment in `encode_side_tables_for_ii` in astencode
1326 let ecx_ptr: *int = unsafe { mem::transmute(ecx) };
1327 visit::walk_crate(&mut EncodeVisitor {
1330 ebml_w_for_visit_item: &mut *ebml_w,
1338 // Path and definition ID indexing
1340 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1341 write_fn: |&mut MemWriter, &T|) {
1342 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1343 for elt in index.move_iter() {
1344 let h = hash::hash(&elt.val) as uint;
1345 buckets.get_mut(h % 256).push(elt);
1348 ebml_w.start_tag(tag_index);
1349 let mut bucket_locs = Vec::new();
1350 ebml_w.start_tag(tag_index_buckets);
1351 for bucket in buckets.iter() {
1352 bucket_locs.push(ebml_w.writer.tell().unwrap());
1353 ebml_w.start_tag(tag_index_buckets_bucket);
1354 for elt in bucket.iter() {
1355 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1356 assert!(elt.pos < 0xffff_ffff);
1358 let wr: &mut MemWriter = ebml_w.writer;
1359 wr.write_be_u32(elt.pos as u32);
1361 write_fn(ebml_w.writer, &elt.val);
1367 ebml_w.start_tag(tag_index_table);
1368 for pos in bucket_locs.iter() {
1369 assert!(*pos < 0xffff_ffff);
1370 let wr: &mut MemWriter = ebml_w.writer;
1371 wr.write_be_u32(*pos as u32);
1377 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1378 let wr: &mut MemWriter = writer;
1379 assert!(n < 0x7fff_ffff);
1380 wr.write_be_u32(n as u32);
1383 fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
1385 MetaWord(ref name) => {
1386 ebml_w.start_tag(tag_meta_item_word);
1387 ebml_w.start_tag(tag_meta_item_name);
1388 ebml_w.writer.write(name.get().as_bytes());
1392 MetaNameValue(ref name, ref value) => {
1394 LitStr(ref value, _) => {
1395 ebml_w.start_tag(tag_meta_item_name_value);
1396 ebml_w.start_tag(tag_meta_item_name);
1397 ebml_w.writer.write(name.get().as_bytes());
1399 ebml_w.start_tag(tag_meta_item_value);
1400 ebml_w.writer.write(value.get().as_bytes());
1404 _ => {/* FIXME (#623): encode other variants */ }
1407 MetaList(ref name, ref items) => {
1408 ebml_w.start_tag(tag_meta_item_list);
1409 ebml_w.start_tag(tag_meta_item_name);
1410 ebml_w.writer.write(name.get().as_bytes());
1412 for inner_item in items.iter() {
1413 encode_meta_item(ebml_w, *inner_item);
1420 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1421 ebml_w.start_tag(tag_attributes);
1422 for attr in attrs.iter() {
1423 ebml_w.start_tag(tag_attribute);
1424 encode_meta_item(ebml_w, attr.node.value);
1430 // So there's a special crate attribute called 'crate_id' which defines the
1431 // metadata that Rust cares about for linking crates. If the user didn't
1432 // provide it we will throw it in anyway with a default value.
1433 fn synthesize_crate_attrs(ecx: &EncodeContext,
1434 krate: &Crate) -> Vec<Attribute> {
1436 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1437 assert!(!ecx.link_meta.crateid.name.is_empty());
1439 attr::mk_attr_inner(
1440 attr::mk_name_value_item_str(
1441 InternedString::new("crate_id"),
1442 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1445 let mut attrs = Vec::new();
1446 for attr in krate.attrs.iter() {
1447 if !attr.name().equiv(&("crate_id")) {
1451 attrs.push(synthesize_crateid_attr(ecx));
1456 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1457 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1458 // Pull the cnums and name,vers,hash out of cstore
1459 let mut deps = Vec::new();
1460 cstore.iter_crate_data(|key, val| {
1461 let dep = decoder::CrateDep {
1463 crate_id: decoder::get_crate_id(val.data()),
1464 hash: decoder::get_crate_hash(val.data())
1470 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1472 // Sanity-check the crate numbers
1473 let mut expected_cnum = 1;
1474 for n in deps.iter() {
1475 assert_eq!(n.cnum, expected_cnum);
1482 // We're just going to write a list of crate 'name-hash-version's, with
1483 // the assumption that they are numbered 1 to n.
1484 // FIXME (#2166): This is not nearly enough to support correct versioning
1485 // but is enough to get transitive crate dependencies working.
1486 ebml_w.start_tag(tag_crate_deps);
1487 let r = get_ordered_deps(cstore);
1488 for dep in r.iter() {
1489 encode_crate_dep(ebml_w, (*dep).clone());
1494 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1495 ebml_w.start_tag(tag_lang_items);
1497 for (i, def_id) in ecx.tcx.lang_items.items() {
1498 for id in def_id.iter() {
1499 if id.krate == LOCAL_CRATE {
1500 ebml_w.start_tag(tag_lang_items_item);
1502 ebml_w.start_tag(tag_lang_items_item_id);
1504 let wr: &mut MemWriter = ebml_w.writer;
1505 wr.write_be_u32(i as u32);
1507 ebml_w.end_tag(); // tag_lang_items_item_id
1509 ebml_w.start_tag(tag_lang_items_item_node_id);
1511 let wr: &mut MemWriter = ebml_w.writer;
1512 wr.write_be_u32(id.node as u32);
1514 ebml_w.end_tag(); // tag_lang_items_item_node_id
1516 ebml_w.end_tag(); // tag_lang_items_item
1521 for i in ecx.tcx.lang_items.missing.iter() {
1522 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1525 ebml_w.end_tag(); // tag_lang_items
1528 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1529 ebml_w.start_tag(tag_native_libraries);
1531 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1534 cstore::NativeStatic => {} // these libraries are not propagated
1535 cstore::NativeFramework | cstore::NativeUnknown => {
1536 ebml_w.start_tag(tag_native_libraries_lib);
1538 ebml_w.start_tag(tag_native_libraries_kind);
1539 ebml_w.writer.write_be_u32(kind as u32);
1542 ebml_w.start_tag(tag_native_libraries_name);
1543 ebml_w.writer.write(lib.as_bytes());
1554 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1555 match ecx.tcx.sess.macro_registrar_fn.get() {
1556 Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
1561 struct MacroDefVisitor<'a, 'b, 'c> {
1562 ecx: &'a EncodeContext<'b>,
1563 ebml_w: &'a mut Encoder<'c>
1566 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1567 fn visit_item(&mut self, item: &Item, _: ()) {
1570 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1571 .expect("Unable to find source for macro");
1572 self.ebml_w.start_tag(tag_macro_def);
1573 self.ebml_w.wr_str(def.as_slice());
1574 self.ebml_w.end_tag();
1578 visit::walk_item(self, item, ());
1582 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1584 ebml_w: &'a mut Encoder) {
1585 ebml_w.start_tag(tag_exported_macros);
1587 let mut visitor = MacroDefVisitor {
1591 visit::walk_crate(&mut visitor, krate, ());
1596 struct ImplVisitor<'a,'b,'c> {
1597 ecx: &'a EncodeContext<'b>,
1598 ebml_w: &'a mut Encoder<'c>,
1601 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1602 fn visit_item(&mut self, item: &Item, _: ()) {
1604 ItemImpl(_, Some(ref trait_ref), _, _) => {
1605 let def_map = &self.ecx.tcx.def_map;
1606 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1607 let def_id = ast_util::def_id_of_def(trait_def);
1609 // Load eagerly if this is an implementation of the Drop trait
1610 // or if the trait is not defined in this crate.
1611 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1612 def_id.krate != LOCAL_CRATE {
1613 self.ebml_w.start_tag(tag_impls_impl);
1614 encode_def_id(self.ebml_w, local_def(item.id));
1615 self.ebml_w.end_tag();
1620 visit::walk_item(self, item, ());
1624 /// Encodes implementations that are eagerly loaded.
1626 /// None of this is necessary in theory; we can load all implementations
1627 /// lazily. However, in two cases the optimizations to lazily load
1628 /// implementations are not yet implemented. These two cases, which require us
1629 /// to load implementations eagerly, are:
1631 /// * Destructors (implementations of the Drop trait).
1633 /// * Implementations of traits not defined in this crate.
1634 fn encode_impls<'a>(ecx: &'a EncodeContext,
1636 ebml_w: &'a mut Encoder) {
1637 ebml_w.start_tag(tag_impls);
1640 let mut visitor = ImplVisitor {
1644 visit::walk_crate(&mut visitor, krate, ());
1650 fn encode_misc_info(ecx: &EncodeContext,
1652 ebml_w: &mut Encoder) {
1653 ebml_w.start_tag(tag_misc_info);
1654 ebml_w.start_tag(tag_misc_info_crate_items);
1655 for &item in krate.module.items.iter() {
1656 ebml_w.start_tag(tag_mod_child);
1657 ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
1660 each_auxiliary_node_id(item, |auxiliary_node_id| {
1661 ebml_w.start_tag(tag_mod_child);
1662 ebml_w.wr_str(def_to_str(local_def(
1663 auxiliary_node_id)).as_slice());
1669 // Encode reexports for the root module.
1670 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1676 fn encode_crate_dep(ebml_w: &mut Encoder,
1677 dep: decoder::CrateDep) {
1678 ebml_w.start_tag(tag_crate_dep);
1679 ebml_w.start_tag(tag_crate_dep_crateid);
1680 ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1682 ebml_w.start_tag(tag_crate_dep_hash);
1683 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1688 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1689 ebml_w.start_tag(tag_crate_hash);
1690 ebml_w.writer.write(hash.as_str().as_bytes());
1694 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1695 ebml_w.start_tag(tag_crate_crateid);
1696 ebml_w.writer.write(crate_id.to_str().as_bytes());
1700 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1701 ebml_w.start_tag(tag_crate_triple);
1702 ebml_w.writer.write(triple.as_bytes());
1706 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1707 ebml_w.start_tag(tag_dylib_dependency_formats);
1708 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1710 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1711 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1712 cstore::RequireDynamic => "d",
1713 cstore::RequireStatic => "s",
1715 }).collect::<Vec<StrBuf>>();
1716 ebml_w.writer.write(s.connect(",").as_bytes());
1723 // NB: Increment this as you change the metadata encoding version.
1724 pub static metadata_encoding_version : &'static [u8] =
1725 &[0x72, //'r' as u8,
1731 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1732 let mut wr = MemWriter::new();
1733 encode_metadata_inner(&mut wr, parms, krate);
1734 wr.unwrap().move_iter().collect()
1737 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1741 lang_item_bytes: u64,
1742 native_lib_bytes: u64,
1743 macro_registrar_fn_bytes: u64,
1744 macro_defs_bytes: u64,
1752 let mut stats = Stats {
1756 native_lib_bytes: 0,
1757 macro_registrar_fn_bytes: 0,
1758 macro_defs_bytes: 0,
1772 encode_inlined_item,
1774 non_inlineable_statics,
1777 let ecx = EncodeContext {
1780 reexports2: reexports2,
1781 item_symbols: item_symbols,
1782 non_inlineable_statics: non_inlineable_statics,
1783 link_meta: link_meta,
1785 encode_inlined_item: RefCell::new(encode_inlined_item),
1786 type_abbrevs: RefCell::new(HashMap::new()),
1789 let mut ebml_w = writer::Encoder(wr);
1791 encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1792 encode_crate_triple(&mut ebml_w,
1798 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1799 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1801 let mut i = ebml_w.writer.tell().unwrap();
1802 let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1803 encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1804 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1806 i = ebml_w.writer.tell().unwrap();
1807 encode_crate_deps(&mut ebml_w, ecx.cstore);
1808 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1810 // Encode the language items.
1811 i = ebml_w.writer.tell().unwrap();
1812 encode_lang_items(&ecx, &mut ebml_w);
1813 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1815 // Encode the native libraries used
1816 i = ebml_w.writer.tell().unwrap();
1817 encode_native_libraries(&ecx, &mut ebml_w);
1818 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1820 // Encode the macro registrar function
1821 i = ebml_w.writer.tell().unwrap();
1822 encode_macro_registrar_fn(&ecx, &mut ebml_w);
1823 stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1825 // Encode macro definitions
1826 i = ebml_w.writer.tell().unwrap();
1827 encode_macro_defs(&ecx, krate, &mut ebml_w);
1828 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1830 // Encode the def IDs of impls, for coherence checking.
1831 i = ebml_w.writer.tell().unwrap();
1832 encode_impls(&ecx, krate, &mut ebml_w);
1833 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1835 // Encode miscellaneous info.
1836 i = ebml_w.writer.tell().unwrap();
1837 encode_misc_info(&ecx, krate, &mut ebml_w);
1838 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1840 // Encode and index the items.
1841 ebml_w.start_tag(tag_items);
1842 i = ebml_w.writer.tell().unwrap();
1843 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1844 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1846 i = ebml_w.writer.tell().unwrap();
1847 encode_index(&mut ebml_w, items_index, write_i64);
1848 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1851 stats.total_bytes = ebml_w.writer.tell().unwrap();
1853 if tcx.sess.meta_stats() {
1854 for e in ebml_w.writer.get_ref().iter() {
1856 stats.zero_bytes += 1;
1860 println!("metadata stats:");
1861 println!(" attribute bytes: {}", stats.attr_bytes);
1862 println!(" dep bytes: {}", stats.dep_bytes);
1863 println!(" lang item bytes: {}", stats.lang_item_bytes);
1864 println!(" native bytes: {}", stats.native_lib_bytes);
1865 println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
1866 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1867 println!(" impl bytes: {}", stats.impl_bytes);
1868 println!(" misc bytes: {}", stats.misc_bytes);
1869 println!(" item bytes: {}", stats.item_bytes);
1870 println!(" index bytes: {}", stats.index_bytes);
1871 println!(" zero bytes: {}", stats.zero_bytes);
1872 println!(" total bytes: {}", stats.total_bytes);
1876 // Get the encoded string for a type
1877 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> StrBuf {
1878 let mut wr = MemWriter::new();
1879 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1880 diag: tcx.sess.diagnostic(),
1883 abbrevs: &RefCell::new(HashMap::new())
1885 str::from_utf8_owned(wr.get_ref().to_owned()).unwrap().to_strbuf()