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
::{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_util
::*;
40 use syntax
::attr
::AttrMetaMethods
;
41 use syntax
::diagnostic
::SpanHandler
;
42 use syntax
::parse
::token
::special_idents
;
43 use syntax
::print
::pprust
;
45 use syntax
::visit
::Visitor
;
48 use rbml
::writer
::Encoder
;
50 /// A borrowed version of `ast::InlinedItem`.
51 pub enum InlinedItemRef
<'a
> {
52 IIItemRef(&'a ast
::Item
),
53 IITraitItemRef(DefId
, &'a ast
::TraitItem
),
54 IIImplItemRef(DefId
, &'a ast
::ImplItem
),
55 IIForeignRef(&'a ast
::ForeignItem
)
58 pub type EncodeInlinedItem
<'a
> =
59 Box
<FnMut(&EncodeContext
, &mut Encoder
, InlinedItemRef
) + 'a
>;
61 pub struct EncodeParams
<'a
, 'tcx
: 'a
> {
62 pub diag
: &'a SpanHandler
,
63 pub tcx
: &'a ty
::ctxt
<'tcx
>,
64 pub reexports
: &'a def
::ExportMap
,
65 pub item_symbols
: &'a RefCell
<NodeMap
<String
>>,
66 pub link_meta
: &'a LinkMeta
,
67 pub cstore
: &'a cstore
::CStore
,
68 pub encode_inlined_item
: EncodeInlinedItem
<'a
>,
69 pub reachable
: &'a NodeSet
,
72 pub struct EncodeContext
<'a
, 'tcx
: 'a
> {
73 pub diag
: &'a SpanHandler
,
74 pub tcx
: &'a ty
::ctxt
<'tcx
>,
75 pub reexports
: &'a def
::ExportMap
,
76 pub item_symbols
: &'a RefCell
<NodeMap
<String
>>,
77 pub link_meta
: &'a LinkMeta
,
78 pub cstore
: &'a cstore
::CStore
,
79 pub encode_inlined_item
: RefCell
<EncodeInlinedItem
<'a
>>,
80 pub type_abbrevs
: tyencode
::abbrev_map
<'tcx
>,
81 pub reachable
: &'a NodeSet
,
84 fn encode_name(rbml_w
: &mut Encoder
, name
: ast
::Name
) {
85 rbml_w
.wr_tagged_str(tag_paths_data_name
, &name
.as_str());
88 fn encode_impl_type_basename(rbml_w
: &mut Encoder
, name
: ast
::Name
) {
89 rbml_w
.wr_tagged_str(tag_item_impl_type_basename
, &name
.as_str());
92 fn encode_def_id(rbml_w
: &mut Encoder
, id
: DefId
) {
93 rbml_w
.wr_tagged_u64(tag_def_id
, def_to_u64(id
));
102 fn encode_trait_ref
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
103 ecx
: &EncodeContext
<'a
, 'tcx
>,
104 trait_ref
: ty
::TraitRef
<'tcx
>,
106 let ty_str_ctxt
= &tyencode
::ctxt
{
110 abbrevs
: &ecx
.type_abbrevs
113 rbml_w
.start_tag(tag
);
114 tyencode
::enc_trait_ref(rbml_w
, ty_str_ctxt
, trait_ref
);
118 // Item info table encoding
119 fn encode_family(rbml_w
: &mut Encoder
, c
: char) {
120 rbml_w
.wr_tagged_u8(tag_items_data_item_family
, c
as u8);
123 pub fn def_to_u64(did
: DefId
) -> u64 {
124 (did
.krate
as u64) << 32 | (did
.node
as u64)
127 pub fn def_to_string(did
: DefId
) -> String
{
128 format
!("{}:{}", did
.krate
, did
.node
)
131 fn encode_item_variances(rbml_w
: &mut Encoder
,
134 let v
= ecx
.tcx
.item_variances(ast_util
::local_def(id
));
135 rbml_w
.start_tag(tag_item_variances
);
140 fn encode_bounds_and_type_for_item
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
141 ecx
: &EncodeContext
<'a
, 'tcx
>,
143 encode_bounds_and_type(rbml_w
,
145 &ecx
.tcx
.lookup_item_type(local_def(id
)),
146 &ecx
.tcx
.lookup_predicates(local_def(id
)));
149 fn encode_bounds_and_type
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
150 ecx
: &EncodeContext
<'a
, 'tcx
>,
151 scheme
: &ty
::TypeScheme
<'tcx
>,
152 predicates
: &ty
::GenericPredicates
<'tcx
>) {
153 encode_generics(rbml_w
, ecx
, &scheme
.generics
, &predicates
, tag_item_generics
);
154 encode_type(ecx
, rbml_w
, scheme
.ty
);
157 fn encode_variant_id(rbml_w
: &mut Encoder
, vid
: DefId
) {
158 let id
= def_to_u64(vid
);
159 rbml_w
.wr_tagged_u64(tag_items_data_item_variant
, id
);
160 rbml_w
.wr_tagged_u64(tag_mod_child
, id
);
163 pub fn write_closure_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
164 rbml_w
: &mut Encoder
,
165 closure_type
: &ty
::ClosureTy
<'tcx
>) {
166 let ty_str_ctxt
= &tyencode
::ctxt
{
170 abbrevs
: &ecx
.type_abbrevs
172 tyencode
::enc_closure_ty(rbml_w
, ty_str_ctxt
, closure_type
);
175 pub fn write_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
176 rbml_w
: &mut Encoder
,
178 let ty_str_ctxt
= &tyencode
::ctxt
{
182 abbrevs
: &ecx
.type_abbrevs
184 tyencode
::enc_ty(rbml_w
, ty_str_ctxt
, typ
);
187 pub fn write_trait_ref
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
188 rbml_w
: &mut Encoder
,
189 trait_ref
: &ty
::TraitRef
<'tcx
>) {
190 let ty_str_ctxt
= &tyencode
::ctxt
{
194 abbrevs
: &ecx
.type_abbrevs
196 tyencode
::enc_trait_ref(rbml_w
, ty_str_ctxt
, *trait_ref
);
199 pub fn write_region(ecx
: &EncodeContext
,
200 rbml_w
: &mut Encoder
,
202 let ty_str_ctxt
= &tyencode
::ctxt
{
206 abbrevs
: &ecx
.type_abbrevs
208 tyencode
::enc_region(rbml_w
, ty_str_ctxt
, r
);
211 fn encode_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
212 rbml_w
: &mut Encoder
,
214 rbml_w
.start_tag(tag_items_data_item_type
);
215 write_type(ecx
, rbml_w
, typ
);
219 fn encode_region(ecx
: &EncodeContext
,
220 rbml_w
: &mut Encoder
,
222 rbml_w
.start_tag(tag_items_data_region
);
223 write_region(ecx
, rbml_w
, r
);
227 fn encode_method_fty
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
228 rbml_w
: &mut Encoder
,
229 typ
: &ty
::BareFnTy
<'tcx
>) {
230 rbml_w
.start_tag(tag_item_method_fty
);
232 let ty_str_ctxt
= &tyencode
::ctxt
{
236 abbrevs
: &ecx
.type_abbrevs
238 tyencode
::enc_bare_fn_ty(rbml_w
, ty_str_ctxt
, typ
);
243 fn encode_symbol(ecx
: &EncodeContext
,
244 rbml_w
: &mut Encoder
,
246 match ecx
.item_symbols
.borrow().get(&id
) {
248 debug
!("encode_symbol(id={}, str={})", id
, *x
);
249 rbml_w
.wr_tagged_str(tag_items_data_item_symbol
, x
);
252 ecx
.diag
.handler().bug(
253 &format
!("encode_symbol: id not found {}", id
));
258 fn encode_disr_val(_
: &EncodeContext
,
259 rbml_w
: &mut Encoder
,
260 disr_val
: ty
::Disr
) {
261 rbml_w
.wr_tagged_str(tag_disr_val
, &disr_val
.to_string());
264 fn encode_parent_item(rbml_w
: &mut Encoder
, id
: DefId
) {
265 rbml_w
.wr_tagged_u64(tag_items_data_parent_item
, def_to_u64(id
));
268 fn encode_struct_fields(rbml_w
: &mut Encoder
,
269 fields
: &[ty
::FieldTy
],
272 if f
.name
== special_idents
::unnamed_field
.name
{
273 rbml_w
.start_tag(tag_item_unnamed_field
);
275 rbml_w
.start_tag(tag_item_field
);
276 encode_name(rbml_w
, f
.name
);
278 encode_struct_field_family(rbml_w
, f
.vis
);
279 encode_def_id(rbml_w
, f
.id
);
280 rbml_w
.wr_tagged_u64(tag_item_field_origin
, def_to_u64(origin
));
285 fn encode_enum_variant_info(ecx
: &EncodeContext
,
286 rbml_w
: &mut Encoder
,
288 variants
: &[P
<ast
::Variant
>],
289 index
: &mut Vec
<entry
<i64>>) {
290 debug
!("encode_enum_variant_info(id={})", id
);
292 let mut disr_val
= 0;
294 let vi
= ecx
.tcx
.enum_variants(local_def(id
));
295 for variant
in variants
{
296 let def_id
= local_def(variant
.node
.id
);
298 val
: variant
.node
.id
as i64,
299 pos
: rbml_w
.mark_stable_position(),
301 rbml_w
.start_tag(tag_items_data_item
);
302 encode_def_id(rbml_w
, def_id
);
303 match variant
.node
.kind
{
304 ast
::TupleVariantKind(_
) => encode_family(rbml_w
, 'v'
),
305 ast
::StructVariantKind(_
) => encode_family(rbml_w
, 'V'
)
307 encode_name(rbml_w
, variant
.node
.name
.name
);
308 encode_parent_item(rbml_w
, local_def(id
));
309 encode_visibility(rbml_w
, variant
.node
.vis
);
310 encode_attributes(rbml_w
, &variant
.node
.attrs
);
311 encode_repr_attrs(rbml_w
, ecx
, &variant
.node
.attrs
);
313 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(variant
.node
.id
));
314 encode_stability(rbml_w
, stab
);
316 match variant
.node
.kind
{
317 ast
::TupleVariantKind(_
) => {}
,
318 ast
::StructVariantKind(_
) => {
319 let fields
= ecx
.tcx
.lookup_struct_fields(def_id
);
320 let idx
= encode_info_for_struct(ecx
,
324 encode_struct_fields(rbml_w
, &fields
[..], def_id
);
325 encode_index(rbml_w
, idx
, write_i64
);
328 let specified_disr_val
= vi
[i
].disr_val
;
329 if specified_disr_val
!= disr_val
{
330 encode_disr_val(ecx
, rbml_w
, specified_disr_val
);
331 disr_val
= specified_disr_val
;
333 encode_bounds_and_type_for_item(rbml_w
, ecx
, def_id
.local_id());
335 ecx
.tcx
.map
.with_path(variant
.node
.id
, |path
| encode_path(rbml_w
, path
));
337 disr_val
= disr_val
.wrapping_add(1);
342 fn encode_path
<PI
: Iterator
<Item
=PathElem
>>(rbml_w
: &mut Encoder
, path
: PI
) {
343 let path
= path
.collect
::<Vec
<_
>>();
344 rbml_w
.start_tag(tag_path
);
345 rbml_w
.wr_tagged_u32(tag_path_len
, path
.len() as u32);
347 let tag
= match *pe
{
348 ast_map
::PathMod(_
) => tag_path_elem_mod
,
349 ast_map
::PathName(_
) => tag_path_elem_name
351 rbml_w
.wr_tagged_str(tag
, &pe
.name().as_str());
356 fn encode_reexported_static_method(rbml_w
: &mut Encoder
,
358 method_def_id
: DefId
,
359 method_name
: ast
::Name
) {
360 debug
!("(encode reexported static method) {}::{}",
361 exp
.name
, method_name
);
362 rbml_w
.start_tag(tag_items_data_item_reexport
);
363 rbml_w
.wr_tagged_u64(tag_items_data_item_reexport_def_id
,
364 def_to_u64(method_def_id
));
365 rbml_w
.wr_tagged_str(tag_items_data_item_reexport_name
,
366 &format
!("{}::{}", exp
.name
,
371 fn encode_reexported_static_base_methods(ecx
: &EncodeContext
,
372 rbml_w
: &mut Encoder
,
375 let impl_items
= ecx
.tcx
.impl_items
.borrow();
376 match ecx
.tcx
.inherent_impls
.borrow().get(&exp
.def_id
) {
377 Some(implementations
) => {
378 for base_impl_did
in implementations
.iter() {
379 for &method_did
in impl_items
.get(base_impl_did
).unwrap() {
380 let impl_item
= ecx
.tcx
.impl_or_trait_item(method_did
.def_id());
381 if let ty
::MethodTraitItem(ref m
) = impl_item
{
382 encode_reexported_static_method(rbml_w
,
396 fn encode_reexported_static_trait_methods(ecx
: &EncodeContext
,
397 rbml_w
: &mut Encoder
,
400 match ecx
.tcx
.trait_items_cache
.borrow().get(&exp
.def_id
) {
401 Some(trait_items
) => {
402 for trait_item
in trait_items
.iter() {
403 if let ty
::MethodTraitItem(ref m
) = *trait_item
{
404 encode_reexported_static_method(rbml_w
,
416 fn encode_reexported_static_methods(ecx
: &EncodeContext
,
417 rbml_w
: &mut Encoder
,
420 if let Some(ast_map
::NodeItem(item
)) = ecx
.tcx
.map
.find(exp
.def_id
.node
) {
421 let path_differs
= ecx
.tcx
.map
.with_path(exp
.def_id
.node
, |path
| {
422 let (mut a
, mut b
) = (path
, mod_path
.clone());
424 match (a
.next(), b
.next()) {
425 (None
, None
) => return true,
426 (None
, _
) | (_
, None
) => return false,
427 (Some(x
), Some(y
)) => if x
!= y { return false }
,
433 // We don't need to reexport static methods on items
434 // declared in the same module as our `pub use ...` since
435 // that's done when we encode the item itself.
437 // The only exception is when the reexport *changes* the
438 // name e.g. `pub use Foo = self::Bar` -- we have
439 // encoded metadata for static methods relative to Bar,
440 // but not yet for Foo.
442 if path_differs
|| item
.ident
.name
!= exp
.name
{
443 if !encode_reexported_static_base_methods(ecx
, rbml_w
, exp
) {
444 if encode_reexported_static_trait_methods(ecx
, rbml_w
, exp
) {
445 debug
!("(encode reexported static methods) {} [trait]",
450 debug
!("(encode reexported static methods) {} [base]",
457 /// Iterates through "auxiliary node IDs", which are node IDs that describe
458 /// top-level items that are sub-items of the given item. Specifically:
460 /// * For newtype structs, iterates through the node ID of the constructor.
461 fn each_auxiliary_node_id
<F
>(item
: &ast
::Item
, callback
: F
) -> bool
where
462 F
: FnOnce(NodeId
) -> bool
,
464 let mut continue_
= true;
466 ast
::ItemStruct(ref struct_def
, _
) => {
467 // If this is a newtype struct, return the constructor.
468 match struct_def
.ctor_id
{
469 Some(ctor_id
) if !struct_def
.fields
.is_empty() &&
470 struct_def
.fields
[0].node
.kind
.is_unnamed() => {
471 continue_
= callback(ctor_id
);
482 fn encode_reexports(ecx
: &EncodeContext
,
483 rbml_w
: &mut Encoder
,
486 debug
!("(encoding info for module) encoding reexports for {}", id
);
487 match ecx
.reexports
.get(&id
) {
489 debug
!("(encoding info for module) found reexports for {}", id
);
491 debug
!("(encoding info for module) reexport '{}' ({}/{}) for \
497 rbml_w
.start_tag(tag_items_data_item_reexport
);
498 rbml_w
.wr_tagged_u64(tag_items_data_item_reexport_def_id
,
499 def_to_u64(exp
.def_id
));
500 rbml_w
.wr_tagged_str(tag_items_data_item_reexport_name
,
503 encode_reexported_static_methods(ecx
, rbml_w
, path
.clone(), exp
);
506 None
=> debug
!("(encoding info for module) found no reexports for {}", id
),
510 fn encode_info_for_mod(ecx
: &EncodeContext
,
511 rbml_w
: &mut Encoder
,
513 attrs
: &[ast
::Attribute
],
517 vis
: ast
::Visibility
) {
518 rbml_w
.start_tag(tag_items_data_item
);
519 encode_def_id(rbml_w
, local_def(id
));
520 encode_family(rbml_w
, 'm'
);
521 encode_name(rbml_w
, name
);
522 debug
!("(encoding info for module) encoding info for module ID {}", id
);
524 // Encode info about all the module children.
525 for item
in &md
.items
{
526 rbml_w
.wr_tagged_u64(tag_mod_child
,
527 def_to_u64(local_def(item
.id
)));
529 each_auxiliary_node_id(&**item
, |auxiliary_node_id
| {
530 rbml_w
.wr_tagged_u64(tag_mod_child
,
531 def_to_u64(local_def(auxiliary_node_id
)));
535 if let ast
::ItemImpl(..) = item
.node
{
536 let (ident
, did
) = (item
.ident
, item
.id
);
537 debug
!("(encoding info for module) ... encoding impl {} ({}/{})",
539 did
, ecx
.tcx
.map
.node_to_string(did
));
541 rbml_w
.wr_tagged_u64(tag_mod_impl
, def_to_u64(local_def(did
)));
545 encode_path(rbml_w
, path
.clone());
546 encode_visibility(rbml_w
, vis
);
548 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(id
));
549 encode_stability(rbml_w
, stab
);
551 // Encode the reexports of this module, if this module is public.
552 if vis
== ast
::Public
{
553 debug
!("(encoding info for module) encoding reexports for {}", id
);
554 encode_reexports(ecx
, rbml_w
, id
, path
);
556 encode_attributes(rbml_w
, attrs
);
561 fn encode_struct_field_family(rbml_w
: &mut Encoder
,
562 visibility
: ast
::Visibility
) {
563 encode_family(rbml_w
, match visibility
{
565 ast
::Inherited
=> 'N'
569 fn encode_visibility(rbml_w
: &mut Encoder
, visibility
: ast
::Visibility
) {
570 let ch
= match visibility
{
572 ast
::Inherited
=> 'i'
,
574 rbml_w
.wr_tagged_u8(tag_items_data_item_visibility
, ch
as u8);
577 fn encode_constness(rbml_w
: &mut Encoder
, constness
: ast
::Constness
) {
578 rbml_w
.start_tag(tag_items_data_item_constness
);
579 let ch
= match constness
{
580 ast
::Constness
::Const
=> 'c'
,
581 ast
::Constness
::NotConst
=> 'n'
,
583 rbml_w
.wr_str(&ch
.to_string());
587 fn encode_explicit_self(rbml_w
: &mut Encoder
,
588 explicit_self
: &ty
::ExplicitSelfCategory
) {
589 let tag
= tag_item_trait_method_explicit_self
;
591 // Encode the base self type.
592 match *explicit_self
{
593 ty
::StaticExplicitSelfCategory
=> {
594 rbml_w
.wr_tagged_bytes(tag
, &['s'
as u8]);
596 ty
::ByValueExplicitSelfCategory
=> {
597 rbml_w
.wr_tagged_bytes(tag
, &['v'
as u8]);
599 ty
::ByBoxExplicitSelfCategory
=> {
600 rbml_w
.wr_tagged_bytes(tag
, &['
~'
as u8]);
602 ty
::ByReferenceExplicitSelfCategory(_
, m
) => {
603 // FIXME(#4846) encode custom lifetime
604 let ch
= encode_mutability(m
);
605 rbml_w
.wr_tagged_bytes(tag
, &['
&'
as u8, ch
]);
609 fn encode_mutability(m
: ast
::Mutability
) -> u8 {
611 ast
::MutImmutable
=> 'i'
as u8,
612 ast
::MutMutable
=> 'm'
as u8,
617 fn encode_item_sort(rbml_w
: &mut Encoder
, sort
: char) {
618 rbml_w
.wr_tagged_u8(tag_item_trait_item_sort
, sort
as u8);
621 fn encode_parent_sort(rbml_w
: &mut Encoder
, sort
: char) {
622 rbml_w
.wr_tagged_u8(tag_item_trait_parent_sort
, sort
as u8);
625 fn encode_provided_source(rbml_w
: &mut Encoder
,
626 source_opt
: Option
<DefId
>) {
627 if let Some(source
) = source_opt
{
628 rbml_w
.wr_tagged_u64(tag_item_method_provided_source
, def_to_u64(source
));
632 /* Returns an index of items in this class */
633 fn encode_info_for_struct(ecx
: &EncodeContext
,
634 rbml_w
: &mut Encoder
,
635 fields
: &[ty
::FieldTy
],
636 global_index
: &mut Vec
<entry
<i64>>)
638 /* Each class has its own index, since different classes
639 may have fields with the same name */
640 let mut index
= Vec
::new();
641 /* We encode both private and public fields -- need to include
642 private fields to get the offsets right */
643 for field
in fields
{
645 let id
= field
.id
.node
;
647 let pos
= rbml_w
.mark_stable_position();
648 index
.push(entry {val: id as i64, pos: pos}
);
649 global_index
.push(entry
{
653 rbml_w
.start_tag(tag_items_data_item
);
654 debug
!("encode_info_for_struct: doing {} {}",
656 encode_struct_field_family(rbml_w
, field
.vis
);
657 encode_name(rbml_w
, nm
);
658 encode_bounds_and_type_for_item(rbml_w
, ecx
, id
);
659 encode_def_id(rbml_w
, local_def(id
));
661 let stab
= stability
::lookup(ecx
.tcx
, field
.id
);
662 encode_stability(rbml_w
, stab
);
669 fn encode_info_for_struct_ctor(ecx
: &EncodeContext
,
670 rbml_w
: &mut Encoder
,
673 index
: &mut Vec
<entry
<i64>>,
677 pos
: rbml_w
.mark_stable_position(),
680 rbml_w
.start_tag(tag_items_data_item
);
681 encode_def_id(rbml_w
, local_def(ctor_id
));
682 encode_family(rbml_w
, 'o'
);
683 encode_bounds_and_type_for_item(rbml_w
, ecx
, ctor_id
);
684 encode_name(rbml_w
, name
);
685 ecx
.tcx
.map
.with_path(ctor_id
, |path
| encode_path(rbml_w
, path
));
686 encode_parent_item(rbml_w
, local_def(struct_id
));
688 if ecx
.item_symbols
.borrow().contains_key(&ctor_id
) {
689 encode_symbol(ecx
, rbml_w
, ctor_id
);
692 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(ctor_id
));
693 encode_stability(rbml_w
, stab
);
695 // indicate that this is a tuple struct ctor, because downstream users will normally want
696 // the tuple struct definition, but without this there is no way for them to tell that
697 // they actually have a ctor rather than a normal function
698 rbml_w
.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor
, &[]);
703 fn encode_generics
<'a
, 'tcx
>(rbml_w
: &mut Encoder
,
704 ecx
: &EncodeContext
<'a
, 'tcx
>,
705 generics
: &ty
::Generics
<'tcx
>,
706 predicates
: &ty
::GenericPredicates
<'tcx
>,
709 rbml_w
.start_tag(tag
);
712 let ty_str_ctxt
= &tyencode
::ctxt
{
716 abbrevs
: &ecx
.type_abbrevs
719 for param
in &generics
.types
{
720 rbml_w
.start_tag(tag_type_param_def
);
721 tyencode
::enc_type_param_def(rbml_w
, ty_str_ctxt
, param
);
726 for param
in &generics
.regions
{
727 rbml_w
.start_tag(tag_region_param_def
);
729 rbml_w
.start_tag(tag_region_param_def_ident
);
730 encode_name(rbml_w
, param
.name
);
733 rbml_w
.wr_tagged_u64(tag_region_param_def_def_id
,
734 def_to_u64(param
.def_id
));
736 rbml_w
.wr_tagged_u64(tag_region_param_def_space
,
737 param
.space
.to_uint() as u64);
739 rbml_w
.wr_tagged_u64(tag_region_param_def_index
,
742 for &bound_region
in ¶m
.bounds
{
743 encode_region(ecx
, rbml_w
, bound_region
);
749 encode_predicates_in_current_doc(rbml_w
, ecx
, predicates
);
754 fn encode_predicates_in_current_doc
<'a
,'tcx
>(rbml_w
: &mut Encoder
,
755 ecx
: &EncodeContext
<'a
,'tcx
>,
756 predicates
: &ty
::GenericPredicates
<'tcx
>)
758 let ty_str_ctxt
= &tyencode
::ctxt
{
762 abbrevs
: &ecx
.type_abbrevs
765 for (space
, _
, predicate
) in predicates
.predicates
.iter_enumerated() {
766 rbml_w
.start_tag(tag_predicate
);
768 rbml_w
.wr_tagged_u8(tag_predicate_space
, space
as u8);
770 rbml_w
.start_tag(tag_predicate_data
);
771 tyencode
::enc_predicate(rbml_w
, ty_str_ctxt
, predicate
);
778 fn encode_predicates
<'a
,'tcx
>(rbml_w
: &mut Encoder
,
779 ecx
: &EncodeContext
<'a
,'tcx
>,
780 predicates
: &ty
::GenericPredicates
<'tcx
>,
783 rbml_w
.start_tag(tag
);
784 encode_predicates_in_current_doc(rbml_w
, ecx
, predicates
);
788 fn encode_method_ty_fields
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
789 rbml_w
: &mut Encoder
,
790 method_ty
: &ty
::Method
<'tcx
>) {
791 encode_def_id(rbml_w
, method_ty
.def_id
);
792 encode_name(rbml_w
, method_ty
.name
);
793 encode_generics(rbml_w
, ecx
, &method_ty
.generics
, &method_ty
.predicates
,
794 tag_method_ty_generics
);
795 encode_method_fty(ecx
, rbml_w
, &method_ty
.fty
);
796 encode_visibility(rbml_w
, method_ty
.vis
);
797 encode_explicit_self(rbml_w
, &method_ty
.explicit_self
);
798 match method_ty
.explicit_self
{
799 ty
::StaticExplicitSelfCategory
=> {
800 encode_family(rbml_w
, STATIC_METHOD_FAMILY
);
802 _
=> encode_family(rbml_w
, METHOD_FAMILY
)
804 encode_provided_source(rbml_w
, method_ty
.provided_source
);
807 fn encode_info_for_associated_const(ecx
: &EncodeContext
,
808 rbml_w
: &mut Encoder
,
809 associated_const
: &ty
::AssociatedConst
,
810 impl_path
: PathElems
,
812 impl_item_opt
: Option
<&ast
::ImplItem
>) {
813 debug
!("encode_info_for_associated_const({:?},{:?})",
814 associated_const
.def_id
,
815 associated_const
.name
);
817 rbml_w
.start_tag(tag_items_data_item
);
819 encode_def_id(rbml_w
, associated_const
.def_id
);
820 encode_name(rbml_w
, associated_const
.name
);
821 encode_visibility(rbml_w
, associated_const
.vis
);
822 encode_family(rbml_w
, 'C'
);
823 encode_provided_source(rbml_w
, associated_const
.default);
825 encode_parent_item(rbml_w
, local_def(parent_id
));
826 encode_item_sort(rbml_w
, 'C'
);
828 encode_bounds_and_type_for_item(rbml_w
, ecx
, associated_const
.def_id
.local_id());
830 let stab
= stability
::lookup(ecx
.tcx
, associated_const
.def_id
);
831 encode_stability(rbml_w
, stab
);
833 let elem
= ast_map
::PathName(associated_const
.name
);
834 encode_path(rbml_w
, impl_path
.chain(Some(elem
)));
836 if let Some(ii
) = impl_item_opt
{
837 encode_attributes(rbml_w
, &ii
.attrs
);
838 encode_inlined_item(ecx
, rbml_w
, IIImplItemRef(local_def(parent_id
), ii
));
844 fn encode_info_for_method
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
845 rbml_w
: &mut Encoder
,
846 m
: &ty
::Method
<'tcx
>,
847 impl_path
: PathElems
,
848 is_default_impl
: bool
,
850 impl_item_opt
: Option
<&ast
::ImplItem
>) {
852 debug
!("encode_info_for_method: {:?} {:?}", m
.def_id
,
854 rbml_w
.start_tag(tag_items_data_item
);
856 encode_method_ty_fields(ecx
, rbml_w
, m
);
857 encode_parent_item(rbml_w
, local_def(parent_id
));
858 encode_item_sort(rbml_w
, 'r'
);
860 let stab
= stability
::lookup(ecx
.tcx
, m
.def_id
);
861 encode_stability(rbml_w
, stab
);
863 // The type for methods gets encoded twice, which is unfortunate.
864 encode_bounds_and_type_for_item(rbml_w
, ecx
, m
.def_id
.local_id());
866 let elem
= ast_map
::PathName(m
.name
);
867 encode_path(rbml_w
, impl_path
.chain(Some(elem
)));
868 if let Some(impl_item
) = impl_item_opt
{
869 if let ast
::MethodImplItem(ref sig
, _
) = impl_item
.node
{
870 encode_attributes(rbml_w
, &impl_item
.attrs
);
871 let scheme
= ecx
.tcx
.lookup_item_type(m
.def_id
);
872 let any_types
= !scheme
.generics
.types
.is_empty();
873 let needs_inline
= any_types
|| is_default_impl
||
874 attr
::requests_inline(&impl_item
.attrs
);
875 if needs_inline
|| sig
.constness
== ast
::Constness
::Const
{
876 encode_inlined_item(ecx
, rbml_w
, IIImplItemRef(local_def(parent_id
),
879 encode_constness(rbml_w
, sig
.constness
);
881 encode_symbol(ecx
, rbml_w
, m
.def_id
.node
);
883 encode_method_argument_names(rbml_w
, &sig
.decl
);
890 fn encode_info_for_associated_type
<'a
, 'tcx
>(ecx
: &EncodeContext
<'a
, 'tcx
>,
891 rbml_w
: &mut Encoder
,
892 associated_type
: &ty
::AssociatedType
<'tcx
>,
893 impl_path
: PathElems
,
895 impl_item_opt
: Option
<&ast
::ImplItem
>) {
896 debug
!("encode_info_for_associated_type({:?},{:?})",
897 associated_type
.def_id
,
898 associated_type
.name
);
900 rbml_w
.start_tag(tag_items_data_item
);
902 encode_def_id(rbml_w
, associated_type
.def_id
);
903 encode_name(rbml_w
, associated_type
.name
);
904 encode_visibility(rbml_w
, associated_type
.vis
);
905 encode_family(rbml_w
, 'y'
);
906 encode_parent_item(rbml_w
, local_def(parent_id
));
907 encode_item_sort(rbml_w
, 't'
);
909 let stab
= stability
::lookup(ecx
.tcx
, associated_type
.def_id
);
910 encode_stability(rbml_w
, stab
);
912 let elem
= ast_map
::PathName(associated_type
.name
);
913 encode_path(rbml_w
, impl_path
.chain(Some(elem
)));
915 if let Some(ii
) = impl_item_opt
{
916 encode_attributes(rbml_w
, &ii
.attrs
);
918 encode_predicates(rbml_w
, ecx
,
919 &ecx
.tcx
.lookup_predicates(associated_type
.def_id
),
923 if let Some(ty
) = associated_type
.ty
{
924 encode_type(ecx
, rbml_w
, ty
);
930 fn encode_method_argument_names(rbml_w
: &mut Encoder
,
931 decl
: &ast
::FnDecl
) {
932 rbml_w
.start_tag(tag_method_argument_names
);
933 for arg
in &decl
.inputs
{
934 let tag
= tag_method_argument_name
;
935 if let ast
::PatIdent(_
, ref path1
, _
) = arg
.pat
.node
{
936 let name
= path1
.node
.name
.as_str();
937 rbml_w
.wr_tagged_bytes(tag
, name
.as_bytes());
939 rbml_w
.wr_tagged_bytes(tag
, &[]);
945 fn encode_repr_attrs(rbml_w
: &mut Encoder
,
947 attrs
: &[ast
::Attribute
]) {
948 let mut repr_attrs
= Vec
::new();
950 repr_attrs
.extend(attr
::find_repr_attrs(ecx
.tcx
.sess
.diagnostic(),
953 rbml_w
.start_tag(tag_items_data_item_repr
);
954 repr_attrs
.encode(rbml_w
);
958 fn encode_inlined_item(ecx
: &EncodeContext
,
959 rbml_w
: &mut Encoder
,
960 ii
: InlinedItemRef
) {
961 let mut eii
= ecx
.encode_inlined_item
.borrow_mut();
962 let eii
: &mut EncodeInlinedItem
= &mut *eii
;
966 const FN_FAMILY
: char = 'f'
;
967 const STATIC_METHOD_FAMILY
: char = 'F'
;
968 const METHOD_FAMILY
: char = 'h'
;
970 // Encodes the inherent implementations of a structure, enumeration, or trait.
971 fn encode_inherent_implementations(ecx
: &EncodeContext
,
972 rbml_w
: &mut Encoder
,
974 match ecx
.tcx
.inherent_impls
.borrow().get(&def_id
) {
976 Some(implementations
) => {
977 for &impl_def_id
in implementations
.iter() {
978 rbml_w
.start_tag(tag_items_data_item_inherent_impl
);
979 encode_def_id(rbml_w
, impl_def_id
);
986 // Encodes the implementations of a trait defined in this crate.
987 fn encode_extension_implementations(ecx
: &EncodeContext
,
988 rbml_w
: &mut Encoder
,
989 trait_def_id
: DefId
) {
990 assert
!(ast_util
::is_local(trait_def_id
));
991 let def
= ecx
.tcx
.lookup_trait_def(trait_def_id
);
993 def
.for_each_impl(ecx
.tcx
, |impl_def_id
| {
994 rbml_w
.start_tag(tag_items_data_item_extension_impl
);
995 encode_def_id(rbml_w
, impl_def_id
);
1000 fn encode_stability(rbml_w
: &mut Encoder
, stab_opt
: Option
<&attr
::Stability
>) {
1001 stab_opt
.map(|stab
| {
1002 rbml_w
.start_tag(tag_items_data_item_stability
);
1003 stab
.encode(rbml_w
).unwrap();
1008 fn encode_info_for_item(ecx
: &EncodeContext
,
1009 rbml_w
: &mut Encoder
,
1011 index
: &mut Vec
<entry
<i64>>,
1013 vis
: ast
::Visibility
) {
1016 fn add_to_index(item
: &ast
::Item
, rbml_w
: &mut Encoder
,
1017 index
: &mut Vec
<entry
<i64>>) {
1019 val
: item
.id
as i64,
1020 pos
: rbml_w
.mark_stable_position(),
1024 debug
!("encoding info for item at {}",
1025 tcx
.sess
.codemap().span_to_string(item
.span
));
1027 let def_id
= local_def(item
.id
);
1028 let stab
= stability
::lookup(tcx
, ast_util
::local_def(item
.id
));
1031 ast
::ItemStatic(_
, m
, _
) => {
1032 add_to_index(item
, rbml_w
, index
);
1033 rbml_w
.start_tag(tag_items_data_item
);
1034 encode_def_id(rbml_w
, def_id
);
1035 if m
== ast
::MutMutable
{
1036 encode_family(rbml_w
, 'b'
);
1038 encode_family(rbml_w
, 'c'
);
1040 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1041 encode_symbol(ecx
, rbml_w
, item
.id
);
1042 encode_name(rbml_w
, item
.ident
.name
);
1043 encode_path(rbml_w
, path
);
1044 encode_visibility(rbml_w
, vis
);
1045 encode_stability(rbml_w
, stab
);
1046 encode_attributes(rbml_w
, &item
.attrs
);
1049 ast
::ItemConst(_
, _
) => {
1050 add_to_index(item
, rbml_w
, index
);
1051 rbml_w
.start_tag(tag_items_data_item
);
1052 encode_def_id(rbml_w
, def_id
);
1053 encode_family(rbml_w
, 'C'
);
1054 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1055 encode_name(rbml_w
, item
.ident
.name
);
1056 encode_path(rbml_w
, path
);
1057 encode_attributes(rbml_w
, &item
.attrs
);
1058 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1059 encode_visibility(rbml_w
, vis
);
1060 encode_stability(rbml_w
, stab
);
1063 ast
::ItemFn(ref decl
, _
, constness
, _
, ref generics
, _
) => {
1064 add_to_index(item
, rbml_w
, index
);
1065 rbml_w
.start_tag(tag_items_data_item
);
1066 encode_def_id(rbml_w
, def_id
);
1067 encode_family(rbml_w
, FN_FAMILY
);
1068 let tps_len
= generics
.ty_params
.len();
1069 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1070 encode_name(rbml_w
, item
.ident
.name
);
1071 encode_path(rbml_w
, path
);
1072 encode_attributes(rbml_w
, &item
.attrs
);
1073 let needs_inline
= tps_len
> 0 || attr
::requests_inline(&item
.attrs
);
1074 if needs_inline
|| constness
== ast
::Constness
::Const
{
1075 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1078 encode_symbol(ecx
, rbml_w
, item
.id
);
1080 encode_constness(rbml_w
, constness
);
1081 encode_visibility(rbml_w
, vis
);
1082 encode_stability(rbml_w
, stab
);
1083 encode_method_argument_names(rbml_w
, &**decl
);
1086 ast
::ItemMod(ref m
) => {
1087 add_to_index(item
, rbml_w
, index
);
1088 encode_info_for_mod(ecx
,
1097 ast
::ItemForeignMod(ref fm
) => {
1098 add_to_index(item
, rbml_w
, index
);
1099 rbml_w
.start_tag(tag_items_data_item
);
1100 encode_def_id(rbml_w
, def_id
);
1101 encode_family(rbml_w
, 'n'
);
1102 encode_name(rbml_w
, item
.ident
.name
);
1103 encode_path(rbml_w
, path
);
1105 // Encode all the items in this module.
1106 for foreign_item
in &fm
.items
{
1107 rbml_w
.wr_tagged_u64(tag_mod_child
,
1108 def_to_u64(local_def(foreign_item
.id
)));
1110 encode_visibility(rbml_w
, vis
);
1111 encode_stability(rbml_w
, stab
);
1114 ast
::ItemTy(..) => {
1115 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
, 'y'
);
1119 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1120 encode_name(rbml_w
, item
.ident
.name
);
1121 encode_path(rbml_w
, path
);
1122 encode_visibility(rbml_w
, vis
);
1123 encode_stability(rbml_w
, stab
);
1126 ast
::ItemEnum(ref enum_definition
, _
) => {
1127 add_to_index(item
, rbml_w
, index
);
1129 rbml_w
.start_tag(tag_items_data_item
);
1130 encode_def_id(rbml_w
, def_id
);
1131 encode_family(rbml_w
, 't'
);
1132 encode_item_variances(rbml_w
, ecx
, item
.id
);
1133 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1134 encode_name(rbml_w
, item
.ident
.name
);
1135 encode_attributes(rbml_w
, &item
.attrs
);
1136 encode_repr_attrs(rbml_w
, ecx
, &item
.attrs
);
1137 for v
in &enum_definition
.variants
{
1138 encode_variant_id(rbml_w
, local_def(v
.node
.id
));
1140 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1141 encode_path(rbml_w
, path
);
1143 // Encode inherent implementations for this enumeration.
1144 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1146 encode_visibility(rbml_w
, vis
);
1147 encode_stability(rbml_w
, stab
);
1150 encode_enum_variant_info(ecx
,
1153 &(*enum_definition
).variants
,
1156 ast
::ItemStruct(ref struct_def
, _
) => {
1157 let fields
= tcx
.lookup_struct_fields(def_id
);
1159 /* First, encode the fields
1160 These come first because we need to write them to make
1161 the index, and the index needs to be in the item for the
1163 let idx
= encode_info_for_struct(ecx
,
1168 /* Index the class*/
1169 add_to_index(item
, rbml_w
, index
);
1171 /* Now, make an item for the class itself */
1172 rbml_w
.start_tag(tag_items_data_item
);
1173 encode_def_id(rbml_w
, def_id
);
1174 encode_family(rbml_w
, 'S'
);
1175 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1177 encode_item_variances(rbml_w
, ecx
, item
.id
);
1178 encode_name(rbml_w
, item
.ident
.name
);
1179 encode_attributes(rbml_w
, &item
.attrs
);
1180 encode_path(rbml_w
, path
.clone());
1181 encode_stability(rbml_w
, stab
);
1182 encode_visibility(rbml_w
, vis
);
1183 encode_repr_attrs(rbml_w
, ecx
, &item
.attrs
);
1185 /* Encode def_ids for each field and method
1186 for methods, write all the stuff get_trait_method
1188 encode_struct_fields(rbml_w
, &fields
[..], def_id
);
1190 encode_inlined_item(ecx
, rbml_w
, IIItemRef(item
));
1192 // Encode inherent implementations for this structure.
1193 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1195 /* Each class has its own index -- encode it */
1196 encode_index(rbml_w
, idx
, write_i64
);
1199 // If this is a tuple-like struct, encode the type of the constructor.
1200 match struct_def
.ctor_id
{
1202 encode_info_for_struct_ctor(ecx
, rbml_w
, item
.ident
.name
,
1203 ctor_id
, index
, def_id
.node
);
1208 ast
::ItemDefaultImpl(unsafety
, _
) => {
1209 add_to_index(item
, rbml_w
, index
);
1210 rbml_w
.start_tag(tag_items_data_item
);
1211 encode_def_id(rbml_w
, def_id
);
1212 encode_family(rbml_w
, 'd'
);
1213 encode_name(rbml_w
, item
.ident
.name
);
1214 encode_unsafety(rbml_w
, unsafety
);
1216 let trait_ref
= tcx
.impl_trait_ref(local_def(item
.id
)).unwrap();
1217 encode_trait_ref(rbml_w
, ecx
, trait_ref
, tag_item_trait_ref
);
1220 ast
::ItemImpl(unsafety
, polarity
, _
, _
, ref ty
, ref ast_items
) => {
1221 // We need to encode information about the default methods we
1222 // have inherited, so we drive this based on the impl structure.
1223 let impl_items
= tcx
.impl_items
.borrow();
1224 let items
= impl_items
.get(&def_id
).unwrap();
1226 add_to_index(item
, rbml_w
, index
);
1227 rbml_w
.start_tag(tag_items_data_item
);
1228 encode_def_id(rbml_w
, def_id
);
1229 encode_family(rbml_w
, 'i'
);
1230 encode_bounds_and_type_for_item(rbml_w
, ecx
, item
.id
);
1231 encode_name(rbml_w
, item
.ident
.name
);
1232 encode_attributes(rbml_w
, &item
.attrs
);
1233 encode_unsafety(rbml_w
, unsafety
);
1234 encode_polarity(rbml_w
, polarity
);
1236 match tcx
.custom_coerce_unsized_kinds
.borrow().get(&local_def(item
.id
)) {
1238 rbml_w
.start_tag(tag_impl_coerce_unsized_kind
);
1239 kind
.encode(rbml_w
);
1246 ast
::TyPath(None
, ref path
) if path
.segments
.len() == 1 => {
1247 let name
= path
.segments
.last().unwrap().identifier
.name
;
1248 encode_impl_type_basename(rbml_w
, name
);
1252 for &item_def_id
in items
{
1253 rbml_w
.start_tag(tag_item_impl_item
);
1255 ty
::ConstTraitItemId(item_def_id
) => {
1256 encode_def_id(rbml_w
, item_def_id
);
1257 encode_item_sort(rbml_w
, 'C'
);
1259 ty
::MethodTraitItemId(item_def_id
) => {
1260 encode_def_id(rbml_w
, item_def_id
);
1261 encode_item_sort(rbml_w
, 'r'
);
1263 ty
::TypeTraitItemId(item_def_id
) => {
1264 encode_def_id(rbml_w
, item_def_id
);
1265 encode_item_sort(rbml_w
, 't'
);
1270 if let Some(trait_ref
) = tcx
.impl_trait_ref(local_def(item
.id
)) {
1271 encode_trait_ref(rbml_w
, ecx
, trait_ref
, tag_item_trait_ref
);
1273 encode_path(rbml_w
, path
.clone());
1274 encode_stability(rbml_w
, stab
);
1277 // Iterate down the trait items, emitting them. We rely on the
1278 // assumption that all of the actually implemented trait items
1279 // appear first in the impl structure, in the same order they do
1280 // in the ast. This is a little sketchy.
1281 let num_implemented_methods
= ast_items
.len();
1282 for (i
, &trait_item_def_id
) in items
.iter().enumerate() {
1283 let ast_item
= if i
< num_implemented_methods
{
1284 Some(&*ast_items
[i
])
1290 val
: trait_item_def_id
.def_id().node
as i64,
1291 pos
: rbml_w
.mark_stable_position(),
1294 match tcx
.impl_or_trait_item(trait_item_def_id
.def_id()) {
1295 ty
::ConstTraitItem(ref associated_const
) => {
1296 encode_info_for_associated_const(ecx
,
1303 ty
::MethodTraitItem(ref method_type
) => {
1304 encode_info_for_method(ecx
,
1312 ty
::TypeTraitItem(ref associated_type
) => {
1313 encode_info_for_associated_type(ecx
,
1323 ast
::ItemTrait(_
, _
, _
, ref ms
) => {
1324 add_to_index(item
, rbml_w
, index
);
1325 rbml_w
.start_tag(tag_items_data_item
);
1326 encode_def_id(rbml_w
, def_id
);
1327 encode_family(rbml_w
, 'I'
);
1328 encode_item_variances(rbml_w
, ecx
, item
.id
);
1329 let trait_def
= tcx
.lookup_trait_def(def_id
);
1330 let trait_predicates
= tcx
.lookup_predicates(def_id
);
1331 encode_unsafety(rbml_w
, trait_def
.unsafety
);
1332 encode_paren_sugar(rbml_w
, trait_def
.paren_sugar
);
1333 encode_defaulted(rbml_w
, tcx
.trait_has_default_impl(def_id
));
1334 encode_associated_type_names(rbml_w
, &trait_def
.associated_type_names
);
1335 encode_generics(rbml_w
, ecx
, &trait_def
.generics
, &trait_predicates
,
1337 encode_predicates(rbml_w
, ecx
, &tcx
.lookup_super_predicates(def_id
),
1338 tag_item_super_predicates
);
1339 encode_trait_ref(rbml_w
, ecx
, trait_def
.trait_ref
, tag_item_trait_ref
);
1340 encode_name(rbml_w
, item
.ident
.name
);
1341 encode_attributes(rbml_w
, &item
.attrs
);
1342 encode_visibility(rbml_w
, vis
);
1343 encode_stability(rbml_w
, stab
);
1344 for &method_def_id
in tcx
.trait_item_def_ids(def_id
).iter() {
1345 rbml_w
.start_tag(tag_item_trait_item
);
1346 match method_def_id
{
1347 ty
::ConstTraitItemId(const_def_id
) => {
1348 encode_def_id(rbml_w
, const_def_id
);
1349 encode_item_sort(rbml_w
, 'C'
);
1351 ty
::MethodTraitItemId(method_def_id
) => {
1352 encode_def_id(rbml_w
, method_def_id
);
1353 encode_item_sort(rbml_w
, 'r'
);
1355 ty
::TypeTraitItemId(type_def_id
) => {
1356 encode_def_id(rbml_w
, type_def_id
);
1357 encode_item_sort(rbml_w
, 't'
);
1362 rbml_w
.wr_tagged_u64(tag_mod_child
,
1363 def_to_u64(method_def_id
.def_id()));
1365 encode_path(rbml_w
, path
.clone());
1367 // Encode the implementations of this trait.
1368 encode_extension_implementations(ecx
, rbml_w
, def_id
);
1370 // Encode inherent implementations for this trait.
1371 encode_inherent_implementations(ecx
, rbml_w
, def_id
);
1375 // Now output the trait item info for each trait item.
1376 let r
= tcx
.trait_item_def_ids(def_id
);
1377 for (i
, &item_def_id
) in r
.iter().enumerate() {
1378 assert_eq
!(item_def_id
.def_id().krate
, ast
::LOCAL_CRATE
);
1381 val
: item_def_id
.def_id().node
as i64,
1382 pos
: rbml_w
.mark_stable_position(),
1385 rbml_w
.start_tag(tag_items_data_item
);
1387 encode_parent_item(rbml_w
, def_id
);
1389 let stab
= stability
::lookup(tcx
, item_def_id
.def_id());
1390 encode_stability(rbml_w
, stab
);
1392 let trait_item_type
=
1393 tcx
.impl_or_trait_item(item_def_id
.def_id());
1394 let is_nonstatic_method
;
1395 match trait_item_type
{
1396 ty
::ConstTraitItem(associated_const
) => {
1397 encode_name(rbml_w
, associated_const
.name
);
1398 encode_def_id(rbml_w
, associated_const
.def_id
);
1399 encode_visibility(rbml_w
, associated_const
.vis
);
1401 encode_provided_source(rbml_w
, associated_const
.default);
1403 let elem
= ast_map
::PathName(associated_const
.name
);
1405 path
.clone().chain(Some(elem
)));
1407 encode_item_sort(rbml_w
, 'C'
);
1408 encode_family(rbml_w
, 'C'
);
1410 encode_bounds_and_type_for_item(rbml_w
, ecx
,
1411 associated_const
.def_id
.local_id());
1413 is_nonstatic_method
= false;
1415 ty
::MethodTraitItem(method_ty
) => {
1416 let method_def_id
= item_def_id
.def_id();
1418 encode_method_ty_fields(ecx
, rbml_w
, &*method_ty
);
1420 let elem
= ast_map
::PathName(method_ty
.name
);
1422 path
.clone().chain(Some(elem
)));
1424 match method_ty
.explicit_self
{
1425 ty
::StaticExplicitSelfCategory
=> {
1426 encode_family(rbml_w
,
1427 STATIC_METHOD_FAMILY
);
1430 encode_family(rbml_w
,
1434 encode_bounds_and_type_for_item(rbml_w
, ecx
, method_def_id
.local_id());
1436 is_nonstatic_method
= method_ty
.explicit_self
!=
1437 ty
::StaticExplicitSelfCategory
;
1439 ty
::TypeTraitItem(associated_type
) => {
1440 encode_name(rbml_w
, associated_type
.name
);
1441 encode_def_id(rbml_w
, associated_type
.def_id
);
1443 let elem
= ast_map
::PathName(associated_type
.name
);
1445 path
.clone().chain(Some(elem
)));
1447 encode_item_sort(rbml_w
, 't'
);
1448 encode_family(rbml_w
, 'y'
);
1450 if let Some(ty
) = associated_type
.ty
{
1451 encode_type(ecx
, rbml_w
, ty
);
1454 is_nonstatic_method
= false;
1458 encode_parent_sort(rbml_w
, 't'
);
1460 let trait_item
= &*ms
[i
];
1461 encode_attributes(rbml_w
, &trait_item
.attrs
);
1462 match trait_item
.node
{
1463 ast
::ConstTraitItem(_
, _
) => {
1464 encode_inlined_item(ecx
, rbml_w
,
1465 IITraitItemRef(def_id
, trait_item
));
1467 ast
::MethodTraitItem(ref sig
, ref body
) => {
1468 // If this is a static method, we've already
1470 if is_nonstatic_method
{
1471 // FIXME: I feel like there is something funny
1473 encode_bounds_and_type_for_item(rbml_w
, ecx
,
1474 item_def_id
.def_id().local_id());
1478 encode_item_sort(rbml_w
, 'p'
);
1479 encode_inlined_item(ecx
, rbml_w
, IITraitItemRef(def_id
, trait_item
));
1481 encode_item_sort(rbml_w
, 'r'
);
1483 encode_method_argument_names(rbml_w
, &sig
.decl
);
1486 ast
::TypeTraitItem(..) => {}
1492 ast
::ItemExternCrate(_
) | ast
::ItemUse(_
) |ast
::ItemMac(..) => {
1493 // these are encoded separately
1498 fn encode_info_for_foreign_item(ecx
: &EncodeContext
,
1499 rbml_w
: &mut Encoder
,
1500 nitem
: &ast
::ForeignItem
,
1501 index
: &mut Vec
<entry
<i64>>,
1505 val
: nitem
.id
as i64,
1506 pos
: rbml_w
.mark_stable_position(),
1509 rbml_w
.start_tag(tag_items_data_item
);
1510 encode_def_id(rbml_w
, local_def(nitem
.id
));
1511 encode_visibility(rbml_w
, nitem
.vis
);
1513 ast
::ForeignItemFn(ref fndecl
, _
) => {
1514 encode_family(rbml_w
, FN_FAMILY
);
1515 encode_bounds_and_type_for_item(rbml_w
, ecx
, nitem
.id
);
1516 encode_name(rbml_w
, nitem
.ident
.name
);
1517 if abi
== abi
::RustIntrinsic
{
1518 encode_inlined_item(ecx
, rbml_w
, IIForeignRef(nitem
));
1520 encode_attributes(rbml_w
, &*nitem
.attrs
);
1521 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(nitem
.id
));
1522 encode_stability(rbml_w
, stab
);
1523 encode_symbol(ecx
, rbml_w
, nitem
.id
);
1524 encode_method_argument_names(rbml_w
, &*fndecl
);
1526 ast
::ForeignItemStatic(_
, mutbl
) => {
1528 encode_family(rbml_w
, 'b'
);
1530 encode_family(rbml_w
, 'c'
);
1532 encode_bounds_and_type_for_item(rbml_w
, ecx
, nitem
.id
);
1533 encode_attributes(rbml_w
, &*nitem
.attrs
);
1534 let stab
= stability
::lookup(ecx
.tcx
, ast_util
::local_def(nitem
.id
));
1535 encode_stability(rbml_w
, stab
);
1536 encode_symbol(ecx
, rbml_w
, nitem
.id
);
1537 encode_name(rbml_w
, nitem
.ident
.name
);
1540 encode_path(rbml_w
, path
);
1544 fn my_visit_expr(_e
: &ast
::Expr
) { }
1546 fn my_visit_item(i
: &ast
::Item
,
1547 rbml_w
: &mut Encoder
,
1548 ecx
: &EncodeContext
,
1549 index
: &mut Vec
<entry
<i64>>) {
1550 ecx
.tcx
.map
.with_path(i
.id
, |path
| {
1551 encode_info_for_item(ecx
, rbml_w
, i
, index
, path
, i
.vis
);
1555 fn my_visit_foreign_item(ni
: &ast
::ForeignItem
,
1556 rbml_w
: &mut Encoder
,
1557 ecx
: &EncodeContext
,
1558 index
: &mut Vec
<entry
<i64>>) {
1559 debug
!("writing foreign item {}::{}",
1560 ecx
.tcx
.map
.path_to_string(ni
.id
),
1563 let abi
= ecx
.tcx
.map
.get_foreign_abi(ni
.id
);
1564 ecx
.tcx
.map
.with_path(ni
.id
, |path
| {
1565 encode_info_for_foreign_item(ecx
, rbml_w
,
1571 struct EncodeVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'c
> {
1572 rbml_w_for_visit_item
: &'a
mut Encoder
<'b
>,
1573 ecx
: &'a EncodeContext
<'c
,'tcx
>,
1574 index
: &'a
mut Vec
<entry
<i64>>,
1577 impl<'a
, 'b
, 'c
, 'tcx
, 'v
> Visitor
<'v
> for EncodeVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1578 fn visit_expr(&mut self, ex
: &ast
::Expr
) {
1579 visit
::walk_expr(self, ex
);
1582 fn visit_item(&mut self, i
: &ast
::Item
) {
1583 visit
::walk_item(self, i
);
1585 self.rbml_w_for_visit_item
,
1589 fn visit_foreign_item(&mut self, ni
: &ast
::ForeignItem
) {
1590 visit
::walk_foreign_item(self, ni
);
1591 my_visit_foreign_item(ni
,
1592 self.rbml_w_for_visit_item
,
1598 fn encode_info_for_items(ecx
: &EncodeContext
,
1599 rbml_w
: &mut Encoder
,
1601 -> Vec
<entry
<i64>> {
1602 let mut index
= Vec
::new();
1603 rbml_w
.start_tag(tag_items_data
);
1605 val
: ast
::CRATE_NODE_ID
as i64,
1606 pos
: rbml_w
.mark_stable_position(),
1608 encode_info_for_mod(ecx
,
1613 [].iter().cloned().chain(LinkedPath
::empty()),
1614 syntax
::parse
::token
::special_idents
::invalid
.name
,
1617 visit
::walk_crate(&mut EncodeVisitor
{
1620 rbml_w_for_visit_item
: &mut *rbml_w
,
1628 // Path and definition ID indexing
1630 fn encode_index
<T
, F
>(rbml_w
: &mut Encoder
, index
: Vec
<entry
<T
>>, mut write_fn
: F
) where
1631 F
: FnMut(&mut Cursor
<Vec
<u8>>, &T
),
1634 let mut buckets
: Vec
<Vec
<entry
<T
>>> = (0..256u16).map(|_
| Vec
::new()).collect();
1636 let mut s
= SipHasher
::new();
1637 elt
.val
.hash(&mut s
);
1638 let h
= s
.finish() as usize;
1639 (&mut buckets
[h
% 256]).push(elt
);
1642 rbml_w
.start_tag(tag_index
);
1643 let mut bucket_locs
= Vec
::new();
1644 rbml_w
.start_tag(tag_index_buckets
);
1645 for bucket
in &buckets
{
1646 bucket_locs
.push(rbml_w
.mark_stable_position());
1647 rbml_w
.start_tag(tag_index_buckets_bucket
);
1649 rbml_w
.start_tag(tag_index_buckets_bucket_elt
);
1650 assert
!(elt
.pos
< 0xffff_ffff);
1652 let wr
: &mut Cursor
<Vec
<u8>> = rbml_w
.writer
;
1653 write_be_u32(wr
, elt
.pos
as u32);
1655 write_fn(rbml_w
.writer
, &elt
.val
);
1661 rbml_w
.start_tag(tag_index_table
);
1662 for pos
in &bucket_locs
{
1663 assert
!(*pos
< 0xffff_ffff);
1664 let wr
: &mut Cursor
<Vec
<u8>> = rbml_w
.writer
;
1665 write_be_u32(wr
, *pos
as u32);
1671 fn write_i64(writer
: &mut Cursor
<Vec
<u8>>, &n
: &i64) {
1672 let wr
: &mut Cursor
<Vec
<u8>> = writer
;
1673 assert
!(n
< 0x7fff_ffff);
1674 write_be_u32(wr
, n
as u32);
1677 fn write_be_u32(w
: &mut Write
, u
: u32) {
1686 fn encode_meta_item(rbml_w
: &mut Encoder
, mi
: &ast
::MetaItem
) {
1688 ast
::MetaWord(ref name
) => {
1689 rbml_w
.start_tag(tag_meta_item_word
);
1690 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1693 ast
::MetaNameValue(ref name
, ref value
) => {
1695 ast
::LitStr(ref value
, _
) => {
1696 rbml_w
.start_tag(tag_meta_item_name_value
);
1697 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1698 rbml_w
.wr_tagged_str(tag_meta_item_value
, value
);
1701 _
=> {/* FIXME (#623): encode other variants */ }
1704 ast
::MetaList(ref name
, ref items
) => {
1705 rbml_w
.start_tag(tag_meta_item_list
);
1706 rbml_w
.wr_tagged_str(tag_meta_item_name
, name
);
1707 for inner_item
in items
{
1708 encode_meta_item(rbml_w
, &**inner_item
);
1715 fn encode_attributes(rbml_w
: &mut Encoder
, attrs
: &[ast
::Attribute
]) {
1716 rbml_w
.start_tag(tag_attributes
);
1718 rbml_w
.start_tag(tag_attribute
);
1719 rbml_w
.wr_tagged_u8(tag_attribute_is_sugared_doc
, attr
.node
.is_sugared_doc
as u8);
1720 encode_meta_item(rbml_w
, &*attr
.node
.value
);
1726 fn encode_unsafety(rbml_w
: &mut Encoder
, unsafety
: ast
::Unsafety
) {
1727 let byte
: u8 = match unsafety
{
1728 ast
::Unsafety
::Normal
=> 0,
1729 ast
::Unsafety
::Unsafe
=> 1,
1731 rbml_w
.wr_tagged_u8(tag_unsafety
, byte
);
1734 fn encode_paren_sugar(rbml_w
: &mut Encoder
, paren_sugar
: bool
) {
1735 let byte
: u8 = if paren_sugar {1}
else {0}
;
1736 rbml_w
.wr_tagged_u8(tag_paren_sugar
, byte
);
1739 fn encode_defaulted(rbml_w
: &mut Encoder
, is_defaulted
: bool
) {
1740 let byte
: u8 = if is_defaulted {1}
else {0}
;
1741 rbml_w
.wr_tagged_u8(tag_defaulted_trait
, byte
);
1744 fn encode_associated_type_names(rbml_w
: &mut Encoder
, names
: &[ast
::Name
]) {
1745 rbml_w
.start_tag(tag_associated_type_names
);
1746 for &name
in names
{
1747 rbml_w
.wr_tagged_str(tag_associated_type_name
, &name
.as_str());
1752 fn encode_polarity(rbml_w
: &mut Encoder
, polarity
: ast
::ImplPolarity
) {
1753 let byte
: u8 = match polarity
{
1754 ast
::ImplPolarity
::Positive
=> 0,
1755 ast
::ImplPolarity
::Negative
=> 1,
1757 rbml_w
.wr_tagged_u8(tag_polarity
, byte
);
1760 fn encode_crate_deps(rbml_w
: &mut Encoder
, cstore
: &cstore
::CStore
) {
1761 fn get_ordered_deps(cstore
: &cstore
::CStore
) -> Vec
<decoder
::CrateDep
> {
1762 // Pull the cnums and name,vers,hash out of cstore
1763 let mut deps
= Vec
::new();
1764 cstore
.iter_crate_data(|key
, val
| {
1765 let dep
= decoder
::CrateDep
{
1767 name
: decoder
::get_crate_name(val
.data()),
1768 hash
: decoder
::get_crate_hash(val
.data()),
1774 deps
.sort_by(|kv1
, kv2
| kv1
.cnum
.cmp(&kv2
.cnum
));
1776 // Sanity-check the crate numbers
1777 let mut expected_cnum
= 1;
1779 assert_eq
!(n
.cnum
, expected_cnum
);
1786 // We're just going to write a list of crate 'name-hash-version's, with
1787 // the assumption that they are numbered 1 to n.
1788 // FIXME (#2166): This is not nearly enough to support correct versioning
1789 // but is enough to get transitive crate dependencies working.
1790 rbml_w
.start_tag(tag_crate_deps
);
1791 let r
= get_ordered_deps(cstore
);
1793 encode_crate_dep(rbml_w
, (*dep
).clone());
1798 fn encode_lang_items(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1799 rbml_w
.start_tag(tag_lang_items
);
1801 for (i
, &def_id
) in ecx
.tcx
.lang_items
.items() {
1802 if let Some(id
) = def_id
{
1803 if id
.krate
== ast
::LOCAL_CRATE
{
1804 rbml_w
.start_tag(tag_lang_items_item
);
1805 rbml_w
.wr_tagged_u32(tag_lang_items_item_id
, i
as u32);
1806 rbml_w
.wr_tagged_u32(tag_lang_items_item_node_id
, id
.node
as u32);
1812 for i
in &ecx
.tcx
.lang_items
.missing
{
1813 rbml_w
.wr_tagged_u32(tag_lang_items_missing
, *i
as u32);
1816 rbml_w
.end_tag(); // tag_lang_items
1819 fn encode_native_libraries(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1820 rbml_w
.start_tag(tag_native_libraries
);
1822 for &(ref lib
, kind
) in ecx
.tcx
.sess
.cstore
.get_used_libraries()
1825 cstore
::NativeStatic
=> {}
// these libraries are not propagated
1826 cstore
::NativeFramework
| cstore
::NativeUnknown
=> {
1827 rbml_w
.start_tag(tag_native_libraries_lib
);
1828 rbml_w
.wr_tagged_u32(tag_native_libraries_kind
, kind
as u32);
1829 rbml_w
.wr_tagged_str(tag_native_libraries_name
, lib
);
1838 fn encode_plugin_registrar_fn(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1839 match ecx
.tcx
.sess
.plugin_registrar_fn
.get() {
1840 Some(id
) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1845 fn encode_codemap(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1846 rbml_w
.start_tag(tag_codemap
);
1847 let codemap
= ecx
.tcx
.sess
.codemap();
1849 for filemap
in &codemap
.files
.borrow()[..] {
1851 if filemap
.lines
.borrow().is_empty() || filemap
.is_imported() {
1852 // No need to export empty filemaps, as they can't contain spans
1853 // that need translation.
1854 // Also no need to re-export imported filemaps, as any downstream
1855 // crate will import them from their original source.
1859 rbml_w
.start_tag(tag_codemap_filemap
);
1860 filemap
.encode(rbml_w
);
1867 /// Serialize the text of the exported macros
1868 fn encode_macro_defs(rbml_w
: &mut Encoder
,
1869 krate
: &ast
::Crate
) {
1870 rbml_w
.start_tag(tag_macro_defs
);
1871 for def
in &krate
.exported_macros
{
1872 rbml_w
.start_tag(tag_macro_def
);
1874 encode_name(rbml_w
, def
.ident
.name
);
1875 encode_attributes(rbml_w
, &def
.attrs
);
1877 rbml_w
.wr_tagged_str(tag_macro_def_body
,
1878 &pprust
::tts_to_string(&def
.body
));
1885 fn encode_struct_field_attrs(rbml_w
: &mut Encoder
, krate
: &ast
::Crate
) {
1886 struct StructFieldVisitor
<'a
, 'b
:'a
> {
1887 rbml_w
: &'a
mut Encoder
<'b
>,
1890 impl<'a
, 'b
, 'v
> Visitor
<'v
> for StructFieldVisitor
<'a
, 'b
> {
1891 fn visit_struct_field(&mut self, field
: &ast
::StructField
) {
1892 self.rbml_w
.start_tag(tag_struct_field
);
1893 self.rbml_w
.wr_tagged_u32(tag_struct_field_id
, field
.node
.id
);
1894 encode_attributes(self.rbml_w
, &field
.node
.attrs
);
1895 self.rbml_w
.end_tag();
1899 rbml_w
.start_tag(tag_struct_fields
);
1900 visit
::walk_crate(&mut StructFieldVisitor
{
1908 struct ImplVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'b
> {
1909 ecx
: &'a EncodeContext
<'b
, 'tcx
>,
1910 rbml_w
: &'a
mut Encoder
<'c
>,
1913 impl<'a
, 'b
, 'c
, 'tcx
, 'v
> Visitor
<'v
> for ImplVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1914 fn visit_item(&mut self, item
: &ast
::Item
) {
1915 if let ast
::ItemImpl(_
, _
, _
, Some(ref trait_ref
), _
, _
) = item
.node
{
1916 let def_id
= self.ecx
.tcx
.def_map
.borrow().get(&trait_ref
.ref_id
).unwrap().def_id();
1918 // Load eagerly if this is an implementation of the Drop trait
1919 // or if the trait is not defined in this crate.
1920 if Some(def_id
) == self.ecx
.tcx
.lang_items
.drop_trait() ||
1921 def_id
.krate
!= ast
::LOCAL_CRATE
{
1922 self.rbml_w
.start_tag(tag_impls_impl
);
1923 encode_def_id(self.rbml_w
, local_def(item
.id
));
1924 self.rbml_w
.wr_tagged_u64(tag_impls_impl_trait_def_id
, def_to_u64(def_id
));
1925 self.rbml_w
.end_tag();
1928 visit
::walk_item(self, item
);
1932 /// Encodes implementations that are eagerly loaded.
1934 /// None of this is necessary in theory; we can load all implementations
1935 /// lazily. However, in two cases the optimizations to lazily load
1936 /// implementations are not yet implemented. These two cases, which require us
1937 /// to load implementations eagerly, are:
1939 /// * Destructors (implementations of the Drop trait).
1941 /// * Implementations of traits not defined in this crate.
1942 fn encode_impls
<'a
>(ecx
: &'a EncodeContext
,
1944 rbml_w
: &'a
mut Encoder
) {
1945 rbml_w
.start_tag(tag_impls
);
1948 let mut visitor
= ImplVisitor
{
1952 visit
::walk_crate(&mut visitor
, krate
);
1958 fn encode_misc_info(ecx
: &EncodeContext
,
1960 rbml_w
: &mut Encoder
) {
1961 rbml_w
.start_tag(tag_misc_info
);
1962 rbml_w
.start_tag(tag_misc_info_crate_items
);
1963 for item
in &krate
.module
.items
{
1964 rbml_w
.wr_tagged_u64(tag_mod_child
,
1965 def_to_u64(local_def(item
.id
)));
1967 each_auxiliary_node_id(&**item
, |auxiliary_node_id
| {
1968 rbml_w
.wr_tagged_u64(tag_mod_child
,
1969 def_to_u64(local_def(auxiliary_node_id
)));
1974 // Encode reexports for the root module.
1975 encode_reexports(ecx
, rbml_w
, 0, [].iter().cloned().chain(LinkedPath
::empty()));
1981 fn encode_reachable_extern_fns(ecx
: &EncodeContext
, rbml_w
: &mut Encoder
) {
1982 rbml_w
.start_tag(tag_reachable_extern_fns
);
1984 for id
in ecx
.reachable
{
1985 if let Some(ast_map
::NodeItem(i
)) = ecx
.tcx
.map
.find(*id
) {
1986 if let ast
::ItemFn(_
, _
, _
, abi
, ref generics
, _
) = i
.node
{
1987 if abi
!= abi
::Rust
&& !generics
.is_type_parameterized() {
1988 rbml_w
.wr_tagged_u32(tag_reachable_extern_fn_id
, *id
);
1997 fn encode_crate_dep(rbml_w
: &mut Encoder
,
1998 dep
: decoder
::CrateDep
) {
1999 rbml_w
.start_tag(tag_crate_dep
);
2000 rbml_w
.wr_tagged_str(tag_crate_dep_crate_name
, &dep
.name
);
2001 rbml_w
.wr_tagged_str(tag_crate_dep_hash
, dep
.hash
.as_str());
2005 fn encode_hash(rbml_w
: &mut Encoder
, hash
: &Svh
) {
2006 rbml_w
.wr_tagged_str(tag_crate_hash
, hash
.as_str());
2009 fn encode_crate_name(rbml_w
: &mut Encoder
, crate_name
: &str) {
2010 rbml_w
.wr_tagged_str(tag_crate_crate_name
, crate_name
);
2013 fn encode_crate_triple(rbml_w
: &mut Encoder
, triple
: &str) {
2014 rbml_w
.wr_tagged_str(tag_crate_triple
, triple
);
2017 fn encode_dylib_dependency_formats(rbml_w
: &mut Encoder
, ecx
: &EncodeContext
) {
2018 let tag
= tag_dylib_dependency_formats
;
2019 match ecx
.tcx
.dependency_formats
.borrow().get(&config
::CrateTypeDylib
) {
2021 let s
= arr
.iter().enumerate().filter_map(|(i
, slot
)| {
2022 slot
.map(|kind
| (format
!("{}:{}", i
+ 1, match kind
{
2023 cstore
::RequireDynamic
=> "d",
2024 cstore
::RequireStatic
=> "s",
2026 }).collect
::<Vec
<String
>>();
2027 rbml_w
.wr_tagged_str(tag
, &s
.join(","));
2030 rbml_w
.wr_tagged_str(tag
, "");
2035 // NB: Increment this as you change the metadata encoding version.
2036 #[allow(non_upper_case_globals)]
2037 pub const metadata_encoding_version
: &'
static [u8] = &[b'r'
, b'u'
, b's'
, b't'
, 0, 0, 0, 2 ];
2039 pub fn encode_metadata(parms
: EncodeParams
, krate
: &ast
::Crate
) -> Vec
<u8> {
2040 let mut wr
= Cursor
::new(Vec
::new());
2041 encode_metadata_inner(&mut wr
, parms
, krate
);
2043 // RBML compacts the encoded bytes whenever appropriate,
2044 // so there are some garbages left after the end of the data.
2045 let metalen
= wr
.seek(SeekFrom
::Current(0)).unwrap() as usize;
2046 let mut v
= wr
.into_inner();
2047 v
.truncate(metalen
);
2048 assert_eq
!(v
.len(), metalen
);
2050 // And here we run into yet another obscure archive bug: in which metadata
2051 // loaded from archives may have trailing garbage bytes. Awhile back one of
2052 // our tests was failing sporadically on the OSX 64-bit builders (both nopt
2053 // and opt) by having rbml generate an out-of-bounds panic when looking at
2056 // Upon investigation it turned out that the metadata file inside of an rlib
2057 // (and ar archive) was being corrupted. Some compilations would generate a
2058 // metadata file which would end in a few extra bytes, while other
2059 // compilations would not have these extra bytes appended to the end. These
2060 // extra bytes were interpreted by rbml as an extra tag, so they ended up
2061 // being interpreted causing the out-of-bounds.
2063 // The root cause of why these extra bytes were appearing was never
2064 // discovered, and in the meantime the solution we're employing is to insert
2065 // the length of the metadata to the start of the metadata. Later on this
2066 // will allow us to slice the metadata to the precise length that we just
2067 // generated regardless of trailing bytes that end up in it.
2068 let len
= v
.len() as u32;
2069 v
.insert(0, (len
>> 0) as u8);
2070 v
.insert(0, (len
>> 8) as u8);
2071 v
.insert(0, (len
>> 16) as u8);
2072 v
.insert(0, (len
>> 24) as u8);
2076 fn encode_metadata_inner(wr
: &mut Cursor
<Vec
<u8>>,
2077 parms
: EncodeParams
,
2078 krate
: &ast
::Crate
) {
2082 lang_item_bytes
: u64,
2083 native_lib_bytes
: u64,
2084 plugin_registrar_fn_bytes
: u64,
2086 macro_defs_bytes
: u64,
2094 let mut stats
= Stats
{
2098 native_lib_bytes
: 0,
2099 plugin_registrar_fn_bytes
: 0,
2101 macro_defs_bytes
: 0,
2115 encode_inlined_item
,
2120 let ecx
= EncodeContext
{
2123 reexports
: reexports
,
2124 item_symbols
: item_symbols
,
2125 link_meta
: link_meta
,
2127 encode_inlined_item
: RefCell
::new(encode_inlined_item
),
2128 type_abbrevs
: RefCell
::new(FnvHashMap()),
2129 reachable
: reachable
,
2132 let mut rbml_w
= Encoder
::new(wr
);
2134 encode_crate_name(&mut rbml_w
, &ecx
.link_meta
.crate_name
);
2135 encode_crate_triple(&mut rbml_w
, &tcx
.sess
.opts
.target_triple
);
2136 encode_hash(&mut rbml_w
, &ecx
.link_meta
.crate_hash
);
2137 encode_dylib_dependency_formats(&mut rbml_w
, &ecx
);
2139 let mut i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2140 encode_attributes(&mut rbml_w
, &krate
.attrs
);
2141 stats
.attr_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2143 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2144 encode_crate_deps(&mut rbml_w
, ecx
.cstore
);
2145 stats
.dep_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2147 // Encode the language items.
2148 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2149 encode_lang_items(&ecx
, &mut rbml_w
);
2150 stats
.lang_item_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2152 // Encode the native libraries used
2153 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2154 encode_native_libraries(&ecx
, &mut rbml_w
);
2155 stats
.native_lib_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2157 // Encode the plugin registrar function
2158 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2159 encode_plugin_registrar_fn(&ecx
, &mut rbml_w
);
2160 stats
.plugin_registrar_fn_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2163 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2164 encode_codemap(&ecx
, &mut rbml_w
);
2165 stats
.codemap_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2167 // Encode macro definitions
2168 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2169 encode_macro_defs(&mut rbml_w
, krate
);
2170 stats
.macro_defs_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2172 // Encode the def IDs of impls, for coherence checking.
2173 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2174 encode_impls(&ecx
, krate
, &mut rbml_w
);
2175 stats
.impl_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2177 // Encode miscellaneous info.
2178 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2179 encode_misc_info(&ecx
, krate
, &mut rbml_w
);
2180 encode_reachable_extern_fns(&ecx
, &mut rbml_w
);
2181 stats
.misc_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2183 // Encode and index the items.
2184 rbml_w
.start_tag(tag_items
);
2185 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2186 let items_index
= encode_info_for_items(&ecx
, &mut rbml_w
, krate
);
2187 stats
.item_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2189 i
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2190 encode_index(&mut rbml_w
, items_index
, write_i64
);
2191 stats
.index_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap() - i
;
2194 encode_struct_field_attrs(&mut rbml_w
, krate
);
2196 stats
.total_bytes
= rbml_w
.writer
.seek(SeekFrom
::Current(0)).unwrap();
2198 if tcx
.sess
.meta_stats() {
2199 for e
in rbml_w
.writer
.get_ref() {
2201 stats
.zero_bytes
+= 1;
2205 println
!("metadata stats:");
2206 println
!(" attribute bytes: {}", stats
.attr_bytes
);
2207 println
!(" dep bytes: {}", stats
.dep_bytes
);
2208 println
!(" lang item bytes: {}", stats
.lang_item_bytes
);
2209 println
!(" native bytes: {}", stats
.native_lib_bytes
);
2210 println
!("plugin registrar bytes: {}", stats
.plugin_registrar_fn_bytes
);
2211 println
!(" codemap bytes: {}", stats
.codemap_bytes
);
2212 println
!(" macro def bytes: {}", stats
.macro_defs_bytes
);
2213 println
!(" impl bytes: {}", stats
.impl_bytes
);
2214 println
!(" misc bytes: {}", stats
.misc_bytes
);
2215 println
!(" item bytes: {}", stats
.item_bytes
);
2216 println
!(" index bytes: {}", stats
.index_bytes
);
2217 println
!(" zero bytes: {}", stats
.zero_bytes
);
2218 println
!(" total bytes: {}", stats
.total_bytes
);
2222 // Get the encoded string for a type
2223 pub fn encoded_ty
<'tcx
>(tcx
: &ty
::ctxt
<'tcx
>, t
: Ty
<'tcx
>) -> String
{
2224 let mut wr
= Cursor
::new(Vec
::new());
2225 tyencode
::enc_ty(&mut Encoder
::new(&mut wr
), &tyencode
::ctxt
{
2226 diag
: tcx
.sess
.diagnostic(),
2229 abbrevs
: &RefCell
::new(FnvHashMap())
2231 String
::from_utf8(wr
.into_inner()).unwrap()