1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use c = metadata::common;
12 use cstore = metadata::cstore;
13 use driver::session::Session;
14 use e = metadata::encoder;
15 use metadata::decoder;
16 use metadata::encoder;
17 use metadata::tydecode;
18 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
19 use metadata::tyencode;
20 use middle::freevars::freevar_entry;
21 use middle::typeck::{method_origin, method_map_entry};
22 use middle::{ty, typeck, moves};
24 use util::ppaux::ty_to_str;
26 use std::ebml::reader;
29 use std::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers};
30 use std::serialize::{Decoder, Decodable};
33 use syntax::ast_util::inlined_item_utils;
35 use syntax::codemap::span;
40 use writer = std::ebml::writer;
42 #[cfg(test)] use syntax::parse;
43 #[cfg(test)] use syntax::print::pprust;
45 // Auxiliary maps of things to be encoded
47 mutbl_map: middle::borrowck::mutbl_map,
48 root_map: middle::borrowck::root_map,
49 last_use_map: middle::liveness::last_use_map,
50 method_map: middle::typeck::method_map,
51 vtable_map: middle::typeck::vtable_map,
52 write_guard_map: middle::borrowck::write_guard_map,
53 moves_map: middle::moves::MovesMap,
54 capture_map: middle::moves::CaptureMap,
57 struct DecodeContext {
58 cdata: @cstore::crate_metadata,
63 struct ExtendedDecodeContext {
65 from_id_range: ast_util::id_range,
66 to_id_range: ast_util::id_range
70 fn tr(&self, xcx: @ExtendedDecodeContext) -> Self;
74 fn tr_intern(&self, xcx: @ExtendedDecodeContext) -> ast::def_id;
77 // ______________________________________________________________________
81 pub fn encode_inlined_item(ecx: @e::EncodeContext,
82 ebml_w: &writer::Encoder,
83 path: &[ast_map::path_elt],
84 ii: ast::inlined_item,
86 debug!("> Encoding inlined item: %s::%s (%u)",
87 ast_map::path_to_str(path, ecx.tcx.sess.parse_sess.interner),
88 *ecx.tcx.sess.str_of(ii.ident()),
89 ebml_w.writer.tell());
91 let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
92 do ebml_w.wr_tag(c::tag_ast as uint) {
93 id_range.encode(ebml_w);
94 encode_ast(ebml_w, simplify_ast(&ii));
95 encode_side_tables_for_ii(ecx, maps, ebml_w, &ii);
98 debug!("< Encoded inlined fn: %s::%s (%u)",
99 ast_map::path_to_str(path, ecx.tcx.sess.parse_sess.interner),
100 *ecx.tcx.sess.str_of(ii.ident()),
101 ebml_w.writer.tell());
105 pub fn encode_inlined_item(ecx: @e::EncodeContext,
106 ebml_w: &mut writer::Encoder,
107 path: &[ast_map::path_elt],
108 ii: ast::inlined_item,
110 debug!("> Encoding inlined item: %s::%s (%u)",
111 ast_map::path_to_str(path, ecx.tcx.sess.parse_sess.interner),
112 *ecx.tcx.sess.str_of(ii.ident()),
113 ebml_w.writer.tell());
115 let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
117 ebml_w.start_tag(c::tag_ast as uint);
118 id_range.encode(ebml_w);
119 encode_ast(ebml_w, simplify_ast(&ii));
120 encode_side_tables_for_ii(ecx, maps, ebml_w, &ii);
123 debug!("< Encoded inlined fn: %s::%s (%u)",
124 ast_map::path_to_str(path, ecx.tcx.sess.parse_sess.interner),
125 *ecx.tcx.sess.str_of(ii.ident()),
126 ebml_w.writer.tell());
130 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
135 -> Option<ast::inlined_item> {
136 let dcx = @DecodeContext {
141 match par_doc.opt_child(c::tag_ast) {
144 debug!("> Decoding inlined fn: %s::?",
145 ast_map::path_to_str(path, tcx.sess.parse_sess.interner));
146 let ast_dsr = &reader::Decoder(ast_doc);
147 let from_id_range = Decodable::decode(ast_dsr);
148 let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range);
149 let xcx = @ExtendedDecodeContext {
151 from_id_range: from_id_range,
152 to_id_range: to_id_range
154 let raw_ii = decode_ast(ast_doc);
155 let ii = renumber_ast(xcx, raw_ii);
156 debug!("Fn named: %s", *tcx.sess.str_of(ii.ident()));
157 debug!("< Decoded inlined fn: %s::%s",
158 ast_map::path_to_str(path, tcx.sess.parse_sess.interner),
159 *tcx.sess.str_of(ii.ident()));
160 ast_map::map_decoded_item(tcx.sess.diagnostic(),
161 dcx.tcx.items, path, &ii);
162 decode_side_tables(xcx, ast_doc);
165 debug!(">>> DECODED ITEM >>>\n%s\n<<< DECODED ITEM <<<",
166 syntax::print::pprust::item_to_str(i, tcx.sess.intr()));
176 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
181 -> Option<ast::inlined_item> {
182 let dcx = @DecodeContext {
187 match par_doc.opt_child(c::tag_ast) {
190 debug!("> Decoding inlined fn: %s::?",
191 ast_map::path_to_str(path, tcx.sess.parse_sess.interner));
192 let mut ast_dsr = reader::Decoder(ast_doc);
193 let from_id_range = Decodable::decode(&mut ast_dsr);
194 let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range);
195 let xcx = @ExtendedDecodeContext {
197 from_id_range: from_id_range,
198 to_id_range: to_id_range
200 let raw_ii = decode_ast(ast_doc);
201 let ii = renumber_ast(xcx, raw_ii);
202 debug!("Fn named: %s", *tcx.sess.str_of(ii.ident()));
203 debug!("< Decoded inlined fn: %s::%s",
204 ast_map::path_to_str(path, tcx.sess.parse_sess.interner),
205 *tcx.sess.str_of(ii.ident()));
206 ast_map::map_decoded_item(tcx.sess.diagnostic(),
207 dcx.tcx.items, path, &ii);
208 decode_side_tables(xcx, ast_doc);
211 debug!(">>> DECODED ITEM >>>\n%s\n<<< DECODED ITEM <<<",
212 syntax::print::pprust::item_to_str(i, tcx.sess.intr()));
221 // ______________________________________________________________________
222 // Enumerating the IDs which appear in an AST
224 fn reserve_id_range(sess: Session,
225 from_id_range: ast_util::id_range) -> ast_util::id_range {
226 // Handle the case of an empty range:
227 if ast_util::empty(from_id_range) { return from_id_range; }
228 let cnt = from_id_range.max - from_id_range.min;
229 let to_id_min = sess.parse_sess.next_id;
230 let to_id_max = sess.parse_sess.next_id + cnt;
231 sess.parse_sess.next_id = to_id_max;
232 ast_util::id_range { min: to_id_min, max: to_id_min }
235 pub impl ExtendedDecodeContext {
236 fn tr_id(&self, id: ast::node_id) -> ast::node_id {
239 * Translates an internal id, meaning a node id that is known
240 * to refer to some part of the item currently being inlined,
241 * such as a local variable or argument. All naked node-ids
242 * that appear in types have this property, since if something
243 * might refer to an external item we would use a def-id to
244 * allow for the possibility that the item resides in another
248 // from_id_range should be non-empty
249 assert!(!ast_util::empty(self.from_id_range));
250 (id - self.from_id_range.min + self.to_id_range.min)
252 fn tr_def_id(&self, did: ast::def_id) -> ast::def_id {
255 * Translates an EXTERNAL def-id, converting the crate number
256 * from the one used in the encoded data to the current crate
257 * numbers.. By external, I mean that it be translated to a
258 * reference to the item in its original crate, as opposed to
259 * being translated to a reference to the inlined version of
260 * the item. This is typically, but not always, what you
261 * want, because most def-ids refer to external things like
262 * types or other fns that may or may not be inlined. Note
263 * that even when the inlined function is referencing itself
264 * recursively, we would want `tr_def_id` for that
265 * reference--- conceptually the function calls the original,
266 * non-inlined version, and trans deals with linking that
267 * recursive call to the inlined copy.
269 * However, there are a *few* cases where def-ids are used but
270 * we know that the thing being referenced is in fact *internal*
271 * to the item being inlined. In those cases, you should use
272 * `tr_intern_def_id()` below.
275 decoder::translate_def_id(self.dcx.cdata, did)
277 fn tr_intern_def_id(&self, did: ast::def_id) -> ast::def_id {
280 * Translates an INTERNAL def-id, meaning a def-id that is
281 * known to refer to some part of the item currently being
282 * inlined. In that case, we want to convert the def-id to
283 * refer to the current crate and to the new, inlined node-id.
286 assert!(did.crate == ast::local_crate);
287 ast::def_id { crate: ast::local_crate, node: self.tr_id(did.node) }
289 fn tr_span(&self, _span: span) -> span {
290 codemap::dummy_sp() // FIXME (#1972): handle span properly
294 impl tr_intern for ast::def_id {
295 fn tr_intern(&self, xcx: @ExtendedDecodeContext) -> ast::def_id {
296 xcx.tr_intern_def_id(*self)
300 impl tr for ast::def_id {
301 fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def_id {
307 fn tr(&self, xcx: @ExtendedDecodeContext) -> span {
313 trait def_id_encoder_helpers {
314 fn emit_def_id(&self, did: ast::def_id);
318 trait def_id_encoder_helpers {
319 fn emit_def_id(&mut self, did: ast::def_id);
323 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
324 fn emit_def_id(&self, did: ast::def_id) {
330 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
331 fn emit_def_id(&mut self, did: ast::def_id) {
337 trait def_id_decoder_helpers {
338 fn read_def_id(&self, xcx: @ExtendedDecodeContext) -> ast::def_id;
342 trait def_id_decoder_helpers {
343 fn read_def_id(&mut self, xcx: @ExtendedDecodeContext) -> ast::def_id;
347 impl<D:serialize::Decoder> def_id_decoder_helpers for D {
348 fn read_def_id(&self, xcx: @ExtendedDecodeContext) -> ast::def_id {
349 let did: ast::def_id = Decodable::decode(self);
355 impl<D:serialize::Decoder> def_id_decoder_helpers for D {
356 fn read_def_id(&mut self, xcx: @ExtendedDecodeContext) -> ast::def_id {
357 let did: ast::def_id = Decodable::decode(self);
362 // ______________________________________________________________________
363 // Encoding and decoding the AST itself
365 // The hard work is done by an autogenerated module astencode_gen. To
366 // regenerate astencode_gen, run src/etc/gen-astencode. It will
367 // replace astencode_gen with a dummy file and regenerate its
368 // contents. If you get compile errors, the dummy file
369 // remains---resolve the errors and then rerun astencode_gen.
370 // Annoying, I know, but hopefully only temporary.
372 // When decoding, we have to renumber the AST so that the node ids that
373 // appear within are disjoint from the node ids in our existing ASTs.
374 // We also have to adjust the spans: for now we just insert a dummy span,
375 // but eventually we should add entries to the local codemap as required.
378 fn encode_ast(ebml_w: &writer::Encoder, item: ast::inlined_item) {
379 do ebml_w.wr_tag(c::tag_tree as uint) {
385 fn encode_ast(ebml_w: &mut writer::Encoder, item: ast::inlined_item) {
386 ebml_w.start_tag(c::tag_tree as uint);
391 // Produces a simplified copy of the AST which does not include things
392 // that we do not need to or do not want to export. For example, we
393 // do not include any nested items: if these nested items are to be
394 // inlined, their AST will be exported separately (this only makes
395 // sense because, in Rust, nested items are independent except for
396 // their visibility).
398 // As it happens, trans relies on the fact that we do not export
399 // nested items, as otherwise it would get confused when translating
401 fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
402 fn drop_nested_items(blk: &ast::blk_, fld: @fold::ast_fold) -> ast::blk_ {
403 let stmts_sans_items = do blk.stmts.filtered |stmt| {
405 ast::stmt_expr(_, _) | ast::stmt_semi(_, _) |
406 ast::stmt_decl(@codemap::spanned { node: ast::decl_local(_),
407 span: _}, _) => true,
408 ast::stmt_decl(@codemap::spanned { node: ast::decl_item(_),
409 span: _}, _) => false,
410 ast::stmt_mac(*) => fail!(~"unexpanded macro in astencode")
413 let blk_sans_items = ast::blk_ {
414 view_items: ~[], // I don't know if we need the view_items here,
415 // but it doesn't break tests!
416 stmts: stmts_sans_items,
421 fold::noop_fold_block(&blk_sans_items, fld)
424 let fld = fold::make_fold(@fold::AstFoldFns {
425 fold_block: fold::wrap(drop_nested_items),
426 .. *fold::default_ast_fold()
431 ast::ii_item(fld.fold_item(i).get()) //hack: we're not dropping items
433 ast::ii_method(d, m) => {
434 ast::ii_method(d, fld.fold_method(m))
436 ast::ii_foreign(i) => {
437 ast::ii_foreign(fld.fold_foreign_item(i))
443 fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item {
444 let chi_doc = par_doc.get(c::tag_tree as uint);
445 let d = &reader::Decoder(chi_doc);
450 fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item {
451 let chi_doc = par_doc.get(c::tag_tree as uint);
452 let mut d = reader::Decoder(chi_doc);
453 Decodable::decode(&mut d)
456 fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
457 -> ast::inlined_item {
458 let fld = fold::make_fold(@fold::AstFoldFns{
459 new_id: |a| xcx.tr_id(a),
460 new_span: |a| xcx.tr_span(a),
461 .. *fold::default_ast_fold()
466 ast::ii_item(fld.fold_item(i).get())
468 ast::ii_method(d, m) => {
469 ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m))
471 ast::ii_foreign(i) => {
472 ast::ii_foreign(fld.fold_foreign_item(i))
477 // ______________________________________________________________________
478 // Encoding and decoding of ast::def
481 fn encode_def(ebml_w: &writer::Encoder, def: ast::def) {
486 fn encode_def(ebml_w: &mut writer::Encoder, def: ast::def) {
491 fn decode_def(xcx: @ExtendedDecodeContext, doc: ebml::Doc) -> ast::def {
492 let dsr = &reader::Decoder(doc);
493 let def: ast::def = Decodable::decode(dsr);
498 fn decode_def(xcx: @ExtendedDecodeContext, doc: ebml::Doc) -> ast::def {
499 let mut dsr = reader::Decoder(doc);
500 let def: ast::def = Decodable::decode(&mut dsr);
504 impl tr for ast::def {
505 fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def {
507 ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) }
508 ast::def_static_method(did, did2_opt, p) => {
509 ast::def_static_method(did.tr(xcx),
510 did2_opt.map(|did2| did2.tr(xcx)),
513 ast::def_self_ty(nid) => { ast::def_self_ty(xcx.tr_id(nid)) }
514 ast::def_self(nid, i) => { ast::def_self(xcx.tr_id(nid), i) }
515 ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
516 ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) }
517 ast::def_const(did) => { ast::def_const(did.tr(xcx)) }
518 ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) }
519 ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) }
520 ast::def_variant(e_did, v_did) => {
521 ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
523 ast::def_trait(did) => ast::def_trait(did.tr(xcx)),
524 ast::def_ty(did) => ast::def_ty(did.tr(xcx)),
525 ast::def_prim_ty(p) => ast::def_prim_ty(p),
526 ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
527 ast::def_binding(nid, bm) => ast::def_binding(xcx.tr_id(nid), bm),
528 ast::def_use(did) => ast::def_use(did.tr(xcx)),
529 ast::def_upvar(nid1, def, nid2, nid3) => {
530 ast::def_upvar(xcx.tr_id(nid1),
535 ast::def_struct(did) => {
536 ast::def_struct(did.tr(xcx))
538 ast::def_region(nid) => ast::def_region(xcx.tr_id(nid)),
539 ast::def_typaram_binder(nid) => {
540 ast::def_typaram_binder(xcx.tr_id(nid))
542 ast::def_label(nid) => ast::def_label(xcx.tr_id(nid))
547 // ______________________________________________________________________
548 // Encoding and decoding of adjustment information
550 impl tr for ty::AutoAdjustment {
551 fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment {
553 &ty::AutoAddEnv(r, s) => {
554 ty::AutoAddEnv(r.tr(xcx), s)
557 &ty::AutoDerefRef(ref adr) => {
558 ty::AutoDerefRef(ty::AutoDerefRef {
559 autoderefs: adr.autoderefs,
560 autoref: adr.autoref.map(|ar| ar.tr(xcx)),
567 impl tr for ty::AutoRef {
568 fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoRef {
571 region: self.region.tr(xcx),
577 impl tr for ty::Region {
578 fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region {
580 ty::re_bound(br) => ty::re_bound(br.tr(xcx)),
581 ty::re_scope(id) => ty::re_scope(xcx.tr_id(id)),
582 ty::re_static | ty::re_infer(*) => *self,
583 ty::re_free(ref fr) => {
584 ty::re_free(ty::FreeRegion {scope_id: xcx.tr_id(fr.scope_id),
585 bound_region: fr.bound_region.tr(xcx)})
591 impl tr for ty::bound_region {
592 fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::bound_region {
594 ty::br_anon(_) | ty::br_named(_) | ty::br_self |
595 ty::br_fresh(_) => *self,
596 ty::br_cap_avoid(id, br) => ty::br_cap_avoid(xcx.tr_id(id),
602 // ______________________________________________________________________
603 // Encoding and decoding of freevar information
606 fn encode_freevar_entry(ebml_w: &writer::Encoder, fv: @freevar_entry) {
611 fn encode_freevar_entry(ebml_w: &mut writer::Encoder, fv: @freevar_entry) {
616 trait ebml_decoder_helper {
617 fn read_freevar_entry(&self, xcx: @ExtendedDecodeContext)
622 trait ebml_decoder_helper {
623 fn read_freevar_entry(&mut self, xcx: @ExtendedDecodeContext)
628 impl ebml_decoder_helper for reader::Decoder {
629 fn read_freevar_entry(&self, xcx: @ExtendedDecodeContext)
631 let fv: freevar_entry = Decodable::decode(self);
637 impl ebml_decoder_helper for reader::Decoder {
638 fn read_freevar_entry(&mut self, xcx: @ExtendedDecodeContext)
640 let fv: freevar_entry = Decodable::decode(self);
645 impl tr for freevar_entry {
646 fn tr(&self, xcx: @ExtendedDecodeContext) -> freevar_entry {
648 def: self.def.tr(xcx),
649 span: self.span.tr(xcx),
654 // ______________________________________________________________________
655 // Encoding and decoding of CaptureVar information
658 trait capture_var_helper {
659 fn read_capture_var(&self, xcx: @ExtendedDecodeContext)
660 -> moves::CaptureVar;
664 trait capture_var_helper {
665 fn read_capture_var(&mut self, xcx: @ExtendedDecodeContext)
666 -> moves::CaptureVar;
670 impl capture_var_helper for reader::Decoder {
671 fn read_capture_var(&self, xcx: @ExtendedDecodeContext)
672 -> moves::CaptureVar {
673 let cvar: moves::CaptureVar = Decodable::decode(self);
679 impl capture_var_helper for reader::Decoder {
680 fn read_capture_var(&mut self, xcx: @ExtendedDecodeContext)
681 -> moves::CaptureVar {
682 let cvar: moves::CaptureVar = Decodable::decode(self);
687 impl tr for moves::CaptureVar {
688 fn tr(&self, xcx: @ExtendedDecodeContext) -> moves::CaptureVar {
690 def: self.def.tr(xcx),
691 span: self.span.tr(xcx),
697 // ______________________________________________________________________
698 // Encoding and decoding of method_map_entry
700 trait read_method_map_entry_helper {
702 fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext)
705 fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
710 fn encode_method_map_entry(ecx: @e::EncodeContext,
711 ebml_w: &writer::Encoder,
712 mme: method_map_entry) {
713 do ebml_w.emit_struct("method_map_entry", 3) {
714 do ebml_w.emit_field(~"self_arg", 0u) {
715 ebml_w.emit_arg(ecx, mme.self_arg);
717 do ebml_w.emit_field(~"explicit_self", 2u) {
718 mme.explicit_self.encode(ebml_w);
720 do ebml_w.emit_field(~"origin", 1u) {
721 mme.origin.encode(ebml_w);
723 do ebml_w.emit_field(~"self_mode", 3) {
724 mme.self_mode.encode(ebml_w);
730 fn encode_method_map_entry(ecx: @e::EncodeContext,
731 ebml_w: &mut writer::Encoder,
732 mme: method_map_entry) {
733 do ebml_w.emit_struct("method_map_entry", 3) |ebml_w| {
734 do ebml_w.emit_struct_field("self_arg", 0u) |ebml_w| {
735 ebml_w.emit_arg(ecx, mme.self_arg);
737 do ebml_w.emit_struct_field("explicit_self", 2u) |ebml_w| {
738 mme.explicit_self.encode(ebml_w);
740 do ebml_w.emit_struct_field("origin", 1u) |ebml_w| {
741 mme.origin.encode(ebml_w);
743 do ebml_w.emit_struct_field("self_mode", 3) |ebml_w| {
744 mme.self_mode.encode(ebml_w);
749 impl read_method_map_entry_helper for reader::Decoder {
751 fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext)
752 -> method_map_entry {
753 do self.read_struct("method_map_entry", 3) {
755 self_arg: self.read_field(~"self_arg", 0u, || {
758 explicit_self: self.read_field(~"explicit_self", 2u, || {
759 let self_type: ast::self_ty_ = Decodable::decode(self);
762 origin: self.read_field(~"origin", 1u, || {
763 let method_origin: method_origin =
764 Decodable::decode(self);
765 method_origin.tr(xcx)
767 self_mode: self.read_field(~"self_mode", 3, || {
768 let self_mode: ty::SelfMode = Decodable::decode(self);
776 fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
777 -> method_map_entry {
778 do self.read_struct("method_map_entry", 3) |this| {
780 self_arg: this.read_struct_field("self_arg", 0, |this| {
783 explicit_self: this.read_struct_field("explicit_self",
786 let self_type: ast::self_ty_ = Decodable::decode(this);
789 origin: this.read_struct_field("origin", 1, |this| {
790 let method_origin: method_origin =
791 Decodable::decode(this);
792 method_origin.tr(xcx)
794 self_mode: this.read_struct_field("self_mode", 3, |this| {
795 let self_mode: ty::SelfMode = Decodable::decode(this);
803 impl tr for method_origin {
804 fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
806 typeck::method_static(did) => {
807 typeck::method_static(did.tr(xcx))
809 typeck::method_param(ref mp) => {
810 typeck::method_param(
811 typeck::method_param {
812 trait_id: mp.trait_id.tr(xcx),
817 typeck::method_trait(did, m, vstore) => {
818 typeck::method_trait(did.tr(xcx), m, vstore)
820 typeck::method_self(did, m) => {
821 typeck::method_self(did.tr(xcx), m)
823 typeck::method_super(trait_did, m) => {
824 typeck::method_super(trait_did.tr(xcx), m)
830 // ______________________________________________________________________
831 // Encoding and decoding vtable_res
834 fn encode_vtable_res(ecx: @e::EncodeContext,
835 ebml_w: &writer::Encoder,
836 dr: typeck::vtable_res) {
837 // can't autogenerate this code because automatic code of
838 // ty::t doesn't work, and there is no way (atm) to have
839 // hand-written encoding routines combine with auto-generated
840 // ones. perhaps we should fix this.
841 do ebml_w.emit_from_vec(*dr) |vtable_origin| {
842 encode_vtable_origin(ecx, ebml_w, vtable_origin)
847 fn encode_vtable_res(ecx: @e::EncodeContext,
848 ebml_w: &mut writer::Encoder,
849 dr: typeck::vtable_res) {
850 // can't autogenerate this code because automatic code of
851 // ty::t doesn't work, and there is no way (atm) to have
852 // hand-written encoding routines combine with auto-generated
853 // ones. perhaps we should fix this.
854 do ebml_w.emit_from_vec(*dr) |ebml_w, vtable_origin| {
855 encode_vtable_origin(ecx, ebml_w, vtable_origin)
860 fn encode_vtable_origin(ecx: @e::EncodeContext,
861 ebml_w: &writer::Encoder,
862 vtable_origin: &typeck::vtable_origin) {
863 do ebml_w.emit_enum(~"vtable_origin") {
864 match *vtable_origin {
865 typeck::vtable_static(def_id, ref tys, vtable_res) => {
866 do ebml_w.emit_enum_variant(~"vtable_static", 0u, 3u) {
867 do ebml_w.emit_enum_variant_arg(0u) {
868 ebml_w.emit_def_id(def_id)
870 do ebml_w.emit_enum_variant_arg(1u) {
871 ebml_w.emit_tys(ecx, /*bad*/copy *tys);
873 do ebml_w.emit_enum_variant_arg(2u) {
874 encode_vtable_res(ecx, ebml_w, vtable_res);
878 typeck::vtable_param(pn, bn) => {
879 do ebml_w.emit_enum_variant(~"vtable_param", 1u, 2u) {
880 do ebml_w.emit_enum_variant_arg(0u) {
881 ebml_w.emit_uint(pn);
883 do ebml_w.emit_enum_variant_arg(1u) {
884 ebml_w.emit_uint(bn);
893 fn encode_vtable_origin(ecx: @e::EncodeContext,
894 ebml_w: &mut writer::Encoder,
895 vtable_origin: &typeck::vtable_origin) {
896 do ebml_w.emit_enum(~"vtable_origin") |ebml_w| {
897 match *vtable_origin {
898 typeck::vtable_static(def_id, ref tys, vtable_res) => {
899 do ebml_w.emit_enum_variant(~"vtable_static", 0u, 3u) |ebml_w| {
900 do ebml_w.emit_enum_variant_arg(0u) |ebml_w| {
901 ebml_w.emit_def_id(def_id)
903 do ebml_w.emit_enum_variant_arg(1u) |ebml_w| {
904 ebml_w.emit_tys(ecx, /*bad*/copy *tys);
906 do ebml_w.emit_enum_variant_arg(2u) |ebml_w| {
907 encode_vtable_res(ecx, ebml_w, vtable_res);
911 typeck::vtable_param(pn, bn) => {
912 do ebml_w.emit_enum_variant(~"vtable_param", 1u, 2u) |ebml_w| {
913 do ebml_w.emit_enum_variant_arg(0u) |ebml_w| {
914 ebml_w.emit_uint(pn);
916 do ebml_w.emit_enum_variant_arg(1u) |ebml_w| {
917 ebml_w.emit_uint(bn);
925 trait vtable_decoder_helpers {
927 fn read_vtable_res(&self, xcx: @ExtendedDecodeContext)
928 -> typeck::vtable_res;
930 fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
931 -> typeck::vtable_res;
933 fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
934 -> typeck::vtable_origin;
936 fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
937 -> typeck::vtable_origin;
940 impl vtable_decoder_helpers for reader::Decoder {
942 fn read_vtable_res(&self, xcx: @ExtendedDecodeContext)
943 -> typeck::vtable_res {
944 @self.read_to_vec(|| self.read_vtable_origin(xcx))
948 fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
949 -> typeck::vtable_res {
950 @self.read_to_vec(|this| this.read_vtable_origin(xcx))
954 fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
955 -> typeck::vtable_origin {
956 do self.read_enum("vtable_origin") {
957 do self.read_enum_variant(["vtable_static", "vtable_param"]) |i| {
960 typeck::vtable_static(
961 do self.read_enum_variant_arg(0u) {
962 self.read_def_id(xcx)
964 do self.read_enum_variant_arg(1u) {
967 do self.read_enum_variant_arg(2u) {
968 self.read_vtable_res(xcx)
973 typeck::vtable_param(
974 do self.read_enum_variant_arg(0u) {
977 do self.read_enum_variant_arg(1u) {
982 // hard to avoid - user input
983 _ => fail!(~"bad enum variant")
990 fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
991 -> typeck::vtable_origin {
992 do self.read_enum("vtable_origin") |this| {
993 do this.read_enum_variant(["vtable_static", "vtable_param"])
997 typeck::vtable_static(
998 do this.read_enum_variant_arg(0u) |this| {
999 this.read_def_id(xcx)
1001 do this.read_enum_variant_arg(1u) |this| {
1004 do this.read_enum_variant_arg(2u) |this| {
1005 this.read_vtable_res(xcx)
1010 typeck::vtable_param(
1011 do this.read_enum_variant_arg(0u) |this| {
1014 do this.read_enum_variant_arg(1u) |this| {
1019 // hard to avoid - user input
1020 _ => fail!(~"bad enum variant")
1027 // ______________________________________________________________________
1028 // Encoding and decoding the side tables
1030 trait get_ty_str_ctxt {
1031 fn ty_str_ctxt(@self) -> @tyencode::ctxt;
1034 impl get_ty_str_ctxt for e::EncodeContext {
1035 // IMPLICIT SELF WARNING: fix this!
1036 fn ty_str_ctxt(@self) -> @tyencode::ctxt {
1037 @tyencode::ctxt {diag: self.tcx.sess.diagnostic(),
1040 reachable: |a| encoder::reachable(self, a),
1041 abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)}
1046 trait ebml_writer_helpers {
1047 fn emit_arg(&self, ecx: @e::EncodeContext, arg: ty::arg);
1048 fn emit_ty(&self, ecx: @e::EncodeContext, ty: ty::t);
1049 fn emit_vstore(&self, ecx: @e::EncodeContext, vstore: ty::vstore);
1050 fn emit_tys(&self, ecx: @e::EncodeContext, tys: ~[ty::t]);
1051 fn emit_type_param_def(&self,
1052 ecx: @e::EncodeContext,
1053 type_param_def: &ty::TypeParameterDef);
1054 fn emit_tpbt(&self, ecx: @e::EncodeContext,
1055 tpbt: ty::ty_param_bounds_and_ty);
1059 trait ebml_writer_helpers {
1060 fn emit_arg(&mut self, ecx: @e::EncodeContext, arg: ty::arg);
1061 fn emit_ty(&mut self, ecx: @e::EncodeContext, ty: ty::t);
1062 fn emit_vstore(&mut self, ecx: @e::EncodeContext, vstore: ty::vstore);
1063 fn emit_tys(&mut self, ecx: @e::EncodeContext, tys: ~[ty::t]);
1064 fn emit_type_param_def(&mut self,
1065 ecx: @e::EncodeContext,
1066 type_param_def: &ty::TypeParameterDef);
1067 fn emit_tpbt(&mut self,
1068 ecx: @e::EncodeContext,
1069 tpbt: ty::ty_param_bounds_and_ty);
1072 impl ebml_writer_helpers for writer::Encoder {
1074 fn emit_ty(&self, ecx: @e::EncodeContext, ty: ty::t) {
1075 do self.emit_opaque {
1076 e::write_type(ecx, self, ty)
1081 fn emit_ty(&mut self, ecx: @e::EncodeContext, ty: ty::t) {
1082 do self.emit_opaque |this| {
1083 e::write_type(ecx, this, ty)
1088 fn emit_vstore(&self, ecx: @e::EncodeContext, vstore: ty::vstore) {
1089 do self.emit_opaque {
1090 e::write_vstore(ecx, self, vstore)
1095 fn emit_vstore(&mut self, ecx: @e::EncodeContext, vstore: ty::vstore) {
1096 do self.emit_opaque |this| {
1097 e::write_vstore(ecx, this, vstore)
1102 fn emit_arg(&self, ecx: @e::EncodeContext, arg: ty::arg) {
1103 do self.emit_opaque {
1104 tyencode::enc_arg(self.writer, ecx.ty_str_ctxt(), arg);
1109 fn emit_arg(&mut self, ecx: @e::EncodeContext, arg: ty::arg) {
1110 do self.emit_opaque |this| {
1111 tyencode::enc_arg(this.writer, ecx.ty_str_ctxt(), arg);
1116 fn emit_tys(&self, ecx: @e::EncodeContext, tys: ~[ty::t]) {
1117 do self.emit_from_vec(tys) |ty| {
1118 self.emit_ty(ecx, *ty)
1123 fn emit_tys(&mut self, ecx: @e::EncodeContext, tys: ~[ty::t]) {
1124 do self.emit_from_vec(tys) |this, ty| {
1125 this.emit_ty(ecx, *ty)
1130 fn emit_type_param_def(&self,
1131 ecx: @e::EncodeContext,
1132 type_param_def: &ty::TypeParameterDef) {
1133 do self.emit_opaque {
1134 tyencode::enc_type_param_def(self.writer, ecx.ty_str_ctxt(),
1140 fn emit_type_param_def(&mut self,
1141 ecx: @e::EncodeContext,
1142 type_param_def: &ty::TypeParameterDef) {
1143 do self.emit_opaque |this| {
1144 tyencode::enc_type_param_def(this.writer,
1152 ecx: @e::EncodeContext,
1153 tpbt: ty::ty_param_bounds_and_ty) {
1154 do self.emit_struct("ty_param_bounds_and_ty", 2) {
1155 do self.emit_field(~"generics", 0) {
1156 do self.emit_struct("Generics", 2) {
1157 do self.emit_field(~"type_param_defs", 0) {
1158 do self.emit_from_vec(*tpbt.generics.type_param_defs)
1160 self.emit_type_param_def(ecx, type_param_def);
1163 do self.emit_field(~"region_param", 1) {
1164 tpbt.generics.region_param.encode(self);
1168 do self.emit_field(~"ty", 1) {
1169 self.emit_ty(ecx, tpbt.ty);
1175 fn emit_tpbt(&mut self,
1176 ecx: @e::EncodeContext,
1177 tpbt: ty::ty_param_bounds_and_ty) {
1178 do self.emit_struct("ty_param_bounds_and_ty", 2) |this| {
1179 do this.emit_struct_field(~"generics", 0) |this| {
1180 do this.emit_struct("Generics", 2) |this| {
1181 do this.emit_struct_field(~"type_param_defs", 0) |this| {
1182 do this.emit_from_vec(*tpbt.generics.type_param_defs)
1183 |this, type_param_def| {
1184 this.emit_type_param_def(ecx, type_param_def);
1187 do this.emit_struct_field(~"region_param", 1) |this| {
1188 tpbt.generics.region_param.encode(this);
1192 do this.emit_struct_field(~"ty", 1) |this| {
1193 this.emit_ty(ecx, tpbt.ty);
1200 trait write_tag_and_id {
1201 fn tag(&self, tag_id: c::astencode_tag, f: &fn());
1202 fn id(&self, id: ast::node_id);
1206 trait write_tag_and_id {
1207 fn tag(&mut self, tag_id: c::astencode_tag, f: &fn(&mut Self));
1208 fn id(&mut self, id: ast::node_id);
1212 impl write_tag_and_id for writer::Encoder {
1213 fn tag(&self, tag_id: c::astencode_tag, f: &fn()) {
1214 do self.wr_tag(tag_id as uint) { f() }
1217 fn id(&self, id: ast::node_id) {
1218 self.wr_tagged_u64(c::tag_table_id as uint, id as u64)
1223 impl write_tag_and_id for writer::Encoder {
1225 tag_id: c::astencode_tag,
1226 f: &fn(&mut writer::Encoder)) {
1227 self.start_tag(tag_id as uint);
1232 fn id(&mut self, id: ast::node_id) {
1233 self.wr_tagged_u64(c::tag_table_id as uint, id as u64)
1238 fn encode_side_tables_for_ii(ecx: @e::EncodeContext,
1240 ebml_w: &writer::Encoder,
1241 ii: &ast::inlined_item) {
1242 do ebml_w.wr_tag(c::tag_table as uint) {
1243 let ebml_w = copy *ebml_w;
1244 ast_util::visit_ids_for_inlined_item(
1246 |id: ast::node_id| {
1247 // Note: this will cause a copy of ebml_w, which is bad as
1248 // it has mut fields. But I believe it's harmless since
1249 // we generate balanced EBML.
1250 /*let ebml_w = copy ebml_w;*/
1251 encode_side_tables_for_id(ecx, maps, &ebml_w, id)
1257 fn encode_side_tables_for_ii(ecx: @e::EncodeContext,
1259 ebml_w: &mut writer::Encoder,
1260 ii: &ast::inlined_item) {
1261 ebml_w.start_tag(c::tag_table as uint);
1262 let new_ebml_w = copy *ebml_w;
1263 ast_util::visit_ids_for_inlined_item(
1265 |id: ast::node_id| {
1266 // Note: this will cause a copy of ebml_w, which is bad as
1267 // it is mutable. But I believe it's harmless since we generate
1269 let mut new_ebml_w = copy new_ebml_w;
1270 encode_side_tables_for_id(ecx, maps, &mut new_ebml_w, id)
1276 fn encode_side_tables_for_id(ecx: @e::EncodeContext,
1278 ebml_w: &writer::Encoder,
1282 debug!("Encoding side tables for id %d", id);
1284 for tcx.def_map.find(&id).each |def| {
1285 do ebml_w.tag(c::tag_table_def) {
1287 do ebml_w.tag(c::tag_table_val) {
1288 (*def).encode(ebml_w)
1293 for tcx.node_types.find(&(id as uint)).each |&ty| {
1294 do ebml_w.tag(c::tag_table_node_type) {
1296 do ebml_w.tag(c::tag_table_val) {
1297 ebml_w.emit_ty(ecx, *ty);
1302 for tcx.node_type_substs.find(&id).each |tys| {
1303 do ebml_w.tag(c::tag_table_node_type_subst) {
1305 do ebml_w.tag(c::tag_table_val) {
1306 // FIXME(#5562): removing this copy causes a segfault
1308 ebml_w.emit_tys(ecx, /*bad*/copy **tys)
1313 for tcx.freevars.find(&id).each |&fv| {
1314 do ebml_w.tag(c::tag_table_freevars) {
1316 do ebml_w.tag(c::tag_table_val) {
1317 do ebml_w.emit_from_vec(**fv) |fv_entry| {
1318 encode_freevar_entry(ebml_w, *fv_entry)
1324 let lid = ast::def_id { crate: ast::local_crate, node: id };
1325 for tcx.tcache.find(&lid).each |&tpbt| {
1326 do ebml_w.tag(c::tag_table_tcache) {
1328 do ebml_w.tag(c::tag_table_val) {
1329 ebml_w.emit_tpbt(ecx, *tpbt);
1334 for tcx.ty_param_defs.find(&id).each |&type_param_def| {
1335 do ebml_w.tag(c::tag_table_param_defs) {
1337 do ebml_w.tag(c::tag_table_val) {
1338 ebml_w.emit_type_param_def(ecx, type_param_def)
1343 if maps.mutbl_map.contains(&id) {
1344 do ebml_w.tag(c::tag_table_mutbl) {
1349 for maps.last_use_map.find(&id).each |&m| {
1350 do ebml_w.tag(c::tag_table_last_use) {
1352 do ebml_w.tag(c::tag_table_val) {
1353 do ebml_w.emit_from_vec(/*bad*/ copy **m) |id| {
1360 for maps.method_map.find(&id).each |&mme| {
1361 do ebml_w.tag(c::tag_table_method_map) {
1363 do ebml_w.tag(c::tag_table_val) {
1364 encode_method_map_entry(ecx, ebml_w, *mme)
1369 for maps.vtable_map.find(&id).each |&dr| {
1370 do ebml_w.tag(c::tag_table_vtable_map) {
1372 do ebml_w.tag(c::tag_table_val) {
1373 encode_vtable_res(ecx, ebml_w, *dr);
1378 for tcx.adjustments.find(&id).each |adj| {
1379 do ebml_w.tag(c::tag_table_adjustments) {
1381 do ebml_w.tag(c::tag_table_val) {
1382 (**adj).encode(ebml_w)
1387 if maps.moves_map.contains(&id) {
1388 do ebml_w.tag(c::tag_table_moves_map) {
1393 for maps.capture_map.find(&id).each |&cap_vars| {
1394 do ebml_w.tag(c::tag_table_capture_map) {
1396 do ebml_w.tag(c::tag_table_val) {
1397 do ebml_w.emit_from_vec(*cap_vars) |cap_var| {
1398 cap_var.encode(ebml_w);
1406 fn encode_side_tables_for_id(ecx: @e::EncodeContext,
1408 ebml_w: &mut writer::Encoder,
1412 debug!("Encoding side tables for id %d", id);
1414 for tcx.def_map.find(&id).each |def| {
1415 do ebml_w.tag(c::tag_table_def) |ebml_w| {
1417 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1418 (*def).encode(ebml_w)
1423 for tcx.node_types.find(&(id as uint)).each |&ty| {
1424 do ebml_w.tag(c::tag_table_node_type) |ebml_w| {
1426 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1427 ebml_w.emit_ty(ecx, *ty);
1432 for tcx.node_type_substs.find(&id).each |tys| {
1433 do ebml_w.tag(c::tag_table_node_type_subst) |ebml_w| {
1435 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1436 // FIXME(#5562): removing this copy causes a segfault
1438 ebml_w.emit_tys(ecx, /*bad*/copy **tys)
1443 for tcx.freevars.find(&id).each |&fv| {
1444 do ebml_w.tag(c::tag_table_freevars) |ebml_w| {
1446 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1447 do ebml_w.emit_from_vec(**fv) |ebml_w, fv_entry| {
1448 encode_freevar_entry(ebml_w, *fv_entry)
1454 let lid = ast::def_id { crate: ast::local_crate, node: id };
1455 for tcx.tcache.find(&lid).each |&tpbt| {
1456 do ebml_w.tag(c::tag_table_tcache) |ebml_w| {
1458 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1459 ebml_w.emit_tpbt(ecx, *tpbt);
1464 for tcx.ty_param_defs.find(&id).each |&type_param_def| {
1465 do ebml_w.tag(c::tag_table_param_defs) |ebml_w| {
1467 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1468 ebml_w.emit_type_param_def(ecx, type_param_def)
1473 if maps.mutbl_map.contains(&id) {
1474 do ebml_w.tag(c::tag_table_mutbl) |ebml_w| {
1479 for maps.last_use_map.find(&id).each |&m| {
1480 do ebml_w.tag(c::tag_table_last_use) |ebml_w| {
1482 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1483 do ebml_w.emit_from_vec(/*bad*/ copy **m) |ebml_w, id| {
1490 for maps.method_map.find(&id).each |&mme| {
1491 do ebml_w.tag(c::tag_table_method_map) |ebml_w| {
1493 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1494 encode_method_map_entry(ecx, ebml_w, *mme)
1499 for maps.vtable_map.find(&id).each |&dr| {
1500 do ebml_w.tag(c::tag_table_vtable_map) |ebml_w| {
1502 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1503 encode_vtable_res(ecx, ebml_w, *dr);
1508 for tcx.adjustments.find(&id).each |adj| {
1509 do ebml_w.tag(c::tag_table_adjustments) |ebml_w| {
1511 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1512 (**adj).encode(ebml_w)
1517 if maps.moves_map.contains(&id) {
1518 do ebml_w.tag(c::tag_table_moves_map) |ebml_w| {
1523 for maps.capture_map.find(&id).each |&cap_vars| {
1524 do ebml_w.tag(c::tag_table_capture_map) |ebml_w| {
1526 do ebml_w.tag(c::tag_table_val) |ebml_w| {
1527 do ebml_w.emit_from_vec(*cap_vars) |ebml_w, cap_var| {
1528 cap_var.encode(ebml_w);
1535 trait doc_decoder_helpers {
1536 fn as_int(&self) -> int;
1537 fn opt_child(&self, tag: c::astencode_tag) -> Option<ebml::Doc>;
1540 impl doc_decoder_helpers for ebml::Doc {
1541 fn as_int(&self) -> int { reader::doc_as_u64(*self) as int }
1542 fn opt_child(&self, tag: c::astencode_tag) -> Option<ebml::Doc> {
1543 reader::maybe_get_doc(*self, tag as uint)
1548 trait ebml_decoder_decoder_helpers {
1549 fn read_arg(&self, xcx: @ExtendedDecodeContext) -> ty::arg;
1550 fn read_ty(&self, xcx: @ExtendedDecodeContext) -> ty::t;
1551 fn read_tys(&self, xcx: @ExtendedDecodeContext) -> ~[ty::t];
1552 fn read_type_param_def(&self, xcx: @ExtendedDecodeContext) -> ty::TypeParameterDef;
1553 fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext)
1554 -> ty::ty_param_bounds_and_ty;
1555 fn convert_def_id(&self, xcx: @ExtendedDecodeContext,
1556 source: DefIdSource,
1557 did: ast::def_id) -> ast::def_id;
1561 trait ebml_decoder_decoder_helpers {
1562 fn read_arg(&mut self, xcx: @ExtendedDecodeContext) -> ty::arg;
1563 fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t;
1564 fn read_tys(&mut self, xcx: @ExtendedDecodeContext) -> ~[ty::t];
1565 fn read_type_param_def(&mut self, xcx: @ExtendedDecodeContext)
1566 -> ty::TypeParameterDef;
1567 fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
1568 -> ty::ty_param_bounds_and_ty;
1569 fn convert_def_id(&mut self,
1570 xcx: @ExtendedDecodeContext,
1571 source: DefIdSource,
1576 impl ebml_decoder_decoder_helpers for reader::Decoder {
1578 fn read_arg(&self, xcx: @ExtendedDecodeContext) -> ty::arg {
1579 do self.read_opaque |doc| {
1580 tydecode::parse_arg_data(
1581 doc.data, xcx.dcx.cdata.cnum, doc.start, xcx.dcx.tcx,
1582 |s, a| self.convert_def_id(xcx, s, a))
1587 fn read_arg(&mut self, xcx: @ExtendedDecodeContext) -> ty::arg {
1588 do self.read_opaque |this, doc| {
1589 tydecode::parse_arg_data(
1594 |s, a| this.convert_def_id(xcx, s, a))
1599 fn read_ty(&self, xcx: @ExtendedDecodeContext) -> ty::t {
1600 // Note: regions types embed local node ids. In principle, we
1601 // should translate these node ids into the new decode
1602 // context. However, we do not bother, because region types
1603 // are not used during trans.
1605 return do self.read_opaque |doc| {
1607 let ty = tydecode::parse_ty_data(
1608 doc.data, xcx.dcx.cdata.cnum, doc.start, xcx.dcx.tcx,
1609 |s, a| self.convert_def_id(xcx, s, a));
1611 debug!("read_ty(%s) = %s",
1612 type_string(doc), ty_to_str(xcx.dcx.tcx, ty));
1617 fn type_string(doc: ebml::Doc) -> ~str {
1619 for uint::range(doc.start, doc.end) |i| {
1620 str::push_char(&mut str, doc.data[i] as char);
1627 fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t {
1628 // Note: regions types embed local node ids. In principle, we
1629 // should translate these node ids into the new decode
1630 // context. However, we do not bother, because region types
1631 // are not used during trans.
1633 return do self.read_opaque |this, doc| {
1634 let ty = tydecode::parse_ty_data(
1639 |s, a| this.convert_def_id(xcx, s, a));
1641 debug!("read_ty(%s) = %s",
1643 ty_to_str(xcx.dcx.tcx, ty));
1648 fn type_string(doc: ebml::Doc) -> ~str {
1650 for uint::range(doc.start, doc.end) |i| {
1651 str::push_char(&mut str, doc.data[i] as char);
1658 fn read_tys(&self, xcx: @ExtendedDecodeContext) -> ~[ty::t] {
1659 self.read_to_vec(|| self.read_ty(xcx) )
1663 fn read_tys(&mut self, xcx: @ExtendedDecodeContext) -> ~[ty::t] {
1664 self.read_to_vec(|this| this.read_ty(xcx) )
1668 fn read_type_param_def(&self, xcx: @ExtendedDecodeContext)
1669 -> ty::TypeParameterDef {
1670 do self.read_opaque |doc| {
1671 tydecode::parse_type_param_def_data(
1672 doc.data, doc.start, xcx.dcx.cdata.cnum, xcx.dcx.tcx,
1673 |s, a| self.convert_def_id(xcx, s, a))
1678 fn read_type_param_def(&mut self, xcx: @ExtendedDecodeContext)
1679 -> ty::TypeParameterDef {
1680 do self.read_opaque |this, doc| {
1681 tydecode::parse_type_param_def_data(
1686 |s, a| this.convert_def_id(xcx, s, a))
1691 fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext)
1692 -> ty::ty_param_bounds_and_ty {
1693 do self.read_struct("ty_param_bounds_and_ty", 2) {
1694 ty::ty_param_bounds_and_ty {
1695 generics: do self.read_field("generics", 0) {
1696 do self.read_struct("Generics", 2) {
1698 type_param_defs: self.read_field("type_param_defs", 0, || {
1699 @self.read_to_vec(|| self.read_type_param_def(xcx))
1701 region_param: self.read_field(~"region_param", 1, || {
1702 Decodable::decode(self)
1707 ty: self.read_field(~"ty", 1, || {
1715 fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
1716 -> ty::ty_param_bounds_and_ty {
1717 do self.read_struct("ty_param_bounds_and_ty", 2) |this| {
1718 ty::ty_param_bounds_and_ty {
1719 generics: do this.read_struct_field("generics", 0) |this| {
1720 do this.read_struct("Generics", 2) |this| {
1723 this.read_struct_field("type_param_defs",
1726 @this.read_to_vec(|this|
1727 this.read_type_param_def(xcx))
1730 this.read_struct_field("region_param",
1733 Decodable::decode(this)
1738 ty: this.read_struct_field("ty", 1, |this| {
1746 fn convert_def_id(&self,
1747 xcx: @ExtendedDecodeContext,
1748 source: tydecode::DefIdSource,
1753 * Converts a def-id that appears in a type. The correct
1754 * translation will depend on what kind of def-id this is.
1755 * This is a subtle point: type definitions are not
1756 * inlined into the current crate, so if the def-id names
1757 * a nominal type or type alias, then it should be
1758 * translated to refer to the source crate.
1760 * However, *type parameters* are cloned along with the function
1761 * they are attached to. So we should translate those def-ids
1762 * to refer to the new, cloned copy of the type parameter.
1765 let r = match source {
1766 NominalType | TypeWithId => xcx.tr_def_id(did),
1767 TypeParameter => xcx.tr_intern_def_id(did)
1769 debug!("convert_def_id(source=%?, did=%?)=%?", source, did, r);
1774 fn convert_def_id(&mut self,
1775 xcx: @ExtendedDecodeContext,
1776 source: tydecode::DefIdSource,
1781 * Converts a def-id that appears in a type. The correct
1782 * translation will depend on what kind of def-id this is.
1783 * This is a subtle point: type definitions are not
1784 * inlined into the current crate, so if the def-id names
1785 * a nominal type or type alias, then it should be
1786 * translated to refer to the source crate.
1788 * However, *type parameters* are cloned along with the function
1789 * they are attached to. So we should translate those def-ids
1790 * to refer to the new, cloned copy of the type parameter.
1793 let r = match source {
1794 NominalType | TypeWithId => xcx.tr_def_id(did),
1795 TypeParameter => xcx.tr_intern_def_id(did)
1797 debug!("convert_def_id(source=%?, did=%?)=%?", source, did, r);
1803 fn decode_side_tables(xcx: @ExtendedDecodeContext,
1804 ast_doc: ebml::Doc) {
1806 let tbl_doc = ast_doc.get(c::tag_table as uint);
1807 for reader::docs(tbl_doc) |tag, entry_doc| {
1808 let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
1809 let id = xcx.tr_id(id0);
1811 debug!(">> Side table document with tag 0x%x \
1812 found for id %d (orig %d)",
1815 if tag == (c::tag_table_mutbl as uint) {
1816 dcx.maps.mutbl_map.insert(id);
1817 } else if tag == (c::tag_table_moves_map as uint) {
1818 dcx.maps.moves_map.insert(id);
1820 let val_doc = entry_doc.get(c::tag_table_val as uint);
1821 let val_dsr = &reader::Decoder(val_doc);
1822 if tag == (c::tag_table_def as uint) {
1823 let def = decode_def(xcx, val_doc);
1824 dcx.tcx.def_map.insert(id, def);
1825 } else if tag == (c::tag_table_node_type as uint) {
1826 let ty = val_dsr.read_ty(xcx);
1827 debug!("inserting ty for node %?: %s",
1828 id, ty_to_str(dcx.tcx, ty));
1829 dcx.tcx.node_types.insert(id as uint, ty);
1830 } else if tag == (c::tag_table_node_type_subst as uint) {
1831 let tys = val_dsr.read_tys(xcx);
1832 dcx.tcx.node_type_substs.insert(id, tys);
1833 } else if tag == (c::tag_table_freevars as uint) {
1834 let fv_info = @val_dsr.read_to_vec(|| {
1835 @val_dsr.read_freevar_entry(xcx)
1837 dcx.tcx.freevars.insert(id, fv_info);
1838 } else if tag == (c::tag_table_tcache as uint) {
1839 let tpbt = val_dsr.read_ty_param_bounds_and_ty(xcx);
1840 let lid = ast::def_id { crate: ast::local_crate, node: id };
1841 dcx.tcx.tcache.insert(lid, tpbt);
1842 } else if tag == (c::tag_table_param_defs as uint) {
1843 let bounds = val_dsr.read_type_param_def(xcx);
1844 dcx.tcx.ty_param_defs.insert(id, bounds);
1845 } else if tag == (c::tag_table_last_use as uint) {
1846 let ids = val_dsr.read_to_vec(|| {
1847 xcx.tr_id(val_dsr.read_int())
1849 dcx.maps.last_use_map.insert(id, @mut ids);
1850 } else if tag == (c::tag_table_method_map as uint) {
1851 dcx.maps.method_map.insert(
1853 val_dsr.read_method_map_entry(xcx));
1854 } else if tag == (c::tag_table_vtable_map as uint) {
1855 dcx.maps.vtable_map.insert(id,
1856 val_dsr.read_vtable_res(xcx));
1857 } else if tag == (c::tag_table_adjustments as uint) {
1858 let adj: @ty::AutoAdjustment = @Decodable::decode(val_dsr);
1860 dcx.tcx.adjustments.insert(id, adj);
1861 } else if tag == (c::tag_table_capture_map as uint) {
1864 val_dsr.read_to_vec(
1865 || val_dsr.read_capture_var(xcx)));
1866 dcx.maps.capture_map.insert(id, cvars);
1868 xcx.dcx.tcx.sess.bug(
1869 fmt!("unknown tag found in side tables: %x", tag));
1873 debug!(">< Side table doc loaded");
1878 fn decode_side_tables(xcx: @ExtendedDecodeContext,
1879 ast_doc: ebml::Doc) {
1881 let tbl_doc = ast_doc.get(c::tag_table as uint);
1882 for reader::docs(tbl_doc) |tag, entry_doc| {
1883 let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
1884 let id = xcx.tr_id(id0);
1886 debug!(">> Side table document with tag 0x%x \
1887 found for id %d (orig %d)",
1890 if tag == (c::tag_table_mutbl as uint) {
1891 dcx.maps.mutbl_map.insert(id);
1892 } else if tag == (c::tag_table_moves_map as uint) {
1893 dcx.maps.moves_map.insert(id);
1895 let val_doc = entry_doc.get(c::tag_table_val as uint);
1896 let mut val_dsr = reader::Decoder(val_doc);
1897 let val_dsr = &mut val_dsr;
1898 if tag == (c::tag_table_def as uint) {
1899 let def = decode_def(xcx, val_doc);
1900 dcx.tcx.def_map.insert(id, def);
1901 } else if tag == (c::tag_table_node_type as uint) {
1902 let ty = val_dsr.read_ty(xcx);
1903 debug!("inserting ty for node %?: %s",
1904 id, ty_to_str(dcx.tcx, ty));
1905 dcx.tcx.node_types.insert(id as uint, ty);
1906 } else if tag == (c::tag_table_node_type_subst as uint) {
1907 let tys = val_dsr.read_tys(xcx);
1908 dcx.tcx.node_type_substs.insert(id, tys);
1909 } else if tag == (c::tag_table_freevars as uint) {
1910 let fv_info = @val_dsr.read_to_vec(|val_dsr| {
1911 @val_dsr.read_freevar_entry(xcx)
1913 dcx.tcx.freevars.insert(id, fv_info);
1914 } else if tag == (c::tag_table_tcache as uint) {
1915 let tpbt = val_dsr.read_ty_param_bounds_and_ty(xcx);
1916 let lid = ast::def_id { crate: ast::local_crate, node: id };
1917 dcx.tcx.tcache.insert(lid, tpbt);
1918 } else if tag == (c::tag_table_param_defs as uint) {
1919 let bounds = val_dsr.read_type_param_def(xcx);
1920 dcx.tcx.ty_param_defs.insert(id, bounds);
1921 } else if tag == (c::tag_table_last_use as uint) {
1922 let ids = val_dsr.read_to_vec(|val_dsr| {
1923 xcx.tr_id(val_dsr.read_int())
1925 dcx.maps.last_use_map.insert(id, @mut ids);
1926 } else if tag == (c::tag_table_method_map as uint) {
1927 dcx.maps.method_map.insert(
1929 val_dsr.read_method_map_entry(xcx));
1930 } else if tag == (c::tag_table_vtable_map as uint) {
1931 dcx.maps.vtable_map.insert(id,
1932 val_dsr.read_vtable_res(xcx));
1933 } else if tag == (c::tag_table_adjustments as uint) {
1934 let adj: @ty::AutoAdjustment = @Decodable::decode(val_dsr);
1936 dcx.tcx.adjustments.insert(id, adj);
1937 } else if tag == (c::tag_table_capture_map as uint) {
1940 val_dsr.read_to_vec(
1941 |val_dsr| val_dsr.read_capture_var(xcx)));
1942 dcx.maps.capture_map.insert(id, cvars);
1944 xcx.dcx.tcx.sess.bug(
1945 fmt!("unknown tag found in side tables: %x", tag));
1949 debug!(">< Side table doc loaded");
1953 // ______________________________________________________________________
1954 // Testing of astencode_gen
1957 fn encode_item_ast(ebml_w: &mut writer::Encoder, item: @ast::item) {
1958 ebml_w.start_tag(c::tag_tree as uint);
1959 (*item).encode(ebml_w);
1964 fn decode_item_ast(par_doc: ebml::Doc) -> @ast::item {
1965 let chi_doc = par_doc.get(c::tag_tree as uint);
1966 let mut d = reader::Decoder(chi_doc);
1967 @Decodable::decode(&mut d)
1971 trait fake_ext_ctxt {
1972 fn cfg(&self) -> ast::crate_cfg;
1973 fn parse_sess(&self) -> @mut parse::ParseSess;
1974 fn call_site(&self) -> span;
1975 fn ident_of(&self, st: ~str) -> ast::ident;
1979 type fake_session = @mut parse::ParseSess;
1982 impl fake_ext_ctxt for fake_session {
1983 fn cfg(&self) -> ast::crate_cfg { ~[] }
1984 fn parse_sess(&self) -> @mut parse::ParseSess { *self }
1985 fn call_site(&self) -> span {
1987 lo: codemap::BytePos(0),
1988 hi: codemap::BytePos(0),
1992 fn ident_of(&self, st: ~str) -> ast::ident {
1993 self.interner.intern(@st)
1998 fn mk_ctxt() -> @fake_ext_ctxt {
1999 @parse::new_parse_sess(None) as @fake_ext_ctxt
2003 fn roundtrip(in_item: Option<@ast::item>) {
2006 let in_item = in_item.get();
2007 let bytes = do io::with_bytes_writer |wr| {
2008 let mut ebml_w = writer::Encoder(wr);
2009 encode_item_ast(&mut ebml_w, in_item);
2011 let ebml_doc = reader::Doc(@bytes);
2012 let out_item = decode_item_ast(ebml_doc);
2014 assert_eq!(in_item, out_item);
2019 let ext_cx = mk_ctxt();
2020 roundtrip(quote_item!(
2026 fn test_smalltalk() {
2027 let ext_cx = mk_ctxt();
2028 roundtrip(quote_item!(
2029 fn foo() -> int { 3 + 4 } // first smalltalk program ever executed.
2035 let ext_cx = mk_ctxt();
2036 roundtrip(quote_item!(
2037 fn foo(x: uint, y: uint) -> uint {
2045 fn test_simplification() {
2046 let ext_cx = mk_ctxt();
2047 let item_in = ast::ii_item(quote_item!(
2048 fn new_int_alist<B:Copy>() -> alist<int, B> {
2049 fn eq_int(&&a: int, &&b: int) -> bool { a == b }
2050 return alist {eq_fn: eq_int, data: ~[]};
2053 let item_out = simplify_ast(&item_in);
2054 let item_exp = ast::ii_item(quote_item!(
2055 fn new_int_alist<B:Copy>() -> alist<int, B> {
2056 return alist {eq_fn: eq_int, data: ~[]};
2059 match (item_out, item_exp) {
2060 (ast::ii_item(item_out), ast::ii_item(item_exp)) => {
2061 assert!(pprust::item_to_str(item_out,
2062 ext_cx.parse_sess().interner)
2063 == pprust::item_to_str(item_exp,
2064 ext_cx.parse_sess().interner));