1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
18 use metadata::common::*;
20 use metadata::cstore::LOCAL_CRATE;
21 use metadata::decoder;
22 use metadata::tyencode;
23 use metadata::index::{self, IndexData};
24 use metadata::inline::InlinedItemRef;
26 use middle::def_id::{CRATE_DEF_INDEX, DefId};
27 use middle::dependency_format::Linkage;
28 use middle::stability;
30 use middle::ty::{self, Ty};
31 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
33 use serialize::Encodable;
34 use std::cell::RefCell;
35 use std::io::prelude::*;
36 use std::io::{Cursor, SeekFrom};
40 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
42 use syntax::attr::AttrMetaMethods;
43 use syntax::diagnostic::SpanHandler;
44 use syntax::parse::token::special_idents;
46 use rbml::writer::Encoder;
49 use rustc_front::intravisit::Visitor;
50 use rustc_front::intravisit;
51 use front::map::{LinkedPath, PathElem, PathElems};
52 use front::map as ast_map;
54 pub type EncodeInlinedItem<'a> =
55 Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
57 pub struct EncodeParams<'a, 'tcx: 'a> {
58 pub diag: &'a SpanHandler,
59 pub tcx: &'a ty::ctxt<'tcx>,
60 pub reexports: &'a def::ExportMap,
61 pub item_symbols: &'a RefCell<NodeMap<String>>,
62 pub link_meta: &'a LinkMeta,
63 pub cstore: &'a cstore::CStore,
64 pub encode_inlined_item: EncodeInlinedItem<'a>,
65 pub reachable: &'a NodeSet,
68 pub struct EncodeContext<'a, 'tcx: 'a> {
69 pub diag: &'a SpanHandler,
70 pub tcx: &'a ty::ctxt<'tcx>,
71 pub reexports: &'a def::ExportMap,
72 pub item_symbols: &'a RefCell<NodeMap<String>>,
73 pub link_meta: &'a LinkMeta,
74 pub cstore: &'a cstore::CStore,
75 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
76 pub type_abbrevs: tyencode::abbrev_map<'tcx>,
77 pub reachable: &'a NodeSet,
80 impl<'a, 'tcx> EncodeContext<'a,'tcx> {
81 fn local_id(&self, def_id: DefId) -> NodeId {
82 self.tcx.map.as_local_node_id(def_id).unwrap()
86 /// "interned" entries referenced by id
87 #[derive(PartialEq, Eq, Hash)]
88 pub enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
90 struct CrateIndex<'tcx> {
92 xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
95 impl<'tcx> CrateIndex<'tcx> {
96 fn record(&mut self, id: DefId, rbml_w: &mut Encoder) {
97 let position = rbml_w.mark_stable_position();
98 self.items.record(id, position);
101 fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
102 let old_len = self.xrefs.len() as u32;
103 *self.xrefs.entry(xref).or_insert(old_len)
107 fn encode_name(rbml_w: &mut Encoder, name: Name) {
108 rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
111 fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
112 rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
115 /// For every DefId that we create a metadata item for, we include a
116 /// serialized copy of its DefKey, which allows us to recreate a path.
117 fn encode_def_id_and_key(ecx: &EncodeContext,
118 rbml_w: &mut Encoder,
121 encode_def_id(rbml_w, def_id);
122 encode_def_key(ecx, rbml_w, def_id);
125 fn encode_def_key(ecx: &EncodeContext,
126 rbml_w: &mut Encoder,
129 rbml_w.start_tag(tag_def_key);
130 let def_key = ecx.tcx.map.def_key(def_id);
131 def_key.encode(rbml_w);
135 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
136 ecx: &EncodeContext<'a, 'tcx>,
137 trait_ref: ty::TraitRef<'tcx>,
139 let ty_str_ctxt = &tyencode::ctxt {
143 abbrevs: &ecx.type_abbrevs
146 rbml_w.start_tag(tag);
147 tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
151 // Item info table encoding
152 fn encode_family(rbml_w: &mut Encoder, c: char) {
153 rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
156 pub fn def_to_u64(did: DefId) -> u64 {
157 assert!(did.index.as_u32() < u32::MAX);
158 (did.krate as u64) << 32 | (did.index.as_usize() as u64)
161 pub fn def_to_string(did: DefId) -> String {
162 format!("{}:{}", did.krate, did.index.as_usize())
165 fn encode_item_variances(rbml_w: &mut Encoder,
168 let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id));
169 rbml_w.start_tag(tag_item_variances);
174 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
175 ecx: &EncodeContext<'a, 'tcx>,
176 index: &mut CrateIndex<'tcx>,
178 encode_bounds_and_type(rbml_w,
181 &ecx.tcx.lookup_item_type(ecx.tcx.map.local_def_id(id)),
182 &ecx.tcx.lookup_predicates(ecx.tcx.map.local_def_id(id)));
185 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
186 ecx: &EncodeContext<'a, 'tcx>,
187 index: &mut CrateIndex<'tcx>,
188 scheme: &ty::TypeScheme<'tcx>,
189 predicates: &ty::GenericPredicates<'tcx>) {
190 encode_generics(rbml_w, ecx, index,
191 &scheme.generics, &predicates, tag_item_generics);
192 encode_type(ecx, rbml_w, scheme.ty);
195 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
196 let id = def_to_u64(vid);
197 rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
198 rbml_w.wr_tagged_u64(tag_mod_child, id);
201 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
202 rbml_w: &mut Encoder,
203 closure_type: &ty::ClosureTy<'tcx>) {
204 let ty_str_ctxt = &tyencode::ctxt {
208 abbrevs: &ecx.type_abbrevs
210 tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
213 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
214 rbml_w: &mut Encoder,
216 let ty_str_ctxt = &tyencode::ctxt {
220 abbrevs: &ecx.type_abbrevs
222 tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
225 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
226 rbml_w: &mut Encoder,
227 trait_ref: &ty::TraitRef<'tcx>) {
228 let ty_str_ctxt = &tyencode::ctxt {
232 abbrevs: &ecx.type_abbrevs
234 tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref);
237 pub fn write_region(ecx: &EncodeContext,
238 rbml_w: &mut Encoder,
240 let ty_str_ctxt = &tyencode::ctxt {
244 abbrevs: &ecx.type_abbrevs
246 tyencode::enc_region(rbml_w, ty_str_ctxt, r);
249 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
250 rbml_w: &mut Encoder,
252 rbml_w.start_tag(tag_items_data_item_type);
253 write_type(ecx, rbml_w, typ);
257 fn encode_region(ecx: &EncodeContext,
258 rbml_w: &mut Encoder,
260 rbml_w.start_tag(tag_items_data_region);
261 write_region(ecx, rbml_w, r);
265 fn encode_symbol(ecx: &EncodeContext,
266 rbml_w: &mut Encoder,
268 match ecx.item_symbols.borrow().get(&id) {
270 debug!("encode_symbol(id={}, str={})", id, *x);
271 rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
274 ecx.diag.handler().bug(
275 &format!("encode_symbol: id not found {}", id));
280 fn encode_disr_val(_: &EncodeContext,
281 rbml_w: &mut Encoder,
282 disr_val: ty::Disr) {
283 rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_string());
286 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
287 rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
290 fn encode_struct_fields(rbml_w: &mut Encoder,
291 variant: ty::VariantDef) {
292 for f in &variant.fields {
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.did);
305 fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
306 rbml_w: &mut Encoder,
308 vis: hir::Visibility,
309 index: &mut CrateIndex<'tcx>) {
310 debug!("encode_enum_variant_info(id={})", id);
312 let mut disr_val = 0;
313 let def = ecx.tcx.lookup_adt_def(ecx.tcx.map.local_def_id(id));
314 for variant in &def.variants {
315 let vid = variant.did;
316 let variant_node_id = ecx.local_id(vid);
318 if let ty::VariantKind::Struct = variant.kind() {
319 // tuple-like enum variant fields aren't really items so
320 // don't try to encode them.
321 for field in &variant.fields {
322 encode_field(ecx, rbml_w, field, index);
326 index.record(vid, rbml_w);
327 rbml_w.start_tag(tag_items_data_item);
328 encode_def_id_and_key(ecx, rbml_w, vid);
329 encode_family(rbml_w, match variant.kind() {
330 ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
331 ty::VariantKind::Struct => 'V'
333 encode_name(rbml_w, variant.name);
334 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(id));
335 encode_visibility(rbml_w, vis);
337 let attrs = ecx.tcx.get_attrs(vid);
338 encode_attributes(rbml_w, &attrs);
339 encode_repr_attrs(rbml_w, ecx, &attrs);
341 let stab = stability::lookup(ecx.tcx, vid);
342 encode_stability(rbml_w, stab);
344 encode_struct_fields(rbml_w, variant);
346 let specified_disr_val = variant.disr_val;
347 if specified_disr_val != disr_val {
348 encode_disr_val(ecx, rbml_w, specified_disr_val);
349 disr_val = specified_disr_val;
351 encode_bounds_and_type_for_item(rbml_w, ecx, index, variant_node_id);
353 ecx.tcx.map.with_path(variant_node_id, |path| encode_path(rbml_w, path));
355 disr_val = disr_val.wrapping_add(1);
359 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
360 let path = path.collect::<Vec<_>>();
361 rbml_w.start_tag(tag_path);
362 rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
364 let tag = match *pe {
365 ast_map::PathMod(_) => tag_path_elem_mod,
366 ast_map::PathName(_) => tag_path_elem_name
368 rbml_w.wr_tagged_str(tag, &pe.name().as_str());
373 /// Iterates through "auxiliary node IDs", which are node IDs that describe
374 /// top-level items that are sub-items of the given item. Specifically:
376 /// * For newtype structs, iterates through the node ID of the constructor.
377 fn each_auxiliary_node_id<F>(item: &hir::Item, callback: F) -> bool where
378 F: FnOnce(NodeId) -> bool,
380 let mut continue_ = true;
382 hir::ItemStruct(ref struct_def, _) => {
383 // If this is a newtype struct, return the constructor.
384 if struct_def.is_tuple() {
385 continue_ = callback(struct_def.id());
394 fn encode_reexports(ecx: &EncodeContext,
395 rbml_w: &mut Encoder,
397 debug!("(encoding info for module) encoding reexports for {}", id);
398 match ecx.reexports.get(&id) {
400 debug!("(encoding info for module) found reexports for {}", id);
402 debug!("(encoding info for module) reexport '{}' ({:?}) for \
407 rbml_w.start_tag(tag_items_data_item_reexport);
408 rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
409 def_to_u64(exp.def_id));
410 rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
415 None => debug!("(encoding info for module) found no reexports for {}", id),
419 fn encode_info_for_mod(ecx: &EncodeContext,
420 rbml_w: &mut Encoder,
422 attrs: &[ast::Attribute],
426 vis: hir::Visibility) {
427 rbml_w.start_tag(tag_items_data_item);
428 encode_def_id_and_key(ecx, rbml_w, ecx.tcx.map.local_def_id(id));
429 encode_family(rbml_w, 'm');
430 encode_name(rbml_w, name);
431 debug!("(encoding info for module) encoding info for module ID {}", id);
433 // Encode info about all the module children.
434 for item_id in &md.item_ids {
435 rbml_w.wr_tagged_u64(tag_mod_child,
436 def_to_u64(ecx.tcx.map.local_def_id(item_id.id)));
438 let item = ecx.tcx.map.expect_item(item_id.id);
439 each_auxiliary_node_id(item, |auxiliary_node_id| {
440 rbml_w.wr_tagged_u64(tag_mod_child,
441 def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
446 encode_path(rbml_w, path.clone());
447 encode_visibility(rbml_w, vis);
449 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(id));
450 encode_stability(rbml_w, stab);
452 // Encode the reexports of this module, if this module is public.
453 if vis == hir::Public {
454 debug!("(encoding info for module) encoding reexports for {}", id);
455 encode_reexports(ecx, rbml_w, id);
457 encode_attributes(rbml_w, attrs);
462 fn encode_struct_field_family(rbml_w: &mut Encoder,
463 visibility: hir::Visibility) {
464 encode_family(rbml_w, match visibility {
466 hir::Inherited => 'N'
470 fn encode_visibility(rbml_w: &mut Encoder, visibility: hir::Visibility) {
471 let ch = match visibility {
473 hir::Inherited => 'i',
475 rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
478 fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) {
479 rbml_w.start_tag(tag_items_data_item_constness);
480 let ch = match constness {
481 hir::Constness::Const => 'c',
482 hir::Constness::NotConst => 'n',
484 rbml_w.wr_str(&ch.to_string());
488 fn encode_explicit_self(rbml_w: &mut Encoder,
489 explicit_self: &ty::ExplicitSelfCategory) {
490 let tag = tag_item_trait_method_explicit_self;
492 // Encode the base self type.
493 match *explicit_self {
494 ty::StaticExplicitSelfCategory => {
495 rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
497 ty::ByValueExplicitSelfCategory => {
498 rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
500 ty::ByBoxExplicitSelfCategory => {
501 rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
503 ty::ByReferenceExplicitSelfCategory(_, m) => {
504 // FIXME(#4846) encode custom lifetime
505 let ch = encode_mutability(m);
506 rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]);
510 fn encode_mutability(m: hir::Mutability) -> u8 {
512 hir::MutImmutable => 'i' as u8,
513 hir::MutMutable => 'm' as u8,
518 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
519 rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
522 fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
523 rbml_w: &mut Encoder,
524 field: ty::FieldDef<'tcx>,
525 index: &mut CrateIndex<'tcx>) {
527 let id = ecx.local_id(field.did);
529 index.record(field.did, rbml_w);
530 rbml_w.start_tag(tag_items_data_item);
531 debug!("encode_field: encoding {} {}", nm, id);
532 encode_struct_field_family(rbml_w, field.vis);
533 encode_name(rbml_w, nm);
534 encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
535 encode_def_id_and_key(ecx, rbml_w, field.did);
537 let stab = stability::lookup(ecx.tcx, field.did);
538 encode_stability(rbml_w, stab);
543 fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
544 rbml_w: &mut Encoder,
547 index: &mut CrateIndex<'tcx>,
549 let ctor_def_id = ecx.tcx.map.local_def_id(ctor_id);
551 index.record(ctor_def_id, rbml_w);
552 rbml_w.start_tag(tag_items_data_item);
553 encode_def_id_and_key(ecx, rbml_w, ctor_def_id);
554 encode_family(rbml_w, 'o');
555 encode_bounds_and_type_for_item(rbml_w, ecx, index, ctor_id);
556 encode_name(rbml_w, name);
557 ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
558 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id));
560 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
561 encode_symbol(ecx, rbml_w, ctor_id);
564 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
565 encode_stability(rbml_w, stab);
567 // indicate that this is a tuple struct ctor, because downstream users will normally want
568 // the tuple struct definition, but without this there is no way for them to tell that
569 // they actually have a ctor rather than a normal function
570 rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]);
575 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
576 ecx: &EncodeContext<'a, 'tcx>,
577 index: &mut CrateIndex<'tcx>,
578 generics: &ty::Generics<'tcx>,
579 predicates: &ty::GenericPredicates<'tcx>,
582 rbml_w.start_tag(tag);
585 let ty_str_ctxt = &tyencode::ctxt {
589 abbrevs: &ecx.type_abbrevs
592 for param in &generics.types {
593 rbml_w.start_tag(tag_type_param_def);
594 tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
599 for param in &generics.regions {
600 rbml_w.start_tag(tag_region_param_def);
602 rbml_w.start_tag(tag_region_param_def_ident);
603 encode_name(rbml_w, param.name);
606 rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
607 def_to_u64(param.def_id));
609 rbml_w.wr_tagged_u64(tag_region_param_def_space,
610 param.space.to_uint() as u64);
612 rbml_w.wr_tagged_u64(tag_region_param_def_index,
615 for &bound_region in ¶m.bounds {
616 encode_region(ecx, rbml_w, bound_region);
622 encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
627 fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
628 _ecx: &EncodeContext<'a,'tcx>,
629 index: &mut CrateIndex<'tcx>,
630 predicates: &ty::GenericPredicates<'tcx>)
632 for (space, _, predicate) in predicates.predicates.iter_enumerated() {
633 let tag = match space {
634 subst::TypeSpace => tag_type_predicate,
635 subst::SelfSpace => tag_self_predicate,
636 subst::FnSpace => tag_fn_predicate
639 rbml_w.wr_tagged_u32(tag,
640 index.add_xref(XRef::Predicate(predicate.clone())));
644 fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
645 ecx: &EncodeContext<'a,'tcx>,
646 index: &mut CrateIndex<'tcx>,
647 predicates: &ty::GenericPredicates<'tcx>,
650 rbml_w.start_tag(tag);
651 encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
655 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
656 rbml_w: &mut Encoder,
657 index: &mut CrateIndex<'tcx>,
658 method_ty: &ty::Method<'tcx>) {
659 encode_def_id_and_key(ecx, rbml_w, method_ty.def_id);
660 encode_name(rbml_w, method_ty.name);
661 encode_generics(rbml_w, ecx, index,
662 &method_ty.generics, &method_ty.predicates,
663 tag_method_ty_generics);
664 encode_visibility(rbml_w, method_ty.vis);
665 encode_explicit_self(rbml_w, &method_ty.explicit_self);
666 match method_ty.explicit_self {
667 ty::StaticExplicitSelfCategory => {
668 encode_family(rbml_w, STATIC_METHOD_FAMILY);
670 _ => encode_family(rbml_w, METHOD_FAMILY)
674 fn encode_info_for_associated_const<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
675 rbml_w: &mut Encoder,
676 index: &mut CrateIndex<'tcx>,
677 associated_const: &ty::AssociatedConst,
678 impl_path: PathElems,
680 impl_item_opt: Option<&hir::ImplItem>) {
681 debug!("encode_info_for_associated_const({:?},{:?})",
682 associated_const.def_id,
683 associated_const.name);
685 index.record(associated_const.def_id, rbml_w);
686 rbml_w.start_tag(tag_items_data_item);
688 encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
689 encode_name(rbml_w, associated_const.name);
690 encode_visibility(rbml_w, associated_const.vis);
691 encode_family(rbml_w, 'C');
693 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
694 encode_item_sort(rbml_w, 'C');
696 encode_bounds_and_type_for_item(rbml_w, ecx, index,
697 ecx.local_id(associated_const.def_id));
699 let stab = stability::lookup(ecx.tcx, associated_const.def_id);
700 encode_stability(rbml_w, stab);
702 let elem = ast_map::PathName(associated_const.name);
703 encode_path(rbml_w, impl_path.chain(Some(elem)));
705 if let Some(ii) = impl_item_opt {
706 encode_attributes(rbml_w, &ii.attrs);
707 encode_inlined_item(ecx,
709 InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
716 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
717 rbml_w: &mut Encoder,
718 index: &mut CrateIndex<'tcx>,
719 m: &ty::Method<'tcx>,
720 impl_path: PathElems,
721 is_default_impl: bool,
723 impl_item_opt: Option<&hir::ImplItem>) {
725 debug!("encode_info_for_method: {:?} {:?}", m.def_id,
727 index.record(m.def_id, rbml_w);
728 rbml_w.start_tag(tag_items_data_item);
730 encode_method_ty_fields(ecx, rbml_w, index, m);
731 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
732 encode_item_sort(rbml_w, 'r');
734 let stab = stability::lookup(ecx.tcx, m.def_id);
735 encode_stability(rbml_w, stab);
737 let m_node_id = ecx.local_id(m.def_id);
738 encode_bounds_and_type_for_item(rbml_w, ecx, index, m_node_id);
740 let elem = ast_map::PathName(m.name);
741 encode_path(rbml_w, impl_path.chain(Some(elem)));
742 if let Some(impl_item) = impl_item_opt {
743 if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
744 encode_attributes(rbml_w, &impl_item.attrs);
745 let scheme = ecx.tcx.lookup_item_type(m.def_id);
746 let any_types = !scheme.generics.types.is_empty();
747 let needs_inline = any_types || is_default_impl ||
748 attr::requests_inline(&impl_item.attrs);
749 if needs_inline || sig.constness == hir::Constness::Const {
750 encode_inlined_item(ecx,
752 InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
755 encode_constness(rbml_w, sig.constness);
757 let m_id = ecx.local_id(m.def_id);
758 encode_symbol(ecx, rbml_w, m_id);
760 encode_method_argument_names(rbml_w, &sig.decl);
767 fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
768 rbml_w: &mut Encoder,
769 index: &mut CrateIndex<'tcx>,
770 associated_type: &ty::AssociatedType<'tcx>,
771 impl_path: PathElems,
773 impl_item_opt: Option<&hir::ImplItem>) {
774 debug!("encode_info_for_associated_type({:?},{:?})",
775 associated_type.def_id,
776 associated_type.name);
778 index.record(associated_type.def_id, rbml_w);
779 rbml_w.start_tag(tag_items_data_item);
781 encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
782 encode_name(rbml_w, associated_type.name);
783 encode_visibility(rbml_w, associated_type.vis);
784 encode_family(rbml_w, 'y');
785 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
786 encode_item_sort(rbml_w, 't');
788 let stab = stability::lookup(ecx.tcx, associated_type.def_id);
789 encode_stability(rbml_w, stab);
791 let elem = ast_map::PathName(associated_type.name);
792 encode_path(rbml_w, impl_path.chain(Some(elem)));
794 if let Some(ii) = impl_item_opt {
795 encode_attributes(rbml_w, &ii.attrs);
797 encode_predicates(rbml_w, ecx, index,
798 &ecx.tcx.lookup_predicates(associated_type.def_id),
802 if let Some(ty) = associated_type.ty {
803 encode_type(ecx, rbml_w, ty);
809 fn encode_method_argument_names(rbml_w: &mut Encoder,
810 decl: &hir::FnDecl) {
811 rbml_w.start_tag(tag_method_argument_names);
812 for arg in &decl.inputs {
813 let tag = tag_method_argument_name;
814 if let hir::PatIdent(_, ref path1, _) = arg.pat.node {
815 let name = path1.node.name.as_str();
816 rbml_w.wr_tagged_bytes(tag, name.as_bytes());
818 rbml_w.wr_tagged_bytes(tag, &[]);
824 fn encode_repr_attrs(rbml_w: &mut Encoder,
826 attrs: &[ast::Attribute]) {
827 let mut repr_attrs = Vec::new();
829 repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
832 rbml_w.start_tag(tag_items_data_item_repr);
833 repr_attrs.encode(rbml_w);
837 fn encode_inlined_item(ecx: &EncodeContext,
838 rbml_w: &mut Encoder,
839 ii: InlinedItemRef) {
840 let mut eii = ecx.encode_inlined_item.borrow_mut();
841 let eii: &mut EncodeInlinedItem = &mut *eii;
845 const FN_FAMILY: char = 'f';
846 const STATIC_METHOD_FAMILY: char = 'F';
847 const METHOD_FAMILY: char = 'h';
849 // Encodes the inherent implementations of a structure, enumeration, or trait.
850 fn encode_inherent_implementations(ecx: &EncodeContext,
851 rbml_w: &mut Encoder,
853 match ecx.tcx.inherent_impls.borrow().get(&def_id) {
855 Some(implementations) => {
856 for &impl_def_id in implementations.iter() {
857 rbml_w.start_tag(tag_items_data_item_inherent_impl);
858 encode_def_id(rbml_w, impl_def_id);
865 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
866 stab_opt.map(|stab| {
867 rbml_w.start_tag(tag_items_data_item_stability);
868 stab.encode(rbml_w).unwrap();
873 fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
874 rbml_w: &mut Encoder,
875 xrefs: FnvHashMap<XRef<'tcx>, u32>)
877 let ty_str_ctxt = &tyencode::ctxt {
881 abbrevs: &ecx.type_abbrevs
884 let mut xref_positions = vec![0; xrefs.len()];
885 rbml_w.start_tag(tag_xref_data);
886 for (xref, id) in xrefs.into_iter() {
887 xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
889 XRef::Predicate(p) => {
890 tyencode::enc_predicate(rbml_w, ty_str_ctxt, &p)
896 rbml_w.start_tag(tag_xref_index);
897 index::write_dense_index(xref_positions, rbml_w.writer);
901 fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
902 rbml_w: &mut Encoder,
904 index: &mut CrateIndex<'tcx>,
906 vis: hir::Visibility) {
909 debug!("encoding info for item at {}",
910 tcx.sess.codemap().span_to_string(item.span));
912 let def_id = ecx.tcx.map.local_def_id(item.id);
913 let stab = stability::lookup(tcx, ecx.tcx.map.local_def_id(item.id));
916 hir::ItemStatic(_, m, _) => {
917 index.record(def_id, rbml_w);
918 rbml_w.start_tag(tag_items_data_item);
919 encode_def_id_and_key(ecx, rbml_w, def_id);
920 if m == hir::MutMutable {
921 encode_family(rbml_w, 'b');
923 encode_family(rbml_w, 'c');
925 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
926 encode_symbol(ecx, rbml_w, item.id);
927 encode_name(rbml_w, item.name);
928 encode_path(rbml_w, path);
929 encode_visibility(rbml_w, vis);
930 encode_stability(rbml_w, stab);
931 encode_attributes(rbml_w, &item.attrs);
934 hir::ItemConst(_, _) => {
935 index.record(def_id, rbml_w);
936 rbml_w.start_tag(tag_items_data_item);
937 encode_def_id_and_key(ecx, rbml_w, def_id);
938 encode_family(rbml_w, 'C');
939 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
940 encode_name(rbml_w, item.name);
941 encode_path(rbml_w, path);
942 encode_attributes(rbml_w, &item.attrs);
943 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
944 encode_visibility(rbml_w, vis);
945 encode_stability(rbml_w, stab);
948 hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
949 index.record(def_id, rbml_w);
950 rbml_w.start_tag(tag_items_data_item);
951 encode_def_id_and_key(ecx, rbml_w, def_id);
952 encode_family(rbml_w, FN_FAMILY);
953 let tps_len = generics.ty_params.len();
954 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
955 encode_name(rbml_w, item.name);
956 encode_path(rbml_w, path);
957 encode_attributes(rbml_w, &item.attrs);
958 let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
959 if needs_inline || constness == hir::Constness::Const {
960 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
963 encode_symbol(ecx, rbml_w, item.id);
965 encode_constness(rbml_w, constness);
966 encode_visibility(rbml_w, vis);
967 encode_stability(rbml_w, stab);
968 encode_method_argument_names(rbml_w, &**decl);
971 hir::ItemMod(ref m) => {
972 index.record(def_id, rbml_w);
973 encode_info_for_mod(ecx,
982 hir::ItemForeignMod(ref fm) => {
983 index.record(def_id, rbml_w);
984 rbml_w.start_tag(tag_items_data_item);
985 encode_def_id_and_key(ecx, rbml_w, def_id);
986 encode_family(rbml_w, 'n');
987 encode_name(rbml_w, item.name);
988 encode_path(rbml_w, path);
990 // Encode all the items in this module.
991 for foreign_item in &fm.items {
992 rbml_w.wr_tagged_u64(tag_mod_child,
993 def_to_u64(ecx.tcx.map.local_def_id(foreign_item.id)));
995 encode_visibility(rbml_w, vis);
996 encode_stability(rbml_w, stab);
1000 index.record(def_id, rbml_w);
1001 rbml_w.start_tag(tag_items_data_item);
1002 encode_def_id_and_key(ecx, rbml_w, def_id);
1003 encode_family(rbml_w, 'y');
1004 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1005 encode_name(rbml_w, item.name);
1006 encode_path(rbml_w, path);
1007 encode_visibility(rbml_w, vis);
1008 encode_stability(rbml_w, stab);
1011 hir::ItemEnum(ref enum_definition, _) => {
1012 index.record(def_id, rbml_w);
1014 rbml_w.start_tag(tag_items_data_item);
1015 encode_def_id_and_key(ecx, rbml_w, def_id);
1016 encode_family(rbml_w, 't');
1017 encode_item_variances(rbml_w, ecx, item.id);
1018 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1019 encode_name(rbml_w, item.name);
1020 encode_attributes(rbml_w, &item.attrs);
1021 encode_repr_attrs(rbml_w, ecx, &item.attrs);
1022 for v in &enum_definition.variants {
1023 encode_variant_id(rbml_w, ecx.tcx.map.local_def_id(v.node.data.id()));
1025 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1026 encode_path(rbml_w, path);
1028 // Encode inherent implementations for this enumeration.
1029 encode_inherent_implementations(ecx, rbml_w, def_id);
1031 encode_visibility(rbml_w, vis);
1032 encode_stability(rbml_w, stab);
1035 encode_enum_variant_info(ecx,
1041 hir::ItemStruct(ref struct_def, _) => {
1042 let def = ecx.tcx.lookup_adt_def(def_id);
1043 let variant = def.struct_variant();
1045 /* Index the class*/
1046 index.record(def_id, rbml_w);
1048 /* Now, make an item for the class itself */
1049 rbml_w.start_tag(tag_items_data_item);
1050 encode_def_id_and_key(ecx, rbml_w, def_id);
1051 encode_family(rbml_w, 'S');
1052 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1054 encode_item_variances(rbml_w, ecx, item.id);
1055 encode_name(rbml_w, item.name);
1056 encode_attributes(rbml_w, &item.attrs);
1057 encode_path(rbml_w, path.clone());
1058 encode_stability(rbml_w, stab);
1059 encode_visibility(rbml_w, vis);
1060 encode_repr_attrs(rbml_w, ecx, &item.attrs);
1062 /* Encode def_ids for each field and method
1063 for methods, write all the stuff get_trait_method
1065 encode_struct_fields(rbml_w, variant);
1067 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1069 // Encode inherent implementations for this structure.
1070 encode_inherent_implementations(ecx, rbml_w, def_id);
1072 if !struct_def.is_struct() {
1073 let ctor_did = ecx.tcx.map.local_def_id(struct_def.id());
1074 rbml_w.wr_tagged_u64(tag_items_data_item_struct_ctor,
1075 def_to_u64(ctor_did));
1080 for field in &variant.fields {
1081 encode_field(ecx, rbml_w, field, index);
1084 // If this is a tuple-like struct, encode the type of the constructor.
1085 if !struct_def.is_struct() {
1086 encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id(), index, item.id);
1089 hir::ItemDefaultImpl(unsafety, _) => {
1090 index.record(def_id, rbml_w);
1091 rbml_w.start_tag(tag_items_data_item);
1092 encode_def_id_and_key(ecx, rbml_w, def_id);
1093 encode_family(rbml_w, 'd');
1094 encode_name(rbml_w, item.name);
1095 encode_unsafety(rbml_w, unsafety);
1097 let trait_ref = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)).unwrap();
1098 encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1101 hir::ItemImpl(unsafety, polarity, _, _, _, ref ast_items) => {
1102 // We need to encode information about the default methods we
1103 // have inherited, so we drive this based on the impl structure.
1104 let impl_items = tcx.impl_items.borrow();
1105 let items = impl_items.get(&def_id).unwrap();
1107 index.record(def_id, rbml_w);
1108 rbml_w.start_tag(tag_items_data_item);
1109 encode_def_id_and_key(ecx, rbml_w, def_id);
1110 encode_family(rbml_w, 'i');
1111 encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
1112 encode_name(rbml_w, item.name);
1113 encode_attributes(rbml_w, &item.attrs);
1114 encode_unsafety(rbml_w, unsafety);
1115 encode_polarity(rbml_w, polarity);
1117 match tcx.custom_coerce_unsized_kinds.borrow().get(&ecx.tcx.map.local_def_id(item.id)) {
1119 rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1120 kind.encode(rbml_w);
1126 for &item_def_id in items {
1127 rbml_w.start_tag(tag_item_impl_item);
1129 ty::ConstTraitItemId(item_def_id) => {
1130 encode_def_id(rbml_w, item_def_id);
1131 encode_item_sort(rbml_w, 'C');
1133 ty::MethodTraitItemId(item_def_id) => {
1134 encode_def_id(rbml_w, item_def_id);
1135 encode_item_sort(rbml_w, 'r');
1137 ty::TypeTraitItemId(item_def_id) => {
1138 encode_def_id(rbml_w, item_def_id);
1139 encode_item_sort(rbml_w, 't');
1144 if let Some(trait_ref) = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)) {
1145 encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1147 encode_path(rbml_w, path.clone());
1148 encode_stability(rbml_w, stab);
1151 // Iterate down the trait items, emitting them. We rely on the
1152 // assumption that all of the actually implemented trait items
1153 // appear first in the impl structure, in the same order they do
1154 // in the ast. This is a little sketchy.
1155 let num_implemented_methods = ast_items.len();
1156 for (i, &trait_item_def_id) in items.iter().enumerate() {
1157 let ast_item = if i < num_implemented_methods {
1158 Some(&*ast_items[i])
1163 match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
1164 ty::ConstTraitItem(ref associated_const) => {
1165 encode_info_for_associated_const(ecx,
1173 ty::MethodTraitItem(ref method_type) => {
1174 encode_info_for_method(ecx,
1183 ty::TypeTraitItem(ref associated_type) => {
1184 encode_info_for_associated_type(ecx,
1195 hir::ItemTrait(_, _, _, ref ms) => {
1196 index.record(def_id, rbml_w);
1197 rbml_w.start_tag(tag_items_data_item);
1198 encode_def_id_and_key(ecx, rbml_w, def_id);
1199 encode_family(rbml_w, 'I');
1200 encode_item_variances(rbml_w, ecx, item.id);
1201 let trait_def = tcx.lookup_trait_def(def_id);
1202 let trait_predicates = tcx.lookup_predicates(def_id);
1203 encode_unsafety(rbml_w, trait_def.unsafety);
1204 encode_paren_sugar(rbml_w, trait_def.paren_sugar);
1205 encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
1206 encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
1207 encode_generics(rbml_w, ecx, index,
1208 &trait_def.generics, &trait_predicates,
1210 encode_predicates(rbml_w, ecx, index,
1211 &tcx.lookup_super_predicates(def_id),
1212 tag_item_super_predicates);
1213 encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1214 encode_name(rbml_w, item.name);
1215 encode_attributes(rbml_w, &item.attrs);
1216 encode_visibility(rbml_w, vis);
1217 encode_stability(rbml_w, stab);
1218 for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
1219 rbml_w.start_tag(tag_item_trait_item);
1220 match method_def_id {
1221 ty::ConstTraitItemId(const_def_id) => {
1222 encode_def_id(rbml_w, const_def_id);
1223 encode_item_sort(rbml_w, 'C');
1225 ty::MethodTraitItemId(method_def_id) => {
1226 encode_def_id(rbml_w, method_def_id);
1227 encode_item_sort(rbml_w, 'r');
1229 ty::TypeTraitItemId(type_def_id) => {
1230 encode_def_id(rbml_w, type_def_id);
1231 encode_item_sort(rbml_w, 't');
1236 rbml_w.wr_tagged_u64(tag_mod_child,
1237 def_to_u64(method_def_id.def_id()));
1239 encode_path(rbml_w, path.clone());
1241 // Encode inherent implementations for this trait.
1242 encode_inherent_implementations(ecx, rbml_w, def_id);
1246 // Now output the trait item info for each trait item.
1247 let r = tcx.trait_item_def_ids(def_id);
1248 for (i, &item_def_id) in r.iter().enumerate() {
1249 assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
1251 index.record(item_def_id.def_id(), rbml_w);
1252 rbml_w.start_tag(tag_items_data_item);
1254 encode_parent_item(rbml_w, def_id);
1256 let stab = stability::lookup(tcx, item_def_id.def_id());
1257 encode_stability(rbml_w, stab);
1259 let trait_item_type =
1260 tcx.impl_or_trait_item(item_def_id.def_id());
1261 let is_nonstatic_method;
1262 match trait_item_type {
1263 ty::ConstTraitItem(associated_const) => {
1264 encode_name(rbml_w, associated_const.name);
1265 encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
1266 encode_visibility(rbml_w, associated_const.vis);
1268 let elem = ast_map::PathName(associated_const.name);
1270 path.clone().chain(Some(elem)));
1272 encode_family(rbml_w, 'C');
1274 encode_bounds_and_type_for_item(rbml_w, ecx, index,
1275 ecx.local_id(associated_const.def_id));
1277 is_nonstatic_method = false;
1279 ty::MethodTraitItem(method_ty) => {
1280 let method_def_id = item_def_id.def_id();
1282 encode_method_ty_fields(ecx, rbml_w, index, &*method_ty);
1284 let elem = ast_map::PathName(method_ty.name);
1286 path.clone().chain(Some(elem)));
1288 match method_ty.explicit_self {
1289 ty::StaticExplicitSelfCategory => {
1290 encode_family(rbml_w,
1291 STATIC_METHOD_FAMILY);
1294 encode_family(rbml_w,
1298 encode_bounds_and_type_for_item(rbml_w, ecx, index,
1299 ecx.local_id(method_def_id));
1301 is_nonstatic_method = method_ty.explicit_self !=
1302 ty::StaticExplicitSelfCategory;
1304 ty::TypeTraitItem(associated_type) => {
1305 encode_name(rbml_w, associated_type.name);
1306 encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
1308 let elem = ast_map::PathName(associated_type.name);
1310 path.clone().chain(Some(elem)));
1312 encode_item_sort(rbml_w, 't');
1313 encode_family(rbml_w, 'y');
1315 if let Some(ty) = associated_type.ty {
1316 encode_type(ecx, rbml_w, ty);
1319 is_nonstatic_method = false;
1323 let trait_item = &*ms[i];
1324 encode_attributes(rbml_w, &trait_item.attrs);
1325 match trait_item.node {
1326 hir::ConstTraitItem(_, ref default) => {
1327 if default.is_some() {
1328 encode_item_sort(rbml_w, 'C');
1330 encode_item_sort(rbml_w, 'c');
1333 encode_inlined_item(ecx, rbml_w,
1334 InlinedItemRef::TraitItem(def_id, trait_item));
1336 hir::MethodTraitItem(ref sig, ref body) => {
1337 // If this is a static method, we've already
1339 if is_nonstatic_method {
1340 // FIXME: I feel like there is something funny
1342 encode_bounds_and_type_for_item(rbml_w, ecx, index,
1343 ecx.local_id(item_def_id.def_id()));
1347 encode_item_sort(rbml_w, 'p');
1348 encode_inlined_item(ecx, rbml_w,
1349 InlinedItemRef::TraitItem(def_id, trait_item));
1351 encode_item_sort(rbml_w, 'r');
1353 encode_method_argument_names(rbml_w, &sig.decl);
1356 hir::TypeTraitItem(..) => {}
1362 hir::ItemExternCrate(_) | hir::ItemUse(_) => {
1363 // these are encoded separately
1368 fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
1369 rbml_w: &mut Encoder,
1370 nitem: &hir::ForeignItem,
1371 index: &mut CrateIndex<'tcx>,
1374 let def_id = ecx.tcx.map.local_def_id(nitem.id);
1376 index.record(def_id, rbml_w);
1377 rbml_w.start_tag(tag_items_data_item);
1378 encode_def_id_and_key(ecx, rbml_w, def_id);
1379 encode_visibility(rbml_w, nitem.vis);
1381 hir::ForeignItemFn(ref fndecl, _) => {
1382 encode_family(rbml_w, FN_FAMILY);
1383 encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
1384 encode_name(rbml_w, nitem.name);
1385 if abi == abi::RustIntrinsic || abi == abi::PlatformIntrinsic {
1386 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
1388 encode_attributes(rbml_w, &*nitem.attrs);
1389 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1390 encode_stability(rbml_w, stab);
1391 encode_symbol(ecx, rbml_w, nitem.id);
1392 encode_method_argument_names(rbml_w, &*fndecl);
1394 hir::ForeignItemStatic(_, mutbl) => {
1396 encode_family(rbml_w, 'b');
1398 encode_family(rbml_w, 'c');
1400 encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
1401 encode_attributes(rbml_w, &*nitem.attrs);
1402 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1403 encode_stability(rbml_w, stab);
1404 encode_symbol(ecx, rbml_w, nitem.id);
1405 encode_name(rbml_w, nitem.name);
1408 encode_path(rbml_w, path);
1412 fn my_visit_expr(expr: &hir::Expr,
1413 rbml_w: &mut Encoder,
1414 ecx: &EncodeContext,
1415 index: &mut CrateIndex) {
1417 hir::ExprClosure(..) => {
1418 let def_id = ecx.tcx.map.local_def_id(expr.id);
1420 index.record(def_id, rbml_w);
1422 rbml_w.start_tag(tag_items_data_item);
1423 encode_def_id_and_key(ecx, rbml_w, def_id);
1425 rbml_w.start_tag(tag_items_closure_ty);
1426 write_closure_type(ecx, rbml_w, &ecx.tcx.tables.borrow().closure_tys[&def_id]);
1429 rbml_w.start_tag(tag_items_closure_kind);
1430 ecx.tcx.closure_kind(def_id).encode(rbml_w).unwrap();
1433 ecx.tcx.map.with_path(expr.id, |path| encode_path(rbml_w, path));
1441 fn my_visit_item<'a, 'tcx>(i: &hir::Item,
1442 rbml_w: &mut Encoder,
1443 ecx: &EncodeContext<'a, 'tcx>,
1444 index: &mut CrateIndex<'tcx>) {
1445 ecx.tcx.map.with_path(i.id, |path| {
1446 encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1450 fn my_visit_foreign_item<'a, 'tcx>(ni: &hir::ForeignItem,
1451 rbml_w: &mut Encoder,
1452 ecx: &EncodeContext<'a, 'tcx>,
1453 index: &mut CrateIndex<'tcx>) {
1454 debug!("writing foreign item {}::{}",
1455 ecx.tcx.map.path_to_string(ni.id),
1458 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1459 ecx.tcx.map.with_path(ni.id, |path| {
1460 encode_info_for_foreign_item(ecx, rbml_w,
1466 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1467 rbml_w_for_visit_item: &'a mut Encoder<'b>,
1468 ecx: &'a EncodeContext<'c,'tcx>,
1469 index: &'a mut CrateIndex<'tcx>,
1472 impl<'a, 'b, 'c, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1473 fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
1474 intravisit::walk_expr(self, ex);
1475 my_visit_expr(ex, self.rbml_w_for_visit_item, self.ecx, self.index);
1477 fn visit_item(&mut self, i: &'tcx hir::Item) {
1478 intravisit::walk_item(self, i);
1479 my_visit_item(i, self.rbml_w_for_visit_item, self.ecx, self.index);
1481 fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
1482 intravisit::walk_foreign_item(self, ni);
1483 my_visit_foreign_item(ni, self.rbml_w_for_visit_item, self.ecx, self.index);
1487 fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
1488 rbml_w: &mut Encoder)
1489 -> CrateIndex<'tcx> {
1490 let krate = ecx.tcx.map.krate();
1492 let mut index = CrateIndex {
1493 items: IndexData::new(ecx.tcx.map.num_local_def_ids()),
1496 rbml_w.start_tag(tag_items_data);
1498 index.record(DefId::local(CRATE_DEF_INDEX), rbml_w);
1499 encode_info_for_mod(ecx,
1504 [].iter().cloned().chain(LinkedPath::empty()),
1505 syntax::parse::token::intern(&ecx.link_meta.crate_name),
1508 krate.visit_all_items(&mut EncodeVisitor {
1511 rbml_w_for_visit_item: &mut *rbml_w,
1518 fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
1519 rbml_w.start_tag(tag_index);
1520 index.write_index(rbml_w.writer);
1524 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1526 ast::MetaWord(ref name) => {
1527 rbml_w.start_tag(tag_meta_item_word);
1528 rbml_w.wr_tagged_str(tag_meta_item_name, name);
1531 ast::MetaNameValue(ref name, ref value) => {
1533 ast::LitStr(ref value, _) => {
1534 rbml_w.start_tag(tag_meta_item_name_value);
1535 rbml_w.wr_tagged_str(tag_meta_item_name, name);
1536 rbml_w.wr_tagged_str(tag_meta_item_value, value);
1539 _ => {/* FIXME (#623): encode other variants */ }
1542 ast::MetaList(ref name, ref items) => {
1543 rbml_w.start_tag(tag_meta_item_list);
1544 rbml_w.wr_tagged_str(tag_meta_item_name, name);
1545 for inner_item in items {
1546 encode_meta_item(rbml_w, &**inner_item);
1553 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1554 rbml_w.start_tag(tag_attributes);
1556 rbml_w.start_tag(tag_attribute);
1557 rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1558 encode_meta_item(rbml_w, &*attr.node.value);
1564 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: hir::Unsafety) {
1565 let byte: u8 = match unsafety {
1566 hir::Unsafety::Normal => 0,
1567 hir::Unsafety::Unsafe => 1,
1569 rbml_w.wr_tagged_u8(tag_unsafety, byte);
1572 fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) {
1573 let byte: u8 = if paren_sugar {1} else {0};
1574 rbml_w.wr_tagged_u8(tag_paren_sugar, byte);
1577 fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) {
1578 let byte: u8 = if is_defaulted {1} else {0};
1579 rbml_w.wr_tagged_u8(tag_defaulted_trait, byte);
1582 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) {
1583 rbml_w.start_tag(tag_associated_type_names);
1584 for &name in names {
1585 rbml_w.wr_tagged_str(tag_associated_type_name, &name.as_str());
1590 fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
1591 let byte: u8 = match polarity {
1592 hir::ImplPolarity::Positive => 0,
1593 hir::ImplPolarity::Negative => 1,
1595 rbml_w.wr_tagged_u8(tag_polarity, byte);
1598 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1599 fn get_ordered_deps(cstore: &cstore::CStore)
1600 -> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
1601 // Pull the cnums and name,vers,hash out of cstore
1602 let mut deps = Vec::new();
1603 cstore.iter_crate_data(|cnum, val| {
1604 deps.push((cnum, val.clone()));
1608 deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0));
1610 // Sanity-check the crate numbers
1611 let mut expected_cnum = 1;
1612 for &(n, _) in &deps {
1613 assert_eq!(n, expected_cnum);
1620 // We're just going to write a list of crate 'name-hash-version's, with
1621 // the assumption that they are numbered 1 to n.
1622 // FIXME (#2166): This is not nearly enough to support correct versioning
1623 // but is enough to get transitive crate dependencies working.
1624 rbml_w.start_tag(tag_crate_deps);
1625 for (_cnum, dep) in get_ordered_deps(cstore) {
1626 encode_crate_dep(rbml_w, &dep);
1631 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1632 rbml_w.start_tag(tag_lang_items);
1634 for (i, &opt_def_id) in ecx.tcx.lang_items.items() {
1635 if let Some(def_id) = opt_def_id {
1636 if def_id.is_local() {
1637 rbml_w.start_tag(tag_lang_items_item);
1638 rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
1639 rbml_w.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32());
1645 for i in &ecx.tcx.lang_items.missing {
1646 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1649 rbml_w.end_tag(); // tag_lang_items
1652 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1653 rbml_w.start_tag(tag_native_libraries);
1655 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1658 cstore::NativeStatic => {} // these libraries are not propagated
1659 cstore::NativeFramework | cstore::NativeUnknown => {
1660 rbml_w.start_tag(tag_native_libraries_lib);
1661 rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32);
1662 rbml_w.wr_tagged_str(tag_native_libraries_name, lib);
1671 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1672 match ecx.tcx.sess.plugin_registrar_fn.get() {
1674 let def_id = ecx.tcx.map.local_def_id(id);
1675 rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32());
1681 fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1682 rbml_w.start_tag(tag_codemap);
1683 let codemap = ecx.tcx.sess.codemap();
1685 for filemap in &codemap.files.borrow()[..] {
1687 if filemap.lines.borrow().is_empty() || filemap.is_imported() {
1688 // No need to export empty filemaps, as they can't contain spans
1689 // that need translation.
1690 // Also no need to re-export imported filemaps, as any downstream
1691 // crate will import them from their original source.
1695 rbml_w.start_tag(tag_codemap_filemap);
1696 filemap.encode(rbml_w);
1703 /// Serialize the text of the exported macros
1704 fn encode_macro_defs(rbml_w: &mut Encoder,
1705 krate: &hir::Crate) {
1706 rbml_w.start_tag(tag_macro_defs);
1707 for def in &krate.exported_macros {
1708 rbml_w.start_tag(tag_macro_def);
1710 encode_name(rbml_w, def.name);
1711 encode_attributes(rbml_w, &def.attrs);
1713 rbml_w.wr_tagged_str(tag_macro_def_body,
1714 &::syntax::print::pprust::tts_to_string(&def.body));
1721 fn encode_struct_field_attrs(ecx: &EncodeContext,
1722 rbml_w: &mut Encoder,
1723 krate: &hir::Crate) {
1724 struct StructFieldVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1725 ecx: &'a EncodeContext<'b, 'tcx>,
1726 rbml_w: &'a mut Encoder<'c>,
1729 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'c, 'tcx> {
1730 fn visit_struct_field(&mut self, field: &hir::StructField) {
1731 self.rbml_w.start_tag(tag_struct_field);
1732 let def_id = self.ecx.tcx.map.local_def_id(field.node.id);
1733 encode_def_id(self.rbml_w, def_id);
1734 encode_attributes(self.rbml_w, &field.node.attrs);
1735 self.rbml_w.end_tag();
1739 rbml_w.start_tag(tag_struct_fields);
1740 krate.visit_all_items(&mut StructFieldVisitor { ecx: ecx, rbml_w: rbml_w });
1746 struct ImplVisitor<'a, 'tcx:'a> {
1747 tcx: &'a ty::ctxt<'tcx>,
1748 impls: FnvHashMap<DefId, Vec<DefId>>
1751 impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> {
1752 fn visit_item(&mut self, item: &hir::Item) {
1753 if let hir::ItemImpl(..) = item.node {
1754 let impl_id = self.tcx.map.local_def_id(item.id);
1755 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
1756 self.impls.entry(trait_ref.def_id)
1764 /// Encodes an index, mapping each trait to its (local) implementations.
1765 fn encode_impls<'a>(ecx: &'a EncodeContext,
1767 rbml_w: &'a mut Encoder) {
1768 let mut visitor = ImplVisitor {
1772 krate.visit_all_items(&mut visitor);
1774 rbml_w.start_tag(tag_impls);
1775 for (trait_, trait_impls) in visitor.impls {
1776 rbml_w.start_tag(tag_impls_trait);
1777 encode_def_id(rbml_w, trait_);
1778 for impl_ in trait_impls {
1779 rbml_w.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_));
1786 fn encode_misc_info(ecx: &EncodeContext,
1788 rbml_w: &mut Encoder) {
1789 rbml_w.start_tag(tag_misc_info);
1790 rbml_w.start_tag(tag_misc_info_crate_items);
1791 for item_id in &krate.module.item_ids {
1792 rbml_w.wr_tagged_u64(tag_mod_child,
1793 def_to_u64(ecx.tcx.map.local_def_id(item_id.id)));
1795 let item = ecx.tcx.map.expect_item(item_id.id);
1796 each_auxiliary_node_id(item, |auxiliary_node_id| {
1797 rbml_w.wr_tagged_u64(tag_mod_child,
1798 def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
1803 // Encode reexports for the root module.
1804 encode_reexports(ecx, rbml_w, 0);
1810 // Encodes all reachable symbols in this crate into the metadata.
1812 // This pass is seeded off the reachability list calculated in the
1813 // middle::reachable module but filters out items that either don't have a
1814 // symbol associated with them (they weren't translated) or if they're an FFI
1815 // definition (as that's not defined in this crate).
1816 fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1817 rbml_w.start_tag(tag_reachable_ids);
1818 for &id in ecx.reachable {
1819 let def_id = ecx.tcx.map.local_def_id(id);
1820 rbml_w.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32());
1825 fn encode_crate_dep(rbml_w: &mut Encoder,
1826 dep: &cstore::crate_metadata) {
1827 rbml_w.start_tag(tag_crate_dep);
1828 rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
1829 let hash = decoder::get_crate_hash(dep.data());
1830 rbml_w.wr_tagged_str(tag_crate_dep_hash, hash.as_str());
1831 rbml_w.wr_tagged_u8(tag_crate_dep_explicitly_linked,
1832 dep.explicitly_linked.get() as u8);
1836 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1837 rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
1840 fn encode_rustc_version(rbml_w: &mut Encoder) {
1841 rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version());
1844 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1845 rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
1848 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1849 rbml_w.wr_tagged_str(tag_crate_triple, triple);
1852 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
1853 let tag = tag_dylib_dependency_formats;
1854 match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1856 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1857 let kind = match *slot {
1858 Linkage::NotLinked |
1859 Linkage::IncludedFromDylib => return None,
1860 Linkage::Dynamic => "d",
1861 Linkage::Static => "s",
1863 Some(format!("{}:{}", i + 1, kind))
1864 }).collect::<Vec<String>>();
1865 rbml_w.wr_tagged_str(tag, &s.join(","));
1868 rbml_w.wr_tagged_str(tag, "");
1873 // NB: Increment this as you change the metadata encoding version.
1874 #[allow(non_upper_case_globals)]
1875 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
1877 pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
1878 let mut wr = Cursor::new(Vec::new());
1879 encode_metadata_inner(&mut wr, parms, krate);
1881 // RBML compacts the encoded bytes whenever appropriate,
1882 // so there are some garbages left after the end of the data.
1883 let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as usize;
1884 let mut v = wr.into_inner();
1885 v.truncate(metalen);
1886 assert_eq!(v.len(), metalen);
1888 // And here we run into yet another obscure archive bug: in which metadata
1889 // loaded from archives may have trailing garbage bytes. Awhile back one of
1890 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
1891 // and opt) by having rbml generate an out-of-bounds panic when looking at
1894 // Upon investigation it turned out that the metadata file inside of an rlib
1895 // (and ar archive) was being corrupted. Some compilations would generate a
1896 // metadata file which would end in a few extra bytes, while other
1897 // compilations would not have these extra bytes appended to the end. These
1898 // extra bytes were interpreted by rbml as an extra tag, so they ended up
1899 // being interpreted causing the out-of-bounds.
1901 // The root cause of why these extra bytes were appearing was never
1902 // discovered, and in the meantime the solution we're employing is to insert
1903 // the length of the metadata to the start of the metadata. Later on this
1904 // will allow us to slice the metadata to the precise length that we just
1905 // generated regardless of trailing bytes that end up in it.
1906 let len = v.len() as u32;
1907 v.insert(0, (len >> 0) as u8);
1908 v.insert(0, (len >> 8) as u8);
1909 v.insert(0, (len >> 16) as u8);
1910 v.insert(0, (len >> 24) as u8);
1914 fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
1915 parms: EncodeParams,
1916 krate: &hir::Crate) {
1920 lang_item_bytes: u64,
1921 native_lib_bytes: u64,
1922 plugin_registrar_fn_bytes: u64,
1924 macro_defs_bytes: u64,
1933 let mut stats = Stats {
1937 native_lib_bytes: 0,
1938 plugin_registrar_fn_bytes: 0,
1940 macro_defs_bytes: 0,
1955 encode_inlined_item,
1960 let ecx = EncodeContext {
1963 reexports: reexports,
1964 item_symbols: item_symbols,
1965 link_meta: link_meta,
1967 encode_inlined_item: RefCell::new(encode_inlined_item),
1968 type_abbrevs: RefCell::new(FnvHashMap()),
1969 reachable: reachable,
1972 let mut rbml_w = Encoder::new(wr);
1974 encode_rustc_version(&mut rbml_w);
1975 encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
1976 encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
1977 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
1978 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
1980 let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
1981 encode_attributes(&mut rbml_w, &krate.attrs);
1982 stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
1984 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
1985 encode_crate_deps(&mut rbml_w, ecx.cstore);
1986 stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
1988 // Encode the language items.
1989 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
1990 encode_lang_items(&ecx, &mut rbml_w);
1991 stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
1993 // Encode the native libraries used
1994 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
1995 encode_native_libraries(&ecx, &mut rbml_w);
1996 stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
1998 // Encode the plugin registrar function
1999 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2000 encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2001 stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2004 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2005 encode_codemap(&ecx, &mut rbml_w);
2006 stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2008 // Encode macro definitions
2009 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2010 encode_macro_defs(&mut rbml_w, krate);
2011 stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2013 // Encode the def IDs of impls, for coherence checking.
2014 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2015 encode_impls(&ecx, krate, &mut rbml_w);
2016 stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2018 // Encode miscellaneous info.
2019 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2020 encode_misc_info(&ecx, krate, &mut rbml_w);
2021 encode_reachable(&ecx, &mut rbml_w);
2022 stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2024 // Encode and index the items.
2025 rbml_w.start_tag(tag_items);
2026 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2027 let index = encode_info_for_items(&ecx, &mut rbml_w);
2028 stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2031 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2032 encode_item_index(&mut rbml_w, index.items);
2033 stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2035 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2036 encode_xrefs(&ecx, &mut rbml_w, index.xrefs);
2037 stats.xref_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2039 encode_struct_field_attrs(&ecx, &mut rbml_w, krate);
2041 stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2043 if tcx.sess.meta_stats() {
2044 for e in rbml_w.writer.get_ref() {
2046 stats.zero_bytes += 1;
2050 println!("metadata stats:");
2051 println!(" attribute bytes: {}", stats.attr_bytes);
2052 println!(" dep bytes: {}", stats.dep_bytes);
2053 println!(" lang item bytes: {}", stats.lang_item_bytes);
2054 println!(" native bytes: {}", stats.native_lib_bytes);
2055 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2056 println!(" codemap bytes: {}", stats.codemap_bytes);
2057 println!(" macro def bytes: {}", stats.macro_defs_bytes);
2058 println!(" impl bytes: {}", stats.impl_bytes);
2059 println!(" misc bytes: {}", stats.misc_bytes);
2060 println!(" item bytes: {}", stats.item_bytes);
2061 println!(" index bytes: {}", stats.index_bytes);
2062 println!(" xref bytes: {}", stats.xref_bytes);
2063 println!(" zero bytes: {}", stats.zero_bytes);
2064 println!(" total bytes: {}", stats.total_bytes);
2068 // Get the encoded string for a type
2069 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec<u8> {
2070 let mut wr = Cursor::new(Vec::new());
2071 tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
2072 diag: tcx.sess.diagnostic(),
2075 abbrevs: &RefCell::new(FnvHashMap())