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, IndexEntry};
24 use metadata::inline::InlinedItemRef;
26 use middle::def_id::DefId;
27 use middle::dependency_format::Linkage;
28 use middle::stability;
29 use middle::ty::{self, Ty};
30 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
32 use serialize::Encodable;
33 use std::cell::RefCell;
34 use std::io::prelude::*;
35 use std::io::{Cursor, SeekFrom};
38 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
40 use syntax::attr::AttrMetaMethods;
41 use syntax::diagnostic::SpanHandler;
42 use syntax::parse::token::special_idents;
44 use rbml::writer::Encoder;
47 use rustc_front::visit::Visitor;
48 use rustc_front::visit;
49 use front::map::{LinkedPath, PathElem, PathElems};
50 use front::map as ast_map;
52 pub type EncodeInlinedItem<'a> =
53 Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
55 pub struct EncodeParams<'a, 'tcx: 'a> {
56 pub diag: &'a SpanHandler,
57 pub tcx: &'a ty::ctxt<'tcx>,
58 pub reexports: &'a def::ExportMap,
59 pub item_symbols: &'a RefCell<NodeMap<String>>,
60 pub link_meta: &'a LinkMeta,
61 pub cstore: &'a cstore::CStore,
62 pub encode_inlined_item: EncodeInlinedItem<'a>,
63 pub reachable: &'a NodeSet,
66 pub struct EncodeContext<'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: RefCell<EncodeInlinedItem<'a>>,
74 pub type_abbrevs: tyencode::abbrev_map<'tcx>,
75 pub reachable: &'a NodeSet,
78 impl<'a, 'tcx> EncodeContext<'a,'tcx> {
79 fn local_id(&self, def_id: DefId) -> NodeId {
80 self.tcx.map.as_local_node_id(def_id).unwrap()
84 fn encode_name(rbml_w: &mut Encoder, name: Name) {
85 rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
88 fn encode_impl_type_basename(rbml_w: &mut Encoder, name: Name) {
89 rbml_w.wr_tagged_str(tag_item_impl_type_basename, &name.as_str());
92 fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
93 rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
96 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
97 ecx: &EncodeContext<'a, 'tcx>,
98 trait_ref: ty::TraitRef<'tcx>,
100 let ty_str_ctxt = &tyencode::ctxt {
104 abbrevs: &ecx.type_abbrevs
107 rbml_w.start_tag(tag);
108 tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
112 // Item info table encoding
113 fn encode_family(rbml_w: &mut Encoder, c: char) {
114 rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8);
117 pub fn def_to_u64(did: DefId) -> u64 {
118 (did.krate as u64) << 32 | (did.xxx_node as u64)
121 pub fn def_to_string(did: DefId) -> String {
122 format!("{}:{}", did.krate, did.xxx_node)
125 fn encode_item_variances(rbml_w: &mut Encoder,
128 let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id));
129 rbml_w.start_tag(tag_item_variances);
134 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
135 ecx: &EncodeContext<'a, 'tcx>,
137 encode_bounds_and_type(rbml_w,
139 &ecx.tcx.lookup_item_type(ecx.tcx.map.local_def_id(id)),
140 &ecx.tcx.lookup_predicates(ecx.tcx.map.local_def_id(id)));
143 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
144 ecx: &EncodeContext<'a, 'tcx>,
145 scheme: &ty::TypeScheme<'tcx>,
146 predicates: &ty::GenericPredicates<'tcx>) {
147 encode_generics(rbml_w, ecx, &scheme.generics, &predicates, tag_item_generics);
148 encode_type(ecx, rbml_w, scheme.ty);
151 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
152 let id = def_to_u64(vid);
153 rbml_w.wr_tagged_u64(tag_items_data_item_variant, id);
154 rbml_w.wr_tagged_u64(tag_mod_child, id);
157 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
158 rbml_w: &mut Encoder,
159 closure_type: &ty::ClosureTy<'tcx>) {
160 let ty_str_ctxt = &tyencode::ctxt {
164 abbrevs: &ecx.type_abbrevs
166 tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
169 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
170 rbml_w: &mut Encoder,
172 let ty_str_ctxt = &tyencode::ctxt {
176 abbrevs: &ecx.type_abbrevs
178 tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
181 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
182 rbml_w: &mut Encoder,
183 trait_ref: &ty::TraitRef<'tcx>) {
184 let ty_str_ctxt = &tyencode::ctxt {
188 abbrevs: &ecx.type_abbrevs
190 tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref);
193 pub fn write_region(ecx: &EncodeContext,
194 rbml_w: &mut Encoder,
196 let ty_str_ctxt = &tyencode::ctxt {
200 abbrevs: &ecx.type_abbrevs
202 tyencode::enc_region(rbml_w, ty_str_ctxt, r);
205 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
206 rbml_w: &mut Encoder,
208 rbml_w.start_tag(tag_items_data_item_type);
209 write_type(ecx, rbml_w, typ);
213 fn encode_region(ecx: &EncodeContext,
214 rbml_w: &mut Encoder,
216 rbml_w.start_tag(tag_items_data_region);
217 write_region(ecx, rbml_w, r);
221 fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
222 rbml_w: &mut Encoder,
223 typ: &ty::BareFnTy<'tcx>) {
224 rbml_w.start_tag(tag_item_method_fty);
226 let ty_str_ctxt = &tyencode::ctxt {
230 abbrevs: &ecx.type_abbrevs
232 tyencode::enc_bare_fn_ty(rbml_w, ty_str_ctxt, typ);
237 fn encode_symbol(ecx: &EncodeContext,
238 rbml_w: &mut Encoder,
240 match ecx.item_symbols.borrow().get(&id) {
242 debug!("encode_symbol(id={}, str={})", id, *x);
243 rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
246 ecx.diag.handler().bug(
247 &format!("encode_symbol: id not found {}", id));
252 fn encode_disr_val(_: &EncodeContext,
253 rbml_w: &mut Encoder,
254 disr_val: ty::Disr) {
255 rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_string());
258 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
259 rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
262 fn encode_struct_fields(rbml_w: &mut Encoder,
263 variant: ty::VariantDef,
265 for f in &variant.fields {
266 if f.name == special_idents::unnamed_field.name {
267 rbml_w.start_tag(tag_item_unnamed_field);
269 rbml_w.start_tag(tag_item_field);
270 encode_name(rbml_w, f.name);
272 encode_struct_field_family(rbml_w, f.vis);
273 encode_def_id(rbml_w, f.did);
274 rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
279 fn encode_enum_variant_info(ecx: &EncodeContext,
280 rbml_w: &mut Encoder,
282 vis: hir::Visibility,
283 index: &mut Vec<IndexEntry>) {
284 debug!("encode_enum_variant_info(id={})", id);
286 let mut disr_val = 0;
287 let def = ecx.tcx.lookup_adt_def(ecx.tcx.map.local_def_id(id));
288 for variant in &def.variants {
289 let vid = variant.did;
290 let variant_node_id = ecx.local_id(vid);
292 if let ty::VariantKind::Dict = variant.kind() {
293 // tuple-like enum variant fields aren't really items so
294 // don't try to encode them.
295 for field in &variant.fields {
296 encode_field(ecx, rbml_w, field, index);
300 index.push(IndexEntry {
302 pos: rbml_w.mark_stable_position(),
304 rbml_w.start_tag(tag_items_data_item);
305 encode_def_id(rbml_w, vid);
306 encode_family(rbml_w, match variant.kind() {
307 ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
308 ty::VariantKind::Dict => 'V'
310 encode_name(rbml_w, variant.name);
311 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(id));
312 encode_visibility(rbml_w, vis);
314 let attrs = ecx.tcx.get_attrs(vid);
315 encode_attributes(rbml_w, &attrs);
316 encode_repr_attrs(rbml_w, ecx, &attrs);
318 let stab = stability::lookup(ecx.tcx, vid);
319 encode_stability(rbml_w, stab);
321 encode_struct_fields(rbml_w, variant, vid);
323 let specified_disr_val = variant.disr_val;
324 if specified_disr_val != disr_val {
325 encode_disr_val(ecx, rbml_w, specified_disr_val);
326 disr_val = specified_disr_val;
328 encode_bounds_and_type_for_item(rbml_w, ecx, variant_node_id);
330 ecx.tcx.map.with_path(variant_node_id, |path| encode_path(rbml_w, path));
332 disr_val = disr_val.wrapping_add(1);
336 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
337 let path = path.collect::<Vec<_>>();
338 rbml_w.start_tag(tag_path);
339 rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
341 let tag = match *pe {
342 ast_map::PathMod(_) => tag_path_elem_mod,
343 ast_map::PathName(_) => tag_path_elem_name
345 rbml_w.wr_tagged_str(tag, &pe.name().as_str());
350 fn encode_reexported_static_method(rbml_w: &mut Encoder,
352 method_def_id: DefId,
354 debug!("(encode reexported static method) {}::{}",
355 exp.name, method_name);
356 rbml_w.start_tag(tag_items_data_item_reexport);
357 rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
358 def_to_u64(method_def_id));
359 rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
360 &format!("{}::{}", exp.name,
365 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
366 rbml_w: &mut Encoder,
369 let impl_items = ecx.tcx.impl_items.borrow();
370 match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
371 Some(implementations) => {
372 for base_impl_did in implementations.iter() {
373 for &method_did in impl_items.get(base_impl_did).unwrap() {
374 let impl_item = ecx.tcx.impl_or_trait_item(method_did.def_id());
375 if let ty::MethodTraitItem(ref m) = impl_item {
376 encode_reexported_static_method(rbml_w,
390 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
391 rbml_w: &mut Encoder,
394 match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
395 Some(trait_items) => {
396 for trait_item in trait_items.iter() {
397 if let ty::MethodTraitItem(ref m) = *trait_item {
398 encode_reexported_static_method(rbml_w,
410 fn encode_reexported_static_methods(ecx: &EncodeContext,
411 rbml_w: &mut Encoder,
414 let exp_node_id = if let Some(n) = ecx.tcx.map.as_local_node_id(exp.def_id) {
417 // Before the refactor that introducd `as_local_node_id`, we
418 // were just extracting the node and checking into the
419 // ast-map. Since the node might have been from another crate,
420 // this was a tenuous thing to do at best. Anyway, I'm not
421 // 100% clear on why it's ok to ignore things from other
422 // crates, but it seems to be what we were doing pre-refactor.
427 if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp_node_id) {
428 let path_differs = ecx.tcx.map.with_path(exp_node_id, |path| {
429 let (mut a, mut b) = (path, mod_path.clone());
431 match (a.next(), b.next()) {
432 (None, None) => return true,
433 (None, _) | (_, None) => return false,
434 (Some(x), Some(y)) => if x != y { return false },
440 // We don't need to reexport static methods on items
441 // declared in the same module as our `pub use ...` since
442 // that's done when we encode the item itself.
444 // The only exception is when the reexport *changes* the
445 // name e.g. `pub use Foo = self::Bar` -- we have
446 // encoded metadata for static methods relative to Bar,
447 // but not yet for Foo.
449 if path_differs || item.name != exp.name {
450 if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
451 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
452 debug!("(encode reexported static methods) {} [trait]",
457 debug!("(encode reexported static methods) {} [base]",
464 /// Iterates through "auxiliary node IDs", which are node IDs that describe
465 /// top-level items that are sub-items of the given item. Specifically:
467 /// * For newtype structs, iterates through the node ID of the constructor.
468 fn each_auxiliary_node_id<F>(item: &hir::Item, callback: F) -> bool where
469 F: FnOnce(NodeId) -> bool,
471 let mut continue_ = true;
473 hir::ItemStruct(ref struct_def, _) => {
474 // If this is a newtype struct, return the constructor.
475 match struct_def.ctor_id {
476 Some(ctor_id) if !struct_def.fields.is_empty() &&
477 struct_def.fields[0].node.kind.is_unnamed() => {
478 continue_ = callback(ctor_id);
489 fn encode_reexports(ecx: &EncodeContext,
490 rbml_w: &mut Encoder,
493 debug!("(encoding info for module) encoding reexports for {}", id);
494 match ecx.reexports.get(&id) {
496 debug!("(encoding info for module) found reexports for {}", id);
498 debug!("(encoding info for module) reexport '{}' ({:?}) for \
503 rbml_w.start_tag(tag_items_data_item_reexport);
504 rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
505 def_to_u64(exp.def_id));
506 rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
509 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
512 None => debug!("(encoding info for module) found no reexports for {}", id),
516 fn encode_info_for_mod(ecx: &EncodeContext,
517 rbml_w: &mut Encoder,
519 attrs: &[ast::Attribute],
523 vis: hir::Visibility) {
524 rbml_w.start_tag(tag_items_data_item);
525 encode_def_id(rbml_w, ecx.tcx.map.local_def_id(id));
526 encode_family(rbml_w, 'm');
527 encode_name(rbml_w, name);
528 debug!("(encoding info for module) encoding info for module ID {}", id);
530 // Encode info about all the module children.
531 for item in &md.items {
532 rbml_w.wr_tagged_u64(tag_mod_child,
533 def_to_u64(ecx.tcx.map.local_def_id(item.id)));
535 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
536 rbml_w.wr_tagged_u64(tag_mod_child,
537 def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
541 if let hir::ItemImpl(..) = item.node {
542 let (name, did) = (item.name, item.id);
543 debug!("(encoding info for module) ... encoding impl {} ({}/{})",
545 did, ecx.tcx.map.node_to_string(did));
547 rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(ecx.tcx.map.local_def_id(did)));
551 encode_path(rbml_w, path.clone());
552 encode_visibility(rbml_w, vis);
554 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(id));
555 encode_stability(rbml_w, stab);
557 // Encode the reexports of this module, if this module is public.
558 if vis == hir::Public {
559 debug!("(encoding info for module) encoding reexports for {}", id);
560 encode_reexports(ecx, rbml_w, id, path);
562 encode_attributes(rbml_w, attrs);
567 fn encode_struct_field_family(rbml_w: &mut Encoder,
568 visibility: hir::Visibility) {
569 encode_family(rbml_w, match visibility {
571 hir::Inherited => 'N'
575 fn encode_visibility(rbml_w: &mut Encoder, visibility: hir::Visibility) {
576 let ch = match visibility {
578 hir::Inherited => 'i',
580 rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
583 fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) {
584 rbml_w.start_tag(tag_items_data_item_constness);
585 let ch = match constness {
586 hir::Constness::Const => 'c',
587 hir::Constness::NotConst => 'n',
589 rbml_w.wr_str(&ch.to_string());
593 fn encode_explicit_self(rbml_w: &mut Encoder,
594 explicit_self: &ty::ExplicitSelfCategory) {
595 let tag = tag_item_trait_method_explicit_self;
597 // Encode the base self type.
598 match *explicit_self {
599 ty::StaticExplicitSelfCategory => {
600 rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
602 ty::ByValueExplicitSelfCategory => {
603 rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
605 ty::ByBoxExplicitSelfCategory => {
606 rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
608 ty::ByReferenceExplicitSelfCategory(_, m) => {
609 // FIXME(#4846) encode custom lifetime
610 let ch = encode_mutability(m);
611 rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]);
615 fn encode_mutability(m: hir::Mutability) -> u8 {
617 hir::MutImmutable => 'i' as u8,
618 hir::MutMutable => 'm' as u8,
623 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
624 rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
627 fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
628 rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8);
631 fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
632 rbml_w: &mut Encoder,
633 field: ty::FieldDef<'tcx>,
634 global_index: &mut Vec<IndexEntry>) {
636 let id = ecx.local_id(field.did);
638 let pos = rbml_w.mark_stable_position();
639 global_index.push(IndexEntry {
643 rbml_w.start_tag(tag_items_data_item);
644 debug!("encode_field: encoding {} {}", nm, id);
645 encode_struct_field_family(rbml_w, field.vis);
646 encode_name(rbml_w, nm);
647 encode_bounds_and_type_for_item(rbml_w, ecx, id);
648 encode_def_id(rbml_w, ecx.tcx.map.local_def_id(id));
650 let stab = stability::lookup(ecx.tcx, field.did);
651 encode_stability(rbml_w, stab);
656 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
657 rbml_w: &mut Encoder,
660 index: &mut Vec<IndexEntry>,
662 index.push(IndexEntry {
664 pos: rbml_w.mark_stable_position(),
667 rbml_w.start_tag(tag_items_data_item);
668 encode_def_id(rbml_w, ecx.tcx.map.local_def_id(ctor_id));
669 encode_family(rbml_w, 'o');
670 encode_bounds_and_type_for_item(rbml_w, ecx, ctor_id);
671 encode_name(rbml_w, name);
672 ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
673 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id));
675 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
676 encode_symbol(ecx, rbml_w, ctor_id);
679 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
680 encode_stability(rbml_w, stab);
682 // indicate that this is a tuple struct ctor, because downstream users will normally want
683 // the tuple struct definition, but without this there is no way for them to tell that
684 // they actually have a ctor rather than a normal function
685 rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]);
690 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
691 ecx: &EncodeContext<'a, 'tcx>,
692 generics: &ty::Generics<'tcx>,
693 predicates: &ty::GenericPredicates<'tcx>,
696 rbml_w.start_tag(tag);
699 let ty_str_ctxt = &tyencode::ctxt {
703 abbrevs: &ecx.type_abbrevs
706 for param in &generics.types {
707 rbml_w.start_tag(tag_type_param_def);
708 tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param);
713 for param in &generics.regions {
714 rbml_w.start_tag(tag_region_param_def);
716 rbml_w.start_tag(tag_region_param_def_ident);
717 encode_name(rbml_w, param.name);
720 rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
721 def_to_u64(param.def_id));
723 rbml_w.wr_tagged_u64(tag_region_param_def_space,
724 param.space.to_uint() as u64);
726 rbml_w.wr_tagged_u64(tag_region_param_def_index,
729 for &bound_region in ¶m.bounds {
730 encode_region(ecx, rbml_w, bound_region);
736 encode_predicates_in_current_doc(rbml_w, ecx, predicates);
741 fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
742 ecx: &EncodeContext<'a,'tcx>,
743 predicates: &ty::GenericPredicates<'tcx>)
745 let ty_str_ctxt = &tyencode::ctxt {
749 abbrevs: &ecx.type_abbrevs
752 for (space, _, predicate) in predicates.predicates.iter_enumerated() {
753 rbml_w.start_tag(tag_predicate);
755 rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
757 rbml_w.start_tag(tag_predicate_data);
758 tyencode::enc_predicate(rbml_w, ty_str_ctxt, predicate);
765 fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
766 ecx: &EncodeContext<'a,'tcx>,
767 predicates: &ty::GenericPredicates<'tcx>,
770 rbml_w.start_tag(tag);
771 encode_predicates_in_current_doc(rbml_w, ecx, predicates);
775 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
776 rbml_w: &mut Encoder,
777 method_ty: &ty::Method<'tcx>) {
778 encode_def_id(rbml_w, method_ty.def_id);
779 encode_name(rbml_w, method_ty.name);
780 encode_generics(rbml_w, ecx, &method_ty.generics, &method_ty.predicates,
781 tag_method_ty_generics);
782 encode_method_fty(ecx, rbml_w, &method_ty.fty);
783 encode_visibility(rbml_w, method_ty.vis);
784 encode_explicit_self(rbml_w, &method_ty.explicit_self);
785 match method_ty.explicit_self {
786 ty::StaticExplicitSelfCategory => {
787 encode_family(rbml_w, STATIC_METHOD_FAMILY);
789 _ => encode_family(rbml_w, METHOD_FAMILY)
793 fn encode_info_for_associated_const(ecx: &EncodeContext,
794 rbml_w: &mut Encoder,
795 associated_const: &ty::AssociatedConst,
796 impl_path: PathElems,
798 impl_item_opt: Option<&hir::ImplItem>) {
799 debug!("encode_info_for_associated_const({:?},{:?})",
800 associated_const.def_id,
801 associated_const.name);
803 rbml_w.start_tag(tag_items_data_item);
805 encode_def_id(rbml_w, associated_const.def_id);
806 encode_name(rbml_w, associated_const.name);
807 encode_visibility(rbml_w, associated_const.vis);
808 encode_family(rbml_w, 'C');
810 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
811 encode_item_sort(rbml_w, 'C');
813 encode_bounds_and_type_for_item(rbml_w, ecx, ecx.local_id(associated_const.def_id));
815 let stab = stability::lookup(ecx.tcx, associated_const.def_id);
816 encode_stability(rbml_w, stab);
818 let elem = ast_map::PathName(associated_const.name);
819 encode_path(rbml_w, impl_path.chain(Some(elem)));
821 if let Some(ii) = impl_item_opt {
822 encode_attributes(rbml_w, &ii.attrs);
823 encode_inlined_item(ecx,
825 InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
832 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
833 rbml_w: &mut Encoder,
834 m: &ty::Method<'tcx>,
835 impl_path: PathElems,
836 is_default_impl: bool,
838 impl_item_opt: Option<&hir::ImplItem>) {
840 debug!("encode_info_for_method: {:?} {:?}", m.def_id,
842 rbml_w.start_tag(tag_items_data_item);
844 encode_method_ty_fields(ecx, rbml_w, m);
845 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
846 encode_item_sort(rbml_w, 'r');
848 let stab = stability::lookup(ecx.tcx, m.def_id);
849 encode_stability(rbml_w, stab);
851 // The type for methods gets encoded twice, which is unfortunate.
852 let m_node_id = ecx.local_id(m.def_id);
853 encode_bounds_and_type_for_item(rbml_w, ecx, m_node_id);
855 let elem = ast_map::PathName(m.name);
856 encode_path(rbml_w, impl_path.chain(Some(elem)));
857 if let Some(impl_item) = impl_item_opt {
858 if let hir::MethodImplItem(ref sig, _) = impl_item.node {
859 encode_attributes(rbml_w, &impl_item.attrs);
860 let scheme = ecx.tcx.lookup_item_type(m.def_id);
861 let any_types = !scheme.generics.types.is_empty();
862 let needs_inline = any_types || is_default_impl ||
863 attr::requests_inline(&impl_item.attrs);
864 if needs_inline || sig.constness == hir::Constness::Const {
865 encode_inlined_item(ecx,
867 InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
870 encode_constness(rbml_w, sig.constness);
872 let m_id = ecx.local_id(m.def_id);
873 encode_symbol(ecx, rbml_w, m_id);
875 encode_method_argument_names(rbml_w, &sig.decl);
882 fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
883 rbml_w: &mut Encoder,
884 associated_type: &ty::AssociatedType<'tcx>,
885 impl_path: PathElems,
887 impl_item_opt: Option<&hir::ImplItem>) {
888 debug!("encode_info_for_associated_type({:?},{:?})",
889 associated_type.def_id,
890 associated_type.name);
892 rbml_w.start_tag(tag_items_data_item);
894 encode_def_id(rbml_w, associated_type.def_id);
895 encode_name(rbml_w, associated_type.name);
896 encode_visibility(rbml_w, associated_type.vis);
897 encode_family(rbml_w, 'y');
898 encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
899 encode_item_sort(rbml_w, 't');
901 let stab = stability::lookup(ecx.tcx, associated_type.def_id);
902 encode_stability(rbml_w, stab);
904 let elem = ast_map::PathName(associated_type.name);
905 encode_path(rbml_w, impl_path.chain(Some(elem)));
907 if let Some(ii) = impl_item_opt {
908 encode_attributes(rbml_w, &ii.attrs);
910 encode_predicates(rbml_w, ecx,
911 &ecx.tcx.lookup_predicates(associated_type.def_id),
915 if let Some(ty) = associated_type.ty {
916 encode_type(ecx, rbml_w, ty);
922 fn encode_method_argument_names(rbml_w: &mut Encoder,
923 decl: &hir::FnDecl) {
924 rbml_w.start_tag(tag_method_argument_names);
925 for arg in &decl.inputs {
926 let tag = tag_method_argument_name;
927 if let hir::PatIdent(_, ref path1, _) = arg.pat.node {
928 let name = path1.node.name.as_str();
929 rbml_w.wr_tagged_bytes(tag, name.as_bytes());
931 rbml_w.wr_tagged_bytes(tag, &[]);
937 fn encode_repr_attrs(rbml_w: &mut Encoder,
939 attrs: &[ast::Attribute]) {
940 let mut repr_attrs = Vec::new();
942 repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
945 rbml_w.start_tag(tag_items_data_item_repr);
946 repr_attrs.encode(rbml_w);
950 fn encode_inlined_item(ecx: &EncodeContext,
951 rbml_w: &mut Encoder,
952 ii: InlinedItemRef) {
953 let mut eii = ecx.encode_inlined_item.borrow_mut();
954 let eii: &mut EncodeInlinedItem = &mut *eii;
958 const FN_FAMILY: char = 'f';
959 const STATIC_METHOD_FAMILY: char = 'F';
960 const METHOD_FAMILY: char = 'h';
962 // Encodes the inherent implementations of a structure, enumeration, or trait.
963 fn encode_inherent_implementations(ecx: &EncodeContext,
964 rbml_w: &mut Encoder,
966 match ecx.tcx.inherent_impls.borrow().get(&def_id) {
968 Some(implementations) => {
969 for &impl_def_id in implementations.iter() {
970 rbml_w.start_tag(tag_items_data_item_inherent_impl);
971 encode_def_id(rbml_w, impl_def_id);
978 // Encodes the implementations of a trait defined in this crate.
979 fn encode_extension_implementations(ecx: &EncodeContext,
980 rbml_w: &mut Encoder,
981 trait_def_id: DefId) {
982 assert!(trait_def_id.is_local());
983 let def = ecx.tcx.lookup_trait_def(trait_def_id);
985 def.for_each_impl(ecx.tcx, |impl_def_id| {
986 rbml_w.start_tag(tag_items_data_item_extension_impl);
987 encode_def_id(rbml_w, impl_def_id);
992 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
993 stab_opt.map(|stab| {
994 rbml_w.start_tag(tag_items_data_item_stability);
995 stab.encode(rbml_w).unwrap();
1000 fn encode_info_for_item(ecx: &EncodeContext,
1001 rbml_w: &mut Encoder,
1003 index: &mut Vec<IndexEntry>,
1005 vis: hir::Visibility) {
1008 fn add_to_index(item: &hir::Item, rbml_w: &mut Encoder,
1009 index: &mut Vec<IndexEntry>) {
1010 index.push(IndexEntry {
1012 pos: rbml_w.mark_stable_position(),
1016 debug!("encoding info for item at {}",
1017 tcx.sess.codemap().span_to_string(item.span));
1019 let def_id = ecx.tcx.map.local_def_id(item.id);
1020 let stab = stability::lookup(tcx, ecx.tcx.map.local_def_id(item.id));
1023 hir::ItemStatic(_, m, _) => {
1024 add_to_index(item, rbml_w, index);
1025 rbml_w.start_tag(tag_items_data_item);
1026 encode_def_id(rbml_w, def_id);
1027 if m == hir::MutMutable {
1028 encode_family(rbml_w, 'b');
1030 encode_family(rbml_w, 'c');
1032 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1033 encode_symbol(ecx, rbml_w, item.id);
1034 encode_name(rbml_w, item.name);
1035 encode_path(rbml_w, path);
1036 encode_visibility(rbml_w, vis);
1037 encode_stability(rbml_w, stab);
1038 encode_attributes(rbml_w, &item.attrs);
1041 hir::ItemConst(_, _) => {
1042 add_to_index(item, rbml_w, index);
1043 rbml_w.start_tag(tag_items_data_item);
1044 encode_def_id(rbml_w, def_id);
1045 encode_family(rbml_w, 'C');
1046 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1047 encode_name(rbml_w, item.name);
1048 encode_path(rbml_w, path);
1049 encode_attributes(rbml_w, &item.attrs);
1050 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1051 encode_visibility(rbml_w, vis);
1052 encode_stability(rbml_w, stab);
1055 hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
1056 add_to_index(item, rbml_w, index);
1057 rbml_w.start_tag(tag_items_data_item);
1058 encode_def_id(rbml_w, def_id);
1059 encode_family(rbml_w, FN_FAMILY);
1060 let tps_len = generics.ty_params.len();
1061 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1062 encode_name(rbml_w, item.name);
1063 encode_path(rbml_w, path);
1064 encode_attributes(rbml_w, &item.attrs);
1065 let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
1066 if needs_inline || constness == hir::Constness::Const {
1067 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1070 encode_symbol(ecx, rbml_w, item.id);
1072 encode_constness(rbml_w, constness);
1073 encode_visibility(rbml_w, vis);
1074 encode_stability(rbml_w, stab);
1075 encode_method_argument_names(rbml_w, &**decl);
1078 hir::ItemMod(ref m) => {
1079 add_to_index(item, rbml_w, index);
1080 encode_info_for_mod(ecx,
1089 hir::ItemForeignMod(ref fm) => {
1090 add_to_index(item, rbml_w, index);
1091 rbml_w.start_tag(tag_items_data_item);
1092 encode_def_id(rbml_w, def_id);
1093 encode_family(rbml_w, 'n');
1094 encode_name(rbml_w, item.name);
1095 encode_path(rbml_w, path);
1097 // Encode all the items in this module.
1098 for foreign_item in &fm.items {
1099 rbml_w.wr_tagged_u64(tag_mod_child,
1100 def_to_u64(ecx.tcx.map.local_def_id(foreign_item.id)));
1102 encode_visibility(rbml_w, vis);
1103 encode_stability(rbml_w, stab);
1106 hir::ItemTy(..) => {
1107 add_to_index(item, rbml_w, index);
1108 rbml_w.start_tag(tag_items_data_item);
1109 encode_def_id(rbml_w, def_id);
1110 encode_family(rbml_w, 'y');
1111 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1112 encode_name(rbml_w, item.name);
1113 encode_path(rbml_w, path);
1114 encode_visibility(rbml_w, vis);
1115 encode_stability(rbml_w, stab);
1118 hir::ItemEnum(ref enum_definition, _) => {
1119 add_to_index(item, rbml_w, index);
1121 rbml_w.start_tag(tag_items_data_item);
1122 encode_def_id(rbml_w, def_id);
1123 encode_family(rbml_w, 't');
1124 encode_item_variances(rbml_w, ecx, item.id);
1125 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1126 encode_name(rbml_w, item.name);
1127 encode_attributes(rbml_w, &item.attrs);
1128 encode_repr_attrs(rbml_w, ecx, &item.attrs);
1129 for v in &enum_definition.variants {
1130 encode_variant_id(rbml_w, ecx.tcx.map.local_def_id(v.node.id));
1132 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1133 encode_path(rbml_w, path);
1135 // Encode inherent implementations for this enumeration.
1136 encode_inherent_implementations(ecx, rbml_w, def_id);
1138 encode_visibility(rbml_w, vis);
1139 encode_stability(rbml_w, stab);
1142 encode_enum_variant_info(ecx,
1148 hir::ItemStruct(ref struct_def, _) => {
1149 let def = ecx.tcx.lookup_adt_def(def_id);
1150 let variant = def.struct_variant();
1152 for field in &variant.fields {
1153 encode_field(ecx, rbml_w, field, index);
1156 /* Index the class*/
1157 add_to_index(item, rbml_w, index);
1159 /* Now, make an item for the class itself */
1160 rbml_w.start_tag(tag_items_data_item);
1161 encode_def_id(rbml_w, def_id);
1162 encode_family(rbml_w, 'S');
1163 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1165 encode_item_variances(rbml_w, ecx, item.id);
1166 encode_name(rbml_w, item.name);
1167 encode_attributes(rbml_w, &item.attrs);
1168 encode_path(rbml_w, path.clone());
1169 encode_stability(rbml_w, stab);
1170 encode_visibility(rbml_w, vis);
1171 encode_repr_attrs(rbml_w, ecx, &item.attrs);
1173 /* Encode def_ids for each field and method
1174 for methods, write all the stuff get_trait_method
1176 encode_struct_fields(rbml_w, variant, def_id);
1178 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
1180 // Encode inherent implementations for this structure.
1181 encode_inherent_implementations(ecx, rbml_w, def_id);
1185 // If this is a tuple-like struct, encode the type of the constructor.
1186 match struct_def.ctor_id {
1188 encode_info_for_struct_ctor(ecx, rbml_w, item.name,
1189 ctor_id, index, item.id);
1194 hir::ItemDefaultImpl(unsafety, _) => {
1195 add_to_index(item, rbml_w, index);
1196 rbml_w.start_tag(tag_items_data_item);
1197 encode_def_id(rbml_w, def_id);
1198 encode_family(rbml_w, 'd');
1199 encode_name(rbml_w, item.name);
1200 encode_unsafety(rbml_w, unsafety);
1202 let trait_ref = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)).unwrap();
1203 encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1206 hir::ItemImpl(unsafety, polarity, _, _, ref ty, ref ast_items) => {
1207 // We need to encode information about the default methods we
1208 // have inherited, so we drive this based on the impl structure.
1209 let impl_items = tcx.impl_items.borrow();
1210 let items = impl_items.get(&def_id).unwrap();
1212 add_to_index(item, rbml_w, index);
1213 rbml_w.start_tag(tag_items_data_item);
1214 encode_def_id(rbml_w, def_id);
1215 encode_family(rbml_w, 'i');
1216 encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
1217 encode_name(rbml_w, item.name);
1218 encode_attributes(rbml_w, &item.attrs);
1219 encode_unsafety(rbml_w, unsafety);
1220 encode_polarity(rbml_w, polarity);
1222 match tcx.custom_coerce_unsized_kinds.borrow().get(&ecx.tcx.map.local_def_id(item.id)) {
1224 rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1225 kind.encode(rbml_w);
1232 hir::TyPath(None, ref path) if path.segments.len() == 1 => {
1233 let name = path.segments.last().unwrap().identifier.name;
1234 encode_impl_type_basename(rbml_w, name);
1238 for &item_def_id in items {
1239 rbml_w.start_tag(tag_item_impl_item);
1241 ty::ConstTraitItemId(item_def_id) => {
1242 encode_def_id(rbml_w, item_def_id);
1243 encode_item_sort(rbml_w, 'C');
1245 ty::MethodTraitItemId(item_def_id) => {
1246 encode_def_id(rbml_w, item_def_id);
1247 encode_item_sort(rbml_w, 'r');
1249 ty::TypeTraitItemId(item_def_id) => {
1250 encode_def_id(rbml_w, item_def_id);
1251 encode_item_sort(rbml_w, 't');
1256 if let Some(trait_ref) = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)) {
1257 encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
1259 encode_path(rbml_w, path.clone());
1260 encode_stability(rbml_w, stab);
1263 // Iterate down the trait items, emitting them. We rely on the
1264 // assumption that all of the actually implemented trait items
1265 // appear first in the impl structure, in the same order they do
1266 // in the ast. This is a little sketchy.
1267 let num_implemented_methods = ast_items.len();
1268 for (i, &trait_item_def_id) in items.iter().enumerate() {
1269 let ast_item = if i < num_implemented_methods {
1270 Some(&*ast_items[i])
1275 index.push(IndexEntry {
1276 node: trait_item_def_id.def_id().xxx_node,
1277 pos: rbml_w.mark_stable_position(),
1280 match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
1281 ty::ConstTraitItem(ref associated_const) => {
1282 encode_info_for_associated_const(ecx,
1289 ty::MethodTraitItem(ref method_type) => {
1290 encode_info_for_method(ecx,
1298 ty::TypeTraitItem(ref associated_type) => {
1299 encode_info_for_associated_type(ecx,
1309 hir::ItemTrait(_, _, _, ref ms) => {
1310 add_to_index(item, rbml_w, index);
1311 rbml_w.start_tag(tag_items_data_item);
1312 encode_def_id(rbml_w, def_id);
1313 encode_family(rbml_w, 'I');
1314 encode_item_variances(rbml_w, ecx, item.id);
1315 let trait_def = tcx.lookup_trait_def(def_id);
1316 let trait_predicates = tcx.lookup_predicates(def_id);
1317 encode_unsafety(rbml_w, trait_def.unsafety);
1318 encode_paren_sugar(rbml_w, trait_def.paren_sugar);
1319 encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
1320 encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
1321 encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates,
1323 encode_predicates(rbml_w, ecx, &tcx.lookup_super_predicates(def_id),
1324 tag_item_super_predicates);
1325 encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1326 encode_name(rbml_w, item.name);
1327 encode_attributes(rbml_w, &item.attrs);
1328 encode_visibility(rbml_w, vis);
1329 encode_stability(rbml_w, stab);
1330 for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
1331 rbml_w.start_tag(tag_item_trait_item);
1332 match method_def_id {
1333 ty::ConstTraitItemId(const_def_id) => {
1334 encode_def_id(rbml_w, const_def_id);
1335 encode_item_sort(rbml_w, 'C');
1337 ty::MethodTraitItemId(method_def_id) => {
1338 encode_def_id(rbml_w, method_def_id);
1339 encode_item_sort(rbml_w, 'r');
1341 ty::TypeTraitItemId(type_def_id) => {
1342 encode_def_id(rbml_w, type_def_id);
1343 encode_item_sort(rbml_w, 't');
1348 rbml_w.wr_tagged_u64(tag_mod_child,
1349 def_to_u64(method_def_id.def_id()));
1351 encode_path(rbml_w, path.clone());
1353 // Encode the implementations of this trait.
1354 encode_extension_implementations(ecx, rbml_w, def_id);
1356 // Encode inherent implementations for this trait.
1357 encode_inherent_implementations(ecx, rbml_w, def_id);
1361 // Now output the trait item info for each trait item.
1362 let r = tcx.trait_item_def_ids(def_id);
1363 for (i, &item_def_id) in r.iter().enumerate() {
1364 assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
1366 index.push(IndexEntry {
1367 node: item_def_id.def_id().xxx_node,
1368 pos: rbml_w.mark_stable_position(),
1371 rbml_w.start_tag(tag_items_data_item);
1373 encode_parent_item(rbml_w, def_id);
1375 let stab = stability::lookup(tcx, item_def_id.def_id());
1376 encode_stability(rbml_w, stab);
1378 let trait_item_type =
1379 tcx.impl_or_trait_item(item_def_id.def_id());
1380 let is_nonstatic_method;
1381 match trait_item_type {
1382 ty::ConstTraitItem(associated_const) => {
1383 encode_name(rbml_w, associated_const.name);
1384 encode_def_id(rbml_w, associated_const.def_id);
1385 encode_visibility(rbml_w, associated_const.vis);
1387 let elem = ast_map::PathName(associated_const.name);
1389 path.clone().chain(Some(elem)));
1391 encode_family(rbml_w, 'C');
1393 encode_bounds_and_type_for_item(rbml_w,
1395 ecx.local_id(associated_const.def_id));
1397 is_nonstatic_method = false;
1399 ty::MethodTraitItem(method_ty) => {
1400 let method_def_id = item_def_id.def_id();
1402 encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1404 let elem = ast_map::PathName(method_ty.name);
1406 path.clone().chain(Some(elem)));
1408 match method_ty.explicit_self {
1409 ty::StaticExplicitSelfCategory => {
1410 encode_family(rbml_w,
1411 STATIC_METHOD_FAMILY);
1414 encode_family(rbml_w,
1418 encode_bounds_and_type_for_item(rbml_w, ecx, ecx.local_id(method_def_id));
1420 is_nonstatic_method = method_ty.explicit_self !=
1421 ty::StaticExplicitSelfCategory;
1423 ty::TypeTraitItem(associated_type) => {
1424 encode_name(rbml_w, associated_type.name);
1425 encode_def_id(rbml_w, associated_type.def_id);
1427 let elem = ast_map::PathName(associated_type.name);
1429 path.clone().chain(Some(elem)));
1431 encode_item_sort(rbml_w, 't');
1432 encode_family(rbml_w, 'y');
1434 if let Some(ty) = associated_type.ty {
1435 encode_type(ecx, rbml_w, ty);
1438 is_nonstatic_method = false;
1442 encode_parent_sort(rbml_w, 't');
1444 let trait_item = &*ms[i];
1445 encode_attributes(rbml_w, &trait_item.attrs);
1446 match trait_item.node {
1447 hir::ConstTraitItem(_, ref default) => {
1448 if default.is_some() {
1449 encode_item_sort(rbml_w, 'C');
1451 encode_item_sort(rbml_w, 'c');
1454 encode_inlined_item(ecx, rbml_w,
1455 InlinedItemRef::TraitItem(def_id, trait_item));
1457 hir::MethodTraitItem(ref sig, ref body) => {
1458 // If this is a static method, we've already
1460 if is_nonstatic_method {
1461 // FIXME: I feel like there is something funny
1463 encode_bounds_and_type_for_item(
1466 ecx.local_id(item_def_id.def_id()));
1470 encode_item_sort(rbml_w, 'p');
1471 encode_inlined_item(ecx, rbml_w,
1472 InlinedItemRef::TraitItem(def_id, trait_item));
1474 encode_item_sort(rbml_w, 'r');
1476 encode_method_argument_names(rbml_w, &sig.decl);
1479 hir::TypeTraitItem(..) => {}
1485 hir::ItemExternCrate(_) | hir::ItemUse(_) => {
1486 // these are encoded separately
1491 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1492 rbml_w: &mut Encoder,
1493 nitem: &hir::ForeignItem,
1494 index: &mut Vec<IndexEntry>,
1497 index.push(IndexEntry {
1499 pos: rbml_w.mark_stable_position(),
1502 rbml_w.start_tag(tag_items_data_item);
1503 encode_def_id(rbml_w, ecx.tcx.map.local_def_id(nitem.id));
1504 encode_visibility(rbml_w, nitem.vis);
1506 hir::ForeignItemFn(ref fndecl, _) => {
1507 encode_family(rbml_w, FN_FAMILY);
1508 encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
1509 encode_name(rbml_w, nitem.name);
1510 if abi == abi::RustIntrinsic || abi == abi::PlatformIntrinsic {
1511 encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
1513 encode_attributes(rbml_w, &*nitem.attrs);
1514 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1515 encode_stability(rbml_w, stab);
1516 encode_symbol(ecx, rbml_w, nitem.id);
1517 encode_method_argument_names(rbml_w, &*fndecl);
1519 hir::ForeignItemStatic(_, mutbl) => {
1521 encode_family(rbml_w, 'b');
1523 encode_family(rbml_w, 'c');
1525 encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
1526 encode_attributes(rbml_w, &*nitem.attrs);
1527 let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
1528 encode_stability(rbml_w, stab);
1529 encode_symbol(ecx, rbml_w, nitem.id);
1530 encode_name(rbml_w, nitem.name);
1533 encode_path(rbml_w, path);
1537 fn my_visit_expr(_e: &hir::Expr) { }
1539 fn my_visit_item(i: &hir::Item,
1540 rbml_w: &mut Encoder,
1541 ecx: &EncodeContext,
1542 index: &mut Vec<IndexEntry>) {
1543 ecx.tcx.map.with_path(i.id, |path| {
1544 encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1548 fn my_visit_foreign_item(ni: &hir::ForeignItem,
1549 rbml_w: &mut Encoder,
1550 ecx: &EncodeContext,
1551 index: &mut Vec<IndexEntry>) {
1552 debug!("writing foreign item {}::{}",
1553 ecx.tcx.map.path_to_string(ni.id),
1556 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1557 ecx.tcx.map.with_path(ni.id, |path| {
1558 encode_info_for_foreign_item(ecx, rbml_w,
1564 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1565 rbml_w_for_visit_item: &'a mut Encoder<'b>,
1566 ecx: &'a EncodeContext<'c,'tcx>,
1567 index: &'a mut Vec<IndexEntry>,
1570 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1571 fn visit_expr(&mut self, ex: &hir::Expr) {
1572 visit::walk_expr(self, ex);
1575 fn visit_item(&mut self, i: &hir::Item) {
1576 visit::walk_item(self, i);
1578 self.rbml_w_for_visit_item,
1582 fn visit_foreign_item(&mut self, ni: &hir::ForeignItem) {
1583 visit::walk_foreign_item(self, ni);
1584 my_visit_foreign_item(ni,
1585 self.rbml_w_for_visit_item,
1591 fn encode_info_for_items(ecx: &EncodeContext,
1592 rbml_w: &mut Encoder,
1594 -> Vec<IndexEntry> {
1595 let mut index = Vec::new();
1596 rbml_w.start_tag(tag_items_data);
1597 index.push(IndexEntry {
1598 node: CRATE_NODE_ID,
1599 pos: rbml_w.mark_stable_position(),
1601 encode_info_for_mod(ecx,
1606 [].iter().cloned().chain(LinkedPath::empty()),
1607 syntax::parse::token::special_idents::invalid.name,
1610 visit::walk_crate(&mut EncodeVisitor {
1613 rbml_w_for_visit_item: &mut *rbml_w,
1623 fn encode_index(rbml_w: &mut Encoder, index: Vec<IndexEntry>)
1625 rbml_w.start_tag(tag_index);
1626 index::write_index(index, rbml_w.writer);
1630 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1632 ast::MetaWord(ref name) => {
1633 rbml_w.start_tag(tag_meta_item_word);
1634 rbml_w.wr_tagged_str(tag_meta_item_name, name);
1637 ast::MetaNameValue(ref name, ref value) => {
1639 ast::LitStr(ref value, _) => {
1640 rbml_w.start_tag(tag_meta_item_name_value);
1641 rbml_w.wr_tagged_str(tag_meta_item_name, name);
1642 rbml_w.wr_tagged_str(tag_meta_item_value, value);
1645 _ => {/* FIXME (#623): encode other variants */ }
1648 ast::MetaList(ref name, ref items) => {
1649 rbml_w.start_tag(tag_meta_item_list);
1650 rbml_w.wr_tagged_str(tag_meta_item_name, name);
1651 for inner_item in items {
1652 encode_meta_item(rbml_w, &**inner_item);
1659 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1660 rbml_w.start_tag(tag_attributes);
1662 rbml_w.start_tag(tag_attribute);
1663 rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1664 encode_meta_item(rbml_w, &*attr.node.value);
1670 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: hir::Unsafety) {
1671 let byte: u8 = match unsafety {
1672 hir::Unsafety::Normal => 0,
1673 hir::Unsafety::Unsafe => 1,
1675 rbml_w.wr_tagged_u8(tag_unsafety, byte);
1678 fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) {
1679 let byte: u8 = if paren_sugar {1} else {0};
1680 rbml_w.wr_tagged_u8(tag_paren_sugar, byte);
1683 fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) {
1684 let byte: u8 = if is_defaulted {1} else {0};
1685 rbml_w.wr_tagged_u8(tag_defaulted_trait, byte);
1688 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) {
1689 rbml_w.start_tag(tag_associated_type_names);
1690 for &name in names {
1691 rbml_w.wr_tagged_str(tag_associated_type_name, &name.as_str());
1696 fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
1697 let byte: u8 = match polarity {
1698 hir::ImplPolarity::Positive => 0,
1699 hir::ImplPolarity::Negative => 1,
1701 rbml_w.wr_tagged_u8(tag_polarity, byte);
1704 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1705 fn get_ordered_deps(cstore: &cstore::CStore)
1706 -> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
1707 // Pull the cnums and name,vers,hash out of cstore
1708 let mut deps = Vec::new();
1709 cstore.iter_crate_data(|cnum, val| {
1710 deps.push((cnum, val.clone()));
1714 deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0));
1716 // Sanity-check the crate numbers
1717 let mut expected_cnum = 1;
1718 for &(n, _) in &deps {
1719 assert_eq!(n, expected_cnum);
1726 // We're just going to write a list of crate 'name-hash-version's, with
1727 // the assumption that they are numbered 1 to n.
1728 // FIXME (#2166): This is not nearly enough to support correct versioning
1729 // but is enough to get transitive crate dependencies working.
1730 rbml_w.start_tag(tag_crate_deps);
1731 for (_cnum, dep) in get_ordered_deps(cstore) {
1732 encode_crate_dep(rbml_w, &dep);
1737 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1738 rbml_w.start_tag(tag_lang_items);
1740 for (i, &def_id) in ecx.tcx.lang_items.items() {
1741 if let Some(id) = def_id {
1742 if let Some(id) = ecx.tcx.map.as_local_node_id(id) {
1743 rbml_w.start_tag(tag_lang_items_item);
1744 rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
1745 rbml_w.wr_tagged_u32(tag_lang_items_item_node_id, id as u32);
1751 for i in &ecx.tcx.lang_items.missing {
1752 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1755 rbml_w.end_tag(); // tag_lang_items
1758 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1759 rbml_w.start_tag(tag_native_libraries);
1761 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1764 cstore::NativeStatic => {} // these libraries are not propagated
1765 cstore::NativeFramework | cstore::NativeUnknown => {
1766 rbml_w.start_tag(tag_native_libraries_lib);
1767 rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32);
1768 rbml_w.wr_tagged_str(tag_native_libraries_name, lib);
1777 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1778 match ecx.tcx.sess.plugin_registrar_fn.get() {
1779 Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1784 fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1785 rbml_w.start_tag(tag_codemap);
1786 let codemap = ecx.tcx.sess.codemap();
1788 for filemap in &codemap.files.borrow()[..] {
1790 if filemap.lines.borrow().is_empty() || filemap.is_imported() {
1791 // No need to export empty filemaps, as they can't contain spans
1792 // that need translation.
1793 // Also no need to re-export imported filemaps, as any downstream
1794 // crate will import them from their original source.
1798 rbml_w.start_tag(tag_codemap_filemap);
1799 filemap.encode(rbml_w);
1806 /// Serialize the text of the exported macros
1807 fn encode_macro_defs(rbml_w: &mut Encoder,
1808 krate: &hir::Crate) {
1809 rbml_w.start_tag(tag_macro_defs);
1810 for def in &krate.exported_macros {
1811 rbml_w.start_tag(tag_macro_def);
1813 encode_name(rbml_w, def.name);
1814 encode_attributes(rbml_w, &def.attrs);
1816 rbml_w.wr_tagged_str(tag_macro_def_body,
1817 &::syntax::print::pprust::tts_to_string(&def.body));
1824 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &hir::Crate) {
1825 struct StructFieldVisitor<'a, 'b:'a> {
1826 rbml_w: &'a mut Encoder<'b>,
1829 impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1830 fn visit_struct_field(&mut self, field: &hir::StructField) {
1831 self.rbml_w.start_tag(tag_struct_field);
1832 self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1833 encode_attributes(self.rbml_w, &field.node.attrs);
1834 self.rbml_w.end_tag();
1838 rbml_w.start_tag(tag_struct_fields);
1839 visit::walk_crate(&mut StructFieldVisitor {
1847 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1848 ecx: &'a EncodeContext<'b, 'tcx>,
1849 rbml_w: &'a mut Encoder<'c>,
1852 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1853 fn visit_item(&mut self, item: &hir::Item) {
1854 if let hir::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
1855 let def_id = self.ecx.tcx.def_map.borrow().get(&trait_ref.ref_id).unwrap().def_id();
1857 // Load eagerly if this is an implementation of the Drop trait
1858 // or if the trait is not defined in this crate.
1859 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1860 def_id.krate != LOCAL_CRATE {
1861 self.rbml_w.start_tag(tag_impls_impl);
1862 encode_def_id(self.rbml_w, self.ecx.tcx.map.local_def_id(item.id));
1863 self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
1864 self.rbml_w.end_tag();
1867 visit::walk_item(self, item);
1871 /// Encodes implementations that are eagerly loaded.
1873 /// None of this is necessary in theory; we can load all implementations
1874 /// lazily. However, in two cases the optimizations to lazily load
1875 /// implementations are not yet implemented. These two cases, which require us
1876 /// to load implementations eagerly, are:
1878 /// * Destructors (implementations of the Drop trait).
1880 /// * Implementations of traits not defined in this crate.
1881 fn encode_impls<'a>(ecx: &'a EncodeContext,
1883 rbml_w: &'a mut Encoder) {
1884 rbml_w.start_tag(tag_impls);
1887 let mut visitor = ImplVisitor {
1891 visit::walk_crate(&mut visitor, krate);
1897 fn encode_misc_info(ecx: &EncodeContext,
1899 rbml_w: &mut Encoder) {
1900 rbml_w.start_tag(tag_misc_info);
1901 rbml_w.start_tag(tag_misc_info_crate_items);
1902 for item in &krate.module.items {
1903 rbml_w.wr_tagged_u64(tag_mod_child,
1904 def_to_u64(ecx.tcx.map.local_def_id(item.id)));
1906 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1907 rbml_w.wr_tagged_u64(tag_mod_child,
1908 def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
1913 // Encode reexports for the root module.
1914 encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(LinkedPath::empty()));
1920 // Encodes all reachable symbols in this crate into the metadata.
1922 // This pass is seeded off the reachability list calculated in the
1923 // middle::reachable module but filters out items that either don't have a
1924 // symbol associated with them (they weren't translated) or if they're an FFI
1925 // definition (as that's not defined in this crate).
1926 fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1927 rbml_w.start_tag(tag_reachable_ids);
1928 for id in ecx.reachable {
1929 rbml_w.wr_tagged_u32(tag_reachable_id, *id);
1934 fn encode_crate_dep(rbml_w: &mut Encoder,
1935 dep: &cstore::crate_metadata) {
1936 rbml_w.start_tag(tag_crate_dep);
1937 rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
1938 let hash = decoder::get_crate_hash(dep.data());
1939 rbml_w.wr_tagged_str(tag_crate_dep_hash, hash.as_str());
1940 rbml_w.wr_tagged_u8(tag_crate_dep_explicitly_linked,
1941 dep.explicitly_linked.get() as u8);
1945 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1946 rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
1949 fn encode_rustc_version(rbml_w: &mut Encoder) {
1950 rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version());
1953 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
1954 rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
1957 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
1958 rbml_w.wr_tagged_str(tag_crate_triple, triple);
1961 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
1962 let tag = tag_dylib_dependency_formats;
1963 match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1965 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1966 let kind = match *slot {
1967 Linkage::NotLinked |
1968 Linkage::IncludedFromDylib => return None,
1969 Linkage::Dynamic => "d",
1970 Linkage::Static => "s",
1972 Some(format!("{}:{}", i + 1, kind))
1973 }).collect::<Vec<String>>();
1974 rbml_w.wr_tagged_str(tag, &s.join(","));
1977 rbml_w.wr_tagged_str(tag, "");
1982 // NB: Increment this as you change the metadata encoding version.
1983 #[allow(non_upper_case_globals)]
1984 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
1986 pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
1987 let mut wr = Cursor::new(Vec::new());
1988 encode_metadata_inner(&mut wr, parms, krate);
1990 // RBML compacts the encoded bytes whenever appropriate,
1991 // so there are some garbages left after the end of the data.
1992 let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as usize;
1993 let mut v = wr.into_inner();
1994 v.truncate(metalen);
1995 assert_eq!(v.len(), metalen);
1997 // And here we run into yet another obscure archive bug: in which metadata
1998 // loaded from archives may have trailing garbage bytes. Awhile back one of
1999 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
2000 // and opt) by having rbml generate an out-of-bounds panic when looking at
2003 // Upon investigation it turned out that the metadata file inside of an rlib
2004 // (and ar archive) was being corrupted. Some compilations would generate a
2005 // metadata file which would end in a few extra bytes, while other
2006 // compilations would not have these extra bytes appended to the end. These
2007 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2008 // being interpreted causing the out-of-bounds.
2010 // The root cause of why these extra bytes were appearing was never
2011 // discovered, and in the meantime the solution we're employing is to insert
2012 // the length of the metadata to the start of the metadata. Later on this
2013 // will allow us to slice the metadata to the precise length that we just
2014 // generated regardless of trailing bytes that end up in it.
2015 let len = v.len() as u32;
2016 v.insert(0, (len >> 0) as u8);
2017 v.insert(0, (len >> 8) as u8);
2018 v.insert(0, (len >> 16) as u8);
2019 v.insert(0, (len >> 24) as u8);
2023 fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
2024 parms: EncodeParams,
2025 krate: &hir::Crate) {
2029 lang_item_bytes: u64,
2030 native_lib_bytes: u64,
2031 plugin_registrar_fn_bytes: u64,
2033 macro_defs_bytes: u64,
2041 let mut stats = Stats {
2045 native_lib_bytes: 0,
2046 plugin_registrar_fn_bytes: 0,
2048 macro_defs_bytes: 0,
2062 encode_inlined_item,
2067 let ecx = EncodeContext {
2070 reexports: reexports,
2071 item_symbols: item_symbols,
2072 link_meta: link_meta,
2074 encode_inlined_item: RefCell::new(encode_inlined_item),
2075 type_abbrevs: RefCell::new(FnvHashMap()),
2076 reachable: reachable,
2079 let mut rbml_w = Encoder::new(wr);
2081 encode_rustc_version(&mut rbml_w);
2082 encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
2083 encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
2084 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2085 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2087 let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2088 encode_attributes(&mut rbml_w, &krate.attrs);
2089 stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2091 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2092 encode_crate_deps(&mut rbml_w, ecx.cstore);
2093 stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2095 // Encode the language items.
2096 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2097 encode_lang_items(&ecx, &mut rbml_w);
2098 stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2100 // Encode the native libraries used
2101 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2102 encode_native_libraries(&ecx, &mut rbml_w);
2103 stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2105 // Encode the plugin registrar function
2106 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2107 encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2108 stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2111 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2112 encode_codemap(&ecx, &mut rbml_w);
2113 stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2115 // Encode macro definitions
2116 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2117 encode_macro_defs(&mut rbml_w, krate);
2118 stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2120 // Encode the def IDs of impls, for coherence checking.
2121 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2122 encode_impls(&ecx, krate, &mut rbml_w);
2123 stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2125 // Encode miscellaneous info.
2126 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2127 encode_misc_info(&ecx, krate, &mut rbml_w);
2128 encode_reachable(&ecx, &mut rbml_w);
2129 stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2131 // Encode and index the items.
2132 rbml_w.start_tag(tag_items);
2133 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2134 let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2135 stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2138 i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2139 encode_index(&mut rbml_w, items_index);
2140 stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
2142 encode_struct_field_attrs(&mut rbml_w, krate);
2144 stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2146 if tcx.sess.meta_stats() {
2147 for e in rbml_w.writer.get_ref() {
2149 stats.zero_bytes += 1;
2153 println!("metadata stats:");
2154 println!(" attribute bytes: {}", stats.attr_bytes);
2155 println!(" dep bytes: {}", stats.dep_bytes);
2156 println!(" lang item bytes: {}", stats.lang_item_bytes);
2157 println!(" native bytes: {}", stats.native_lib_bytes);
2158 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2159 println!(" codemap bytes: {}", stats.codemap_bytes);
2160 println!(" macro def bytes: {}", stats.macro_defs_bytes);
2161 println!(" impl bytes: {}", stats.impl_bytes);
2162 println!(" misc bytes: {}", stats.misc_bytes);
2163 println!(" item bytes: {}", stats.item_bytes);
2164 println!(" index bytes: {}", stats.index_bytes);
2165 println!(" zero bytes: {}", stats.zero_bytes);
2166 println!(" total bytes: {}", stats.total_bytes);
2170 // Get the encoded string for a type
2171 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2172 let mut wr = Cursor::new(Vec::new());
2173 tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
2174 diag: tcx.sess.diagnostic(),
2177 abbrevs: &RefCell::new(FnvHashMap())
2179 String::from_utf8(wr.into_inner()).unwrap()