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