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
::*;
18 use ast_map
::{self, LinkedPath, PathElem, PathElems}
;
21 use metadata
::common
::*;
23 use metadata
::decoder
;
24 use metadata
::tyencode
;
26 use middle
::ty
::lookup_item_type
;
27 use middle
::ty
::{self, Ty}
;
28 use middle
::stability
;
29 use util
::nodemap
::{FnvHashMap, NodeMap, NodeSet}
;
31 use serialize
::Encodable
;
32 use std
::cell
::RefCell
;
33 use std
::hash
::{Hash, Hasher, SipHasher}
;
34 use std
::io
::prelude
::*;
35 use std
::io
::{Cursor, SeekFrom}
;
37 use syntax
::ast
::{self, DefId, NodeId}
;
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
.iter() {
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
.iter() {
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_constness(rbml_w
: &mut Encoder
, constness
: ast
::Constness
) {
585 rbml_w
.start_tag(tag_items_data_item_constness
);
586 let ch
= match constness
{
587 ast
::Constness
::Const
=> 'c'
,
588 ast
::Constness
::NotConst
=> 'n'
,
590 rbml_w
.wr_str(&ch
.to_string());
594 fn encode_explicit_self(rbml_w
: &mut Encoder
,
595 explicit_self
: &ty
::ExplicitSelfCategory
) {
596 let tag
= tag_item_trait_method_explicit_self
;
598 // Encode the base self type.
599 match *explicit_self
{
600 ty
::StaticExplicitSelfCategory
=> {
601 rbml_w
.wr_tagged_bytes(tag
, &['s'
as u8]);
603 ty
::ByValueExplicitSelfCategory
=> {
604 rbml_w
.wr_tagged_bytes(tag
, &['v'
as u8]);
606 ty
::ByBoxExplicitSelfCategory
=> {
607 rbml_w
.wr_tagged_bytes(tag
, &['
~'
as u8]);
609 ty
::ByReferenceExplicitSelfCategory(_
, m
) => {
610 // FIXME(#4846) encode custom lifetime
611 let ch
= encode_mutability(m
);
612 rbml_w
.wr_tagged_bytes(tag
, &['
&'
as u8, ch
]);
616 fn encode_mutability(m
: ast
::Mutability
) -> u8 {
618 ast
::MutImmutable
=> 'i'
as u8,
619 ast
::MutMutable
=> 'm'
as u8,
624 fn encode_item_sort(rbml_w
: &mut Encoder
, sort
: char) {
625 rbml_w
.wr_tagged_u8(tag_item_trait_item_sort
, sort
as u8);
628 fn encode_parent_sort(rbml_w
: &mut Encoder
, sort
: char) {
629 rbml_w
.wr_tagged_u8(tag_item_trait_parent_sort
, sort
as u8);
632 fn encode_provided_source(rbml_w
: &mut Encoder
,
633 source_opt
: Option
<DefId
>) {
634 if let Some(source
) = source_opt
{
635 rbml_w
.wr_tagged_u64(tag_item_method_provided_source
, def_to_u64(source
));
639 /* Returns an index of items in this class */
640 fn encode_info_for_struct(ecx
: &EncodeContext
,
641 rbml_w
: &mut Encoder
,
642 fields
: &[ty
::field_ty
],
643 global_index
: &mut Vec
<entry
<i64>>)
645 /* Each class has its own index, since different classes
646 may have fields with the same name */
647 let mut index
= Vec
::new();
648 /* We encode both private and public fields -- need to include
649 private fields to get the offsets right */
650 for field
in fields
{
652 let id
= field
.id
.node
;
654 let pos
= rbml_w
.mark_stable_position();
655 index
.push(entry {val: id as i64, pos: pos}
);
656 global_index
.push(entry
{
660 rbml_w
.start_tag(tag_items_data_item
);
661 debug
!("encode_info_for_struct: doing {} {}",
662 token
::get_name(nm
), id
);
663 encode_struct_field_family(rbml_w
, field
.vis
);
664 encode_name(rbml_w
, nm
);
665 encode_bounds_and_type_for_item(rbml_w
, ecx
, id
);
666 encode_def_id(rbml_w
, local_def(id
));
668 let stab
= stability
::lookup(ecx
.tcx
, field
.id
);
669 encode_stability(rbml_w
, stab
);
676 fn encode_info_for_struct_ctor(ecx
: &EncodeContext
,
677 rbml_w
: &mut Encoder
,
680 index
: &mut Vec
<entry
<i64>>,
684 pos
: rbml_w
.mark_stable_position(),
687 rbml_w
.start_tag(tag_items_data_item
);
688 encode_def_id(rbml_w
, local_def(ctor_id
));
689 encode_family(rbml_w
, 'o'
);
690 encode_bounds_and_type_for_item(rbml_w
, ecx
, ctor_id
);
691 encode_name(rbml_w
, name
);
692 ecx
.tcx
.map
.with_path(ctor_id
, |path
| encode_path(rbml_w
, path
));
693 encode_parent_item(rbml_w
, local_def(struct_id
));
695 if ecx
.item_symbols
.borrow().contains_key(&ctor_id
) {
696 encode_symbol(ecx
, rbml_w
, ctor_id
);
699 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(ctor_id
));
700 encode_stability(rbml_w
, stab
);
702 // indicate that this is a tuple struct ctor, because downstream users will normally want
703 // the tuple struct definition, but without this there is no way for them to tell that
704 // they actually have a ctor rather than a normal function
705 rbml_w
.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor
, &[]);
710 fn encode_generics
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
711 ecx
: &EncodeContext
<'a
, 'tcx
>,
712 generics
: &ty
::Generics
<'tcx
>,
713 predicates
: &ty
::GenericPredicates
<'tcx
>,
716 rbml_w
.start_tag(tag
);
719 let ty_str_ctxt
= &tyencode
::ctxt
{
723 abbrevs
: &ecx
.type_abbrevs
726 for param
in &generics
.types
{
727 rbml_w
.start_tag(tag_type_param_def
);
728 tyencode
::enc_type_param_def(rbml_w
, ty_str_ctxt
, param
);
733 for param
in &generics
.regions
{
734 rbml_w
.start_tag(tag_region_param_def
);
736 rbml_w
.start_tag(tag_region_param_def_ident
);
737 encode_name(rbml_w
, param
.name
);
740 rbml_w
.wr_tagged_u64(tag_region_param_def_def_id
,
741 def_to_u64(param
.def_id
));
743 rbml_w
.wr_tagged_u64(tag_region_param_def_space
,
744 param
.space
.to_uint() as u64);
746 rbml_w
.wr_tagged_u64(tag_region_param_def_index
,
749 for &bound_region
in ¶m
.bounds
{
750 encode_region(ecx
, rbml_w
, bound_region
);
756 encode_predicates_in_current_doc(rbml_w
, ecx
, predicates
);
761 fn encode_predicates_in_current_doc
<'a
,'tcx
>(rbml_w
: &mut Encoder
,
762 ecx
: &EncodeContext
<'a
,'tcx
>,
763 predicates
: &ty
::GenericPredicates
<'tcx
>)
765 let ty_str_ctxt
= &tyencode
::ctxt
{
769 abbrevs
: &ecx
.type_abbrevs
772 for (space
, _
, predicate
) in predicates
.predicates
.iter_enumerated() {
773 rbml_w
.start_tag(tag_predicate
);
775 rbml_w
.wr_tagged_u8(tag_predicate_space
, space
as u8);
777 rbml_w
.start_tag(tag_predicate_data
);
778 tyencode
::enc_predicate(rbml_w
, ty_str_ctxt
, predicate
);
785 fn encode_predicates
<'a
,'tcx
>(rbml_w
: &mut Encoder
,
786 ecx
: &EncodeContext
<'a
,'tcx
>,
787 predicates
: &ty
::GenericPredicates
<'tcx
>,
790 rbml_w
.start_tag(tag
);
791 encode_predicates_in_current_doc(rbml_w
, ecx
, predicates
);
795 fn encode_method_ty_fields
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
796 rbml_w
: &mut Encoder
,
797 method_ty
: &ty
::Method
<'tcx
>) {
798 encode_def_id(rbml_w
, method_ty
.def_id
);
799 encode_name(rbml_w
, method_ty
.name
);
800 encode_generics(rbml_w
, ecx
, &method_ty
.generics
, &method_ty
.predicates
,
801 tag_method_ty_generics
);
802 encode_method_fty(ecx
, rbml_w
, &method_ty
.fty
);
803 encode_visibility(rbml_w
, method_ty
.vis
);
804 encode_explicit_self(rbml_w
, &method_ty
.explicit_self
);
805 match method_ty
.explicit_self
{
806 ty
::StaticExplicitSelfCategory
=> {
807 encode_family(rbml_w
, STATIC_METHOD_FAMILY
);
809 _
=> encode_family(rbml_w
, METHOD_FAMILY
)
811 encode_provided_source(rbml_w
, method_ty
.provided_source
);
814 fn encode_info_for_associated_const(ecx
: &EncodeContext
,
815 rbml_w
: &mut Encoder
,
816 associated_const
: &ty
::AssociatedConst
,
817 impl_path
: PathElems
,
819 impl_item_opt
: Option
<&ast
::ImplItem
>) {
820 debug
!("encode_info_for_associated_const({:?},{:?})",
821 associated_const
.def_id
,
822 token
::get_name(associated_const
.name
));
824 rbml_w
.start_tag(tag_items_data_item
);
826 encode_def_id(rbml_w
, associated_const
.def_id
);
827 encode_name(rbml_w
, associated_const
.name
);
828 encode_visibility(rbml_w
, associated_const
.vis
);
829 encode_family(rbml_w
, 'C'
);
830 encode_provided_source(rbml_w
, associated_const
.default);
832 encode_parent_item(rbml_w
, local_def(parent_id
));
833 encode_item_sort(rbml_w
, 'C'
);
835 encode_bounds_and_type_for_item(rbml_w
, ecx
, associated_const
.def_id
.local_id());
837 let stab
= stability
::lookup(ecx
.tcx
, associated_const
.def_id
);
838 encode_stability(rbml_w
, stab
);
840 let elem
= ast_map
::PathName(associated_const
.name
);
841 encode_path(rbml_w
, impl_path
.chain(Some(elem
)));
843 if let Some(ii
) = impl_item_opt
{
844 encode_attributes(rbml_w
, &ii
.attrs
);
845 encode_inlined_item(ecx
, rbml_w
, IIImplItemRef(local_def(parent_id
), ii
));
851 fn encode_info_for_method
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
852 rbml_w
: &mut Encoder
,
853 m
: &ty
::Method
<'tcx
>,
854 impl_path
: PathElems
,
855 is_default_impl
: bool
,
857 impl_item_opt
: Option
<&ast
::ImplItem
>) {
859 debug
!("encode_info_for_method: {:?} {:?}", m
.def_id
,
860 token
::get_name(m
.name
));
861 rbml_w
.start_tag(tag_items_data_item
);
863 encode_method_ty_fields(ecx
, rbml_w
, m
);
864 encode_parent_item(rbml_w
, local_def(parent_id
));
865 encode_item_sort(rbml_w
, 'r'
);
867 let stab
= stability
::lookup(ecx
.tcx
, m
.def_id
);
868 encode_stability(rbml_w
, stab
);
870 // The type for methods gets encoded twice, which is unfortunate.
871 encode_bounds_and_type_for_item(rbml_w
, ecx
, m
.def_id
.local_id());
873 let elem
= ast_map
::PathName(m
.name
);
874 encode_path(rbml_w
, impl_path
.chain(Some(elem
)));
875 if let Some(impl_item
) = impl_item_opt
{
876 if let ast
::MethodImplItem(ref sig
, _
) = impl_item
.node
{
877 encode_attributes(rbml_w
, &impl_item
.attrs
);
878 let scheme
= ty
::lookup_item_type(ecx
.tcx
, m
.def_id
);
879 let any_types
= !scheme
.generics
.types
.is_empty();
880 let needs_inline
= any_types
|| is_default_impl
||
881 attr
::requests_inline(&impl_item
.attrs
);
882 if needs_inline
|| sig
.constness
== ast
::Constness
::Const
{
883 encode_inlined_item(ecx
, rbml_w
, IIImplItemRef(local_def(parent_id
),
886 encode_constness(rbml_w
, sig
.constness
);
888 encode_symbol(ecx
, rbml_w
, m
.def_id
.node
);
890 encode_method_argument_names(rbml_w
, &sig
.decl
);
897 fn encode_info_for_associated_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
898 rbml_w
: &mut Encoder
,
899 associated_type
: &ty
::AssociatedType
<'tcx
>,
900 impl_path
: PathElems
,
902 impl_item_opt
: Option
<&ast
::ImplItem
>) {
903 debug
!("encode_info_for_associated_type({:?},{:?})",
904 associated_type
.def_id
,
905 token
::get_name(associated_type
.name
));
907 rbml_w
.start_tag(tag_items_data_item
);
909 encode_def_id(rbml_w
, associated_type
.def_id
);
910 encode_name(rbml_w
, associated_type
.name
);
911 encode_visibility(rbml_w
, associated_type
.vis
);
912 encode_family(rbml_w
, 'y'
);
913 encode_parent_item(rbml_w
, local_def(parent_id
));
914 encode_item_sort(rbml_w
, 't'
);
916 let stab
= stability
::lookup(ecx
.tcx
, associated_type
.def_id
);
917 encode_stability(rbml_w
, stab
);
919 let elem
= ast_map
::PathName(associated_type
.name
);
920 encode_path(rbml_w
, impl_path
.chain(Some(elem
)));
922 if let Some(ii
) = impl_item_opt
{
923 encode_attributes(rbml_w
, &ii
.attrs
);
925 encode_predicates(rbml_w
, ecx
,
926 &ty
::lookup_predicates(ecx
.tcx
, associated_type
.def_id
),
930 if let Some(ty
) = associated_type
.ty
{
931 encode_type(ecx
, rbml_w
, ty
);
937 fn encode_method_argument_names(rbml_w
: &mut Encoder
,
938 decl
: &ast
::FnDecl
) {
939 rbml_w
.start_tag(tag_method_argument_names
);
940 for arg
in &decl
.inputs
{
941 let tag
= tag_method_argument_name
;
942 if let ast
::PatIdent(_
, ref path1
, _
) = arg
.pat
.node
{
943 let name
= token
::get_name(path1
.node
.name
);
944 rbml_w
.wr_tagged_bytes(tag
, name
.as_bytes());
946 rbml_w
.wr_tagged_bytes(tag
, &[]);
952 fn encode_repr_attrs(rbml_w
: &mut Encoder
,
954 attrs
: &[ast
::Attribute
]) {
955 let mut repr_attrs
= Vec
::new();
957 repr_attrs
.extend(attr
::find_repr_attrs(ecx
.tcx
.sess
.diagnostic(),
960 rbml_w
.start_tag(tag_items_data_item_repr
);
961 repr_attrs
.encode(rbml_w
);
965 fn encode_inlined_item(ecx
: &EncodeContext
,
966 rbml_w
: &mut Encoder
,
967 ii
: InlinedItemRef
) {
968 let mut eii
= ecx
.encode_inlined_item
.borrow_mut();
969 let eii
: &mut EncodeInlinedItem
= &mut *eii
;
973 const FN_FAMILY
: char = 'f'
;
974 const STATIC_METHOD_FAMILY
: char = 'F'
;
975 const METHOD_FAMILY
: char = 'h'
;
977 // Encodes the inherent implementations of a structure, enumeration, or trait.
978 fn encode_inherent_implementations(ecx
: &EncodeContext
,
979 rbml_w
: &mut Encoder
,
981 match ecx
.tcx
.inherent_impls
.borrow().get(&def_id
) {
983 Some(implementations
) => {
984 for &impl_def_id
in implementations
.iter() {
985 rbml_w
.start_tag(tag_items_data_item_inherent_impl
);
986 encode_def_id(rbml_w
, impl_def_id
);
993 // Encodes the implementations of a trait defined in this crate.
994 fn encode_extension_implementations(ecx
: &EncodeContext
,
995 rbml_w
: &mut Encoder
,
996 trait_def_id
: DefId
) {
997 assert
!(ast_util
::is_local(trait_def_id
));
998 let def
= ty
::lookup_trait_def(ecx
.tcx
, trait_def_id
);
1000 def
.for_each_impl(ecx
.tcx
, |impl_def_id
| {
1001 rbml_w
.start_tag(tag_items_data_item_extension_impl
);
1002 encode_def_id(rbml_w
, impl_def_id
);
1007 fn encode_stability(rbml_w
: &mut Encoder
, stab_opt
: Option
<&attr
::Stability
>) {
1008 stab_opt
.map(|stab
| {
1009 rbml_w
.start_tag(tag_items_data_item_stability
);
1010 stab
.encode(rbml_w
).unwrap();
1015 fn encode_info_for_item(ecx
: &EncodeContext
,
1016 rbml_w
: &mut Encoder
,
1018 index
: &mut Vec
<entry
<i64>>,
1020 vis
: ast
::Visibility
) {
1023 fn add_to_index(item
: &ast
::Item
, rbml_w
: &mut Encoder
,
1024 index
: &mut Vec
<entry
<i64>>) {
1026 val
: item
.id
as i64,
1027 pos
: rbml_w
.mark_stable_position(),
1031 debug
!("encoding info for item at {}",
1032 tcx
.sess
.codemap().span_to_string(item
.span
));
1034 let def_id
= local_def(item
.id
);
1035 let stab
= stability
::lookup(tcx
, ast_util
::local_def(item
.id
));
1038 ast
::ItemStatic(_
, m
, _
) => {
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 if m
== ast
::MutMutable
{
1043 encode_family(rbml_w
, 'b'
);
1045 encode_family(rbml_w
, 'c'
);
1047 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1048 encode_symbol(ecx
, rbml_w
, item
.id
);
1049 encode_name(rbml_w
, item
.ident
.name
);
1050 encode_path(rbml_w
, path
);
1051 encode_visibility(rbml_w
, vis
);
1052 encode_stability(rbml_w
, stab
);
1053 encode_attributes(rbml_w
, &item
.attrs
);
1056 ast
::ItemConst(_
, _
) => {
1057 add_to_index(item
, rbml_w
, index
);
1058 rbml_w
.start_tag(tag_items_data_item
);
1059 encode_def_id(rbml_w
, def_id
);
1060 encode_family(rbml_w
, 'C'
);
1061 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1062 encode_name(rbml_w
, item
.ident
.name
);
1063 encode_path(rbml_w
, path
);
1064 encode_attributes(rbml_w
, &item
.attrs
);
1065 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1066 encode_visibility(rbml_w
, vis
);
1067 encode_stability(rbml_w
, stab
);
1070 ast
::ItemFn(ref decl
, _
, constness
, _
, ref generics
, _
) => {
1071 add_to_index(item
, rbml_w
, index
);
1072 rbml_w
.start_tag(tag_items_data_item
);
1073 encode_def_id(rbml_w
, def_id
);
1074 encode_family(rbml_w
, FN_FAMILY
);
1075 let tps_len
= generics
.ty_params
.len();
1076 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1077 encode_name(rbml_w
, item
.ident
.name
);
1078 encode_path(rbml_w
, path
);
1079 encode_attributes(rbml_w
, &item
.attrs
);
1080 let needs_inline
= tps_len
> 0 || attr
::requests_inline(&item
.attrs
);
1081 if needs_inline
|| constness
== ast
::Constness
::Const
{
1082 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1085 encode_symbol(ecx
, rbml_w
, item
.id
);
1087 encode_constness(rbml_w
, constness
);
1088 encode_visibility(rbml_w
, vis
);
1089 encode_stability(rbml_w
, stab
);
1090 encode_method_argument_names(rbml_w
, &**decl
);
1093 ast
::ItemMod(ref m
) => {
1094 add_to_index(item
, rbml_w
, index
);
1095 encode_info_for_mod(ecx
,
1104 ast
::ItemForeignMod(ref fm
) => {
1105 add_to_index(item
, rbml_w
, index
);
1106 rbml_w
.start_tag(tag_items_data_item
);
1107 encode_def_id(rbml_w
, def_id
);
1108 encode_family(rbml_w
, 'n'
);
1109 encode_name(rbml_w
, item
.ident
.name
);
1110 encode_path(rbml_w
, path
);
1112 // Encode all the items in this module.
1113 for foreign_item
in &fm
.items
{
1114 rbml_w
.wr_tagged_u64(tag_mod_child
,
1115 def_to_u64(local_def(foreign_item
.id
)));
1117 encode_visibility(rbml_w
, vis
);
1118 encode_stability(rbml_w
, stab
);
1121 ast
::ItemTy(..) => {
1122 add_to_index(item
, rbml_w
, index
);
1123 rbml_w
.start_tag(tag_items_data_item
);
1124 encode_def_id(rbml_w
, def_id
);
1125 encode_family(rbml_w
, 'y'
);
1126 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1127 encode_name(rbml_w
, item
.ident
.name
);
1128 encode_path(rbml_w
, path
);
1129 encode_visibility(rbml_w
, vis
);
1130 encode_stability(rbml_w
, stab
);
1133 ast
::ItemEnum(ref enum_definition
, _
) => {
1134 add_to_index(item
, rbml_w
, index
);
1136 rbml_w
.start_tag(tag_items_data_item
);
1137 encode_def_id(rbml_w
, def_id
);
1138 encode_family(rbml_w
, 't'
);
1139 encode_item_variances(rbml_w
, ecx
, item
.id
);
1140 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1141 encode_name(rbml_w
, item
.ident
.name
);
1142 encode_attributes(rbml_w
, &item
.attrs
);
1143 encode_repr_attrs(rbml_w
, ecx
, &item
.attrs
);
1144 for v
in &enum_definition
.variants
{
1145 encode_variant_id(rbml_w
, local_def(v
.node
.id
));
1147 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1148 encode_path(rbml_w
, path
);
1150 // Encode inherent implementations for this enumeration.
1151 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1153 encode_visibility(rbml_w
, vis
);
1154 encode_stability(rbml_w
, stab
);
1157 encode_enum_variant_info(ecx
,
1160 &(*enum_definition
).variants
,
1163 ast
::ItemStruct(ref struct_def
, _
) => {
1164 let fields
= ty
::lookup_struct_fields(tcx
, def_id
);
1166 /* First, encode the fields
1167 These come first because we need to write them to make
1168 the index, and the index needs to be in the item for the
1170 let idx
= encode_info_for_struct(ecx
,
1175 /* Index the class*/
1176 add_to_index(item
, rbml_w
, index
);
1178 /* Now, make an item for the class itself */
1179 rbml_w
.start_tag(tag_items_data_item
);
1180 encode_def_id(rbml_w
, def_id
);
1181 encode_family(rbml_w
, 'S'
);
1182 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1184 encode_item_variances(rbml_w
, ecx
, item
.id
);
1185 encode_name(rbml_w
, item
.ident
.name
);
1186 encode_attributes(rbml_w
, &item
.attrs
);
1187 encode_path(rbml_w
, path
.clone());
1188 encode_stability(rbml_w
, stab
);
1189 encode_visibility(rbml_w
, vis
);
1190 encode_repr_attrs(rbml_w
, ecx
, &item
.attrs
);
1192 /* Encode def_ids for each field and method
1193 for methods, write all the stuff get_trait_method
1195 encode_struct_fields(rbml_w
, &fields
[..], def_id
);
1197 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1199 // Encode inherent implementations for this structure.
1200 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1202 /* Each class has its own index -- encode it */
1203 encode_index(rbml_w
, idx
, write_i64
);
1206 // If this is a tuple-like struct, encode the type of the constructor.
1207 match struct_def
.ctor_id
{
1209 encode_info_for_struct_ctor(ecx
, rbml_w
, item
.ident
.name
,
1210 ctor_id
, index
, def_id
.node
);
1215 ast
::ItemDefaultImpl(unsafety
, _
) => {
1216 add_to_index(item
, rbml_w
, index
);
1217 rbml_w
.start_tag(tag_items_data_item
);
1218 encode_def_id(rbml_w
, def_id
);
1219 encode_family(rbml_w
, 'd'
);
1220 encode_name(rbml_w
, item
.ident
.name
);
1221 encode_unsafety(rbml_w
, unsafety
);
1223 let trait_ref
= ty
::impl_trait_ref(tcx
, local_def(item
.id
)).unwrap();
1224 encode_trait_ref(rbml_w
, ecx
, trait_ref
, tag_item_trait_ref
);
1227 ast
::ItemImpl(unsafety
, polarity
, _
, _
, ref ty
, ref ast_items
) => {
1228 // We need to encode information about the default methods we
1229 // have inherited, so we drive this based on the impl structure.
1230 let impl_items
= tcx
.impl_items
.borrow();
1231 let items
= impl_items
.get(&def_id
).unwrap();
1233 add_to_index(item
, rbml_w
, index
);
1234 rbml_w
.start_tag(tag_items_data_item
);
1235 encode_def_id(rbml_w
, def_id
);
1236 encode_family(rbml_w
, 'i'
);
1237 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1238 encode_name(rbml_w
, item
.ident
.name
);
1239 encode_attributes(rbml_w
, &item
.attrs
);
1240 encode_unsafety(rbml_w
, unsafety
);
1241 encode_polarity(rbml_w
, polarity
);
1243 match tcx
.custom_coerce_unsized_kinds
.borrow().get(&local_def(item
.id
)) {
1245 rbml_w
.start_tag(tag_impl_coerce_unsized_kind
);
1246 kind
.encode(rbml_w
);
1253 ast
::TyPath(None
, ref path
) if path
.segments
.len() == 1 => {
1254 let name
= path
.segments
.last().unwrap().identifier
.name
;
1255 encode_impl_type_basename(rbml_w
, name
);
1259 for &item_def_id
in items
{
1260 rbml_w
.start_tag(tag_item_impl_item
);
1262 ty
::ConstTraitItemId(item_def_id
) => {
1263 encode_def_id(rbml_w
, item_def_id
);
1264 encode_item_sort(rbml_w
, 'C'
);
1266 ty
::MethodTraitItemId(item_def_id
) => {
1267 encode_def_id(rbml_w
, item_def_id
);
1268 encode_item_sort(rbml_w
, 'r'
);
1270 ty
::TypeTraitItemId(item_def_id
) => {
1271 encode_def_id(rbml_w
, item_def_id
);
1272 encode_item_sort(rbml_w
, 't'
);
1277 if let Some(trait_ref
) = ty
::impl_trait_ref(tcx
, local_def(item
.id
)) {
1278 encode_trait_ref(rbml_w
, ecx
, trait_ref
, tag_item_trait_ref
);
1280 encode_path(rbml_w
, path
.clone());
1281 encode_stability(rbml_w
, stab
);
1284 // Iterate down the trait items, emitting them. We rely on the
1285 // assumption that all of the actually implemented trait items
1286 // appear first in the impl structure, in the same order they do
1287 // in the ast. This is a little sketchy.
1288 let num_implemented_methods
= ast_items
.len();
1289 for (i
, &trait_item_def_id
) in items
.iter().enumerate() {
1290 let ast_item
= if i
< num_implemented_methods
{
1291 Some(&*ast_items
[i
])
1297 val
: trait_item_def_id
.def_id().node
as i64,
1298 pos
: rbml_w
.mark_stable_position(),
1301 match ty
::impl_or_trait_item(tcx
, trait_item_def_id
.def_id()) {
1302 ty
::ConstTraitItem(ref associated_const
) => {
1303 encode_info_for_associated_const(ecx
,
1310 ty
::MethodTraitItem(ref method_type
) => {
1311 encode_info_for_method(ecx
,
1319 ty
::TypeTraitItem(ref associated_type
) => {
1320 encode_info_for_associated_type(ecx
,
1330 ast
::ItemTrait(_
, _
, _
, ref ms
) => {
1331 add_to_index(item
, rbml_w
, index
);
1332 rbml_w
.start_tag(tag_items_data_item
);
1333 encode_def_id(rbml_w
, def_id
);
1334 encode_family(rbml_w
, 'I'
);
1335 encode_item_variances(rbml_w
, ecx
, item
.id
);
1336 let trait_def
= ty
::lookup_trait_def(tcx
, def_id
);
1337 let trait_predicates
= ty
::lookup_predicates(tcx
, def_id
);
1338 encode_unsafety(rbml_w
, trait_def
.unsafety
);
1339 encode_paren_sugar(rbml_w
, trait_def
.paren_sugar
);
1340 encode_defaulted(rbml_w
, ty
::trait_has_default_impl(tcx
, def_id
));
1341 encode_associated_type_names(rbml_w
, &trait_def
.associated_type_names
);
1342 encode_generics(rbml_w
, ecx
, &trait_def
.generics
, &trait_predicates
,
1344 encode_predicates(rbml_w
, ecx
, &ty
::lookup_super_predicates(tcx
, def_id
),
1345 tag_item_super_predicates
);
1346 encode_trait_ref(rbml_w
, ecx
, trait_def
.trait_ref
, tag_item_trait_ref
);
1347 encode_name(rbml_w
, item
.ident
.name
);
1348 encode_attributes(rbml_w
, &item
.attrs
);
1349 encode_visibility(rbml_w
, vis
);
1350 encode_stability(rbml_w
, stab
);
1351 for &method_def_id
in ty
::trait_item_def_ids(tcx
, def_id
).iter() {
1352 rbml_w
.start_tag(tag_item_trait_item
);
1353 match method_def_id
{
1354 ty
::ConstTraitItemId(const_def_id
) => {
1355 encode_def_id(rbml_w
, const_def_id
);
1356 encode_item_sort(rbml_w
, 'C'
);
1358 ty
::MethodTraitItemId(method_def_id
) => {
1359 encode_def_id(rbml_w
, method_def_id
);
1360 encode_item_sort(rbml_w
, 'r'
);
1362 ty
::TypeTraitItemId(type_def_id
) => {
1363 encode_def_id(rbml_w
, type_def_id
);
1364 encode_item_sort(rbml_w
, 't'
);
1369 rbml_w
.wr_tagged_u64(tag_mod_child
,
1370 def_to_u64(method_def_id
.def_id()));
1372 encode_path(rbml_w
, path
.clone());
1374 // Encode the implementations of this trait.
1375 encode_extension_implementations(ecx
, rbml_w
, def_id
);
1377 // Encode inherent implementations for this trait.
1378 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1382 // Now output the trait item info for each trait item.
1383 let r
= ty
::trait_item_def_ids(tcx
, def_id
);
1384 for (i
, &item_def_id
) in r
.iter().enumerate() {
1385 assert_eq
!(item_def_id
.def_id().krate
, ast
::LOCAL_CRATE
);
1388 val
: item_def_id
.def_id().node
as i64,
1389 pos
: rbml_w
.mark_stable_position(),
1392 rbml_w
.start_tag(tag_items_data_item
);
1394 encode_parent_item(rbml_w
, def_id
);
1396 let stab
= stability
::lookup(tcx
, item_def_id
.def_id());
1397 encode_stability(rbml_w
, stab
);
1399 let trait_item_type
=
1400 ty
::impl_or_trait_item(tcx
, item_def_id
.def_id());
1401 let is_nonstatic_method
;
1402 match trait_item_type
{
1403 ty
::ConstTraitItem(associated_const
) => {
1404 encode_name(rbml_w
, associated_const
.name
);
1405 encode_def_id(rbml_w
, associated_const
.def_id
);
1406 encode_visibility(rbml_w
, associated_const
.vis
);
1408 encode_provided_source(rbml_w
, associated_const
.default);
1410 let elem
= ast_map
::PathName(associated_const
.name
);
1412 path
.clone().chain(Some(elem
)));
1414 encode_item_sort(rbml_w
, 'C'
);
1415 encode_family(rbml_w
, 'C'
);
1417 encode_bounds_and_type_for_item(rbml_w
, ecx
,
1418 associated_const
.def_id
.local_id());
1420 is_nonstatic_method
= false;
1422 ty
::MethodTraitItem(method_ty
) => {
1423 let method_def_id
= item_def_id
.def_id();
1425 encode_method_ty_fields(ecx
, rbml_w
, &*method_ty
);
1427 let elem
= ast_map
::PathName(method_ty
.name
);
1429 path
.clone().chain(Some(elem
)));
1431 match method_ty
.explicit_self
{
1432 ty
::StaticExplicitSelfCategory
=> {
1433 encode_family(rbml_w
,
1434 STATIC_METHOD_FAMILY
);
1437 encode_family(rbml_w
,
1441 encode_bounds_and_type_for_item(rbml_w
, ecx
, method_def_id
.local_id());
1443 is_nonstatic_method
= method_ty
.explicit_self
!=
1444 ty
::StaticExplicitSelfCategory
;
1446 ty
::TypeTraitItem(associated_type
) => {
1447 encode_name(rbml_w
, associated_type
.name
);
1448 encode_def_id(rbml_w
, associated_type
.def_id
);
1450 let elem
= ast_map
::PathName(associated_type
.name
);
1452 path
.clone().chain(Some(elem
)));
1454 encode_item_sort(rbml_w
, 't'
);
1455 encode_family(rbml_w
, 'y'
);
1457 is_nonstatic_method
= false;
1461 encode_parent_sort(rbml_w
, 't'
);
1463 let trait_item
= &*ms
[i
];
1464 encode_attributes(rbml_w
, &trait_item
.attrs
);
1465 match trait_item
.node
{
1466 ast
::ConstTraitItem(_
, _
) => {
1467 encode_inlined_item(ecx
, rbml_w
,
1468 IITraitItemRef(def_id
, trait_item
));
1470 ast
::MethodTraitItem(ref sig
, ref body
) => {
1471 // If this is a static method, we've already
1473 if is_nonstatic_method
{
1474 // FIXME: I feel like there is something funny
1476 encode_bounds_and_type_for_item(rbml_w
, ecx
,
1477 item_def_id
.def_id().local_id());
1481 encode_item_sort(rbml_w
, 'p'
);
1482 encode_inlined_item(ecx
, rbml_w
, IITraitItemRef(def_id
, trait_item
));
1484 encode_item_sort(rbml_w
, 'r'
);
1486 encode_method_argument_names(rbml_w
, &sig
.decl
);
1489 ast
::TypeTraitItem(..) => {}
1495 ast
::ItemExternCrate(_
) | ast
::ItemUse(_
) |ast
::ItemMac(..) => {
1496 // these are encoded separately
1501 fn encode_info_for_foreign_item(ecx
: &EncodeContext
,
1502 rbml_w
: &mut Encoder
,
1503 nitem
: &ast
::ForeignItem
,
1504 index
: &mut Vec
<entry
<i64>>,
1508 val
: nitem
.id
as i64,
1509 pos
: rbml_w
.mark_stable_position(),
1512 rbml_w
.start_tag(tag_items_data_item
);
1513 encode_def_id(rbml_w
, local_def(nitem
.id
));
1514 encode_visibility(rbml_w
, nitem
.vis
);
1516 ast
::ForeignItemFn(ref fndecl
, _
) => {
1517 encode_family(rbml_w
, FN_FAMILY
);
1518 encode_bounds_and_type_for_item(rbml_w
, ecx
, nitem
.id
);
1519 encode_name(rbml_w
, nitem
.ident
.name
);
1520 if abi
== abi
::RustIntrinsic
{
1521 encode_inlined_item(ecx
, rbml_w
, IIForeignRef(nitem
));
1523 encode_attributes(rbml_w
, &*nitem
.attrs
);
1524 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(nitem
.id
));
1525 encode_stability(rbml_w
, stab
);
1526 encode_symbol(ecx
, rbml_w
, nitem
.id
);
1527 encode_method_argument_names(rbml_w
, &*fndecl
);
1529 ast
::ForeignItemStatic(_
, mutbl
) => {
1531 encode_family(rbml_w
, 'b'
);
1533 encode_family(rbml_w
, 'c'
);
1535 encode_bounds_and_type_for_item(rbml_w
, ecx
, nitem
.id
);
1536 encode_attributes(rbml_w
, &*nitem
.attrs
);
1537 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(nitem
.id
));
1538 encode_stability(rbml_w
, stab
);
1539 encode_symbol(ecx
, rbml_w
, nitem
.id
);
1540 encode_name(rbml_w
, nitem
.ident
.name
);
1543 encode_path(rbml_w
, path
);
1547 fn my_visit_expr(_e
: &ast
::Expr
) { }
1549 fn my_visit_item(i
: &ast
::Item
,
1550 rbml_w
: &mut Encoder
,
1551 ecx
: &EncodeContext
,
1552 index
: &mut Vec
<entry
<i64>>) {
1553 ecx
.tcx
.map
.with_path(i
.id
, |path
| {
1554 encode_info_for_item(ecx
, rbml_w
, i
, index
, path
, i
.vis
);
1558 fn my_visit_foreign_item(ni
: &ast
::ForeignItem
,
1559 rbml_w
: &mut Encoder
,
1560 ecx
: &EncodeContext
,
1561 index
: &mut Vec
<entry
<i64>>) {
1562 debug
!("writing foreign item {}::{}",
1563 ecx
.tcx
.map
.path_to_string(ni
.id
),
1564 token
::get_ident(ni
.ident
));
1566 let abi
= ecx
.tcx
.map
.get_foreign_abi(ni
.id
);
1567 ecx
.tcx
.map
.with_path(ni
.id
, |path
| {
1568 encode_info_for_foreign_item(ecx
, rbml_w
,
1574 struct EncodeVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'c
> {
1575 rbml_w_for_visit_item
: &'a
mut Encoder
<'b
>,
1576 ecx
: &'a EncodeContext
<'c
,'tcx
>,
1577 index
: &'a
mut Vec
<entry
<i64>>,
1580 impl<'a
, 'b
, 'c
, 'tcx
, 'v
> Visitor
<'v
> for EncodeVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1581 fn visit_expr(&mut self, ex
: &ast
::Expr
) {
1582 visit
::walk_expr(self, ex
);
1585 fn visit_item(&mut self, i
: &ast
::Item
) {
1586 visit
::walk_item(self, i
);
1588 self.rbml_w_for_visit_item
,
1592 fn visit_foreign_item(&mut self, ni
: &ast
::ForeignItem
) {
1593 visit
::walk_foreign_item(self, ni
);
1594 my_visit_foreign_item(ni
,
1595 self.rbml_w_for_visit_item
,
1601 fn encode_info_for_items(ecx
: &EncodeContext
,
1602 rbml_w
: &mut Encoder
,
1604 -> Vec
<entry
<i64>> {
1605 let mut index
= Vec
::new();
1606 rbml_w
.start_tag(tag_items_data
);
1608 val
: ast
::CRATE_NODE_ID
as i64,
1609 pos
: rbml_w
.mark_stable_position(),
1611 encode_info_for_mod(ecx
,
1616 [].iter().cloned().chain(LinkedPath
::empty()),
1617 syntax
::parse
::token
::special_idents
::invalid
.name
,
1620 visit
::walk_crate(&mut EncodeVisitor
{
1623 rbml_w_for_visit_item
: &mut *rbml_w
,
1631 // Path and definition ID indexing
1633 fn encode_index
<T
, F
>(rbml_w
: &mut Encoder
, index
: Vec
<entry
<T
>>, mut write_fn
: F
) where
1634 F
: FnMut(&mut Cursor
<Vec
<u8>>, &T
),
1637 let mut buckets
: Vec
<Vec
<entry
<T
>>> = (0..256u16).map(|_
| Vec
::new()).collect();
1639 let mut s
= SipHasher
::new();
1640 elt
.val
.hash(&mut s
);
1641 let h
= s
.finish() as usize;
1642 (&mut buckets
[h
% 256]).push(elt
);
1645 rbml_w
.start_tag(tag_index
);
1646 let mut bucket_locs
= Vec
::new();
1647 rbml_w
.start_tag(tag_index_buckets
);
1648 for bucket
in &buckets
{
1649 bucket_locs
.push(rbml_w
.mark_stable_position());
1650 rbml_w
.start_tag(tag_index_buckets_bucket
);
1652 rbml_w
.start_tag(tag_index_buckets_bucket_elt
);
1653 assert
!(elt
.pos
< 0xffff_ffff);
1655 let wr
: &mut Cursor
<Vec
<u8>> = rbml_w
.writer
;
1656 write_be_u32(wr
, elt
.pos
as u32);
1658 write_fn(rbml_w
.writer
, &elt
.val
);
1664 rbml_w
.start_tag(tag_index_table
);
1665 for pos
in &bucket_locs
{
1666 assert
!(*pos
< 0xffff_ffff);
1667 let wr
: &mut Cursor
<Vec
<u8>> = rbml_w
.writer
;
1668 write_be_u32(wr
, *pos
as u32);
1674 fn write_i64(writer
: &mut Cursor
<Vec
<u8>>, &n
: &i64) {
1675 let wr
: &mut Cursor
<Vec
<u8>> = writer
;
1676 assert
!(n
< 0x7fff_ffff);
1677 write_be_u32(wr
, n
as u32);
1680 fn write_be_u32(w
: &mut Write
, u
: u32) {
1689 fn encode_meta_item(rbml_w
: &mut Encoder
, mi
: &ast
::MetaItem
) {
1691 ast
::MetaWord(ref name
) => {
1692 rbml_w
.start_tag(tag_meta_item_word
);
1693 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1696 ast
::MetaNameValue(ref name
, ref value
) => {
1698 ast
::LitStr(ref value
, _
) => {
1699 rbml_w
.start_tag(tag_meta_item_name_value
);
1700 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1701 rbml_w
.wr_tagged_str(tag_meta_item_value
, value
);
1704 _
=> {/* FIXME (#623): encode other variants */ }
1707 ast
::MetaList(ref name
, ref items
) => {
1708 rbml_w
.start_tag(tag_meta_item_list
);
1709 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1710 for inner_item
in items
{
1711 encode_meta_item(rbml_w
, &**inner_item
);
1718 fn encode_attributes(rbml_w
: &mut Encoder
, attrs
: &[ast
::Attribute
]) {
1719 rbml_w
.start_tag(tag_attributes
);
1721 rbml_w
.start_tag(tag_attribute
);
1722 rbml_w
.wr_tagged_u8(tag_attribute_is_sugared_doc
, attr
.node
.is_sugared_doc
as u8);
1723 encode_meta_item(rbml_w
, &*attr
.node
.value
);
1729 fn encode_unsafety(rbml_w
: &mut Encoder
, unsafety
: ast
::Unsafety
) {
1730 let byte
: u8 = match unsafety
{
1731 ast
::Unsafety
::Normal
=> 0,
1732 ast
::Unsafety
::Unsafe
=> 1,
1734 rbml_w
.wr_tagged_u8(tag_unsafety
, byte
);
1737 fn encode_paren_sugar(rbml_w
: &mut Encoder
, paren_sugar
: bool
) {
1738 let byte
: u8 = if paren_sugar {1}
else {0}
;
1739 rbml_w
.wr_tagged_u8(tag_paren_sugar
, byte
);
1742 fn encode_defaulted(rbml_w
: &mut Encoder
, is_defaulted
: bool
) {
1743 let byte
: u8 = if is_defaulted {1}
else {0}
;
1744 rbml_w
.wr_tagged_u8(tag_defaulted_trait
, byte
);
1747 fn encode_associated_type_names(rbml_w
: &mut Encoder
, names
: &[ast
::Name
]) {
1748 rbml_w
.start_tag(tag_associated_type_names
);
1749 for &name
in names
{
1750 rbml_w
.wr_tagged_str(tag_associated_type_name
, &token
::get_name(name
));
1755 fn encode_polarity(rbml_w
: &mut Encoder
, polarity
: ast
::ImplPolarity
) {
1756 let byte
: u8 = match polarity
{
1757 ast
::ImplPolarity
::Positive
=> 0,
1758 ast
::ImplPolarity
::Negative
=> 1,
1760 rbml_w
.wr_tagged_u8(tag_polarity
, byte
);
1763 fn encode_crate_deps(rbml_w
: &mut Encoder
, cstore
: &cstore
::CStore
) {
1764 fn get_ordered_deps(cstore
: &cstore
::CStore
) -> Vec
<decoder
::CrateDep
> {
1765 // Pull the cnums and name,vers,hash out of cstore
1766 let mut deps
= Vec
::new();
1767 cstore
.iter_crate_data(|key
, val
| {
1768 let dep
= decoder
::CrateDep
{
1770 name
: decoder
::get_crate_name(val
.data()),
1771 hash
: decoder
::get_crate_hash(val
.data()),
1777 deps
.sort_by(|kv1
, kv2
| kv1
.cnum
.cmp(&kv2
.cnum
));
1779 // Sanity-check the crate numbers
1780 let mut expected_cnum
= 1;
1782 assert_eq
!(n
.cnum
, expected_cnum
);
1789 // We're just going to write a list of crate 'name-hash-version's, with
1790 // the assumption that they are numbered 1 to n.
1791 // FIXME (#2166): This is not nearly enough to support correct versioning
1792 // but is enough to get transitive crate dependencies working.
1793 rbml_w
.start_tag(tag_crate_deps
);
1794 let r
= get_ordered_deps(cstore
);
1796 encode_crate_dep(rbml_w
, (*dep
).clone());
1801 fn encode_lang_items(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1802 rbml_w
.start_tag(tag_lang_items
);
1804 for (i
, &def_id
) in ecx
.tcx
.lang_items
.items() {
1805 if let Some(id
) = def_id
{
1806 if id
.krate
== ast
::LOCAL_CRATE
{
1807 rbml_w
.start_tag(tag_lang_items_item
);
1808 rbml_w
.wr_tagged_u32(tag_lang_items_item_id
, i
as u32);
1809 rbml_w
.wr_tagged_u32(tag_lang_items_item_node_id
, id
.node
as u32);
1815 for i
in &ecx
.tcx
.lang_items
.missing
{
1816 rbml_w
.wr_tagged_u32(tag_lang_items_missing
, *i
as u32);
1819 rbml_w
.end_tag(); // tag_lang_items
1822 fn encode_native_libraries(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1823 rbml_w
.start_tag(tag_native_libraries
);
1825 for &(ref lib
, kind
) in ecx
.tcx
.sess
.cstore
.get_used_libraries()
1828 cstore
::NativeStatic
=> {}
// these libraries are not propagated
1829 cstore
::NativeFramework
| cstore
::NativeUnknown
=> {
1830 rbml_w
.start_tag(tag_native_libraries_lib
);
1831 rbml_w
.wr_tagged_u32(tag_native_libraries_kind
, kind
as u32);
1832 rbml_w
.wr_tagged_str(tag_native_libraries_name
, lib
);
1841 fn encode_plugin_registrar_fn(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1842 match ecx
.tcx
.sess
.plugin_registrar_fn
.get() {
1843 Some(id
) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1848 fn encode_codemap(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1849 rbml_w
.start_tag(tag_codemap
);
1850 let codemap
= ecx
.tcx
.sess
.codemap();
1852 for filemap
in &codemap
.files
.borrow()[..] {
1854 if filemap
.lines
.borrow().is_empty() || filemap
.is_imported() {
1855 // No need to export empty filemaps, as they can't contain spans
1856 // that need translation.
1857 // Also no need to re-export imported filemaps, as any downstream
1858 // crate will import them from their original source.
1862 rbml_w
.start_tag(tag_codemap_filemap
);
1863 filemap
.encode(rbml_w
);
1870 /// Serialize the text of the exported macros
1871 fn encode_macro_defs(rbml_w
: &mut Encoder
,
1872 krate
: &ast
::Crate
) {
1873 rbml_w
.start_tag(tag_macro_defs
);
1874 for def
in &krate
.exported_macros
{
1875 rbml_w
.start_tag(tag_macro_def
);
1877 encode_name(rbml_w
, def
.ident
.name
);
1878 encode_attributes(rbml_w
, &def
.attrs
);
1880 rbml_w
.wr_tagged_str(tag_macro_def_body
,
1881 &pprust
::tts_to_string(&def
.body
));
1888 fn encode_struct_field_attrs(rbml_w
: &mut Encoder
, krate
: &ast
::Crate
) {
1889 struct StructFieldVisitor
<'a
, 'b
:'a
> {
1890 rbml_w
: &'a
mut Encoder
<'b
>,
1893 impl<'a
, 'b
, 'v
> Visitor
<'v
> for StructFieldVisitor
<'a
, 'b
> {
1894 fn visit_struct_field(&mut self, field
: &ast
::StructField
) {
1895 self.rbml_w
.start_tag(tag_struct_field
);
1896 self.rbml_w
.wr_tagged_u32(tag_struct_field_id
, field
.node
.id
);
1897 encode_attributes(self.rbml_w
, &field
.node
.attrs
);
1898 self.rbml_w
.end_tag();
1902 rbml_w
.start_tag(tag_struct_fields
);
1903 visit
::walk_crate(&mut StructFieldVisitor
{
1911 struct ImplVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'b
> {
1912 ecx
: &'a EncodeContext
<'b
, 'tcx
>,
1913 rbml_w
: &'a
mut Encoder
<'c
>,
1916 impl<'a
, 'b
, 'c
, 'tcx
, 'v
> Visitor
<'v
> for ImplVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1917 fn visit_item(&mut self, item
: &ast
::Item
) {
1918 if let ast
::ItemImpl(_
, _
, _
, Some(ref trait_ref
), _
, _
) = item
.node
{
1919 let def_id
= self.ecx
.tcx
.def_map
.borrow().get(&trait_ref
.ref_id
).unwrap().def_id();
1921 // Load eagerly if this is an implementation of the Drop trait
1922 // or if the trait is not defined in this crate.
1923 if Some(def_id
) == self.ecx
.tcx
.lang_items
.drop_trait() ||
1924 def_id
.krate
!= ast
::LOCAL_CRATE
{
1925 self.rbml_w
.start_tag(tag_impls_impl
);
1926 encode_def_id(self.rbml_w
, local_def(item
.id
));
1927 self.rbml_w
.wr_tagged_u64(tag_impls_impl_trait_def_id
, def_to_u64(def_id
));
1928 self.rbml_w
.end_tag();
1931 visit
::walk_item(self, item
);
1935 /// Encodes implementations that are eagerly loaded.
1937 /// None of this is necessary in theory; we can load all implementations
1938 /// lazily. However, in two cases the optimizations to lazily load
1939 /// implementations are not yet implemented. These two cases, which require us
1940 /// to load implementations eagerly, are:
1942 /// * Destructors (implementations of the Drop trait).
1944 /// * Implementations of traits not defined in this crate.
1945 fn encode_impls
<'a
>(ecx
: &'a EncodeContext
,
1947 rbml_w
: &'a
mut Encoder
) {
1948 rbml_w
.start_tag(tag_impls
);
1951 let mut visitor
= ImplVisitor
{
1955 visit
::walk_crate(&mut visitor
, krate
);
1961 fn encode_misc_info(ecx
: &EncodeContext
,
1963 rbml_w
: &mut Encoder
) {
1964 rbml_w
.start_tag(tag_misc_info
);
1965 rbml_w
.start_tag(tag_misc_info_crate_items
);
1966 for item
in &krate
.module
.items
{
1967 rbml_w
.wr_tagged_u64(tag_mod_child
,
1968 def_to_u64(local_def(item
.id
)));
1970 each_auxiliary_node_id(&**item
, |auxiliary_node_id
| {
1971 rbml_w
.wr_tagged_u64(tag_mod_child
,
1972 def_to_u64(local_def(auxiliary_node_id
)));
1977 // Encode reexports for the root module.
1978 encode_reexports(ecx
, rbml_w
, 0, [].iter().cloned().chain(LinkedPath
::empty()));
1984 fn encode_reachable_extern_fns(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1985 rbml_w
.start_tag(tag_reachable_extern_fns
);
1987 for id
in ecx
.reachable
{
1988 if let Some(ast_map
::NodeItem(i
)) = ecx
.tcx
.map
.find(*id
) {
1989 if let ast
::ItemFn(_
, _
, _
, abi
, ref generics
, _
) = i
.node
{
1990 if abi
!= abi
::Rust
&& !generics
.is_type_parameterized() {
1991 rbml_w
.wr_tagged_u32(tag_reachable_extern_fn_id
, *id
);
2000 fn encode_crate_dep(rbml_w
: &mut Encoder
,
2001 dep
: decoder
::CrateDep
) {
2002 rbml_w
.start_tag(tag_crate_dep
);
2003 rbml_w
.wr_tagged_str(tag_crate_dep_crate_name
, &dep
.name
);
2004 rbml_w
.wr_tagged_str(tag_crate_dep_hash
, dep
.hash
.as_str());
2008 fn encode_hash(rbml_w
: &mut Encoder
, hash
: &Svh
) {
2009 rbml_w
.wr_tagged_str(tag_crate_hash
, hash
.as_str());
2012 fn encode_crate_name(rbml_w
: &mut Encoder
, crate_name
: &str) {
2013 rbml_w
.wr_tagged_str(tag_crate_crate_name
, crate_name
);
2016 fn encode_crate_triple(rbml_w
: &mut Encoder
, triple
: &str) {
2017 rbml_w
.wr_tagged_str(tag_crate_triple
, triple
);
2020 fn encode_dylib_dependency_formats(rbml_w
: &mut Encoder
, ecx
: &EncodeContext
) {
2021 let tag
= tag_dylib_dependency_formats
;
2022 match ecx
.tcx
.dependency_formats
.borrow().get(&config
::CrateTypeDylib
) {
2024 let s
= arr
.iter().enumerate().filter_map(|(i
, slot
)| {
2025 slot
.map(|kind
| (format
!("{}:{}", i
+ 1, match kind
{
2026 cstore
::RequireDynamic
=> "d",
2027 cstore
::RequireStatic
=> "s",
2029 }).collect
::<Vec
<String
>>();
2030 rbml_w
.wr_tagged_str(tag
, &s
.connect(","));
2033 rbml_w
.wr_tagged_str(tag
, "");
2038 // NB: Increment this as you change the metadata encoding version.
2039 #[allow(non_upper_case_globals)]
2040 pub const metadata_encoding_version
: &'
static [u8] = &[b'r'
, b'u'
, b's'
, b't'
, 0, 0, 0, 2 ];
2042 pub fn encode_metadata(parms
: EncodeParams
, krate
: &ast
::Crate
) -> Vec
<u8> {
2043 let mut wr
= Cursor
::new(Vec
::new());
2044 encode_metadata_inner(&mut wr
, parms
, krate
);
2046 // RBML compacts the encoded bytes whenever appropriate,
2047 // so there are some garbages left after the end of the data.
2048 let metalen
= wr
.seek(SeekFrom
::Current(0)).unwrap() as usize;
2049 let mut v
= wr
.into_inner();
2050 v
.truncate(metalen
);
2051 assert_eq
!(v
.len(), metalen
);
2053 // And here we run into yet another obscure archive bug: in which metadata
2054 // loaded from archives may have trailing garbage bytes. Awhile back one of
2055 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
2056 // and opt) by having rbml generate an out-of-bounds panic when looking at
2059 // Upon investigation it turned out that the metadata file inside of an rlib
2060 // (and ar archive) was being corrupted. Some compilations would generate a
2061 // metadata file which would end in a few extra bytes, while other
2062 // compilations would not have these extra bytes appended to the end. These
2063 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2064 // being interpreted causing the out-of-bounds.
2066 // The root cause of why these extra bytes were appearing was never
2067 // discovered, and in the meantime the solution we're employing is to insert
2068 // the length of the metadata to the start of the metadata. Later on this
2069 // will allow us to slice the metadata to the precise length that we just
2070 // generated regardless of trailing bytes that end up in it.
2071 let len
= v
.len() as u32;
2072 v
.insert(0, (len
>> 0) as u8);
2073 v
.insert(0, (len
>> 8) as u8);
2074 v
.insert(0, (len
>> 16) as u8);
2075 v
.insert(0, (len
>> 24) as u8);
2079 fn encode_metadata_inner(wr
: &mut Cursor
<Vec
<u8>>,
2080 parms
: EncodeParams
,
2081 krate
: &ast
::Crate
) {
2085 lang_item_bytes
: u64,
2086 native_lib_bytes
: u64,
2087 plugin_registrar_fn_bytes
: u64,
2089 macro_defs_bytes
: u64,
2097 let mut stats
= Stats
{
2101 native_lib_bytes
: 0,
2102 plugin_registrar_fn_bytes
: 0,
2104 macro_defs_bytes
: 0,
2118 encode_inlined_item
,
2123 let ecx
= EncodeContext
{
2126 reexports
: reexports
,
2127 item_symbols
: item_symbols
,
2128 link_meta
: link_meta
,
2130 encode_inlined_item
: RefCell
::new(encode_inlined_item
),
2131 type_abbrevs
: RefCell
::new(FnvHashMap()),
2132 reachable
: reachable
,
2135 let mut rbml_w
= Encoder
::new(wr
);
2137 encode_crate_name(&mut rbml_w
, &ecx
.link_meta
.crate_name
);
2138 encode_crate_triple(&mut rbml_w
,
2143 encode_hash(&mut rbml_w
, &ecx
.link_meta
.crate_hash
);
2144 encode_dylib_dependency_formats(&mut rbml_w
, &ecx
);
2146 let mut i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2147 encode_attributes(&mut rbml_w
, &krate
.attrs
);
2148 stats
.attr_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2150 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2151 encode_crate_deps(&mut rbml_w
, ecx
.cstore
);
2152 stats
.dep_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2154 // Encode the language items.
2155 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2156 encode_lang_items(&ecx
, &mut rbml_w
);
2157 stats
.lang_item_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2159 // Encode the native libraries used
2160 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2161 encode_native_libraries(&ecx
, &mut rbml_w
);
2162 stats
.native_lib_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2164 // Encode the plugin registrar function
2165 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2166 encode_plugin_registrar_fn(&ecx
, &mut rbml_w
);
2167 stats
.plugin_registrar_fn_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2170 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2171 encode_codemap(&ecx
, &mut rbml_w
);
2172 stats
.codemap_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2174 // Encode macro definitions
2175 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2176 encode_macro_defs(&mut rbml_w
, krate
);
2177 stats
.macro_defs_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2179 // Encode the def IDs of impls, for coherence checking.
2180 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2181 encode_impls(&ecx
, krate
, &mut rbml_w
);
2182 stats
.impl_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2184 // Encode miscellaneous info.
2185 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2186 encode_misc_info(&ecx
, krate
, &mut rbml_w
);
2187 encode_reachable_extern_fns(&ecx
, &mut rbml_w
);
2188 stats
.misc_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2190 // Encode and index the items.
2191 rbml_w
.start_tag(tag_items
);
2192 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2193 let items_index
= encode_info_for_items(&ecx
, &mut rbml_w
, krate
);
2194 stats
.item_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2196 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2197 encode_index(&mut rbml_w
, items_index
, write_i64
);
2198 stats
.index_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2201 encode_struct_field_attrs(&mut rbml_w
, krate
);
2203 stats
.total_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2205 if tcx
.sess
.meta_stats() {
2206 for e
in rbml_w
.writer
.get_ref() {
2208 stats
.zero_bytes
+= 1;
2212 println
!("metadata stats:");
2213 println
!(" attribute bytes: {}", stats
.attr_bytes
);
2214 println
!(" dep bytes: {}", stats
.dep_bytes
);
2215 println
!(" lang item bytes: {}", stats
.lang_item_bytes
);
2216 println
!(" native bytes: {}", stats
.native_lib_bytes
);
2217 println
!("plugin registrar bytes: {}", stats
.plugin_registrar_fn_bytes
);
2218 println
!(" codemap bytes: {}", stats
.codemap_bytes
);
2219 println
!(" macro def bytes: {}", stats
.macro_defs_bytes
);
2220 println
!(" impl bytes: {}", stats
.impl_bytes
);
2221 println
!(" misc bytes: {}", stats
.misc_bytes
);
2222 println
!(" item bytes: {}", stats
.item_bytes
);
2223 println
!(" index bytes: {}", stats
.index_bytes
);
2224 println
!(" zero bytes: {}", stats
.zero_bytes
);
2225 println
!(" total bytes: {}", stats
.total_bytes
);
2229 // Get the encoded string for a type
2230 pub fn encoded_ty
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>, t
: Ty
<'tcx
>) -> String
{
2231 let mut wr
= Cursor
::new(Vec
::new());
2232 tyencode
::enc_ty(&mut Encoder
::new(&mut wr
), &tyencode
::ctxt
{
2233 diag
: tcx
.sess
.diagnostic(),
2236 abbrevs
: &RefCell
::new(FnvHashMap())
2238 String
::from_utf8(wr
.into_inner()).unwrap()