]> git.proxmox.com Git - rustc.git/blob - src/librustc/metadata/encoder.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / librustc / metadata / encoder.rs
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.
4 //
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.
10
11 // Metadata encoding
12
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
15
16 pub use self::InlinedItemRef::*;
17
18 use ast_map::{self, LinkedPath, PathElem, PathElems};
19 use back::svh::Svh;
20 use session::config;
21 use metadata::common::*;
22 use metadata::cstore;
23 use metadata::decoder;
24 use metadata::tyencode;
25 use middle::def;
26 use middle::ty::lookup_item_type;
27 use middle::ty::{self, Ty};
28 use middle::stability;
29 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
30
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};
36 use syntax::abi;
37 use syntax::ast::{self, DefId, NodeId};
38 use syntax::ast_util::*;
39 use syntax::ast_util;
40 use syntax::attr;
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;
46 use syntax::ptr::P;
47 use syntax::visit::Visitor;
48 use syntax::visit;
49 use syntax;
50 use rbml::writer::Encoder;
51
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)
58 }
59
60 pub type EncodeInlinedItem<'a> =
61 Box<FnMut(&EncodeContext, &mut Encoder, InlinedItemRef) + 'a>;
62
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,
72 }
73
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,
84 }
85
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));
88 }
89
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));
92 }
93
94 fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
95 rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
96 }
97
98 #[derive(Clone)]
99 struct entry<T> {
100 val: T,
101 pos: u64
102 }
103
104 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
105 ecx: &EncodeContext<'a, 'tcx>,
106 trait_ref: ty::TraitRef<'tcx>,
107 tag: usize) {
108 let ty_str_ctxt = &tyencode::ctxt {
109 diag: ecx.diag,
110 ds: def_to_string,
111 tcx: ecx.tcx,
112 abbrevs: &ecx.type_abbrevs
113 };
114
115 rbml_w.start_tag(tag);
116 tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref);
117 rbml_w.end_tag();
118 }
119
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);
123 }
124
125 pub fn def_to_u64(did: DefId) -> u64 {
126 (did.krate as u64) << 32 | (did.node as u64)
127 }
128
129 pub fn def_to_string(did: DefId) -> String {
130 format!("{}:{}", did.krate, did.node)
131 }
132
133 fn encode_item_variances(rbml_w: &mut Encoder,
134 ecx: &EncodeContext,
135 id: NodeId) {
136 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
137 rbml_w.start_tag(tag_item_variances);
138 v.encode(rbml_w);
139 rbml_w.end_tag();
140 }
141
142 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
143 ecx: &EncodeContext<'a, 'tcx>,
144 id: ast::NodeId) {
145 encode_bounds_and_type(rbml_w,
146 ecx,
147 &ty::lookup_item_type(ecx.tcx, local_def(id)),
148 &ty::lookup_predicates(ecx.tcx, local_def(id)));
149 }
150
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);
157 }
158
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);
163 }
164
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 {
169 diag: ecx.diag,
170 ds: def_to_string,
171 tcx: ecx.tcx,
172 abbrevs: &ecx.type_abbrevs
173 };
174 tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type);
175 }
176
177 pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
178 rbml_w: &mut Encoder,
179 typ: Ty<'tcx>) {
180 let ty_str_ctxt = &tyencode::ctxt {
181 diag: ecx.diag,
182 ds: def_to_string,
183 tcx: ecx.tcx,
184 abbrevs: &ecx.type_abbrevs
185 };
186 tyencode::enc_ty(rbml_w, ty_str_ctxt, typ);
187 }
188
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 {
193 diag: ecx.diag,
194 ds: def_to_string,
195 tcx: ecx.tcx,
196 abbrevs: &ecx.type_abbrevs
197 };
198 tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref);
199 }
200
201 pub fn write_region(ecx: &EncodeContext,
202 rbml_w: &mut Encoder,
203 r: ty::Region) {
204 let ty_str_ctxt = &tyencode::ctxt {
205 diag: ecx.diag,
206 ds: def_to_string,
207 tcx: ecx.tcx,
208 abbrevs: &ecx.type_abbrevs
209 };
210 tyencode::enc_region(rbml_w, ty_str_ctxt, r);
211 }
212
213 fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
214 rbml_w: &mut Encoder,
215 typ: Ty<'tcx>) {
216 rbml_w.start_tag(tag_items_data_item_type);
217 write_type(ecx, rbml_w, typ);
218 rbml_w.end_tag();
219 }
220
221 fn encode_region(ecx: &EncodeContext,
222 rbml_w: &mut Encoder,
223 r: ty::Region) {
224 rbml_w.start_tag(tag_items_data_region);
225 write_region(ecx, rbml_w, r);
226 rbml_w.end_tag();
227 }
228
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);
233
234 let ty_str_ctxt = &tyencode::ctxt {
235 diag: ecx.diag,
236 ds: def_to_string,
237 tcx: ecx.tcx,
238 abbrevs: &ecx.type_abbrevs
239 };
240 tyencode::enc_bare_fn_ty(rbml_w, ty_str_ctxt, typ);
241
242 rbml_w.end_tag();
243 }
244
245 fn encode_symbol(ecx: &EncodeContext,
246 rbml_w: &mut Encoder,
247 id: NodeId) {
248 match ecx.item_symbols.borrow().get(&id) {
249 Some(x) => {
250 debug!("encode_symbol(id={}, str={})", id, *x);
251 rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
252 }
253 None => {
254 ecx.diag.handler().bug(
255 &format!("encode_symbol: id not found {}", id));
256 }
257 }
258 }
259
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());
264 }
265
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));
268 }
269
270 fn encode_struct_fields(rbml_w: &mut Encoder,
271 fields: &[ty::field_ty],
272 origin: DefId) {
273 for f in fields {
274 if f.name == special_idents::unnamed_field.name {
275 rbml_w.start_tag(tag_item_unnamed_field);
276 } else {
277 rbml_w.start_tag(tag_item_field);
278 encode_name(rbml_w, f.name);
279 }
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));
283 rbml_w.end_tag();
284 }
285 }
286
287 fn encode_enum_variant_info(ecx: &EncodeContext,
288 rbml_w: &mut Encoder,
289 id: NodeId,
290 variants: &[P<ast::Variant>],
291 index: &mut Vec<entry<i64>>) {
292 debug!("encode_enum_variant_info(id={})", id);
293
294 let mut disr_val = 0;
295 let mut i = 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);
300 index.push(entry {
301 val: variant.node.id as i64,
302 pos: rbml_w.mark_stable_position(),
303 });
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')
309 }
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);
315
316 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
317 encode_stability(rbml_w, stab);
318
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,
324 rbml_w,
325 &fields[..],
326 index);
327 encode_struct_fields(rbml_w, &fields[..], def_id);
328 encode_index(rbml_w, idx, write_i64);
329 }
330 }
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;
334 }
335 encode_bounds_and_type_for_item(rbml_w, ecx, def_id.local_id());
336
337 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
338 rbml_w.end_tag();
339 disr_val = disr_val.wrapping_add(1);
340 i += 1;
341 }
342 }
343
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);
348 for pe in &path {
349 let tag = match *pe {
350 ast_map::PathMod(_) => tag_path_elem_mod,
351 ast_map::PathName(_) => tag_path_elem_name
352 };
353 rbml_w.wr_tagged_str(tag, &token::get_name(pe.name()));
354 }
355 rbml_w.end_tag();
356 }
357
358 fn encode_reexported_static_method(rbml_w: &mut Encoder,
359 exp: &def::Export,
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)));
370 rbml_w.end_tag();
371 }
372
373 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
374 rbml_w: &mut Encoder,
375 exp: &def::Export)
376 -> bool {
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(
383 ecx.tcx,
384 method_did.def_id());
385 if let ty::MethodTraitItem(ref m) = impl_item {
386 encode_reexported_static_method(rbml_w,
387 exp,
388 m.def_id,
389 m.name);
390 }
391 }
392 }
393
394 true
395 }
396 None => { false }
397 }
398 }
399
400 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
401 rbml_w: &mut Encoder,
402 exp: &def::Export)
403 -> bool {
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,
409 exp,
410 m.def_id,
411 m.name);
412 }
413 }
414 true
415 }
416 None => { false }
417 }
418 }
419
420 fn encode_reexported_static_methods(ecx: &EncodeContext,
421 rbml_w: &mut Encoder,
422 mod_path: PathElems,
423 exp: &def::Export) {
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());
427 loop {
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 },
432 }
433 }
434 });
435
436 //
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.
440 //
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.
445 //
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]",
450 item.ident.name);
451 }
452 }
453 else {
454 debug!("(encode reexported static methods) {} [base]",
455 item.ident.name);
456 }
457 }
458 }
459 }
460
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:
463 ///
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,
467 {
468 let mut continue_ = true;
469 match item.node {
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);
476 }
477 _ => {}
478 }
479 }
480 _ => {}
481 }
482
483 continue_
484 }
485
486 fn encode_reexports(ecx: &EncodeContext,
487 rbml_w: &mut Encoder,
488 id: NodeId,
489 path: PathElems) {
490 debug!("(encoding info for module) encoding reexports for {}", id);
491 match ecx.reexports.get(&id) {
492 Some(exports) => {
493 debug!("(encoding info for module) found reexports for {}", id);
494 for exp in exports {
495 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
496 {}",
497 exp.name,
498 exp.def_id.krate,
499 exp.def_id.node,
500 id);
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,
505 exp.name.as_str());
506 rbml_w.end_tag();
507 encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
508 }
509 }
510 None => {
511 debug!("(encoding info for module) found no reexports for {}",
512 id);
513 }
514 }
515 }
516
517 fn encode_info_for_mod(ecx: &EncodeContext,
518 rbml_w: &mut Encoder,
519 md: &ast::Mod,
520 attrs: &[ast::Attribute],
521 id: NodeId,
522 path: PathElems,
523 name: ast::Name,
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);
530
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)));
535
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)));
539 true
540 });
541
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));
547
548 rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(local_def(did)));
549 }
550 }
551
552 encode_path(rbml_w, path.clone());
553 encode_visibility(rbml_w, vis);
554
555 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
556 encode_stability(rbml_w, stab);
557
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);
562 }
563 encode_attributes(rbml_w, attrs);
564
565 rbml_w.end_tag();
566 }
567
568 fn encode_struct_field_family(rbml_w: &mut Encoder,
569 visibility: ast::Visibility) {
570 encode_family(rbml_w, match visibility {
571 ast::Public => 'g',
572 ast::Inherited => 'N'
573 });
574 }
575
576 fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
577 let ch = match visibility {
578 ast::Public => 'y',
579 ast::Inherited => 'i',
580 };
581 rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
582 }
583
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',
589 };
590 rbml_w.wr_str(&ch.to_string());
591 rbml_w.end_tag();
592 }
593
594 fn encode_explicit_self(rbml_w: &mut Encoder,
595 explicit_self: &ty::ExplicitSelfCategory) {
596 let tag = tag_item_trait_method_explicit_self;
597
598 // Encode the base self type.
599 match *explicit_self {
600 ty::StaticExplicitSelfCategory => {
601 rbml_w.wr_tagged_bytes(tag, &['s' as u8]);
602 }
603 ty::ByValueExplicitSelfCategory => {
604 rbml_w.wr_tagged_bytes(tag, &['v' as u8]);
605 }
606 ty::ByBoxExplicitSelfCategory => {
607 rbml_w.wr_tagged_bytes(tag, &['~' as u8]);
608 }
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]);
613 }
614 }
615
616 fn encode_mutability(m: ast::Mutability) -> u8 {
617 match m {
618 ast::MutImmutable => 'i' as u8,
619 ast::MutMutable => 'm' as u8,
620 }
621 }
622 }
623
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);
626 }
627
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);
630 }
631
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));
636 }
637 }
638
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>>)
644 -> 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 {
651 let nm = field.name;
652 let id = field.id.node;
653
654 let pos = rbml_w.mark_stable_position();
655 index.push(entry {val: id as i64, pos: pos});
656 global_index.push(entry {
657 val: id as i64,
658 pos: pos,
659 });
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));
667
668 let stab = stability::lookup(ecx.tcx, field.id);
669 encode_stability(rbml_w, stab);
670
671 rbml_w.end_tag();
672 }
673 index
674 }
675
676 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
677 rbml_w: &mut Encoder,
678 name: ast::Name,
679 ctor_id: NodeId,
680 index: &mut Vec<entry<i64>>,
681 struct_id: NodeId) {
682 index.push(entry {
683 val: ctor_id as i64,
684 pos: rbml_w.mark_stable_position(),
685 });
686
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));
694
695 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
696 encode_symbol(ecx, rbml_w, ctor_id);
697 }
698
699 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
700 encode_stability(rbml_w, stab);
701
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, &[]);
706
707 rbml_w.end_tag();
708 }
709
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>,
714 tag: usize)
715 {
716 rbml_w.start_tag(tag);
717
718 // Type parameters
719 let ty_str_ctxt = &tyencode::ctxt {
720 diag: ecx.diag,
721 ds: def_to_string,
722 tcx: ecx.tcx,
723 abbrevs: &ecx.type_abbrevs
724 };
725
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);
729 rbml_w.end_tag();
730 }
731
732 // Region parameters
733 for param in &generics.regions {
734 rbml_w.start_tag(tag_region_param_def);
735
736 rbml_w.start_tag(tag_region_param_def_ident);
737 encode_name(rbml_w, param.name);
738 rbml_w.end_tag();
739
740 rbml_w.wr_tagged_u64(tag_region_param_def_def_id,
741 def_to_u64(param.def_id));
742
743 rbml_w.wr_tagged_u64(tag_region_param_def_space,
744 param.space.to_uint() as u64);
745
746 rbml_w.wr_tagged_u64(tag_region_param_def_index,
747 param.index as u64);
748
749 for &bound_region in &param.bounds {
750 encode_region(ecx, rbml_w, bound_region);
751 }
752
753 rbml_w.end_tag();
754 }
755
756 encode_predicates_in_current_doc(rbml_w, ecx, predicates);
757
758 rbml_w.end_tag();
759 }
760
761 fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
762 ecx: &EncodeContext<'a,'tcx>,
763 predicates: &ty::GenericPredicates<'tcx>)
764 {
765 let ty_str_ctxt = &tyencode::ctxt {
766 diag: ecx.diag,
767 ds: def_to_string,
768 tcx: ecx.tcx,
769 abbrevs: &ecx.type_abbrevs
770 };
771
772 for (space, _, predicate) in predicates.predicates.iter_enumerated() {
773 rbml_w.start_tag(tag_predicate);
774
775 rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
776
777 rbml_w.start_tag(tag_predicate_data);
778 tyencode::enc_predicate(rbml_w, ty_str_ctxt, predicate);
779 rbml_w.end_tag();
780
781 rbml_w.end_tag();
782 }
783 }
784
785 fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
786 ecx: &EncodeContext<'a,'tcx>,
787 predicates: &ty::GenericPredicates<'tcx>,
788 tag: usize)
789 {
790 rbml_w.start_tag(tag);
791 encode_predicates_in_current_doc(rbml_w, ecx, predicates);
792 rbml_w.end_tag();
793 }
794
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);
808 }
809 _ => encode_family(rbml_w, METHOD_FAMILY)
810 }
811 encode_provided_source(rbml_w, method_ty.provided_source);
812 }
813
814 fn encode_info_for_associated_const(ecx: &EncodeContext,
815 rbml_w: &mut Encoder,
816 associated_const: &ty::AssociatedConst,
817 impl_path: PathElems,
818 parent_id: NodeId,
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));
823
824 rbml_w.start_tag(tag_items_data_item);
825
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);
831
832 encode_parent_item(rbml_w, local_def(parent_id));
833 encode_item_sort(rbml_w, 'C');
834
835 encode_bounds_and_type_for_item(rbml_w, ecx, associated_const.def_id.local_id());
836
837 let stab = stability::lookup(ecx.tcx, associated_const.def_id);
838 encode_stability(rbml_w, stab);
839
840 let elem = ast_map::PathName(associated_const.name);
841 encode_path(rbml_w, impl_path.chain(Some(elem)));
842
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));
846 }
847
848 rbml_w.end_tag();
849 }
850
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,
856 parent_id: NodeId,
857 impl_item_opt: Option<&ast::ImplItem>) {
858
859 debug!("encode_info_for_method: {:?} {:?}", m.def_id,
860 token::get_name(m.name));
861 rbml_w.start_tag(tag_items_data_item);
862
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');
866
867 let stab = stability::lookup(ecx.tcx, m.def_id);
868 encode_stability(rbml_w, stab);
869
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());
872
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),
884 impl_item));
885 }
886 encode_constness(rbml_w, sig.constness);
887 if !any_types {
888 encode_symbol(ecx, rbml_w, m.def_id.node);
889 }
890 encode_method_argument_names(rbml_w, &sig.decl);
891 }
892 }
893
894 rbml_w.end_tag();
895 }
896
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,
901 parent_id: NodeId,
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));
906
907 rbml_w.start_tag(tag_items_data_item);
908
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');
915
916 let stab = stability::lookup(ecx.tcx, associated_type.def_id);
917 encode_stability(rbml_w, stab);
918
919 let elem = ast_map::PathName(associated_type.name);
920 encode_path(rbml_w, impl_path.chain(Some(elem)));
921
922 if let Some(ii) = impl_item_opt {
923 encode_attributes(rbml_w, &ii.attrs);
924 } else {
925 encode_predicates(rbml_w, ecx,
926 &ty::lookup_predicates(ecx.tcx, associated_type.def_id),
927 tag_item_generics);
928 }
929
930 if let Some(ty) = associated_type.ty {
931 encode_type(ecx, rbml_w, ty);
932 }
933
934 rbml_w.end_tag();
935 }
936
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());
945 } else {
946 rbml_w.wr_tagged_bytes(tag, &[]);
947 }
948 }
949 rbml_w.end_tag();
950 }
951
952 fn encode_repr_attrs(rbml_w: &mut Encoder,
953 ecx: &EncodeContext,
954 attrs: &[ast::Attribute]) {
955 let mut repr_attrs = Vec::new();
956 for attr in attrs {
957 repr_attrs.extend(attr::find_repr_attrs(ecx.tcx.sess.diagnostic(),
958 attr));
959 }
960 rbml_w.start_tag(tag_items_data_item_repr);
961 repr_attrs.encode(rbml_w);
962 rbml_w.end_tag();
963 }
964
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;
970 eii(ecx, rbml_w, ii)
971 }
972
973 const FN_FAMILY: char = 'f';
974 const STATIC_METHOD_FAMILY: char = 'F';
975 const METHOD_FAMILY: char = 'h';
976
977 // Encodes the inherent implementations of a structure, enumeration, or trait.
978 fn encode_inherent_implementations(ecx: &EncodeContext,
979 rbml_w: &mut Encoder,
980 def_id: DefId) {
981 match ecx.tcx.inherent_impls.borrow().get(&def_id) {
982 None => {}
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);
987 rbml_w.end_tag();
988 }
989 }
990 }
991 }
992
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);
999
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);
1003 rbml_w.end_tag();
1004 });
1005 }
1006
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();
1011 rbml_w.end_tag();
1012 });
1013 }
1014
1015 fn encode_info_for_item(ecx: &EncodeContext,
1016 rbml_w: &mut Encoder,
1017 item: &ast::Item,
1018 index: &mut Vec<entry<i64>>,
1019 path: PathElems,
1020 vis: ast::Visibility) {
1021 let tcx = ecx.tcx;
1022
1023 fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
1024 index: &mut Vec<entry<i64>>) {
1025 index.push(entry {
1026 val: item.id as i64,
1027 pos: rbml_w.mark_stable_position(),
1028 });
1029 }
1030
1031 debug!("encoding info for item at {}",
1032 tcx.sess.codemap().span_to_string(item.span));
1033
1034 let def_id = local_def(item.id);
1035 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
1036
1037 match item.node {
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');
1044 } else {
1045 encode_family(rbml_w, 'c');
1046 }
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);
1054 rbml_w.end_tag();
1055 }
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);
1068 rbml_w.end_tag();
1069 }
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));
1083 }
1084 if tps_len == 0 {
1085 encode_symbol(ecx, rbml_w, item.id);
1086 }
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);
1091 rbml_w.end_tag();
1092 }
1093 ast::ItemMod(ref m) => {
1094 add_to_index(item, rbml_w, index);
1095 encode_info_for_mod(ecx,
1096 rbml_w,
1097 m,
1098 &item.attrs,
1099 item.id,
1100 path,
1101 item.ident.name,
1102 item.vis);
1103 }
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);
1111
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)));
1116 }
1117 encode_visibility(rbml_w, vis);
1118 encode_stability(rbml_w, stab);
1119 rbml_w.end_tag();
1120 }
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);
1131 rbml_w.end_tag();
1132 }
1133 ast::ItemEnum(ref enum_definition, _) => {
1134 add_to_index(item, rbml_w, index);
1135
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));
1146 }
1147 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1148 encode_path(rbml_w, path);
1149
1150 // Encode inherent implementations for this enumeration.
1151 encode_inherent_implementations(ecx, rbml_w, def_id);
1152
1153 encode_visibility(rbml_w, vis);
1154 encode_stability(rbml_w, stab);
1155 rbml_w.end_tag();
1156
1157 encode_enum_variant_info(ecx,
1158 rbml_w,
1159 item.id,
1160 &(*enum_definition).variants,
1161 index);
1162 }
1163 ast::ItemStruct(ref struct_def, _) => {
1164 let fields = ty::lookup_struct_fields(tcx, def_id);
1165
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
1169 class itself */
1170 let idx = encode_info_for_struct(ecx,
1171 rbml_w,
1172 &fields[..],
1173 index);
1174
1175 /* Index the class*/
1176 add_to_index(item, rbml_w, index);
1177
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);
1183
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);
1191
1192 /* Encode def_ids for each field and method
1193 for methods, write all the stuff get_trait_method
1194 needs to know*/
1195 encode_struct_fields(rbml_w, &fields[..], def_id);
1196
1197 encode_inlined_item(ecx, rbml_w, IIItemRef(item));
1198
1199 // Encode inherent implementations for this structure.
1200 encode_inherent_implementations(ecx, rbml_w, def_id);
1201
1202 /* Each class has its own index -- encode it */
1203 encode_index(rbml_w, idx, write_i64);
1204 rbml_w.end_tag();
1205
1206 // If this is a tuple-like struct, encode the type of the constructor.
1207 match struct_def.ctor_id {
1208 Some(ctor_id) => {
1209 encode_info_for_struct_ctor(ecx, rbml_w, item.ident.name,
1210 ctor_id, index, def_id.node);
1211 }
1212 None => {}
1213 }
1214 }
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);
1222
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);
1225 rbml_w.end_tag();
1226 }
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();
1232
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);
1242
1243 match tcx.custom_coerce_unsized_kinds.borrow().get(&local_def(item.id)) {
1244 Some(&kind) => {
1245 rbml_w.start_tag(tag_impl_coerce_unsized_kind);
1246 kind.encode(rbml_w);
1247 rbml_w.end_tag();
1248 }
1249 None => {}
1250 }
1251
1252 match ty.node {
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);
1256 }
1257 _ => {}
1258 }
1259 for &item_def_id in items {
1260 rbml_w.start_tag(tag_item_impl_item);
1261 match item_def_id {
1262 ty::ConstTraitItemId(item_def_id) => {
1263 encode_def_id(rbml_w, item_def_id);
1264 encode_item_sort(rbml_w, 'C');
1265 }
1266 ty::MethodTraitItemId(item_def_id) => {
1267 encode_def_id(rbml_w, item_def_id);
1268 encode_item_sort(rbml_w, 'r');
1269 }
1270 ty::TypeTraitItemId(item_def_id) => {
1271 encode_def_id(rbml_w, item_def_id);
1272 encode_item_sort(rbml_w, 't');
1273 }
1274 }
1275 rbml_w.end_tag();
1276 }
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);
1279 }
1280 encode_path(rbml_w, path.clone());
1281 encode_stability(rbml_w, stab);
1282 rbml_w.end_tag();
1283
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])
1292 } else {
1293 None
1294 };
1295
1296 index.push(entry {
1297 val: trait_item_def_id.def_id().node as i64,
1298 pos: rbml_w.mark_stable_position(),
1299 });
1300
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,
1304 rbml_w,
1305 &*associated_const,
1306 path.clone(),
1307 item.id,
1308 ast_item)
1309 }
1310 ty::MethodTraitItem(ref method_type) => {
1311 encode_info_for_method(ecx,
1312 rbml_w,
1313 &**method_type,
1314 path.clone(),
1315 false,
1316 item.id,
1317 ast_item)
1318 }
1319 ty::TypeTraitItem(ref associated_type) => {
1320 encode_info_for_associated_type(ecx,
1321 rbml_w,
1322 &**associated_type,
1323 path.clone(),
1324 item.id,
1325 ast_item)
1326 }
1327 }
1328 }
1329 }
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,
1343 tag_item_generics);
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');
1357 }
1358 ty::MethodTraitItemId(method_def_id) => {
1359 encode_def_id(rbml_w, method_def_id);
1360 encode_item_sort(rbml_w, 'r');
1361 }
1362 ty::TypeTraitItemId(type_def_id) => {
1363 encode_def_id(rbml_w, type_def_id);
1364 encode_item_sort(rbml_w, 't');
1365 }
1366 }
1367 rbml_w.end_tag();
1368
1369 rbml_w.wr_tagged_u64(tag_mod_child,
1370 def_to_u64(method_def_id.def_id()));
1371 }
1372 encode_path(rbml_w, path.clone());
1373
1374 // Encode the implementations of this trait.
1375 encode_extension_implementations(ecx, rbml_w, def_id);
1376
1377 // Encode inherent implementations for this trait.
1378 encode_inherent_implementations(ecx, rbml_w, def_id);
1379
1380 rbml_w.end_tag();
1381
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);
1386
1387 index.push(entry {
1388 val: item_def_id.def_id().node as i64,
1389 pos: rbml_w.mark_stable_position(),
1390 });
1391
1392 rbml_w.start_tag(tag_items_data_item);
1393
1394 encode_parent_item(rbml_w, def_id);
1395
1396 let stab = stability::lookup(tcx, item_def_id.def_id());
1397 encode_stability(rbml_w, stab);
1398
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);
1407
1408 encode_provided_source(rbml_w, associated_const.default);
1409
1410 let elem = ast_map::PathName(associated_const.name);
1411 encode_path(rbml_w,
1412 path.clone().chain(Some(elem)));
1413
1414 encode_item_sort(rbml_w, 'C');
1415 encode_family(rbml_w, 'C');
1416
1417 encode_bounds_and_type_for_item(rbml_w, ecx,
1418 associated_const.def_id.local_id());
1419
1420 is_nonstatic_method = false;
1421 }
1422 ty::MethodTraitItem(method_ty) => {
1423 let method_def_id = item_def_id.def_id();
1424
1425 encode_method_ty_fields(ecx, rbml_w, &*method_ty);
1426
1427 let elem = ast_map::PathName(method_ty.name);
1428 encode_path(rbml_w,
1429 path.clone().chain(Some(elem)));
1430
1431 match method_ty.explicit_self {
1432 ty::StaticExplicitSelfCategory => {
1433 encode_family(rbml_w,
1434 STATIC_METHOD_FAMILY);
1435 }
1436 _ => {
1437 encode_family(rbml_w,
1438 METHOD_FAMILY);
1439 }
1440 }
1441 encode_bounds_and_type_for_item(rbml_w, ecx, method_def_id.local_id());
1442
1443 is_nonstatic_method = method_ty.explicit_self !=
1444 ty::StaticExplicitSelfCategory;
1445 }
1446 ty::TypeTraitItem(associated_type) => {
1447 encode_name(rbml_w, associated_type.name);
1448 encode_def_id(rbml_w, associated_type.def_id);
1449
1450 let elem = ast_map::PathName(associated_type.name);
1451 encode_path(rbml_w,
1452 path.clone().chain(Some(elem)));
1453
1454 encode_item_sort(rbml_w, 't');
1455 encode_family(rbml_w, 'y');
1456
1457 is_nonstatic_method = false;
1458 }
1459 }
1460
1461 encode_parent_sort(rbml_w, 't');
1462
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));
1469 }
1470 ast::MethodTraitItem(ref sig, ref body) => {
1471 // If this is a static method, we've already
1472 // encoded this.
1473 if is_nonstatic_method {
1474 // FIXME: I feel like there is something funny
1475 // going on.
1476 encode_bounds_and_type_for_item(rbml_w, ecx,
1477 item_def_id.def_id().local_id());
1478 }
1479
1480 if body.is_some() {
1481 encode_item_sort(rbml_w, 'p');
1482 encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
1483 } else {
1484 encode_item_sort(rbml_w, 'r');
1485 }
1486 encode_method_argument_names(rbml_w, &sig.decl);
1487 }
1488
1489 ast::TypeTraitItem(..) => {}
1490 }
1491
1492 rbml_w.end_tag();
1493 }
1494 }
1495 ast::ItemExternCrate(_) | ast::ItemUse(_) |ast::ItemMac(..) => {
1496 // these are encoded separately
1497 }
1498 }
1499 }
1500
1501 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1502 rbml_w: &mut Encoder,
1503 nitem: &ast::ForeignItem,
1504 index: &mut Vec<entry<i64>>,
1505 path: PathElems,
1506 abi: abi::Abi) {
1507 index.push(entry {
1508 val: nitem.id as i64,
1509 pos: rbml_w.mark_stable_position(),
1510 });
1511
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);
1515 match nitem.node {
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));
1522 }
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);
1528 }
1529 ast::ForeignItemStatic(_, mutbl) => {
1530 if mutbl {
1531 encode_family(rbml_w, 'b');
1532 } else {
1533 encode_family(rbml_w, 'c');
1534 }
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);
1541 }
1542 }
1543 encode_path(rbml_w, path);
1544 rbml_w.end_tag();
1545 }
1546
1547 fn my_visit_expr(_e: &ast::Expr) { }
1548
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);
1555 });
1556 }
1557
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));
1565
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,
1569 ni, index,
1570 path, abi);
1571 });
1572 }
1573
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>>,
1578 }
1579
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);
1583 my_visit_expr(ex);
1584 }
1585 fn visit_item(&mut self, i: &ast::Item) {
1586 visit::walk_item(self, i);
1587 my_visit_item(i,
1588 self.rbml_w_for_visit_item,
1589 self.ecx,
1590 self.index);
1591 }
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,
1596 self.ecx,
1597 self.index);
1598 }
1599 }
1600
1601 fn encode_info_for_items(ecx: &EncodeContext,
1602 rbml_w: &mut Encoder,
1603 krate: &ast::Crate)
1604 -> Vec<entry<i64>> {
1605 let mut index = Vec::new();
1606 rbml_w.start_tag(tag_items_data);
1607 index.push(entry {
1608 val: ast::CRATE_NODE_ID as i64,
1609 pos: rbml_w.mark_stable_position(),
1610 });
1611 encode_info_for_mod(ecx,
1612 rbml_w,
1613 &krate.module,
1614 &[],
1615 ast::CRATE_NODE_ID,
1616 [].iter().cloned().chain(LinkedPath::empty()),
1617 syntax::parse::token::special_idents::invalid.name,
1618 ast::Public);
1619
1620 visit::walk_crate(&mut EncodeVisitor {
1621 index: &mut index,
1622 ecx: ecx,
1623 rbml_w_for_visit_item: &mut *rbml_w,
1624 }, krate);
1625
1626 rbml_w.end_tag();
1627 index
1628 }
1629
1630
1631 // Path and definition ID indexing
1632
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),
1635 T: Hash,
1636 {
1637 let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect();
1638 for elt in index {
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);
1643 }
1644
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);
1651 for elt in bucket {
1652 rbml_w.start_tag(tag_index_buckets_bucket_elt);
1653 assert!(elt.pos < 0xffff_ffff);
1654 {
1655 let wr: &mut Cursor<Vec<u8>> = rbml_w.writer;
1656 write_be_u32(wr, elt.pos as u32);
1657 }
1658 write_fn(rbml_w.writer, &elt.val);
1659 rbml_w.end_tag();
1660 }
1661 rbml_w.end_tag();
1662 }
1663 rbml_w.end_tag();
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);
1669 }
1670 rbml_w.end_tag();
1671 rbml_w.end_tag();
1672 }
1673
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);
1678 }
1679
1680 fn write_be_u32(w: &mut Write, u: u32) {
1681 w.write_all(&[
1682 (u >> 24) as u8,
1683 (u >> 16) as u8,
1684 (u >> 8) as u8,
1685 (u >> 0) as u8,
1686 ]);
1687 }
1688
1689 fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
1690 match mi.node {
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);
1694 rbml_w.end_tag();
1695 }
1696 ast::MetaNameValue(ref name, ref value) => {
1697 match value.node {
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);
1702 rbml_w.end_tag();
1703 }
1704 _ => {/* FIXME (#623): encode other variants */ }
1705 }
1706 }
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);
1712 }
1713 rbml_w.end_tag();
1714 }
1715 }
1716 }
1717
1718 fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
1719 rbml_w.start_tag(tag_attributes);
1720 for attr in attrs {
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);
1724 rbml_w.end_tag();
1725 }
1726 rbml_w.end_tag();
1727 }
1728
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,
1733 };
1734 rbml_w.wr_tagged_u8(tag_unsafety, byte);
1735 }
1736
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);
1740 }
1741
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);
1745 }
1746
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));
1751 }
1752 rbml_w.end_tag();
1753 }
1754
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,
1759 };
1760 rbml_w.wr_tagged_u8(tag_polarity, byte);
1761 }
1762
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 {
1769 cnum: key,
1770 name: decoder::get_crate_name(val.data()),
1771 hash: decoder::get_crate_hash(val.data()),
1772 };
1773 deps.push(dep);
1774 });
1775
1776 // Sort by cnum
1777 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1778
1779 // Sanity-check the crate numbers
1780 let mut expected_cnum = 1;
1781 for n in &deps {
1782 assert_eq!(n.cnum, expected_cnum);
1783 expected_cnum += 1;
1784 }
1785
1786 deps
1787 }
1788
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);
1795 for dep in &r {
1796 encode_crate_dep(rbml_w, (*dep).clone());
1797 }
1798 rbml_w.end_tag();
1799 }
1800
1801 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1802 rbml_w.start_tag(tag_lang_items);
1803
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);
1810 rbml_w.end_tag();
1811 }
1812 }
1813 }
1814
1815 for i in &ecx.tcx.lang_items.missing {
1816 rbml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1817 }
1818
1819 rbml_w.end_tag(); // tag_lang_items
1820 }
1821
1822 fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1823 rbml_w.start_tag(tag_native_libraries);
1824
1825 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1826 .borrow().iter() {
1827 match kind {
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);
1833 rbml_w.end_tag();
1834 }
1835 }
1836 }
1837
1838 rbml_w.end_tag();
1839 }
1840
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); }
1844 None => {}
1845 }
1846 }
1847
1848 fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1849 rbml_w.start_tag(tag_codemap);
1850 let codemap = ecx.tcx.sess.codemap();
1851
1852 for filemap in &codemap.files.borrow()[..] {
1853
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.
1859 continue;
1860 }
1861
1862 rbml_w.start_tag(tag_codemap_filemap);
1863 filemap.encode(rbml_w);
1864 rbml_w.end_tag();
1865 }
1866
1867 rbml_w.end_tag();
1868 }
1869
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);
1876
1877 encode_name(rbml_w, def.ident.name);
1878 encode_attributes(rbml_w, &def.attrs);
1879
1880 rbml_w.wr_tagged_str(tag_macro_def_body,
1881 &pprust::tts_to_string(&def.body));
1882
1883 rbml_w.end_tag();
1884 }
1885 rbml_w.end_tag();
1886 }
1887
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>,
1891 }
1892
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();
1899 }
1900 }
1901
1902 rbml_w.start_tag(tag_struct_fields);
1903 visit::walk_crate(&mut StructFieldVisitor {
1904 rbml_w: rbml_w
1905 }, krate);
1906 rbml_w.end_tag();
1907 }
1908
1909
1910
1911 struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
1912 ecx: &'a EncodeContext<'b, 'tcx>,
1913 rbml_w: &'a mut Encoder<'c>,
1914 }
1915
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();
1920
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();
1929 }
1930 }
1931 visit::walk_item(self, item);
1932 }
1933 }
1934
1935 /// Encodes implementations that are eagerly loaded.
1936 ///
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:
1941 ///
1942 /// * Destructors (implementations of the Drop trait).
1943 ///
1944 /// * Implementations of traits not defined in this crate.
1945 fn encode_impls<'a>(ecx: &'a EncodeContext,
1946 krate: &ast::Crate,
1947 rbml_w: &'a mut Encoder) {
1948 rbml_w.start_tag(tag_impls);
1949
1950 {
1951 let mut visitor = ImplVisitor {
1952 ecx: ecx,
1953 rbml_w: rbml_w,
1954 };
1955 visit::walk_crate(&mut visitor, krate);
1956 }
1957
1958 rbml_w.end_tag();
1959 }
1960
1961 fn encode_misc_info(ecx: &EncodeContext,
1962 krate: &ast::Crate,
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)));
1969
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)));
1973 true
1974 });
1975 }
1976
1977 // Encode reexports for the root module.
1978 encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(LinkedPath::empty()));
1979
1980 rbml_w.end_tag();
1981 rbml_w.end_tag();
1982 }
1983
1984 fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) {
1985 rbml_w.start_tag(tag_reachable_extern_fns);
1986
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);
1992 }
1993 }
1994 }
1995 }
1996
1997 rbml_w.end_tag();
1998 }
1999
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());
2005 rbml_w.end_tag();
2006 }
2007
2008 fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
2009 rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
2010 }
2011
2012 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
2013 rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
2014 }
2015
2016 fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
2017 rbml_w.wr_tagged_str(tag_crate_triple, triple);
2018 }
2019
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) {
2023 Some(arr) => {
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",
2028 })).to_string())
2029 }).collect::<Vec<String>>();
2030 rbml_w.wr_tagged_str(tag, &s.connect(","));
2031 }
2032 None => {
2033 rbml_w.wr_tagged_str(tag, "");
2034 }
2035 }
2036 }
2037
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 ];
2041
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);
2045
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);
2052
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
2057 // metadata.
2058 //
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.
2065 //
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);
2076 return v;
2077 }
2078
2079 fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
2080 parms: EncodeParams,
2081 krate: &ast::Crate) {
2082 struct Stats {
2083 attr_bytes: u64,
2084 dep_bytes: u64,
2085 lang_item_bytes: u64,
2086 native_lib_bytes: u64,
2087 plugin_registrar_fn_bytes: u64,
2088 codemap_bytes: u64,
2089 macro_defs_bytes: u64,
2090 impl_bytes: u64,
2091 misc_bytes: u64,
2092 item_bytes: u64,
2093 index_bytes: u64,
2094 zero_bytes: u64,
2095 total_bytes: u64,
2096 }
2097 let mut stats = Stats {
2098 attr_bytes: 0,
2099 dep_bytes: 0,
2100 lang_item_bytes: 0,
2101 native_lib_bytes: 0,
2102 plugin_registrar_fn_bytes: 0,
2103 codemap_bytes: 0,
2104 macro_defs_bytes: 0,
2105 impl_bytes: 0,
2106 misc_bytes: 0,
2107 item_bytes: 0,
2108 index_bytes: 0,
2109 zero_bytes: 0,
2110 total_bytes: 0,
2111 };
2112 let EncodeParams {
2113 item_symbols,
2114 diag,
2115 tcx,
2116 reexports,
2117 cstore,
2118 encode_inlined_item,
2119 link_meta,
2120 reachable,
2121 ..
2122 } = parms;
2123 let ecx = EncodeContext {
2124 diag: diag,
2125 tcx: tcx,
2126 reexports: reexports,
2127 item_symbols: item_symbols,
2128 link_meta: link_meta,
2129 cstore: cstore,
2130 encode_inlined_item: RefCell::new(encode_inlined_item),
2131 type_abbrevs: RefCell::new(FnvHashMap()),
2132 reachable: reachable,
2133 };
2134
2135 let mut rbml_w = Encoder::new(wr);
2136
2137 encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
2138 encode_crate_triple(&mut rbml_w,
2139 &tcx.sess
2140 .opts
2141 .target_triple
2142 );
2143 encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
2144 encode_dylib_dependency_formats(&mut rbml_w, &ecx);
2145
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;
2149
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;
2153
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;
2158
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;
2163
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;
2168
2169 // Encode codemap
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;
2173
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;
2178
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;
2183
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;
2189
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;
2195
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;
2199 rbml_w.end_tag();
2200
2201 encode_struct_field_attrs(&mut rbml_w, krate);
2202
2203 stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
2204
2205 if tcx.sess.meta_stats() {
2206 for e in rbml_w.writer.get_ref() {
2207 if *e == 0 {
2208 stats.zero_bytes += 1;
2209 }
2210 }
2211
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);
2226 }
2227 }
2228
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(),
2234 ds: def_to_string,
2235 tcx: tcx,
2236 abbrevs: &RefCell::new(FnvHashMap())
2237 }, t);
2238 String::from_utf8(wr.into_inner()).unwrap()
2239 }