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