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)]
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
;
32 use std
::hash
::{Hash, Hasher, SipHasher}
;
33 use std
::io
::prelude
::*;
34 use std
::io
::{Cursor, SeekFrom}
;
36 use syntax
::ast
::{self, DefId, NodeId}
;
37 use syntax
::ast_map
::{self, LinkedPath, PathElem, PathElems}
;
38 use syntax
::ast_util
::*;
41 use syntax
::attr
::AttrMetaMethods
;
42 use syntax
::diagnostic
::SpanHandler
;
43 use syntax
::parse
::token
::special_idents
;
44 use syntax
::parse
::token
;
45 use syntax
::print
::pprust
;
47 use syntax
::visit
::Visitor
;
50 use rbml
::writer
::Encoder
;
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 EncodeInlinedItem
<'a
> =
61 Box
<FnMut(&EncodeContext
, &mut Encoder
, InlinedItemRef
) + 'a
>;
63 pub struct EncodeParams
<'a
, 'tcx
: 'a
> {
64 pub diag
: &'a SpanHandler
,
65 pub tcx
: &'a ty
::ctxt
<'tcx
>,
66 pub reexports
: &'a def
::ExportMap
,
67 pub item_symbols
: &'a RefCell
<NodeMap
<String
>>,
68 pub link_meta
: &'a LinkMeta
,
69 pub cstore
: &'a cstore
::CStore
,
70 pub encode_inlined_item
: EncodeInlinedItem
<'a
>,
71 pub reachable
: &'a NodeSet
,
74 pub struct EncodeContext
<'a
, 'tcx
: 'a
> {
75 pub diag
: &'a SpanHandler
,
76 pub tcx
: &'a ty
::ctxt
<'tcx
>,
77 pub reexports
: &'a def
::ExportMap
,
78 pub item_symbols
: &'a RefCell
<NodeMap
<String
>>,
79 pub link_meta
: &'a LinkMeta
,
80 pub cstore
: &'a cstore
::CStore
,
81 pub encode_inlined_item
: RefCell
<EncodeInlinedItem
<'a
>>,
82 pub type_abbrevs
: tyencode
::abbrev_map
<'tcx
>,
83 pub reachable
: &'a NodeSet
,
86 fn encode_name(rbml_w
: &mut Encoder
, name
: ast
::Name
) {
87 rbml_w
.wr_tagged_str(tag_paths_data_name
, &token
::get_name(name
));
90 fn encode_impl_type_basename(rbml_w
: &mut Encoder
, name
: ast
::Name
) {
91 rbml_w
.wr_tagged_str(tag_item_impl_type_basename
, &token
::get_name(name
));
94 fn encode_def_id(rbml_w
: &mut Encoder
, id
: DefId
) {
95 rbml_w
.wr_tagged_u64(tag_def_id
, def_to_u64(id
));
104 fn encode_trait_ref
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
105 ecx
: &EncodeContext
<'a
, 'tcx
>,
106 trait_ref
: ty
::TraitRef
<'tcx
>,
108 let ty_str_ctxt
= &tyencode
::ctxt
{
112 abbrevs
: &ecx
.type_abbrevs
115 rbml_w
.start_tag(tag
);
116 tyencode
::enc_trait_ref(rbml_w
, ty_str_ctxt
, trait_ref
);
120 // Item info table encoding
121 fn encode_family(rbml_w
: &mut Encoder
, c
: char) {
122 rbml_w
.wr_tagged_u8(tag_items_data_item_family
, c
as u8);
125 pub fn def_to_u64(did
: DefId
) -> u64 {
126 (did
.krate
as u64) << 32 | (did
.node
as u64)
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_for_item
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
143 ecx
: &EncodeContext
<'a
, 'tcx
>,
145 encode_bounds_and_type(rbml_w
,
147 &ty
::lookup_item_type(ecx
.tcx
, local_def(id
)),
148 &ty
::lookup_predicates(ecx
.tcx
, local_def(id
)));
151 fn encode_bounds_and_type
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
152 ecx
: &EncodeContext
<'a
, 'tcx
>,
153 scheme
: &ty
::TypeScheme
<'tcx
>,
154 predicates
: &ty
::GenericPredicates
<'tcx
>) {
155 encode_generics(rbml_w
, ecx
, &scheme
.generics
, &predicates
, tag_item_generics
);
156 encode_type(ecx
, rbml_w
, scheme
.ty
);
159 fn encode_variant_id(rbml_w
: &mut Encoder
, vid
: DefId
) {
160 let id
= def_to_u64(vid
);
161 rbml_w
.wr_tagged_u64(tag_items_data_item_variant
, id
);
162 rbml_w
.wr_tagged_u64(tag_mod_child
, id
);
165 pub fn write_closure_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
166 rbml_w
: &mut Encoder
,
167 closure_type
: &ty
::ClosureTy
<'tcx
>) {
168 let ty_str_ctxt
= &tyencode
::ctxt
{
172 abbrevs
: &ecx
.type_abbrevs
174 tyencode
::enc_closure_ty(rbml_w
, ty_str_ctxt
, closure_type
);
177 pub fn write_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
178 rbml_w
: &mut Encoder
,
180 let ty_str_ctxt
= &tyencode
::ctxt
{
184 abbrevs
: &ecx
.type_abbrevs
186 tyencode
::enc_ty(rbml_w
, ty_str_ctxt
, typ
);
189 pub fn write_trait_ref
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
190 rbml_w
: &mut Encoder
,
191 trait_ref
: &ty
::TraitRef
<'tcx
>) {
192 let ty_str_ctxt
= &tyencode
::ctxt
{
196 abbrevs
: &ecx
.type_abbrevs
198 tyencode
::enc_trait_ref(rbml_w
, ty_str_ctxt
, *trait_ref
);
201 pub fn write_region(ecx
: &EncodeContext
,
202 rbml_w
: &mut Encoder
,
204 let ty_str_ctxt
= &tyencode
::ctxt
{
208 abbrevs
: &ecx
.type_abbrevs
210 tyencode
::enc_region(rbml_w
, ty_str_ctxt
, r
);
213 fn encode_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
214 rbml_w
: &mut Encoder
,
216 rbml_w
.start_tag(tag_items_data_item_type
);
217 write_type(ecx
, rbml_w
, typ
);
221 fn encode_region(ecx
: &EncodeContext
,
222 rbml_w
: &mut Encoder
,
224 rbml_w
.start_tag(tag_items_data_region
);
225 write_region(ecx
, rbml_w
, r
);
229 fn encode_method_fty
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
230 rbml_w
: &mut Encoder
,
231 typ
: &ty
::BareFnTy
<'tcx
>) {
232 rbml_w
.start_tag(tag_item_method_fty
);
234 let ty_str_ctxt
= &tyencode
::ctxt
{
238 abbrevs
: &ecx
.type_abbrevs
240 tyencode
::enc_bare_fn_ty(rbml_w
, ty_str_ctxt
, typ
);
245 fn encode_symbol(ecx
: &EncodeContext
,
246 rbml_w
: &mut Encoder
,
248 match ecx
.item_symbols
.borrow().get(&id
) {
250 debug
!("encode_symbol(id={}, str={})", id
, *x
);
251 rbml_w
.wr_tagged_str(tag_items_data_item_symbol
, x
);
254 ecx
.diag
.handler().bug(
255 &format
!("encode_symbol: id not found {}", id
));
260 fn encode_disr_val(_
: &EncodeContext
,
261 rbml_w
: &mut Encoder
,
262 disr_val
: ty
::Disr
) {
263 rbml_w
.wr_tagged_str(tag_disr_val
, &disr_val
.to_string());
266 fn encode_parent_item(rbml_w
: &mut Encoder
, id
: DefId
) {
267 rbml_w
.wr_tagged_u64(tag_items_data_parent_item
, def_to_u64(id
));
270 fn encode_struct_fields(rbml_w
: &mut Encoder
,
271 fields
: &[ty
::field_ty
],
274 if f
.name
== special_idents
::unnamed_field
.name
{
275 rbml_w
.start_tag(tag_item_unnamed_field
);
277 rbml_w
.start_tag(tag_item_field
);
278 encode_name(rbml_w
, f
.name
);
280 encode_struct_field_family(rbml_w
, f
.vis
);
281 encode_def_id(rbml_w
, f
.id
);
282 rbml_w
.wr_tagged_u64(tag_item_field_origin
, def_to_u64(origin
));
287 fn encode_enum_variant_info(ecx
: &EncodeContext
,
288 rbml_w
: &mut Encoder
,
290 variants
: &[P
<ast
::Variant
>],
291 index
: &mut Vec
<entry
<i64>>) {
292 debug
!("encode_enum_variant_info(id={})", id
);
294 let mut disr_val
= 0;
296 let vi
= ty
::enum_variants(ecx
.tcx
,
297 DefId { krate: ast::LOCAL_CRATE, node: id }
);
298 for variant
in variants
{
299 let def_id
= local_def(variant
.node
.id
);
301 val
: variant
.node
.id
as i64,
302 pos
: rbml_w
.mark_stable_position(),
304 rbml_w
.start_tag(tag_items_data_item
);
305 encode_def_id(rbml_w
, def_id
);
306 match variant
.node
.kind
{
307 ast
::TupleVariantKind(_
) => encode_family(rbml_w
, 'v'
),
308 ast
::StructVariantKind(_
) => encode_family(rbml_w
, 'V'
)
310 encode_name(rbml_w
, variant
.node
.name
.name
);
311 encode_parent_item(rbml_w
, local_def(id
));
312 encode_visibility(rbml_w
, variant
.node
.vis
);
313 encode_attributes(rbml_w
, &variant
.node
.attrs
);
314 encode_repr_attrs(rbml_w
, ecx
, &variant
.node
.attrs
);
316 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(variant
.node
.id
));
317 encode_stability(rbml_w
, stab
);
319 match variant
.node
.kind
{
320 ast
::TupleVariantKind(_
) => {}
,
321 ast
::StructVariantKind(_
) => {
322 let fields
= ty
::lookup_struct_fields(ecx
.tcx
, def_id
);
323 let idx
= encode_info_for_struct(ecx
,
327 encode_struct_fields(rbml_w
, &fields
[..], def_id
);
328 encode_index(rbml_w
, idx
, write_i64
);
331 if (*vi
)[i
].disr_val
!= disr_val
{
332 encode_disr_val(ecx
, rbml_w
, (*vi
)[i
].disr_val
);
333 disr_val
= (*vi
)[i
].disr_val
;
335 encode_bounds_and_type_for_item(rbml_w
, ecx
, def_id
.local_id());
337 ecx
.tcx
.map
.with_path(variant
.node
.id
, |path
| encode_path(rbml_w
, path
));
339 disr_val
= disr_val
.wrapping_add(1);
344 fn encode_path
<PI
: Iterator
<Item
=PathElem
>>(rbml_w
: &mut Encoder
, path
: PI
) {
345 let path
= path
.collect
::<Vec
<_
>>();
346 rbml_w
.start_tag(tag_path
);
347 rbml_w
.wr_tagged_u32(tag_path_len
, path
.len() as u32);
349 let tag
= match *pe
{
350 ast_map
::PathMod(_
) => tag_path_elem_mod
,
351 ast_map
::PathName(_
) => tag_path_elem_name
353 rbml_w
.wr_tagged_str(tag
, &token
::get_name(pe
.name()));
358 fn encode_reexported_static_method(rbml_w
: &mut Encoder
,
360 method_def_id
: DefId
,
361 method_name
: ast
::Name
) {
362 debug
!("(encode reexported static method) {}::{}",
363 exp
.name
, token
::get_name(method_name
));
364 rbml_w
.start_tag(tag_items_data_item_reexport
);
365 rbml_w
.wr_tagged_u64(tag_items_data_item_reexport_def_id
,
366 def_to_u64(method_def_id
));
367 rbml_w
.wr_tagged_str(tag_items_data_item_reexport_name
,
368 &format
!("{}::{}", exp
.name
,
369 token
::get_name(method_name
)));
373 fn encode_reexported_static_base_methods(ecx
: &EncodeContext
,
374 rbml_w
: &mut Encoder
,
377 let impl_items
= ecx
.tcx
.impl_items
.borrow();
378 match ecx
.tcx
.inherent_impls
.borrow().get(&exp
.def_id
) {
379 Some(implementations
) => {
380 for base_impl_did
in &**implementations
{
381 for &method_did
in impl_items
.get(base_impl_did
).unwrap() {
382 let impl_item
= ty
::impl_or_trait_item(
384 method_did
.def_id());
385 if let ty
::MethodTraitItem(ref m
) = impl_item
{
386 encode_reexported_static_method(rbml_w
,
400 fn encode_reexported_static_trait_methods(ecx
: &EncodeContext
,
401 rbml_w
: &mut Encoder
,
404 match ecx
.tcx
.trait_items_cache
.borrow().get(&exp
.def_id
) {
405 Some(trait_items
) => {
406 for trait_item
in &**trait_items
{
407 if let ty
::MethodTraitItem(ref m
) = *trait_item
{
408 encode_reexported_static_method(rbml_w
,
420 fn encode_reexported_static_methods(ecx
: &EncodeContext
,
421 rbml_w
: &mut Encoder
,
424 if let Some(ast_map
::NodeItem(item
)) = ecx
.tcx
.map
.find(exp
.def_id
.node
) {
425 let path_differs
= ecx
.tcx
.map
.with_path(exp
.def_id
.node
, |path
| {
426 let (mut a
, mut b
) = (path
, mod_path
.clone());
428 match (a
.next(), b
.next()) {
429 (None
, None
) => return true,
430 (None
, _
) | (_
, None
) => return false,
431 (Some(x
), Some(y
)) => if x
!= y { return false }
,
437 // We don't need to reexport static methods on items
438 // declared in the same module as our `pub use ...` since
439 // that's done when we encode the item itself.
441 // The only exception is when the reexport *changes* the
442 // name e.g. `pub use Foo = self::Bar` -- we have
443 // encoded metadata for static methods relative to Bar,
444 // but not yet for Foo.
446 if path_differs
|| item
.ident
.name
!= exp
.name
{
447 if !encode_reexported_static_base_methods(ecx
, rbml_w
, exp
) {
448 if encode_reexported_static_trait_methods(ecx
, rbml_w
, exp
) {
449 debug
!("(encode reexported static methods) {} [trait]",
454 debug
!("(encode reexported static methods) {} [base]",
461 /// Iterates through "auxiliary node IDs", which are node IDs that describe
462 /// top-level items that are sub-items of the given item. Specifically:
464 /// * For newtype structs, iterates through the node ID of the constructor.
465 fn each_auxiliary_node_id
<F
>(item
: &ast
::Item
, callback
: F
) -> bool
where
466 F
: FnOnce(NodeId
) -> bool
,
468 let mut continue_
= true;
470 ast
::ItemStruct(ref struct_def
, _
) => {
471 // If this is a newtype struct, return the constructor.
472 match struct_def
.ctor_id
{
473 Some(ctor_id
) if !struct_def
.fields
.is_empty() &&
474 struct_def
.fields
[0].node
.kind
.is_unnamed() => {
475 continue_
= callback(ctor_id
);
486 fn encode_reexports(ecx
: &EncodeContext
,
487 rbml_w
: &mut Encoder
,
490 debug
!("(encoding info for module) encoding reexports for {}", id
);
491 match ecx
.reexports
.get(&id
) {
493 debug
!("(encoding info for module) found reexports for {}", id
);
495 debug
!("(encoding info for module) reexport '{}' ({}/{}) for \
501 rbml_w
.start_tag(tag_items_data_item_reexport
);
502 rbml_w
.wr_tagged_u64(tag_items_data_item_reexport_def_id
,
503 def_to_u64(exp
.def_id
));
504 rbml_w
.wr_tagged_str(tag_items_data_item_reexport_name
,
507 encode_reexported_static_methods(ecx
, rbml_w
, path
.clone(), exp
);
511 debug
!("(encoding info for module) found no reexports for {}",
517 fn encode_info_for_mod(ecx
: &EncodeContext
,
518 rbml_w
: &mut Encoder
,
520 attrs
: &[ast
::Attribute
],
524 vis
: ast
::Visibility
) {
525 rbml_w
.start_tag(tag_items_data_item
);
526 encode_def_id(rbml_w
, local_def(id
));
527 encode_family(rbml_w
, 'm'
);
528 encode_name(rbml_w
, name
);
529 debug
!("(encoding info for module) encoding info for module ID {}", id
);
531 // Encode info about all the module children.
532 for item
in &md
.items
{
533 rbml_w
.wr_tagged_u64(tag_mod_child
,
534 def_to_u64(local_def(item
.id
)));
536 each_auxiliary_node_id(&**item
, |auxiliary_node_id
| {
537 rbml_w
.wr_tagged_u64(tag_mod_child
,
538 def_to_u64(local_def(auxiliary_node_id
)));
542 if let ast
::ItemImpl(..) = item
.node
{
543 let (ident
, did
) = (item
.ident
, item
.id
);
544 debug
!("(encoding info for module) ... encoding impl {} ({}/{})",
545 token
::get_ident(ident
),
546 did
, ecx
.tcx
.map
.node_to_string(did
));
548 rbml_w
.wr_tagged_u64(tag_mod_impl
, def_to_u64(local_def(did
)));
552 encode_path(rbml_w
, path
.clone());
553 encode_visibility(rbml_w
, vis
);
555 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(id
));
556 encode_stability(rbml_w
, stab
);
558 // Encode the reexports of this module, if this module is public.
559 if vis
== ast
::Public
{
560 debug
!("(encoding info for module) encoding reexports for {}", id
);
561 encode_reexports(ecx
, rbml_w
, id
, path
);
563 encode_attributes(rbml_w
, attrs
);
568 fn encode_struct_field_family(rbml_w
: &mut Encoder
,
569 visibility
: ast
::Visibility
) {
570 encode_family(rbml_w
, match visibility
{
572 ast
::Inherited
=> 'N'
576 fn encode_visibility(rbml_w
: &mut Encoder
, visibility
: ast
::Visibility
) {
577 let ch
= match visibility
{
579 ast
::Inherited
=> 'i'
,
581 rbml_w
.wr_tagged_u8(tag_items_data_item_visibility
, ch
as u8);
584 fn encode_explicit_self(rbml_w
: &mut Encoder
,
585 explicit_self
: &ty
::ExplicitSelfCategory
) {
586 let tag
= tag_item_trait_method_explicit_self
;
588 // Encode the base self type.
589 match *explicit_self
{
590 ty
::StaticExplicitSelfCategory
=> {
591 rbml_w
.wr_tagged_bytes(tag
, &['s'
as u8]);
593 ty
::ByValueExplicitSelfCategory
=> {
594 rbml_w
.wr_tagged_bytes(tag
, &['v'
as u8]);
596 ty
::ByBoxExplicitSelfCategory
=> {
597 rbml_w
.wr_tagged_bytes(tag
, &['
~'
as u8]);
599 ty
::ByReferenceExplicitSelfCategory(_
, m
) => {
600 // FIXME(#4846) encode custom lifetime
601 let ch
= encode_mutability(m
);
602 rbml_w
.wr_tagged_bytes(tag
, &['
&'
as u8, ch
]);
606 fn encode_mutability(m
: ast
::Mutability
) -> u8 {
608 ast
::MutImmutable
=> 'i'
as u8,
609 ast
::MutMutable
=> 'm'
as u8,
614 fn encode_item_sort(rbml_w
: &mut Encoder
, sort
: char) {
615 rbml_w
.wr_tagged_u8(tag_item_trait_item_sort
, sort
as u8);
618 fn encode_parent_sort(rbml_w
: &mut Encoder
, sort
: char) {
619 rbml_w
.wr_tagged_u8(tag_item_trait_parent_sort
, sort
as u8);
622 fn encode_provided_source(rbml_w
: &mut Encoder
,
623 source_opt
: Option
<DefId
>) {
624 if let Some(source
) = source_opt
{
625 rbml_w
.wr_tagged_u64(tag_item_method_provided_source
, def_to_u64(source
));
629 /* Returns an index of items in this class */
630 fn encode_info_for_struct(ecx
: &EncodeContext
,
631 rbml_w
: &mut Encoder
,
632 fields
: &[ty
::field_ty
],
633 global_index
: &mut Vec
<entry
<i64>>)
635 /* Each class has its own index, since different classes
636 may have fields with the same name */
637 let mut index
= Vec
::new();
638 /* We encode both private and public fields -- need to include
639 private fields to get the offsets right */
640 for field
in fields
{
642 let id
= field
.id
.node
;
644 let pos
= rbml_w
.mark_stable_position();
645 index
.push(entry {val: id as i64, pos: pos}
);
646 global_index
.push(entry
{
650 rbml_w
.start_tag(tag_items_data_item
);
651 debug
!("encode_info_for_struct: doing {} {}",
652 token
::get_name(nm
), id
);
653 encode_struct_field_family(rbml_w
, field
.vis
);
654 encode_name(rbml_w
, nm
);
655 encode_bounds_and_type_for_item(rbml_w
, ecx
, id
);
656 encode_def_id(rbml_w
, local_def(id
));
658 let stab
= stability
::lookup(ecx
.tcx
, field
.id
);
659 encode_stability(rbml_w
, stab
);
666 fn encode_info_for_struct_ctor(ecx
: &EncodeContext
,
667 rbml_w
: &mut Encoder
,
670 index
: &mut Vec
<entry
<i64>>,
674 pos
: rbml_w
.mark_stable_position(),
677 rbml_w
.start_tag(tag_items_data_item
);
678 encode_def_id(rbml_w
, local_def(ctor_id
));
679 encode_family(rbml_w
, 'o'
);
680 encode_bounds_and_type_for_item(rbml_w
, ecx
, ctor_id
);
681 encode_name(rbml_w
, name
);
682 ecx
.tcx
.map
.with_path(ctor_id
, |path
| encode_path(rbml_w
, path
));
683 encode_parent_item(rbml_w
, local_def(struct_id
));
685 if ecx
.item_symbols
.borrow().contains_key(&ctor_id
) {
686 encode_symbol(ecx
, rbml_w
, ctor_id
);
689 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(ctor_id
));
690 encode_stability(rbml_w
, stab
);
692 // indicate that this is a tuple struct ctor, because downstream users will normally want
693 // the tuple struct definition, but without this there is no way for them to tell that
694 // they actually have a ctor rather than a normal function
695 rbml_w
.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor
, &[]);
700 fn encode_generics
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
701 ecx
: &EncodeContext
<'a
, 'tcx
>,
702 generics
: &ty
::Generics
<'tcx
>,
703 predicates
: &ty
::GenericPredicates
<'tcx
>,
706 rbml_w
.start_tag(tag
);
709 let ty_str_ctxt
= &tyencode
::ctxt
{
713 abbrevs
: &ecx
.type_abbrevs
716 for param
in generics
.types
.iter() {
717 rbml_w
.start_tag(tag_type_param_def
);
718 tyencode
::enc_type_param_def(rbml_w
, ty_str_ctxt
, param
);
723 for param
in generics
.regions
.iter() {
724 rbml_w
.start_tag(tag_region_param_def
);
726 rbml_w
.start_tag(tag_region_param_def_ident
);
727 encode_name(rbml_w
, param
.name
);
730 rbml_w
.wr_tagged_u64(tag_region_param_def_def_id
,
731 def_to_u64(param
.def_id
));
733 rbml_w
.wr_tagged_u64(tag_region_param_def_space
,
734 param
.space
.to_uint() as u64);
736 rbml_w
.wr_tagged_u64(tag_region_param_def_index
,
739 for &bound_region
in ¶m
.bounds
{
740 encode_region(ecx
, rbml_w
, bound_region
);
746 encode_predicates_in_current_doc(rbml_w
, ecx
, predicates
);
751 fn encode_predicates_in_current_doc
<'a
,'tcx
>(rbml_w
: &mut Encoder
,
752 ecx
: &EncodeContext
<'a
,'tcx
>,
753 predicates
: &ty
::GenericPredicates
<'tcx
>)
755 let ty_str_ctxt
= &tyencode
::ctxt
{
759 abbrevs
: &ecx
.type_abbrevs
762 for (space
, _
, predicate
) in predicates
.predicates
.iter_enumerated() {
763 rbml_w
.start_tag(tag_predicate
);
765 rbml_w
.wr_tagged_u8(tag_predicate_space
, space
as u8);
767 rbml_w
.start_tag(tag_predicate_data
);
768 tyencode
::enc_predicate(rbml_w
, ty_str_ctxt
, predicate
);
775 fn encode_predicates
<'a
,'tcx
>(rbml_w
: &mut Encoder
,
776 ecx
: &EncodeContext
<'a
,'tcx
>,
777 predicates
: &ty
::GenericPredicates
<'tcx
>,
780 rbml_w
.start_tag(tag
);
781 encode_predicates_in_current_doc(rbml_w
, ecx
, predicates
);
785 fn encode_method_ty_fields
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
786 rbml_w
: &mut Encoder
,
787 method_ty
: &ty
::Method
<'tcx
>) {
788 encode_def_id(rbml_w
, method_ty
.def_id
);
789 encode_name(rbml_w
, method_ty
.name
);
790 encode_generics(rbml_w
, ecx
, &method_ty
.generics
, &method_ty
.predicates
,
791 tag_method_ty_generics
);
792 encode_method_fty(ecx
, rbml_w
, &method_ty
.fty
);
793 encode_visibility(rbml_w
, method_ty
.vis
);
794 encode_explicit_self(rbml_w
, &method_ty
.explicit_self
);
795 match method_ty
.explicit_self
{
796 ty
::StaticExplicitSelfCategory
=> {
797 encode_family(rbml_w
, STATIC_METHOD_FAMILY
);
799 _
=> encode_family(rbml_w
, METHOD_FAMILY
)
801 encode_provided_source(rbml_w
, method_ty
.provided_source
);
804 fn encode_info_for_associated_const(ecx
: &EncodeContext
,
805 rbml_w
: &mut Encoder
,
806 associated_const
: &ty
::AssociatedConst
,
807 impl_path
: PathElems
,
809 impl_item_opt
: Option
<&ast
::ImplItem
>) {
810 debug
!("encode_info_for_associated_const({:?},{:?})",
811 associated_const
.def_id
,
812 token
::get_name(associated_const
.name
));
814 rbml_w
.start_tag(tag_items_data_item
);
816 encode_def_id(rbml_w
, associated_const
.def_id
);
817 encode_name(rbml_w
, associated_const
.name
);
818 encode_visibility(rbml_w
, associated_const
.vis
);
819 encode_family(rbml_w
, 'C'
);
820 encode_provided_source(rbml_w
, associated_const
.default);
822 encode_parent_item(rbml_w
, local_def(parent_id
));
823 encode_item_sort(rbml_w
, 'C'
);
825 encode_bounds_and_type_for_item(rbml_w
, ecx
, associated_const
.def_id
.local_id());
827 let stab
= stability
::lookup(ecx
.tcx
, associated_const
.def_id
);
828 encode_stability(rbml_w
, stab
);
830 let elem
= ast_map
::PathName(associated_const
.name
);
831 encode_path(rbml_w
, impl_path
.chain(Some(elem
).into_iter()));
833 if let Some(ii
) = impl_item_opt
{
834 encode_attributes(rbml_w
, &ii
.attrs
);
835 encode_inlined_item(ecx
, rbml_w
, IIImplItemRef(local_def(parent_id
), ii
));
841 fn encode_info_for_method
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
842 rbml_w
: &mut Encoder
,
843 m
: &ty
::Method
<'tcx
>,
844 impl_path
: PathElems
,
845 is_default_impl
: bool
,
847 impl_item_opt
: Option
<&ast
::ImplItem
>) {
849 debug
!("encode_info_for_method: {:?} {:?}", m
.def_id
,
850 token
::get_name(m
.name
));
851 rbml_w
.start_tag(tag_items_data_item
);
853 encode_method_ty_fields(ecx
, rbml_w
, m
);
854 encode_parent_item(rbml_w
, local_def(parent_id
));
855 encode_item_sort(rbml_w
, 'r'
);
857 let stab
= stability
::lookup(ecx
.tcx
, m
.def_id
);
858 encode_stability(rbml_w
, stab
);
860 // The type for methods gets encoded twice, which is unfortunate.
861 encode_bounds_and_type_for_item(rbml_w
, ecx
, m
.def_id
.local_id());
863 let elem
= ast_map
::PathName(m
.name
);
864 encode_path(rbml_w
, impl_path
.chain(Some(elem
).into_iter()));
865 if let Some(impl_item
) = impl_item_opt
{
866 if let ast
::MethodImplItem(ref sig
, _
) = impl_item
.node
{
867 encode_attributes(rbml_w
, &impl_item
.attrs
);
868 let scheme
= ty
::lookup_item_type(ecx
.tcx
, m
.def_id
);
869 let any_types
= !scheme
.generics
.types
.is_empty();
870 if any_types
|| is_default_impl
|| attr
::requests_inline(&impl_item
.attrs
) {
871 encode_inlined_item(ecx
, rbml_w
, IIImplItemRef(local_def(parent_id
),
875 encode_symbol(ecx
, rbml_w
, m
.def_id
.node
);
877 encode_method_argument_names(rbml_w
, &sig
.decl
);
884 fn encode_info_for_associated_type(ecx
: &EncodeContext
,
885 rbml_w
: &mut Encoder
,
886 associated_type
: &ty
::AssociatedType
,
887 impl_path
: PathElems
,
889 impl_item_opt
: Option
<&ast
::ImplItem
>) {
890 debug
!("encode_info_for_associated_type({:?},{:?})",
891 associated_type
.def_id
,
892 token
::get_name(associated_type
.name
));
894 rbml_w
.start_tag(tag_items_data_item
);
896 encode_def_id(rbml_w
, associated_type
.def_id
);
897 encode_name(rbml_w
, associated_type
.name
);
898 encode_visibility(rbml_w
, associated_type
.vis
);
899 encode_family(rbml_w
, 'y'
);
900 encode_parent_item(rbml_w
, local_def(parent_id
));
901 encode_item_sort(rbml_w
, 't'
);
903 encode_bounds_and_type_for_item(rbml_w
, ecx
, associated_type
.def_id
.local_id());
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()));
911 if let Some(ii
) = impl_item_opt
{
912 encode_attributes(rbml_w
, &ii
.attrs
);
913 encode_type(ecx
, rbml_w
, ty
::node_id_to_type(ecx
.tcx
, ii
.id
));
919 fn encode_method_argument_names(rbml_w
: &mut Encoder
,
920 decl
: &ast
::FnDecl
) {
921 rbml_w
.start_tag(tag_method_argument_names
);
922 for arg
in &decl
.inputs
{
923 let tag
= tag_method_argument_name
;
924 if let ast
::PatIdent(_
, ref path1
, _
) = arg
.pat
.node
{
925 let name
= token
::get_name(path1
.node
.name
);
926 rbml_w
.wr_tagged_bytes(tag
, name
.as_bytes());
928 rbml_w
.wr_tagged_bytes(tag
, &[]);
934 fn encode_repr_attrs(rbml_w
: &mut Encoder
,
936 attrs
: &[ast
::Attribute
]) {
937 let mut repr_attrs
= Vec
::new();
939 repr_attrs
.extend(attr
::find_repr_attrs(ecx
.tcx
.sess
.diagnostic(),
942 rbml_w
.start_tag(tag_items_data_item_repr
);
943 repr_attrs
.encode(rbml_w
);
947 fn encode_inlined_item(ecx
: &EncodeContext
,
948 rbml_w
: &mut Encoder
,
949 ii
: InlinedItemRef
) {
950 let mut eii
= ecx
.encode_inlined_item
.borrow_mut();
951 let eii
: &mut EncodeInlinedItem
= &mut *eii
;
955 const FN_FAMILY
: char = 'f'
;
956 const STATIC_METHOD_FAMILY
: char = 'F'
;
957 const METHOD_FAMILY
: char = 'h'
;
959 // Encodes the inherent implementations of a structure, enumeration, or trait.
960 fn encode_inherent_implementations(ecx
: &EncodeContext
,
961 rbml_w
: &mut Encoder
,
963 match ecx
.tcx
.inherent_impls
.borrow().get(&def_id
) {
965 Some(implementations
) => {
966 for &impl_def_id
in &**implementations
{
967 rbml_w
.start_tag(tag_items_data_item_inherent_impl
);
968 encode_def_id(rbml_w
, impl_def_id
);
975 // Encodes the implementations of a trait defined in this crate.
976 fn encode_extension_implementations(ecx
: &EncodeContext
,
977 rbml_w
: &mut Encoder
,
978 trait_def_id
: DefId
) {
979 assert
!(ast_util
::is_local(trait_def_id
));
980 let def
= ty
::lookup_trait_def(ecx
.tcx
, trait_def_id
);
982 def
.for_each_impl(ecx
.tcx
, |impl_def_id
| {
983 rbml_w
.start_tag(tag_items_data_item_extension_impl
);
984 encode_def_id(rbml_w
, impl_def_id
);
989 fn encode_stability(rbml_w
: &mut Encoder
, stab_opt
: Option
<attr
::Stability
>) {
990 stab_opt
.map(|stab
| {
991 rbml_w
.start_tag(tag_items_data_item_stability
);
992 stab
.encode(rbml_w
).unwrap();
997 fn encode_info_for_item(ecx
: &EncodeContext
,
998 rbml_w
: &mut Encoder
,
1000 index
: &mut Vec
<entry
<i64>>,
1002 vis
: ast
::Visibility
) {
1005 fn add_to_index(item
: &ast
::Item
, rbml_w
: &mut Encoder
,
1006 index
: &mut Vec
<entry
<i64>>) {
1008 val
: item
.id
as i64,
1009 pos
: rbml_w
.mark_stable_position(),
1013 debug
!("encoding info for item at {}",
1014 tcx
.sess
.codemap().span_to_string(item
.span
));
1016 let def_id
= local_def(item
.id
);
1017 let stab
= stability
::lookup(tcx
, ast_util
::local_def(item
.id
));
1020 ast
::ItemStatic(_
, m
, _
) => {
1021 add_to_index(item
, rbml_w
, index
);
1022 rbml_w
.start_tag(tag_items_data_item
);
1023 encode_def_id(rbml_w
, def_id
);
1024 if m
== ast
::MutMutable
{
1025 encode_family(rbml_w
, 'b'
);
1027 encode_family(rbml_w
, 'c'
);
1029 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1030 encode_symbol(ecx
, rbml_w
, item
.id
);
1031 encode_name(rbml_w
, item
.ident
.name
);
1032 encode_path(rbml_w
, path
);
1033 encode_visibility(rbml_w
, vis
);
1034 encode_stability(rbml_w
, stab
);
1035 encode_attributes(rbml_w
, &item
.attrs
);
1038 ast
::ItemConst(_
, _
) => {
1039 add_to_index(item
, rbml_w
, index
);
1040 rbml_w
.start_tag(tag_items_data_item
);
1041 encode_def_id(rbml_w
, def_id
);
1042 encode_family(rbml_w
, 'C'
);
1043 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1044 encode_name(rbml_w
, item
.ident
.name
);
1045 encode_path(rbml_w
, path
);
1046 encode_attributes(rbml_w
, &item
.attrs
);
1047 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1048 encode_visibility(rbml_w
, vis
);
1049 encode_stability(rbml_w
, stab
);
1052 ast
::ItemFn(ref decl
, _
, _
, ref generics
, _
) => {
1053 add_to_index(item
, rbml_w
, index
);
1054 rbml_w
.start_tag(tag_items_data_item
);
1055 encode_def_id(rbml_w
, def_id
);
1056 encode_family(rbml_w
, FN_FAMILY
);
1057 let tps_len
= generics
.ty_params
.len();
1058 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1059 encode_name(rbml_w
, item
.ident
.name
);
1060 encode_path(rbml_w
, path
);
1061 encode_attributes(rbml_w
, &item
.attrs
);
1062 if tps_len
> 0 || attr
::requests_inline(&item
.attrs
) {
1063 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1066 encode_symbol(ecx
, rbml_w
, item
.id
);
1068 encode_visibility(rbml_w
, vis
);
1069 encode_stability(rbml_w
, stab
);
1070 encode_method_argument_names(rbml_w
, &**decl
);
1073 ast
::ItemMod(ref m
) => {
1074 add_to_index(item
, rbml_w
, index
);
1075 encode_info_for_mod(ecx
,
1084 ast
::ItemForeignMod(ref fm
) => {
1085 add_to_index(item
, rbml_w
, index
);
1086 rbml_w
.start_tag(tag_items_data_item
);
1087 encode_def_id(rbml_w
, def_id
);
1088 encode_family(rbml_w
, 'n'
);
1089 encode_name(rbml_w
, item
.ident
.name
);
1090 encode_path(rbml_w
, path
);
1092 // Encode all the items in this module.
1093 for foreign_item
in &fm
.items
{
1094 rbml_w
.wr_tagged_u64(tag_mod_child
,
1095 def_to_u64(local_def(foreign_item
.id
)));
1097 encode_visibility(rbml_w
, vis
);
1098 encode_stability(rbml_w
, stab
);
1101 ast
::ItemTy(..) => {
1102 add_to_index(item
, rbml_w
, index
);
1103 rbml_w
.start_tag(tag_items_data_item
);
1104 encode_def_id(rbml_w
, def_id
);
1105 encode_family(rbml_w
, 'y'
);
1106 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1107 encode_name(rbml_w
, item
.ident
.name
);
1108 encode_path(rbml_w
, path
);
1109 encode_visibility(rbml_w
, vis
);
1110 encode_stability(rbml_w
, stab
);
1113 ast
::ItemEnum(ref enum_definition
, _
) => {
1114 add_to_index(item
, rbml_w
, index
);
1116 rbml_w
.start_tag(tag_items_data_item
);
1117 encode_def_id(rbml_w
, def_id
);
1118 encode_family(rbml_w
, 't'
);
1119 encode_item_variances(rbml_w
, ecx
, item
.id
);
1120 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1121 encode_name(rbml_w
, item
.ident
.name
);
1122 encode_attributes(rbml_w
, &item
.attrs
);
1123 encode_repr_attrs(rbml_w
, ecx
, &item
.attrs
);
1124 for v
in &enum_definition
.variants
{
1125 encode_variant_id(rbml_w
, local_def(v
.node
.id
));
1127 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1128 encode_path(rbml_w
, path
);
1130 // Encode inherent implementations for this enumeration.
1131 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1133 encode_visibility(rbml_w
, vis
);
1134 encode_stability(rbml_w
, stab
);
1137 encode_enum_variant_info(ecx
,
1140 &(*enum_definition
).variants
,
1143 ast
::ItemStruct(ref struct_def
, _
) => {
1144 let fields
= ty
::lookup_struct_fields(tcx
, def_id
);
1146 /* First, encode the fields
1147 These come first because we need to write them to make
1148 the index, and the index needs to be in the item for the
1150 let idx
= encode_info_for_struct(ecx
,
1155 /* Index the class*/
1156 add_to_index(item
, rbml_w
, index
);
1158 /* Now, make an item for the class itself */
1159 rbml_w
.start_tag(tag_items_data_item
);
1160 encode_def_id(rbml_w
, def_id
);
1161 encode_family(rbml_w
, 'S'
);
1162 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1164 encode_item_variances(rbml_w
, ecx
, item
.id
);
1165 encode_name(rbml_w
, item
.ident
.name
);
1166 encode_attributes(rbml_w
, &item
.attrs
);
1167 encode_path(rbml_w
, path
.clone());
1168 encode_stability(rbml_w
, stab
);
1169 encode_visibility(rbml_w
, vis
);
1170 encode_repr_attrs(rbml_w
, ecx
, &item
.attrs
);
1172 /* Encode def_ids for each field and method
1173 for methods, write all the stuff get_trait_method
1175 encode_struct_fields(rbml_w
, &fields
[..], def_id
);
1177 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1179 // Encode inherent implementations for this structure.
1180 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1182 /* Each class has its own index -- encode it */
1183 encode_index(rbml_w
, idx
, write_i64
);
1186 // If this is a tuple-like struct, encode the type of the constructor.
1187 match struct_def
.ctor_id
{
1189 encode_info_for_struct_ctor(ecx
, rbml_w
, item
.ident
.name
,
1190 ctor_id
, index
, def_id
.node
);
1195 ast
::ItemDefaultImpl(unsafety
, _
) => {
1196 add_to_index(item
, rbml_w
, index
);
1197 rbml_w
.start_tag(tag_items_data_item
);
1198 encode_def_id(rbml_w
, def_id
);
1199 encode_family(rbml_w
, 'd'
);
1200 encode_name(rbml_w
, item
.ident
.name
);
1201 encode_unsafety(rbml_w
, unsafety
);
1203 let trait_ref
= ty
::impl_id_to_trait_ref(tcx
, item
.id
);
1204 encode_trait_ref(rbml_w
, ecx
, trait_ref
, tag_item_trait_ref
);
1207 ast
::ItemImpl(unsafety
, polarity
, _
, ref opt_trait
, ref ty
, ref ast_items
) => {
1208 // We need to encode information about the default methods we
1209 // have inherited, so we drive this based on the impl structure.
1210 let impl_items
= tcx
.impl_items
.borrow();
1211 let items
= impl_items
.get(&def_id
).unwrap();
1213 add_to_index(item
, rbml_w
, index
);
1214 rbml_w
.start_tag(tag_items_data_item
);
1215 encode_def_id(rbml_w
, def_id
);
1216 encode_family(rbml_w
, 'i'
);
1217 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1218 encode_name(rbml_w
, item
.ident
.name
);
1219 encode_attributes(rbml_w
, &item
.attrs
);
1220 encode_unsafety(rbml_w
, unsafety
);
1221 encode_polarity(rbml_w
, polarity
);
1223 match tcx
.custom_coerce_unsized_kinds
.borrow().get(&local_def(item
.id
)) {
1225 rbml_w
.start_tag(tag_impl_coerce_unsized_kind
);
1226 kind
.encode(rbml_w
);
1233 ast
::TyPath(None
, ref path
) if path
.segments
.len() == 1 => {
1234 let name
= path
.segments
.last().unwrap().identifier
.name
;
1235 encode_impl_type_basename(rbml_w
, name
);
1239 for &item_def_id
in items
{
1240 rbml_w
.start_tag(tag_item_impl_item
);
1242 ty
::ConstTraitItemId(item_def_id
) => {
1243 encode_def_id(rbml_w
, item_def_id
);
1244 encode_item_sort(rbml_w
, 'C'
);
1246 ty
::MethodTraitItemId(item_def_id
) => {
1247 encode_def_id(rbml_w
, item_def_id
);
1248 encode_item_sort(rbml_w
, 'r'
);
1250 ty
::TypeTraitItemId(item_def_id
) => {
1251 encode_def_id(rbml_w
, item_def_id
);
1252 encode_item_sort(rbml_w
, 't'
);
1257 if opt_trait
.is_some() {
1258 let trait_ref
= ty
::impl_id_to_trait_ref(tcx
, item
.id
);
1259 encode_trait_ref(rbml_w
, ecx
, trait_ref
, tag_item_trait_ref
);
1261 encode_path(rbml_w
, path
.clone());
1262 encode_stability(rbml_w
, stab
);
1265 // Iterate down the trait items, emitting them. We rely on the
1266 // assumption that all of the actually implemented trait items
1267 // appear first in the impl structure, in the same order they do
1268 // in the ast. This is a little sketchy.
1269 let num_implemented_methods
= ast_items
.len();
1270 for (i
, &trait_item_def_id
) in items
.iter().enumerate() {
1271 let ast_item
= if i
< num_implemented_methods
{
1272 Some(&*ast_items
[i
])
1278 val
: trait_item_def_id
.def_id().node
as i64,
1279 pos
: rbml_w
.mark_stable_position(),
1282 match ty
::impl_or_trait_item(tcx
, trait_item_def_id
.def_id()) {
1283 ty
::ConstTraitItem(ref associated_const
) => {
1284 encode_info_for_associated_const(ecx
,
1291 ty
::MethodTraitItem(ref method_type
) => {
1292 encode_info_for_method(ecx
,
1300 ty
::TypeTraitItem(ref associated_type
) => {
1301 encode_info_for_associated_type(ecx
,
1311 ast
::ItemTrait(_
, _
, _
, ref ms
) => {
1312 add_to_index(item
, rbml_w
, index
);
1313 rbml_w
.start_tag(tag_items_data_item
);
1314 encode_def_id(rbml_w
, def_id
);
1315 encode_family(rbml_w
, 'I'
);
1316 encode_item_variances(rbml_w
, ecx
, item
.id
);
1317 let trait_def
= ty
::lookup_trait_def(tcx
, def_id
);
1318 let trait_predicates
= ty
::lookup_predicates(tcx
, def_id
);
1319 encode_unsafety(rbml_w
, trait_def
.unsafety
);
1320 encode_paren_sugar(rbml_w
, trait_def
.paren_sugar
);
1321 encode_defaulted(rbml_w
, ty
::trait_has_default_impl(tcx
, def_id
));
1322 encode_associated_type_names(rbml_w
, &trait_def
.associated_type_names
);
1323 encode_generics(rbml_w
, ecx
, &trait_def
.generics
, &trait_predicates
,
1325 encode_predicates(rbml_w
, ecx
, &ty
::lookup_super_predicates(tcx
, def_id
),
1326 tag_item_super_predicates
);
1327 encode_trait_ref(rbml_w
, ecx
, trait_def
.trait_ref
, tag_item_trait_ref
);
1328 encode_name(rbml_w
, item
.ident
.name
);
1329 encode_attributes(rbml_w
, &item
.attrs
);
1330 encode_visibility(rbml_w
, vis
);
1331 encode_stability(rbml_w
, stab
);
1332 for &method_def_id
in &*ty
::trait_item_def_ids(tcx
, def_id
) {
1333 rbml_w
.start_tag(tag_item_trait_item
);
1334 match method_def_id
{
1335 ty
::ConstTraitItemId(const_def_id
) => {
1336 encode_def_id(rbml_w
, const_def_id
);
1337 encode_item_sort(rbml_w
, 'C'
);
1339 ty
::MethodTraitItemId(method_def_id
) => {
1340 encode_def_id(rbml_w
, method_def_id
);
1341 encode_item_sort(rbml_w
, 'r'
);
1343 ty
::TypeTraitItemId(type_def_id
) => {
1344 encode_def_id(rbml_w
, type_def_id
);
1345 encode_item_sort(rbml_w
, 't'
);
1350 rbml_w
.wr_tagged_u64(tag_mod_child
,
1351 def_to_u64(method_def_id
.def_id()));
1353 encode_path(rbml_w
, path
.clone());
1355 // Encode the implementations of this trait.
1356 encode_extension_implementations(ecx
, rbml_w
, def_id
);
1358 // Encode inherent implementations for this trait.
1359 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1363 // Now output the trait item info for each trait item.
1364 let r
= ty
::trait_item_def_ids(tcx
, def_id
);
1365 for (i
, &item_def_id
) in r
.iter().enumerate() {
1366 assert_eq
!(item_def_id
.def_id().krate
, ast
::LOCAL_CRATE
);
1369 val
: item_def_id
.def_id().node
as i64,
1370 pos
: rbml_w
.mark_stable_position(),
1373 rbml_w
.start_tag(tag_items_data_item
);
1375 encode_parent_item(rbml_w
, def_id
);
1377 let stab
= stability
::lookup(tcx
, item_def_id
.def_id());
1378 encode_stability(rbml_w
, stab
);
1380 let trait_item_type
=
1381 ty
::impl_or_trait_item(tcx
, item_def_id
.def_id());
1382 let is_nonstatic_method
;
1383 match trait_item_type
{
1384 ty
::ConstTraitItem(associated_const
) => {
1385 encode_name(rbml_w
, associated_const
.name
);
1386 encode_def_id(rbml_w
, associated_const
.def_id
);
1387 encode_visibility(rbml_w
, associated_const
.vis
);
1389 encode_provided_source(rbml_w
, associated_const
.default);
1391 let elem
= ast_map
::PathName(associated_const
.name
);
1393 path
.clone().chain(Some(elem
).into_iter()));
1395 encode_item_sort(rbml_w
, 'C'
);
1396 encode_family(rbml_w
, 'C'
);
1398 encode_bounds_and_type_for_item(rbml_w
, ecx
,
1399 associated_const
.def_id
.local_id());
1401 is_nonstatic_method
= false;
1403 ty
::MethodTraitItem(method_ty
) => {
1404 let method_def_id
= item_def_id
.def_id();
1406 encode_method_ty_fields(ecx
, rbml_w
, &*method_ty
);
1408 let elem
= ast_map
::PathName(method_ty
.name
);
1410 path
.clone().chain(Some(elem
).into_iter()));
1412 match method_ty
.explicit_self
{
1413 ty
::StaticExplicitSelfCategory
=> {
1414 encode_family(rbml_w
,
1415 STATIC_METHOD_FAMILY
);
1418 encode_family(rbml_w
,
1422 encode_bounds_and_type_for_item(rbml_w
, ecx
, method_def_id
.local_id());
1424 is_nonstatic_method
= method_ty
.explicit_self
!=
1425 ty
::StaticExplicitSelfCategory
;
1427 ty
::TypeTraitItem(associated_type
) => {
1428 encode_name(rbml_w
, associated_type
.name
);
1429 encode_def_id(rbml_w
, associated_type
.def_id
);
1431 let elem
= ast_map
::PathName(associated_type
.name
);
1433 path
.clone().chain(Some(elem
).into_iter()));
1435 encode_item_sort(rbml_w
, 't'
);
1436 encode_family(rbml_w
, 'y'
);
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 ast
::ConstTraitItem(_
, _
) => {
1448 encode_inlined_item(ecx
, rbml_w
,
1449 IITraitItemRef(def_id
, trait_item
));
1451 ast
::MethodTraitItem(ref sig
, ref body
) => {
1452 // If this is a static method, we've already
1454 if is_nonstatic_method
{
1455 // FIXME: I feel like there is something funny
1457 encode_bounds_and_type_for_item(rbml_w
, ecx
,
1458 item_def_id
.def_id().local_id());
1462 encode_item_sort(rbml_w
, 'p'
);
1463 encode_inlined_item(ecx
, rbml_w
, IITraitItemRef(def_id
, trait_item
));
1465 encode_item_sort(rbml_w
, 'r'
);
1467 encode_method_argument_names(rbml_w
, &sig
.decl
);
1470 ast
::TypeTraitItem(..) => {}
1476 ast
::ItemExternCrate(_
) | ast
::ItemUse(_
) |ast
::ItemMac(..) => {
1477 // these are encoded separately
1482 fn encode_info_for_foreign_item(ecx
: &EncodeContext
,
1483 rbml_w
: &mut Encoder
,
1484 nitem
: &ast
::ForeignItem
,
1485 index
: &mut Vec
<entry
<i64>>,
1489 val
: nitem
.id
as i64,
1490 pos
: rbml_w
.mark_stable_position(),
1493 rbml_w
.start_tag(tag_items_data_item
);
1494 encode_def_id(rbml_w
, local_def(nitem
.id
));
1495 encode_visibility(rbml_w
, nitem
.vis
);
1497 ast
::ForeignItemFn(ref fndecl
, _
) => {
1498 encode_family(rbml_w
, FN_FAMILY
);
1499 encode_bounds_and_type_for_item(rbml_w
, ecx
, nitem
.id
);
1500 encode_name(rbml_w
, nitem
.ident
.name
);
1501 if abi
== abi
::RustIntrinsic
{
1502 encode_inlined_item(ecx
, rbml_w
, IIForeignRef(nitem
));
1504 encode_attributes(rbml_w
, &*nitem
.attrs
);
1505 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(nitem
.id
));
1506 encode_stability(rbml_w
, stab
);
1507 encode_symbol(ecx
, rbml_w
, nitem
.id
);
1508 encode_method_argument_names(rbml_w
, &*fndecl
);
1510 ast
::ForeignItemStatic(_
, mutbl
) => {
1512 encode_family(rbml_w
, 'b'
);
1514 encode_family(rbml_w
, 'c'
);
1516 encode_bounds_and_type_for_item(rbml_w
, ecx
, nitem
.id
);
1517 encode_attributes(rbml_w
, &*nitem
.attrs
);
1518 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(nitem
.id
));
1519 encode_stability(rbml_w
, stab
);
1520 encode_symbol(ecx
, rbml_w
, nitem
.id
);
1521 encode_name(rbml_w
, nitem
.ident
.name
);
1524 encode_path(rbml_w
, path
);
1528 fn my_visit_expr(_e
: &ast
::Expr
) { }
1530 fn my_visit_item(i
: &ast
::Item
,
1531 rbml_w
: &mut Encoder
,
1532 ecx
: &EncodeContext
,
1533 index
: &mut Vec
<entry
<i64>>) {
1534 ecx
.tcx
.map
.with_path(i
.id
, |path
| {
1535 encode_info_for_item(ecx
, rbml_w
, i
, index
, path
, i
.vis
);
1539 fn my_visit_foreign_item(ni
: &ast
::ForeignItem
,
1540 rbml_w
: &mut Encoder
,
1541 ecx
: &EncodeContext
,
1542 index
: &mut Vec
<entry
<i64>>) {
1543 debug
!("writing foreign item {}::{}",
1544 ecx
.tcx
.map
.path_to_string(ni
.id
),
1545 token
::get_ident(ni
.ident
));
1547 let abi
= ecx
.tcx
.map
.get_foreign_abi(ni
.id
);
1548 ecx
.tcx
.map
.with_path(ni
.id
, |path
| {
1549 encode_info_for_foreign_item(ecx
, rbml_w
,
1555 struct EncodeVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'c
> {
1556 rbml_w_for_visit_item
: &'a
mut Encoder
<'b
>,
1557 ecx
: &'a EncodeContext
<'c
,'tcx
>,
1558 index
: &'a
mut Vec
<entry
<i64>>,
1561 impl<'a
, 'b
, 'c
, 'tcx
, 'v
> Visitor
<'v
> for EncodeVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1562 fn visit_expr(&mut self, ex
: &ast
::Expr
) {
1563 visit
::walk_expr(self, ex
);
1566 fn visit_item(&mut self, i
: &ast
::Item
) {
1567 visit
::walk_item(self, i
);
1569 self.rbml_w_for_visit_item
,
1573 fn visit_foreign_item(&mut self, ni
: &ast
::ForeignItem
) {
1574 visit
::walk_foreign_item(self, ni
);
1575 my_visit_foreign_item(ni
,
1576 self.rbml_w_for_visit_item
,
1582 fn encode_info_for_items(ecx
: &EncodeContext
,
1583 rbml_w
: &mut Encoder
,
1585 -> Vec
<entry
<i64>> {
1586 let mut index
= Vec
::new();
1587 rbml_w
.start_tag(tag_items_data
);
1589 val
: ast
::CRATE_NODE_ID
as i64,
1590 pos
: rbml_w
.mark_stable_position(),
1592 encode_info_for_mod(ecx
,
1597 [].iter().cloned().chain(LinkedPath
::empty()),
1598 syntax
::parse
::token
::special_idents
::invalid
.name
,
1601 visit
::walk_crate(&mut EncodeVisitor
{
1604 rbml_w_for_visit_item
: &mut *rbml_w
,
1612 // Path and definition ID indexing
1614 fn encode_index
<T
, F
>(rbml_w
: &mut Encoder
, index
: Vec
<entry
<T
>>, mut write_fn
: F
) where
1615 F
: FnMut(&mut Cursor
<Vec
<u8>>, &T
),
1618 let mut buckets
: Vec
<Vec
<entry
<T
>>> = (0..256u16).map(|_
| Vec
::new()).collect();
1620 let mut s
= SipHasher
::new();
1621 elt
.val
.hash(&mut s
);
1622 let h
= s
.finish() as usize;
1623 (&mut buckets
[h
% 256]).push(elt
);
1626 rbml_w
.start_tag(tag_index
);
1627 let mut bucket_locs
= Vec
::new();
1628 rbml_w
.start_tag(tag_index_buckets
);
1629 for bucket
in &buckets
{
1630 bucket_locs
.push(rbml_w
.mark_stable_position());
1631 rbml_w
.start_tag(tag_index_buckets_bucket
);
1633 rbml_w
.start_tag(tag_index_buckets_bucket_elt
);
1634 assert
!(elt
.pos
< 0xffff_ffff);
1636 let wr
: &mut Cursor
<Vec
<u8>> = rbml_w
.writer
;
1637 write_be_u32(wr
, elt
.pos
as u32);
1639 write_fn(rbml_w
.writer
, &elt
.val
);
1645 rbml_w
.start_tag(tag_index_table
);
1646 for pos
in &bucket_locs
{
1647 assert
!(*pos
< 0xffff_ffff);
1648 let wr
: &mut Cursor
<Vec
<u8>> = rbml_w
.writer
;
1649 write_be_u32(wr
, *pos
as u32);
1655 fn write_i64(writer
: &mut Cursor
<Vec
<u8>>, &n
: &i64) {
1656 let wr
: &mut Cursor
<Vec
<u8>> = writer
;
1657 assert
!(n
< 0x7fff_ffff);
1658 write_be_u32(wr
, n
as u32);
1661 fn write_be_u32(w
: &mut Write
, u
: u32) {
1670 fn encode_meta_item(rbml_w
: &mut Encoder
, mi
: &ast
::MetaItem
) {
1672 ast
::MetaWord(ref name
) => {
1673 rbml_w
.start_tag(tag_meta_item_word
);
1674 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1677 ast
::MetaNameValue(ref name
, ref value
) => {
1679 ast
::LitStr(ref value
, _
) => {
1680 rbml_w
.start_tag(tag_meta_item_name_value
);
1681 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1682 rbml_w
.wr_tagged_str(tag_meta_item_value
, value
);
1685 _
=> {/* FIXME (#623): encode other variants */ }
1688 ast
::MetaList(ref name
, ref items
) => {
1689 rbml_w
.start_tag(tag_meta_item_list
);
1690 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1691 for inner_item
in items
{
1692 encode_meta_item(rbml_w
, &**inner_item
);
1699 fn encode_attributes(rbml_w
: &mut Encoder
, attrs
: &[ast
::Attribute
]) {
1700 rbml_w
.start_tag(tag_attributes
);
1702 rbml_w
.start_tag(tag_attribute
);
1703 rbml_w
.wr_tagged_u8(tag_attribute_is_sugared_doc
, attr
.node
.is_sugared_doc
as u8);
1704 encode_meta_item(rbml_w
, &*attr
.node
.value
);
1710 fn encode_unsafety(rbml_w
: &mut Encoder
, unsafety
: ast
::Unsafety
) {
1711 let byte
: u8 = match unsafety
{
1712 ast
::Unsafety
::Normal
=> 0,
1713 ast
::Unsafety
::Unsafe
=> 1,
1715 rbml_w
.wr_tagged_u8(tag_unsafety
, byte
);
1718 fn encode_paren_sugar(rbml_w
: &mut Encoder
, paren_sugar
: bool
) {
1719 let byte
: u8 = if paren_sugar {1}
else {0}
;
1720 rbml_w
.wr_tagged_u8(tag_paren_sugar
, byte
);
1723 fn encode_defaulted(rbml_w
: &mut Encoder
, is_defaulted
: bool
) {
1724 let byte
: u8 = if is_defaulted {1}
else {0}
;
1725 rbml_w
.wr_tagged_u8(tag_defaulted_trait
, byte
);
1728 fn encode_associated_type_names(rbml_w
: &mut Encoder
, names
: &[ast
::Name
]) {
1729 rbml_w
.start_tag(tag_associated_type_names
);
1730 for &name
in names
{
1731 rbml_w
.wr_tagged_str(tag_associated_type_name
, &token
::get_name(name
));
1736 fn encode_polarity(rbml_w
: &mut Encoder
, polarity
: ast
::ImplPolarity
) {
1737 let byte
: u8 = match polarity
{
1738 ast
::ImplPolarity
::Positive
=> 0,
1739 ast
::ImplPolarity
::Negative
=> 1,
1741 rbml_w
.wr_tagged_u8(tag_polarity
, byte
);
1744 fn encode_crate_deps(rbml_w
: &mut Encoder
, cstore
: &cstore
::CStore
) {
1745 fn get_ordered_deps(cstore
: &cstore
::CStore
) -> Vec
<decoder
::CrateDep
> {
1746 // Pull the cnums and name,vers,hash out of cstore
1747 let mut deps
= Vec
::new();
1748 cstore
.iter_crate_data(|key
, val
| {
1749 let dep
= decoder
::CrateDep
{
1751 name
: decoder
::get_crate_name(val
.data()),
1752 hash
: decoder
::get_crate_hash(val
.data()),
1758 deps
.sort_by(|kv1
, kv2
| kv1
.cnum
.cmp(&kv2
.cnum
));
1760 // Sanity-check the crate numbers
1761 let mut expected_cnum
= 1;
1763 assert_eq
!(n
.cnum
, expected_cnum
);
1770 // We're just going to write a list of crate 'name-hash-version's, with
1771 // the assumption that they are numbered 1 to n.
1772 // FIXME (#2166): This is not nearly enough to support correct versioning
1773 // but is enough to get transitive crate dependencies working.
1774 rbml_w
.start_tag(tag_crate_deps
);
1775 let r
= get_ordered_deps(cstore
);
1777 encode_crate_dep(rbml_w
, (*dep
).clone());
1782 fn encode_lang_items(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1783 rbml_w
.start_tag(tag_lang_items
);
1785 for (i
, &def_id
) in ecx
.tcx
.lang_items
.items() {
1786 if let Some(id
) = def_id
{
1787 if id
.krate
== ast
::LOCAL_CRATE
{
1788 rbml_w
.start_tag(tag_lang_items_item
);
1789 rbml_w
.wr_tagged_u32(tag_lang_items_item_id
, i
as u32);
1790 rbml_w
.wr_tagged_u32(tag_lang_items_item_node_id
, id
.node
as u32);
1796 for i
in &ecx
.tcx
.lang_items
.missing
{
1797 rbml_w
.wr_tagged_u32(tag_lang_items_missing
, *i
as u32);
1800 rbml_w
.end_tag(); // tag_lang_items
1803 fn encode_native_libraries(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1804 rbml_w
.start_tag(tag_native_libraries
);
1806 for &(ref lib
, kind
) in ecx
.tcx
.sess
.cstore
.get_used_libraries()
1809 cstore
::NativeStatic
=> {}
// these libraries are not propagated
1810 cstore
::NativeFramework
| cstore
::NativeUnknown
=> {
1811 rbml_w
.start_tag(tag_native_libraries_lib
);
1812 rbml_w
.wr_tagged_u32(tag_native_libraries_kind
, kind
as u32);
1813 rbml_w
.wr_tagged_str(tag_native_libraries_name
, lib
);
1822 fn encode_plugin_registrar_fn(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1823 match ecx
.tcx
.sess
.plugin_registrar_fn
.get() {
1824 Some(id
) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1829 fn encode_codemap(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1830 rbml_w
.start_tag(tag_codemap
);
1831 let codemap
= ecx
.tcx
.sess
.codemap();
1833 for filemap
in &codemap
.files
.borrow()[..] {
1835 if filemap
.lines
.borrow().is_empty() || filemap
.is_imported() {
1836 // No need to export empty filemaps, as they can't contain spans
1837 // that need translation.
1838 // Also no need to re-export imported filemaps, as any downstream
1839 // crate will import them from their original source.
1843 rbml_w
.start_tag(tag_codemap_filemap
);
1844 filemap
.encode(rbml_w
);
1851 /// Serialize the text of the exported macros
1852 fn encode_macro_defs(rbml_w
: &mut Encoder
,
1853 krate
: &ast
::Crate
) {
1854 rbml_w
.start_tag(tag_macro_defs
);
1855 for def
in &krate
.exported_macros
{
1856 rbml_w
.start_tag(tag_macro_def
);
1858 encode_name(rbml_w
, def
.ident
.name
);
1859 encode_attributes(rbml_w
, &def
.attrs
);
1861 rbml_w
.wr_tagged_str(tag_macro_def_body
,
1862 &pprust
::tts_to_string(&def
.body
));
1869 fn encode_struct_field_attrs(rbml_w
: &mut Encoder
, krate
: &ast
::Crate
) {
1870 struct StructFieldVisitor
<'a
, 'b
:'a
> {
1871 rbml_w
: &'a
mut Encoder
<'b
>,
1874 impl<'a
, 'b
, 'v
> Visitor
<'v
> for StructFieldVisitor
<'a
, 'b
> {
1875 fn visit_struct_field(&mut self, field
: &ast
::StructField
) {
1876 self.rbml_w
.start_tag(tag_struct_field
);
1877 self.rbml_w
.wr_tagged_u32(tag_struct_field_id
, field
.node
.id
);
1878 encode_attributes(self.rbml_w
, &field
.node
.attrs
);
1879 self.rbml_w
.end_tag();
1883 rbml_w
.start_tag(tag_struct_fields
);
1884 visit
::walk_crate(&mut StructFieldVisitor
{
1892 struct ImplVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'b
> {
1893 ecx
: &'a EncodeContext
<'b
, 'tcx
>,
1894 rbml_w
: &'a
mut Encoder
<'c
>,
1897 impl<'a
, 'b
, 'c
, 'tcx
, 'v
> Visitor
<'v
> for ImplVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1898 fn visit_item(&mut self, item
: &ast
::Item
) {
1899 if let ast
::ItemImpl(_
, _
, _
, Some(ref trait_ref
), _
, _
) = item
.node
{
1900 let def_id
= self.ecx
.tcx
.def_map
.borrow().get(&trait_ref
.ref_id
).unwrap().def_id();
1902 // Load eagerly if this is an implementation of the Drop trait
1903 // or if the trait is not defined in this crate.
1904 if Some(def_id
) == self.ecx
.tcx
.lang_items
.drop_trait() ||
1905 def_id
.krate
!= ast
::LOCAL_CRATE
{
1906 self.rbml_w
.start_tag(tag_impls_impl
);
1907 encode_def_id(self.rbml_w
, local_def(item
.id
));
1908 self.rbml_w
.wr_tagged_u64(tag_impls_impl_trait_def_id
, def_to_u64(def_id
));
1909 self.rbml_w
.end_tag();
1912 visit
::walk_item(self, item
);
1916 /// Encodes implementations that are eagerly loaded.
1918 /// None of this is necessary in theory; we can load all implementations
1919 /// lazily. However, in two cases the optimizations to lazily load
1920 /// implementations are not yet implemented. These two cases, which require us
1921 /// to load implementations eagerly, are:
1923 /// * Destructors (implementations of the Drop trait).
1925 /// * Implementations of traits not defined in this crate.
1926 fn encode_impls
<'a
>(ecx
: &'a EncodeContext
,
1928 rbml_w
: &'a
mut Encoder
) {
1929 rbml_w
.start_tag(tag_impls
);
1932 let mut visitor
= ImplVisitor
{
1936 visit
::walk_crate(&mut visitor
, krate
);
1942 fn encode_misc_info(ecx
: &EncodeContext
,
1944 rbml_w
: &mut Encoder
) {
1945 rbml_w
.start_tag(tag_misc_info
);
1946 rbml_w
.start_tag(tag_misc_info_crate_items
);
1947 for item
in &krate
.module
.items
{
1948 rbml_w
.wr_tagged_u64(tag_mod_child
,
1949 def_to_u64(local_def(item
.id
)));
1951 each_auxiliary_node_id(&**item
, |auxiliary_node_id
| {
1952 rbml_w
.wr_tagged_u64(tag_mod_child
,
1953 def_to_u64(local_def(auxiliary_node_id
)));
1958 // Encode reexports for the root module.
1959 encode_reexports(ecx
, rbml_w
, 0, [].iter().cloned().chain(LinkedPath
::empty()));
1965 fn encode_reachable_extern_fns(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1966 rbml_w
.start_tag(tag_reachable_extern_fns
);
1968 for id
in ecx
.reachable
{
1969 if let Some(ast_map
::NodeItem(i
)) = ecx
.tcx
.map
.find(*id
) {
1970 if let ast
::ItemFn(_
, _
, abi
, ref generics
, _
) = i
.node
{
1971 if abi
!= abi
::Rust
&& !generics
.is_type_parameterized() {
1972 rbml_w
.wr_tagged_u32(tag_reachable_extern_fn_id
, *id
);
1981 fn encode_crate_dep(rbml_w
: &mut Encoder
,
1982 dep
: decoder
::CrateDep
) {
1983 rbml_w
.start_tag(tag_crate_dep
);
1984 rbml_w
.wr_tagged_str(tag_crate_dep_crate_name
, &dep
.name
);
1985 rbml_w
.wr_tagged_str(tag_crate_dep_hash
, dep
.hash
.as_str());
1989 fn encode_hash(rbml_w
: &mut Encoder
, hash
: &Svh
) {
1990 rbml_w
.wr_tagged_str(tag_crate_hash
, hash
.as_str());
1993 fn encode_crate_name(rbml_w
: &mut Encoder
, crate_name
: &str) {
1994 rbml_w
.wr_tagged_str(tag_crate_crate_name
, crate_name
);
1997 fn encode_crate_triple(rbml_w
: &mut Encoder
, triple
: &str) {
1998 rbml_w
.wr_tagged_str(tag_crate_triple
, triple
);
2001 fn encode_dylib_dependency_formats(rbml_w
: &mut Encoder
, ecx
: &EncodeContext
) {
2002 let tag
= tag_dylib_dependency_formats
;
2003 match ecx
.tcx
.dependency_formats
.borrow().get(&config
::CrateTypeDylib
) {
2005 let s
= arr
.iter().enumerate().filter_map(|(i
, slot
)| {
2006 slot
.map(|kind
| (format
!("{}:{}", i
+ 1, match kind
{
2007 cstore
::RequireDynamic
=> "d",
2008 cstore
::RequireStatic
=> "s",
2010 }).collect
::<Vec
<String
>>();
2011 rbml_w
.wr_tagged_str(tag
, &s
.connect(","));
2014 rbml_w
.wr_tagged_str(tag
, "");
2019 // NB: Increment this as you change the metadata encoding version.
2020 #[allow(non_upper_case_globals)]
2021 pub const metadata_encoding_version
: &'
static [u8] = &[b'r'
, b'u'
, b's'
, b't'
, 0, 0, 0, 2 ];
2023 pub fn encode_metadata(parms
: EncodeParams
, krate
: &ast
::Crate
) -> Vec
<u8> {
2024 let mut wr
= Cursor
::new(Vec
::new());
2025 encode_metadata_inner(&mut wr
, parms
, krate
);
2027 // RBML compacts the encoded bytes whenever appropriate,
2028 // so there are some garbages left after the end of the data.
2029 let metalen
= wr
.seek(SeekFrom
::Current(0)).unwrap() as usize;
2030 let mut v
= wr
.into_inner();
2031 v
.truncate(metalen
);
2032 assert_eq
!(v
.len(), metalen
);
2034 // And here we run into yet another obscure archive bug: in which metadata
2035 // loaded from archives may have trailing garbage bytes. Awhile back one of
2036 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
2037 // and opt) by having rbml generate an out-of-bounds panic when looking at
2040 // Upon investigation it turned out that the metadata file inside of an rlib
2041 // (and ar archive) was being corrupted. Some compilations would generate a
2042 // metadata file which would end in a few extra bytes, while other
2043 // compilations would not have these extra bytes appended to the end. These
2044 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2045 // being interpreted causing the out-of-bounds.
2047 // The root cause of why these extra bytes were appearing was never
2048 // discovered, and in the meantime the solution we're employing is to insert
2049 // the length of the metadata to the start of the metadata. Later on this
2050 // will allow us to slice the metadata to the precise length that we just
2051 // generated regardless of trailing bytes that end up in it.
2052 let len
= v
.len() as u32;
2053 v
.insert(0, (len
>> 0) as u8);
2054 v
.insert(0, (len
>> 8) as u8);
2055 v
.insert(0, (len
>> 16) as u8);
2056 v
.insert(0, (len
>> 24) as u8);
2060 fn encode_metadata_inner(wr
: &mut Cursor
<Vec
<u8>>,
2061 parms
: EncodeParams
,
2062 krate
: &ast
::Crate
) {
2066 lang_item_bytes
: u64,
2067 native_lib_bytes
: u64,
2068 plugin_registrar_fn_bytes
: u64,
2070 macro_defs_bytes
: u64,
2078 let mut stats
= Stats
{
2082 native_lib_bytes
: 0,
2083 plugin_registrar_fn_bytes
: 0,
2085 macro_defs_bytes
: 0,
2099 encode_inlined_item
,
2104 let ecx
= EncodeContext
{
2107 reexports
: reexports
,
2108 item_symbols
: item_symbols
,
2109 link_meta
: link_meta
,
2111 encode_inlined_item
: RefCell
::new(encode_inlined_item
),
2112 type_abbrevs
: RefCell
::new(FnvHashMap()),
2113 reachable
: reachable
,
2116 let mut rbml_w
= Encoder
::new(wr
);
2118 encode_crate_name(&mut rbml_w
, &ecx
.link_meta
.crate_name
);
2119 encode_crate_triple(&mut rbml_w
,
2124 encode_hash(&mut rbml_w
, &ecx
.link_meta
.crate_hash
);
2125 encode_dylib_dependency_formats(&mut rbml_w
, &ecx
);
2127 let mut i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2128 encode_attributes(&mut rbml_w
, &krate
.attrs
);
2129 stats
.attr_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2131 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2132 encode_crate_deps(&mut rbml_w
, ecx
.cstore
);
2133 stats
.dep_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2135 // Encode the language items.
2136 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2137 encode_lang_items(&ecx
, &mut rbml_w
);
2138 stats
.lang_item_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2140 // Encode the native libraries used
2141 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2142 encode_native_libraries(&ecx
, &mut rbml_w
);
2143 stats
.native_lib_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2145 // Encode the plugin registrar function
2146 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2147 encode_plugin_registrar_fn(&ecx
, &mut rbml_w
);
2148 stats
.plugin_registrar_fn_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2151 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2152 encode_codemap(&ecx
, &mut rbml_w
);
2153 stats
.codemap_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2155 // Encode macro definitions
2156 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2157 encode_macro_defs(&mut rbml_w
, krate
);
2158 stats
.macro_defs_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2160 // Encode the def IDs of impls, for coherence checking.
2161 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2162 encode_impls(&ecx
, krate
, &mut rbml_w
);
2163 stats
.impl_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2165 // Encode miscellaneous info.
2166 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2167 encode_misc_info(&ecx
, krate
, &mut rbml_w
);
2168 encode_reachable_extern_fns(&ecx
, &mut rbml_w
);
2169 stats
.misc_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2171 // Encode and index the items.
2172 rbml_w
.start_tag(tag_items
);
2173 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2174 let items_index
= encode_info_for_items(&ecx
, &mut rbml_w
, krate
);
2175 stats
.item_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2177 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2178 encode_index(&mut rbml_w
, items_index
, write_i64
);
2179 stats
.index_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2182 encode_struct_field_attrs(&mut rbml_w
, krate
);
2184 stats
.total_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2186 if tcx
.sess
.meta_stats() {
2187 for e
in rbml_w
.writer
.get_ref() {
2189 stats
.zero_bytes
+= 1;
2193 println
!("metadata stats:");
2194 println
!(" attribute bytes: {}", stats
.attr_bytes
);
2195 println
!(" dep bytes: {}", stats
.dep_bytes
);
2196 println
!(" lang item bytes: {}", stats
.lang_item_bytes
);
2197 println
!(" native bytes: {}", stats
.native_lib_bytes
);
2198 println
!("plugin registrar bytes: {}", stats
.plugin_registrar_fn_bytes
);
2199 println
!(" codemap bytes: {}", stats
.codemap_bytes
);
2200 println
!(" macro def bytes: {}", stats
.macro_defs_bytes
);
2201 println
!(" impl bytes: {}", stats
.impl_bytes
);
2202 println
!(" misc bytes: {}", stats
.misc_bytes
);
2203 println
!(" item bytes: {}", stats
.item_bytes
);
2204 println
!(" index bytes: {}", stats
.index_bytes
);
2205 println
!(" zero bytes: {}", stats
.zero_bytes
);
2206 println
!(" total bytes: {}", stats
.total_bytes
);
2210 // Get the encoded string for a type
2211 pub fn encoded_ty
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>, t
: Ty
<'tcx
>) -> String
{
2212 let mut wr
= Cursor
::new(Vec
::new());
2213 tyencode
::enc_ty(&mut Encoder
::new(&mut wr
), &tyencode
::ctxt
{
2214 diag
: tcx
.sess
.diagnostic(),
2217 abbrevs
: &RefCell
::new(FnvHashMap())
2219 String
::from_utf8(wr
.into_inner()).unwrap()