]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/astencode.rs
librustc: Update the serializer to work properly with INHTWAMA, removing mutable...
[rust.git] / src / librustc / middle / astencode.rs
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.
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 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};
23 use middle;
24 use util::ppaux::ty_to_str;
25
26 use std::ebml::reader;
27 use std::ebml;
28 use std::serialize;
29 use std::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers};
30 use std::serialize::{Decoder, Decodable};
31 use syntax::ast;
32 use syntax::ast_map;
33 use syntax::ast_util::inlined_item_utils;
34 use syntax::ast_util;
35 use syntax::codemap::span;
36 use syntax::codemap;
37 use syntax::fold::*;
38 use syntax::fold;
39 use syntax;
40 use writer = std::ebml::writer;
41
42 #[cfg(test)] use syntax::parse;
43 #[cfg(test)] use syntax::print::pprust;
44
45 // Auxiliary maps of things to be encoded
46 pub struct Maps {
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,
55 }
56
57 struct DecodeContext {
58     cdata: @cstore::crate_metadata,
59     tcx: ty::ctxt,
60     maps: Maps
61 }
62
63 struct ExtendedDecodeContext {
64     dcx: @DecodeContext,
65     from_id_range: ast_util::id_range,
66     to_id_range: ast_util::id_range
67 }
68
69 trait tr {
70     fn tr(&self, xcx: @ExtendedDecodeContext) -> Self;
71 }
72
73 trait tr_intern {
74     fn tr_intern(&self, xcx: @ExtendedDecodeContext) -> ast::def_id;
75 }
76
77 // ______________________________________________________________________
78 // Top-level methods.
79
80 #[cfg(stage0)]
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,
85                            maps: Maps) {
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());
90
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);
96     }
97
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());
102 }
103
104 #[cfg(not(stage0))]
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,
109                            maps: Maps) {
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());
114
115     let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
116
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);
121     ebml_w.end_tag();
122
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());
127 }
128
129 #[cfg(stage0)]
130 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
131                            tcx: ty::ctxt,
132                            maps: Maps,
133                            path: ast_map::path,
134                            par_doc: ebml::Doc)
135                         -> Option<ast::inlined_item> {
136     let dcx = @DecodeContext {
137         cdata: cdata,
138         tcx: tcx,
139         maps: maps
140     };
141     match par_doc.opt_child(c::tag_ast) {
142       None => None,
143       Some(ast_doc) => {
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 {
150             dcx: dcx,
151             from_id_range: from_id_range,
152             to_id_range: to_id_range
153         };
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);
163         match ii {
164           ast::ii_item(i) => {
165             debug!(">>> DECODED ITEM >>>\n%s\n<<< DECODED ITEM <<<",
166                    syntax::print::pprust::item_to_str(i, tcx.sess.intr()));
167           }
168           _ => { }
169         }
170         Some(ii)
171       }
172     }
173 }
174
175 #[cfg(not(stage0))]
176 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
177                            tcx: ty::ctxt,
178                            maps: Maps,
179                            path: ast_map::path,
180                            par_doc: ebml::Doc)
181                         -> Option<ast::inlined_item> {
182     let dcx = @DecodeContext {
183         cdata: cdata,
184         tcx: tcx,
185         maps: maps
186     };
187     match par_doc.opt_child(c::tag_ast) {
188       None => None,
189       Some(ast_doc) => {
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 {
196             dcx: dcx,
197             from_id_range: from_id_range,
198             to_id_range: to_id_range
199         };
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);
209         match ii {
210           ast::ii_item(i) => {
211             debug!(">>> DECODED ITEM >>>\n%s\n<<< DECODED ITEM <<<",
212                    syntax::print::pprust::item_to_str(i, tcx.sess.intr()));
213           }
214           _ => { }
215         }
216         Some(ii)
217       }
218     }
219 }
220
221 // ______________________________________________________________________
222 // Enumerating the IDs which appear in an AST
223
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 }
233 }
234
235 pub impl ExtendedDecodeContext {
236     fn tr_id(&self, id: ast::node_id) -> ast::node_id {
237         /*!
238          *
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
245          * crate.
246          */
247
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)
251     }
252     fn tr_def_id(&self, did: ast::def_id) -> ast::def_id {
253         /*!
254          *
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.
268          *
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.
273          */
274
275         decoder::translate_def_id(self.dcx.cdata, did)
276     }
277     fn tr_intern_def_id(&self, did: ast::def_id) -> ast::def_id {
278         /*!
279          *
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.
284          */
285
286         assert!(did.crate == ast::local_crate);
287         ast::def_id { crate: ast::local_crate, node: self.tr_id(did.node) }
288     }
289     fn tr_span(&self, _span: span) -> span {
290         codemap::dummy_sp() // FIXME (#1972): handle span properly
291     }
292 }
293
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)
297     }
298 }
299
300 impl tr for ast::def_id {
301     fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def_id {
302         xcx.tr_def_id(*self)
303     }
304 }
305
306 impl tr for span {
307     fn tr(&self, xcx: @ExtendedDecodeContext) -> span {
308         xcx.tr_span(*self)
309     }
310 }
311
312 #[cfg(stage0)]
313 trait def_id_encoder_helpers {
314     fn emit_def_id(&self, did: ast::def_id);
315 }
316
317 #[cfg(not(stage0))]
318 trait def_id_encoder_helpers {
319     fn emit_def_id(&mut self, did: ast::def_id);
320 }
321
322 #[cfg(stage0)]
323 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
324     fn emit_def_id(&self, did: ast::def_id) {
325         did.encode(self)
326     }
327 }
328
329 #[cfg(not(stage0))]
330 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
331     fn emit_def_id(&mut self, did: ast::def_id) {
332         did.encode(self)
333     }
334 }
335
336 #[cfg(stage0)]
337 trait def_id_decoder_helpers {
338     fn read_def_id(&self, xcx: @ExtendedDecodeContext) -> ast::def_id;
339 }
340
341 #[cfg(not(stage0))]
342 trait def_id_decoder_helpers {
343     fn read_def_id(&mut self, xcx: @ExtendedDecodeContext) -> ast::def_id;
344 }
345
346 #[cfg(stage0)]
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);
350         did.tr(xcx)
351     }
352 }
353
354 #[cfg(not(stage0))]
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);
358         did.tr(xcx)
359     }
360 }
361
362 // ______________________________________________________________________
363 // Encoding and decoding the AST itself
364 //
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.
371 //
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.
376
377 #[cfg(stage0)]
378 fn encode_ast(ebml_w: &writer::Encoder, item: ast::inlined_item) {
379     do ebml_w.wr_tag(c::tag_tree as uint) {
380         item.encode(ebml_w)
381     }
382 }
383
384 #[cfg(not(stage0))]
385 fn encode_ast(ebml_w: &mut writer::Encoder, item: ast::inlined_item) {
386     ebml_w.start_tag(c::tag_tree as uint);
387     item.encode(ebml_w);
388     ebml_w.end_tag();
389 }
390
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).
397 //
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
400 // inlined items.
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| {
404             match stmt.node {
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")
411             }
412         };
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,
417             expr: blk.expr,
418             id: blk.id,
419             rules: blk.rules
420         };
421         fold::noop_fold_block(&blk_sans_items, fld)
422     }
423
424     let fld = fold::make_fold(@fold::AstFoldFns {
425         fold_block: fold::wrap(drop_nested_items),
426         .. *fold::default_ast_fold()
427     });
428
429     match *ii {
430       ast::ii_item(i) => {
431         ast::ii_item(fld.fold_item(i).get()) //hack: we're not dropping items
432       }
433       ast::ii_method(d, m) => {
434         ast::ii_method(d, fld.fold_method(m))
435       }
436       ast::ii_foreign(i) => {
437         ast::ii_foreign(fld.fold_foreign_item(i))
438       }
439     }
440 }
441
442 #[cfg(stage0)]
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);
446     Decodable::decode(d)
447 }
448
449 #[cfg(not(stage0))]
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)
454 }
455
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()
462     });
463
464     match ii {
465       ast::ii_item(i) => {
466         ast::ii_item(fld.fold_item(i).get())
467       }
468       ast::ii_method(d, m) => {
469         ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m))
470       }
471       ast::ii_foreign(i) => {
472         ast::ii_foreign(fld.fold_foreign_item(i))
473       }
474      }
475 }
476
477 // ______________________________________________________________________
478 // Encoding and decoding of ast::def
479
480 #[cfg(stage0)]
481 fn encode_def(ebml_w: &writer::Encoder, def: ast::def) {
482     def.encode(ebml_w)
483 }
484
485 #[cfg(not(stage0))]
486 fn encode_def(ebml_w: &mut writer::Encoder, def: ast::def) {
487     def.encode(ebml_w)
488 }
489
490 #[cfg(stage0)]
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);
494     def.tr(xcx)
495 }
496
497 #[cfg(not(stage0))]
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);
501     def.tr(xcx)
502 }
503
504 impl tr for ast::def {
505     fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def {
506         match *self {
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)),
511                                    p)
512           }
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))
522           }
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),
531                            @(*def).tr(xcx),
532                            xcx.tr_id(nid2),
533                            xcx.tr_id(nid3))
534           }
535           ast::def_struct(did) => {
536             ast::def_struct(did.tr(xcx))
537           }
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))
541           }
542           ast::def_label(nid) => ast::def_label(xcx.tr_id(nid))
543         }
544     }
545 }
546
547 // ______________________________________________________________________
548 // Encoding and decoding of adjustment information
549
550 impl tr for ty::AutoAdjustment {
551     fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment {
552         match self {
553             &ty::AutoAddEnv(r, s) => {
554                 ty::AutoAddEnv(r.tr(xcx), s)
555             }
556
557             &ty::AutoDerefRef(ref adr) => {
558                 ty::AutoDerefRef(ty::AutoDerefRef {
559                     autoderefs: adr.autoderefs,
560                     autoref: adr.autoref.map(|ar| ar.tr(xcx)),
561                 })
562             }
563         }
564     }
565 }
566
567 impl tr for ty::AutoRef {
568     fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoRef {
569         ty::AutoRef {
570             kind: self.kind,
571             region: self.region.tr(xcx),
572             mutbl: self.mutbl,
573         }
574     }
575 }
576
577 impl tr for ty::Region {
578     fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region {
579         match *self {
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)})
586             }
587         }
588     }
589 }
590
591 impl tr for ty::bound_region {
592     fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::bound_region {
593         match *self {
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),
597                                                          @br.tr(xcx))
598         }
599     }
600 }
601
602 // ______________________________________________________________________
603 // Encoding and decoding of freevar information
604
605 #[cfg(stage0)]
606 fn encode_freevar_entry(ebml_w: &writer::Encoder, fv: @freevar_entry) {
607     (*fv).encode(ebml_w)
608 }
609
610 #[cfg(not(stage0))]
611 fn encode_freevar_entry(ebml_w: &mut writer::Encoder, fv: @freevar_entry) {
612     (*fv).encode(ebml_w)
613 }
614
615 #[cfg(stage0)]
616 trait ebml_decoder_helper {
617     fn read_freevar_entry(&self, xcx: @ExtendedDecodeContext)
618                           -> freevar_entry;
619 }
620
621 #[cfg(not(stage0))]
622 trait ebml_decoder_helper {
623     fn read_freevar_entry(&mut self, xcx: @ExtendedDecodeContext)
624                           -> freevar_entry;
625 }
626
627 #[cfg(stage0)]
628 impl ebml_decoder_helper for reader::Decoder {
629     fn read_freevar_entry(&self, xcx: @ExtendedDecodeContext)
630                           -> freevar_entry {
631         let fv: freevar_entry = Decodable::decode(self);
632         fv.tr(xcx)
633     }
634 }
635
636 #[cfg(not(stage0))]
637 impl ebml_decoder_helper for reader::Decoder {
638     fn read_freevar_entry(&mut self, xcx: @ExtendedDecodeContext)
639                           -> freevar_entry {
640         let fv: freevar_entry = Decodable::decode(self);
641         fv.tr(xcx)
642     }
643 }
644
645 impl tr for freevar_entry {
646     fn tr(&self, xcx: @ExtendedDecodeContext) -> freevar_entry {
647         freevar_entry {
648             def: self.def.tr(xcx),
649             span: self.span.tr(xcx),
650         }
651     }
652 }
653
654 // ______________________________________________________________________
655 // Encoding and decoding of CaptureVar information
656
657 #[cfg(stage0)]
658 trait capture_var_helper {
659     fn read_capture_var(&self, xcx: @ExtendedDecodeContext)
660                         -> moves::CaptureVar;
661 }
662
663 #[cfg(not(stage0))]
664 trait capture_var_helper {
665     fn read_capture_var(&mut self, xcx: @ExtendedDecodeContext)
666                         -> moves::CaptureVar;
667 }
668
669 #[cfg(stage0)]
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);
674         cvar.tr(xcx)
675     }
676 }
677
678 #[cfg(not(stage0))]
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);
683         cvar.tr(xcx)
684     }
685 }
686
687 impl tr for moves::CaptureVar {
688     fn tr(&self, xcx: @ExtendedDecodeContext) -> moves::CaptureVar {
689         moves::CaptureVar {
690             def: self.def.tr(xcx),
691             span: self.span.tr(xcx),
692             mode: self.mode
693         }
694     }
695 }
696
697 // ______________________________________________________________________
698 // Encoding and decoding of method_map_entry
699
700 trait read_method_map_entry_helper {
701     #[cfg(stage0)]
702     fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext)
703                              -> method_map_entry;
704     #[cfg(not(stage0))]
705     fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
706                              -> method_map_entry;
707 }
708
709 #[cfg(stage0)]
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);
716         }
717         do ebml_w.emit_field(~"explicit_self", 2u) {
718             mme.explicit_self.encode(ebml_w);
719         }
720         do ebml_w.emit_field(~"origin", 1u) {
721             mme.origin.encode(ebml_w);
722         }
723         do ebml_w.emit_field(~"self_mode", 3) {
724             mme.self_mode.encode(ebml_w);
725         }
726     }
727 }
728
729 #[cfg(not(stage0))]
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);
736         }
737         do ebml_w.emit_struct_field("explicit_self", 2u) |ebml_w| {
738             mme.explicit_self.encode(ebml_w);
739         }
740         do ebml_w.emit_struct_field("origin", 1u) |ebml_w| {
741             mme.origin.encode(ebml_w);
742         }
743         do ebml_w.emit_struct_field("self_mode", 3) |ebml_w| {
744             mme.self_mode.encode(ebml_w);
745         }
746     }
747 }
748
749 impl read_method_map_entry_helper for reader::Decoder {
750     #[cfg(stage0)]
751     fn read_method_map_entry(&self, xcx: @ExtendedDecodeContext)
752                              -> method_map_entry {
753         do self.read_struct("method_map_entry", 3) {
754             method_map_entry {
755                 self_arg: self.read_field(~"self_arg", 0u, || {
756                     self.read_arg(xcx)
757                 }),
758                 explicit_self: self.read_field(~"explicit_self", 2u, || {
759                     let self_type: ast::self_ty_ = Decodable::decode(self);
760                     self_type
761                 }),
762                 origin: self.read_field(~"origin", 1u, || {
763                     let method_origin: method_origin =
764                         Decodable::decode(self);
765                     method_origin.tr(xcx)
766                 }),
767                 self_mode: self.read_field(~"self_mode", 3, || {
768                     let self_mode: ty::SelfMode = Decodable::decode(self);
769                     self_mode
770                 }),
771             }
772         }
773     }
774
775     #[cfg(not(stage0))]
776     fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
777                              -> method_map_entry {
778         do self.read_struct("method_map_entry", 3) |this| {
779             method_map_entry {
780                 self_arg: this.read_struct_field("self_arg", 0, |this| {
781                     this.read_arg(xcx)
782                 }),
783                 explicit_self: this.read_struct_field("explicit_self",
784                                                       2,
785                                                       |this| {
786                     let self_type: ast::self_ty_ = Decodable::decode(this);
787                     self_type
788                 }),
789                 origin: this.read_struct_field("origin", 1, |this| {
790                     let method_origin: method_origin =
791                         Decodable::decode(this);
792                     method_origin.tr(xcx)
793                 }),
794                 self_mode: this.read_struct_field("self_mode", 3, |this| {
795                     let self_mode: ty::SelfMode = Decodable::decode(this);
796                     self_mode
797                 }),
798             }
799         }
800     }
801 }
802
803 impl tr for method_origin {
804     fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
805         match *self {
806           typeck::method_static(did) => {
807               typeck::method_static(did.tr(xcx))
808           }
809           typeck::method_param(ref mp) => {
810             typeck::method_param(
811                 typeck::method_param {
812                     trait_id: mp.trait_id.tr(xcx),
813                     .. *mp
814                 }
815             )
816           }
817           typeck::method_trait(did, m, vstore) => {
818               typeck::method_trait(did.tr(xcx), m, vstore)
819           }
820           typeck::method_self(did, m) => {
821               typeck::method_self(did.tr(xcx), m)
822           }
823           typeck::method_super(trait_did, m) => {
824               typeck::method_super(trait_did.tr(xcx), m)
825           }
826         }
827     }
828 }
829
830 // ______________________________________________________________________
831 // Encoding and decoding vtable_res
832
833 #[cfg(stage0)]
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)
843     }
844 }
845
846 #[cfg(not(stage0))]
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)
856     }
857 }
858
859 #[cfg(stage0)]
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)
869                 }
870                 do ebml_w.emit_enum_variant_arg(1u) {
871                     ebml_w.emit_tys(ecx, /*bad*/copy *tys);
872                 }
873                 do ebml_w.emit_enum_variant_arg(2u) {
874                     encode_vtable_res(ecx, ebml_w, vtable_res);
875                 }
876             }
877           }
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);
882                 }
883                 do ebml_w.emit_enum_variant_arg(1u) {
884                     ebml_w.emit_uint(bn);
885                 }
886             }
887           }
888         }
889     }
890 }
891
892 #[cfg(not(stage0))]
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)
902                 }
903                 do ebml_w.emit_enum_variant_arg(1u) |ebml_w| {
904                     ebml_w.emit_tys(ecx, /*bad*/copy *tys);
905                 }
906                 do ebml_w.emit_enum_variant_arg(2u) |ebml_w| {
907                     encode_vtable_res(ecx, ebml_w, vtable_res);
908                 }
909             }
910           }
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);
915                 }
916                 do ebml_w.emit_enum_variant_arg(1u) |ebml_w| {
917                     ebml_w.emit_uint(bn);
918                 }
919             }
920           }
921         }
922     }
923 }
924
925 trait vtable_decoder_helpers {
926     #[cfg(stage0)]
927     fn read_vtable_res(&self, xcx: @ExtendedDecodeContext)
928                       -> typeck::vtable_res;
929     #[cfg(not(stage0))]
930     fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
931                       -> typeck::vtable_res;
932     #[cfg(stage0)]
933     fn read_vtable_origin(&self, xcx: @ExtendedDecodeContext)
934                           -> typeck::vtable_origin;
935     #[cfg(not(stage0))]
936     fn read_vtable_origin(&mut self, xcx: @ExtendedDecodeContext)
937                           -> typeck::vtable_origin;
938 }
939
940 impl vtable_decoder_helpers for reader::Decoder {
941     #[cfg(stage0)]
942     fn read_vtable_res(&self, xcx: @ExtendedDecodeContext)
943                       -> typeck::vtable_res {
944         @self.read_to_vec(|| self.read_vtable_origin(xcx))
945     }
946
947     #[cfg(not(stage0))]
948     fn read_vtable_res(&mut self, xcx: @ExtendedDecodeContext)
949                       -> typeck::vtable_res {
950         @self.read_to_vec(|this| this.read_vtable_origin(xcx))
951     }
952
953     #[cfg(stage0)]
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| {
958                 match i {
959                   0 => {
960                     typeck::vtable_static(
961                         do self.read_enum_variant_arg(0u) {
962                             self.read_def_id(xcx)
963                         },
964                         do self.read_enum_variant_arg(1u) {
965                             self.read_tys(xcx)
966                         },
967                         do self.read_enum_variant_arg(2u) {
968                             self.read_vtable_res(xcx)
969                         }
970                     )
971                   }
972                   1 => {
973                     typeck::vtable_param(
974                         do self.read_enum_variant_arg(0u) {
975                             self.read_uint()
976                         },
977                         do self.read_enum_variant_arg(1u) {
978                             self.read_uint()
979                         }
980                     )
981                   }
982                   // hard to avoid - user input
983                   _ => fail!(~"bad enum variant")
984                 }
985             }
986         }
987     }
988
989     #[cfg(not(stage0))]
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"])
994                     |this, i| {
995                 match i {
996                   0 => {
997                     typeck::vtable_static(
998                         do this.read_enum_variant_arg(0u) |this| {
999                             this.read_def_id(xcx)
1000                         },
1001                         do this.read_enum_variant_arg(1u) |this| {
1002                             this.read_tys(xcx)
1003                         },
1004                         do this.read_enum_variant_arg(2u) |this| {
1005                             this.read_vtable_res(xcx)
1006                         }
1007                     )
1008                   }
1009                   1 => {
1010                     typeck::vtable_param(
1011                         do this.read_enum_variant_arg(0u) |this| {
1012                             this.read_uint()
1013                         },
1014                         do this.read_enum_variant_arg(1u) |this| {
1015                             this.read_uint()
1016                         }
1017                     )
1018                   }
1019                   // hard to avoid - user input
1020                   _ => fail!(~"bad enum variant")
1021                 }
1022             }
1023         }
1024     }
1025 }
1026
1027 // ______________________________________________________________________
1028 // Encoding and decoding the side tables
1029
1030 trait get_ty_str_ctxt {
1031     fn ty_str_ctxt(@self) -> @tyencode::ctxt;
1032 }
1033
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(),
1038                         ds: e::def_to_str,
1039                         tcx: self.tcx,
1040                         reachable: |a| encoder::reachable(self, a),
1041                         abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)}
1042     }
1043 }
1044
1045 #[cfg(stage0)]
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);
1056 }
1057
1058 #[cfg(not(stage0))]
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);
1070 }
1071
1072 impl ebml_writer_helpers for writer::Encoder {
1073     #[cfg(stage0)]
1074     fn emit_ty(&self, ecx: @e::EncodeContext, ty: ty::t) {
1075         do self.emit_opaque {
1076             e::write_type(ecx, self, ty)
1077         }
1078     }
1079
1080     #[cfg(not(stage0))]
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)
1084         }
1085     }
1086
1087     #[cfg(stage0)]
1088     fn emit_vstore(&self, ecx: @e::EncodeContext, vstore: ty::vstore) {
1089         do self.emit_opaque {
1090             e::write_vstore(ecx, self, vstore)
1091         }
1092     }
1093
1094     #[cfg(not(stage0))]
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)
1098         }
1099     }
1100
1101     #[cfg(stage0)]
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);
1105         }
1106     }
1107
1108     #[cfg(not(stage0))]
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);
1112         }
1113     }
1114
1115     #[cfg(stage0)]
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)
1119         }
1120     }
1121
1122     #[cfg(not(stage0))]
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)
1126         }
1127     }
1128
1129     #[cfg(stage0)]
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(),
1135                                          type_param_def)
1136         }
1137     }
1138
1139     #[cfg(not(stage0))]
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,
1145                                          ecx.ty_str_ctxt(),
1146                                          type_param_def)
1147         }
1148     }
1149
1150     #[cfg(stage0)]
1151     fn emit_tpbt(&self,
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)
1159                                 |type_param_def| {
1160                             self.emit_type_param_def(ecx, type_param_def);
1161                         }
1162                     }
1163                     do self.emit_field(~"region_param", 1) {
1164                         tpbt.generics.region_param.encode(self);
1165                     }
1166                 }
1167             }
1168             do self.emit_field(~"ty", 1) {
1169                 self.emit_ty(ecx, tpbt.ty);
1170             }
1171         }
1172     }
1173
1174     #[cfg(not(stage0))]
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);
1185                         }
1186                     }
1187                     do this.emit_struct_field(~"region_param", 1) |this| {
1188                         tpbt.generics.region_param.encode(this);
1189                     }
1190                 }
1191             }
1192             do this.emit_struct_field(~"ty", 1) |this| {
1193                 this.emit_ty(ecx, tpbt.ty);
1194             }
1195         }
1196     }
1197 }
1198
1199 #[cfg(stage0)]
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);
1203 }
1204
1205 #[cfg(not(stage0))]
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);
1209 }
1210
1211 #[cfg(stage0)]
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() }
1215     }
1216
1217     fn id(&self, id: ast::node_id) {
1218         self.wr_tagged_u64(c::tag_table_id as uint, id as u64)
1219     }
1220 }
1221
1222 #[cfg(not(stage0))]
1223 impl write_tag_and_id for writer::Encoder {
1224     fn tag(&mut self,
1225            tag_id: c::astencode_tag,
1226            f: &fn(&mut writer::Encoder)) {
1227         self.start_tag(tag_id as uint);
1228         f(self);
1229         self.end_tag();
1230     }
1231
1232     fn id(&mut self, id: ast::node_id) {
1233         self.wr_tagged_u64(c::tag_table_id as uint, id as u64)
1234     }
1235 }
1236
1237 #[cfg(stage0)]
1238 fn encode_side_tables_for_ii(ecx: @e::EncodeContext,
1239                              maps: Maps,
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(
1245             ii,
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)
1252             });
1253     }
1254 }
1255
1256 #[cfg(not(stage0))]
1257 fn encode_side_tables_for_ii(ecx: @e::EncodeContext,
1258                              maps: Maps,
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(
1264         ii,
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
1268             // balanced EBML.
1269             let mut new_ebml_w = copy new_ebml_w;
1270             encode_side_tables_for_id(ecx, maps, &mut new_ebml_w, id)
1271         });
1272     ebml_w.end_tag();
1273 }
1274
1275 #[cfg(stage0)]
1276 fn encode_side_tables_for_id(ecx: @e::EncodeContext,
1277                              maps: Maps,
1278                              ebml_w: &writer::Encoder,
1279                              id: ast::node_id) {
1280     let tcx = ecx.tcx;
1281
1282     debug!("Encoding side tables for id %d", id);
1283
1284     for tcx.def_map.find(&id).each |def| {
1285         do ebml_w.tag(c::tag_table_def) {
1286             ebml_w.id(id);
1287             do ebml_w.tag(c::tag_table_val) {
1288                 (*def).encode(ebml_w)
1289             }
1290         }
1291     }
1292
1293     for tcx.node_types.find(&(id as uint)).each |&ty| {
1294         do ebml_w.tag(c::tag_table_node_type) {
1295             ebml_w.id(id);
1296             do ebml_w.tag(c::tag_table_val) {
1297                 ebml_w.emit_ty(ecx, *ty);
1298             }
1299         }
1300     }
1301
1302     for tcx.node_type_substs.find(&id).each |tys| {
1303         do ebml_w.tag(c::tag_table_node_type_subst) {
1304             ebml_w.id(id);
1305             do ebml_w.tag(c::tag_table_val) {
1306                 // FIXME(#5562): removing this copy causes a segfault
1307                 //               before stage2
1308                 ebml_w.emit_tys(ecx, /*bad*/copy **tys)
1309             }
1310         }
1311     }
1312
1313     for tcx.freevars.find(&id).each |&fv| {
1314         do ebml_w.tag(c::tag_table_freevars) {
1315             ebml_w.id(id);
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)
1319                 }
1320             }
1321         }
1322     }
1323
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) {
1327             ebml_w.id(id);
1328             do ebml_w.tag(c::tag_table_val) {
1329                 ebml_w.emit_tpbt(ecx, *tpbt);
1330             }
1331         }
1332     }
1333
1334     for tcx.ty_param_defs.find(&id).each |&type_param_def| {
1335         do ebml_w.tag(c::tag_table_param_defs) {
1336             ebml_w.id(id);
1337             do ebml_w.tag(c::tag_table_val) {
1338                 ebml_w.emit_type_param_def(ecx, type_param_def)
1339             }
1340         }
1341     }
1342
1343     if maps.mutbl_map.contains(&id) {
1344         do ebml_w.tag(c::tag_table_mutbl) {
1345             ebml_w.id(id);
1346         }
1347     }
1348
1349     for maps.last_use_map.find(&id).each |&m| {
1350         do ebml_w.tag(c::tag_table_last_use) {
1351             ebml_w.id(id);
1352             do ebml_w.tag(c::tag_table_val) {
1353                 do ebml_w.emit_from_vec(/*bad*/ copy **m) |id| {
1354                     id.encode(ebml_w);
1355                 }
1356             }
1357         }
1358     }
1359
1360     for maps.method_map.find(&id).each |&mme| {
1361         do ebml_w.tag(c::tag_table_method_map) {
1362             ebml_w.id(id);
1363             do ebml_w.tag(c::tag_table_val) {
1364                 encode_method_map_entry(ecx, ebml_w, *mme)
1365             }
1366         }
1367     }
1368
1369     for maps.vtable_map.find(&id).each |&dr| {
1370         do ebml_w.tag(c::tag_table_vtable_map) {
1371             ebml_w.id(id);
1372             do ebml_w.tag(c::tag_table_val) {
1373                 encode_vtable_res(ecx, ebml_w, *dr);
1374             }
1375         }
1376     }
1377
1378     for tcx.adjustments.find(&id).each |adj| {
1379         do ebml_w.tag(c::tag_table_adjustments) {
1380             ebml_w.id(id);
1381             do ebml_w.tag(c::tag_table_val) {
1382                 (**adj).encode(ebml_w)
1383             }
1384         }
1385     }
1386
1387     if maps.moves_map.contains(&id) {
1388         do ebml_w.tag(c::tag_table_moves_map) {
1389             ebml_w.id(id);
1390         }
1391     }
1392
1393     for maps.capture_map.find(&id).each |&cap_vars| {
1394         do ebml_w.tag(c::tag_table_capture_map) {
1395             ebml_w.id(id);
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);
1399                 }
1400             }
1401         }
1402     }
1403 }
1404
1405 #[cfg(not(stage0))]
1406 fn encode_side_tables_for_id(ecx: @e::EncodeContext,
1407                              maps: Maps,
1408                              ebml_w: &mut writer::Encoder,
1409                              id: ast::node_id) {
1410     let tcx = ecx.tcx;
1411
1412     debug!("Encoding side tables for id %d", id);
1413
1414     for tcx.def_map.find(&id).each |def| {
1415         do ebml_w.tag(c::tag_table_def) |ebml_w| {
1416             ebml_w.id(id);
1417             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1418                 (*def).encode(ebml_w)
1419             }
1420         }
1421     }
1422
1423     for tcx.node_types.find(&(id as uint)).each |&ty| {
1424         do ebml_w.tag(c::tag_table_node_type) |ebml_w| {
1425             ebml_w.id(id);
1426             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1427                 ebml_w.emit_ty(ecx, *ty);
1428             }
1429         }
1430     }
1431
1432     for tcx.node_type_substs.find(&id).each |tys| {
1433         do ebml_w.tag(c::tag_table_node_type_subst) |ebml_w| {
1434             ebml_w.id(id);
1435             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1436                 // FIXME(#5562): removing this copy causes a segfault
1437                 //               before stage2
1438                 ebml_w.emit_tys(ecx, /*bad*/copy **tys)
1439             }
1440         }
1441     }
1442
1443     for tcx.freevars.find(&id).each |&fv| {
1444         do ebml_w.tag(c::tag_table_freevars) |ebml_w| {
1445             ebml_w.id(id);
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)
1449                 }
1450             }
1451         }
1452     }
1453
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| {
1457             ebml_w.id(id);
1458             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1459                 ebml_w.emit_tpbt(ecx, *tpbt);
1460             }
1461         }
1462     }
1463
1464     for tcx.ty_param_defs.find(&id).each |&type_param_def| {
1465         do ebml_w.tag(c::tag_table_param_defs) |ebml_w| {
1466             ebml_w.id(id);
1467             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1468                 ebml_w.emit_type_param_def(ecx, type_param_def)
1469             }
1470         }
1471     }
1472
1473     if maps.mutbl_map.contains(&id) {
1474         do ebml_w.tag(c::tag_table_mutbl) |ebml_w| {
1475             ebml_w.id(id);
1476         }
1477     }
1478
1479     for maps.last_use_map.find(&id).each |&m| {
1480         do ebml_w.tag(c::tag_table_last_use) |ebml_w| {
1481             ebml_w.id(id);
1482             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1483                 do ebml_w.emit_from_vec(/*bad*/ copy **m) |ebml_w, id| {
1484                     id.encode(ebml_w);
1485                 }
1486             }
1487         }
1488     }
1489
1490     for maps.method_map.find(&id).each |&mme| {
1491         do ebml_w.tag(c::tag_table_method_map) |ebml_w| {
1492             ebml_w.id(id);
1493             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1494                 encode_method_map_entry(ecx, ebml_w, *mme)
1495             }
1496         }
1497     }
1498
1499     for maps.vtable_map.find(&id).each |&dr| {
1500         do ebml_w.tag(c::tag_table_vtable_map) |ebml_w| {
1501             ebml_w.id(id);
1502             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1503                 encode_vtable_res(ecx, ebml_w, *dr);
1504             }
1505         }
1506     }
1507
1508     for tcx.adjustments.find(&id).each |adj| {
1509         do ebml_w.tag(c::tag_table_adjustments) |ebml_w| {
1510             ebml_w.id(id);
1511             do ebml_w.tag(c::tag_table_val) |ebml_w| {
1512                 (**adj).encode(ebml_w)
1513             }
1514         }
1515     }
1516
1517     if maps.moves_map.contains(&id) {
1518         do ebml_w.tag(c::tag_table_moves_map) |ebml_w| {
1519             ebml_w.id(id);
1520         }
1521     }
1522
1523     for maps.capture_map.find(&id).each |&cap_vars| {
1524         do ebml_w.tag(c::tag_table_capture_map) |ebml_w| {
1525             ebml_w.id(id);
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);
1529                 }
1530             }
1531         }
1532     }
1533 }
1534
1535 trait doc_decoder_helpers {
1536     fn as_int(&self) -> int;
1537     fn opt_child(&self, tag: c::astencode_tag) -> Option<ebml::Doc>;
1538 }
1539
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)
1544     }
1545 }
1546
1547 #[cfg(stage0)]
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;
1558 }
1559
1560 #[cfg(not(stage0))]
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,
1572                       did: ast::def_id)
1573                       -> ast::def_id;
1574 }
1575
1576 impl ebml_decoder_decoder_helpers for reader::Decoder {
1577     #[cfg(stage0)]
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))
1583         }
1584     }
1585
1586     #[cfg(not(stage0))]
1587     fn read_arg(&mut self, xcx: @ExtendedDecodeContext) -> ty::arg {
1588         do self.read_opaque |this, doc| {
1589             tydecode::parse_arg_data(
1590                 doc.data,
1591                 xcx.dcx.cdata.cnum,
1592                 doc.start,
1593                 xcx.dcx.tcx,
1594                 |s, a| this.convert_def_id(xcx, s, a))
1595         }
1596     }
1597
1598     #[cfg(stage0)]
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.
1604
1605         return do self.read_opaque |doc| {
1606
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));
1610
1611             debug!("read_ty(%s) = %s",
1612                    type_string(doc), ty_to_str(xcx.dcx.tcx, ty));
1613
1614             ty
1615         };
1616
1617         fn type_string(doc: ebml::Doc) -> ~str {
1618             let mut str = ~"";
1619             for uint::range(doc.start, doc.end) |i| {
1620                 str::push_char(&mut str, doc.data[i] as char);
1621             }
1622             str
1623         }
1624     }
1625
1626     #[cfg(not(stage0))]
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.
1632
1633         return do self.read_opaque |this, doc| {
1634             let ty = tydecode::parse_ty_data(
1635                 doc.data,
1636                 xcx.dcx.cdata.cnum,
1637                 doc.start,
1638                 xcx.dcx.tcx,
1639                 |s, a| this.convert_def_id(xcx, s, a));
1640
1641             debug!("read_ty(%s) = %s",
1642                    type_string(doc),
1643                    ty_to_str(xcx.dcx.tcx, ty));
1644
1645             ty
1646         };
1647
1648         fn type_string(doc: ebml::Doc) -> ~str {
1649             let mut str = ~"";
1650             for uint::range(doc.start, doc.end) |i| {
1651                 str::push_char(&mut str, doc.data[i] as char);
1652             }
1653             str
1654         }
1655     }
1656
1657     #[cfg(stage0)]
1658     fn read_tys(&self, xcx: @ExtendedDecodeContext) -> ~[ty::t] {
1659         self.read_to_vec(|| self.read_ty(xcx) )
1660     }
1661
1662     #[cfg(not(stage0))]
1663     fn read_tys(&mut self, xcx: @ExtendedDecodeContext) -> ~[ty::t] {
1664         self.read_to_vec(|this| this.read_ty(xcx) )
1665     }
1666
1667     #[cfg(stage0)]
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))
1674         }
1675     }
1676
1677     #[cfg(not(stage0))]
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(
1682                 doc.data,
1683                 doc.start,
1684                 xcx.dcx.cdata.cnum,
1685                 xcx.dcx.tcx,
1686                 |s, a| this.convert_def_id(xcx, s, a))
1687         }
1688     }
1689
1690     #[cfg(stage0)]
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) {
1697                         ty::Generics {
1698                             type_param_defs: self.read_field("type_param_defs", 0, || {
1699                                 @self.read_to_vec(|| self.read_type_param_def(xcx))
1700                             }),
1701                             region_param: self.read_field(~"region_param", 1, || {
1702                                 Decodable::decode(self)
1703                             })
1704                         }
1705                     }
1706                 },
1707                 ty: self.read_field(~"ty", 1, || {
1708                     self.read_ty(xcx)
1709                 })
1710             }
1711         }
1712     }
1713
1714     #[cfg(not(stage0))]
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| {
1721                         ty::Generics {
1722                             type_param_defs:
1723                                 this.read_struct_field("type_param_defs",
1724                                                        0,
1725                                                        |this| {
1726                                     @this.read_to_vec(|this|
1727                                         this.read_type_param_def(xcx))
1728                             }),
1729                             region_param:
1730                                 this.read_struct_field("region_param",
1731                                                        1,
1732                                                        |this| {
1733                                     Decodable::decode(this)
1734                                 })
1735                         }
1736                     }
1737                 },
1738                 ty: this.read_struct_field("ty", 1, |this| {
1739                     this.read_ty(xcx)
1740                 })
1741             }
1742         }
1743     }
1744
1745     #[cfg(stage0)]
1746     fn convert_def_id(&self,
1747                       xcx: @ExtendedDecodeContext,
1748                       source: tydecode::DefIdSource,
1749                       did: ast::def_id)
1750                       -> ast::def_id {
1751         /*!
1752          *
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.
1759          *
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.
1763          */
1764
1765         let r = match source {
1766             NominalType | TypeWithId => xcx.tr_def_id(did),
1767             TypeParameter => xcx.tr_intern_def_id(did)
1768         };
1769         debug!("convert_def_id(source=%?, did=%?)=%?", source, did, r);
1770         return r;
1771     }
1772
1773     #[cfg(not(stage0))]
1774     fn convert_def_id(&mut self,
1775                       xcx: @ExtendedDecodeContext,
1776                       source: tydecode::DefIdSource,
1777                       did: ast::def_id)
1778                       -> ast::def_id {
1779         /*!
1780          *
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.
1787          *
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.
1791          */
1792
1793         let r = match source {
1794             NominalType | TypeWithId => xcx.tr_def_id(did),
1795             TypeParameter => xcx.tr_intern_def_id(did)
1796         };
1797         debug!("convert_def_id(source=%?, did=%?)=%?", source, did, r);
1798         return r;
1799     }
1800 }
1801
1802 #[cfg(stage0)]
1803 fn decode_side_tables(xcx: @ExtendedDecodeContext,
1804                       ast_doc: ebml::Doc) {
1805     let dcx = xcx.dcx;
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);
1810
1811         debug!(">> Side table document with tag 0x%x \
1812                 found for id %d (orig %d)",
1813                tag, id, id0);
1814
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);
1819         } else {
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)
1836                 });
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())
1848                 });
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(
1852                     id,
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);
1859                 adj.tr(xcx);
1860                 dcx.tcx.adjustments.insert(id, adj);
1861             } else if tag == (c::tag_table_capture_map as uint) {
1862                 let cvars =
1863                     at_vec::from_owned(
1864                         val_dsr.read_to_vec(
1865                             || val_dsr.read_capture_var(xcx)));
1866                 dcx.maps.capture_map.insert(id, cvars);
1867             } else {
1868                 xcx.dcx.tcx.sess.bug(
1869                     fmt!("unknown tag found in side tables: %x", tag));
1870             }
1871         }
1872
1873         debug!(">< Side table doc loaded");
1874     }
1875 }
1876
1877 #[cfg(not(stage0))]
1878 fn decode_side_tables(xcx: @ExtendedDecodeContext,
1879                       ast_doc: ebml::Doc) {
1880     let dcx = xcx.dcx;
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);
1885
1886         debug!(">> Side table document with tag 0x%x \
1887                 found for id %d (orig %d)",
1888                tag, id, id0);
1889
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);
1894         } else {
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)
1912                 });
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())
1924                 });
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(
1928                     id,
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);
1935                 adj.tr(xcx);
1936                 dcx.tcx.adjustments.insert(id, adj);
1937             } else if tag == (c::tag_table_capture_map as uint) {
1938                 let cvars =
1939                     at_vec::from_owned(
1940                         val_dsr.read_to_vec(
1941                             |val_dsr| val_dsr.read_capture_var(xcx)));
1942                 dcx.maps.capture_map.insert(id, cvars);
1943             } else {
1944                 xcx.dcx.tcx.sess.bug(
1945                     fmt!("unknown tag found in side tables: %x", tag));
1946             }
1947         }
1948
1949         debug!(">< Side table doc loaded");
1950     }
1951 }
1952
1953 // ______________________________________________________________________
1954 // Testing of astencode_gen
1955
1956 #[cfg(test)]
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);
1960     ebml_w.end_tag();
1961 }
1962
1963 #[cfg(test)]
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)
1968 }
1969
1970 #[cfg(test)]
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;
1976 }
1977
1978 #[cfg(test)]
1979 type fake_session = @mut parse::ParseSess;
1980
1981 #[cfg(test)]
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 {
1986         codemap::span {
1987             lo: codemap::BytePos(0),
1988             hi: codemap::BytePos(0),
1989             expn_info: None
1990         }
1991     }
1992     fn ident_of(&self, st: ~str) -> ast::ident {
1993         self.interner.intern(@st)
1994     }
1995 }
1996
1997 #[cfg(test)]
1998 fn mk_ctxt() -> @fake_ext_ctxt {
1999     @parse::new_parse_sess(None) as @fake_ext_ctxt
2000 }
2001
2002 #[cfg(test)]
2003 fn roundtrip(in_item: Option<@ast::item>) {
2004     use core::io;
2005
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);
2010     };
2011     let ebml_doc = reader::Doc(@bytes);
2012     let out_item = decode_item_ast(ebml_doc);
2013
2014     assert_eq!(in_item, out_item);
2015 }
2016
2017 #[test]
2018 fn test_basic() {
2019     let ext_cx = mk_ctxt();
2020     roundtrip(quote_item!(
2021         fn foo() {}
2022     ));
2023 }
2024
2025 #[test]
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.
2030     ));
2031 }
2032
2033 #[test]
2034 fn test_more() {
2035     let ext_cx = mk_ctxt();
2036     roundtrip(quote_item!(
2037         fn foo(x: uint, y: uint) -> uint {
2038             let z = x + y;
2039             return z;
2040         }
2041     ));
2042 }
2043
2044 #[test]
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: ~[]};
2051         }
2052     ).get());
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: ~[]};
2057         }
2058     ).get());
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));
2065       }
2066       _ => fail!()
2067     }
2068 }