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;
45 use syntax::print::pprust;
47 use syntax::visit::Visitor;
51 use rbml::io::SeekableMemWriter;
53 /// A borrowed version of `ast::InlinedItem`.
54 pub enum InlinedItemRef<'a> {
55 IIItemRef(&'a ast::Item),
56 IITraitItemRef(DefId, &'a ast::TraitItem),
57 IIImplItemRef(DefId, &'a ast::ImplItem),
58 IIForeignRef(&'a ast::ForeignItem)
61 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
63 pub type EncodeInlinedItem<'a> =
64 Box<FnMut(&EncodeContext, &mut Encoder, 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).index(&FullRange));
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);
157 rbml_w.wr_str(s.index(&FullRange));
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).index(&FullRange));
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.index(&FullRange));
336 encode_repr_attrs(rbml_w, ecx, variant.node.attrs.index(&FullRange));
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,
347 fields.index(&FullRange),
349 encode_struct_fields(rbml_w, fields.index(&FullRange), 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).index(&FullRange));
391 rbml_w.start_tag(tag_items_data_item_reexport_name);
392 rbml_w.wr_str(format!("{}::{}",
394 token::get_name(method_name)).index(&FullRange));
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).index(&FullRange));
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)).index(&FullRange));
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)).index(&FullRange));
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)).index(&FullRange));
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().index(&FullRange));
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().index(&FullRange));
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).index(&FullRange));
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.index(&FullRange));
868 let any_types = !pty.generics.types.is_empty();
869 if any_types || is_default_impl || should_inline(ast_method.attrs.index(&FullRange)) {
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.index(&FullRange));
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;
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.index(&FullRange));
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.index(&FullRange));
1076 if tps_len > 0u || should_inline(item.attrs.index(&FullRange)) {
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,
1092 item.attrs.index(&FullRange),
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)).index(&FullRange));
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.index(&FullRange));
1138 encode_repr_attrs(rbml_w, ecx, item.attrs.index(&FullRange));
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.index(&FullRange),
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,
1167 fields.index(&FullRange),
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.index(&FullRange));
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.index(&FullRange));
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.index(&FullRange), 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, polarity, _, 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.index(&FullRange));
1223 encode_unsafety(rbml_w, unsafety);
1224 encode_polarity(rbml_w, polarity);
1226 ast::TyPath(ref path, _) if path.segments.len() == 1 => {
1227 let ident = path.segments.last().unwrap().identifier;
1228 encode_impl_type_basename(rbml_w, ident);
1232 for &item_def_id in items.iter() {
1233 rbml_w.start_tag(tag_item_impl_item);
1235 ty::MethodTraitItemId(item_def_id) => {
1236 encode_def_id(rbml_w, item_def_id);
1237 encode_item_sort(rbml_w, 'r');
1239 ty::TypeTraitItemId(item_def_id) => {
1240 encode_def_id(rbml_w, item_def_id);
1241 encode_item_sort(rbml_w, 't');
1246 for ast_trait_ref in opt_trait.iter() {
1247 let trait_ref = ty::node_id_to_trait_ref(
1248 tcx, ast_trait_ref.ref_id);
1249 encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
1251 encode_path(rbml_w, path.clone());
1252 encode_stability(rbml_w, stab);
1255 // Iterate down the trait items, emitting them. We rely on the
1256 // assumption that all of the actually implemented trait items
1257 // appear first in the impl structure, in the same order they do
1258 // in the ast. This is a little sketchy.
1259 let num_implemented_methods = ast_items.len();
1260 for (i, &trait_item_def_id) in items.iter().enumerate() {
1261 let ast_item = if i < num_implemented_methods {
1268 val: trait_item_def_id.def_id().node as i64,
1269 pos: rbml_w.writer.tell().unwrap(),
1272 let trait_item_type =
1273 ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
1274 match (trait_item_type, ast_item) {
1275 (ty::MethodTraitItem(ref method_type),
1276 Some(&ast::MethodImplItem(_))) => {
1277 encode_info_for_method(ecx,
1285 (ty::MethodTraitItem(ref method_type), _) => {
1286 encode_info_for_method(ecx,
1294 (ty::TypeTraitItem(ref associated_type),
1295 Some(&ast::TypeImplItem(ref typedef))) => {
1296 encode_info_for_associated_type(ecx,
1301 Some((*typedef).clone()))
1303 (ty::TypeTraitItem(ref associated_type), _) => {
1304 encode_info_for_associated_type(ecx,
1314 ast::ItemTrait(_, _, _, ref ms) => {
1315 add_to_index(item, rbml_w, index);
1316 rbml_w.start_tag(tag_items_data_item);
1317 encode_def_id(rbml_w, def_id);
1318 encode_family(rbml_w, 'I');
1319 encode_item_variances(rbml_w, ecx, item.id);
1320 let trait_def = ty::lookup_trait_def(tcx, def_id);
1321 encode_unsafety(rbml_w, trait_def.unsafety);
1322 encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice());
1323 encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
1324 encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1325 encode_name(rbml_w, item.ident.name);
1326 encode_attributes(rbml_w, item.attrs.index(&FullRange));
1327 encode_visibility(rbml_w, vis);
1328 encode_stability(rbml_w, stab);
1329 for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
1330 rbml_w.start_tag(tag_item_trait_item);
1331 match method_def_id {
1332 ty::MethodTraitItemId(method_def_id) => {
1333 encode_def_id(rbml_w, method_def_id);
1334 encode_item_sort(rbml_w, 'r');
1336 ty::TypeTraitItemId(type_def_id) => {
1337 encode_def_id(rbml_w, type_def_id);
1338 encode_item_sort(rbml_w, 't');
1343 rbml_w.start_tag(tag_mod_child);
1344 rbml_w.wr_str(def_to_string(method_def_id.def_id()).index(&FullRange));
1347 encode_path(rbml_w, path.clone());
1349 encode_bounds(rbml_w, ecx, &trait_def.bounds, tag_trait_def_bounds);
1351 // Encode the implementations of this trait.
1352 encode_extension_implementations(ecx, rbml_w, def_id);
1354 // Encode inherent implementations for this trait.
1355 encode_inherent_implementations(ecx, rbml_w, def_id);
1359 // Now output the trait item info for each trait item.
1360 let r = ty::trait_item_def_ids(tcx, def_id);
1361 for (i, &item_def_id) in r.iter().enumerate() {
1362 assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
1365 val: item_def_id.def_id().node as i64,
1366 pos: rbml_w.writer.tell().unwrap(),
1369 rbml_w.start_tag(tag_items_data_item);
1371 encode_parent_item(rbml_w, def_id);
1373 let stab = stability::lookup(tcx, item_def_id.def_id());
1374 encode_stability(rbml_w, stab);
1376 let trait_item_type =
1377 ty::impl_or_trait_item(tcx, item_def_id.def_id());
1378 let is_nonstatic_method;
1379 match trait_item_type {
1380 ty::MethodTraitItem(method_ty) => {
1381 let method_def_id = item_def_id.def_id();
1383 encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1385 let elem = ast_map::PathName(method_ty.name);
1387 path.clone().chain(Some(elem).into_iter()));
1389 match method_ty.explicit_self {
1390 ty::StaticExplicitSelfCategory => {
1391 encode_family(rbml_w,
1392 STATIC_METHOD_FAMILY);
1395 encode_family(rbml_w,
1399 let pty = ty::lookup_item_type(tcx,
1401 encode_bounds_and_type(rbml_w, ecx, &pty);
1403 is_nonstatic_method = method_ty.explicit_self !=
1404 ty::StaticExplicitSelfCategory;
1406 ty::TypeTraitItem(associated_type) => {
1407 encode_name(rbml_w, associated_type.name);
1408 encode_def_id(rbml_w, associated_type.def_id);
1410 let elem = ast_map::PathName(associated_type.name);
1412 path.clone().chain(Some(elem).into_iter()));
1414 encode_item_sort(rbml_w, 't');
1415 encode_family(rbml_w, 'y');
1417 is_nonstatic_method = false;
1421 encode_parent_sort(rbml_w, 't');
1423 let trait_item = &ms[i];
1424 let encode_trait_item = |&: rbml_w: &mut Encoder| {
1425 // If this is a static method, we've already
1427 if is_nonstatic_method {
1428 // FIXME: I feel like there is something funny
1430 let pty = ty::lookup_item_type(tcx, item_def_id.def_id());
1431 encode_bounds_and_type(rbml_w, ecx, &pty);
1435 &ast::RequiredMethod(ref m) => {
1436 encode_attributes(rbml_w, m.attrs.index(&FullRange));
1437 encode_trait_item(rbml_w);
1438 encode_item_sort(rbml_w, 'r');
1439 encode_method_argument_names(rbml_w, &*m.decl);
1442 &ast::ProvidedMethod(ref m) => {
1443 encode_attributes(rbml_w, m.attrs.index(&FullRange));
1444 encode_trait_item(rbml_w);
1445 encode_item_sort(rbml_w, 'p');
1446 encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
1447 encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
1450 &ast::TypeTraitItem(ref associated_type) => {
1451 encode_attributes(rbml_w,
1452 associated_type.attrs.index(&FullRange));
1453 encode_item_sort(rbml_w, 't');
1460 ast::ItemMac(..) => {
1461 // macros are encoded separately
1466 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1467 rbml_w: &mut Encoder,
1468 nitem: &ast::ForeignItem,
1469 index: &mut Vec<entry<i64>>,
1473 val: nitem.id as i64,
1474 pos: rbml_w.writer.tell().unwrap(),
1477 rbml_w.start_tag(tag_items_data_item);
1478 encode_def_id(rbml_w, local_def(nitem.id));
1479 encode_visibility(rbml_w, nitem.vis);
1481 ast::ForeignItemFn(..) => {
1482 encode_family(rbml_w, FN_FAMILY);
1483 encode_bounds_and_type(rbml_w, ecx,
1484 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1485 encode_name(rbml_w, nitem.ident.name);
1486 if abi == abi::RustIntrinsic {
1487 encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
1489 encode_attributes(rbml_w, &*nitem.attrs);
1490 let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
1491 encode_stability(rbml_w, stab);
1492 encode_symbol(ecx, rbml_w, nitem.id);
1494 ast::ForeignItemStatic(_, mutbl) => {
1496 encode_family(rbml_w, 'b');
1498 encode_family(rbml_w, 'c');
1500 encode_bounds_and_type(rbml_w, ecx,
1501 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1502 encode_attributes(rbml_w, &*nitem.attrs);
1503 let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
1504 encode_stability(rbml_w, stab);
1505 encode_symbol(ecx, rbml_w, nitem.id);
1506 encode_name(rbml_w, nitem.ident.name);
1509 encode_path(rbml_w, path);
1513 fn my_visit_expr(_e: &ast::Expr) { }
1515 fn my_visit_item(i: &ast::Item,
1516 rbml_w: &mut Encoder,
1517 ecx: &EncodeContext,
1518 index: &mut Vec<entry<i64>>) {
1519 ecx.tcx.map.with_path(i.id, |path| {
1520 encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1524 fn my_visit_foreign_item(ni: &ast::ForeignItem,
1525 rbml_w: &mut Encoder,
1526 ecx: &EncodeContext,
1527 index: &mut Vec<entry<i64>>) {
1528 debug!("writing foreign item {}::{}",
1529 ecx.tcx.map.path_to_string(ni.id),
1530 token::get_ident(ni.ident));
1532 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1533 ecx.tcx.map.with_path(ni.id, |path| {
1534 encode_info_for_foreign_item(ecx, rbml_w,
1540 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1541 rbml_w_for_visit_item: &'a mut Encoder<'b>,
1542 ecx: &'a EncodeContext<'c,'tcx>,
1543 index: &'a mut Vec<entry<i64>>,
1546 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1547 fn visit_expr(&mut self, ex: &ast::Expr) {
1548 visit::walk_expr(self, ex);
1551 fn visit_item(&mut self, i: &ast::Item) {
1552 visit::walk_item(self, i);
1554 self.rbml_w_for_visit_item,
1558 fn visit_foreign_item(&mut self, ni: &ast::ForeignItem) {
1559 visit::walk_foreign_item(self, ni);
1560 my_visit_foreign_item(ni,
1561 self.rbml_w_for_visit_item,
1567 fn encode_info_for_items(ecx: &EncodeContext,
1568 rbml_w: &mut Encoder,
1570 -> Vec<entry<i64>> {
1571 let mut index = Vec::new();
1572 rbml_w.start_tag(tag_items_data);
1574 val: ast::CRATE_NODE_ID as i64,
1575 pos: rbml_w.writer.tell().unwrap(),
1577 encode_info_for_mod(ecx,
1582 ast_map::Values([].iter()).chain(None),
1583 syntax::parse::token::special_idents::invalid,
1586 visit::walk_crate(&mut EncodeVisitor {
1589 rbml_w_for_visit_item: &mut *rbml_w,
1597 // Path and definition ID indexing
1599 fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
1600 F: FnMut(&mut SeekableMemWriter, &T),
1603 let mut buckets: Vec<Vec<entry<T>>> = range(0, 256u16).map(|_| Vec::new()).collect();
1604 for elt in index.into_iter() {
1605 let h = hash::hash(&elt.val) as uint;
1606 (&mut buckets[h % 256]).push(elt);
1609 rbml_w.start_tag(tag_index);
1610 let mut bucket_locs = Vec::new();
1611 rbml_w.start_tag(tag_index_buckets);
1612 for bucket in buckets.iter() {
1613 bucket_locs.push(rbml_w.writer.tell().unwrap());
1614 rbml_w.start_tag(tag_index_buckets_bucket);
1615 for elt in bucket.iter() {
1616 rbml_w.start_tag(tag_index_buckets_bucket_elt);
1617 assert!(elt.pos < 0xffff_ffff);
1619 let wr: &mut SeekableMemWriter = rbml_w.writer;
1620 wr.write_be_u32(elt.pos as u32);
1622 write_fn(rbml_w.writer, &elt.val);
1628 rbml_w.start_tag(tag_index_table);
1629 for pos in bucket_locs.iter() {
1630 assert!(*pos < 0xffff_ffff);
1631 let wr: &mut SeekableMemWriter = rbml_w.writer;
1632 wr.write_be_u32(*pos as u32);
1638 fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1639 let wr: &mut SeekableMemWriter = writer;
1640 assert!(n < 0x7fff_ffff);
1641 wr.write_be_u32(n as u32);
1644 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1646 ast::MetaWord(ref name) => {
1647 rbml_w.start_tag(tag_meta_item_word);
1648 rbml_w.start_tag(tag_meta_item_name);
1649 rbml_w.writer.write(name.get().as_bytes());
1653 ast::MetaNameValue(ref name, ref value) => {
1655 ast::LitStr(ref value, _) => {
1656 rbml_w.start_tag(tag_meta_item_name_value);
1657 rbml_w.start_tag(tag_meta_item_name);
1658 rbml_w.writer.write(name.get().as_bytes());
1660 rbml_w.start_tag(tag_meta_item_value);
1661 rbml_w.writer.write(value.get().as_bytes());
1665 _ => {/* FIXME (#623): encode other variants */ }
1668 ast::MetaList(ref name, ref items) => {
1669 rbml_w.start_tag(tag_meta_item_list);
1670 rbml_w.start_tag(tag_meta_item_name);
1671 rbml_w.writer.write(name.get().as_bytes());
1673 for inner_item in items.iter() {
1674 encode_meta_item(rbml_w, &**inner_item);
1681 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1682 rbml_w.start_tag(tag_attributes);
1683 for attr in attrs.iter() {
1684 rbml_w.start_tag(tag_attribute);
1685 rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1686 encode_meta_item(rbml_w, &*attr.node.value);
1692 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
1693 let byte: u8 = match unsafety {
1694 ast::Unsafety::Normal => 0,
1695 ast::Unsafety::Unsafe => 1,
1697 rbml_w.wr_tagged_u8(tag_unsafety, byte);
1700 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
1701 rbml_w.start_tag(tag_associated_type_names);
1702 for &name in names.iter() {
1703 rbml_w.wr_tagged_str(tag_associated_type_name, token::get_name(name).get());
1708 fn encode_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
1709 let byte: u8 = match polarity {
1710 ast::ImplPolarity::Positive => 0,
1711 ast::ImplPolarity::Negative => 1,
1713 rbml_w.wr_tagged_u8(tag_polarity, byte);
1716 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1717 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1718 // Pull the cnums and name,vers,hash out of cstore
1719 let mut deps = Vec::new();
1720 cstore.iter_crate_data(|key, val| {
1721 let dep = decoder::CrateDep {
1723 name: decoder::get_crate_name(val.data()),
1724 hash: decoder::get_crate_hash(val.data()),
1730 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1732 // Sanity-check the crate numbers
1733 let mut expected_cnum = 1;
1734 for n in deps.iter() {
1735 assert_eq!(n.cnum, expected_cnum);
1742 // We're just going to write a list of crate 'name-hash-version's, with
1743 // the assumption that they are numbered 1 to n.
1744 // FIXME (#2166): This is not nearly enough to support correct versioning
1745 // but is enough to get transitive crate dependencies working.
1746 rbml_w.start_tag(tag_crate_deps);
1747 let r = get_ordered_deps(cstore);
1748 for dep in r.iter() {
1749 encode_crate_dep(rbml_w, (*dep).clone());
1754 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1755 rbml_w.start_tag(tag_lang_items);
1757 for (i, def_id) in ecx.tcx.lang_items.items() {
1758 for id in def_id.iter() {
1759 if id.krate == ast::LOCAL_CRATE {
1760 rbml_w.start_tag(tag_lang_items_item);
1762 rbml_w.start_tag(tag_lang_items_item_id);
1764 let wr: &mut SeekableMemWriter = rbml_w.writer;
1765 wr.write_be_u32(i as u32);
1767 rbml_w.end_tag(); // tag_lang_items_item_id
1769 rbml_w.start_tag(tag_lang_items_item_node_id);
1771 let wr: &mut SeekableMemWriter = rbml_w.writer;
1772 wr.write_be_u32(id.node as u32);
1774 rbml_w.end_tag(); // tag_lang_items_item_node_id
1776 rbml_w.end_tag(); // tag_lang_items_item
1781 for i in ecx.tcx.lang_items.missing.iter() {
1782 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1785 rbml_w.end_tag(); // tag_lang_items
1788 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1789 rbml_w.start_tag(tag_native_libraries);
1791 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1794 cstore::NativeStatic => {} // these libraries are not propagated
1795 cstore::NativeFramework | cstore::NativeUnknown => {
1796 rbml_w.start_tag(tag_native_libraries_lib);
1798 rbml_w.start_tag(tag_native_libraries_kind);
1799 rbml_w.writer.write_be_u32(kind as u32);
1802 rbml_w.start_tag(tag_native_libraries_name);
1803 rbml_w.writer.write(lib.as_bytes());
1814 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1815 match ecx.tcx.sess.plugin_registrar_fn.get() {
1816 Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1821 /// Serialize the text of the exported macros
1822 fn encode_macro_defs(rbml_w: &mut Encoder,
1823 krate: &ast::Crate) {
1824 rbml_w.start_tag(tag_macro_defs);
1825 for def in krate.exported_macros.iter() {
1826 rbml_w.start_tag(tag_macro_def);
1828 encode_name(rbml_w, def.ident.name);
1829 encode_attributes(rbml_w, def.attrs.index(&FullRange));
1831 rbml_w.start_tag(tag_macro_def_body);
1832 rbml_w.wr_str(pprust::tts_to_string(def.body.index(&FullRange)).index(&FullRange));
1840 fn encode_unboxed_closures<'a>(
1841 ecx: &'a EncodeContext,
1842 rbml_w: &'a mut Encoder) {
1843 rbml_w.start_tag(tag_unboxed_closures);
1844 for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1848 if unboxed_closure_id.krate != ast::LOCAL_CRATE {
1852 rbml_w.start_tag(tag_unboxed_closure);
1853 encode_def_id(rbml_w, *unboxed_closure_id);
1854 rbml_w.start_tag(tag_unboxed_closure_type);
1855 write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
1857 encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
1863 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
1864 struct StructFieldVisitor<'a, 'b:'a> {
1865 rbml_w: &'a mut Encoder<'b>,
1868 impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1869 fn visit_struct_field(&mut self, field: &ast::StructField) {
1870 self.rbml_w.start_tag(tag_struct_field);
1871 self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1872 encode_attributes(self.rbml_w, field.node.attrs.index(&FullRange));
1873 self.rbml_w.end_tag();
1877 rbml_w.start_tag(tag_struct_fields);
1878 visit::walk_crate(&mut StructFieldVisitor {
1886 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1887 ecx: &'a EncodeContext<'b, 'tcx>,
1888 rbml_w: &'a mut Encoder<'c>,
1891 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1892 fn visit_item(&mut self, item: &ast::Item) {
1893 if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
1894 let def_map = &self.ecx.tcx.def_map;
1895 let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
1896 let def_id = trait_def.def_id();
1898 // Load eagerly if this is an implementation of the Drop trait
1899 // or if the trait is not defined in this crate.
1900 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1901 def_id.krate != ast::LOCAL_CRATE {
1902 self.rbml_w.start_tag(tag_impls_impl);
1903 encode_def_id(self.rbml_w, local_def(item.id));
1904 self.rbml_w.end_tag();
1907 visit::walk_item(self, item);
1911 /// Encodes implementations that are eagerly loaded.
1913 /// None of this is necessary in theory; we can load all implementations
1914 /// lazily. However, in two cases the optimizations to lazily load
1915 /// implementations are not yet implemented. These two cases, which require us
1916 /// to load implementations eagerly, are:
1918 /// * Destructors (implementations of the Drop trait).
1920 /// * Implementations of traits not defined in this crate.
1921 fn encode_impls<'a>(ecx: &'a EncodeContext,
1923 rbml_w: &'a mut Encoder) {
1924 rbml_w.start_tag(tag_impls);
1927 let mut visitor = ImplVisitor {
1931 visit::walk_crate(&mut visitor, krate);
1937 fn encode_misc_info(ecx: &EncodeContext,
1939 rbml_w: &mut Encoder) {
1940 rbml_w.start_tag(tag_misc_info);
1941 rbml_w.start_tag(tag_misc_info_crate_items);
1942 for item in krate.module.items.iter() {
1943 rbml_w.start_tag(tag_mod_child);
1944 rbml_w.wr_str(def_to_string(local_def(item.id)).index(&FullRange));
1947 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1948 rbml_w.start_tag(tag_mod_child);
1949 rbml_w.wr_str(def_to_string(local_def(
1950 auxiliary_node_id)).index(&FullRange));
1956 // Encode reexports for the root module.
1957 encode_reexports(ecx, rbml_w, 0, ast_map::Values([].iter()).chain(None));
1963 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1964 rbml_w.start_tag(tag_reachable_extern_fns);
1966 for id in ecx.reachable.iter() {
1967 if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1968 if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1969 if abi != abi::Rust && !generics.is_type_parameterized() {
1970 rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1979 fn encode_crate_dep(rbml_w: &mut Encoder,
1980 dep: decoder::CrateDep) {
1981 rbml_w.start_tag(tag_crate_dep);
1982 rbml_w.start_tag(tag_crate_dep_crate_name);
1983 rbml_w.writer.write(dep.name.as_bytes());
1985 rbml_w.start_tag(tag_crate_dep_hash);
1986 rbml_w.writer.write(dep.hash.as_str().as_bytes());
1991 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1992 rbml_w.start_tag(tag_crate_hash);
1993 rbml_w.writer.write(hash.as_str().as_bytes());
1997 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1998 rbml_w.start_tag(tag_crate_crate_name);
1999 rbml_w.writer.write(crate_name.as_bytes());
2003 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
2004 rbml_w.start_tag(tag_crate_triple);
2005 rbml_w.writer.write(triple.as_bytes());
2009 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
2010 rbml_w.start_tag(tag_dylib_dependency_formats);
2011 match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
2013 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
2014 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
2015 cstore::RequireDynamic => "d",
2016 cstore::RequireStatic => "s",
2018 }).collect::<Vec<String>>();
2019 rbml_w.writer.write(s.connect(",").as_bytes());
2026 // NB: Increment this as you change the metadata encoding version.
2027 #[allow(non_upper_case_globals)]
2028 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
2030 pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
2031 let mut wr = SeekableMemWriter::new();
2032 encode_metadata_inner(&mut wr, parms, krate);
2033 let mut v = wr.unwrap();
2035 // And here we run into yet another obscure archive bug: in which metadata
2036 // loaded from archives may have trailing garbage bytes. Awhile back one of
2037 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
2038 // and opt) by having rbml generate an out-of-bounds panic when looking at
2041 // Upon investigation it turned out that the metadata file inside of an rlib
2042 // (and ar archive) was being corrupted. Some compilations would generate a
2043 // metadata file which would end in a few extra bytes, while other
2044 // compilations would not have these extra bytes appended to the end. These
2045 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2046 // being interpreted causing the out-of-bounds.
2048 // The root cause of why these extra bytes were appearing was never
2049 // discovered, and in the meantime the solution we're employing is to insert
2050 // the length of the metadata to the start of the metadata. Later on this
2051 // will allow us to slice the metadata to the precise length that we just
2052 // generated regardless of trailing bytes that end up in it.
2053 let len = v.len() as u32;
2054 v.insert(0, (len >> 0) as u8);
2055 v.insert(0, (len >> 8) as u8);
2056 v.insert(0, (len >> 16) as u8);
2057 v.insert(0, (len >> 24) as u8);
2061 fn encode_metadata_inner(wr: &mut SeekableMemWriter,
2062 parms: EncodeParams,
2063 krate: &ast::Crate) {
2067 lang_item_bytes: u64,
2068 native_lib_bytes: u64,
2069 plugin_registrar_fn_bytes: u64,
2070 macro_defs_bytes: u64,
2071 unboxed_closure_bytes: u64,
2079 let mut stats = Stats {
2083 native_lib_bytes: 0,
2084 plugin_registrar_fn_bytes: 0,
2085 macro_defs_bytes: 0,
2086 unboxed_closure_bytes: 0,
2100 encode_inlined_item,
2105 let ecx = EncodeContext {
2108 reexports: reexports,
2109 item_symbols: item_symbols,
2110 link_meta: link_meta,
2112 encode_inlined_item: RefCell::new(encode_inlined_item),
2113 type_abbrevs: RefCell::new(FnvHashMap::new()),
2114 reachable: reachable,
2117 let mut rbml_w = writer::Encoder::new(wr);
2119 encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.index(&FullRange));
2120 encode_crate_triple(&mut rbml_w,
2124 .index(&FullRange));
2125 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2126 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2128 let mut i = rbml_w.writer.tell().unwrap();
2129 encode_attributes(&mut rbml_w, krate.attrs.index(&FullRange));
2130 stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
2132 i = rbml_w.writer.tell().unwrap();
2133 encode_crate_deps(&mut rbml_w, ecx.cstore);
2134 stats.dep_bytes = rbml_w.writer.tell().unwrap() - i;
2136 // Encode the language items.
2137 i = rbml_w.writer.tell().unwrap();
2138 encode_lang_items(&ecx, &mut rbml_w);
2139 stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i;
2141 // Encode the native libraries used
2142 i = rbml_w.writer.tell().unwrap();
2143 encode_native_libraries(&ecx, &mut rbml_w);
2144 stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i;
2146 // Encode the plugin registrar function
2147 i = rbml_w.writer.tell().unwrap();
2148 encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2149 stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
2151 // Encode macro definitions
2152 i = rbml_w.writer.tell().unwrap();
2153 encode_macro_defs(&mut rbml_w, krate);
2154 stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
2156 // Encode the types of all unboxed closures in this crate.
2157 i = rbml_w.writer.tell().unwrap();
2158 encode_unboxed_closures(&ecx, &mut rbml_w);
2159 stats.unboxed_closure_bytes = rbml_w.writer.tell().unwrap() - i;
2161 // Encode the def IDs of impls, for coherence checking.
2162 i = rbml_w.writer.tell().unwrap();
2163 encode_impls(&ecx, krate, &mut rbml_w);
2164 stats.impl_bytes = rbml_w.writer.tell().unwrap() - i;
2166 // Encode miscellaneous info.
2167 i = rbml_w.writer.tell().unwrap();
2168 encode_misc_info(&ecx, krate, &mut rbml_w);
2169 encode_reachable_extern_fns(&ecx, &mut rbml_w);
2170 stats.misc_bytes = rbml_w.writer.tell().unwrap() - i;
2172 // Encode and index the items.
2173 rbml_w.start_tag(tag_items);
2174 i = rbml_w.writer.tell().unwrap();
2175 let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2176 stats.item_bytes = rbml_w.writer.tell().unwrap() - i;
2178 i = rbml_w.writer.tell().unwrap();
2179 encode_index(&mut rbml_w, items_index, write_i64);
2180 stats.index_bytes = rbml_w.writer.tell().unwrap() - i;
2183 encode_struct_field_attrs(&mut rbml_w, krate);
2185 stats.total_bytes = rbml_w.writer.tell().unwrap();
2187 if tcx.sess.meta_stats() {
2188 for e in rbml_w.writer.get_ref().iter() {
2190 stats.zero_bytes += 1;
2194 println!("metadata stats:");
2195 println!(" attribute bytes: {}", stats.attr_bytes);
2196 println!(" dep bytes: {}", stats.dep_bytes);
2197 println!(" lang item bytes: {}", stats.lang_item_bytes);
2198 println!(" native bytes: {}", stats.native_lib_bytes);
2199 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2200 println!(" macro def bytes: {}", stats.macro_defs_bytes);
2201 println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
2202 println!(" impl bytes: {}", stats.impl_bytes);
2203 println!(" misc bytes: {}", stats.misc_bytes);
2204 println!(" item bytes: {}", stats.item_bytes);
2205 println!(" index bytes: {}", stats.index_bytes);
2206 println!(" zero bytes: {}", stats.zero_bytes);
2207 println!(" total bytes: {}", stats.total_bytes);
2211 // Get the encoded string for a type
2212 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2213 let mut wr = SeekableMemWriter::new();
2214 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
2215 diag: tcx.sess.diagnostic(),
2218 abbrevs: &RefCell::new(FnvHashMap::new())
2220 String::from_utf8(wr.unwrap()).unwrap()