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