1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
16 pub use self::InlinedItemRef::*;
20 use metadata::common::*;
22 use metadata::decoder;
23 use metadata::tyencode;
25 use middle::ty::{lookup_item_type};
26 use middle::ty::{self, Ty};
27 use middle::stability;
28 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
30 use serialize::Encodable;
31 use std::cell::RefCell;
35 use syntax::ast::{self, DefId, NodeId};
36 use syntax::ast_map::{PathElem, PathElems};
38 use syntax::ast_util::*;
41 use syntax::attr::AttrMetaMethods;
42 use syntax::diagnostic::SpanHandler;
43 use syntax::parse::token::special_idents;
44 use syntax::parse::token;
46 use syntax::visit::Visitor;
50 use rbml::io::SeekableMemWriter;
52 /// A borrowed version of `ast::InlinedItem`.
53 pub enum InlinedItemRef<'a> {
54 IIItemRef(&'a ast::Item),
55 IITraitItemRef(DefId, &'a ast::TraitItem),
56 IIImplItemRef(DefId, &'a ast::ImplItem),
57 IIForeignRef(&'a ast::ForeignItem)
60 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
62 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
64 ii: InlinedItemRef|: 'a;
66 pub struct EncodeParams<'a, 'tcx: 'a> {
67 pub diag: &'a SpanHandler,
68 pub tcx: &'a ty::ctxt<'tcx>,
69 pub reexports: &'a def::ExportMap,
70 pub item_symbols: &'a RefCell<NodeMap<String>>,
71 pub link_meta: &'a LinkMeta,
72 pub cstore: &'a cstore::CStore,
73 pub encode_inlined_item: EncodeInlinedItem<'a>,
74 pub reachable: &'a NodeSet,
77 pub struct EncodeContext<'a, 'tcx: 'a> {
78 pub diag: &'a SpanHandler,
79 pub tcx: &'a ty::ctxt<'tcx>,
80 pub reexports: &'a def::ExportMap,
81 pub item_symbols: &'a RefCell<NodeMap<String>>,
82 pub link_meta: &'a LinkMeta,
83 pub cstore: &'a cstore::CStore,
84 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
85 pub type_abbrevs: tyencode::abbrev_map<'tcx>,
86 pub reachable: &'a NodeSet,
89 fn encode_name(rbml_w: &mut Encoder, name: ast::Name) {
90 rbml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
93 fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) {
94 rbml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
97 pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
98 rbml_w.wr_tagged_str(tag_def_id, def_to_string(id)[]);
107 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
108 ecx: &EncodeContext<'a, 'tcx>,
109 trait_ref: &ty::TraitRef<'tcx>,
111 let ty_str_ctxt = &tyencode::ctxt {
115 abbrevs: &ecx.type_abbrevs
118 rbml_w.start_tag(tag);
119 tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
123 // Item info table encoding
124 fn encode_family(rbml_w: &mut Encoder, c: char) {
125 rbml_w.start_tag(tag_items_data_item_family);
126 rbml_w.writer.write(&[c as u8]);
130 pub fn def_to_string(did: DefId) -> String {
131 format!("{}:{}", did.krate, did.node)
134 fn encode_item_variances(rbml_w: &mut Encoder,
137 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
138 rbml_w.start_tag(tag_item_variances);
143 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
144 ecx: &EncodeContext<'a, 'tcx>,
145 pty: &ty::TypeScheme<'tcx>) {
146 encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics);
147 encode_type(ecx, rbml_w, pty.ty);
150 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
151 rbml_w.start_tag(tag_items_data_item_variant);
152 let s = def_to_string(vid);
153 rbml_w.writer.write(s.as_bytes());
156 rbml_w.start_tag(tag_mod_child);
161 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
162 rbml_w: &mut Encoder,
163 closure_type: &ty::ClosureTy<'tcx>) {
164 let ty_str_ctxt = &tyencode::ctxt {
168 abbrevs: &ecx.type_abbrevs
170 tyencode::enc_closure_ty(rbml_w.writer, ty_str_ctxt, closure_type);
173 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
174 rbml_w: &mut Encoder,
176 let ty_str_ctxt = &tyencode::ctxt {
180 abbrevs: &ecx.type_abbrevs
182 tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ);
185 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
186 rbml_w: &mut Encoder,
187 trait_ref: &ty::TraitRef<'tcx>) {
188 let ty_str_ctxt = &tyencode::ctxt {
192 abbrevs: &ecx.type_abbrevs
194 tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
197 pub fn write_region(ecx: &EncodeContext,
198 rbml_w: &mut Encoder,
200 let ty_str_ctxt = &tyencode::ctxt {
204 abbrevs: &ecx.type_abbrevs
206 tyencode::enc_region(rbml_w.writer, ty_str_ctxt, r);
209 fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder,
210 ecx: &EncodeContext<'a, 'tcx>,
211 bounds: &ty::ParamBounds<'tcx>,
213 rbml_w.start_tag(tag);
215 let ty_str_ctxt = &tyencode::ctxt { diag: ecx.diag,
218 abbrevs: &ecx.type_abbrevs };
219 tyencode::enc_bounds(rbml_w.writer, ty_str_ctxt, bounds);
224 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
225 rbml_w: &mut Encoder,
227 rbml_w.start_tag(tag_items_data_item_type);
228 write_type(ecx, rbml_w, typ);
232 fn encode_region(ecx: &EncodeContext,
233 rbml_w: &mut Encoder,
235 rbml_w.start_tag(tag_items_data_region);
236 write_region(ecx, rbml_w, r);
240 fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
241 rbml_w: &mut Encoder,
242 typ: &ty::BareFnTy<'tcx>) {
243 rbml_w.start_tag(tag_item_method_fty);
245 let ty_str_ctxt = &tyencode::ctxt {
249 abbrevs: &ecx.type_abbrevs
251 tyencode::enc_bare_fn_ty(rbml_w.writer, ty_str_ctxt, typ);
256 fn encode_symbol(ecx: &EncodeContext,
257 rbml_w: &mut Encoder,
259 rbml_w.start_tag(tag_items_data_item_symbol);
260 match ecx.item_symbols.borrow().get(&id) {
262 debug!("encode_symbol(id={}, str={})", id, *x);
263 rbml_w.writer.write(x.as_bytes());
266 ecx.diag.handler().bug(
267 format!("encode_symbol: id not found {}", id)[]);
273 fn encode_disr_val(_: &EncodeContext,
274 rbml_w: &mut Encoder,
275 disr_val: ty::Disr) {
276 rbml_w.start_tag(tag_disr_val);
277 let s = disr_val.to_string();
278 rbml_w.writer.write(s.as_bytes());
282 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
283 rbml_w.start_tag(tag_items_data_parent_item);
284 let s = def_to_string(id);
285 rbml_w.writer.write(s.as_bytes());
289 fn encode_struct_fields(rbml_w: &mut Encoder,
290 fields: &[ty::field_ty],
292 for f in fields.iter() {
293 if f.name == special_idents::unnamed_field.name {
294 rbml_w.start_tag(tag_item_unnamed_field);
296 rbml_w.start_tag(tag_item_field);
297 encode_name(rbml_w, f.name);
299 encode_struct_field_family(rbml_w, f.vis);
300 encode_def_id(rbml_w, f.id);
301 rbml_w.start_tag(tag_item_field_origin);
302 let s = def_to_string(origin);
303 rbml_w.writer.write(s.as_bytes());
309 fn encode_enum_variant_info(ecx: &EncodeContext,
310 rbml_w: &mut Encoder,
312 variants: &[P<ast::Variant>],
313 index: &mut Vec<entry<i64>>) {
314 debug!("encode_enum_variant_info(id={})", id);
316 let mut disr_val = 0;
318 let vi = ty::enum_variants(ecx.tcx,
319 DefId { krate: ast::LOCAL_CRATE, node: id });
320 for variant in variants.iter() {
321 let def_id = local_def(variant.node.id);
323 val: variant.node.id as i64,
324 pos: rbml_w.writer.tell().unwrap(),
326 rbml_w.start_tag(tag_items_data_item);
327 encode_def_id(rbml_w, def_id);
328 match variant.node.kind {
329 ast::TupleVariantKind(_) => encode_family(rbml_w, 'v'),
330 ast::StructVariantKind(_) => encode_family(rbml_w, 'V')
332 encode_name(rbml_w, variant.node.name.name);
333 encode_parent_item(rbml_w, local_def(id));
334 encode_visibility(rbml_w, variant.node.vis);
335 encode_attributes(rbml_w, variant.node.attrs[]);
336 encode_repr_attrs(rbml_w, ecx, variant.node.attrs[]);
338 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
339 encode_stability(rbml_w, stab);
341 match variant.node.kind {
342 ast::TupleVariantKind(_) => {},
343 ast::StructVariantKind(_) => {
344 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
345 let idx = encode_info_for_struct(ecx,
349 encode_struct_fields(rbml_w, fields[], def_id);
350 encode_index(rbml_w, idx, write_i64);
353 if (*vi)[i].disr_val != disr_val {
354 encode_disr_val(ecx, rbml_w, (*vi)[i].disr_val);
355 disr_val = (*vi)[i].disr_val;
357 encode_bounds_and_type(rbml_w, ecx,
358 &lookup_item_type(ecx.tcx, def_id));
360 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
367 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
368 let path = path.collect::<Vec<_>>();
369 rbml_w.start_tag(tag_path);
370 rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
371 for pe in path.iter() {
372 let tag = match *pe {
373 ast_map::PathMod(_) => tag_path_elem_mod,
374 ast_map::PathName(_) => tag_path_elem_name
376 rbml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
381 fn encode_reexported_static_method(rbml_w: &mut Encoder,
383 method_def_id: DefId,
384 method_name: ast::Name) {
385 debug!("(encode reexported static method) {}::{}",
386 exp.name, token::get_name(method_name));
387 rbml_w.start_tag(tag_items_data_item_reexport);
388 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
389 rbml_w.wr_str(def_to_string(method_def_id)[]);
391 rbml_w.start_tag(tag_items_data_item_reexport_name);
392 rbml_w.wr_str(format!("{}::{}",
394 token::get_name(method_name))[]);
399 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
400 rbml_w: &mut Encoder,
403 let impl_items = ecx.tcx.impl_items.borrow();
404 match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
405 Some(implementations) => {
406 for base_impl_did in implementations.iter() {
407 for &method_did in (*impl_items)[*base_impl_did].iter() {
408 let impl_item = ty::impl_or_trait_item(
410 method_did.def_id());
412 ty::MethodTraitItem(ref m) => {
413 encode_reexported_static_method(rbml_w,
418 ty::TypeTraitItem(_) => {}
429 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
430 rbml_w: &mut Encoder,
433 match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
434 Some(trait_items) => {
435 for trait_item in trait_items.iter() {
436 if let ty::MethodTraitItem(ref m) = *trait_item {
437 encode_reexported_static_method(rbml_w,
449 fn encode_reexported_static_methods(ecx: &EncodeContext,
450 rbml_w: &mut Encoder,
453 if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
454 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
455 let (mut a, mut b) = (path, mod_path.clone());
457 match (a.next(), b.next()) {
458 (None, None) => return true,
459 (None, _) | (_, None) => return false,
460 (Some(x), Some(y)) => if x != y { return false },
466 // We don't need to reexport static methods on items
467 // declared in the same module as our `pub use ...` since
468 // that's done when we encode the item itself.
470 // The only exception is when the reexport *changes* the
471 // name e.g. `pub use Foo = self::Bar` -- we have
472 // encoded metadata for static methods relative to Bar,
473 // but not yet for Foo.
475 if path_differs || item.ident.name != exp.name {
476 if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
477 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
478 debug!("(encode reexported static methods) {} [trait]",
483 debug!("(encode reexported static methods) {} [base]",
490 /// Iterates through "auxiliary node IDs", which are node IDs that describe
491 /// top-level items that are sub-items of the given item. Specifically:
493 /// * For newtype structs, iterates through the node ID of the constructor.
494 fn each_auxiliary_node_id<F>(item: &ast::Item, callback: F) -> bool where
495 F: FnOnce(NodeId) -> bool,
497 let mut continue_ = true;
499 ast::ItemStruct(ref struct_def, _) => {
500 // If this is a newtype struct, return the constructor.
501 match struct_def.ctor_id {
502 Some(ctor_id) if struct_def.fields.len() > 0 &&
503 struct_def.fields[0].node.kind.is_unnamed() => {
504 continue_ = callback(ctor_id);
515 fn encode_reexports(ecx: &EncodeContext,
516 rbml_w: &mut Encoder,
519 debug!("(encoding info for module) encoding reexports for {}", id);
520 match ecx.reexports.get(&id) {
521 Some(ref exports) => {
522 debug!("(encoding info for module) found reexports for {}", id);
523 for exp in exports.iter() {
524 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
530 rbml_w.start_tag(tag_items_data_item_reexport);
531 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
532 rbml_w.wr_str(def_to_string(exp.def_id)[]);
534 rbml_w.start_tag(tag_items_data_item_reexport_name);
535 rbml_w.wr_str(exp.name.as_str());
538 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
542 debug!("(encoding info for module) found no reexports for {}",
548 fn encode_info_for_mod(ecx: &EncodeContext,
549 rbml_w: &mut Encoder,
551 attrs: &[ast::Attribute],
555 vis: ast::Visibility) {
556 rbml_w.start_tag(tag_items_data_item);
557 encode_def_id(rbml_w, local_def(id));
558 encode_family(rbml_w, 'm');
559 encode_name(rbml_w, name.name);
560 debug!("(encoding info for module) encoding info for module ID {}", id);
562 // Encode info about all the module children.
563 for item in md.items.iter() {
564 rbml_w.start_tag(tag_mod_child);
565 rbml_w.wr_str(def_to_string(local_def(item.id))[]);
568 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
569 rbml_w.start_tag(tag_mod_child);
570 rbml_w.wr_str(def_to_string(local_def(
571 auxiliary_node_id))[]);
576 if let ast::ItemImpl(..) = item.node {
577 let (ident, did) = (item.ident, item.id);
578 debug!("(encoding info for module) ... encoding impl {} ({}/{})",
579 token::get_ident(ident),
580 did, ecx.tcx.map.node_to_string(did));
582 rbml_w.start_tag(tag_mod_impl);
583 rbml_w.wr_str(def_to_string(local_def(did))[]);
588 encode_path(rbml_w, path.clone());
589 encode_visibility(rbml_w, vis);
591 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
592 encode_stability(rbml_w, stab);
594 // Encode the reexports of this module, if this module is public.
595 if vis == ast::Public {
596 debug!("(encoding info for module) encoding reexports for {}", id);
597 encode_reexports(ecx, rbml_w, id, path);
599 encode_attributes(rbml_w, attrs);
604 fn encode_struct_field_family(rbml_w: &mut Encoder,
605 visibility: ast::Visibility) {
606 encode_family(rbml_w, match visibility {
608 ast::Inherited => 'N'
612 fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
613 rbml_w.start_tag(tag_items_data_item_visibility);
614 let ch = match visibility {
616 ast::Inherited => 'i',
618 rbml_w.wr_str(ch.to_string()[]);
622 fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
623 kind: ty::UnboxedClosureKind) {
624 rbml_w.start_tag(tag_unboxed_closure_kind);
625 let ch = match kind {
626 ty::FnUnboxedClosureKind => 'f',
627 ty::FnMutUnboxedClosureKind => 'm',
628 ty::FnOnceUnboxedClosureKind => 'o',
630 rbml_w.wr_str(ch.to_string()[]);
634 fn encode_explicit_self(rbml_w: &mut Encoder,
635 explicit_self: &ty::ExplicitSelfCategory) {
636 rbml_w.start_tag(tag_item_trait_method_explicit_self);
638 // Encode the base self type.
639 match *explicit_self {
640 ty::StaticExplicitSelfCategory => {
641 rbml_w.writer.write(&[ 's' as u8 ]);
643 ty::ByValueExplicitSelfCategory => {
644 rbml_w.writer.write(&[ 'v' as u8 ]);
646 ty::ByBoxExplicitSelfCategory => {
647 rbml_w.writer.write(&[ '~' as u8 ]);
649 ty::ByReferenceExplicitSelfCategory(_, m) => {
650 // FIXME(#4846) encode custom lifetime
651 rbml_w.writer.write(&['&' as u8]);
652 encode_mutability(rbml_w, m);
658 fn encode_mutability(rbml_w: &mut Encoder,
659 m: ast::Mutability) {
661 ast::MutImmutable => { rbml_w.writer.write(&[ 'i' as u8 ]); }
662 ast::MutMutable => { rbml_w.writer.write(&[ 'm' as u8 ]); }
667 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
668 rbml_w.start_tag(tag_item_trait_item_sort);
669 rbml_w.writer.write(&[ sort as u8 ]);
673 fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
674 rbml_w.start_tag(tag_item_trait_parent_sort);
675 rbml_w.writer.write(&[ sort as u8 ]);
679 fn encode_provided_source(rbml_w: &mut Encoder,
680 source_opt: Option<DefId>) {
681 for source in source_opt.iter() {
682 rbml_w.start_tag(tag_item_method_provided_source);
683 let s = def_to_string(*source);
684 rbml_w.writer.write(s.as_bytes());
689 /* Returns an index of items in this class */
690 fn encode_info_for_struct(ecx: &EncodeContext,
691 rbml_w: &mut Encoder,
692 fields: &[ty::field_ty],
693 global_index: &mut Vec<entry<i64>>)
695 /* Each class has its own index, since different classes
696 may have fields with the same name */
697 let mut index = Vec::new();
698 /* We encode both private and public fields -- need to include
699 private fields to get the offsets right */
700 for field in fields.iter() {
702 let id = field.id.node;
704 index.push(entry {val: id as i64, pos: rbml_w.writer.tell().unwrap()});
705 global_index.push(entry {
707 pos: rbml_w.writer.tell().unwrap(),
709 rbml_w.start_tag(tag_items_data_item);
710 debug!("encode_info_for_struct: doing {} {}",
711 token::get_name(nm), id);
712 encode_struct_field_family(rbml_w, field.vis);
713 encode_name(rbml_w, nm);
714 encode_bounds_and_type(rbml_w, ecx,
715 &lookup_item_type(ecx.tcx, local_def(id)));
716 encode_def_id(rbml_w, local_def(id));
718 let stab = stability::lookup(ecx.tcx, field.id);
719 encode_stability(rbml_w, stab);
726 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
727 rbml_w: &mut Encoder,
730 index: &mut Vec<entry<i64>>,
734 pos: rbml_w.writer.tell().unwrap(),
737 rbml_w.start_tag(tag_items_data_item);
738 encode_def_id(rbml_w, local_def(ctor_id));
739 encode_family(rbml_w, 'o');
740 encode_bounds_and_type(rbml_w, ecx,
741 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
742 encode_name(rbml_w, name.name);
743 ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
744 encode_parent_item(rbml_w, local_def(struct_id));
746 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
747 encode_symbol(ecx, rbml_w, ctor_id);
750 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
751 encode_stability(rbml_w, stab);
753 // indicate that this is a tuple struct ctor, because downstream users will normally want
754 // the tuple struct definition, but without this there is no way for them to tell that
755 // they actually have a ctor rather than a normal function
756 rbml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
762 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
763 ecx: &EncodeContext<'a, 'tcx>,
764 generics: &ty::Generics<'tcx>,
767 rbml_w.start_tag(tag);
770 let ty_str_ctxt = &tyencode::ctxt {
774 abbrevs: &ecx.type_abbrevs
776 for param in generics.types.iter() {
777 rbml_w.start_tag(tag_type_param_def);
778 tyencode::enc_type_param_def(rbml_w.writer, ty_str_ctxt, param);
783 for param in generics.regions.iter() {
784 rbml_w.start_tag(tag_region_param_def);
786 rbml_w.start_tag(tag_region_param_def_ident);
787 encode_name(rbml_w, param.name);
790 rbml_w.wr_tagged_str(tag_region_param_def_def_id,
791 def_to_string(param.def_id)[]);
793 rbml_w.wr_tagged_u64(tag_region_param_def_space,
794 param.space.to_uint() as u64);
796 rbml_w.wr_tagged_u64(tag_region_param_def_index,
799 for &bound_region in param.bounds.iter() {
800 encode_region(ecx, rbml_w, bound_region);
806 for (space, _, predicate) in generics.predicates.iter_enumerated() {
807 rbml_w.start_tag(tag_predicate);
809 rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
811 rbml_w.start_tag(tag_predicate_data);
812 tyencode::enc_predicate(rbml_w.writer, ty_str_ctxt, predicate);
821 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
822 rbml_w: &mut Encoder,
823 method_ty: &ty::Method<'tcx>) {
824 encode_def_id(rbml_w, method_ty.def_id);
825 encode_name(rbml_w, method_ty.name);
826 encode_generics(rbml_w, ecx, &method_ty.generics,
827 tag_method_ty_generics);
828 encode_method_fty(ecx, rbml_w, &method_ty.fty);
829 encode_visibility(rbml_w, method_ty.vis);
830 encode_explicit_self(rbml_w, &method_ty.explicit_self);
831 match method_ty.explicit_self {
832 ty::StaticExplicitSelfCategory => {
833 encode_family(rbml_w, STATIC_METHOD_FAMILY);
835 _ => encode_family(rbml_w, METHOD_FAMILY)
837 encode_provided_source(rbml_w, method_ty.provided_source);
840 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
841 rbml_w: &mut Encoder,
842 m: &ty::Method<'tcx>,
843 impl_path: PathElems,
844 is_default_impl: bool,
846 ast_item_opt: Option<&ast::ImplItem>) {
848 debug!("encode_info_for_method: {} {}", m.def_id,
849 token::get_name(m.name));
850 rbml_w.start_tag(tag_items_data_item);
852 encode_method_ty_fields(ecx, rbml_w, m);
853 encode_parent_item(rbml_w, local_def(parent_id));
854 encode_item_sort(rbml_w, 'r');
856 let stab = stability::lookup(ecx.tcx, m.def_id);
857 encode_stability(rbml_w, stab);
859 // The type for methods gets encoded twice, which is unfortunate.
860 let pty = lookup_item_type(ecx.tcx, m.def_id);
861 encode_bounds_and_type(rbml_w, ecx, &pty);
863 let elem = ast_map::PathName(m.name);
864 encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
866 Some(&ast::MethodImplItem(ref ast_method)) => {
867 encode_attributes(rbml_w, ast_method.attrs[]);
868 let any_types = !pty.generics.types.is_empty();
869 if any_types || is_default_impl || should_inline(ast_method.attrs[]) {
870 encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
871 ast_item_opt.unwrap()));
874 encode_symbol(ecx, rbml_w, m.def_id.node);
876 encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
884 fn encode_info_for_associated_type(ecx: &EncodeContext,
885 rbml_w: &mut Encoder,
886 associated_type: &ty::AssociatedType,
887 impl_path: PathElems,
889 typedef_opt: Option<P<ast::Typedef>>) {
890 debug!("encode_info_for_associated_type({},{})",
891 associated_type.def_id,
892 token::get_name(associated_type.name));
894 rbml_w.start_tag(tag_items_data_item);
896 encode_def_id(rbml_w, associated_type.def_id);
897 encode_name(rbml_w, associated_type.name);
898 encode_visibility(rbml_w, associated_type.vis);
899 encode_family(rbml_w, 'y');
900 encode_parent_item(rbml_w, local_def(parent_id));
901 encode_item_sort(rbml_w, 't');
903 let type_scheme = ty::lookup_item_type(ecx.tcx, associated_type.def_id);
904 encode_bounds_and_type(rbml_w, ecx, &type_scheme);
906 let stab = stability::lookup(ecx.tcx, associated_type.def_id);
907 encode_stability(rbml_w, stab);
909 let elem = ast_map::PathName(associated_type.name);
910 encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
915 encode_attributes(rbml_w, typedef.attrs[]);
916 encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
924 fn encode_method_argument_names(rbml_w: &mut Encoder,
925 decl: &ast::FnDecl) {
926 rbml_w.start_tag(tag_method_argument_names);
927 for arg in decl.inputs.iter() {
928 rbml_w.start_tag(tag_method_argument_name);
929 if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
930 let name = token::get_ident(path1.node);
931 rbml_w.writer.write(name.get().as_bytes());
938 fn encode_repr_attrs(rbml_w: &mut Encoder,
940 attrs: &[ast::Attribute]) {
941 let mut repr_attrs = Vec::new();
942 for attr in attrs.iter() {
943 repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
946 rbml_w.start_tag(tag_items_data_item_repr);
947 repr_attrs.encode(rbml_w);
951 fn encode_inlined_item(ecx: &EncodeContext,
952 rbml_w: &mut Encoder,
953 ii: InlinedItemRef) {
954 let mut eii = ecx.encode_inlined_item.borrow_mut();
955 let eii: &mut EncodeInlinedItem = &mut *eii;
956 (*eii)(ecx, rbml_w, ii)
959 const FN_FAMILY: char = 'f';
960 const STATIC_METHOD_FAMILY: char = 'F';
961 const METHOD_FAMILY: char = 'h';
963 fn should_inline(attrs: &[ast::Attribute]) -> bool {
965 match find_inline_attr(attrs) {
966 InlineNone | InlineNever => false,
967 InlineHint | InlineAlways => true
971 // Encodes the inherent implementations of a structure, enumeration, or trait.
972 fn encode_inherent_implementations(ecx: &EncodeContext,
973 rbml_w: &mut Encoder,
975 match ecx.tcx.inherent_impls.borrow().get(&def_id) {
977 Some(implementations) => {
978 for &impl_def_id in implementations.iter() {
979 rbml_w.start_tag(tag_items_data_item_inherent_impl);
980 encode_def_id(rbml_w, impl_def_id);
987 // Encodes the implementations of a trait defined in this crate.
988 fn encode_extension_implementations(ecx: &EncodeContext,
989 rbml_w: &mut Encoder,
990 trait_def_id: DefId) {
991 match ecx.tcx.trait_impls.borrow().get(&trait_def_id) {
993 Some(implementations) => {
994 for &impl_def_id in implementations.borrow().iter() {
995 rbml_w.start_tag(tag_items_data_item_extension_impl);
996 encode_def_id(rbml_w, impl_def_id);
1003 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
1004 stab_opt.map(|stab| {
1005 rbml_w.start_tag(tag_items_data_item_stability);
1006 stab.encode(rbml_w).unwrap();
1011 fn encode_info_for_item(ecx: &EncodeContext,
1012 rbml_w: &mut Encoder,
1014 index: &mut Vec<entry<i64>>,
1016 vis: ast::Visibility) {
1019 fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
1020 index: &mut Vec<entry<i64>>) {
1022 val: item.id as i64,
1023 pos: rbml_w.writer.tell().unwrap(),
1027 debug!("encoding info for item at {}",
1028 tcx.sess.codemap().span_to_string(item.span));
1030 let def_id = local_def(item.id);
1031 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
1034 ast::ItemStatic(_, m, _) => {
1035 add_to_index(item, rbml_w, index);
1036 rbml_w.start_tag(tag_items_data_item);
1037 encode_def_id(rbml_w, def_id);
1038 if m == ast::MutMutable {
1039 encode_family(rbml_w, 'b');
1041 encode_family(rbml_w, 'c');
1043 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1044 encode_symbol(ecx, rbml_w, item.id);
1045 encode_name(rbml_w, item.ident.name);
1046 encode_path(rbml_w, path);
1047 encode_visibility(rbml_w, vis);
1048 encode_stability(rbml_w, stab);
1049 encode_attributes(rbml_w, item.attrs[]);
1052 ast::ItemConst(_, _) => {
1053 add_to_index(item, rbml_w, index);
1054 rbml_w.start_tag(tag_items_data_item);
1055 encode_def_id(rbml_w, def_id);
1056 encode_family(rbml_w, 'C');
1057 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1058 encode_name(rbml_w, item.ident.name);
1059 encode_path(rbml_w, path);
1060 encode_attributes(rbml_w, item.attrs.as_slice());
1061 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1062 encode_visibility(rbml_w, vis);
1063 encode_stability(rbml_w, stab);
1066 ast::ItemFn(ref decl, _, _, ref generics, _) => {
1067 add_to_index(item, rbml_w, index);
1068 rbml_w.start_tag(tag_items_data_item);
1069 encode_def_id(rbml_w, def_id);
1070 encode_family(rbml_w, FN_FAMILY);
1071 let tps_len = generics.ty_params.len();
1072 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1073 encode_name(rbml_w, item.ident.name);
1074 encode_path(rbml_w, path);
1075 encode_attributes(rbml_w, item.attrs[]);
1076 if tps_len > 0u || should_inline(item.attrs[]) {
1077 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1080 encode_symbol(ecx, rbml_w, item.id);
1082 encode_visibility(rbml_w, vis);
1083 encode_stability(rbml_w, stab);
1084 encode_method_argument_names(rbml_w, &**decl);
1087 ast::ItemMod(ref m) => {
1088 add_to_index(item, rbml_w, index);
1089 encode_info_for_mod(ecx,
1098 ast::ItemForeignMod(ref fm) => {
1099 add_to_index(item, rbml_w, index);
1100 rbml_w.start_tag(tag_items_data_item);
1101 encode_def_id(rbml_w, def_id);
1102 encode_family(rbml_w, 'n');
1103 encode_name(rbml_w, item.ident.name);
1104 encode_path(rbml_w, path);
1106 // Encode all the items in this module.
1107 for foreign_item in fm.items.iter() {
1108 rbml_w.start_tag(tag_mod_child);
1109 rbml_w.wr_str(def_to_string(local_def(foreign_item.id))[]);
1112 encode_visibility(rbml_w, vis);
1113 encode_stability(rbml_w, stab);
1116 ast::ItemTy(..) => {
1117 add_to_index(item, rbml_w, index);
1118 rbml_w.start_tag(tag_items_data_item);
1119 encode_def_id(rbml_w, def_id);
1120 encode_family(rbml_w, 'y');
1121 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1122 encode_name(rbml_w, item.ident.name);
1123 encode_path(rbml_w, path);
1124 encode_visibility(rbml_w, vis);
1125 encode_stability(rbml_w, stab);
1128 ast::ItemEnum(ref enum_definition, _) => {
1129 add_to_index(item, rbml_w, index);
1131 rbml_w.start_tag(tag_items_data_item);
1132 encode_def_id(rbml_w, def_id);
1133 encode_family(rbml_w, 't');
1134 encode_item_variances(rbml_w, ecx, item.id);
1135 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1136 encode_name(rbml_w, item.ident.name);
1137 encode_attributes(rbml_w, item.attrs[]);
1138 encode_repr_attrs(rbml_w, ecx, item.attrs[]);
1139 for v in (*enum_definition).variants.iter() {
1140 encode_variant_id(rbml_w, local_def(v.node.id));
1142 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1143 encode_path(rbml_w, path);
1145 // Encode inherent implementations for this enumeration.
1146 encode_inherent_implementations(ecx, rbml_w, def_id);
1148 encode_visibility(rbml_w, vis);
1149 encode_stability(rbml_w, stab);
1152 encode_enum_variant_info(ecx,
1155 (*enum_definition).variants[],
1158 ast::ItemStruct(ref struct_def, _) => {
1159 let fields = ty::lookup_struct_fields(tcx, def_id);
1161 /* First, encode the fields
1162 These come first because we need to write them to make
1163 the index, and the index needs to be in the item for the
1165 let idx = encode_info_for_struct(ecx,
1170 /* Index the class*/
1171 add_to_index(item, rbml_w, index);
1173 /* Now, make an item for the class itself */
1174 rbml_w.start_tag(tag_items_data_item);
1175 encode_def_id(rbml_w, def_id);
1176 encode_family(rbml_w, 'S');
1177 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1179 encode_item_variances(rbml_w, ecx, item.id);
1180 encode_name(rbml_w, item.ident.name);
1181 encode_attributes(rbml_w, item.attrs[]);
1182 encode_path(rbml_w, path.clone());
1183 encode_stability(rbml_w, stab);
1184 encode_visibility(rbml_w, vis);
1185 encode_repr_attrs(rbml_w, ecx, item.attrs[]);
1187 /* Encode def_ids for each field and method
1188 for methods, write all the stuff get_trait_method
1190 encode_struct_fields(rbml_w, fields[], def_id);
1192 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1194 // Encode inherent implementations for this structure.
1195 encode_inherent_implementations(ecx, rbml_w, def_id);
1197 /* Each class has its own index -- encode it */
1198 encode_index(rbml_w, idx, write_i64);
1201 // If this is a tuple-like struct, encode the type of the constructor.
1202 match struct_def.ctor_id {
1204 encode_info_for_struct_ctor(ecx, rbml_w, item.ident,
1205 ctor_id, index, def_id.node);
1210 ast::ItemImpl(unsafety, _, ref opt_trait, ref ty, ref ast_items) => {
1211 // We need to encode information about the default methods we
1212 // have inherited, so we drive this based on the impl structure.
1213 let impl_items = tcx.impl_items.borrow();
1214 let items = &(*impl_items)[def_id];
1216 add_to_index(item, rbml_w, index);
1217 rbml_w.start_tag(tag_items_data_item);
1218 encode_def_id(rbml_w, def_id);
1219 encode_family(rbml_w, 'i');
1220 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1221 encode_name(rbml_w, item.ident.name);
1222 encode_attributes(rbml_w, item.attrs[]);
1223 encode_unsafety(rbml_w, unsafety);
1225 ast::TyPath(ref path, _) if path.segments.len() == 1 => {
1226 let ident = path.segments.last().unwrap().identifier;
1227 encode_impl_type_basename(rbml_w, ident);
1231 for &item_def_id in items.iter() {
1232 rbml_w.start_tag(tag_item_impl_item);
1234 ty::MethodTraitItemId(item_def_id) => {
1235 encode_def_id(rbml_w, item_def_id);
1236 encode_item_sort(rbml_w, 'r');
1238 ty::TypeTraitItemId(item_def_id) => {
1239 encode_def_id(rbml_w, item_def_id);
1240 encode_item_sort(rbml_w, 't');
1245 for ast_trait_ref in opt_trait.iter() {
1246 let trait_ref = ty::node_id_to_trait_ref(
1247 tcx, ast_trait_ref.ref_id);
1248 encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
1250 encode_path(rbml_w, path.clone());
1251 encode_stability(rbml_w, stab);
1254 // Iterate down the trait items, emitting them. We rely on the
1255 // assumption that all of the actually implemented trait items
1256 // appear first in the impl structure, in the same order they do
1257 // in the ast. This is a little sketchy.
1258 let num_implemented_methods = ast_items.len();
1259 for (i, &trait_item_def_id) in items.iter().enumerate() {
1260 let ast_item = if i < num_implemented_methods {
1267 val: trait_item_def_id.def_id().node as i64,
1268 pos: rbml_w.writer.tell().unwrap(),
1271 let trait_item_type =
1272 ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
1273 match (trait_item_type, ast_item) {
1274 (ty::MethodTraitItem(ref method_type),
1275 Some(&ast::MethodImplItem(_))) => {
1276 encode_info_for_method(ecx,
1284 (ty::MethodTraitItem(ref method_type), _) => {
1285 encode_info_for_method(ecx,
1293 (ty::TypeTraitItem(ref associated_type),
1294 Some(&ast::TypeImplItem(ref typedef))) => {
1295 encode_info_for_associated_type(ecx,
1300 Some((*typedef).clone()))
1302 (ty::TypeTraitItem(ref associated_type), _) => {
1303 encode_info_for_associated_type(ecx,
1313 ast::ItemTrait(_, _, _, ref ms) => {
1314 add_to_index(item, rbml_w, index);
1315 rbml_w.start_tag(tag_items_data_item);
1316 encode_def_id(rbml_w, def_id);
1317 encode_family(rbml_w, 'I');
1318 encode_item_variances(rbml_w, ecx, item.id);
1319 let trait_def = ty::lookup_trait_def(tcx, def_id);
1320 encode_unsafety(rbml_w, trait_def.unsafety);
1321 encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice());
1322 encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
1323 encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1324 encode_name(rbml_w, item.ident.name);
1325 encode_attributes(rbml_w, item.attrs[]);
1326 encode_visibility(rbml_w, vis);
1327 encode_stability(rbml_w, stab);
1328 for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
1329 rbml_w.start_tag(tag_item_trait_item);
1330 match method_def_id {
1331 ty::MethodTraitItemId(method_def_id) => {
1332 encode_def_id(rbml_w, method_def_id);
1333 encode_item_sort(rbml_w, 'r');
1335 ty::TypeTraitItemId(type_def_id) => {
1336 encode_def_id(rbml_w, type_def_id);
1337 encode_item_sort(rbml_w, 't');
1342 rbml_w.start_tag(tag_mod_child);
1343 rbml_w.wr_str(def_to_string(method_def_id.def_id())[]);
1346 encode_path(rbml_w, path.clone());
1348 encode_bounds(rbml_w, ecx, &trait_def.bounds, tag_trait_def_bounds);
1350 // Encode the implementations of this trait.
1351 encode_extension_implementations(ecx, rbml_w, def_id);
1353 // Encode inherent implementations for this trait.
1354 encode_inherent_implementations(ecx, rbml_w, def_id);
1358 // Now output the trait item info for each trait item.
1359 let r = ty::trait_item_def_ids(tcx, def_id);
1360 for (i, &item_def_id) in r.iter().enumerate() {
1361 assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
1364 val: item_def_id.def_id().node as i64,
1365 pos: rbml_w.writer.tell().unwrap(),
1368 rbml_w.start_tag(tag_items_data_item);
1370 encode_parent_item(rbml_w, def_id);
1372 let stab = stability::lookup(tcx, item_def_id.def_id());
1373 encode_stability(rbml_w, stab);
1375 let trait_item_type =
1376 ty::impl_or_trait_item(tcx, item_def_id.def_id());
1377 let is_nonstatic_method;
1378 match trait_item_type {
1379 ty::MethodTraitItem(method_ty) => {
1380 let method_def_id = item_def_id.def_id();
1382 encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1384 let elem = ast_map::PathName(method_ty.name);
1386 path.clone().chain(Some(elem).into_iter()));
1388 match method_ty.explicit_self {
1389 ty::StaticExplicitSelfCategory => {
1390 encode_family(rbml_w,
1391 STATIC_METHOD_FAMILY);
1394 encode_family(rbml_w,
1398 let pty = ty::lookup_item_type(tcx,
1400 encode_bounds_and_type(rbml_w, ecx, &pty);
1402 is_nonstatic_method = method_ty.explicit_self !=
1403 ty::StaticExplicitSelfCategory;
1405 ty::TypeTraitItem(associated_type) => {
1406 encode_name(rbml_w, associated_type.name);
1407 encode_def_id(rbml_w, associated_type.def_id);
1409 let elem = ast_map::PathName(associated_type.name);
1411 path.clone().chain(Some(elem).into_iter()));
1413 encode_item_sort(rbml_w, 't');
1414 encode_family(rbml_w, 'y');
1416 is_nonstatic_method = false;
1420 encode_parent_sort(rbml_w, 't');
1422 let trait_item = &ms[i];
1423 let encode_trait_item = |&: rbml_w: &mut Encoder| {
1424 // If this is a static method, we've already
1426 if is_nonstatic_method {
1427 // FIXME: I feel like there is something funny
1429 let pty = ty::lookup_item_type(tcx, item_def_id.def_id());
1430 encode_bounds_and_type(rbml_w, ecx, &pty);
1434 &ast::RequiredMethod(ref m) => {
1435 encode_attributes(rbml_w, m.attrs[]);
1436 encode_trait_item(rbml_w);
1437 encode_item_sort(rbml_w, 'r');
1438 encode_method_argument_names(rbml_w, &*m.decl);
1441 &ast::ProvidedMethod(ref m) => {
1442 encode_attributes(rbml_w, m.attrs[]);
1443 encode_trait_item(rbml_w);
1444 encode_item_sort(rbml_w, 'p');
1445 encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
1446 encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
1449 &ast::TypeTraitItem(ref associated_type) => {
1450 encode_attributes(rbml_w,
1451 associated_type.attrs[]);
1452 encode_item_sort(rbml_w, 't');
1459 ast::ItemMac(..) => {
1460 // macros are encoded separately
1465 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1466 rbml_w: &mut Encoder,
1467 nitem: &ast::ForeignItem,
1468 index: &mut Vec<entry<i64>>,
1472 val: nitem.id as i64,
1473 pos: rbml_w.writer.tell().unwrap(),
1476 rbml_w.start_tag(tag_items_data_item);
1477 encode_def_id(rbml_w, local_def(nitem.id));
1478 encode_visibility(rbml_w, nitem.vis);
1480 ast::ForeignItemFn(..) => {
1481 encode_family(rbml_w, FN_FAMILY);
1482 encode_bounds_and_type(rbml_w, ecx,
1483 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1484 encode_name(rbml_w, nitem.ident.name);
1485 if abi == abi::RustIntrinsic {
1486 encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
1488 encode_attributes(rbml_w, &*nitem.attrs);
1489 let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
1490 encode_stability(rbml_w, stab);
1491 encode_symbol(ecx, rbml_w, nitem.id);
1493 ast::ForeignItemStatic(_, mutbl) => {
1495 encode_family(rbml_w, 'b');
1497 encode_family(rbml_w, 'c');
1499 encode_bounds_and_type(rbml_w, ecx,
1500 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1501 encode_attributes(rbml_w, &*nitem.attrs);
1502 let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
1503 encode_stability(rbml_w, stab);
1504 encode_symbol(ecx, rbml_w, nitem.id);
1505 encode_name(rbml_w, nitem.ident.name);
1508 encode_path(rbml_w, path);
1512 fn my_visit_expr(_e: &ast::Expr) { }
1514 fn my_visit_item(i: &ast::Item,
1515 rbml_w: &mut Encoder,
1516 ecx: &EncodeContext,
1517 index: &mut Vec<entry<i64>>) {
1518 ecx.tcx.map.with_path(i.id, |path| {
1519 encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1523 fn my_visit_foreign_item(ni: &ast::ForeignItem,
1524 rbml_w: &mut Encoder,
1525 ecx: &EncodeContext,
1526 index: &mut Vec<entry<i64>>) {
1527 debug!("writing foreign item {}::{}",
1528 ecx.tcx.map.path_to_string(ni.id),
1529 token::get_ident(ni.ident));
1531 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1532 ecx.tcx.map.with_path(ni.id, |path| {
1533 encode_info_for_foreign_item(ecx, rbml_w,
1539 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1540 rbml_w_for_visit_item: &'a mut Encoder<'b>,
1541 ecx: &'a EncodeContext<'c,'tcx>,
1542 index: &'a mut Vec<entry<i64>>,
1545 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1546 fn visit_expr(&mut self, ex: &ast::Expr) {
1547 visit::walk_expr(self, ex);
1550 fn visit_item(&mut self, i: &ast::Item) {
1551 visit::walk_item(self, i);
1553 self.rbml_w_for_visit_item,
1557 fn visit_foreign_item(&mut self, ni: &ast::ForeignItem) {
1558 visit::walk_foreign_item(self, ni);
1559 my_visit_foreign_item(ni,
1560 self.rbml_w_for_visit_item,
1566 fn encode_info_for_items(ecx: &EncodeContext,
1567 rbml_w: &mut Encoder,
1569 -> Vec<entry<i64>> {
1570 let mut index = Vec::new();
1571 rbml_w.start_tag(tag_items_data);
1573 val: ast::CRATE_NODE_ID as i64,
1574 pos: rbml_w.writer.tell().unwrap(),
1576 encode_info_for_mod(ecx,
1581 ast_map::Values([].iter()).chain(None),
1582 syntax::parse::token::special_idents::invalid,
1585 visit::walk_crate(&mut EncodeVisitor {
1588 rbml_w_for_visit_item: &mut *rbml_w,
1596 // Path and definition ID indexing
1598 fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
1599 F: FnMut(&mut SeekableMemWriter, &T),
1602 let mut buckets: Vec<Vec<entry<T>>> = range(0, 256u16).map(|_| Vec::new()).collect();
1603 for elt in index.into_iter() {
1604 let h = hash::hash(&elt.val) as uint;
1605 buckets[h % 256].push(elt);
1608 rbml_w.start_tag(tag_index);
1609 let mut bucket_locs = Vec::new();
1610 rbml_w.start_tag(tag_index_buckets);
1611 for bucket in buckets.iter() {
1612 bucket_locs.push(rbml_w.writer.tell().unwrap());
1613 rbml_w.start_tag(tag_index_buckets_bucket);
1614 for elt in bucket.iter() {
1615 rbml_w.start_tag(tag_index_buckets_bucket_elt);
1616 assert!(elt.pos < 0xffff_ffff);
1618 let wr: &mut SeekableMemWriter = rbml_w.writer;
1619 wr.write_be_u32(elt.pos as u32);
1621 write_fn(rbml_w.writer, &elt.val);
1627 rbml_w.start_tag(tag_index_table);
1628 for pos in bucket_locs.iter() {
1629 assert!(*pos < 0xffff_ffff);
1630 let wr: &mut SeekableMemWriter = rbml_w.writer;
1631 wr.write_be_u32(*pos as u32);
1637 fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1638 let wr: &mut SeekableMemWriter = writer;
1639 assert!(n < 0x7fff_ffff);
1640 wr.write_be_u32(n as u32);
1643 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1645 ast::MetaWord(ref name) => {
1646 rbml_w.start_tag(tag_meta_item_word);
1647 rbml_w.start_tag(tag_meta_item_name);
1648 rbml_w.writer.write(name.get().as_bytes());
1652 ast::MetaNameValue(ref name, ref value) => {
1654 ast::LitStr(ref value, _) => {
1655 rbml_w.start_tag(tag_meta_item_name_value);
1656 rbml_w.start_tag(tag_meta_item_name);
1657 rbml_w.writer.write(name.get().as_bytes());
1659 rbml_w.start_tag(tag_meta_item_value);
1660 rbml_w.writer.write(value.get().as_bytes());
1664 _ => {/* FIXME (#623): encode other variants */ }
1667 ast::MetaList(ref name, ref items) => {
1668 rbml_w.start_tag(tag_meta_item_list);
1669 rbml_w.start_tag(tag_meta_item_name);
1670 rbml_w.writer.write(name.get().as_bytes());
1672 for inner_item in items.iter() {
1673 encode_meta_item(rbml_w, &**inner_item);
1680 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1681 rbml_w.start_tag(tag_attributes);
1682 for attr in attrs.iter() {
1683 rbml_w.start_tag(tag_attribute);
1684 rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1685 encode_meta_item(rbml_w, &*attr.node.value);
1691 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
1692 let byte: u8 = match unsafety {
1693 ast::Unsafety::Normal => 0,
1694 ast::Unsafety::Unsafe => 1,
1696 rbml_w.wr_tagged_u8(tag_unsafety, byte);
1699 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
1700 rbml_w.start_tag(tag_associated_type_names);
1701 for &name in names.iter() {
1702 rbml_w.wr_tagged_str(tag_associated_type_name, token::get_name(name).get());
1707 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1708 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1709 // Pull the cnums and name,vers,hash out of cstore
1710 let mut deps = Vec::new();
1711 cstore.iter_crate_data(|key, val| {
1712 let dep = decoder::CrateDep {
1714 name: decoder::get_crate_name(val.data()),
1715 hash: decoder::get_crate_hash(val.data()),
1721 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1723 // Sanity-check the crate numbers
1724 let mut expected_cnum = 1;
1725 for n in deps.iter() {
1726 assert_eq!(n.cnum, expected_cnum);
1733 // We're just going to write a list of crate 'name-hash-version's, with
1734 // the assumption that they are numbered 1 to n.
1735 // FIXME (#2166): This is not nearly enough to support correct versioning
1736 // but is enough to get transitive crate dependencies working.
1737 rbml_w.start_tag(tag_crate_deps);
1738 let r = get_ordered_deps(cstore);
1739 for dep in r.iter() {
1740 encode_crate_dep(rbml_w, (*dep).clone());
1745 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1746 rbml_w.start_tag(tag_lang_items);
1748 for (i, def_id) in ecx.tcx.lang_items.items() {
1749 for id in def_id.iter() {
1750 if id.krate == ast::LOCAL_CRATE {
1751 rbml_w.start_tag(tag_lang_items_item);
1753 rbml_w.start_tag(tag_lang_items_item_id);
1755 let wr: &mut SeekableMemWriter = rbml_w.writer;
1756 wr.write_be_u32(i as u32);
1758 rbml_w.end_tag(); // tag_lang_items_item_id
1760 rbml_w.start_tag(tag_lang_items_item_node_id);
1762 let wr: &mut SeekableMemWriter = rbml_w.writer;
1763 wr.write_be_u32(id.node as u32);
1765 rbml_w.end_tag(); // tag_lang_items_item_node_id
1767 rbml_w.end_tag(); // tag_lang_items_item
1772 for i in ecx.tcx.lang_items.missing.iter() {
1773 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1776 rbml_w.end_tag(); // tag_lang_items
1779 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1780 rbml_w.start_tag(tag_native_libraries);
1782 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1785 cstore::NativeStatic => {} // these libraries are not propagated
1786 cstore::NativeFramework | cstore::NativeUnknown => {
1787 rbml_w.start_tag(tag_native_libraries_lib);
1789 rbml_w.start_tag(tag_native_libraries_kind);
1790 rbml_w.writer.write_be_u32(kind as u32);
1793 rbml_w.start_tag(tag_native_libraries_name);
1794 rbml_w.writer.write(lib.as_bytes());
1805 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1806 match ecx.tcx.sess.plugin_registrar_fn.get() {
1807 Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1812 /// Given a span, write the text of that span into the output stream
1813 /// as an exported macro
1814 fn encode_macro_def(ecx: &EncodeContext,
1815 rbml_w: &mut Encoder,
1816 span: &syntax::codemap::Span) {
1817 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1818 .expect("Unable to find source for macro");
1819 rbml_w.start_tag(tag_macro_def);
1820 rbml_w.wr_str(def[]);
1824 /// Serialize the text of the exported macros
1825 fn encode_macro_defs(ecx: &EncodeContext,
1827 rbml_w: &mut Encoder) {
1828 rbml_w.start_tag(tag_exported_macros);
1829 for item in krate.exported_macros.iter() {
1830 encode_macro_def(ecx, rbml_w, &item.span);
1835 fn encode_unboxed_closures<'a>(
1836 ecx: &'a EncodeContext,
1837 rbml_w: &'a mut Encoder) {
1838 rbml_w.start_tag(tag_unboxed_closures);
1839 for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1843 if unboxed_closure_id.krate != ast::LOCAL_CRATE {
1847 rbml_w.start_tag(tag_unboxed_closure);
1848 encode_def_id(rbml_w, *unboxed_closure_id);
1849 rbml_w.start_tag(tag_unboxed_closure_type);
1850 write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
1852 encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
1858 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
1859 struct StructFieldVisitor<'a, 'b:'a> {
1860 rbml_w: &'a mut Encoder<'b>,
1863 impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1864 fn visit_struct_field(&mut self, field: &ast::StructField) {
1865 self.rbml_w.start_tag(tag_struct_field);
1866 self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1867 encode_attributes(self.rbml_w, field.node.attrs[]);
1868 self.rbml_w.end_tag();
1872 rbml_w.start_tag(tag_struct_fields);
1873 visit::walk_crate(&mut StructFieldVisitor {
1881 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1882 ecx: &'a EncodeContext<'b, 'tcx>,
1883 rbml_w: &'a mut Encoder<'c>,
1886 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1887 fn visit_item(&mut self, item: &ast::Item) {
1888 if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node {
1889 let def_map = &self.ecx.tcx.def_map;
1890 let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
1891 let def_id = trait_def.def_id();
1893 // Load eagerly if this is an implementation of the Drop trait
1894 // or if the trait is not defined in this crate.
1895 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1896 def_id.krate != ast::LOCAL_CRATE {
1897 self.rbml_w.start_tag(tag_impls_impl);
1898 encode_def_id(self.rbml_w, local_def(item.id));
1899 self.rbml_w.end_tag();
1902 visit::walk_item(self, item);
1906 /// Encodes implementations that are eagerly loaded.
1908 /// None of this is necessary in theory; we can load all implementations
1909 /// lazily. However, in two cases the optimizations to lazily load
1910 /// implementations are not yet implemented. These two cases, which require us
1911 /// to load implementations eagerly, are:
1913 /// * Destructors (implementations of the Drop trait).
1915 /// * Implementations of traits not defined in this crate.
1916 fn encode_impls<'a>(ecx: &'a EncodeContext,
1918 rbml_w: &'a mut Encoder) {
1919 rbml_w.start_tag(tag_impls);
1922 let mut visitor = ImplVisitor {
1926 visit::walk_crate(&mut visitor, krate);
1932 fn encode_misc_info(ecx: &EncodeContext,
1934 rbml_w: &mut Encoder) {
1935 rbml_w.start_tag(tag_misc_info);
1936 rbml_w.start_tag(tag_misc_info_crate_items);
1937 for item in krate.module.items.iter() {
1938 rbml_w.start_tag(tag_mod_child);
1939 rbml_w.wr_str(def_to_string(local_def(item.id))[]);
1942 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1943 rbml_w.start_tag(tag_mod_child);
1944 rbml_w.wr_str(def_to_string(local_def(
1945 auxiliary_node_id))[]);
1951 // Encode reexports for the root module.
1952 encode_reexports(ecx, rbml_w, 0, ast_map::Values([].iter()).chain(None));
1958 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1959 rbml_w.start_tag(tag_reachable_extern_fns);
1961 for id in ecx.reachable.iter() {
1962 if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1963 if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1964 if abi != abi::Rust && !generics.is_type_parameterized() {
1965 rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1974 fn encode_crate_dep(rbml_w: &mut Encoder,
1975 dep: decoder::CrateDep) {
1976 rbml_w.start_tag(tag_crate_dep);
1977 rbml_w.start_tag(tag_crate_dep_crate_name);
1978 rbml_w.writer.write(dep.name.as_bytes());
1980 rbml_w.start_tag(tag_crate_dep_hash);
1981 rbml_w.writer.write(dep.hash.as_str().as_bytes());
1986 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1987 rbml_w.start_tag(tag_crate_hash);
1988 rbml_w.writer.write(hash.as_str().as_bytes());
1992 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1993 rbml_w.start_tag(tag_crate_crate_name);
1994 rbml_w.writer.write(crate_name.as_bytes());
1998 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1999 rbml_w.start_tag(tag_crate_triple);
2000 rbml_w.writer.write(triple.as_bytes());
2004 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
2005 rbml_w.start_tag(tag_dylib_dependency_formats);
2006 match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
2008 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
2009 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
2010 cstore::RequireDynamic => "d",
2011 cstore::RequireStatic => "s",
2013 }).collect::<Vec<String>>();
2014 rbml_w.writer.write(s.connect(",").as_bytes());
2021 // NB: Increment this as you change the metadata encoding version.
2022 #[allow(non_upper_case_globals)]
2023 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
2025 pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
2026 let mut wr = SeekableMemWriter::new();
2027 encode_metadata_inner(&mut wr, parms, krate);
2028 let mut v = wr.unwrap();
2030 // And here we run into yet another obscure archive bug: in which metadata
2031 // loaded from archives may have trailing garbage bytes. Awhile back one of
2032 // our tests was failing sporadially on the OSX 64-bit builders (both nopt
2033 // and opt) by having rbml generate an out-of-bounds panic when looking at
2036 // Upon investigation it turned out that the metadata file inside of an rlib
2037 // (and ar archive) was being corrupted. Some compilations would generate a
2038 // metadata file which would end in a few extra bytes, while other
2039 // compilations would not have these extra bytes appended to the end. These
2040 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2041 // being interpreted causing the out-of-bounds.
2043 // The root cause of why these extra bytes were appearing was never
2044 // discovered, and in the meantime the solution we're employing is to insert
2045 // the length of the metadata to the start of the metadata. Later on this
2046 // will allow us to slice the metadata to the precise length that we just
2047 // generated regardless of trailing bytes that end up in it.
2048 let len = v.len() as u32;
2049 v.insert(0, (len >> 0) as u8);
2050 v.insert(0, (len >> 8) as u8);
2051 v.insert(0, (len >> 16) as u8);
2052 v.insert(0, (len >> 24) as u8);
2056 fn encode_metadata_inner(wr: &mut SeekableMemWriter,
2057 parms: EncodeParams,
2058 krate: &ast::Crate) {
2062 lang_item_bytes: u64,
2063 native_lib_bytes: u64,
2064 plugin_registrar_fn_bytes: u64,
2065 macro_defs_bytes: u64,
2066 unboxed_closure_bytes: u64,
2074 let mut stats = Stats {
2078 native_lib_bytes: 0,
2079 plugin_registrar_fn_bytes: 0,
2080 macro_defs_bytes: 0,
2081 unboxed_closure_bytes: 0,
2095 encode_inlined_item,
2100 let ecx = EncodeContext {
2103 reexports: reexports,
2104 item_symbols: item_symbols,
2105 link_meta: link_meta,
2107 encode_inlined_item: RefCell::new(encode_inlined_item),
2108 type_abbrevs: RefCell::new(FnvHashMap::new()),
2109 reachable: reachable,
2112 let mut rbml_w = writer::Encoder::new(wr);
2114 encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name[]);
2115 encode_crate_triple(&mut rbml_w,
2120 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2121 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2123 let mut i = rbml_w.writer.tell().unwrap();
2124 encode_attributes(&mut rbml_w, krate.attrs[]);
2125 stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
2127 i = rbml_w.writer.tell().unwrap();
2128 encode_crate_deps(&mut rbml_w, ecx.cstore);
2129 stats.dep_bytes = rbml_w.writer.tell().unwrap() - i;
2131 // Encode the language items.
2132 i = rbml_w.writer.tell().unwrap();
2133 encode_lang_items(&ecx, &mut rbml_w);
2134 stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i;
2136 // Encode the native libraries used
2137 i = rbml_w.writer.tell().unwrap();
2138 encode_native_libraries(&ecx, &mut rbml_w);
2139 stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i;
2141 // Encode the plugin registrar function
2142 i = rbml_w.writer.tell().unwrap();
2143 encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2144 stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
2146 // Encode macro definitions
2147 i = rbml_w.writer.tell().unwrap();
2148 encode_macro_defs(&ecx, krate, &mut rbml_w);
2149 stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
2151 // Encode the types of all unboxed closures in this crate.
2152 i = rbml_w.writer.tell().unwrap();
2153 encode_unboxed_closures(&ecx, &mut rbml_w);
2154 stats.unboxed_closure_bytes = rbml_w.writer.tell().unwrap() - i;
2156 // Encode the def IDs of impls, for coherence checking.
2157 i = rbml_w.writer.tell().unwrap();
2158 encode_impls(&ecx, krate, &mut rbml_w);
2159 stats.impl_bytes = rbml_w.writer.tell().unwrap() - i;
2161 // Encode miscellaneous info.
2162 i = rbml_w.writer.tell().unwrap();
2163 encode_misc_info(&ecx, krate, &mut rbml_w);
2164 encode_reachable_extern_fns(&ecx, &mut rbml_w);
2165 stats.misc_bytes = rbml_w.writer.tell().unwrap() - i;
2167 // Encode and index the items.
2168 rbml_w.start_tag(tag_items);
2169 i = rbml_w.writer.tell().unwrap();
2170 let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2171 stats.item_bytes = rbml_w.writer.tell().unwrap() - i;
2173 i = rbml_w.writer.tell().unwrap();
2174 encode_index(&mut rbml_w, items_index, write_i64);
2175 stats.index_bytes = rbml_w.writer.tell().unwrap() - i;
2178 encode_struct_field_attrs(&mut rbml_w, krate);
2180 stats.total_bytes = rbml_w.writer.tell().unwrap();
2182 if tcx.sess.meta_stats() {
2183 for e in rbml_w.writer.get_ref().iter() {
2185 stats.zero_bytes += 1;
2189 println!("metadata stats:");
2190 println!(" attribute bytes: {}", stats.attr_bytes);
2191 println!(" dep bytes: {}", stats.dep_bytes);
2192 println!(" lang item bytes: {}", stats.lang_item_bytes);
2193 println!(" native bytes: {}", stats.native_lib_bytes);
2194 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2195 println!(" macro def bytes: {}", stats.macro_defs_bytes);
2196 println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
2197 println!(" impl bytes: {}", stats.impl_bytes);
2198 println!(" misc bytes: {}", stats.misc_bytes);
2199 println!(" item bytes: {}", stats.item_bytes);
2200 println!(" index bytes: {}", stats.index_bytes);
2201 println!(" zero bytes: {}", stats.zero_bytes);
2202 println!(" total bytes: {}", stats.total_bytes);
2206 // Get the encoded string for a type
2207 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2208 let mut wr = SeekableMemWriter::new();
2209 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
2210 diag: tcx.sess.diagnostic(),
2213 abbrevs: &RefCell::new(FnvHashMap::new())
2215 String::from_utf8(wr.unwrap()).unwrap()