1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
16 pub use self::InlinedItemRef::*;
20 use metadata::common::*;
22 use metadata::decoder;
23 use metadata::tyencode;
25 use middle::ty::{lookup_item_type};
26 use middle::ty::{self, Ty};
27 use middle::stability;
28 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
30 use serialize::Encodable;
31 use std::cell::RefCell;
35 use syntax::ast::{self, DefId, NodeId};
36 use syntax::ast_map::{PathElem, PathElems};
38 use syntax::ast_util::*;
41 use syntax::attr::AttrMetaMethods;
42 use syntax::diagnostic::SpanHandler;
43 use syntax::parse::token::special_idents;
44 use syntax::parse::token;
46 use syntax::visit::Visitor;
50 use rbml::io::SeekableMemWriter;
52 /// A borrowed version of `ast::InlinedItem`.
53 pub enum InlinedItemRef<'a> {
54 IIItemRef(&'a ast::Item),
55 IITraitItemRef(DefId, &'a ast::TraitItem),
56 IIImplItemRef(DefId, &'a ast::ImplItem),
57 IIForeignRef(&'a ast::ForeignItem)
60 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
62 pub type EncodeInlinedItem<'a> =
63 Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
65 pub struct EncodeParams<'a, 'tcx: 'a> {
66 pub diag: &'a SpanHandler,
67 pub tcx: &'a ty::ctxt<'tcx>,
68 pub reexports: &'a def::ExportMap,
69 pub item_symbols: &'a RefCell<NodeMap<String>>,
70 pub link_meta: &'a LinkMeta,
71 pub cstore: &'a cstore::CStore,
72 pub encode_inlined_item: EncodeInlinedItem<'a>,
73 pub reachable: &'a NodeSet,
76 pub struct EncodeContext<'a, 'tcx: 'a> {
77 pub diag: &'a SpanHandler,
78 pub tcx: &'a ty::ctxt<'tcx>,
79 pub reexports: &'a def::ExportMap,
80 pub item_symbols: &'a RefCell<NodeMap<String>>,
81 pub link_meta: &'a LinkMeta,
82 pub cstore: &'a cstore::CStore,
83 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
84 pub type_abbrevs: tyencode::abbrev_map<'tcx>,
85 pub reachable: &'a NodeSet,
88 fn encode_name(rbml_w: &mut Encoder, name: ast::Name) {
89 rbml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
92 fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) {
93 rbml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
96 pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
97 rbml_w.wr_tagged_str(tag_def_id, def_to_string(id)[]);
106 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
107 ecx: &EncodeContext<'a, 'tcx>,
108 trait_ref: &ty::TraitRef<'tcx>,
110 let ty_str_ctxt = &tyencode::ctxt {
114 abbrevs: &ecx.type_abbrevs
117 rbml_w.start_tag(tag);
118 tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
122 // Item info table encoding
123 fn encode_family(rbml_w: &mut Encoder, c: char) {
124 rbml_w.start_tag(tag_items_data_item_family);
125 rbml_w.writer.write(&[c as u8]);
129 pub fn def_to_string(did: DefId) -> String {
130 format!("{}:{}", did.krate, did.node)
133 fn encode_item_variances(rbml_w: &mut Encoder,
136 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
137 rbml_w.start_tag(tag_item_variances);
142 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
143 ecx: &EncodeContext<'a, 'tcx>,
144 pty: &ty::TypeScheme<'tcx>) {
145 encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics);
146 encode_type(ecx, rbml_w, pty.ty);
149 fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
150 rbml_w.start_tag(tag_items_data_item_variant);
151 let s = def_to_string(vid);
152 rbml_w.writer.write(s.as_bytes());
155 rbml_w.start_tag(tag_mod_child);
160 pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
161 rbml_w: &mut Encoder,
162 closure_type: &ty::ClosureTy<'tcx>) {
163 let ty_str_ctxt = &tyencode::ctxt {
167 abbrevs: &ecx.type_abbrevs
169 tyencode::enc_closure_ty(rbml_w.writer, ty_str_ctxt, closure_type);
172 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
173 rbml_w: &mut Encoder,
175 let ty_str_ctxt = &tyencode::ctxt {
179 abbrevs: &ecx.type_abbrevs
181 tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ);
184 pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
185 rbml_w: &mut Encoder,
186 trait_ref: &ty::TraitRef<'tcx>) {
187 let ty_str_ctxt = &tyencode::ctxt {
191 abbrevs: &ecx.type_abbrevs
193 tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref);
196 pub fn write_region(ecx: &EncodeContext,
197 rbml_w: &mut Encoder,
199 let ty_str_ctxt = &tyencode::ctxt {
203 abbrevs: &ecx.type_abbrevs
205 tyencode::enc_region(rbml_w.writer, ty_str_ctxt, r);
208 fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder,
209 ecx: &EncodeContext<'a, 'tcx>,
210 bounds: &ty::ParamBounds<'tcx>,
212 rbml_w.start_tag(tag);
214 let ty_str_ctxt = &tyencode::ctxt { diag: ecx.diag,
217 abbrevs: &ecx.type_abbrevs };
218 tyencode::enc_bounds(rbml_w.writer, ty_str_ctxt, bounds);
223 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
224 rbml_w: &mut Encoder,
226 rbml_w.start_tag(tag_items_data_item_type);
227 write_type(ecx, rbml_w, typ);
231 fn encode_region(ecx: &EncodeContext,
232 rbml_w: &mut Encoder,
234 rbml_w.start_tag(tag_items_data_region);
235 write_region(ecx, rbml_w, r);
239 fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
240 rbml_w: &mut Encoder,
241 typ: &ty::BareFnTy<'tcx>) {
242 rbml_w.start_tag(tag_item_method_fty);
244 let ty_str_ctxt = &tyencode::ctxt {
248 abbrevs: &ecx.type_abbrevs
250 tyencode::enc_bare_fn_ty(rbml_w.writer, ty_str_ctxt, typ);
255 fn encode_symbol(ecx: &EncodeContext,
256 rbml_w: &mut Encoder,
258 rbml_w.start_tag(tag_items_data_item_symbol);
259 match ecx.item_symbols.borrow().get(&id) {
261 debug!("encode_symbol(id={}, str={})", id, *x);
262 rbml_w.writer.write(x.as_bytes());
265 ecx.diag.handler().bug(
266 format!("encode_symbol: id not found {}", id)[]);
272 fn encode_disr_val(_: &EncodeContext,
273 rbml_w: &mut Encoder,
274 disr_val: ty::Disr) {
275 rbml_w.start_tag(tag_disr_val);
276 let s = disr_val.to_string();
277 rbml_w.writer.write(s.as_bytes());
281 fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
282 rbml_w.start_tag(tag_items_data_parent_item);
283 let s = def_to_string(id);
284 rbml_w.writer.write(s.as_bytes());
288 fn encode_struct_fields(rbml_w: &mut Encoder,
289 fields: &[ty::field_ty],
291 for f in fields.iter() {
292 if f.name == special_idents::unnamed_field.name {
293 rbml_w.start_tag(tag_item_unnamed_field);
295 rbml_w.start_tag(tag_item_field);
296 encode_name(rbml_w, f.name);
298 encode_struct_field_family(rbml_w, f.vis);
299 encode_def_id(rbml_w, f.id);
300 rbml_w.start_tag(tag_item_field_origin);
301 let s = def_to_string(origin);
302 rbml_w.writer.write(s.as_bytes());
308 fn encode_enum_variant_info(ecx: &EncodeContext,
309 rbml_w: &mut Encoder,
311 variants: &[P<ast::Variant>],
312 index: &mut Vec<entry<i64>>) {
313 debug!("encode_enum_variant_info(id={})", id);
315 let mut disr_val = 0;
317 let vi = ty::enum_variants(ecx.tcx,
318 DefId { krate: ast::LOCAL_CRATE, node: id });
319 for variant in variants.iter() {
320 let def_id = local_def(variant.node.id);
322 val: variant.node.id as i64,
323 pos: rbml_w.writer.tell().unwrap(),
325 rbml_w.start_tag(tag_items_data_item);
326 encode_def_id(rbml_w, def_id);
327 match variant.node.kind {
328 ast::TupleVariantKind(_) => encode_family(rbml_w, 'v'),
329 ast::StructVariantKind(_) => encode_family(rbml_w, 'V')
331 encode_name(rbml_w, variant.node.name.name);
332 encode_parent_item(rbml_w, local_def(id));
333 encode_visibility(rbml_w, variant.node.vis);
334 encode_attributes(rbml_w, variant.node.attrs[]);
335 encode_repr_attrs(rbml_w, ecx, variant.node.attrs[]);
337 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
338 encode_stability(rbml_w, stab);
340 match variant.node.kind {
341 ast::TupleVariantKind(_) => {},
342 ast::StructVariantKind(_) => {
343 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
344 let idx = encode_info_for_struct(ecx,
348 encode_struct_fields(rbml_w, fields[], def_id);
349 encode_index(rbml_w, idx, write_i64);
352 if (*vi)[i].disr_val != disr_val {
353 encode_disr_val(ecx, rbml_w, (*vi)[i].disr_val);
354 disr_val = (*vi)[i].disr_val;
356 encode_bounds_and_type(rbml_w, ecx,
357 &lookup_item_type(ecx.tcx, def_id));
359 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
366 fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
367 let path = path.collect::<Vec<_>>();
368 rbml_w.start_tag(tag_path);
369 rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
370 for pe in path.iter() {
371 let tag = match *pe {
372 ast_map::PathMod(_) => tag_path_elem_mod,
373 ast_map::PathName(_) => tag_path_elem_name
375 rbml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
380 fn encode_reexported_static_method(rbml_w: &mut Encoder,
382 method_def_id: DefId,
383 method_name: ast::Name) {
384 debug!("(encode reexported static method) {}::{}",
385 exp.name, token::get_name(method_name));
386 rbml_w.start_tag(tag_items_data_item_reexport);
387 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
388 rbml_w.wr_str(def_to_string(method_def_id)[]);
390 rbml_w.start_tag(tag_items_data_item_reexport_name);
391 rbml_w.wr_str(format!("{}::{}",
393 token::get_name(method_name))[]);
398 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
399 rbml_w: &mut Encoder,
402 let impl_items = ecx.tcx.impl_items.borrow();
403 match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
404 Some(implementations) => {
405 for base_impl_did in implementations.iter() {
406 for &method_did in (*impl_items)[*base_impl_did].iter() {
407 let impl_item = ty::impl_or_trait_item(
409 method_did.def_id());
411 ty::MethodTraitItem(ref m) => {
412 encode_reexported_static_method(rbml_w,
417 ty::TypeTraitItem(_) => {}
428 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
429 rbml_w: &mut Encoder,
432 match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
433 Some(trait_items) => {
434 for trait_item in trait_items.iter() {
435 if let ty::MethodTraitItem(ref m) = *trait_item {
436 encode_reexported_static_method(rbml_w,
448 fn encode_reexported_static_methods(ecx: &EncodeContext,
449 rbml_w: &mut Encoder,
452 if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
453 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
454 let (mut a, mut b) = (path, mod_path.clone());
456 match (a.next(), b.next()) {
457 (None, None) => return true,
458 (None, _) | (_, None) => return false,
459 (Some(x), Some(y)) => if x != y { return false },
465 // We don't need to reexport static methods on items
466 // declared in the same module as our `pub use ...` since
467 // that's done when we encode the item itself.
469 // The only exception is when the reexport *changes* the
470 // name e.g. `pub use Foo = self::Bar` -- we have
471 // encoded metadata for static methods relative to Bar,
472 // but not yet for Foo.
474 if path_differs || item.ident.name != exp.name {
475 if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
476 if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
477 debug!("(encode reexported static methods) {} [trait]",
482 debug!("(encode reexported static methods) {} [base]",
489 /// Iterates through "auxiliary node IDs", which are node IDs that describe
490 /// top-level items that are sub-items of the given item. Specifically:
492 /// * For newtype structs, iterates through the node ID of the constructor.
493 fn each_auxiliary_node_id<F>(item: &ast::Item, callback: F) -> bool where
494 F: FnOnce(NodeId) -> bool,
496 let mut continue_ = true;
498 ast::ItemStruct(ref struct_def, _) => {
499 // If this is a newtype struct, return the constructor.
500 match struct_def.ctor_id {
501 Some(ctor_id) if struct_def.fields.len() > 0 &&
502 struct_def.fields[0].node.kind.is_unnamed() => {
503 continue_ = callback(ctor_id);
514 fn encode_reexports(ecx: &EncodeContext,
515 rbml_w: &mut Encoder,
518 debug!("(encoding info for module) encoding reexports for {}", id);
519 match ecx.reexports.get(&id) {
520 Some(ref exports) => {
521 debug!("(encoding info for module) found reexports for {}", id);
522 for exp in exports.iter() {
523 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
529 rbml_w.start_tag(tag_items_data_item_reexport);
530 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
531 rbml_w.wr_str(def_to_string(exp.def_id)[]);
533 rbml_w.start_tag(tag_items_data_item_reexport_name);
534 rbml_w.wr_str(exp.name.as_str());
537 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
541 debug!("(encoding info for module) found no reexports for {}",
547 fn encode_info_for_mod(ecx: &EncodeContext,
548 rbml_w: &mut Encoder,
550 attrs: &[ast::Attribute],
554 vis: ast::Visibility) {
555 rbml_w.start_tag(tag_items_data_item);
556 encode_def_id(rbml_w, local_def(id));
557 encode_family(rbml_w, 'm');
558 encode_name(rbml_w, name.name);
559 debug!("(encoding info for module) encoding info for module ID {}", id);
561 // Encode info about all the module children.
562 for item in md.items.iter() {
563 rbml_w.start_tag(tag_mod_child);
564 rbml_w.wr_str(def_to_string(local_def(item.id))[]);
567 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
568 rbml_w.start_tag(tag_mod_child);
569 rbml_w.wr_str(def_to_string(local_def(
570 auxiliary_node_id))[]);
575 if let ast::ItemImpl(..) = item.node {
576 let (ident, did) = (item.ident, item.id);
577 debug!("(encoding info for module) ... encoding impl {} ({}/{})",
578 token::get_ident(ident),
579 did, ecx.tcx.map.node_to_string(did));
581 rbml_w.start_tag(tag_mod_impl);
582 rbml_w.wr_str(def_to_string(local_def(did))[]);
587 encode_path(rbml_w, path.clone());
588 encode_visibility(rbml_w, vis);
590 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
591 encode_stability(rbml_w, stab);
593 // Encode the reexports of this module, if this module is public.
594 if vis == ast::Public {
595 debug!("(encoding info for module) encoding reexports for {}", id);
596 encode_reexports(ecx, rbml_w, id, path);
598 encode_attributes(rbml_w, attrs);
603 fn encode_struct_field_family(rbml_w: &mut Encoder,
604 visibility: ast::Visibility) {
605 encode_family(rbml_w, match visibility {
607 ast::Inherited => 'N'
611 fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
612 rbml_w.start_tag(tag_items_data_item_visibility);
613 let ch = match visibility {
615 ast::Inherited => 'i',
617 rbml_w.wr_str(ch.to_string()[]);
621 fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
622 kind: ty::UnboxedClosureKind) {
623 rbml_w.start_tag(tag_unboxed_closure_kind);
624 let ch = match kind {
625 ty::FnUnboxedClosureKind => 'f',
626 ty::FnMutUnboxedClosureKind => 'm',
627 ty::FnOnceUnboxedClosureKind => 'o',
629 rbml_w.wr_str(ch.to_string()[]);
633 fn encode_explicit_self(rbml_w: &mut Encoder,
634 explicit_self: &ty::ExplicitSelfCategory) {
635 rbml_w.start_tag(tag_item_trait_method_explicit_self);
637 // Encode the base self type.
638 match *explicit_self {
639 ty::StaticExplicitSelfCategory => {
640 rbml_w.writer.write(&[ 's' as u8 ]);
642 ty::ByValueExplicitSelfCategory => {
643 rbml_w.writer.write(&[ 'v' as u8 ]);
645 ty::ByBoxExplicitSelfCategory => {
646 rbml_w.writer.write(&[ '~' as u8 ]);
648 ty::ByReferenceExplicitSelfCategory(_, m) => {
649 // FIXME(#4846) encode custom lifetime
650 rbml_w.writer.write(&['&' as u8]);
651 encode_mutability(rbml_w, m);
657 fn encode_mutability(rbml_w: &mut Encoder,
658 m: ast::Mutability) {
660 ast::MutImmutable => { rbml_w.writer.write(&[ 'i' as u8 ]); }
661 ast::MutMutable => { rbml_w.writer.write(&[ 'm' as u8 ]); }
666 fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
667 rbml_w.start_tag(tag_item_trait_item_sort);
668 rbml_w.writer.write(&[ sort as u8 ]);
672 fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
673 rbml_w.start_tag(tag_item_trait_parent_sort);
674 rbml_w.writer.write(&[ sort as u8 ]);
678 fn encode_provided_source(rbml_w: &mut Encoder,
679 source_opt: Option<DefId>) {
680 for source in source_opt.iter() {
681 rbml_w.start_tag(tag_item_method_provided_source);
682 let s = def_to_string(*source);
683 rbml_w.writer.write(s.as_bytes());
688 /* Returns an index of items in this class */
689 fn encode_info_for_struct(ecx: &EncodeContext,
690 rbml_w: &mut Encoder,
691 fields: &[ty::field_ty],
692 global_index: &mut Vec<entry<i64>>)
694 /* Each class has its own index, since different classes
695 may have fields with the same name */
696 let mut index = Vec::new();
697 /* We encode both private and public fields -- need to include
698 private fields to get the offsets right */
699 for field in fields.iter() {
701 let id = field.id.node;
703 index.push(entry {val: id as i64, pos: rbml_w.writer.tell().unwrap()});
704 global_index.push(entry {
706 pos: rbml_w.writer.tell().unwrap(),
708 rbml_w.start_tag(tag_items_data_item);
709 debug!("encode_info_for_struct: doing {} {}",
710 token::get_name(nm), id);
711 encode_struct_field_family(rbml_w, field.vis);
712 encode_name(rbml_w, nm);
713 encode_bounds_and_type(rbml_w, ecx,
714 &lookup_item_type(ecx.tcx, local_def(id)));
715 encode_def_id(rbml_w, local_def(id));
717 let stab = stability::lookup(ecx.tcx, field.id);
718 encode_stability(rbml_w, stab);
725 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
726 rbml_w: &mut Encoder,
729 index: &mut Vec<entry<i64>>,
733 pos: rbml_w.writer.tell().unwrap(),
736 rbml_w.start_tag(tag_items_data_item);
737 encode_def_id(rbml_w, local_def(ctor_id));
738 encode_family(rbml_w, 'o');
739 encode_bounds_and_type(rbml_w, ecx,
740 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
741 encode_name(rbml_w, name.name);
742 ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
743 encode_parent_item(rbml_w, local_def(struct_id));
745 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
746 encode_symbol(ecx, rbml_w, ctor_id);
749 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
750 encode_stability(rbml_w, stab);
752 // indicate that this is a tuple struct ctor, because downstream users will normally want
753 // the tuple struct definition, but without this there is no way for them to tell that
754 // they actually have a ctor rather than a normal function
755 rbml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
761 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
762 ecx: &EncodeContext<'a, 'tcx>,
763 generics: &ty::Generics<'tcx>,
766 rbml_w.start_tag(tag);
769 let ty_str_ctxt = &tyencode::ctxt {
773 abbrevs: &ecx.type_abbrevs
775 for param in generics.types.iter() {
776 rbml_w.start_tag(tag_type_param_def);
777 tyencode::enc_type_param_def(rbml_w.writer, ty_str_ctxt, param);
782 for param in generics.regions.iter() {
783 rbml_w.start_tag(tag_region_param_def);
785 rbml_w.start_tag(tag_region_param_def_ident);
786 encode_name(rbml_w, param.name);
789 rbml_w.wr_tagged_str(tag_region_param_def_def_id,
790 def_to_string(param.def_id)[]);
792 rbml_w.wr_tagged_u64(tag_region_param_def_space,
793 param.space.to_uint() as u64);
795 rbml_w.wr_tagged_u64(tag_region_param_def_index,
798 for &bound_region in param.bounds.iter() {
799 encode_region(ecx, rbml_w, bound_region);
805 for (space, _, predicate) in generics.predicates.iter_enumerated() {
806 rbml_w.start_tag(tag_predicate);
808 rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
810 rbml_w.start_tag(tag_predicate_data);
811 tyencode::enc_predicate(rbml_w.writer, ty_str_ctxt, predicate);
820 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
821 rbml_w: &mut Encoder,
822 method_ty: &ty::Method<'tcx>) {
823 encode_def_id(rbml_w, method_ty.def_id);
824 encode_name(rbml_w, method_ty.name);
825 encode_generics(rbml_w, ecx, &method_ty.generics,
826 tag_method_ty_generics);
827 encode_method_fty(ecx, rbml_w, &method_ty.fty);
828 encode_visibility(rbml_w, method_ty.vis);
829 encode_explicit_self(rbml_w, &method_ty.explicit_self);
830 match method_ty.explicit_self {
831 ty::StaticExplicitSelfCategory => {
832 encode_family(rbml_w, STATIC_METHOD_FAMILY);
834 _ => encode_family(rbml_w, METHOD_FAMILY)
836 encode_provided_source(rbml_w, method_ty.provided_source);
839 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
840 rbml_w: &mut Encoder,
841 m: &ty::Method<'tcx>,
842 impl_path: PathElems,
843 is_default_impl: bool,
845 ast_item_opt: Option<&ast::ImplItem>) {
847 debug!("encode_info_for_method: {} {}", m.def_id,
848 token::get_name(m.name));
849 rbml_w.start_tag(tag_items_data_item);
851 encode_method_ty_fields(ecx, rbml_w, m);
852 encode_parent_item(rbml_w, local_def(parent_id));
853 encode_item_sort(rbml_w, 'r');
855 let stab = stability::lookup(ecx.tcx, m.def_id);
856 encode_stability(rbml_w, stab);
858 // The type for methods gets encoded twice, which is unfortunate.
859 let pty = lookup_item_type(ecx.tcx, m.def_id);
860 encode_bounds_and_type(rbml_w, ecx, &pty);
862 let elem = ast_map::PathName(m.name);
863 encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
865 Some(&ast::MethodImplItem(ref ast_method)) => {
866 encode_attributes(rbml_w, ast_method.attrs[]);
867 let any_types = !pty.generics.types.is_empty();
868 if any_types || is_default_impl || should_inline(ast_method.attrs[]) {
869 encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
870 ast_item_opt.unwrap()));
873 encode_symbol(ecx, rbml_w, m.def_id.node);
875 encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
883 fn encode_info_for_associated_type(ecx: &EncodeContext,
884 rbml_w: &mut Encoder,
885 associated_type: &ty::AssociatedType,
886 impl_path: PathElems,
888 typedef_opt: Option<P<ast::Typedef>>) {
889 debug!("encode_info_for_associated_type({},{})",
890 associated_type.def_id,
891 token::get_name(associated_type.name));
893 rbml_w.start_tag(tag_items_data_item);
895 encode_def_id(rbml_w, associated_type.def_id);
896 encode_name(rbml_w, associated_type.name);
897 encode_visibility(rbml_w, associated_type.vis);
898 encode_family(rbml_w, 'y');
899 encode_parent_item(rbml_w, local_def(parent_id));
900 encode_item_sort(rbml_w, 't');
902 let type_scheme = ty::lookup_item_type(ecx.tcx, associated_type.def_id);
903 encode_bounds_and_type(rbml_w, ecx, &type_scheme);
905 let stab = stability::lookup(ecx.tcx, associated_type.def_id);
906 encode_stability(rbml_w, stab);
908 let elem = ast_map::PathName(associated_type.name);
909 encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
914 encode_attributes(rbml_w, typedef.attrs[]);
915 encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
923 fn encode_method_argument_names(rbml_w: &mut Encoder,
924 decl: &ast::FnDecl) {
925 rbml_w.start_tag(tag_method_argument_names);
926 for arg in decl.inputs.iter() {
927 rbml_w.start_tag(tag_method_argument_name);
928 if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
929 let name = token::get_ident(path1.node);
930 rbml_w.writer.write(name.get().as_bytes());
937 fn encode_repr_attrs(rbml_w: &mut Encoder,
939 attrs: &[ast::Attribute]) {
940 let mut repr_attrs = Vec::new();
941 for attr in attrs.iter() {
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;
955 eii.call_mut((ecx, rbml_w, ii))
958 const FN_FAMILY: char = 'f';
959 const STATIC_METHOD_FAMILY: char = 'F';
960 const METHOD_FAMILY: char = 'h';
962 fn should_inline(attrs: &[ast::Attribute]) -> bool {
964 match find_inline_attr(attrs) {
965 InlineNone | InlineNever => false,
966 InlineHint | InlineAlways => true
970 // Encodes the inherent implementations of a structure, enumeration, or trait.
971 fn encode_inherent_implementations(ecx: &EncodeContext,
972 rbml_w: &mut Encoder,
974 match ecx.tcx.inherent_impls.borrow().get(&def_id) {
976 Some(implementations) => {
977 for &impl_def_id in implementations.iter() {
978 rbml_w.start_tag(tag_items_data_item_inherent_impl);
979 encode_def_id(rbml_w, impl_def_id);
986 // Encodes the implementations of a trait defined in this crate.
987 fn encode_extension_implementations(ecx: &EncodeContext,
988 rbml_w: &mut Encoder,
989 trait_def_id: DefId) {
990 match ecx.tcx.trait_impls.borrow().get(&trait_def_id) {
992 Some(implementations) => {
993 for &impl_def_id in implementations.borrow().iter() {
994 rbml_w.start_tag(tag_items_data_item_extension_impl);
995 encode_def_id(rbml_w, impl_def_id);
1002 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
1003 stab_opt.map(|stab| {
1004 rbml_w.start_tag(tag_items_data_item_stability);
1005 stab.encode(rbml_w).unwrap();
1010 fn encode_info_for_item(ecx: &EncodeContext,
1011 rbml_w: &mut Encoder,
1013 index: &mut Vec<entry<i64>>,
1015 vis: ast::Visibility) {
1018 fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
1019 index: &mut Vec<entry<i64>>) {
1021 val: item.id as i64,
1022 pos: rbml_w.writer.tell().unwrap(),
1026 debug!("encoding info for item at {}",
1027 tcx.sess.codemap().span_to_string(item.span));
1029 let def_id = local_def(item.id);
1030 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
1033 ast::ItemStatic(_, m, _) => {
1034 add_to_index(item, rbml_w, index);
1035 rbml_w.start_tag(tag_items_data_item);
1036 encode_def_id(rbml_w, def_id);
1037 if m == ast::MutMutable {
1038 encode_family(rbml_w, 'b');
1040 encode_family(rbml_w, 'c');
1042 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1043 encode_symbol(ecx, rbml_w, item.id);
1044 encode_name(rbml_w, item.ident.name);
1045 encode_path(rbml_w, path);
1046 encode_visibility(rbml_w, vis);
1047 encode_stability(rbml_w, stab);
1048 encode_attributes(rbml_w, item.attrs[]);
1051 ast::ItemConst(_, _) => {
1052 add_to_index(item, rbml_w, index);
1053 rbml_w.start_tag(tag_items_data_item);
1054 encode_def_id(rbml_w, def_id);
1055 encode_family(rbml_w, 'C');
1056 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1057 encode_name(rbml_w, item.ident.name);
1058 encode_path(rbml_w, path);
1059 encode_attributes(rbml_w, item.attrs.as_slice());
1060 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1061 encode_visibility(rbml_w, vis);
1062 encode_stability(rbml_w, stab);
1065 ast::ItemFn(ref decl, _, _, ref generics, _) => {
1066 add_to_index(item, rbml_w, index);
1067 rbml_w.start_tag(tag_items_data_item);
1068 encode_def_id(rbml_w, def_id);
1069 encode_family(rbml_w, FN_FAMILY);
1070 let tps_len = generics.ty_params.len();
1071 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1072 encode_name(rbml_w, item.ident.name);
1073 encode_path(rbml_w, path);
1074 encode_attributes(rbml_w, item.attrs[]);
1075 if tps_len > 0u || should_inline(item.attrs[]) {
1076 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1079 encode_symbol(ecx, rbml_w, item.id);
1081 encode_visibility(rbml_w, vis);
1082 encode_stability(rbml_w, stab);
1083 encode_method_argument_names(rbml_w, &**decl);
1086 ast::ItemMod(ref m) => {
1087 add_to_index(item, rbml_w, index);
1088 encode_info_for_mod(ecx,
1097 ast::ItemForeignMod(ref fm) => {
1098 add_to_index(item, rbml_w, index);
1099 rbml_w.start_tag(tag_items_data_item);
1100 encode_def_id(rbml_w, def_id);
1101 encode_family(rbml_w, 'n');
1102 encode_name(rbml_w, item.ident.name);
1103 encode_path(rbml_w, path);
1105 // Encode all the items in this module.
1106 for foreign_item in fm.items.iter() {
1107 rbml_w.start_tag(tag_mod_child);
1108 rbml_w.wr_str(def_to_string(local_def(foreign_item.id))[]);
1111 encode_visibility(rbml_w, vis);
1112 encode_stability(rbml_w, stab);
1115 ast::ItemTy(..) => {
1116 add_to_index(item, rbml_w, index);
1117 rbml_w.start_tag(tag_items_data_item);
1118 encode_def_id(rbml_w, def_id);
1119 encode_family(rbml_w, 'y');
1120 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1121 encode_name(rbml_w, item.ident.name);
1122 encode_path(rbml_w, path);
1123 encode_visibility(rbml_w, vis);
1124 encode_stability(rbml_w, stab);
1127 ast::ItemEnum(ref enum_definition, _) => {
1128 add_to_index(item, rbml_w, index);
1130 rbml_w.start_tag(tag_items_data_item);
1131 encode_def_id(rbml_w, def_id);
1132 encode_family(rbml_w, 't');
1133 encode_item_variances(rbml_w, ecx, item.id);
1134 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1135 encode_name(rbml_w, item.ident.name);
1136 encode_attributes(rbml_w, item.attrs[]);
1137 encode_repr_attrs(rbml_w, ecx, item.attrs[]);
1138 for v in (*enum_definition).variants.iter() {
1139 encode_variant_id(rbml_w, local_def(v.node.id));
1141 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1142 encode_path(rbml_w, path);
1144 // Encode inherent implementations for this enumeration.
1145 encode_inherent_implementations(ecx, rbml_w, def_id);
1147 encode_visibility(rbml_w, vis);
1148 encode_stability(rbml_w, stab);
1151 encode_enum_variant_info(ecx,
1154 (*enum_definition).variants[],
1157 ast::ItemStruct(ref struct_def, _) => {
1158 let fields = ty::lookup_struct_fields(tcx, def_id);
1160 /* First, encode the fields
1161 These come first because we need to write them to make
1162 the index, and the index needs to be in the item for the
1164 let idx = encode_info_for_struct(ecx,
1169 /* Index the class*/
1170 add_to_index(item, rbml_w, index);
1172 /* Now, make an item for the class itself */
1173 rbml_w.start_tag(tag_items_data_item);
1174 encode_def_id(rbml_w, def_id);
1175 encode_family(rbml_w, 'S');
1176 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1178 encode_item_variances(rbml_w, ecx, item.id);
1179 encode_name(rbml_w, item.ident.name);
1180 encode_attributes(rbml_w, item.attrs[]);
1181 encode_path(rbml_w, path.clone());
1182 encode_stability(rbml_w, stab);
1183 encode_visibility(rbml_w, vis);
1184 encode_repr_attrs(rbml_w, ecx, item.attrs[]);
1186 /* Encode def_ids for each field and method
1187 for methods, write all the stuff get_trait_method
1189 encode_struct_fields(rbml_w, fields[], def_id);
1191 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1193 // Encode inherent implementations for this structure.
1194 encode_inherent_implementations(ecx, rbml_w, def_id);
1196 /* Each class has its own index -- encode it */
1197 encode_index(rbml_w, idx, write_i64);
1200 // If this is a tuple-like struct, encode the type of the constructor.
1201 match struct_def.ctor_id {
1203 encode_info_for_struct_ctor(ecx, rbml_w, item.ident,
1204 ctor_id, index, def_id.node);
1209 ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
1210 // We need to encode information about the default methods we
1211 // have inherited, so we drive this based on the impl structure.
1212 let impl_items = tcx.impl_items.borrow();
1213 let items = &(*impl_items)[def_id];
1215 add_to_index(item, rbml_w, index);
1216 rbml_w.start_tag(tag_items_data_item);
1217 encode_def_id(rbml_w, def_id);
1218 encode_family(rbml_w, 'i');
1219 encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
1220 encode_name(rbml_w, item.ident.name);
1221 encode_attributes(rbml_w, item.attrs[]);
1222 encode_unsafety(rbml_w, unsafety);
1223 encode_polarity(rbml_w, polarity);
1225 ast::TyPath(ref path, _) if path.segments.len() == 1 => {
1226 let ident = path.segments.last().unwrap().identifier;
1227 encode_impl_type_basename(rbml_w, ident);
1231 for &item_def_id in items.iter() {
1232 rbml_w.start_tag(tag_item_impl_item);
1234 ty::MethodTraitItemId(item_def_id) => {
1235 encode_def_id(rbml_w, item_def_id);
1236 encode_item_sort(rbml_w, 'r');
1238 ty::TypeTraitItemId(item_def_id) => {
1239 encode_def_id(rbml_w, item_def_id);
1240 encode_item_sort(rbml_w, 't');
1245 for ast_trait_ref in opt_trait.iter() {
1246 let trait_ref = ty::node_id_to_trait_ref(
1247 tcx, ast_trait_ref.ref_id);
1248 encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
1250 encode_path(rbml_w, path.clone());
1251 encode_stability(rbml_w, stab);
1254 // Iterate down the trait items, emitting them. We rely on the
1255 // assumption that all of the actually implemented trait items
1256 // appear first in the impl structure, in the same order they do
1257 // in the ast. This is a little sketchy.
1258 let num_implemented_methods = ast_items.len();
1259 for (i, &trait_item_def_id) in items.iter().enumerate() {
1260 let ast_item = if i < num_implemented_methods {
1267 val: trait_item_def_id.def_id().node as i64,
1268 pos: rbml_w.writer.tell().unwrap(),
1271 let trait_item_type =
1272 ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
1273 match (trait_item_type, ast_item) {
1274 (ty::MethodTraitItem(ref method_type),
1275 Some(&ast::MethodImplItem(_))) => {
1276 encode_info_for_method(ecx,
1284 (ty::MethodTraitItem(ref method_type), _) => {
1285 encode_info_for_method(ecx,
1293 (ty::TypeTraitItem(ref associated_type),
1294 Some(&ast::TypeImplItem(ref typedef))) => {
1295 encode_info_for_associated_type(ecx,
1300 Some((*typedef).clone()))
1302 (ty::TypeTraitItem(ref associated_type), _) => {
1303 encode_info_for_associated_type(ecx,
1313 ast::ItemTrait(_, _, _, ref ms) => {
1314 add_to_index(item, rbml_w, index);
1315 rbml_w.start_tag(tag_items_data_item);
1316 encode_def_id(rbml_w, def_id);
1317 encode_family(rbml_w, 'I');
1318 encode_item_variances(rbml_w, ecx, item.id);
1319 let trait_def = ty::lookup_trait_def(tcx, def_id);
1320 encode_unsafety(rbml_w, trait_def.unsafety);
1321 encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice());
1322 encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
1323 encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1324 encode_name(rbml_w, item.ident.name);
1325 encode_attributes(rbml_w, item.attrs[]);
1326 encode_visibility(rbml_w, vis);
1327 encode_stability(rbml_w, stab);
1328 for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
1329 rbml_w.start_tag(tag_item_trait_item);
1330 match method_def_id {
1331 ty::MethodTraitItemId(method_def_id) => {
1332 encode_def_id(rbml_w, method_def_id);
1333 encode_item_sort(rbml_w, 'r');
1335 ty::TypeTraitItemId(type_def_id) => {
1336 encode_def_id(rbml_w, type_def_id);
1337 encode_item_sort(rbml_w, 't');
1342 rbml_w.start_tag(tag_mod_child);
1343 rbml_w.wr_str(def_to_string(method_def_id.def_id())[]);
1346 encode_path(rbml_w, path.clone());
1348 encode_bounds(rbml_w, ecx, &trait_def.bounds, tag_trait_def_bounds);
1350 // Encode the implementations of this trait.
1351 encode_extension_implementations(ecx, rbml_w, def_id);
1353 // Encode inherent implementations for this trait.
1354 encode_inherent_implementations(ecx, rbml_w, def_id);
1358 // Now output the trait item info for each trait item.
1359 let r = ty::trait_item_def_ids(tcx, def_id);
1360 for (i, &item_def_id) in r.iter().enumerate() {
1361 assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
1364 val: item_def_id.def_id().node as i64,
1365 pos: rbml_w.writer.tell().unwrap(),
1368 rbml_w.start_tag(tag_items_data_item);
1370 encode_parent_item(rbml_w, def_id);
1372 let stab = stability::lookup(tcx, item_def_id.def_id());
1373 encode_stability(rbml_w, stab);
1375 let trait_item_type =
1376 ty::impl_or_trait_item(tcx, item_def_id.def_id());
1377 let is_nonstatic_method;
1378 match trait_item_type {
1379 ty::MethodTraitItem(method_ty) => {
1380 let method_def_id = item_def_id.def_id();
1382 encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1384 let elem = ast_map::PathName(method_ty.name);
1386 path.clone().chain(Some(elem).into_iter()));
1388 match method_ty.explicit_self {
1389 ty::StaticExplicitSelfCategory => {
1390 encode_family(rbml_w,
1391 STATIC_METHOD_FAMILY);
1394 encode_family(rbml_w,
1398 let pty = ty::lookup_item_type(tcx,
1400 encode_bounds_and_type(rbml_w, ecx, &pty);
1402 is_nonstatic_method = method_ty.explicit_self !=
1403 ty::StaticExplicitSelfCategory;
1405 ty::TypeTraitItem(associated_type) => {
1406 encode_name(rbml_w, associated_type.name);
1407 encode_def_id(rbml_w, associated_type.def_id);
1409 let elem = ast_map::PathName(associated_type.name);
1411 path.clone().chain(Some(elem).into_iter()));
1413 encode_item_sort(rbml_w, 't');
1414 encode_family(rbml_w, 'y');
1416 is_nonstatic_method = false;
1420 encode_parent_sort(rbml_w, 't');
1422 let trait_item = &ms[i];
1423 let encode_trait_item = |&: rbml_w: &mut Encoder| {
1424 // If this is a static method, we've already
1426 if is_nonstatic_method {
1427 // FIXME: I feel like there is something funny
1429 let pty = ty::lookup_item_type(tcx, item_def_id.def_id());
1430 encode_bounds_and_type(rbml_w, ecx, &pty);
1434 &ast::RequiredMethod(ref m) => {
1435 encode_attributes(rbml_w, m.attrs[]);
1436 encode_trait_item(rbml_w);
1437 encode_item_sort(rbml_w, 'r');
1438 encode_method_argument_names(rbml_w, &*m.decl);
1441 &ast::ProvidedMethod(ref m) => {
1442 encode_attributes(rbml_w, m.attrs[]);
1443 encode_trait_item(rbml_w);
1444 encode_item_sort(rbml_w, 'p');
1445 encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
1446 encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
1449 &ast::TypeTraitItem(ref associated_type) => {
1450 encode_attributes(rbml_w,
1451 associated_type.attrs[]);
1452 encode_item_sort(rbml_w, 't');
1459 ast::ItemMac(..) => {
1460 // macros are encoded separately
1465 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1466 rbml_w: &mut Encoder,
1467 nitem: &ast::ForeignItem,
1468 index: &mut Vec<entry<i64>>,
1472 val: nitem.id as i64,
1473 pos: rbml_w.writer.tell().unwrap(),
1476 rbml_w.start_tag(tag_items_data_item);
1477 encode_def_id(rbml_w, local_def(nitem.id));
1478 encode_visibility(rbml_w, nitem.vis);
1480 ast::ForeignItemFn(..) => {
1481 encode_family(rbml_w, FN_FAMILY);
1482 encode_bounds_and_type(rbml_w, ecx,
1483 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1484 encode_name(rbml_w, nitem.ident.name);
1485 if abi == abi::RustIntrinsic {
1486 encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
1488 encode_attributes(rbml_w, &*nitem.attrs);
1489 let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
1490 encode_stability(rbml_w, stab);
1491 encode_symbol(ecx, rbml_w, nitem.id);
1493 ast::ForeignItemStatic(_, mutbl) => {
1495 encode_family(rbml_w, 'b');
1497 encode_family(rbml_w, 'c');
1499 encode_bounds_and_type(rbml_w, ecx,
1500 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1501 encode_attributes(rbml_w, &*nitem.attrs);
1502 let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
1503 encode_stability(rbml_w, stab);
1504 encode_symbol(ecx, rbml_w, nitem.id);
1505 encode_name(rbml_w, nitem.ident.name);
1508 encode_path(rbml_w, path);
1512 fn my_visit_expr(_e: &ast::Expr) { }
1514 fn my_visit_item(i: &ast::Item,
1515 rbml_w: &mut Encoder,
1516 ecx: &EncodeContext,
1517 index: &mut Vec<entry<i64>>) {
1518 ecx.tcx.map.with_path(i.id, |path| {
1519 encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
1523 fn my_visit_foreign_item(ni: &ast::ForeignItem,
1524 rbml_w: &mut Encoder,
1525 ecx: &EncodeContext,
1526 index: &mut Vec<entry<i64>>) {
1527 debug!("writing foreign item {}::{}",
1528 ecx.tcx.map.path_to_string(ni.id),
1529 token::get_ident(ni.ident));
1531 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1532 ecx.tcx.map.with_path(ni.id, |path| {
1533 encode_info_for_foreign_item(ecx, rbml_w,
1539 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1540 rbml_w_for_visit_item: &'a mut Encoder<'b>,
1541 ecx: &'a EncodeContext<'c,'tcx>,
1542 index: &'a mut Vec<entry<i64>>,
1545 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
1546 fn visit_expr(&mut self, ex: &ast::Expr) {
1547 visit::walk_expr(self, ex);
1550 fn visit_item(&mut self, i: &ast::Item) {
1551 visit::walk_item(self, i);
1553 self.rbml_w_for_visit_item,
1557 fn visit_foreign_item(&mut self, ni: &ast::ForeignItem) {
1558 visit::walk_foreign_item(self, ni);
1559 my_visit_foreign_item(ni,
1560 self.rbml_w_for_visit_item,
1566 fn encode_info_for_items(ecx: &EncodeContext,
1567 rbml_w: &mut Encoder,
1569 -> Vec<entry<i64>> {
1570 let mut index = Vec::new();
1571 rbml_w.start_tag(tag_items_data);
1573 val: ast::CRATE_NODE_ID as i64,
1574 pos: rbml_w.writer.tell().unwrap(),
1576 encode_info_for_mod(ecx,
1581 ast_map::Values([].iter()).chain(None),
1582 syntax::parse::token::special_idents::invalid,
1585 visit::walk_crate(&mut EncodeVisitor {
1588 rbml_w_for_visit_item: &mut *rbml_w,
1596 // Path and definition ID indexing
1598 fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
1599 F: FnMut(&mut SeekableMemWriter, &T),
1602 let mut buckets: Vec<Vec<entry<T>>> = range(0, 256u16).map(|_| Vec::new()).collect();
1603 for elt in index.into_iter() {
1604 let h = hash::hash(&elt.val) as uint;
1605 buckets[h % 256].push(elt);
1608 rbml_w.start_tag(tag_index);
1609 let mut bucket_locs = Vec::new();
1610 rbml_w.start_tag(tag_index_buckets);
1611 for bucket in buckets.iter() {
1612 bucket_locs.push(rbml_w.writer.tell().unwrap());
1613 rbml_w.start_tag(tag_index_buckets_bucket);
1614 for elt in bucket.iter() {
1615 rbml_w.start_tag(tag_index_buckets_bucket_elt);
1616 assert!(elt.pos < 0xffff_ffff);
1618 let wr: &mut SeekableMemWriter = rbml_w.writer;
1619 wr.write_be_u32(elt.pos as u32);
1621 write_fn(rbml_w.writer, &elt.val);
1627 rbml_w.start_tag(tag_index_table);
1628 for pos in bucket_locs.iter() {
1629 assert!(*pos < 0xffff_ffff);
1630 let wr: &mut SeekableMemWriter = rbml_w.writer;
1631 wr.write_be_u32(*pos as u32);
1637 fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1638 let wr: &mut SeekableMemWriter = writer;
1639 assert!(n < 0x7fff_ffff);
1640 wr.write_be_u32(n as u32);
1643 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1645 ast::MetaWord(ref name) => {
1646 rbml_w.start_tag(tag_meta_item_word);
1647 rbml_w.start_tag(tag_meta_item_name);
1648 rbml_w.writer.write(name.get().as_bytes());
1652 ast::MetaNameValue(ref name, ref value) => {
1654 ast::LitStr(ref value, _) => {
1655 rbml_w.start_tag(tag_meta_item_name_value);
1656 rbml_w.start_tag(tag_meta_item_name);
1657 rbml_w.writer.write(name.get().as_bytes());
1659 rbml_w.start_tag(tag_meta_item_value);
1660 rbml_w.writer.write(value.get().as_bytes());
1664 _ => {/* FIXME (#623): encode other variants */ }
1667 ast::MetaList(ref name, ref items) => {
1668 rbml_w.start_tag(tag_meta_item_list);
1669 rbml_w.start_tag(tag_meta_item_name);
1670 rbml_w.writer.write(name.get().as_bytes());
1672 for inner_item in items.iter() {
1673 encode_meta_item(rbml_w, &**inner_item);
1680 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1681 rbml_w.start_tag(tag_attributes);
1682 for attr in attrs.iter() {
1683 rbml_w.start_tag(tag_attribute);
1684 rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
1685 encode_meta_item(rbml_w, &*attr.node.value);
1691 fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
1692 let byte: u8 = match unsafety {
1693 ast::Unsafety::Normal => 0,
1694 ast::Unsafety::Unsafe => 1,
1696 rbml_w.wr_tagged_u8(tag_unsafety, byte);
1699 fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
1700 rbml_w.start_tag(tag_associated_type_names);
1701 for &name in names.iter() {
1702 rbml_w.wr_tagged_str(tag_associated_type_name, token::get_name(name).get());
1707 fn encode_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
1708 let byte: u8 = match polarity {
1709 ast::ImplPolarity::Positive => 0,
1710 ast::ImplPolarity::Negative => 1,
1712 rbml_w.wr_tagged_u8(tag_polarity, byte);
1715 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
1716 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1717 // Pull the cnums and name,vers,hash out of cstore
1718 let mut deps = Vec::new();
1719 cstore.iter_crate_data(|key, val| {
1720 let dep = decoder::CrateDep {
1722 name: decoder::get_crate_name(val.data()),
1723 hash: decoder::get_crate_hash(val.data()),
1729 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1731 // Sanity-check the crate numbers
1732 let mut expected_cnum = 1;
1733 for n in deps.iter() {
1734 assert_eq!(n.cnum, expected_cnum);
1741 // We're just going to write a list of crate 'name-hash-version's, with
1742 // the assumption that they are numbered 1 to n.
1743 // FIXME (#2166): This is not nearly enough to support correct versioning
1744 // but is enough to get transitive crate dependencies working.
1745 rbml_w.start_tag(tag_crate_deps);
1746 let r = get_ordered_deps(cstore);
1747 for dep in r.iter() {
1748 encode_crate_dep(rbml_w, (*dep).clone());
1753 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1754 rbml_w.start_tag(tag_lang_items);
1756 for (i, def_id) in ecx.tcx.lang_items.items() {
1757 for id in def_id.iter() {
1758 if id.krate == ast::LOCAL_CRATE {
1759 rbml_w.start_tag(tag_lang_items_item);
1761 rbml_w.start_tag(tag_lang_items_item_id);
1763 let wr: &mut SeekableMemWriter = rbml_w.writer;
1764 wr.write_be_u32(i as u32);
1766 rbml_w.end_tag(); // tag_lang_items_item_id
1768 rbml_w.start_tag(tag_lang_items_item_node_id);
1770 let wr: &mut SeekableMemWriter = rbml_w.writer;
1771 wr.write_be_u32(id.node as u32);
1773 rbml_w.end_tag(); // tag_lang_items_item_node_id
1775 rbml_w.end_tag(); // tag_lang_items_item
1780 for i in ecx.tcx.lang_items.missing.iter() {
1781 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1784 rbml_w.end_tag(); // tag_lang_items
1787 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1788 rbml_w.start_tag(tag_native_libraries);
1790 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1793 cstore::NativeStatic => {} // these libraries are not propagated
1794 cstore::NativeFramework | cstore::NativeUnknown => {
1795 rbml_w.start_tag(tag_native_libraries_lib);
1797 rbml_w.start_tag(tag_native_libraries_kind);
1798 rbml_w.writer.write_be_u32(kind as u32);
1801 rbml_w.start_tag(tag_native_libraries_name);
1802 rbml_w.writer.write(lib.as_bytes());
1813 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1814 match ecx.tcx.sess.plugin_registrar_fn.get() {
1815 Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1820 /// Given a span, write the text of that span into the output stream
1821 /// as an exported macro
1822 fn encode_macro_def(ecx: &EncodeContext,
1823 rbml_w: &mut Encoder,
1824 span: &syntax::codemap::Span) {
1825 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1826 .expect("Unable to find source for macro");
1827 rbml_w.start_tag(tag_macro_def);
1828 rbml_w.wr_str(def[]);
1832 /// Serialize the text of the exported macros
1833 fn encode_macro_defs(ecx: &EncodeContext,
1835 rbml_w: &mut Encoder) {
1836 rbml_w.start_tag(tag_exported_macros);
1837 for item in krate.exported_macros.iter() {
1838 encode_macro_def(ecx, rbml_w, &item.span);
1843 fn encode_unboxed_closures<'a>(
1844 ecx: &'a EncodeContext,
1845 rbml_w: &'a mut Encoder) {
1846 rbml_w.start_tag(tag_unboxed_closures);
1847 for (unboxed_closure_id, unboxed_closure) in ecx.tcx
1851 if unboxed_closure_id.krate != ast::LOCAL_CRATE {
1855 rbml_w.start_tag(tag_unboxed_closure);
1856 encode_def_id(rbml_w, *unboxed_closure_id);
1857 rbml_w.start_tag(tag_unboxed_closure_type);
1858 write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
1860 encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
1866 fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
1867 struct StructFieldVisitor<'a, 'b:'a> {
1868 rbml_w: &'a mut Encoder<'b>,
1871 impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
1872 fn visit_struct_field(&mut self, field: &ast::StructField) {
1873 self.rbml_w.start_tag(tag_struct_field);
1874 self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
1875 encode_attributes(self.rbml_w, field.node.attrs[]);
1876 self.rbml_w.end_tag();
1880 rbml_w.start_tag(tag_struct_fields);
1881 visit::walk_crate(&mut StructFieldVisitor {
1889 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1890 ecx: &'a EncodeContext<'b, 'tcx>,
1891 rbml_w: &'a mut Encoder<'c>,
1894 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
1895 fn visit_item(&mut self, item: &ast::Item) {
1896 if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
1897 let def_map = &self.ecx.tcx.def_map;
1898 let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
1899 let def_id = trait_def.def_id();
1901 // Load eagerly if this is an implementation of the Drop trait
1902 // or if the trait is not defined in this crate.
1903 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1904 def_id.krate != ast::LOCAL_CRATE {
1905 self.rbml_w.start_tag(tag_impls_impl);
1906 encode_def_id(self.rbml_w, local_def(item.id));
1907 self.rbml_w.end_tag();
1910 visit::walk_item(self, item);
1914 /// Encodes implementations that are eagerly loaded.
1916 /// None of this is necessary in theory; we can load all implementations
1917 /// lazily. However, in two cases the optimizations to lazily load
1918 /// implementations are not yet implemented. These two cases, which require us
1919 /// to load implementations eagerly, are:
1921 /// * Destructors (implementations of the Drop trait).
1923 /// * Implementations of traits not defined in this crate.
1924 fn encode_impls<'a>(ecx: &'a EncodeContext,
1926 rbml_w: &'a mut Encoder) {
1927 rbml_w.start_tag(tag_impls);
1930 let mut visitor = ImplVisitor {
1934 visit::walk_crate(&mut visitor, krate);
1940 fn encode_misc_info(ecx: &EncodeContext,
1942 rbml_w: &mut Encoder) {
1943 rbml_w.start_tag(tag_misc_info);
1944 rbml_w.start_tag(tag_misc_info_crate_items);
1945 for item in krate.module.items.iter() {
1946 rbml_w.start_tag(tag_mod_child);
1947 rbml_w.wr_str(def_to_string(local_def(item.id))[]);
1950 each_auxiliary_node_id(&**item, |auxiliary_node_id| {
1951 rbml_w.start_tag(tag_mod_child);
1952 rbml_w.wr_str(def_to_string(local_def(
1953 auxiliary_node_id))[]);
1959 // Encode reexports for the root module.
1960 encode_reexports(ecx, rbml_w, 0, ast_map::Values([].iter()).chain(None));
1966 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1967 rbml_w.start_tag(tag_reachable_extern_fns);
1969 for id in ecx.reachable.iter() {
1970 if let Some(ast_map::NodeItem(i)) = ecx.tcx.map.find(*id) {
1971 if let ast::ItemFn(_, _, abi, ref generics, _) = i.node {
1972 if abi != abi::Rust && !generics.is_type_parameterized() {
1973 rbml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1982 fn encode_crate_dep(rbml_w: &mut Encoder,
1983 dep: decoder::CrateDep) {
1984 rbml_w.start_tag(tag_crate_dep);
1985 rbml_w.start_tag(tag_crate_dep_crate_name);
1986 rbml_w.writer.write(dep.name.as_bytes());
1988 rbml_w.start_tag(tag_crate_dep_hash);
1989 rbml_w.writer.write(dep.hash.as_str().as_bytes());
1994 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
1995 rbml_w.start_tag(tag_crate_hash);
1996 rbml_w.writer.write(hash.as_str().as_bytes());
2000 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
2001 rbml_w.start_tag(tag_crate_crate_name);
2002 rbml_w.writer.write(crate_name.as_bytes());
2006 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
2007 rbml_w.start_tag(tag_crate_triple);
2008 rbml_w.writer.write(triple.as_bytes());
2012 fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
2013 rbml_w.start_tag(tag_dylib_dependency_formats);
2014 match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) {
2016 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
2017 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
2018 cstore::RequireDynamic => "d",
2019 cstore::RequireStatic => "s",
2021 }).collect::<Vec<String>>();
2022 rbml_w.writer.write(s.connect(",").as_bytes());
2029 // NB: Increment this as you change the metadata encoding version.
2030 #[allow(non_upper_case_globals)]
2031 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ];
2033 pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
2034 let mut wr = SeekableMemWriter::new();
2035 encode_metadata_inner(&mut wr, parms, krate);
2036 let mut v = wr.unwrap();
2038 // And here we run into yet another obscure archive bug: in which metadata
2039 // loaded from archives may have trailing garbage bytes. Awhile back one of
2040 // our tests was failing sporadially on the OSX 64-bit builders (both nopt
2041 // and opt) by having rbml generate an out-of-bounds panic when looking at
2044 // Upon investigation it turned out that the metadata file inside of an rlib
2045 // (and ar archive) was being corrupted. Some compilations would generate a
2046 // metadata file which would end in a few extra bytes, while other
2047 // compilations would not have these extra bytes appended to the end. These
2048 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2049 // being interpreted causing the out-of-bounds.
2051 // The root cause of why these extra bytes were appearing was never
2052 // discovered, and in the meantime the solution we're employing is to insert
2053 // the length of the metadata to the start of the metadata. Later on this
2054 // will allow us to slice the metadata to the precise length that we just
2055 // generated regardless of trailing bytes that end up in it.
2056 let len = v.len() as u32;
2057 v.insert(0, (len >> 0) as u8);
2058 v.insert(0, (len >> 8) as u8);
2059 v.insert(0, (len >> 16) as u8);
2060 v.insert(0, (len >> 24) as u8);
2064 fn encode_metadata_inner(wr: &mut SeekableMemWriter,
2065 parms: EncodeParams,
2066 krate: &ast::Crate) {
2070 lang_item_bytes: u64,
2071 native_lib_bytes: u64,
2072 plugin_registrar_fn_bytes: u64,
2073 macro_defs_bytes: u64,
2074 unboxed_closure_bytes: u64,
2082 let mut stats = Stats {
2086 native_lib_bytes: 0,
2087 plugin_registrar_fn_bytes: 0,
2088 macro_defs_bytes: 0,
2089 unboxed_closure_bytes: 0,
2103 encode_inlined_item,
2108 let ecx = EncodeContext {
2111 reexports: reexports,
2112 item_symbols: item_symbols,
2113 link_meta: link_meta,
2115 encode_inlined_item: RefCell::new(encode_inlined_item),
2116 type_abbrevs: RefCell::new(FnvHashMap::new()),
2117 reachable: reachable,
2120 let mut rbml_w = writer::Encoder::new(wr);
2122 encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name[]);
2123 encode_crate_triple(&mut rbml_w,
2128 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2129 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2131 let mut i = rbml_w.writer.tell().unwrap();
2132 encode_attributes(&mut rbml_w, krate.attrs[]);
2133 stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
2135 i = rbml_w.writer.tell().unwrap();
2136 encode_crate_deps(&mut rbml_w, ecx.cstore);
2137 stats.dep_bytes = rbml_w.writer.tell().unwrap() - i;
2139 // Encode the language items.
2140 i = rbml_w.writer.tell().unwrap();
2141 encode_lang_items(&ecx, &mut rbml_w);
2142 stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i;
2144 // Encode the native libraries used
2145 i = rbml_w.writer.tell().unwrap();
2146 encode_native_libraries(&ecx, &mut rbml_w);
2147 stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i;
2149 // Encode the plugin registrar function
2150 i = rbml_w.writer.tell().unwrap();
2151 encode_plugin_registrar_fn(&ecx, &mut rbml_w);
2152 stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i;
2154 // Encode macro definitions
2155 i = rbml_w.writer.tell().unwrap();
2156 encode_macro_defs(&ecx, krate, &mut rbml_w);
2157 stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
2159 // Encode the types of all unboxed closures in this crate.
2160 i = rbml_w.writer.tell().unwrap();
2161 encode_unboxed_closures(&ecx, &mut rbml_w);
2162 stats.unboxed_closure_bytes = rbml_w.writer.tell().unwrap() - i;
2164 // Encode the def IDs of impls, for coherence checking.
2165 i = rbml_w.writer.tell().unwrap();
2166 encode_impls(&ecx, krate, &mut rbml_w);
2167 stats.impl_bytes = rbml_w.writer.tell().unwrap() - i;
2169 // Encode miscellaneous info.
2170 i = rbml_w.writer.tell().unwrap();
2171 encode_misc_info(&ecx, krate, &mut rbml_w);
2172 encode_reachable_extern_fns(&ecx, &mut rbml_w);
2173 stats.misc_bytes = rbml_w.writer.tell().unwrap() - i;
2175 // Encode and index the items.
2176 rbml_w.start_tag(tag_items);
2177 i = rbml_w.writer.tell().unwrap();
2178 let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
2179 stats.item_bytes = rbml_w.writer.tell().unwrap() - i;
2181 i = rbml_w.writer.tell().unwrap();
2182 encode_index(&mut rbml_w, items_index, write_i64);
2183 stats.index_bytes = rbml_w.writer.tell().unwrap() - i;
2186 encode_struct_field_attrs(&mut rbml_w, krate);
2188 stats.total_bytes = rbml_w.writer.tell().unwrap();
2190 if tcx.sess.meta_stats() {
2191 for e in rbml_w.writer.get_ref().iter() {
2193 stats.zero_bytes += 1;
2197 println!("metadata stats:");
2198 println!(" attribute bytes: {}", stats.attr_bytes);
2199 println!(" dep bytes: {}", stats.dep_bytes);
2200 println!(" lang item bytes: {}", stats.lang_item_bytes);
2201 println!(" native bytes: {}", stats.native_lib_bytes);
2202 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
2203 println!(" macro def bytes: {}", stats.macro_defs_bytes);
2204 println!(" unboxed closure bytes: {}", stats.unboxed_closure_bytes);
2205 println!(" impl bytes: {}", stats.impl_bytes);
2206 println!(" misc bytes: {}", stats.misc_bytes);
2207 println!(" item bytes: {}", stats.item_bytes);
2208 println!(" index bytes: {}", stats.index_bytes);
2209 println!(" zero bytes: {}", stats.zero_bytes);
2210 println!(" total bytes: {}", stats.total_bytes);
2214 // Get the encoded string for a type
2215 pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
2216 let mut wr = SeekableMemWriter::new();
2217 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
2218 diag: tcx.sess.diagnostic(),
2221 abbrevs: &RefCell::new(FnvHashMap::new())
2223 String::from_utf8(wr.unwrap()).unwrap()