1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
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 use back::svh::Svh;
17 use driver::session;
18 use metadata::common::*;
19 use metadata::cstore;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use middle::ty::{node_id_to_type, lookup_item_type};
23 use middle::astencode;
24 use middle::ty;
25 use middle::typeck;
26 use middle;
27 use util::nodemap::{NodeMap, NodeSet};
28
29 use serialize::Encodable;
30 use std::cast;
31 use std::cell::RefCell;
32 use std::hash;
33 use std::hash::Hash;
34 use std::io::MemWriter;
35 use std::str;
36 use collections::HashMap;
37 use syntax::abi;
38 use syntax::ast::*;
39 use syntax::ast;
40 use syntax::ast_map::{PathElem, PathElems};
41 use syntax::ast_map;
42 use syntax::ast_util::*;
43 use syntax::ast_util;
44 use syntax::attr::AttrMetaMethods;
45 use syntax::attr;
46 use syntax::crateid::CrateId;
47 use syntax::diagnostic::SpanHandler;
48 use syntax::parse::token::InternedString;
49 use syntax::parse::token::special_idents;
50 use syntax::parse::token;
51 use syntax::visit::Visitor;
52 use syntax::visit;
53 use syntax;
54 use writer = serialize::ebml::writer;
55
56 /// A borrowed version of ast::InlinedItem.
57 pub enum InlinedItemRef<'a> {
58 IIItemRef(&'a ast::Item),
59 IIMethodRef(ast::DefId, bool, &'a ast::Method),
60 IIForeignRef(&'a ast::ForeignItem)
61 }
62
63 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
64
65 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
66 ebml_w: &mut Encoder,
67 ii: InlinedItemRef|: 'a;
68
69 pub struct EncodeParams<'a> {
70 pub diag: &'a SpanHandler,
71 pub tcx: &'a ty::ctxt,
72 pub reexports2: &'a middle::resolve::ExportMap2,
73 pub item_symbols: &'a RefCell<NodeMap<~str>>,
74 pub non_inlineable_statics: &'a RefCell<NodeSet>,
75 pub link_meta: &'a LinkMeta,
76 pub cstore: &'a cstore::CStore,
77 pub encode_inlined_item: EncodeInlinedItem<'a>,
78 }
79
80 pub struct EncodeContext<'a> {
81 pub diag: &'a SpanHandler,
82 pub tcx: &'a ty::ctxt,
83 pub reexports2: &'a middle::resolve::ExportMap2,
84 pub item_symbols: &'a RefCell<NodeMap<~str>>,
85 pub non_inlineable_statics: &'a RefCell<NodeSet>,
86 pub link_meta: &'a LinkMeta,
87 pub cstore: &'a cstore::CStore,
88 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
89 pub type_abbrevs: tyencode::abbrev_map,
90 }
91
92 fn encode_name(ebml_w: &mut Encoder, name: Name) {
93 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
94 }
95
96 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
97 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
98 }
99
100 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
101 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
102 }
103
104 #[deriving(Clone)]
105 struct entry<T> {
106 val: T,
107 pos: u64
108 }
109
110 fn encode_trait_ref(ebml_w: &mut Encoder,
111 ecx: &EncodeContext,
112 trait_ref: &ty::TraitRef,
113 tag: uint) {
114 let ty_str_ctxt = &tyencode::ctxt {
115 diag: ecx.diag,
116 ds: def_to_str,
117 tcx: ecx.tcx,
118 abbrevs: &ecx.type_abbrevs
119 };
120
121 ebml_w.start_tag(tag);
122 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
123 ebml_w.end_tag();
124 }
125
126 fn encode_impl_vtables(ebml_w: &mut Encoder,
127 ecx: &EncodeContext,
128 vtables: &typeck::impl_res) {
129 ebml_w.start_tag(tag_item_impl_vtables);
130 astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
131 astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
132 ebml_w.end_tag();
133 }
134
135 // Item info table encoding
136 fn encode_family(ebml_w: &mut Encoder, c: char) {
137 ebml_w.start_tag(tag_items_data_item_family);
138 ebml_w.writer.write(&[c as u8]);
139 ebml_w.end_tag();
140 }
141
142 pub fn def_to_str(did: DefId) -> ~str {
143 format!("{}:{}", did.krate, did.node)
144 }
145
146 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
147 ecx: &EncodeContext,
148 params: &[ty::TypeParameterDef],
149 tag: uint) {
150 let ty_str_ctxt = &tyencode::ctxt {
151 diag: ecx.diag,
152 ds: def_to_str,
153 tcx: ecx.tcx,
154 abbrevs: &ecx.type_abbrevs
155 };
156 for param in params.iter() {
157 ebml_w.start_tag(tag);
158 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
159 ebml_w.end_tag();
160 }
161 }
162
163 fn encode_region_param_defs(ebml_w: &mut Encoder,
164 params: &[ty::RegionParameterDef]) {
165 for param in params.iter() {
166 ebml_w.start_tag(tag_region_param_def);
167
168 ebml_w.start_tag(tag_region_param_def_ident);
169 encode_name(ebml_w, param.name);
170 ebml_w.end_tag();
171
172 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
173 def_to_str(param.def_id));
174
175 ebml_w.end_tag();
176 }
177 }
178
179 fn encode_item_variances(ebml_w: &mut Encoder,
180 ecx: &EncodeContext,
181 id: ast::NodeId) {
182 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
183 ebml_w.start_tag(tag_item_variances);
184 v.encode(ebml_w);
185 ebml_w.end_tag();
186 }
187
188 fn encode_bounds_and_type(ebml_w: &mut Encoder,
189 ecx: &EncodeContext,
190 tpt: &ty::ty_param_bounds_and_ty) {
191 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
192 tag_items_data_item_ty_param_bounds);
193 encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
194 encode_type(ecx, ebml_w, tpt.ty);
195 }
196
197 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
198 ebml_w.start_tag(tag_items_data_item_variant);
199 let s = def_to_str(vid);
200 ebml_w.writer.write(s.as_bytes());
201 ebml_w.end_tag();
202 }
203
204 pub fn write_type(ecx: &EncodeContext,
205 ebml_w: &mut Encoder,
206 typ: ty::t) {
207 let ty_str_ctxt = &tyencode::ctxt {
208 diag: ecx.diag,
209 ds: def_to_str,
210 tcx: ecx.tcx,
211 abbrevs: &ecx.type_abbrevs
212 };
213 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
214 }
215
216 fn encode_type(ecx: &EncodeContext,
217 ebml_w: &mut Encoder,
218 typ: ty::t) {
219 ebml_w.start_tag(tag_items_data_item_type);
220 write_type(ecx, ebml_w, typ);
221 ebml_w.end_tag();
222 }
223
224 fn encode_method_fty(ecx: &EncodeContext,
225 ebml_w: &mut Encoder,
226 typ: &ty::BareFnTy) {
227 ebml_w.start_tag(tag_item_method_fty);
228
229 let ty_str_ctxt = &tyencode::ctxt {
230 diag: ecx.diag,
231 ds: def_to_str,
232 tcx: ecx.tcx,
233 abbrevs: &ecx.type_abbrevs
234 };
235 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
236
237 ebml_w.end_tag();
238 }
239
240 fn encode_symbol(ecx: &EncodeContext,
241 ebml_w: &mut Encoder,
242 id: NodeId) {
243 ebml_w.start_tag(tag_items_data_item_symbol);
244 match ecx.item_symbols.borrow().find(&id) {
245 Some(x) => {
246 debug!("encode_symbol(id={:?}, str={})", id, *x);
247 ebml_w.writer.write(x.as_bytes());
248 }
249 None => {
250 ecx.diag.handler().bug(
251 format!("encode_symbol: id not found {}", id));
252 }
253 }
254 ebml_w.end_tag();
255 }
256
257 fn encode_disr_val(_: &EncodeContext,
258 ebml_w: &mut Encoder,
259 disr_val: ty::Disr) {
260 ebml_w.start_tag(tag_disr_val);
261 let s = disr_val.to_str();
262 ebml_w.writer.write(s.as_bytes());
263 ebml_w.end_tag();
264 }
265
266 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
267 ebml_w.start_tag(tag_items_data_parent_item);
268 let s = def_to_str(id);
269 ebml_w.writer.write(s.as_bytes());
270 ebml_w.end_tag();
271 }
272
273 fn encode_struct_fields(ebml_w: &mut Encoder,
274 fields: &[ty::field_ty],
275 origin: DefId) {
276 for f in fields.iter() {
277 if f.name == special_idents::unnamed_field.name {
278 ebml_w.start_tag(tag_item_unnamed_field);
279 } else {
280 ebml_w.start_tag(tag_item_field);
281 encode_name(ebml_w, f.name);
282 }
283 encode_struct_field_family(ebml_w, f.vis);
284 encode_def_id(ebml_w, f.id);
285 ebml_w.start_tag(tag_item_field_origin);
286 let s = def_to_str(origin);
287 ebml_w.writer.write(s.as_bytes());
288 ebml_w.end_tag();
289 ebml_w.end_tag();
290 }
291 }
292
293 fn encode_enum_variant_info(ecx: &EncodeContext,
294 ebml_w: &mut Encoder,
295 id: NodeId,
296 variants: &[P<Variant>],
297 index: &mut Vec<entry<i64>>,
298 generics: &ast::Generics) {
299 debug!("encode_enum_variant_info(id={:?})", id);
300
301 let mut disr_val = 0;
302 let mut i = 0;
303 let vi = ty::enum_variants(ecx.tcx,
304 ast::DefId { krate: LOCAL_CRATE, node: id });
305 for variant in variants.iter() {
306 let def_id = local_def(variant.node.id);
307 index.push(entry {
308 val: variant.node.id as i64,
309 pos: ebml_w.writer.tell().unwrap(),
310 });
311 ebml_w.start_tag(tag_items_data_item);
312 encode_def_id(ebml_w, def_id);
313 match variant.node.kind {
314 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
315 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
316 }
317 encode_name(ebml_w, variant.node.name.name);
318 encode_parent_item(ebml_w, local_def(id));
319 encode_visibility(ebml_w, variant.node.vis);
320 encode_attributes(ebml_w, variant.node.attrs.as_slice());
321 match variant.node.kind {
322 ast::TupleVariantKind(ref args)
323 if args.len() > 0 && generics.ty_params.len() == 0 => {
324 encode_symbol(ecx, ebml_w, variant.node.id);
325 }
326 ast::TupleVariantKind(_) => {},
327 ast::StructVariantKind(_) => {
328 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
329 let idx = encode_info_for_struct(ecx,
330 ebml_w,
331 fields.as_slice(),
332 index);
333 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
334 encode_index(ebml_w, idx, write_i64);
335 }
336 }
337 if vi.get(i).disr_val != disr_val {
338 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
339 disr_val = vi.get(i).disr_val;
340 }
341 encode_bounds_and_type(ebml_w, ecx,
342 &lookup_item_type(ecx.tcx, def_id));
343
344 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
345 ebml_w.end_tag();
346 disr_val += 1;
347 i += 1;
348 }
349 }
350
351 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
352 mut path: PI) {
353 ebml_w.start_tag(tag_path);
354 ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
355 for pe in path {
356 let tag = match pe {
357 ast_map::PathMod(_) => tag_path_elem_mod,
358 ast_map::PathName(_) => tag_path_elem_name
359 };
360 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
361 }
362 ebml_w.end_tag();
363 }
364
365 fn encode_reexported_static_method(ebml_w: &mut Encoder,
366 exp: &middle::resolve::Export2,
367 method_def_id: DefId,
368 method_ident: Ident) {
369 debug!("(encode reexported static method) {}::{}",
370 exp.name, token::get_ident(method_ident));
371 ebml_w.start_tag(tag_items_data_item_reexport);
372 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
373 ebml_w.wr_str(def_to_str(method_def_id));
374 ebml_w.end_tag();
375 ebml_w.start_tag(tag_items_data_item_reexport_name);
376 ebml_w.wr_str(format!("{}::{}", exp.name, token::get_ident(method_ident)));
377 ebml_w.end_tag();
378 ebml_w.end_tag();
379 }
380
381 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
382 ebml_w: &mut Encoder,
383 exp: &middle::resolve::Export2)
384 -> bool {
385 let impl_methods = ecx.tcx.impl_methods.borrow();
386 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
387 Some(implementations) => {
388 for base_impl_did in implementations.borrow().iter() {
389 for &method_did in impl_methods.get(base_impl_did).iter() {
390 let m = ty::method(ecx.tcx, method_did);
391 if m.explicit_self == ast::SelfStatic {
392 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
393 }
394 }
395 }
396
397 true
398 }
399 None => { false }
400 }
401 }
402
403 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
404 ebml_w: &mut Encoder,
405 exp: &middle::resolve::Export2)
406 -> bool {
407 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
408 Some(methods) => {
409 for m in methods.iter() {
410 if m.explicit_self == ast::SelfStatic {
411 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
412 }
413 }
414
415 true
416 }
417 None => { false }
418 }
419 }
420
421 fn encode_reexported_static_methods(ecx: &EncodeContext,
422 ebml_w: &mut Encoder,
423 mod_path: PathElems,
424 exp: &middle::resolve::Export2) {
425 match ecx.tcx.map.find(exp.def_id.node) {
426 Some(ast_map::NodeItem(item)) => {
427 let original_name = token::get_ident(item.ident);
428
429 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
430 let (mut a, mut b) = (path, mod_path.clone());
431 loop {
432 match (a.next(), b.next()) {
433 (None, None) => return true,
434 (None, _) | (_, None) => return false,
435 (Some(x), Some(y)) => if x != y { return false },
436 }
437 }
438 });
439
440 //
441 // We don't need to reexport static methods on items
442 // declared in the same module as our `pub use ...` since
443 // that's done when we encode the item itself.
444 //
445 // The only exception is when the reexport *changes* the
446 // name e.g. `pub use Foo = self::Bar` -- we have
447 // encoded metadata for static methods relative to Bar,
448 // but not yet for Foo.
449 //
450 if path_differs || original_name.get() != exp.name {
451 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
452 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
453 debug!("(encode reexported static methods) {} \
454 [trait]",
455 original_name);
456 }
457 }
458 else {
459 debug!("(encode reexported static methods) {} [base]",
460 original_name);
461 }
462 }
463 }
464 _ => {}
465 }
466 }
467
468 /// Iterates through "auxiliary node IDs", which are node IDs that describe
469 /// top-level items that are sub-items of the given item. Specifically:
470 ///
471 /// * For enums, iterates through the node IDs of the variants.
472 ///
473 /// * For newtype structs, iterates through the node ID of the constructor.
474 fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
475 let mut continue_ = true;
476 match item.node {
477 ItemEnum(ref enum_def, _) => {
478 for variant in enum_def.variants.iter() {
479 continue_ = callback(variant.node.id);
480 if !continue_ {
481 break
482 }
483 }
484 }
485 ItemStruct(struct_def, _) => {
486 // If this is a newtype struct, return the constructor.
487 match struct_def.ctor_id {
488 Some(ctor_id) if struct_def.fields.len() > 0 &&
489 struct_def.fields.get(0).node.kind.is_unnamed() => {
490 continue_ = callback(ctor_id);
491 }
492 _ => {}
493 }
494 }
495 _ => {}
496 }
497
498 continue_
499 }
500
501 fn encode_reexports(ecx: &EncodeContext,
502 ebml_w: &mut Encoder,
503 id: NodeId,
504 path: PathElems) {
505 debug!("(encoding info for module) encoding reexports for {}", id);
506 match ecx.reexports2.borrow().find(&id) {
507 Some(ref exports) => {
508 debug!("(encoding info for module) found reexports for {}", id);
509 for exp in exports.iter() {
510 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
511 {}",
512 exp.name,
513 exp.def_id.krate,
514 exp.def_id.node,
515 id);
516 ebml_w.start_tag(tag_items_data_item_reexport);
517 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
518 ebml_w.wr_str(def_to_str(exp.def_id));
519 ebml_w.end_tag();
520 ebml_w.start_tag(tag_items_data_item_reexport_name);
521 ebml_w.wr_str(exp.name);
522 ebml_w.end_tag();
523 ebml_w.end_tag();
524 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
525 }
526 }
527 None => {
528 debug!("(encoding info for module) found no reexports for {}",
529 id);
530 }
531 }
532 }
533
534 fn encode_info_for_mod(ecx: &EncodeContext,
535 ebml_w: &mut Encoder,
536 md: &Mod,
537 id: NodeId,
538 path: PathElems,
539 name: Ident,
540 vis: Visibility) {
541 ebml_w.start_tag(tag_items_data_item);
542 encode_def_id(ebml_w, local_def(id));
543 encode_family(ebml_w, 'm');
544 encode_name(ebml_w, name.name);
545 debug!("(encoding info for module) encoding info for module ID {}", id);
546
547 // Encode info about all the module children.
548 for item in md.items.iter() {
549 ebml_w.start_tag(tag_mod_child);
550 ebml_w.wr_str(def_to_str(local_def(item.id)));
551 ebml_w.end_tag();
552
553 each_auxiliary_node_id(*item, |auxiliary_node_id| {
554 ebml_w.start_tag(tag_mod_child);
555 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
556 ebml_w.end_tag();
557 true
558 });
559
560 match item.node {
561 ItemImpl(..) => {
562 let (ident, did) = (item.ident, item.id);
563 debug!("(encoding info for module) ... encoding impl {} \
564 ({:?}/{:?})",
565 token::get_ident(ident),
566 did, ecx.tcx.map.node_to_str(did));
567
568 ebml_w.start_tag(tag_mod_impl);
569 ebml_w.wr_str(def_to_str(local_def(did)));
570 ebml_w.end_tag();
571 }
572 _ => {}
573 }
574 }
575
576 encode_path(ebml_w, path.clone());
577 encode_visibility(ebml_w, vis);
578
579 // Encode the reexports of this module, if this module is public.
580 if vis == Public {
581 debug!("(encoding info for module) encoding reexports for {}", id);
582 encode_reexports(ecx, ebml_w, id, path);
583 }
584
585 ebml_w.end_tag();
586 }
587
588 fn encode_struct_field_family(ebml_w: &mut Encoder,
589 visibility: Visibility) {
590 encode_family(ebml_w, match visibility {
591 Public => 'g',
592 Inherited => 'N'
593 });
594 }
595
596 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
597 ebml_w.start_tag(tag_items_data_item_visibility);
598 let ch = match visibility {
599 Public => 'y',
600 Inherited => 'i',
601 };
602 ebml_w.wr_str(str::from_char(ch));
603 ebml_w.end_tag();
604 }
605
606 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
607 ebml_w.start_tag(tag_item_trait_method_explicit_self);
608
609 // Encode the base self type.
610 match explicit_self {
611 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
612 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
613 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
614 SelfRegion(_, m) => {
615 // FIXME(#4846) encode custom lifetime
616 ebml_w.writer.write(&['&' as u8]);
617 encode_mutability(ebml_w, m);
618 }
619 }
620
621 ebml_w.end_tag();
622
623 fn encode_mutability(ebml_w: &mut Encoder,
624 m: ast::Mutability) {
625 match m {
626 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
627 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
628 }
629 }
630 }
631
632 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
633 ebml_w.start_tag(tag_item_trait_method_sort);
634 ebml_w.writer.write(&[ sort as u8 ]);
635 ebml_w.end_tag();
636 }
637
638 fn encode_provided_source(ebml_w: &mut Encoder,
639 source_opt: Option<DefId>) {
640 for source in source_opt.iter() {
641 ebml_w.start_tag(tag_item_method_provided_source);
642 let s = def_to_str(*source);
643 ebml_w.writer.write(s.as_bytes());
644 ebml_w.end_tag();
645 }
646 }
647
648 /* Returns an index of items in this class */
649 fn encode_info_for_struct(ecx: &EncodeContext,
650 ebml_w: &mut Encoder,
651 fields: &[ty::field_ty],
652 global_index: &mut Vec<entry<i64>>)
653 -> Vec<entry<i64>> {
654 /* Each class has its own index, since different classes
655 may have fields with the same name */
656 let mut index = Vec::new();
657 let tcx = ecx.tcx;
658 /* We encode both private and public fields -- need to include
659 private fields to get the offsets right */
660 for field in fields.iter() {
661 let nm = field.name;
662 let id = field.id.node;
663
664 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
665 global_index.push(entry {
666 val: id as i64,
667 pos: ebml_w.writer.tell().unwrap(),
668 });
669 ebml_w.start_tag(tag_items_data_item);
670 debug!("encode_info_for_struct: doing {} {}",
671 token::get_name(nm), id);
672 encode_struct_field_family(ebml_w, field.vis);
673 encode_name(ebml_w, nm);
674 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
675 encode_def_id(ebml_w, local_def(id));
676 ebml_w.end_tag();
677 }
678 index
679 }
680
681 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
682 ebml_w: &mut Encoder,
683 name: ast::Ident,
684 ctor_id: NodeId,
685 index: &mut Vec<entry<i64>>,
686 struct_id: NodeId) {
687 index.push(entry {
688 val: ctor_id as i64,
689 pos: ebml_w.writer.tell().unwrap(),
690 });
691
692 ebml_w.start_tag(tag_items_data_item);
693 encode_def_id(ebml_w, local_def(ctor_id));
694 encode_family(ebml_w, 'f');
695 encode_bounds_and_type(ebml_w, ecx,
696 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
697 encode_name(ebml_w, name.name);
698 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
699 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
700 encode_parent_item(ebml_w, local_def(struct_id));
701
702 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
703 encode_symbol(ecx, ebml_w, ctor_id);
704 }
705
706 // indicate that this is a tuple struct ctor, because downstream users will normally want
707 // the tuple struct definition, but without this there is no way for them to tell that
708 // they actually have a ctor rather than a normal function
709 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
710 ebml_w.end_tag();
711
712 ebml_w.end_tag();
713 }
714
715 fn encode_method_ty_fields(ecx: &EncodeContext,
716 ebml_w: &mut Encoder,
717 method_ty: &ty::Method) {
718 encode_def_id(ebml_w, method_ty.def_id);
719 encode_name(ebml_w, method_ty.ident.name);
720 encode_ty_type_param_defs(ebml_w, ecx,
721 method_ty.generics.type_param_defs(),
722 tag_item_method_tps);
723 encode_method_fty(ecx, ebml_w, &method_ty.fty);
724 encode_visibility(ebml_w, method_ty.vis);
725 encode_explicit_self(ebml_w, method_ty.explicit_self);
726 let fn_style = method_ty.fty.fn_style;
727 match method_ty.explicit_self {
728 ast::SelfStatic => {
729 encode_family(ebml_w, fn_style_static_method_family(fn_style));
730 }
731 _ => encode_family(ebml_w, style_fn_family(fn_style))
732 }
733 encode_provided_source(ebml_w, method_ty.provided_source);
734 }
735
736 fn encode_info_for_method(ecx: &EncodeContext,
737 ebml_w: &mut Encoder,
738 m: &ty::Method,
739 impl_path: PathElems,
740 is_default_impl: bool,
741 parent_id: NodeId,
742 ast_method_opt: Option<@Method>) {
743
744 debug!("encode_info_for_method: {:?} {}", m.def_id,
745 token::get_ident(m.ident));
746 ebml_w.start_tag(tag_items_data_item);
747
748 encode_method_ty_fields(ecx, ebml_w, m);
749 encode_parent_item(ebml_w, local_def(parent_id));
750
751 // The type for methods gets encoded twice, which is unfortunate.
752 let tpt = lookup_item_type(ecx.tcx, m.def_id);
753 encode_bounds_and_type(ebml_w, ecx, &tpt);
754
755 let elem = ast_map::PathName(m.ident.name);
756 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
757 match ast_method_opt {
758 Some(ast_method) => {
759 encode_attributes(ebml_w, ast_method.attrs.as_slice())
760 }
761 None => ()
762 }
763
764 for &ast_method in ast_method_opt.iter() {
765 let num_params = tpt.generics.type_param_defs().len();
766 if num_params > 0u ||
767 is_default_impl ||
768 should_inline(ast_method.attrs.as_slice()) {
769 encode_inlined_item(ecx, ebml_w,
770 IIMethodRef(local_def(parent_id), false, ast_method));
771 } else {
772 encode_symbol(ecx, ebml_w, m.def_id.node);
773 }
774 }
775
776 ebml_w.end_tag();
777 }
778
779 fn encode_inlined_item(ecx: &EncodeContext,
780 ebml_w: &mut Encoder,
781 ii: InlinedItemRef) {
782 let mut eii = ecx.encode_inlined_item.borrow_mut();
783 let eii: &mut EncodeInlinedItem = &mut *eii;
784 (*eii)(ecx, ebml_w, ii)
785 }
786
787 fn style_fn_family(s: FnStyle) -> char {
788 match s {
789 UnsafeFn => 'u',
790 NormalFn => 'f',
791 }
792 }
793
794 fn fn_style_static_method_family(s: FnStyle) -> char {
795 match s {
796 UnsafeFn => 'U',
797 NormalFn => 'F',
798 }
799 }
800
801
802 fn should_inline(attrs: &[Attribute]) -> bool {
803 use syntax::attr::*;
804 match find_inline_attr(attrs) {
805 InlineNone | InlineNever => false,
806 InlineHint | InlineAlways => true
807 }
808 }
809
810 // Encodes the inherent implementations of a structure, enumeration, or trait.
811 fn encode_inherent_implementations(ecx: &EncodeContext,
812 ebml_w: &mut Encoder,
813 def_id: DefId) {
814 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
815 None => {}
816 Some(implementations) => {
817 for &impl_def_id in implementations.borrow().iter() {
818 ebml_w.start_tag(tag_items_data_item_inherent_impl);
819 encode_def_id(ebml_w, impl_def_id);
820 ebml_w.end_tag();
821 }
822 }
823 }
824 }
825
826 // Encodes the implementations of a trait defined in this crate.
827 fn encode_extension_implementations(ecx: &EncodeContext,
828 ebml_w: &mut Encoder,
829 trait_def_id: DefId) {
830 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
831 None => {}
832 Some(implementations) => {
833 for &impl_def_id in implementations.borrow().iter() {
834 ebml_w.start_tag(tag_items_data_item_extension_impl);
835 encode_def_id(ebml_w, impl_def_id);
836 ebml_w.end_tag();
837 }
838 }
839 }
840 }
841
842 fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
843 ebml_w.start_tag(tag_items_data_item_sized);
844 let ch = match sized {
845 DynSize => 'd',
846 StaticSize => 's',
847 };
848 ebml_w.wr_str(str::from_char(ch));
849 ebml_w.end_tag();
850 }
851
852 fn encode_info_for_item(ecx: &EncodeContext,
853 ebml_w: &mut Encoder,
854 item: &Item,
855 index: &mut Vec<entry<i64>>,
856 path: PathElems,
857 vis: ast::Visibility) {
858 let tcx = ecx.tcx;
859
860 fn add_to_index(item: &Item, ebml_w: &Encoder,
861 index: &mut Vec<entry<i64>>) {
862 index.push(entry {
863 val: item.id as i64,
864 pos: ebml_w.writer.tell().unwrap(),
865 });
866 }
867
868 debug!("encoding info for item at {}",
869 ecx.tcx.sess.codemap().span_to_str(item.span));
870
871 let def_id = local_def(item.id);
872 match item.node {
873 ItemStatic(_, m, _) => {
874 add_to_index(item, ebml_w, index);
875 ebml_w.start_tag(tag_items_data_item);
876 encode_def_id(ebml_w, def_id);
877 if m == ast::MutMutable {
878 encode_family(ebml_w, 'b');
879 } else {
880 encode_family(ebml_w, 'c');
881 }
882 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
883 encode_symbol(ecx, ebml_w, item.id);
884 encode_name(ebml_w, item.ident.name);
885 encode_path(ebml_w, path);
886
887 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
888
889 if inlineable {
890 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
891 }
892 encode_visibility(ebml_w, vis);
893 ebml_w.end_tag();
894 }
895 ItemFn(_, fn_style, _, ref generics, _) => {
896 add_to_index(item, ebml_w, index);
897 ebml_w.start_tag(tag_items_data_item);
898 encode_def_id(ebml_w, def_id);
899 encode_family(ebml_w, style_fn_family(fn_style));
900 let tps_len = generics.ty_params.len();
901 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
902 encode_name(ebml_w, item.ident.name);
903 encode_path(ebml_w, path);
904 encode_attributes(ebml_w, item.attrs.as_slice());
905 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
906 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
907 } else {
908 encode_symbol(ecx, ebml_w, item.id);
909 }
910 encode_visibility(ebml_w, vis);
911 ebml_w.end_tag();
912 }
913 ItemMod(ref m) => {
914 add_to_index(item, ebml_w, index);
915 encode_info_for_mod(ecx,
916 ebml_w,
917 m,
918 item.id,
919 path,
920 item.ident,
921 item.vis);
922 }
923 ItemForeignMod(ref fm) => {
924 add_to_index(item, ebml_w, index);
925 ebml_w.start_tag(tag_items_data_item);
926 encode_def_id(ebml_w, def_id);
927 encode_family(ebml_w, 'n');
928 encode_name(ebml_w, item.ident.name);
929 encode_path(ebml_w, path);
930
931 // Encode all the items in this module.
932 for foreign_item in fm.items.iter() {
933 ebml_w.start_tag(tag_mod_child);
934 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
935 ebml_w.end_tag();
936 }
937 encode_visibility(ebml_w, vis);
938 ebml_w.end_tag();
939 }
940 ItemTy(..) => {
941 add_to_index(item, ebml_w, index);
942 ebml_w.start_tag(tag_items_data_item);
943 encode_def_id(ebml_w, def_id);
944 encode_family(ebml_w, 'y');
945 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
946 encode_name(ebml_w, item.ident.name);
947 encode_path(ebml_w, path);
948 encode_visibility(ebml_w, vis);
949 ebml_w.end_tag();
950 }
951 ItemEnum(ref enum_definition, ref generics) => {
952 add_to_index(item, ebml_w, index);
953
954 ebml_w.start_tag(tag_items_data_item);
955 encode_def_id(ebml_w, def_id);
956 encode_family(ebml_w, 't');
957 encode_item_variances(ebml_w, ecx, item.id);
958 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
959 encode_name(ebml_w, item.ident.name);
960 encode_attributes(ebml_w, item.attrs.as_slice());
961 for v in (*enum_definition).variants.iter() {
962 encode_variant_id(ebml_w, local_def(v.node.id));
963 }
964 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
965 encode_path(ebml_w, path);
966
967 // Encode inherent implementations for this enumeration.
968 encode_inherent_implementations(ecx, ebml_w, def_id);
969
970 encode_visibility(ebml_w, vis);
971 ebml_w.end_tag();
972
973 encode_enum_variant_info(ecx,
974 ebml_w,
975 item.id,
976 (*enum_definition).variants.as_slice(),
977 index,
978 generics);
979 }
980 ItemStruct(struct_def, _) => {
981 let fields = ty::lookup_struct_fields(tcx, def_id);
982
983 /* First, encode the fields
984 These come first because we need to write them to make
985 the index, and the index needs to be in the item for the
986 class itself */
987 let idx = encode_info_for_struct(ecx,
988 ebml_w,
989 fields.as_slice(),
990 index);
991
992 /* Index the class*/
993 add_to_index(item, ebml_w, index);
994
995 /* Now, make an item for the class itself */
996 ebml_w.start_tag(tag_items_data_item);
997 encode_def_id(ebml_w, def_id);
998 encode_family(ebml_w, 'S');
999 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1000
1001 encode_item_variances(ebml_w, ecx, item.id);
1002 encode_name(ebml_w, item.ident.name);
1003 encode_attributes(ebml_w, item.attrs.as_slice());
1004 encode_path(ebml_w, path.clone());
1005 encode_visibility(ebml_w, vis);
1006
1007 /* Encode def_ids for each field and method
1008 for methods, write all the stuff get_trait_method
1009 needs to know*/
1010 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1011
1012 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1013
1014 // Encode inherent implementations for this structure.
1015 encode_inherent_implementations(ecx, ebml_w, def_id);
1016
1017 /* Each class has its own index -- encode it */
1018 encode_index(ebml_w, idx, write_i64);
1019 ebml_w.end_tag();
1020
1021 // If this is a tuple-like struct, encode the type of the constructor.
1022 match struct_def.ctor_id {
1023 Some(ctor_id) => {
1024 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1025 ctor_id, index, def_id.node);
1026 }
1027 None => {}
1028 }
1029 }
1030 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1031 // We need to encode information about the default methods we
1032 // have inherited, so we drive this based on the impl structure.
1033 let impl_methods = tcx.impl_methods.borrow();
1034 let methods = impl_methods.get(&def_id);
1035
1036 add_to_index(item, ebml_w, index);
1037 ebml_w.start_tag(tag_items_data_item);
1038 encode_def_id(ebml_w, def_id);
1039 encode_family(ebml_w, 'i');
1040 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1041 encode_name(ebml_w, item.ident.name);
1042 encode_attributes(ebml_w, item.attrs.as_slice());
1043 match ty.node {
1044 ast::TyPath(ref path, ref bounds, _) if path.segments
1045 .len() == 1 => {
1046 assert!(bounds.is_none());
1047 encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
1048 }
1049 _ => {}
1050 }
1051 for &method_def_id in methods.iter() {
1052 ebml_w.start_tag(tag_item_impl_method);
1053 let s = def_to_str(method_def_id);
1054 ebml_w.writer.write(s.as_bytes());
1055 ebml_w.end_tag();
1056 }
1057 for ast_trait_ref in opt_trait.iter() {
1058 let trait_ref = ty::node_id_to_trait_ref(
1059 tcx, ast_trait_ref.ref_id);
1060 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1061 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1062 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1063 }
1064 encode_path(ebml_w, path.clone());
1065 ebml_w.end_tag();
1066
1067 // Iterate down the methods, emitting them. We rely on the
1068 // assumption that all of the actually implemented methods
1069 // appear first in the impl structure, in the same order they do
1070 // in the ast. This is a little sketchy.
1071 let num_implemented_methods = ast_methods.len();
1072 for (i, &method_def_id) in methods.iter().enumerate() {
1073 let ast_method = if i < num_implemented_methods {
1074 Some(*ast_methods.get(i))
1075 } else { None };
1076
1077 index.push(entry {
1078 val: method_def_id.node as i64,
1079 pos: ebml_w.writer.tell().unwrap(),
1080 });
1081 encode_info_for_method(ecx,
1082 ebml_w,
1083 &*ty::method(tcx, method_def_id),
1084 path.clone(),
1085 false,
1086 item.id,
1087 ast_method)
1088 }
1089 }
1090 ItemTrait(_, sized, ref super_traits, ref ms) => {
1091 add_to_index(item, ebml_w, index);
1092 ebml_w.start_tag(tag_items_data_item);
1093 encode_def_id(ebml_w, def_id);
1094 encode_family(ebml_w, 'I');
1095 encode_item_variances(ebml_w, ecx, item.id);
1096 let trait_def = ty::lookup_trait_def(tcx, def_id);
1097 encode_ty_type_param_defs(ebml_w, ecx,
1098 trait_def.generics.type_param_defs(),
1099 tag_items_data_item_ty_param_bounds);
1100 encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
1101 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1102 encode_name(ebml_w, item.ident.name);
1103 encode_attributes(ebml_w, item.attrs.as_slice());
1104 // When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
1105 // should no longer need this ugly little hack either.
1106 encode_sized(ebml_w, sized);
1107 encode_visibility(ebml_w, vis);
1108 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1109 ebml_w.start_tag(tag_item_trait_method);
1110 encode_def_id(ebml_w, method_def_id);
1111 ebml_w.end_tag();
1112
1113 ebml_w.start_tag(tag_mod_child);
1114 ebml_w.wr_str(def_to_str(method_def_id));
1115 ebml_w.end_tag();
1116 }
1117 encode_path(ebml_w, path.clone());
1118 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1119 // reading the AST's list, because the former has already filtered out
1120 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1121 for ast_trait_ref in super_traits.iter() {
1122 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1123 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1124 }
1125
1126 // Encode the implementations of this trait.
1127 encode_extension_implementations(ecx, ebml_w, def_id);
1128
1129 ebml_w.end_tag();
1130
1131 // Now output the method info for each method.
1132 let r = ty::trait_method_def_ids(tcx, def_id);
1133 for (i, &method_def_id) in r.iter().enumerate() {
1134 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1135
1136 let method_ty = ty::method(tcx, method_def_id);
1137
1138 index.push(entry {
1139 val: method_def_id.node as i64,
1140 pos: ebml_w.writer.tell().unwrap(),
1141 });
1142
1143 ebml_w.start_tag(tag_items_data_item);
1144
1145 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1146
1147 encode_parent_item(ebml_w, def_id);
1148
1149 let elem = ast_map::PathName(method_ty.ident.name);
1150 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1151
1152 match method_ty.explicit_self {
1153 SelfStatic => {
1154 encode_family(ebml_w,
1155 fn_style_static_method_family(
1156 method_ty.fty.fn_style));
1157
1158 let tpt = ty::lookup_item_type(tcx, method_def_id);
1159 encode_bounds_and_type(ebml_w, ecx, &tpt);
1160 }
1161
1162 _ => {
1163 encode_family(ebml_w,
1164 style_fn_family(
1165 method_ty.fty.fn_style));
1166 }
1167 }
1168
1169 match ms.get(i) {
1170 &Required(ref tm) => {
1171 encode_attributes(ebml_w, tm.attrs.as_slice());
1172 encode_method_sort(ebml_w, 'r');
1173 }
1174
1175 &Provided(m) => {
1176 encode_attributes(ebml_w, m.attrs.as_slice());
1177 // If this is a static method, we've already encoded
1178 // this.
1179 if method_ty.explicit_self != SelfStatic {
1180 // FIXME: I feel like there is something funny going on.
1181 let tpt = ty::lookup_item_type(tcx, method_def_id);
1182 encode_bounds_and_type(ebml_w, ecx, &tpt);
1183 }
1184 encode_method_sort(ebml_w, 'p');
1185 encode_inlined_item(ecx, ebml_w,
1186 IIMethodRef(def_id, true, m));
1187 }
1188 }
1189
1190 ebml_w.end_tag();
1191 }
1192
1193 // Encode inherent implementations for this trait.
1194 encode_inherent_implementations(ecx, ebml_w, def_id);
1195 }
1196 ItemMac(..) => {
1197 // macros are encoded separately
1198 }
1199 }
1200 }
1201
1202 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1203 ebml_w: &mut Encoder,
1204 nitem: &ForeignItem,
1205 index: &mut Vec<entry<i64>>,
1206 path: PathElems,
1207 abi: abi::Abi) {
1208 index.push(entry {
1209 val: nitem.id as i64,
1210 pos: ebml_w.writer.tell().unwrap(),
1211 });
1212
1213 ebml_w.start_tag(tag_items_data_item);
1214 encode_def_id(ebml_w, local_def(nitem.id));
1215 match nitem.node {
1216 ForeignItemFn(..) => {
1217 encode_family(ebml_w, style_fn_family(NormalFn));
1218 encode_bounds_and_type(ebml_w, ecx,
1219 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1220 encode_name(ebml_w, nitem.ident.name);
1221 if abi == abi::RustIntrinsic {
1222 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1223 } else {
1224 encode_symbol(ecx, ebml_w, nitem.id);
1225 }
1226 }
1227 ForeignItemStatic(_, mutbl) => {
1228 if mutbl {
1229 encode_family(ebml_w, 'b');
1230 } else {
1231 encode_family(ebml_w, 'c');
1232 }
1233 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1234 encode_symbol(ecx, ebml_w, nitem.id);
1235 encode_name(ebml_w, nitem.ident.name);
1236 }
1237 }
1238 encode_path(ebml_w, path);
1239 ebml_w.end_tag();
1240 }
1241
1242 fn my_visit_expr(_e: &Expr) { }
1243
1244 fn my_visit_item(i: &Item,
1245 ebml_w: &mut Encoder,
1246 ecx_ptr: *int,
1247 index: &mut Vec<entry<i64>>) {
1248 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1249 // See above
1250 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1251 ecx.tcx.map.with_path(i.id, |path| {
1252 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1253 });
1254 }
1255
1256 fn my_visit_foreign_item(ni: &ForeignItem,
1257 ebml_w: &mut Encoder,
1258 ecx_ptr:*int,
1259 index: &mut Vec<entry<i64>>) {
1260 // See above
1261 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1262 debug!("writing foreign item {}::{}",
1263 ecx.tcx.map.path_to_str(ni.id),
1264 token::get_ident(ni.ident));
1265
1266 let mut ebml_w = unsafe {
1267 ebml_w.unsafe_clone()
1268 };
1269 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1270 ecx.tcx.map.with_path(ni.id, |path| {
1271 encode_info_for_foreign_item(ecx, &mut ebml_w,
1272 ni, index,
1273 path, abi);
1274 });
1275 }
1276
1277 struct EncodeVisitor<'a,'b> {
1278 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1279 ecx_ptr:*int,
1280 index: &'a mut Vec<entry<i64>>,
1281 }
1282
1283 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1284 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1285 visit::walk_expr(self, ex, ());
1286 my_visit_expr(ex);
1287 }
1288 fn visit_item(&mut self, i: &Item, _: ()) {
1289 visit::walk_item(self, i, ());
1290 my_visit_item(i,
1291 self.ebml_w_for_visit_item,
1292 self.ecx_ptr,
1293 self.index);
1294 }
1295 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1296 visit::walk_foreign_item(self, ni, ());
1297 my_visit_foreign_item(ni,
1298 self.ebml_w_for_visit_item,
1299 self.ecx_ptr,
1300 self.index);
1301 }
1302 }
1303
1304 fn encode_info_for_items(ecx: &EncodeContext,
1305 ebml_w: &mut Encoder,
1306 krate: &Crate)
1307 -> Vec<entry<i64>> {
1308 let mut index = Vec::new();
1309 ebml_w.start_tag(tag_items_data);
1310 index.push(entry {
1311 val: CRATE_NODE_ID as i64,
1312 pos: ebml_w.writer.tell().unwrap(),
1313 });
1314 encode_info_for_mod(ecx,
1315 ebml_w,
1316 &krate.module,
1317 CRATE_NODE_ID,
1318 ast_map::Values([].iter()).chain(None),
1319 syntax::parse::token::special_idents::invalid,
1320 Public);
1321
1322 // See comment in `encode_side_tables_for_ii` in astencode
1323 let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
1324 visit::walk_crate(&mut EncodeVisitor {
1325 index: &mut index,
1326 ecx_ptr: ecx_ptr,
1327 ebml_w_for_visit_item: &mut *ebml_w,
1328 }, krate, ());
1329
1330 ebml_w.end_tag();
1331 index
1332 }
1333
1334
1335 // Path and definition ID indexing
1336
1337 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1338 write_fn: |&mut MemWriter, &T|) {
1339 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1340 for elt in index.move_iter() {
1341 let h = hash::hash(&elt.val) as uint;
1342 buckets.get_mut(h % 256).push(elt);
1343 }
1344
1345 ebml_w.start_tag(tag_index);
1346 let mut bucket_locs = Vec::new();
1347 ebml_w.start_tag(tag_index_buckets);
1348 for bucket in buckets.iter() {
1349 bucket_locs.push(ebml_w.writer.tell().unwrap());
1350 ebml_w.start_tag(tag_index_buckets_bucket);
1351 for elt in bucket.iter() {
1352 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1353 assert!(elt.pos < 0xffff_ffff);
1354 {
1355 let wr: &mut MemWriter = ebml_w.writer;
1356 wr.write_be_u32(elt.pos as u32);
1357 }
1358 write_fn(ebml_w.writer, &elt.val);
1359 ebml_w.end_tag();
1360 }
1361 ebml_w.end_tag();
1362 }
1363 ebml_w.end_tag();
1364 ebml_w.start_tag(tag_index_table);
1365 for pos in bucket_locs.iter() {
1366 assert!(*pos < 0xffff_ffff);
1367 let wr: &mut MemWriter = ebml_w.writer;
1368 wr.write_be_u32(*pos as u32);
1369 }
1370 ebml_w.end_tag();
1371 ebml_w.end_tag();
1372 }
1373
1374 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1375 let wr: &mut MemWriter = writer;
1376 assert!(n < 0x7fff_ffff);
1377 wr.write_be_u32(n as u32);
1378 }
1379
1380 fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
1381 match mi.node {
1382 MetaWord(ref name) => {
1383 ebml_w.start_tag(tag_meta_item_word);
1384 ebml_w.start_tag(tag_meta_item_name);
1385 ebml_w.writer.write(name.get().as_bytes());
1386 ebml_w.end_tag();
1387 ebml_w.end_tag();
1388 }
1389 MetaNameValue(ref name, ref value) => {
1390 match value.node {
1391 LitStr(ref value, _) => {
1392 ebml_w.start_tag(tag_meta_item_name_value);
1393 ebml_w.start_tag(tag_meta_item_name);
1394 ebml_w.writer.write(name.get().as_bytes());
1395 ebml_w.end_tag();
1396 ebml_w.start_tag(tag_meta_item_value);
1397 ebml_w.writer.write(value.get().as_bytes());
1398 ebml_w.end_tag();
1399 ebml_w.end_tag();
1400 }
1401 _ => {/* FIXME (#623): encode other variants */ }
1402 }
1403 }
1404 MetaList(ref name, ref items) => {
1405 ebml_w.start_tag(tag_meta_item_list);
1406 ebml_w.start_tag(tag_meta_item_name);
1407 ebml_w.writer.write(name.get().as_bytes());
1408 ebml_w.end_tag();
1409 for inner_item in items.iter() {
1410 encode_meta_item(ebml_w, *inner_item);
1411 }
1412 ebml_w.end_tag();
1413 }
1414 }
1415 }
1416
1417 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1418 ebml_w.start_tag(tag_attributes);
1419 for attr in attrs.iter() {
1420 ebml_w.start_tag(tag_attribute);
1421 encode_meta_item(ebml_w, attr.node.value);
1422 ebml_w.end_tag();
1423 }
1424 ebml_w.end_tag();
1425 }
1426
1427 // So there's a special crate attribute called 'crate_id' which defines the
1428 // metadata that Rust cares about for linking crates. If the user didn't
1429 // provide it we will throw it in anyway with a default value.
1430 fn synthesize_crate_attrs(ecx: &EncodeContext,
1431 krate: &Crate) -> Vec<Attribute> {
1432
1433 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1434 assert!(!ecx.link_meta.crateid.name.is_empty());
1435
1436 attr::mk_attr(
1437 attr::mk_name_value_item_str(
1438 InternedString::new("crate_id"),
1439 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1440 }
1441
1442 let mut attrs = Vec::new();
1443 for attr in krate.attrs.iter() {
1444 if !attr.name().equiv(&("crate_id")) {
1445 attrs.push(*attr);
1446 }
1447 }
1448 attrs.push(synthesize_crateid_attr(ecx));
1449
1450 attrs
1451 }
1452
1453 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1454 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1455 // Pull the cnums and name,vers,hash out of cstore
1456 let mut deps = Vec::new();
1457 cstore.iter_crate_data(|key, val| {
1458 let dep = decoder::CrateDep {
1459 cnum: key,
1460 crate_id: decoder::get_crate_id(val.data()),
1461 hash: decoder::get_crate_hash(val.data())
1462 };
1463 deps.push(dep);
1464 });
1465
1466 // Sort by cnum
1467 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1468
1469 // Sanity-check the crate numbers
1470 let mut expected_cnum = 1;
1471 for n in deps.iter() {
1472 assert_eq!(n.cnum, expected_cnum);
1473 expected_cnum += 1;
1474 }
1475
1476 deps
1477 }
1478
1479 // We're just going to write a list of crate 'name-hash-version's, with
1480 // the assumption that they are numbered 1 to n.
1481 // FIXME (#2166): This is not nearly enough to support correct versioning
1482 // but is enough to get transitive crate dependencies working.
1483 ebml_w.start_tag(tag_crate_deps);
1484 let r = get_ordered_deps(cstore);
1485 for dep in r.iter() {
1486 encode_crate_dep(ebml_w, (*dep).clone());
1487 }
1488 ebml_w.end_tag();
1489 }
1490
1491 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1492 ebml_w.start_tag(tag_lang_items);
1493
1494 for (i, def_id) in ecx.tcx.lang_items.items() {
1495 for id in def_id.iter() {
1496 if id.krate == LOCAL_CRATE {
1497 ebml_w.start_tag(tag_lang_items_item);
1498
1499 ebml_w.start_tag(tag_lang_items_item_id);
1500 {
1501 let wr: &mut MemWriter = ebml_w.writer;
1502 wr.write_be_u32(i as u32);
1503 }
1504 ebml_w.end_tag(); // tag_lang_items_item_id
1505
1506 ebml_w.start_tag(tag_lang_items_item_node_id);
1507 {
1508 let wr: &mut MemWriter = ebml_w.writer;
1509 wr.write_be_u32(id.node as u32);
1510 }
1511 ebml_w.end_tag(); // tag_lang_items_item_node_id
1512
1513 ebml_w.end_tag(); // tag_lang_items_item
1514 }
1515 }
1516 }
1517
1518 ebml_w.end_tag(); // tag_lang_items
1519 }
1520
1521 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1522 ebml_w.start_tag(tag_native_libraries);
1523
1524 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1525 .borrow().iter() {
1526 match kind {
1527 cstore::NativeStatic => {} // these libraries are not propagated
1528 cstore::NativeFramework | cstore::NativeUnknown => {
1529 ebml_w.start_tag(tag_native_libraries_lib);
1530
1531 ebml_w.start_tag(tag_native_libraries_kind);
1532 ebml_w.writer.write_be_u32(kind as u32);
1533 ebml_w.end_tag();
1534
1535 ebml_w.start_tag(tag_native_libraries_name);
1536 ebml_w.writer.write(lib.as_bytes());
1537 ebml_w.end_tag();
1538
1539 ebml_w.end_tag();
1540 }
1541 }
1542 }
1543
1544 ebml_w.end_tag();
1545 }
1546
1547 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1548 match ecx.tcx.sess.macro_registrar_fn.get() {
1549 Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
1550 None => {}
1551 }
1552 }
1553
1554 struct MacroDefVisitor<'a, 'b, 'c> {
1555 ecx: &'a EncodeContext<'b>,
1556 ebml_w: &'a mut Encoder<'c>
1557 }
1558
1559 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1560 fn visit_item(&mut self, item: &Item, _: ()) {
1561 match item.node {
1562 ItemMac(..) => {
1563 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1564 .expect("Unable to find source for macro");
1565 self.ebml_w.start_tag(tag_macro_def);
1566 self.ebml_w.wr_str(def.as_slice());
1567 self.ebml_w.end_tag();
1568 }
1569 _ => {}
1570 }
1571 visit::walk_item(self, item, ());
1572 }
1573 }
1574
1575 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1576 krate: &Crate,
1577 ebml_w: &'a mut Encoder) {
1578 ebml_w.start_tag(tag_exported_macros);
1579 {
1580 let mut visitor = MacroDefVisitor {
1581 ecx: ecx,
1582 ebml_w: ebml_w,
1583 };
1584 visit::walk_crate(&mut visitor, krate, ());
1585 }
1586 ebml_w.end_tag();
1587 }
1588
1589 struct ImplVisitor<'a,'b,'c> {
1590 ecx: &'a EncodeContext<'b>,
1591 ebml_w: &'a mut Encoder<'c>,
1592 }
1593
1594 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1595 fn visit_item(&mut self, item: &Item, _: ()) {
1596 match item.node {
1597 ItemImpl(_, Some(ref trait_ref), _, _) => {
1598 let def_map = &self.ecx.tcx.def_map;
1599 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1600 let def_id = ast_util::def_id_of_def(trait_def);
1601
1602 // Load eagerly if this is an implementation of the Drop trait
1603 // or if the trait is not defined in this crate.
1604 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1605 def_id.krate != LOCAL_CRATE {
1606 self.ebml_w.start_tag(tag_impls_impl);
1607 encode_def_id(self.ebml_w, local_def(item.id));
1608 self.ebml_w.end_tag();
1609 }
1610 }
1611 _ => {}
1612 }
1613 visit::walk_item(self, item, ());
1614 }
1615 }
1616
1617 /// Encodes implementations that are eagerly loaded.
1618 ///
1619 /// None of this is necessary in theory; we can load all implementations
1620 /// lazily. However, in two cases the optimizations to lazily load
1621 /// implementations are not yet implemented. These two cases, which require us
1622 /// to load implementations eagerly, are:
1623 ///
1624 /// * Destructors (implementations of the Drop trait).
1625 ///
1626 /// * Implementations of traits not defined in this crate.
1627 fn encode_impls<'a>(ecx: &'a EncodeContext,
1628 krate: &Crate,
1629 ebml_w: &'a mut Encoder) {
1630 ebml_w.start_tag(tag_impls);
1631
1632 {
1633 let mut visitor = ImplVisitor {
1634 ecx: ecx,
1635 ebml_w: ebml_w,
1636 };
1637 visit::walk_crate(&mut visitor, krate, ());
1638 }
1639
1640 ebml_w.end_tag();
1641 }
1642
1643 fn encode_misc_info(ecx: &EncodeContext,
1644 krate: &Crate,
1645 ebml_w: &mut Encoder) {
1646 ebml_w.start_tag(tag_misc_info);
1647 ebml_w.start_tag(tag_misc_info_crate_items);
1648 for &item in krate.module.items.iter() {
1649 ebml_w.start_tag(tag_mod_child);
1650 ebml_w.wr_str(def_to_str(local_def(item.id)));
1651 ebml_w.end_tag();
1652
1653 each_auxiliary_node_id(item, |auxiliary_node_id| {
1654 ebml_w.start_tag(tag_mod_child);
1655 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1656 ebml_w.end_tag();
1657 true
1658 });
1659 }
1660
1661 // Encode reexports for the root module.
1662 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1663
1664 ebml_w.end_tag();
1665 ebml_w.end_tag();
1666 }
1667
1668 fn encode_crate_dep(ebml_w: &mut Encoder,
1669 dep: decoder::CrateDep) {
1670 ebml_w.start_tag(tag_crate_dep);
1671 ebml_w.start_tag(tag_crate_dep_crateid);
1672 ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1673 ebml_w.end_tag();
1674 ebml_w.start_tag(tag_crate_dep_hash);
1675 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1676 ebml_w.end_tag();
1677 ebml_w.end_tag();
1678 }
1679
1680 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1681 ebml_w.start_tag(tag_crate_hash);
1682 ebml_w.writer.write(hash.as_str().as_bytes());
1683 ebml_w.end_tag();
1684 }
1685
1686 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1687 ebml_w.start_tag(tag_crate_crateid);
1688 ebml_w.writer.write(crate_id.to_str().as_bytes());
1689 ebml_w.end_tag();
1690 }
1691
1692 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1693 ebml_w.start_tag(tag_crate_triple);
1694 ebml_w.writer.write(triple.as_bytes());
1695 ebml_w.end_tag();
1696 }
1697
1698 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1699 ebml_w.start_tag(tag_dylib_dependency_formats);
1700 match ecx.tcx.dependency_formats.borrow().find(&session::CrateTypeDylib) {
1701 Some(arr) => {
1702 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1703 slot.map(|kind| format!("{}:{}", i + 1, match kind {
1704 cstore::RequireDynamic => "d",
1705 cstore::RequireStatic => "s",
1706 }))
1707 }).collect::<Vec<~str>>();
1708 ebml_w.writer.write(s.connect(",").as_bytes());
1709 }
1710 None => {}
1711 }
1712 ebml_w.end_tag();
1713 }
1714
1715 // NB: Increment this as you change the metadata encoding version.
1716 pub static metadata_encoding_version : &'static [u8] =
1717 &[0x72, //'r' as u8,
1718 0x75, //'u' as u8,
1719 0x73, //'s' as u8,
1720 0x74, //'t' as u8,
1721 0, 0, 0, 1 ];
1722
1723 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1724 let mut wr = MemWriter::new();
1725 encode_metadata_inner(&mut wr, parms, krate);
1726 wr.unwrap().move_iter().collect()
1727 }
1728
1729 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1730 struct Stats {
1731 attr_bytes: u64,
1732 dep_bytes: u64,
1733 lang_item_bytes: u64,
1734 native_lib_bytes: u64,
1735 macro_registrar_fn_bytes: u64,
1736 macro_defs_bytes: u64,
1737 impl_bytes: u64,
1738 misc_bytes: u64,
1739 item_bytes: u64,
1740 index_bytes: u64,
1741 zero_bytes: u64,
1742 total_bytes: u64,
1743 }
1744 let mut stats = Stats {
1745 attr_bytes: 0,
1746 dep_bytes: 0,
1747 lang_item_bytes: 0,
1748 native_lib_bytes: 0,
1749 macro_registrar_fn_bytes: 0,
1750 macro_defs_bytes: 0,
1751 impl_bytes: 0,
1752 misc_bytes: 0,
1753 item_bytes: 0,
1754 index_bytes: 0,
1755 zero_bytes: 0,
1756 total_bytes: 0,
1757 };
1758 let EncodeParams {
1759 item_symbols,
1760 diag,
1761 tcx,
1762 reexports2,
1763 cstore,
1764 encode_inlined_item,
1765 link_meta,
1766 non_inlineable_statics,
1767 ..
1768 } = parms;
1769 let ecx = EncodeContext {
1770 diag: diag,
1771 tcx: tcx,
1772 reexports2: reexports2,
1773 item_symbols: item_symbols,
1774 non_inlineable_statics: non_inlineable_statics,
1775 link_meta: link_meta,
1776 cstore: cstore,
1777 encode_inlined_item: RefCell::new(encode_inlined_item),
1778 type_abbrevs: RefCell::new(HashMap::new()),
1779 };
1780
1781 let mut ebml_w = writer::Encoder(wr);
1782
1783 encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1784 encode_crate_triple(&mut ebml_w, tcx.sess.targ_cfg.target_strs.target_triple);
1785 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1786 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1787
1788 let mut i = ebml_w.writer.tell().unwrap();
1789 let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1790 encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1791 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1792
1793 i = ebml_w.writer.tell().unwrap();
1794 encode_crate_deps(&mut ebml_w, ecx.cstore);
1795 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1796
1797 // Encode the language items.
1798 i = ebml_w.writer.tell().unwrap();
1799 encode_lang_items(&ecx, &mut ebml_w);
1800 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1801
1802 // Encode the native libraries used
1803 i = ebml_w.writer.tell().unwrap();
1804 encode_native_libraries(&ecx, &mut ebml_w);
1805 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1806
1807 // Encode the macro registrar function
1808 i = ebml_w.writer.tell().unwrap();
1809 encode_macro_registrar_fn(&ecx, &mut ebml_w);
1810 stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1811
1812 // Encode macro definitions
1813 i = ebml_w.writer.tell().unwrap();
1814 encode_macro_defs(&ecx, krate, &mut ebml_w);
1815 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1816
1817 // Encode the def IDs of impls, for coherence checking.
1818 i = ebml_w.writer.tell().unwrap();
1819 encode_impls(&ecx, krate, &mut ebml_w);
1820 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1821
1822 // Encode miscellaneous info.
1823 i = ebml_w.writer.tell().unwrap();
1824 encode_misc_info(&ecx, krate, &mut ebml_w);
1825 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1826
1827 // Encode and index the items.
1828 ebml_w.start_tag(tag_items);
1829 i = ebml_w.writer.tell().unwrap();
1830 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1831 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1832
1833 i = ebml_w.writer.tell().unwrap();
1834 encode_index(&mut ebml_w, items_index, write_i64);
1835 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1836 ebml_w.end_tag();
1837
1838 stats.total_bytes = ebml_w.writer.tell().unwrap();
1839
1840 if tcx.sess.meta_stats() {
1841 for e in ebml_w.writer.get_ref().iter() {
1842 if *e == 0 {
1843 stats.zero_bytes += 1;
1844 }
1845 }
1846
1847 println!("metadata stats:");
1848 println!(" attribute bytes: {}", stats.attr_bytes);
1849 println!(" dep bytes: {}", stats.dep_bytes);
1850 println!(" lang item bytes: {}", stats.lang_item_bytes);
1851 println!(" native bytes: {}", stats.native_lib_bytes);
1852 println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
1853 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1854 println!(" impl bytes: {}", stats.impl_bytes);
1855 println!(" misc bytes: {}", stats.misc_bytes);
1856 println!(" item bytes: {}", stats.item_bytes);
1857 println!(" index bytes: {}", stats.index_bytes);
1858 println!(" zero bytes: {}", stats.zero_bytes);
1859 println!(" total bytes: {}", stats.total_bytes);
1860 }
1861 }
1862
1863 // Get the encoded string for a type
1864 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> ~str {
1865 let mut wr = MemWriter::new();
1866 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1867 diag: tcx.sess.diagnostic(),
1868 ds: def_to_str,
1869 tcx: tcx,
1870 abbrevs: &RefCell::new(HashMap::new())
1871 }, t);
1872 str::from_utf8_owned(wr.get_ref().to_owned()).unwrap()
1873 }
librustc/metadata/encoder.rs:215:1-215:1 -fn- definition:
fn encode_type(ecx: &EncodeContext,
ebml_w: &mut Encoder,
typ: ty::t) {
references:- 5673: encode_name(ebml_w, nm);
674: encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
675: encode_def_id(ebml_w, local_def(id));
--
697: encode_name(ebml_w, name.name);
698: encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
699: ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
--
1232: }
1233: encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1234: encode_symbol(ecx, ebml_w, nitem.id);
librustc/metadata/encoder.rs:793:1-793:1 -fn- definition:
fn fn_style_static_method_family(s: FnStyle) -> char {
match s {
UnsafeFn => 'U',
references:- 2728: ast::SelfStatic => {
729: encode_family(ebml_w, fn_style_static_method_family(fn_style));
730: }
--
1154: encode_family(ebml_w,
1155: fn_style_static_method_family(
1156: method_ty.fty.fn_style));
librustc/metadata/encoder.rs:648:46-648:46 -fn- definition:
/* Returns an index of items in this class */
fn encode_info_for_struct(ecx: &EncodeContext,
ebml_w: &mut Encoder,
references:- 2328: let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
329: let idx = encode_info_for_struct(ecx,
330: ebml_w,
--
986: class itself */
987: let idx = encode_info_for_struct(ecx,
988: ebml_w,
librustc/metadata/encoder.rs:860:4-860:4 -fn- definition:
fn add_to_index(item: &Item, ebml_w: &Encoder,
index: &mut Vec<entry<i64>>) {
index.push(entry {
references:- 9992: /* Index the class*/
993: add_to_index(item, ebml_w, index);
--
1036: add_to_index(item, ebml_w, index);
1037: ebml_w.start_tag(tag_items_data_item);
--
1090: ItemTrait(_, sized, ref super_traits, ref ms) => {
1091: add_to_index(item, ebml_w, index);
1092: ebml_w.start_tag(tag_items_data_item);
librustc/metadata/encoder.rs:62:1-62:1 -NK_AS_STR_TODO- definition:
pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
ebml_w: &mut Encoder,
references:- 65librustc/metadata/encoder.rs:141:1-141:1 -fn- definition:
pub fn def_to_str(did: DefId) -> ~str {
format!("{}:{}", did.krate, did.node)
}
references:- 22933: ebml_w.start_tag(tag_mod_child);
934: ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
935: ebml_w.end_tag();
--
1113: ebml_w.start_tag(tag_mod_child);
1114: ebml_w.wr_str(def_to_str(method_def_id));
1115: ebml_w.end_tag();
--
1867: diag: tcx.sess.diagnostic(),
1868: ds: def_to_str,
1869: tcx: tcx,
librustc/middle/astencode.rs:
782: diag: self.tcx.sess.diagnostic(),
783: ds: e::def_to_str,
784: tcx: self.tcx,
librustc/metadata/encoder.rs:
568: ebml_w.start_tag(tag_mod_impl);
569: ebml_w.wr_str(def_to_str(local_def(did)));
570: ebml_w.end_tag();
librustc/metadata/encoder.rs:99:1-99:1 -fn- definition:
pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
}
references:- 19692: ebml_w.start_tag(tag_items_data_item);
693: encode_def_id(ebml_w, local_def(ctor_id));
694: encode_family(ebml_w, 'f');
--
1213: ebml_w.start_tag(tag_items_data_item);
1214: encode_def_id(ebml_w, local_def(nitem.id));
1215: match nitem.node {
--
1606: self.ebml_w.start_tag(tag_impls_impl);
1607: encode_def_id(self.ebml_w, local_def(item.id));
1608: self.ebml_w.end_tag();
librustc/metadata/encoder.rs:500:1-500:1 -fn- definition:
fn encode_reexports(ecx: &EncodeContext,
ebml_w: &mut Encoder,
id: NodeId,
references:- 21661: // Encode reexports for the root module.
1662: encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
librustc/metadata/encoder.rs:1336:1-1336:1 -fn- definition:
fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
write_fn: |&mut MemWriter, &T|) {
let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
references:- 3333: encode_struct_fields(ebml_w, fields.as_slice(), def_id);
334: encode_index(ebml_w, idx, write_i64);
335: }
--
1017: /* Each class has its own index -- encode it */
1018: encode_index(ebml_w, idx, write_i64);
1019: ebml_w.end_tag();
--
1833: i = ebml_w.writer.tell().unwrap();
1834: encode_index(&mut ebml_w, items_index, write_i64);
1835: stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
librustc/metadata/encoder.rs:91:1-91:1 -fn- definition:
fn encode_name(ebml_w: &mut Encoder, name: Name) {
ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
}
references:- 17543: encode_family(ebml_w, 'm');
544: encode_name(ebml_w, name.name);
545: debug!("(encoding info for module) encoding info for module ID {}", id);
--
1219: &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1220: encode_name(ebml_w, nitem.ident.name);
1221: if abi == abi::RustIntrinsic {
--
1234: encode_symbol(ecx, ebml_w, nitem.id);
1235: encode_name(ebml_w, nitem.ident.name);
1236: }
librustc/metadata/encoder.rs:104:19-104:19 -struct- definition:
struct entry<T> {
val: T,
pos: u64
references:- 26664: index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
665: global_index.push(entry {
--
1207: abi: abi::Abi) {
1208: index.push(entry {
1209: val: nitem.id as i64,
--
1309: ebml_w.start_tag(tag_items_data);
1310: index.push(entry {
1311: val: CRATE_NODE_ID as i64,
--
1338: write_fn: |&mut MemWriter, &T|) {
1339: let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1340: for elt in index.move_iter() {
librustc/metadata/encoder.rs:272:1-272:1 -fn- definition:
fn encode_struct_fields(ebml_w: &mut Encoder,
fields: &[ty::field_ty],
origin: DefId) {
references:- 2332: index);
333: encode_struct_fields(ebml_w, fields.as_slice(), def_id);
334: encode_index(ebml_w, idx, write_i64);
--
1009: needs to know*/
1010: encode_struct_fields(ebml_w, fields.as_slice(), def_id);
librustc/metadata/encoder.rs:350:1-350:1 -fn- definition:
fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
mut path: PI) {
ebml_w.start_tag(tag_path);
references:- 14576: encode_path(ebml_w, path.clone());
577: encode_visibility(ebml_w, vis);
--
1063: }
1064: encode_path(ebml_w, path.clone());
1065: ebml_w.end_tag();
--
1149: let elem = ast_map::PathName(method_ty.ident.name);
1150: encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
--
1237: }
1238: encode_path(ebml_w, path);
1239: ebml_w.end_tag();
librustc/metadata/encoder.rs:778:1-778:1 -fn- definition:
fn encode_inlined_item(ecx: &EncodeContext,
ebml_w: &mut Encoder,
ii: InlinedItemRef) {
references:- 71184: encode_method_sort(ebml_w, 'p');
1185: encode_inlined_item(ecx, ebml_w,
1186: IIMethodRef(def_id, true, m));
--
1221: if abi == abi::RustIntrinsic {
1222: encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1223: } else {
librustc/metadata/encoder.rs:587:1-587:1 -fn- definition:
fn encode_struct_field_family(ebml_w: &mut Encoder,
visibility: Visibility) {
encode_family(ebml_w, match visibility {
references:- 2282: }
283: encode_struct_field_family(ebml_w, f.vis);
284: encode_def_id(ebml_w, f.id);
--
671: token::get_name(nm), id);
672: encode_struct_field_family(ebml_w, field.vis);
673: encode_name(ebml_w, nm);
librustc/metadata/encoder.rs:1373:1-1373:1 -fn- definition:
fn write_i64(writer: &mut MemWriter, &n: &i64) {
let wr: &mut MemWriter = writer;
assert!(n < 0x7fff_ffff);
references:- 31833: i = ebml_w.writer.tell().unwrap();
1834: encode_index(&mut ebml_w, items_index, write_i64);
1835: stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
librustc/metadata/encoder.rs:1553:1-1553:1 -struct- definition:
struct MacroDefVisitor<'a, 'b, 'c> {
ecx: &'a EncodeContext<'b>,
ebml_w: &'a mut Encoder<'c>
references:- 21559: impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1560: fn visit_item(&mut self, item: &Item, _: ()) {
--
1579: {
1580: let mut visitor = MacroDefVisitor {
1581: ecx: ecx,
librustc/metadata/encoder.rs:364:1-364:1 -fn- definition:
fn encode_reexported_static_method(ebml_w: &mut Encoder,
exp: &middle::resolve::Export2,
method_def_id: DefId,
references:- 2391: if m.explicit_self == ast::SelfStatic {
392: encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
393: }
--
410: if m.explicit_self == ast::SelfStatic {
411: encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
412: }
librustc/metadata/encoder.rs:786:1-786:1 -fn- definition:
fn style_fn_family(s: FnStyle) -> char {
match s {
UnsafeFn => 'u',
references:- 4898: encode_def_id(ebml_w, def_id);
899: encode_family(ebml_w, style_fn_family(fn_style));
900: let tps_len = generics.ty_params.len();
--
1163: encode_family(ebml_w,
1164: style_fn_family(
1165: method_ty.fty.fn_style));
--
1216: ForeignItemFn(..) => {
1217: encode_family(ebml_w, style_fn_family(NormalFn));
1218: encode_bounds_and_type(ebml_w, ecx,
librustc/metadata/encoder.rs:56:44-56:44 -enum- definition:
/// A borrowed version of ast::InlinedItem.
pub enum InlinedItemRef<'a> {
IIItemRef(&'a ast::Item),
references:- 4780: ebml_w: &mut Encoder,
781: ii: InlinedItemRef) {
782: let mut eii = ecx.encode_inlined_item.borrow_mut();
librustc/middle/astencode.rs:
78: ebml_w: &mut Encoder,
79: ii: e::InlinedItemRef) {
80: let id = match ii {
--
337: // inlined items.
338: fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
339: let mut fld = NestedItemsDropper;
librustc/metadata/encoder.rs:
66: ebml_w: &mut Encoder,
67: ii: InlinedItemRef|: 'a;
librustc/metadata/encoder.rs:109:1-109:1 -fn- definition:
fn encode_trait_ref(ebml_w: &mut Encoder,
ecx: &EncodeContext,
trait_ref: &ty::TraitRef,
references:- 31122: let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1123: encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1124: }
librustc/metadata/encoder.rs:79:1-79:1 -struct- definition:
pub struct EncodeContext<'a> {
pub diag: &'a SpanHandler,
pub tcx: &'a ty::ctxt,
references:- 63librustc/middle/astencode.rs:
librustc/metadata/encoder.rs:145:1-145:1 -fn- definition:
fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
ecx: &EncodeContext,
params: &[ty::TypeParameterDef],
references:- 3719: encode_name(ebml_w, method_ty.ident.name);
720: encode_ty_type_param_defs(ebml_w, ecx,
721: method_ty.generics.type_param_defs(),
--
1096: let trait_def = ty::lookup_trait_def(tcx, def_id);
1097: encode_ty_type_param_defs(ebml_w, ecx,
1098: trait_def.generics.type_param_defs(),
librustc/metadata/encoder.rs:533:1-533:1 -fn- definition:
fn encode_info_for_mod(ecx: &EncodeContext,
ebml_w: &mut Encoder,
md: &Mod,
references:- 21313: });
1314: encode_info_for_mod(ecx,
1315: ebml_w,
librustc/metadata/encoder.rs:203:1-203:1 -fn- definition:
pub fn write_type(ecx: &EncodeContext,
ebml_w: &mut Encoder,
typ: ty::t) {
references:- 2librustc/middle/astencode.rs:
804: fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t) {
805: self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty)));
806: }
librustc/metadata/encoder.rs:
219: ebml_w.start_tag(tag_items_data_item_type);
220: write_type(ecx, ebml_w, typ);
221: ebml_w.end_tag();
librustc/metadata/encoder.rs:714:1-714:1 -fn- definition:
fn encode_method_ty_fields(ecx: &EncodeContext,
ebml_w: &mut Encoder,
method_ty: &ty::Method) {
references:- 21145: encode_method_ty_fields(ecx, ebml_w, &*method_ty);
librustc/metadata/encoder.rs:473:76-473:76 -fn- definition:
/// * For newtype structs, iterates through the node ID of the constructor.
fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
let mut continue_ = true;
references:- 2553: each_auxiliary_node_id(*item, |auxiliary_node_id| {
554: ebml_w.start_tag(tag_mod_child);
--
1653: each_auxiliary_node_id(item, |auxiliary_node_id| {
1654: ebml_w.start_tag(tag_mod_child);
librustc/metadata/encoder.rs:68:1-68:1 -struct- definition:
pub struct EncodeParams<'a> {
pub diag: &'a SpanHandler,
pub tcx: &'a ty::ctxt,
references:- 51723: pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1724: let mut wr = MemWriter::new();
--
1757: };
1758: let EncodeParams {
1759: item_symbols,
librustc/middle/trans/base.rs:
2084: pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
2085: -> encoder::EncodeParams<'r> {
2086: encoder::EncodeParams {
2087: diag: cx.sess().diagnostic(),
librustc/metadata/encoder.rs:801:1-801:1 -fn- definition:
fn should_inline(attrs: &[Attribute]) -> bool {
use syntax::attr::*;
match find_inline_attr(attrs) {
references:- 2904: encode_attributes(ebml_w, item.attrs.as_slice());
905: if tps_len > 0u || should_inline(item.attrs.as_slice()) {
906: encode_inlined_item(ecx, ebml_w, IIItemRef(item));
librustc/metadata/encoder.rs:187:1-187:1 -fn- definition:
fn encode_bounds_and_type(ebml_w: &mut Encoder,
ecx: &EncodeContext,
tpt: &ty::ty_param_bounds_and_ty) {
references:- 11957: encode_item_variances(ebml_w, ecx, item.id);
958: encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
959: encode_name(ebml_w, item.ident.name);
--
1217: encode_family(ebml_w, style_fn_family(NormalFn));
1218: encode_bounds_and_type(ebml_w, ecx,
1219: &lookup_item_type(ecx.tcx,local_def(nitem.id)));
librustc/metadata/encoder.rs:178:1-178:1 -fn- definition:
fn encode_item_variances(ebml_w: &mut Encoder,
ecx: &EncodeContext,
id: ast::NodeId) {
references:- 31094: encode_family(ebml_w, 'I');
1095: encode_item_variances(ebml_w, ecx, item.id);
1096: let trait_def = ty::lookup_trait_def(tcx, def_id);
librustc/metadata/encoder.rs:135:28-135:28 -fn- definition:
// Item info table encoding
fn encode_family(ebml_w: &mut Encoder, c: char) {
ebml_w.start_tag(tag_items_data_item_family);
references:- 21877: if m == ast::MutMutable {
878: encode_family(ebml_w, 'b');
879: } else {
--
1228: if mutbl {
1229: encode_family(ebml_w, 'b');
1230: } else {
1231: encode_family(ebml_w, 'c');
1232: }
librustc/metadata/encoder.rs:631:1-631:1 -fn- definition:
fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
ebml_w.start_tag(tag_item_trait_method_sort);
ebml_w.writer.write(&[ sort as u8 ]);
references:- 21171: encode_attributes(ebml_w, tm.attrs.as_slice());
1172: encode_method_sort(ebml_w, 'r');
1173: }
--
1183: }
1184: encode_method_sort(ebml_w, 'p');
1185: encode_inlined_item(ecx, ebml_w,
librustc/metadata/encoder.rs:1276:1-1276:1 -struct- definition:
struct EncodeVisitor<'a,'b> {
ebml_w_for_visit_item: &'a mut Encoder<'b>,
ecx_ptr:*int,
references:- 21323: let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
1324: visit::walk_crate(&mut EncodeVisitor {
1325: index: &mut index,
librustc/metadata/encoder.rs:239:1-239:1 -fn- definition:
fn encode_symbol(ecx: &EncodeContext,
ebml_w: &mut Encoder,
id: NodeId) {
references:- 7323: if args.len() > 0 && generics.ty_params.len() == 0 => {
324: encode_symbol(ecx, ebml_w, variant.node.id);
325: }
--
882: encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
883: encode_symbol(ecx, ebml_w, item.id);
884: encode_name(ebml_w, item.ident.name);
--
1233: encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1234: encode_symbol(ecx, ebml_w, nitem.id);
1235: encode_name(ebml_w, nitem.ident.name);
librustc/metadata/encoder.rs:810:79-810:79 -fn- definition:
// Encodes the inherent implementations of a structure, enumeration, or trait.
fn encode_inherent_implementations(ecx: &EncodeContext,
ebml_w: &mut Encoder,
references:- 31014: // Encode inherent implementations for this structure.
1015: encode_inherent_implementations(ecx, ebml_w, def_id);
--
1193: // Encode inherent implementations for this trait.
1194: encode_inherent_implementations(ecx, ebml_w, def_id);
1195: }
librustc/metadata/encoder.rs:64:1-64:1 -NK_AS_STR_TODO- definition:
pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
ebml_w: &mut Encoder,
ii: InlinedItemRef|: 'a;
references:- 576: pub cstore: &'a cstore::CStore,
77: pub encode_inlined_item: EncodeInlinedItem<'a>,
78: }
--
87: pub cstore: &'a cstore::CStore,
88: pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
89: pub type_abbrevs: tyencode::abbrev_map,
--
782: let mut eii = ecx.encode_inlined_item.borrow_mut();
783: let eii: &mut EncodeInlinedItem = &mut *eii;
784: (*eii)(ecx, ebml_w, ii)
librustc/middle/trans/base.rs:
2084: pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
2085: -> encoder::EncodeParams<'r> {
--
2108: let encode_inlined_item: encoder::EncodeInlinedItem =
2109: |ecx, ebml_w, ii| astencode::encode_inlined_item(ecx, ebml_w, ii);
librustc/metadata/encoder.rs:265:1-265:1 -fn- definition:
fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
ebml_w.start_tag(tag_items_data_parent_item);
let s = def_to_str(id);
references:- 4748: encode_method_ty_fields(ecx, ebml_w, m);
749: encode_parent_item(ebml_w, local_def(parent_id));
--
1147: encode_parent_item(ebml_w, def_id);
librustc/metadata/encoder.rs:595:1-595:1 -fn- definition:
fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
ebml_w.start_tag(tag_items_data_item_visibility);
let ch = match visibility {
references:- 10891: }
892: encode_visibility(ebml_w, vis);
893: ebml_w.end_tag();
--
936: }
937: encode_visibility(ebml_w, vis);
938: ebml_w.end_tag();
--
970: encode_visibility(ebml_w, vis);
971: ebml_w.end_tag();
--
1106: encode_sized(ebml_w, sized);
1107: encode_visibility(ebml_w, vis);
1108: for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
librustc/metadata/encoder.rs:162:1-162:1 -fn- definition:
fn encode_region_param_defs(ebml_w: &mut Encoder,
params: &[ty::RegionParameterDef]) {
for param in params.iter() {
references:- 2192: tag_items_data_item_ty_param_bounds);
193: encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
194: encode_type(ecx, ebml_w, tpt.ty);
--
1099: tag_items_data_item_ty_param_bounds);
1100: encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
1101: encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
librustc/metadata/encoder.rs:1588:1-1588:1 -struct- definition:
struct ImplVisitor<'a,'b,'c> {
ecx: &'a EncodeContext<'b>,
ebml_w: &'a mut Encoder<'c>,
references:- 21594: impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1595: fn visit_item(&mut self, item: &Item, _: ()) {
--
1632: {
1633: let mut visitor = ImplVisitor {
1634: ecx: ecx,
librustc/metadata/encoder.rs:1416:1-1416:1 -fn- definition:
fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
ebml_w.start_tag(tag_attributes);
for attr in attrs.iter() {
references:- 101002: encode_name(ebml_w, item.ident.name);
1003: encode_attributes(ebml_w, item.attrs.as_slice());
1004: encode_path(ebml_w, path.clone());
--
1041: encode_name(ebml_w, item.ident.name);
1042: encode_attributes(ebml_w, item.attrs.as_slice());
1043: match ty.node {
--
1170: &Required(ref tm) => {
1171: encode_attributes(ebml_w, tm.attrs.as_slice());
1172: encode_method_sort(ebml_w, 'r');
--
1789: let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1790: encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1791: stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
librustc/metadata/encoder.rs:1379:1-1379:1 -fn- definition:
fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
match mi.node {
MetaWord(ref name) => {
references:- 21420: ebml_w.start_tag(tag_attribute);
1421: encode_meta_item(ebml_w, attr.node.value);
1422: ebml_w.end_tag();