]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/astencode.rs
Convert most code to new inner attribute syntax.
[rust.git] / src / librustc / middle / astencode.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(non_camel_case_types)]
12 // FIXME: remove this after snapshot, and Results are handled
13 #![allow(unused_must_use)]
14
15 use c = metadata::common;
16 use cstore = metadata::cstore;
17 use driver::session::Session;
18 use metadata::decoder;
19 use e = metadata::encoder;
20 use middle::freevars::freevar_entry;
21 use middle::region;
22 use metadata::tydecode;
23 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
24                          RegionParameter};
25 use metadata::tyencode;
26 use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
27 use middle::{ty, typeck, moves};
28 use middle;
29 use util::ppaux::ty_to_str;
30
31 use syntax::{ast, ast_map, ast_util, codemap, fold};
32 use syntax::codemap::Span;
33 use syntax::fold::Folder;
34 use syntax::parse::token;
35 use syntax;
36
37 use std::libc;
38 use std::cast;
39 use std::cell::RefCell;
40 use std::io::Seek;
41 // FIXME: remove this attr after snapshot
42 #[cfg(not(stage0))]
43 use std::io::MemWriter;
44 use std::rc::Rc;
45
46 use serialize::ebml::reader;
47 use serialize::ebml;
48 use serialize;
49 use serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers};
50 use serialize::{Decoder, Decodable};
51 use writer = serialize::ebml::writer;
52
53 #[cfg(test)] use syntax::parse;
54 #[cfg(test)] use syntax::print::pprust;
55
56 // Auxiliary maps of things to be encoded
57 pub struct Maps {
58     root_map: middle::borrowck::root_map,
59     method_map: middle::typeck::MethodMap,
60     vtable_map: middle::typeck::vtable_map,
61     capture_map: RefCell<middle::moves::CaptureMap>,
62 }
63
64 struct DecodeContext<'a> {
65     cdata: @cstore::crate_metadata,
66     tcx: &'a ty::ctxt,
67     maps: &'a Maps
68 }
69
70 struct ExtendedDecodeContext<'a> {
71     dcx: &'a DecodeContext<'a>,
72     from_id_range: ast_util::IdRange,
73     to_id_range: ast_util::IdRange
74 }
75
76 trait tr {
77     fn tr(&self, xcx: &ExtendedDecodeContext) -> Self;
78 }
79
80 trait tr_intern {
81     fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
82 }
83
84 // FIXME: remove this Encoder type after snapshot
85 #[cfg(stage0)]
86 pub type Encoder<'a> = writer::Encoder<'a>;
87
88 #[cfg(not(stage0))]
89 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
90
91 // FIXME: remove unwrap_ and wrap_ after snapshot
92 #[cfg(stage0)]
93 fn unwrap_<T>(t: T) -> T {
94     t
95 }
96
97 #[cfg(not(stage0))]
98 fn unwrap_<T, E>(r: Result<T, E>) -> T {
99     r.unwrap()
100 }
101
102 #[cfg(stage0)]
103 fn wrap_<T>(t: T) -> T {
104     t
105 }
106
107 #[cfg(not(stage0))]
108 fn wrap_<T, E>(t: T) -> Result<T, E> {
109     Ok(t)
110 }
111
112
113
114 // ______________________________________________________________________
115 // Top-level methods.
116
117 pub fn encode_inlined_item(ecx: &e::EncodeContext,
118                            ebml_w: &mut Encoder,
119                            ii: e::InlinedItemRef,
120                            maps: &Maps) {
121     let id = match ii {
122         e::IIItemRef(i) => i.id,
123         e::IIForeignRef(i) => i.id,
124         e::IIMethodRef(_, _, m) => m.id,
125     };
126     debug!("> Encoding inlined item: {} ({})",
127            ecx.tcx.map.path_to_str(id),
128            ebml_w.writer.tell());
129
130     let ii = simplify_ast(ii);
131     let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
132
133     ebml_w.start_tag(c::tag_ast as uint);
134     id_range.encode(ebml_w);
135     encode_ast(ebml_w, ii);
136     encode_side_tables_for_ii(ecx, maps, ebml_w, &ii);
137     ebml_w.end_tag();
138
139     debug!("< Encoded inlined fn: {} ({})",
140            ecx.tcx.map.path_to_str(id),
141            ebml_w.writer.tell());
142 }
143
144 pub fn encode_exported_macro(ebml_w: &mut Encoder, i: &ast::Item) {
145     match i.node {
146         ast::ItemMac(..) => encode_ast(ebml_w, ast::IIItem(@i.clone())),
147         _ => fail!("expected a macro")
148     }
149 }
150
151 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
152                            tcx: &ty::ctxt,
153                            maps: &Maps,
154                            path: Vec<ast_map::PathElem>,
155                            par_doc: ebml::Doc)
156                            -> Result<ast::InlinedItem, Vec<ast_map::PathElem>> {
157     let dcx = &DecodeContext {
158         cdata: cdata,
159         tcx: tcx,
160         maps: maps
161     };
162     match par_doc.opt_child(c::tag_ast) {
163       None => Err(path),
164       Some(ast_doc) => {
165         let mut path_as_str = None;
166         debug!("> Decoding inlined fn: {}::?",
167         {
168             // Do an Option dance to use the path after it is moved below.
169             let s = ast_map::path_to_str(ast_map::Values(path.iter()));
170             path_as_str = Some(s);
171             path_as_str.as_ref().map(|x| x.as_slice())
172         });
173         let mut ast_dsr = reader::Decoder(ast_doc);
174         let from_id_range = unwrap_(Decodable::decode(&mut ast_dsr));
175         let to_id_range = reserve_id_range(&dcx.tcx.sess, from_id_range);
176         let xcx = &ExtendedDecodeContext {
177             dcx: dcx,
178             from_id_range: from_id_range,
179             to_id_range: to_id_range
180         };
181         let raw_ii = decode_ast(ast_doc);
182         let ii = renumber_and_map_ast(xcx, &dcx.tcx.map, path, raw_ii);
183         let ident = match ii {
184             ast::IIItem(i) => i.ident,
185             ast::IIForeign(i) => i.ident,
186             ast::IIMethod(_, _, m) => m.ident,
187         };
188         debug!("Fn named: {}", token::get_ident(ident));
189         debug!("< Decoded inlined fn: {}::{}",
190                path_as_str.unwrap(),
191                token::get_ident(ident));
192         region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, &ii);
193         decode_side_tables(xcx, ast_doc);
194         match ii {
195           ast::IIItem(i) => {
196             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
197                    syntax::print::pprust::item_to_str(i));
198           }
199           _ => { }
200         }
201         Ok(ii)
202       }
203     }
204 }
205
206 pub fn decode_exported_macro(par_doc: ebml::Doc) -> @ast::Item {
207     match decode_ast(par_doc) {
208         ast::IIItem(item) => item,
209         _ => fail!("expected item")
210     }
211 }
212
213 // ______________________________________________________________________
214 // Enumerating the IDs which appear in an AST
215
216 fn reserve_id_range(sess: &Session,
217                     from_id_range: ast_util::IdRange) -> ast_util::IdRange {
218     // Handle the case of an empty range:
219     if from_id_range.empty() { return from_id_range; }
220     let cnt = from_id_range.max - from_id_range.min;
221     let to_id_min = sess.reserve_node_ids(cnt);
222     let to_id_max = to_id_min + cnt;
223     ast_util::IdRange { min: to_id_min, max: to_id_max }
224 }
225
226 impl<'a> ExtendedDecodeContext<'a> {
227     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
228         /*!
229          * Translates an internal id, meaning a node id that is known
230          * to refer to some part of the item currently being inlined,
231          * such as a local variable or argument.  All naked node-ids
232          * that appear in types have this property, since if something
233          * might refer to an external item we would use a def-id to
234          * allow for the possibility that the item resides in another
235          * crate.
236          */
237
238         // from_id_range should be non-empty
239         assert!(!self.from_id_range.empty());
240         (id - self.from_id_range.min + self.to_id_range.min)
241     }
242     pub fn tr_def_id(&self, did: ast::DefId) -> ast::DefId {
243         /*!
244          * Translates an EXTERNAL def-id, converting the crate number
245          * from the one used in the encoded data to the current crate
246          * numbers..  By external, I mean that it be translated to a
247          * reference to the item in its original crate, as opposed to
248          * being translated to a reference to the inlined version of
249          * the item.  This is typically, but not always, what you
250          * want, because most def-ids refer to external things like
251          * types or other fns that may or may not be inlined.  Note
252          * that even when the inlined function is referencing itself
253          * recursively, we would want `tr_def_id` for that
254          * reference--- conceptually the function calls the original,
255          * non-inlined version, and trans deals with linking that
256          * recursive call to the inlined copy.
257          *
258          * However, there are a *few* cases where def-ids are used but
259          * we know that the thing being referenced is in fact *internal*
260          * to the item being inlined.  In those cases, you should use
261          * `tr_intern_def_id()` below.
262          */
263
264         decoder::translate_def_id(self.dcx.cdata, did)
265     }
266     pub fn tr_intern_def_id(&self, did: ast::DefId) -> ast::DefId {
267         /*!
268          * Translates an INTERNAL def-id, meaning a def-id that is
269          * known to refer to some part of the item currently being
270          * inlined.  In that case, we want to convert the def-id to
271          * refer to the current crate and to the new, inlined node-id.
272          */
273
274         assert_eq!(did.krate, ast::LOCAL_CRATE);
275         ast::DefId { krate: ast::LOCAL_CRATE, node: self.tr_id(did.node) }
276     }
277     pub fn tr_span(&self, _span: Span) -> Span {
278         codemap::DUMMY_SP // FIXME (#1972): handle span properly
279     }
280 }
281
282 impl tr_intern for ast::DefId {
283     fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId {
284         xcx.tr_intern_def_id(*self)
285     }
286 }
287
288 impl tr for ast::DefId {
289     fn tr(&self, xcx: &ExtendedDecodeContext) -> ast::DefId {
290         xcx.tr_def_id(*self)
291     }
292 }
293
294 impl tr for Option<ast::DefId> {
295     fn tr(&self, xcx: &ExtendedDecodeContext) -> Option<ast::DefId> {
296         self.map(|d| xcx.tr_def_id(d))
297     }
298 }
299
300 impl tr for Span {
301     fn tr(&self, xcx: &ExtendedDecodeContext) -> Span {
302         xcx.tr_span(*self)
303     }
304 }
305
306 trait def_id_encoder_helpers {
307     fn emit_def_id(&mut self, did: ast::DefId);
308 }
309
310 #[cfg(stage0)]
311 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
312     fn emit_def_id(&mut self, did: ast::DefId) {
313         did.encode(self)
314     }
315 }
316
317 #[cfg(not(stage0))]
318 impl<S:serialize::Encoder<E>, E> def_id_encoder_helpers for S {
319     fn emit_def_id(&mut self, did: ast::DefId) {
320         unwrap_(did.encode(self))
321     }
322 }
323
324 trait def_id_decoder_helpers {
325     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId;
326     fn read_def_id_noxcx(&mut self,
327                          cdata: @cstore::crate_metadata) -> ast::DefId;
328 }
329
330 #[cfg(stage0)]
331 impl<D:serialize::Decoder> def_id_decoder_helpers for D {
332     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
333         let did: ast::DefId = unwrap_(Decodable::decode(self));
334         did.tr(xcx)
335     }
336
337     fn read_def_id_noxcx(&mut self,
338                          cdata: @cstore::crate_metadata) -> ast::DefId {
339         let did: ast::DefId = unwrap_(Decodable::decode(self));
340         decoder::translate_def_id(cdata, did)
341     }
342 }
343
344 #[cfg(not(stage0))]
345 impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
346     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
347         let did: ast::DefId = unwrap_(Decodable::decode(self));
348         did.tr(xcx)
349     }
350
351     fn read_def_id_noxcx(&mut self,
352                          cdata: @cstore::crate_metadata) -> ast::DefId {
353         let did: ast::DefId = unwrap_(Decodable::decode(self));
354         decoder::translate_def_id(cdata, did)
355     }
356 }
357
358 // ______________________________________________________________________
359 // Encoding and decoding the AST itself
360 //
361 // The hard work is done by an autogenerated module astencode_gen.  To
362 // regenerate astencode_gen, run src/etc/gen-astencode.  It will
363 // replace astencode_gen with a dummy file and regenerate its
364 // contents.  If you get compile errors, the dummy file
365 // remains---resolve the errors and then rerun astencode_gen.
366 // Annoying, I know, but hopefully only temporary.
367 //
368 // When decoding, we have to renumber the AST so that the node ids that
369 // appear within are disjoint from the node ids in our existing ASTs.
370 // We also have to adjust the spans: for now we just insert a dummy span,
371 // but eventually we should add entries to the local codemap as required.
372
373 fn encode_ast(ebml_w: &mut Encoder, item: ast::InlinedItem) {
374     ebml_w.start_tag(c::tag_tree as uint);
375     item.encode(ebml_w);
376     ebml_w.end_tag();
377 }
378
379 struct NestedItemsDropper;
380
381 impl Folder for NestedItemsDropper {
382     fn fold_block(&mut self, blk: ast::P<ast::Block>) -> ast::P<ast::Block> {
383         let stmts_sans_items = blk.stmts.iter().filter_map(|stmt| {
384             match stmt.node {
385                 ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => Some(*stmt),
386                 ast::StmtDecl(decl, _) => {
387                     match decl.node {
388                         ast::DeclLocal(_) => Some(*stmt),
389                         ast::DeclItem(_) => None,
390                     }
391                 }
392                 ast::StmtMac(..) => fail!("unexpanded macro in astencode")
393             }
394         }).collect();
395         let blk_sans_items = ast::P(ast::Block {
396             view_items: Vec::new(), // I don't know if we need the view_items
397                                     // here, but it doesn't break tests!
398             stmts: stmts_sans_items,
399             expr: blk.expr,
400             id: blk.id,
401             rules: blk.rules,
402             span: blk.span,
403         });
404         fold::noop_fold_block(blk_sans_items, self)
405     }
406 }
407
408 // Produces a simplified copy of the AST which does not include things
409 // that we do not need to or do not want to export.  For example, we
410 // do not include any nested items: if these nested items are to be
411 // inlined, their AST will be exported separately (this only makes
412 // sense because, in Rust, nested items are independent except for
413 // their visibility).
414 //
415 // As it happens, trans relies on the fact that we do not export
416 // nested items, as otherwise it would get confused when translating
417 // inlined items.
418 fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
419     let mut fld = NestedItemsDropper;
420
421     match ii {
422         // HACK we're not dropping items.
423         e::IIItemRef(i) => ast::IIItem(fold::noop_fold_item(i, &mut fld)
424                                        .expect_one("expected one item")),
425         e::IIMethodRef(d, p, m) => ast::IIMethod(d, p, fold::noop_fold_method(m, &mut fld)),
426         e::IIForeignRef(i) => ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
427     }
428 }
429
430 fn decode_ast(par_doc: ebml::Doc) -> ast::InlinedItem {
431     let chi_doc = par_doc.get(c::tag_tree as uint);
432     let mut d = reader::Decoder(chi_doc);
433     unwrap_(Decodable::decode(&mut d))
434 }
435
436 struct AstRenumberer<'a> {
437     xcx: &'a ExtendedDecodeContext<'a>,
438 }
439
440 impl<'a> ast_map::FoldOps for AstRenumberer<'a> {
441     fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
442         if id == ast::DUMMY_NODE_ID {
443             // Used by ast_map to map the NodeInlinedParent.
444             self.xcx.dcx.tcx.sess.next_node_id()
445         } else {
446             self.xcx.tr_id(id)
447         }
448     }
449     fn new_span(&self, span: Span) -> Span {
450         self.xcx.tr_span(span)
451     }
452 }
453
454 fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
455                         map: &ast_map::Map,
456                         path: Vec<ast_map::PathElem> ,
457                         ii: ast::InlinedItem) -> ast::InlinedItem {
458     ast_map::map_decoded_item(map,
459                               path.move_iter().collect(),
460                               AstRenumberer { xcx: xcx },
461                               |fld| {
462         match ii {
463             ast::IIItem(i) => {
464                 ast::IIItem(fld.fold_item(i).expect_one("expected one item"))
465             }
466             ast::IIMethod(d, is_provided, m) => {
467                 ast::IIMethod(xcx.tr_def_id(d), is_provided, fld.fold_method(m))
468             }
469             ast::IIForeign(i) => ast::IIForeign(fld.fold_foreign_item(i))
470         }
471     })
472 }
473
474 // ______________________________________________________________________
475 // Encoding and decoding of ast::def
476
477 fn decode_def(xcx: &ExtendedDecodeContext, doc: ebml::Doc) -> ast::Def {
478     let mut dsr = reader::Decoder(doc);
479     let def: ast::Def = unwrap_(Decodable::decode(&mut dsr));
480     def.tr(xcx)
481 }
482
483 impl tr for ast::Def {
484     fn tr(&self, xcx: &ExtendedDecodeContext) -> ast::Def {
485         match *self {
486           ast::DefFn(did, p) => ast::DefFn(did.tr(xcx), p),
487           ast::DefStaticMethod(did, wrapped_did2, p) => {
488             ast::DefStaticMethod(did.tr(xcx),
489                                    match wrapped_did2 {
490                                     ast::FromTrait(did2) => {
491                                         ast::FromTrait(did2.tr(xcx))
492                                     }
493                                     ast::FromImpl(did2) => {
494                                         ast::FromImpl(did2.tr(xcx))
495                                     }
496                                    },
497                                    p)
498           }
499           ast::DefMethod(did0, did1) => {
500             ast::DefMethod(did0.tr(xcx), did1.map(|did1| did1.tr(xcx)))
501           }
502           ast::DefSelfTy(nid) => { ast::DefSelfTy(xcx.tr_id(nid)) }
503           ast::DefMod(did) => { ast::DefMod(did.tr(xcx)) }
504           ast::DefForeignMod(did) => { ast::DefForeignMod(did.tr(xcx)) }
505           ast::DefStatic(did, m) => { ast::DefStatic(did.tr(xcx), m) }
506           ast::DefArg(nid, b) => { ast::DefArg(xcx.tr_id(nid), b) }
507           ast::DefLocal(nid, b) => { ast::DefLocal(xcx.tr_id(nid), b) }
508           ast::DefVariant(e_did, v_did, is_s) => {
509             ast::DefVariant(e_did.tr(xcx), v_did.tr(xcx), is_s)
510           },
511           ast::DefTrait(did) => ast::DefTrait(did.tr(xcx)),
512           ast::DefTy(did) => ast::DefTy(did.tr(xcx)),
513           ast::DefPrimTy(p) => ast::DefPrimTy(p),
514           ast::DefTyParam(did, v) => ast::DefTyParam(did.tr(xcx), v),
515           ast::DefBinding(nid, bm) => ast::DefBinding(xcx.tr_id(nid), bm),
516           ast::DefUse(did) => ast::DefUse(did.tr(xcx)),
517           ast::DefUpvar(nid1, def, nid2, nid3) => {
518             ast::DefUpvar(xcx.tr_id(nid1),
519                            @(*def).tr(xcx),
520                            xcx.tr_id(nid2),
521                            xcx.tr_id(nid3))
522           }
523           ast::DefStruct(did) => ast::DefStruct(did.tr(xcx)),
524           ast::DefRegion(nid) => ast::DefRegion(xcx.tr_id(nid)),
525           ast::DefTyParamBinder(nid) => {
526             ast::DefTyParamBinder(xcx.tr_id(nid))
527           }
528           ast::DefLabel(nid) => ast::DefLabel(xcx.tr_id(nid))
529         }
530     }
531 }
532
533 // ______________________________________________________________________
534 // Encoding and decoding of adjustment information
535
536 impl tr for ty::AutoDerefRef {
537     fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef {
538         ty::AutoDerefRef {
539             autoderefs: self.autoderefs,
540             autoref: match self.autoref {
541                 Some(ref autoref) => Some(autoref.tr(xcx)),
542                 None => None
543             }
544         }
545     }
546 }
547
548 impl tr for ty::AutoRef {
549     fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::AutoRef {
550         self.map_region(|r| r.tr(xcx))
551     }
552 }
553
554 impl tr for ty::Region {
555     fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::Region {
556         match *self {
557             ty::ReLateBound(id, br) => ty::ReLateBound(xcx.tr_id(id),
558                                                        br.tr(xcx)),
559             ty::ReEarlyBound(id, index, ident) => ty::ReEarlyBound(xcx.tr_id(id),
560                                                                      index,
561                                                                      ident),
562             ty::ReScope(id) => ty::ReScope(xcx.tr_id(id)),
563             ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => *self,
564             ty::ReFree(ref fr) => {
565                 ty::ReFree(ty::FreeRegion {scope_id: xcx.tr_id(fr.scope_id),
566                                             bound_region: fr.bound_region.tr(xcx)})
567             }
568         }
569     }
570 }
571
572 impl tr for ty::BoundRegion {
573     fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::BoundRegion {
574         match *self {
575             ty::BrAnon(_) |
576             ty::BrFresh(_) => *self,
577             ty::BrNamed(id, ident) => ty::BrNamed(xcx.tr_def_id(id),
578                                                     ident),
579         }
580     }
581 }
582
583 // ______________________________________________________________________
584 // Encoding and decoding of freevar information
585
586 fn encode_freevar_entry(ebml_w: &mut Encoder, fv: @freevar_entry) {
587     unwrap_((*fv).encode(ebml_w))
588 }
589
590 trait ebml_decoder_helper {
591     fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
592                           -> freevar_entry;
593 }
594
595 impl<'a> ebml_decoder_helper for reader::Decoder<'a> {
596     fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
597                           -> freevar_entry {
598         let fv: freevar_entry = unwrap_(Decodable::decode(self));
599         fv.tr(xcx)
600     }
601 }
602
603 impl tr for freevar_entry {
604     fn tr(&self, xcx: &ExtendedDecodeContext) -> freevar_entry {
605         freevar_entry {
606             def: self.def.tr(xcx),
607             span: self.span.tr(xcx),
608         }
609     }
610 }
611
612 // ______________________________________________________________________
613 // Encoding and decoding of CaptureVar information
614
615 trait capture_var_helper {
616     fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
617                         -> moves::CaptureVar;
618 }
619
620 impl<'a> capture_var_helper for reader::Decoder<'a> {
621     fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
622                         -> moves::CaptureVar {
623         let cvar: moves::CaptureVar = unwrap_(Decodable::decode(self));
624         cvar.tr(xcx)
625     }
626 }
627
628 impl tr for moves::CaptureVar {
629     fn tr(&self, xcx: &ExtendedDecodeContext) -> moves::CaptureVar {
630         moves::CaptureVar {
631             def: self.def.tr(xcx),
632             span: self.span.tr(xcx),
633             mode: self.mode
634         }
635     }
636 }
637
638 // ______________________________________________________________________
639 // Encoding and decoding of MethodCallee
640
641 trait read_method_callee_helper {
642     fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee);
643 }
644
645 fn encode_method_callee(ecx: &e::EncodeContext,
646                         ebml_w: &mut Encoder,
647                         autoderef: u32,
648                         method: &MethodCallee) {
649     unwrap_(ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
650         ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
651             autoderef.encode(ebml_w)
652         });
653         ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
654             method.origin.encode(ebml_w)
655         });
656         ebml_w.emit_struct_field("ty", 2u, |ebml_w| {
657             wrap_(ebml_w.emit_ty(ecx, method.ty))
658         });
659         ebml_w.emit_struct_field("substs", 3u, |ebml_w| {
660             wrap_(ebml_w.emit_substs(ecx, &method.substs))
661         })
662     }));
663 }
664
665 impl<'a> read_method_callee_helper for reader::Decoder<'a> {
666     fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee) {
667         unwrap_(self.read_struct("MethodCallee", 4, |this| {
668             let autoderef = unwrap_(this.read_struct_field("autoderef", 0, |this| {
669                 Decodable::decode(this)
670             }));
671             wrap_((autoderef, MethodCallee {
672                 origin: unwrap_(this.read_struct_field("origin", 1, |this| {
673                     let method_origin: MethodOrigin =
674                         unwrap_(Decodable::decode(this));
675                     wrap_(method_origin.tr(xcx))
676                 })),
677                 ty: unwrap_(this.read_struct_field("ty", 2, |this| {
678                     wrap_(this.read_ty(xcx))
679                 })),
680                 substs: unwrap_(this.read_struct_field("substs", 3, |this| {
681                     wrap_(this.read_substs(xcx))
682                 }))
683             }))
684         }))
685     }
686 }
687
688 impl tr for MethodOrigin {
689     fn tr(&self, xcx: &ExtendedDecodeContext) -> MethodOrigin {
690         match *self {
691             typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(xcx)),
692             typeck::MethodParam(ref mp) => {
693                 typeck::MethodParam(
694                     typeck::MethodParam {
695                         trait_id: mp.trait_id.tr(xcx),
696                         .. *mp
697                     }
698                 )
699             }
700             typeck::MethodObject(ref mo) => {
701                 typeck::MethodObject(
702                     typeck::MethodObject {
703                         trait_id: mo.trait_id.tr(xcx),
704                         .. *mo
705                     }
706                 )
707             }
708         }
709     }
710 }
711
712 // ______________________________________________________________________
713 // Encoding and decoding vtable_res
714
715 fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
716                               ebml_w: &mut Encoder,
717                               autoderef: u32,
718                               dr: typeck::vtable_res) {
719     unwrap_(ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
720         ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
721             autoderef.encode(ebml_w)
722         });
723         ebml_w.emit_struct_field("vtable_res", 1u, |ebml_w| {
724             wrap_(encode_vtable_res(ecx, ebml_w, dr))
725         })
726     }))
727 }
728
729 pub fn encode_vtable_res(ecx: &e::EncodeContext,
730                      ebml_w: &mut Encoder,
731                      dr: typeck::vtable_res) {
732     // can't autogenerate this code because automatic code of
733     // ty::t doesn't work, and there is no way (atm) to have
734     // hand-written encoding routines combine with auto-generated
735     // ones.  perhaps we should fix this.
736     unwrap_(ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
737         wrap_(encode_vtable_param_res(ecx, ebml_w, *param_tables))
738     }))
739 }
740
741 pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
742                      ebml_w: &mut Encoder,
743                      param_tables: typeck::vtable_param_res) {
744     unwrap_(ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| {
745         wrap_(encode_vtable_origin(ecx, ebml_w, vtable_origin))
746     }))
747 }
748
749
750 pub fn encode_vtable_origin(ecx: &e::EncodeContext,
751                         ebml_w: &mut Encoder,
752                         vtable_origin: &typeck::vtable_origin) {
753     unwrap_(ebml_w.emit_enum("vtable_origin", |ebml_w| {
754         match *vtable_origin {
755           typeck::vtable_static(def_id, ref tys, vtable_res) => {
756             ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| {
757                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
758                     wrap_(ebml_w.emit_def_id(def_id))
759                 });
760                 ebml_w.emit_enum_variant_arg(1u, |ebml_w| {
761                     wrap_(ebml_w.emit_tys(ecx, tys.as_slice()))
762                 });
763                 ebml_w.emit_enum_variant_arg(2u, |ebml_w| {
764                     wrap_(encode_vtable_res(ecx, ebml_w, vtable_res))
765                 })
766             })
767           }
768           typeck::vtable_param(pn, bn) => {
769             ebml_w.emit_enum_variant("vtable_param", 1u, 2u, |ebml_w| {
770                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
771                     pn.encode(ebml_w)
772                 });
773                 ebml_w.emit_enum_variant_arg(1u, |ebml_w| {
774                     ebml_w.emit_uint(bn)
775                 })
776             })
777           }
778         }
779     }))
780 }
781
782 pub trait vtable_decoder_helpers {
783     fn read_vtable_res_with_key(&mut self,
784                                 tcx: &ty::ctxt,
785                                 cdata: @cstore::crate_metadata)
786                                 -> (u32, typeck::vtable_res);
787     fn read_vtable_res(&mut self,
788                        tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
789                       -> typeck::vtable_res;
790     fn read_vtable_param_res(&mut self,
791                        tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
792                       -> typeck::vtable_param_res;
793     fn read_vtable_origin(&mut self,
794                           tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
795                           -> typeck::vtable_origin;
796 }
797
798 impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
799     fn read_vtable_res_with_key(&mut self,
800                                 tcx: &ty::ctxt,
801                                 cdata: @cstore::crate_metadata)
802                                 -> (u32, typeck::vtable_res) {
803         unwrap_(self.read_struct("VtableWithKey", 2, |this| {
804             let autoderef = unwrap_(this.read_struct_field("autoderef", 0, |this| {
805                 Decodable::decode(this)
806             }));
807             wrap_((autoderef, unwrap_(this.read_struct_field("vtable_res", 1, |this| {
808                 wrap_(this.read_vtable_res(tcx, cdata))
809             }))))
810         }))
811     }
812
813     fn read_vtable_res(&mut self,
814                        tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
815                       -> typeck::vtable_res {
816         @unwrap_(self.read_to_vec(|this|
817                           wrap_(this.read_vtable_param_res(tcx, cdata))))
818              .move_iter()
819              .collect()
820     }
821
822     fn read_vtable_param_res(&mut self,
823                              tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
824                       -> typeck::vtable_param_res {
825         @unwrap_(self.read_to_vec(|this|
826                           wrap_(this.read_vtable_origin(tcx, cdata))))
827              .move_iter()
828              .collect()
829     }
830
831     fn read_vtable_origin(&mut self,
832                           tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
833         -> typeck::vtable_origin {
834         unwrap_(self.read_enum("vtable_origin", |this| {
835             this.read_enum_variant(["vtable_static",
836                                     "vtable_param",
837                                     "vtable_self"],
838                                    |this, i| {
839                 wrap_(match i {
840                   0 => {
841                     typeck::vtable_static(
842                         unwrap_(this.read_enum_variant_arg(0u, |this| {
843                             wrap_(this.read_def_id_noxcx(cdata))
844                         })),
845                         unwrap_(this.read_enum_variant_arg(1u, |this| {
846                             wrap_(this.read_tys_noxcx(tcx, cdata))
847                         })),
848                         unwrap_(this.read_enum_variant_arg(2u, |this| {
849                             wrap_(this.read_vtable_res(tcx, cdata))
850                         }))
851                     )
852                   }
853                   1 => {
854                     typeck::vtable_param(
855                         unwrap_(this.read_enum_variant_arg(0u, |this| {
856                             Decodable::decode(this)
857                         })),
858                         unwrap_(this.read_enum_variant_arg(1u, |this| {
859                             this.read_uint()
860                         }))
861                     )
862                   }
863                   // hard to avoid - user input
864                   _ => fail!("bad enum variant")
865                 })
866             })
867         }))
868     }
869 }
870
871 // ______________________________________________________________________
872 // Encoding and decoding the side tables
873
874 trait get_ty_str_ctxt {
875     fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a>;
876 }
877
878 impl<'a> get_ty_str_ctxt for e::EncodeContext<'a> {
879     fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a> {
880         tyencode::ctxt {
881             diag: self.tcx.sess.diagnostic(),
882             ds: e::def_to_str,
883             tcx: self.tcx,
884             abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)
885         }
886     }
887 }
888
889 trait ebml_writer_helpers {
890     fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t);
891     fn emit_vstore(&mut self, ecx: &e::EncodeContext, vstore: ty::vstore);
892     fn emit_tys(&mut self, ecx: &e::EncodeContext, tys: &[ty::t]);
893     fn emit_type_param_def(&mut self,
894                            ecx: &e::EncodeContext,
895                            type_param_def: &ty::TypeParameterDef);
896     fn emit_tpbt(&mut self,
897                  ecx: &e::EncodeContext,
898                  tpbt: ty::ty_param_bounds_and_ty);
899     fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &ty::substs);
900     fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment);
901 }
902
903 impl<'a> ebml_writer_helpers for Encoder<'a> {
904     fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t) {
905         self.emit_opaque(|this| wrap_(e::write_type(ecx, this, ty)));
906     }
907
908     fn emit_vstore(&mut self, ecx: &e::EncodeContext, vstore: ty::vstore) {
909         self.emit_opaque(|this| wrap_(e::write_vstore(ecx, this, vstore)));
910     }
911
912     fn emit_tys(&mut self, ecx: &e::EncodeContext, tys: &[ty::t]) {
913         self.emit_from_vec(tys, |this, ty| wrap_(this.emit_ty(ecx, *ty)));
914     }
915
916     fn emit_type_param_def(&mut self,
917                            ecx: &e::EncodeContext,
918                            type_param_def: &ty::TypeParameterDef) {
919         self.emit_opaque(|this| {
920             wrap_(tyencode::enc_type_param_def(this.writer,
921                                          &ecx.ty_str_ctxt(),
922                                          type_param_def))
923         });
924     }
925
926     fn emit_tpbt(&mut self,
927                  ecx: &e::EncodeContext,
928                  tpbt: ty::ty_param_bounds_and_ty) {
929         self.emit_struct("ty_param_bounds_and_ty", 2, |this| {
930             this.emit_struct_field("generics", 0, |this| {
931                 this.emit_struct("Generics", 2, |this| {
932                     this.emit_struct_field("type_param_defs", 0, |this| {
933                         this.emit_from_vec(tpbt.generics.type_param_defs(),
934                                            |this, type_param_def| {
935                             wrap_(this.emit_type_param_def(ecx, type_param_def))
936                         })
937                     });
938                     this.emit_struct_field("region_param_defs", 1, |this| {
939                         tpbt.generics.region_param_defs().encode(this)
940                     })
941                 })
942             });
943             this.emit_struct_field("ty", 1, |this| {
944                 wrap_(this.emit_ty(ecx, tpbt.ty))
945             })
946         });
947     }
948
949     fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &ty::substs) {
950         self.emit_opaque(|this| wrap_(tyencode::enc_substs(this.writer,
951                                                            &ecx.ty_str_ctxt(),
952                                                            substs)));
953     }
954
955     fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment) {
956         self.emit_enum("AutoAdjustment", |this| {
957             match *adj {
958                 ty::AutoAddEnv(region, sigil) => {
959                     this.emit_enum_variant("AutoAddEnv", 0, 2, |this| {
960                         this.emit_enum_variant_arg(0, |this| region.encode(this));
961                         this.emit_enum_variant_arg(1, |this| sigil.encode(this))
962                     })
963                 }
964
965                 ty::AutoDerefRef(ref auto_deref_ref) => {
966                     this.emit_enum_variant("AutoDerefRef", 1, 1, |this| {
967                         this.emit_enum_variant_arg(0, |this| auto_deref_ref.encode(this))
968                     })
969                 }
970
971                 ty::AutoObject(sigil, region, m, b, def_id, ref substs) => {
972                     this.emit_enum_variant("AutoObject", 2, 6, |this| {
973                         this.emit_enum_variant_arg(0, |this| sigil.encode(this));
974                         this.emit_enum_variant_arg(1, |this| region.encode(this));
975                         this.emit_enum_variant_arg(2, |this| m.encode(this));
976                         this.emit_enum_variant_arg(3, |this| b.encode(this));
977                         this.emit_enum_variant_arg(4, |this| def_id.encode(this));
978                         this.emit_enum_variant_arg(5, |this| wrap_(this.emit_substs(ecx, substs)))
979                     })
980                 }
981             }
982         });
983     }
984 }
985
986 trait write_tag_and_id {
987     fn tag(&mut self, tag_id: c::astencode_tag, f: |&mut Self|);
988     fn id(&mut self, id: ast::NodeId);
989 }
990
991 impl<'a> write_tag_and_id for Encoder<'a> {
992     fn tag(&mut self,
993            tag_id: c::astencode_tag,
994            f: |&mut Encoder<'a>|) {
995         self.start_tag(tag_id as uint);
996         f(self);
997         self.end_tag();
998     }
999
1000     fn id(&mut self, id: ast::NodeId) {
1001         self.wr_tagged_u64(c::tag_table_id as uint, id as u64);
1002     }
1003 }
1004
1005 struct SideTableEncodingIdVisitor<'a,'b> {
1006     ecx_ptr: *libc::c_void,
1007     new_ebml_w: &'a mut Encoder<'b>,
1008     maps: &'a Maps,
1009 }
1010
1011 impl<'a,'b> ast_util::IdVisitingOperation for
1012         SideTableEncodingIdVisitor<'a,'b> {
1013     fn visit_id(&self, id: ast::NodeId) {
1014         // Note: this will cause a copy of ebml_w, which is bad as
1015         // it is mutable. But I believe it's harmless since we generate
1016         // balanced EBML.
1017         //
1018         // FIXME(pcwalton): Don't copy this way.
1019         let mut new_ebml_w = unsafe {
1020             self.new_ebml_w.unsafe_clone()
1021         };
1022         // See above
1023         let ecx: &e::EncodeContext = unsafe {
1024             cast::transmute(self.ecx_ptr)
1025         };
1026         encode_side_tables_for_id(ecx, self.maps, &mut new_ebml_w, id)
1027     }
1028 }
1029
1030 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
1031                              maps: &Maps,
1032                              ebml_w: &mut Encoder,
1033                              ii: &ast::InlinedItem) {
1034     ebml_w.start_tag(c::tag_table as uint);
1035     let mut new_ebml_w = unsafe {
1036         ebml_w.unsafe_clone()
1037     };
1038
1039     // Because the ast visitor uses @IdVisitingOperation, I can't pass in
1040     // ecx directly, but /I/ know that it'll be fine since the lifetime is
1041     // tied to the CrateContext that lives throughout this entire section.
1042     ast_util::visit_ids_for_inlined_item(ii, &SideTableEncodingIdVisitor {
1043         ecx_ptr: unsafe {
1044             cast::transmute(ecx)
1045         },
1046         new_ebml_w: &mut new_ebml_w,
1047         maps: maps,
1048     });
1049     ebml_w.end_tag();
1050 }
1051
1052 fn encode_side_tables_for_id(ecx: &e::EncodeContext,
1053                              maps: &Maps,
1054                              ebml_w: &mut Encoder,
1055                              id: ast::NodeId) {
1056     let tcx = ecx.tcx;
1057
1058     debug!("Encoding side tables for id {}", id);
1059
1060     for def in tcx.def_map.borrow().find(&id).iter() {
1061         ebml_w.tag(c::tag_table_def, |ebml_w| {
1062             ebml_w.id(id);
1063             ebml_w.tag(c::tag_table_val, |ebml_w| unwrap_((*def).encode(ebml_w)));
1064         })
1065     }
1066
1067     for &ty in tcx.node_types.borrow().find(&(id as uint)).iter() {
1068         ebml_w.tag(c::tag_table_node_type, |ebml_w| {
1069             ebml_w.id(id);
1070             ebml_w.tag(c::tag_table_val, |ebml_w| {
1071                 ebml_w.emit_ty(ecx, *ty);
1072             })
1073         })
1074     }
1075
1076     for tys in tcx.node_type_substs.borrow().find(&id).iter() {
1077         ebml_w.tag(c::tag_table_node_type_subst, |ebml_w| {
1078             ebml_w.id(id);
1079             ebml_w.tag(c::tag_table_val, |ebml_w| {
1080                 ebml_w.emit_tys(ecx, tys.as_slice())
1081             })
1082         })
1083     }
1084
1085     for &fv in tcx.freevars.borrow().find(&id).iter() {
1086         ebml_w.tag(c::tag_table_freevars, |ebml_w| {
1087             ebml_w.id(id);
1088             ebml_w.tag(c::tag_table_val, |ebml_w| {
1089                 ebml_w.emit_from_vec(fv.as_slice(), |ebml_w, fv_entry| {
1090                     wrap_(encode_freevar_entry(ebml_w, *fv_entry))
1091                 });
1092             })
1093         })
1094     }
1095
1096     let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
1097     for &tpbt in tcx.tcache.borrow().find(&lid).iter() {
1098         ebml_w.tag(c::tag_table_tcache, |ebml_w| {
1099             ebml_w.id(id);
1100             ebml_w.tag(c::tag_table_val, |ebml_w| {
1101                 ebml_w.emit_tpbt(ecx, tpbt.clone());
1102             })
1103         })
1104     }
1105
1106     for &type_param_def in tcx.ty_param_defs.borrow().find(&id).iter() {
1107         ebml_w.tag(c::tag_table_param_defs, |ebml_w| {
1108             ebml_w.id(id);
1109             ebml_w.tag(c::tag_table_val, |ebml_w| {
1110                 ebml_w.emit_type_param_def(ecx, type_param_def)
1111             })
1112         })
1113     }
1114
1115     let method_call = MethodCall::expr(id);
1116     for &method in maps.method_map.borrow().find(&method_call).iter() {
1117         ebml_w.tag(c::tag_table_method_map, |ebml_w| {
1118             ebml_w.id(id);
1119             ebml_w.tag(c::tag_table_val, |ebml_w| {
1120                 encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
1121             })
1122         })
1123     }
1124
1125     for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
1126         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
1127             ebml_w.id(id);
1128             ebml_w.tag(c::tag_table_val, |ebml_w| {
1129                 encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
1130             })
1131         })
1132     }
1133
1134     for adj in tcx.adjustments.borrow().find(&id).iter() {
1135         match ***adj {
1136             ty::AutoDerefRef(adj) => {
1137                 for autoderef in range(0, adj.autoderefs) {
1138                     let method_call = MethodCall::autoderef(id, autoderef as u32);
1139                     for &method in maps.method_map.borrow().find(&method_call).iter() {
1140                         ebml_w.tag(c::tag_table_method_map, |ebml_w| {
1141                             ebml_w.id(id);
1142                             ebml_w.tag(c::tag_table_val, |ebml_w| {
1143                                 encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
1144                             })
1145                         })
1146                     }
1147
1148                     for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
1149                         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
1150                             ebml_w.id(id);
1151                             ebml_w.tag(c::tag_table_val, |ebml_w| {
1152                                 encode_vtable_res_with_key(ecx, ebml_w,
1153                                                            method_call.autoderef, *dr);
1154                             })
1155                         })
1156                     }
1157                 }
1158             }
1159             _ => {}
1160         }
1161
1162         ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
1163             ebml_w.id(id);
1164             ebml_w.tag(c::tag_table_val, |ebml_w| {
1165                 ebml_w.emit_auto_adjustment(ecx, **adj);
1166             })
1167         })
1168     }
1169
1170     for &cap_vars in maps.capture_map.borrow().find(&id).iter() {
1171         ebml_w.tag(c::tag_table_capture_map, |ebml_w| {
1172             ebml_w.id(id);
1173             ebml_w.tag(c::tag_table_val, |ebml_w| {
1174                 ebml_w.emit_from_vec(cap_vars.as_slice(), |ebml_w, cap_var| {
1175                     cap_var.encode(ebml_w)
1176                 });
1177             })
1178         })
1179     }
1180 }
1181
1182 trait doc_decoder_helpers {
1183     fn as_int(&self) -> int;
1184     fn opt_child(&self, tag: c::astencode_tag) -> Option<Self>;
1185 }
1186
1187 impl<'a> doc_decoder_helpers for ebml::Doc<'a> {
1188     fn as_int(&self) -> int { reader::doc_as_u64(*self) as int }
1189     fn opt_child(&self, tag: c::astencode_tag) -> Option<ebml::Doc<'a>> {
1190         reader::maybe_get_doc(*self, tag as uint)
1191     }
1192 }
1193
1194 trait ebml_decoder_decoder_helpers {
1195     fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t;
1196     fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t>;
1197     fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
1198                            -> ty::TypeParameterDef;
1199     fn read_ty_param_bounds_and_ty(&mut self, xcx: &ExtendedDecodeContext)
1200                                 -> ty::ty_param_bounds_and_ty;
1201     fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> ty::substs;
1202     fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
1203     fn convert_def_id(&mut self,
1204                       xcx: &ExtendedDecodeContext,
1205                       source: DefIdSource,
1206                       did: ast::DefId)
1207                       -> ast::DefId;
1208
1209     // Versions of the type reading functions that don't need the full
1210     // ExtendedDecodeContext.
1211     fn read_ty_noxcx(&mut self,
1212                      tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t;
1213     fn read_tys_noxcx(&mut self,
1214                       tcx: &ty::ctxt,
1215                       cdata: @cstore::crate_metadata) -> Vec<ty::t>;
1216 }
1217
1218 impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
1219     fn read_ty_noxcx(&mut self,
1220                      tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
1221         unwrap_(self.read_opaque(|_, doc| {
1222             wrap_(tydecode::parse_ty_data(
1223                 doc.data,
1224                 cdata.cnum,
1225                 doc.start,
1226                 tcx,
1227                 |_, id| decoder::translate_def_id(cdata, id)))
1228         }))
1229     }
1230
1231     fn read_tys_noxcx(&mut self,
1232                       tcx: &ty::ctxt,
1233                       cdata: @cstore::crate_metadata) -> Vec<ty::t> {
1234         unwrap_(self.read_to_vec(|this| wrap_(this.read_ty_noxcx(tcx, cdata)) ))
1235             .move_iter()
1236             .collect()
1237     }
1238
1239     fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t {
1240         // Note: regions types embed local node ids.  In principle, we
1241         // should translate these node ids into the new decode
1242         // context.  However, we do not bother, because region types
1243         // are not used during trans.
1244
1245         return unwrap_(self.read_opaque(|this, doc| {
1246             debug!("read_ty({})", type_string(doc));
1247
1248             let ty = tydecode::parse_ty_data(
1249                 doc.data,
1250                 xcx.dcx.cdata.cnum,
1251                 doc.start,
1252                 xcx.dcx.tcx,
1253                 |s, a| this.convert_def_id(xcx, s, a));
1254
1255             wrap_(ty)
1256         }));
1257
1258         fn type_string(doc: ebml::Doc) -> ~str {
1259             let mut str = ~"";
1260             for i in range(doc.start, doc.end) {
1261                 str.push_char(doc.data[i] as char);
1262             }
1263             str
1264         }
1265     }
1266
1267     fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t> {
1268         unwrap_(self.read_to_vec(|this| wrap_(this.read_ty(xcx)))).move_iter().collect()
1269     }
1270
1271     fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
1272                            -> ty::TypeParameterDef {
1273         unwrap_(self.read_opaque(|this, doc| {
1274             wrap_(tydecode::parse_type_param_def_data(
1275                 doc.data,
1276                 doc.start,
1277                 xcx.dcx.cdata.cnum,
1278                 xcx.dcx.tcx,
1279                 |s, a| this.convert_def_id(xcx, s, a)))
1280         }))
1281     }
1282
1283     fn read_ty_param_bounds_and_ty(&mut self, xcx: &ExtendedDecodeContext)
1284                                    -> ty::ty_param_bounds_and_ty {
1285         unwrap_(self.read_struct("ty_param_bounds_and_ty", 2, |this| {
1286             wrap_(ty::ty_param_bounds_and_ty {
1287                 generics: unwrap_(this.read_struct_field("generics", 0, |this| {
1288                     this.read_struct("Generics", 2, |this| {
1289                         wrap_(ty::Generics {
1290                             type_param_defs:
1291                                 unwrap_(this.read_struct_field("type_param_defs",
1292                                                        0,
1293                                                        |this| {
1294                                     wrap_(Rc::new(unwrap_(this.read_to_vec(|this|
1295                                                              wrap_(this.read_type_param_def(xcx))))
1296                                                 .move_iter()
1297                                                 .collect()))
1298                             })),
1299                             region_param_defs:
1300                                 unwrap_(this.read_struct_field("region_param_defs",
1301                                                        1,
1302                                                        |this| {
1303                                     Decodable::decode(this)
1304                                 }))
1305                         })
1306                     })
1307                 })),
1308                 ty: unwrap_(this.read_struct_field("ty", 1, |this| {
1309                     wrap_(this.read_ty(xcx))
1310                 }))
1311             })
1312         }))
1313     }
1314
1315     fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> ty::substs {
1316         unwrap_(self.read_opaque(|this, doc| {
1317             wrap_(tydecode::parse_substs_data(doc.data,
1318                                         xcx.dcx.cdata.cnum,
1319                                         doc.start,
1320                                         xcx.dcx.tcx,
1321                                         |s, a| this.convert_def_id(xcx, s, a)))
1322         }))
1323     }
1324
1325     fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment {
1326         unwrap_(self.read_enum("AutoAdjustment", |this| {
1327             let variants = ["AutoAddEnv", "AutoDerefRef", "AutoObject"];
1328             this.read_enum_variant(variants, |this, i| {
1329                 wrap_(match i {
1330                     0 => {
1331                         let region: ty::Region =
1332                             unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
1333                         let sigil: ast::Sigil =
1334                             unwrap_(this.read_enum_variant_arg(1, |this| Decodable::decode(this)));
1335
1336                         ty:: AutoAddEnv(region.tr(xcx), sigil)
1337                     }
1338                     1 => {
1339                         let auto_deref_ref: ty::AutoDerefRef =
1340                             unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
1341
1342                         ty::AutoDerefRef(auto_deref_ref.tr(xcx))
1343                     }
1344                     2 => {
1345                         let sigil: ast::Sigil =
1346                             unwrap_(this.read_enum_variant_arg(0, |this| Decodable::decode(this)));
1347                         let region: Option<ty::Region> =
1348                             unwrap_(this.read_enum_variant_arg(1, |this| Decodable::decode(this)));
1349                         let m: ast::Mutability =
1350                             unwrap_(this.read_enum_variant_arg(2, |this| Decodable::decode(this)));
1351                         let b: ty::BuiltinBounds =
1352                             unwrap_(this.read_enum_variant_arg(3, |this| Decodable::decode(this)));
1353                         let def_id: ast::DefId =
1354                             unwrap_(this.read_enum_variant_arg(4, |this| Decodable::decode(this)));
1355                         let substs = unwrap_(
1356                             this.read_enum_variant_arg(5, |this| wrap_(this.read_substs(xcx))));
1357
1358                         let region = match region {
1359                             Some(r) => Some(r.tr(xcx)),
1360                             None => None
1361                         };
1362
1363                         ty::AutoObject(sigil, region, m, b, def_id.tr(xcx), substs)
1364                     }
1365                     _ => fail!("bad enum variant for ty::AutoAdjustment")
1366                 })
1367             })
1368         }))
1369     }
1370
1371     fn convert_def_id(&mut self,
1372                       xcx: &ExtendedDecodeContext,
1373                       source: tydecode::DefIdSource,
1374                       did: ast::DefId)
1375                       -> ast::DefId {
1376         /*!
1377          * Converts a def-id that appears in a type.  The correct
1378          * translation will depend on what kind of def-id this is.
1379          * This is a subtle point: type definitions are not
1380          * inlined into the current crate, so if the def-id names
1381          * a nominal type or type alias, then it should be
1382          * translated to refer to the source crate.
1383          *
1384          * However, *type parameters* are cloned along with the function
1385          * they are attached to.  So we should translate those def-ids
1386          * to refer to the new, cloned copy of the type parameter.
1387          * We only see references to free type parameters in the body of
1388          * an inlined function. In such cases, we need the def-id to
1389          * be a local id so that the TypeContents code is able to lookup
1390          * the relevant info in the ty_param_defs table.
1391          *
1392          * *Region parameters*, unfortunately, are another kettle of fish.
1393          * In such cases, def_id's can appear in types to distinguish
1394          * shadowed bound regions and so forth. It doesn't actually
1395          * matter so much what we do to these, since regions are erased
1396          * at trans time, but it's good to keep them consistent just in
1397          * case. We translate them with `tr_def_id()` which will map
1398          * the crate numbers back to the original source crate.
1399          *
1400          * It'd be really nice to refactor the type repr to not include
1401          * def-ids so that all these distinctions were unnecessary.
1402          */
1403
1404         let r = match source {
1405             NominalType | TypeWithId | RegionParameter => xcx.tr_def_id(did),
1406             TypeParameter => xcx.tr_intern_def_id(did)
1407         };
1408         debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
1409         return r;
1410     }
1411 }
1412
1413 fn decode_side_tables(xcx: &ExtendedDecodeContext,
1414                       ast_doc: ebml::Doc) {
1415     let dcx = xcx.dcx;
1416     let tbl_doc = ast_doc.get(c::tag_table as uint);
1417     reader::docs(tbl_doc, |tag, entry_doc| {
1418         let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
1419         let id = xcx.tr_id(id0 as ast::NodeId);
1420
1421         debug!(">> Side table document with tag 0x{:x} \
1422                 found for id {} (orig {})",
1423                tag, id, id0);
1424
1425         match c::astencode_tag::from_uint(tag) {
1426             None => {
1427                 xcx.dcx.tcx.sess.bug(
1428                     format!("unknown tag found in side tables: {:x}", tag));
1429             }
1430             Some(value) => {
1431                 let val_doc = entry_doc.get(c::tag_table_val as uint);
1432                 let mut val_dsr = reader::Decoder(val_doc);
1433                 let val_dsr = &mut val_dsr;
1434
1435                 match value {
1436                     c::tag_table_def => {
1437                         let def = decode_def(xcx, val_doc);
1438                         dcx.tcx.def_map.borrow_mut().insert(id, def);
1439                     }
1440                     c::tag_table_node_type => {
1441                         let ty = val_dsr.read_ty(xcx);
1442                         debug!("inserting ty for node {:?}: {}",
1443                                id, ty_to_str(dcx.tcx, ty));
1444                         dcx.tcx.node_types.borrow_mut().insert(id as uint, ty);
1445                     }
1446                     c::tag_table_node_type_subst => {
1447                         let tys = val_dsr.read_tys(xcx);
1448                         dcx.tcx.node_type_substs.borrow_mut().insert(id, tys);
1449                     }
1450                     c::tag_table_freevars => {
1451                         let fv_info = @unwrap_(val_dsr.read_to_vec(|val_dsr| {
1452                             wrap_(@val_dsr.read_freevar_entry(xcx))
1453                         })).move_iter().collect();
1454                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
1455                     }
1456                     c::tag_table_tcache => {
1457                         let tpbt = val_dsr.read_ty_param_bounds_and_ty(xcx);
1458                         let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
1459                         dcx.tcx.tcache.borrow_mut().insert(lid, tpbt);
1460                     }
1461                     c::tag_table_param_defs => {
1462                         let bounds = val_dsr.read_type_param_def(xcx);
1463                         dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
1464                     }
1465                     c::tag_table_method_map => {
1466                         let (autoderef, method) = val_dsr.read_method_callee(xcx);
1467                         let method_call = MethodCall {
1468                             expr_id: id,
1469                             autoderef: autoderef
1470                         };
1471                         dcx.maps.method_map.borrow_mut().insert(method_call, method);
1472                     }
1473                     c::tag_table_vtable_map => {
1474                         let (autoderef, vtable_res) =
1475                             val_dsr.read_vtable_res_with_key(xcx.dcx.tcx,
1476                                                              xcx.dcx.cdata);
1477                         let vtable_key = MethodCall {
1478                             expr_id: id,
1479                             autoderef: autoderef
1480                         };
1481                         dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
1482                     }
1483                     c::tag_table_adjustments => {
1484                         let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx);
1485                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
1486                     }
1487                     c::tag_table_capture_map => {
1488                         let cvars =
1489                                 unwrap_(val_dsr.read_to_vec(
1490                                             |val_dsr| wrap_(val_dsr.read_capture_var(xcx))))
1491                                        .move_iter()
1492                                        .collect();
1493                         dcx.maps.capture_map.borrow_mut().insert(id, Rc::new(cvars));
1494                     }
1495                     _ => {
1496                         xcx.dcx.tcx.sess.bug(
1497                             format!("unknown tag found in side tables: {:x}", tag));
1498                     }
1499                 }
1500             }
1501         }
1502
1503         debug!(">< Side table doc loaded");
1504         true
1505     });
1506 }
1507
1508 // ______________________________________________________________________
1509 // Testing of astencode_gen
1510
1511 #[cfg(test)]
1512 fn encode_item_ast(ebml_w: &mut Encoder, item: @ast::Item) {
1513     ebml_w.start_tag(c::tag_tree as uint);
1514     (*item).encode(ebml_w);
1515     ebml_w.end_tag();
1516 }
1517
1518 #[cfg(test)]
1519 fn decode_item_ast(par_doc: ebml::Doc) -> @ast::Item {
1520     let chi_doc = par_doc.get(c::tag_tree as uint);
1521     let mut d = reader::Decoder(chi_doc);
1522     @unwrap_(Decodable::decode(&mut d))
1523 }
1524
1525 #[cfg(test)]
1526 trait fake_ext_ctxt {
1527     fn cfg(&self) -> ast::CrateConfig;
1528     fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess;
1529     fn call_site(&self) -> Span;
1530     fn ident_of(&self, st: &str) -> ast::Ident;
1531 }
1532
1533 #[cfg(test)]
1534 impl fake_ext_ctxt for parse::ParseSess {
1535     fn cfg(&self) -> ast::CrateConfig {
1536         Vec::new()
1537     }
1538     fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { self }
1539     fn call_site(&self) -> Span {
1540         codemap::Span {
1541             lo: codemap::BytePos(0),
1542             hi: codemap::BytePos(0),
1543             expn_info: None
1544         }
1545     }
1546     fn ident_of(&self, st: &str) -> ast::Ident {
1547         token::str_to_ident(st)
1548     }
1549 }
1550
1551 #[cfg(test)]
1552 fn mk_ctxt() -> parse::ParseSess {
1553     parse::new_parse_sess()
1554 }
1555
1556 #[cfg(test)]
1557 fn roundtrip(in_item: Option<@ast::Item>) {
1558     use std::io::MemWriter;
1559
1560     let in_item = in_item.unwrap();
1561     let mut wr = MemWriter::new();
1562     {
1563         let mut ebml_w = writer::Encoder(&mut wr);
1564         encode_item_ast(&mut ebml_w, in_item);
1565     }
1566     let ebml_doc = reader::Doc(wr.get_ref());
1567     let out_item = decode_item_ast(ebml_doc);
1568
1569     assert!(in_item == out_item);
1570 }
1571
1572 #[test]
1573 fn test_basic() {
1574     let cx = mk_ctxt();
1575     roundtrip(quote_item!(cx,
1576         fn foo() {}
1577     ));
1578 }
1579
1580 #[test]
1581 fn test_smalltalk() {
1582     let cx = mk_ctxt();
1583     roundtrip(quote_item!(cx,
1584         fn foo() -> int { 3 + 4 } // first smalltalk program ever executed.
1585     ));
1586 }
1587
1588 #[test]
1589 fn test_more() {
1590     let cx = mk_ctxt();
1591     roundtrip(quote_item!(cx,
1592         fn foo(x: uint, y: uint) -> uint {
1593             let z = x + y;
1594             return z;
1595         }
1596     ));
1597 }
1598
1599 #[test]
1600 fn test_simplification() {
1601     let cx = mk_ctxt();
1602     let item = quote_item!(&cx,
1603         fn new_int_alist<B>() -> alist<int, B> {
1604             fn eq_int(a: int, b: int) -> bool { a == b }
1605             return alist {eq_fn: eq_int, data: Vec::new()};
1606         }
1607     ).unwrap();
1608     let item_in = e::IIItemRef(item);
1609     let item_out = simplify_ast(item_in);
1610     let item_exp = ast::IIItem(quote_item!(cx,
1611         fn new_int_alist<B>() -> alist<int, B> {
1612             return alist {eq_fn: eq_int, data: Vec::new()};
1613         }
1614     ).unwrap());
1615     match (item_out, item_exp) {
1616       (ast::IIItem(item_out), ast::IIItem(item_exp)) => {
1617         assert!(pprust::item_to_str(item_out) == pprust::item_to_str(item_exp));
1618       }
1619       _ => fail!()
1620     }
1621 }