]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/astencode.rs
debuginfo: Make debuginfo source location assignment more stable (Pt. 1)
[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 metadata::common as c;
16 use metadata::cstore as cstore;
17 use session::Session;
18 use metadata::decoder;
19 use middle::def;
20 use metadata::encoder as e;
21 use middle::region;
22 use metadata::tydecode;
23 use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
24 use metadata::tydecode::{RegionParameter, UnboxedClosureSource};
25 use metadata::tyencode;
26 use middle::mem_categorization::Typer;
27 use middle::subst;
28 use middle::subst::VecPerParamSpace;
29 use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
30 use util::ppaux::ty_to_string;
31
32 use syntax::{ast, ast_map, ast_util, codemap, fold};
33 use syntax::ast_util::PostExpansionMethod;
34 use syntax::codemap::Span;
35 use syntax::fold::Folder;
36 use syntax::parse::token;
37 use syntax::ptr::P;
38 use syntax;
39
40 use std::io::Seek;
41 use std::rc::Rc;
42
43 use rbml::io::SeekableMemWriter;
44 use rbml::{reader, writer};
45 use rbml;
46 use serialize;
47 use serialize::{Decodable, Decoder, DecoderHelpers, Encodable};
48 use serialize::{EncoderHelpers};
49
50 #[cfg(test)] use syntax::parse;
51 #[cfg(test)] use syntax::print::pprust;
52
53 struct DecodeContext<'a, 'b, 'tcx: 'a> {
54     tcx: &'a ty::ctxt<'tcx>,
55     cdata: &'b cstore::crate_metadata,
56     from_id_range: ast_util::IdRange,
57     to_id_range: ast_util::IdRange
58 }
59
60 trait tr {
61     fn tr(&self, dcx: &DecodeContext) -> Self;
62 }
63
64 trait tr_intern {
65     fn tr_intern(&self, dcx: &DecodeContext) -> ast::DefId;
66 }
67
68 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
69
70 // ______________________________________________________________________
71 // Top-level methods.
72
73 pub fn encode_inlined_item(ecx: &e::EncodeContext,
74                            rbml_w: &mut Encoder,
75                            ii: e::InlinedItemRef) {
76     let id = match ii {
77         e::IIItemRef(i) => i.id,
78         e::IIForeignRef(i) => i.id,
79         e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
80         e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
81         e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.ty_param.id,
82         e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id,
83         e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id,
84     };
85     debug!("> Encoding inlined item: {} ({:?})",
86            ecx.tcx.map.path_to_string(id),
87            rbml_w.writer.tell());
88
89     // Folding could be avoided with a smarter encoder.
90     let ii = simplify_ast(ii);
91     let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
92
93     rbml_w.start_tag(c::tag_ast as uint);
94     id_range.encode(rbml_w);
95     encode_ast(rbml_w, &ii);
96     encode_side_tables_for_ii(ecx, rbml_w, &ii);
97     rbml_w.end_tag();
98
99     debug!("< Encoded inlined fn: {} ({:?})",
100            ecx.tcx.map.path_to_string(id),
101            rbml_w.writer.tell());
102 }
103
104 impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
105     fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
106         if id == ast::DUMMY_NODE_ID {
107             // Used by ast_map to map the NodeInlinedParent.
108             self.tcx.sess.next_node_id()
109         } else {
110             self.tr_id(id)
111         }
112     }
113     fn new_def_id(&self, def_id: ast::DefId) -> ast::DefId {
114         self.tr_def_id(def_id)
115     }
116     fn new_span(&self, span: Span) -> Span {
117         self.tr_span(span)
118     }
119 }
120
121 pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
122                                  tcx: &ty::ctxt<'tcx>,
123                                  path: Vec<ast_map::PathElem>,
124                                  par_doc: rbml::Doc)
125                                  -> Result<&'tcx ast::InlinedItem, Vec<ast_map::PathElem>> {
126     match par_doc.opt_child(c::tag_ast) {
127       None => Err(path),
128       Some(ast_doc) => {
129         let mut path_as_str = None;
130         debug!("> Decoding inlined fn: {:?}::?",
131         {
132             // Do an Option dance to use the path after it is moved below.
133             let s = ast_map::path_to_string(ast_map::Values(path.iter()));
134             path_as_str = Some(s);
135             path_as_str.as_ref().map(|x| &x[])
136         });
137         let mut ast_dsr = reader::Decoder::new(ast_doc);
138         let from_id_range = Decodable::decode(&mut ast_dsr).unwrap();
139         let to_id_range = reserve_id_range(&tcx.sess, from_id_range);
140         let dcx = &DecodeContext {
141             cdata: cdata,
142             tcx: tcx,
143             from_id_range: from_id_range,
144             to_id_range: to_id_range
145         };
146         let raw_ii = decode_ast(ast_doc);
147         let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, raw_ii, dcx);
148
149         let ident = match *ii {
150             ast::IIItem(ref i) => i.ident,
151             ast::IIForeign(ref i) => i.ident,
152             ast::IITraitItem(_, ref ti) => {
153                 match *ti {
154                     ast::ProvidedMethod(ref m) => m.pe_ident(),
155                     ast::RequiredMethod(ref ty_m) => ty_m.ident,
156                     ast::TypeTraitItem(ref ti) => ti.ty_param.ident,
157                 }
158             },
159             ast::IIImplItem(_, ref m) => {
160                 match *m {
161                     ast::MethodImplItem(ref m) => m.pe_ident(),
162                     ast::TypeImplItem(ref ti) => ti.ident,
163                 }
164             }
165         };
166         debug!("Fn named: {}", token::get_ident(ident));
167         debug!("< Decoded inlined fn: {}::{}",
168                path_as_str.unwrap(),
169                token::get_ident(ident));
170         region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii);
171         decode_side_tables(dcx, ast_doc);
172         match *ii {
173           ast::IIItem(ref i) => {
174             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
175                    syntax::print::pprust::item_to_string(&**i));
176           }
177           _ => { }
178         }
179         Ok(ii)
180       }
181     }
182 }
183
184 // ______________________________________________________________________
185 // Enumerating the IDs which appear in an AST
186
187 fn reserve_id_range(sess: &Session,
188                     from_id_range: ast_util::IdRange) -> ast_util::IdRange {
189     // Handle the case of an empty range:
190     if from_id_range.empty() { return from_id_range; }
191     let cnt = from_id_range.max - from_id_range.min;
192     let to_id_min = sess.reserve_node_ids(cnt);
193     let to_id_max = to_id_min + cnt;
194     ast_util::IdRange { min: to_id_min, max: to_id_max }
195 }
196
197 impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
198     /// Translates an internal id, meaning a node id that is known to refer to some part of the
199     /// item currently being inlined, such as a local variable or argument.  All naked node-ids
200     /// that appear in types have this property, since if something might refer to an external item
201     /// we would use a def-id to allow for the possibility that the item resides in another crate.
202     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
203         // from_id_range should be non-empty
204         assert!(!self.from_id_range.empty());
205         (id - self.from_id_range.min + self.to_id_range.min)
206     }
207
208     /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
209     /// data to the current crate numbers..  By external, I mean that it be translated to a
210     /// reference to the item in its original crate, as opposed to being translated to a reference
211     /// to the inlined version of the item.  This is typically, but not always, what you want,
212     /// because most def-ids refer to external things like types or other fns that may or may not
213     /// be inlined.  Note that even when the inlined function is referencing itself recursively, we
214     /// would want `tr_def_id` for that reference--- conceptually the function calls the original,
215     /// non-inlined version, and trans deals with linking that recursive call to the inlined copy.
216     ///
217     /// However, there are a *few* cases where def-ids are used but we know that the thing being
218     /// referenced is in fact *internal* to the item being inlined.  In those cases, you should use
219     /// `tr_intern_def_id()` below.
220     pub fn tr_def_id(&self, did: ast::DefId) -> ast::DefId {
221
222         decoder::translate_def_id(self.cdata, did)
223     }
224
225     /// Translates an INTERNAL def-id, meaning a def-id that is
226     /// known to refer to some part of the item currently being
227     /// inlined.  In that case, we want to convert the def-id to
228     /// refer to the current crate and to the new, inlined node-id.
229     pub fn tr_intern_def_id(&self, did: ast::DefId) -> ast::DefId {
230         assert_eq!(did.krate, ast::LOCAL_CRATE);
231         ast::DefId { krate: ast::LOCAL_CRATE, node: self.tr_id(did.node) }
232     }
233     pub fn tr_span(&self, _span: Span) -> Span {
234         codemap::DUMMY_SP // FIXME (#1972): handle span properly
235     }
236 }
237
238 impl tr_intern for ast::DefId {
239     fn tr_intern(&self, dcx: &DecodeContext) -> ast::DefId {
240         dcx.tr_intern_def_id(*self)
241     }
242 }
243
244 impl tr for ast::DefId {
245     fn tr(&self, dcx: &DecodeContext) -> ast::DefId {
246         dcx.tr_def_id(*self)
247     }
248 }
249
250 impl tr for Option<ast::DefId> {
251     fn tr(&self, dcx: &DecodeContext) -> Option<ast::DefId> {
252         self.map(|d| dcx.tr_def_id(d))
253     }
254 }
255
256 impl tr for Span {
257     fn tr(&self, dcx: &DecodeContext) -> Span {
258         dcx.tr_span(*self)
259     }
260 }
261
262 trait def_id_encoder_helpers {
263     fn emit_def_id(&mut self, did: ast::DefId);
264 }
265
266 impl<S:serialize::Encoder> def_id_encoder_helpers for S {
267     fn emit_def_id(&mut self, did: ast::DefId) {
268         did.encode(self).ok().unwrap()
269     }
270 }
271
272 trait def_id_decoder_helpers {
273     fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId;
274     fn read_def_id_nodcx(&mut self,
275                          cdata: &cstore::crate_metadata) -> ast::DefId;
276 }
277
278 impl<D:serialize::Decoder> def_id_decoder_helpers for D {
279     fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId {
280         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
281         did.tr(dcx)
282     }
283
284     fn read_def_id_nodcx(&mut self,
285                          cdata: &cstore::crate_metadata) -> ast::DefId {
286         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
287         decoder::translate_def_id(cdata, did)
288     }
289 }
290
291 // ______________________________________________________________________
292 // Encoding and decoding the AST itself
293 //
294 // The hard work is done by an autogenerated module astencode_gen.  To
295 // regenerate astencode_gen, run src/etc/gen-astencode.  It will
296 // replace astencode_gen with a dummy file and regenerate its
297 // contents.  If you get compile errors, the dummy file
298 // remains---resolve the errors and then rerun astencode_gen.
299 // Annoying, I know, but hopefully only temporary.
300 //
301 // When decoding, we have to renumber the AST so that the node ids that
302 // appear within are disjoint from the node ids in our existing ASTs.
303 // We also have to adjust the spans: for now we just insert a dummy span,
304 // but eventually we should add entries to the local codemap as required.
305
306 fn encode_ast(rbml_w: &mut Encoder, item: &ast::InlinedItem) {
307     rbml_w.start_tag(c::tag_tree as uint);
308     item.encode(rbml_w);
309     rbml_w.end_tag();
310 }
311
312 struct NestedItemsDropper;
313
314 impl Folder for NestedItemsDropper {
315     fn fold_block(&mut self, blk: P<ast::Block>) -> P<ast::Block> {
316         blk.and_then(|ast::Block {id, stmts, expr, rules, span, ..}| {
317             let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
318                 let use_stmt = match stmt.node {
319                     ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
320                     ast::StmtDecl(ref decl, _) => {
321                         match decl.node {
322                             ast::DeclLocal(_) => true,
323                             ast::DeclItem(_) => false,
324                         }
325                     }
326                     ast::StmtMac(..) => panic!("unexpanded macro in astencode")
327                 };
328                 if use_stmt {
329                     Some(stmt)
330                 } else {
331                     None
332                 }
333             }).collect();
334             let blk_sans_items = P(ast::Block {
335                 view_items: Vec::new(), // I don't know if we need the view_items
336                                         // here, but it doesn't break tests!
337                 stmts: stmts_sans_items,
338                 expr: expr,
339                 id: id,
340                 rules: rules,
341                 span: span,
342             });
343             fold::noop_fold_block(blk_sans_items, self)
344         })
345     }
346 }
347
348 // Produces a simplified copy of the AST which does not include things
349 // that we do not need to or do not want to export.  For example, we
350 // do not include any nested items: if these nested items are to be
351 // inlined, their AST will be exported separately (this only makes
352 // sense because, in Rust, nested items are independent except for
353 // their visibility).
354 //
355 // As it happens, trans relies on the fact that we do not export
356 // nested items, as otherwise it would get confused when translating
357 // inlined items.
358 fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
359     let mut fld = NestedItemsDropper;
360
361     match ii {
362         // HACK we're not dropping items.
363         e::IIItemRef(i) => {
364             ast::IIItem(fold::noop_fold_item(P(i.clone()), &mut fld)
365                             .expect_one("expected one item"))
366         }
367         e::IITraitItemRef(d, ti) => {
368             ast::IITraitItem(d, match *ti {
369                 ast::ProvidedMethod(ref m) => {
370                     ast::ProvidedMethod(
371                         fold::noop_fold_method(m.clone(), &mut fld)
372                             .expect_one("noop_fold_method must produce \
373                                          exactly one method"))
374                 }
375                 ast::RequiredMethod(ref ty_m) => {
376                     ast::RequiredMethod(
377                         fold::noop_fold_type_method(ty_m.clone(), &mut fld))
378                 }
379                 ast::TypeTraitItem(ref associated_type) => {
380                     ast::TypeTraitItem(
381                         P(fold::noop_fold_associated_type(
382                             (**associated_type).clone(),
383                             &mut fld)))
384                 }
385             })
386         }
387         e::IIImplItemRef(d, m) => {
388             ast::IIImplItem(d, match *m {
389                 ast::MethodImplItem(ref m) => {
390                     ast::MethodImplItem(
391                         fold::noop_fold_method(m.clone(), &mut fld)
392                             .expect_one("noop_fold_method must produce \
393                                          exactly one method"))
394                 }
395                 ast::TypeImplItem(ref td) => {
396                     ast::TypeImplItem(
397                         P(fold::noop_fold_typedef((**td).clone(), &mut fld)))
398                 }
399             })
400         }
401         e::IIForeignRef(i) => {
402             ast::IIForeign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld))
403         }
404     }
405 }
406
407 fn decode_ast(par_doc: rbml::Doc) -> ast::InlinedItem {
408     let chi_doc = par_doc.get(c::tag_tree as uint);
409     let mut d = reader::Decoder::new(chi_doc);
410     Decodable::decode(&mut d).unwrap()
411 }
412
413 // ______________________________________________________________________
414 // Encoding and decoding of ast::def
415
416 fn decode_def(dcx: &DecodeContext, doc: rbml::Doc) -> def::Def {
417     let mut dsr = reader::Decoder::new(doc);
418     let def: def::Def = Decodable::decode(&mut dsr).unwrap();
419     def.tr(dcx)
420 }
421
422 impl tr for def::Def {
423     fn tr(&self, dcx: &DecodeContext) -> def::Def {
424         match *self {
425           def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
426           def::DefStaticMethod(did, p) => {
427             def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
428           }
429           def::DefMethod(did0, did1, p) => {
430             def::DefMethod(did0.tr(dcx),
431                            did1.map(|did1| did1.tr(dcx)),
432                            p.map(|did2| did2.tr(dcx)))
433           }
434           def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
435           def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
436           def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
437           def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
438           def::DefConst(did) => { def::DefConst(did.tr(dcx)) }
439           def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) }
440           def::DefVariant(e_did, v_did, is_s) => {
441             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
442           },
443           def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
444           def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
445           def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
446           def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) =>
447               def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident),
448           def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) =>
449               def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident),
450           def::DefPrimTy(p) => def::DefPrimTy(p),
451           def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
452           def::DefUse(did) => def::DefUse(did.tr(dcx)),
453           def::DefUpvar(nid1, nid2, nid3) => {
454             def::DefUpvar(dcx.tr_id(nid1),
455                            dcx.tr_id(nid2),
456                            dcx.tr_id(nid3))
457           }
458           def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
459           def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
460           def::DefTyParamBinder(nid) => {
461             def::DefTyParamBinder(dcx.tr_id(nid))
462           }
463           def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
464         }
465     }
466 }
467
468 // ______________________________________________________________________
469 // Encoding and decoding of ancillary information
470
471 impl tr for ty::Region {
472     fn tr(&self, dcx: &DecodeContext) -> ty::Region {
473         match *self {
474             ty::ReLateBound(debruijn, br) => {
475                 ty::ReLateBound(debruijn, br.tr(dcx))
476             }
477             ty::ReEarlyBound(id, space, index, ident) => {
478                 ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)
479             }
480             ty::ReScope(scope) => {
481                 ty::ReScope(scope.tr(dcx))
482             }
483             ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => {
484                 *self
485             }
486             ty::ReFree(ref fr) => {
487                 ty::ReFree(fr.tr(dcx))
488             }
489         }
490     }
491 }
492
493 impl tr for ty::FreeRegion {
494     fn tr(&self, dcx: &DecodeContext) -> ty::FreeRegion {
495         ty::FreeRegion { scope: self.scope.tr(dcx),
496                          bound_region: self.bound_region.tr(dcx) }
497     }
498 }
499
500 impl tr for region::CodeExtent {
501     fn tr(&self, dcx: &DecodeContext) -> region::CodeExtent {
502         self.map_id(|id| dcx.tr_id(id))
503     }
504 }
505
506 impl tr for ty::BoundRegion {
507     fn tr(&self, dcx: &DecodeContext) -> ty::BoundRegion {
508         match *self {
509             ty::BrAnon(_) |
510             ty::BrFresh(_) |
511             ty::BrEnv => *self,
512             ty::BrNamed(id, ident) => ty::BrNamed(dcx.tr_def_id(id),
513                                                     ident),
514         }
515     }
516 }
517
518 impl tr for ty::TraitStore {
519     fn tr(&self, dcx: &DecodeContext) -> ty::TraitStore {
520         match *self {
521             ty::RegionTraitStore(r, m) => {
522                 ty::RegionTraitStore(r.tr(dcx), m)
523             }
524             ty::UniqTraitStore => ty::UniqTraitStore
525         }
526     }
527 }
528
529 // ______________________________________________________________________
530 // Encoding and decoding of freevar information
531
532 fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &ty::Freevar) {
533     (*fv).encode(rbml_w).unwrap();
534 }
535
536 fn encode_capture_mode(rbml_w: &mut Encoder, cm: ast::CaptureClause) {
537     cm.encode(rbml_w).unwrap();
538 }
539
540 trait rbml_decoder_helper {
541     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
542                           -> ty::Freevar;
543     fn read_capture_mode(&mut self) -> ast::CaptureClause;
544 }
545
546 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
547     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
548                           -> ty::Freevar {
549         let fv: ty::Freevar = Decodable::decode(self).unwrap();
550         fv.tr(dcx)
551     }
552
553     fn read_capture_mode(&mut self) -> ast::CaptureClause {
554         let cm: ast::CaptureClause = Decodable::decode(self).unwrap();
555         cm
556     }
557 }
558
559 impl tr for ty::Freevar {
560     fn tr(&self, dcx: &DecodeContext) -> ty::Freevar {
561         ty::Freevar {
562             def: self.def.tr(dcx),
563             span: self.span.tr(dcx),
564         }
565     }
566 }
567
568 impl tr for ty::UpvarBorrow {
569     fn tr(&self, dcx: &DecodeContext) -> ty::UpvarBorrow {
570         ty::UpvarBorrow {
571             kind: self.kind,
572             region: self.region.tr(dcx)
573         }
574     }
575 }
576
577 // ______________________________________________________________________
578 // Encoding and decoding of MethodCallee
579
580 trait read_method_callee_helper<'tcx> {
581     fn read_method_callee<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
582         -> (ty::ExprAdjustment, MethodCallee<'tcx>);
583 }
584
585 fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>,
586                                   rbml_w: &mut Encoder,
587                                   adjustment: ty::ExprAdjustment,
588                                   method: &MethodCallee<'tcx>) {
589     use serialize::Encoder;
590
591     rbml_w.emit_struct("MethodCallee", 4, |rbml_w| {
592         rbml_w.emit_struct_field("adjustment", 0u, |rbml_w| {
593             adjustment.encode(rbml_w)
594         });
595         rbml_w.emit_struct_field("origin", 1u, |rbml_w| {
596             Ok(rbml_w.emit_method_origin(ecx, &method.origin))
597         });
598         rbml_w.emit_struct_field("ty", 2u, |rbml_w| {
599             Ok(rbml_w.emit_ty(ecx, method.ty))
600         });
601         rbml_w.emit_struct_field("substs", 3u, |rbml_w| {
602             Ok(rbml_w.emit_substs(ecx, &method.substs))
603         })
604     }).unwrap();
605 }
606
607 impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
608     fn read_method_callee<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
609         -> (ty::ExprAdjustment, MethodCallee<'tcx>) {
610
611         self.read_struct("MethodCallee", 4, |this| {
612             let adjustment = this.read_struct_field("adjustment", 0, |this| {
613                 Decodable::decode(this)
614             }).unwrap();
615             Ok((adjustment, MethodCallee {
616                 origin: this.read_struct_field("origin", 1, |this| {
617                     Ok(this.read_method_origin(dcx))
618                 }).unwrap(),
619                 ty: this.read_struct_field("ty", 2, |this| {
620                     Ok(this.read_ty(dcx))
621                 }).unwrap(),
622                 substs: this.read_struct_field("substs", 3, |this| {
623                     Ok(this.read_substs(dcx))
624                 }).unwrap()
625             }))
626         }).unwrap()
627     }
628 }
629
630 impl<'tcx> tr for MethodOrigin<'tcx> {
631     fn tr(&self, dcx: &DecodeContext) -> MethodOrigin<'tcx> {
632         match *self {
633             ty::MethodStatic(did) => ty::MethodStatic(did.tr(dcx)),
634             ty::MethodStaticUnboxedClosure(did) => {
635                 ty::MethodStaticUnboxedClosure(did.tr(dcx))
636             }
637             ty::MethodTypeParam(ref mp) => {
638                 ty::MethodTypeParam(
639                     ty::MethodParam {
640                         // def-id is already translated when we read it out
641                         trait_ref: mp.trait_ref.clone(),
642                         method_num: mp.method_num,
643                     }
644                 )
645             }
646             ty::MethodTraitObject(ref mo) => {
647                 ty::MethodTraitObject(
648                     ty::MethodObject {
649                         trait_ref: mo.trait_ref.clone(),
650                         .. *mo
651                     }
652                 )
653             }
654         }
655     }
656 }
657
658 pub fn encode_unboxed_closure_kind(ebml_w: &mut Encoder,
659                                    kind: ty::UnboxedClosureKind) {
660     use serialize::Encoder;
661
662     ebml_w.emit_enum("UnboxedClosureKind", |ebml_w| {
663         match kind {
664             ty::FnUnboxedClosureKind => {
665                 ebml_w.emit_enum_variant("FnUnboxedClosureKind", 0, 3, |_| {
666                     Ok(())
667                 })
668             }
669             ty::FnMutUnboxedClosureKind => {
670                 ebml_w.emit_enum_variant("FnMutUnboxedClosureKind", 1, 3, |_| {
671                     Ok(())
672                 })
673             }
674             ty::FnOnceUnboxedClosureKind => {
675                 ebml_w.emit_enum_variant("FnOnceUnboxedClosureKind",
676                                          2,
677                                          3,
678                                          |_| {
679                     Ok(())
680                 })
681             }
682         }
683     }).unwrap()
684 }
685
686 pub trait vtable_decoder_helpers<'tcx> {
687     fn read_vec_per_param_space<T, F>(&mut self, f: F) -> VecPerParamSpace<T> where
688         F: FnMut(&mut Self) -> T;
689     fn read_vtable_res_with_key(&mut self,
690                                 tcx: &ty::ctxt<'tcx>,
691                                 cdata: &cstore::crate_metadata)
692                                 -> (ty::ExprAdjustment, ty::vtable_res<'tcx>);
693     fn read_vtable_res(&mut self,
694                        tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
695                       -> ty::vtable_res<'tcx>;
696     fn read_vtable_param_res(&mut self,
697                        tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
698                       -> ty::vtable_param_res<'tcx>;
699     fn read_vtable_origin(&mut self,
700                           tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
701                           -> ty::vtable_origin<'tcx>;
702 }
703
704 impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
705     fn read_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
706         F: FnMut(&mut reader::Decoder<'a>) -> T,
707     {
708         let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
709         let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
710         let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
711         VecPerParamSpace::new(types, selfs, fns)
712     }
713
714     fn read_vtable_res_with_key(&mut self,
715                                 tcx: &ty::ctxt<'tcx>,
716                                 cdata: &cstore::crate_metadata)
717                                 -> (ty::ExprAdjustment, ty::vtable_res<'tcx>) {
718         self.read_struct("VtableWithKey", 2, |this| {
719             let adjustment = this.read_struct_field("adjustment", 0, |this| {
720                 Decodable::decode(this)
721             }).unwrap();
722             Ok((adjustment, this.read_struct_field("vtable_res", 1, |this| {
723                 Ok(this.read_vtable_res(tcx, cdata))
724             }).unwrap()))
725         }).unwrap()
726     }
727
728     fn read_vtable_res(&mut self,
729                        tcx: &ty::ctxt<'tcx>,
730                        cdata: &cstore::crate_metadata)
731                        -> ty::vtable_res<'tcx>
732     {
733         self.read_vec_per_param_space(
734             |this| this.read_vtable_param_res(tcx, cdata))
735     }
736
737     fn read_vtable_param_res(&mut self,
738                              tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
739                       -> ty::vtable_param_res<'tcx> {
740         self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
741              .unwrap().into_iter().collect()
742     }
743
744     fn read_vtable_origin(&mut self,
745                           tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
746         -> ty::vtable_origin<'tcx> {
747         self.read_enum("vtable_origin", |this| {
748             this.read_enum_variant(&["vtable_static",
749                                      "vtable_param",
750                                      "vtable_error",
751                                      "vtable_unboxed_closure"],
752                                    |this, i| {
753                 Ok(match i {
754                   0 => {
755                     ty::vtable_static(
756                         this.read_enum_variant_arg(0u, |this| {
757                             Ok(this.read_def_id_nodcx(cdata))
758                         }).unwrap(),
759                         this.read_enum_variant_arg(1u, |this| {
760                             Ok(this.read_substs_nodcx(tcx, cdata))
761                         }).unwrap(),
762                         this.read_enum_variant_arg(2u, |this| {
763                             Ok(this.read_vtable_res(tcx, cdata))
764                         }).unwrap()
765                     )
766                   }
767                   1 => {
768                     ty::vtable_param(
769                         this.read_enum_variant_arg(0u, |this| {
770                             Decodable::decode(this)
771                         }).unwrap(),
772                         this.read_enum_variant_arg(1u, |this| {
773                             this.read_uint()
774                         }).unwrap()
775                     )
776                   }
777                   2 => {
778                     ty::vtable_unboxed_closure(
779                         this.read_enum_variant_arg(0u, |this| {
780                             Ok(this.read_def_id_nodcx(cdata))
781                         }).unwrap()
782                     )
783                   }
784                   3 => {
785                     ty::vtable_error
786                   }
787                   _ => panic!("bad enum variant")
788                 })
789             })
790         }).unwrap()
791     }
792 }
793
794 // ___________________________________________________________________________
795 //
796
797 fn encode_vec_per_param_space<T, F>(rbml_w: &mut Encoder,
798                                     v: &subst::VecPerParamSpace<T>,
799                                     mut f: F) where
800     F: FnMut(&mut Encoder, &T),
801 {
802     for &space in subst::ParamSpace::all().iter() {
803         rbml_w.emit_from_vec(v.get_slice(space),
804                              |rbml_w, n| Ok(f(rbml_w, n))).unwrap();
805     }
806 }
807
808 // ______________________________________________________________________
809 // Encoding and decoding the side tables
810
811 trait get_ty_str_ctxt<'tcx> {
812     fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a, 'tcx>;
813 }
814
815 impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> {
816     fn ty_str_ctxt<'b>(&'b self) -> tyencode::ctxt<'b, 'tcx> {
817         tyencode::ctxt {
818             diag: self.tcx.sess.diagnostic(),
819             ds: e::def_to_string,
820             tcx: self.tcx,
821             abbrevs: &self.type_abbrevs
822         }
823     }
824 }
825
826 trait rbml_writer_helpers<'tcx> {
827     fn emit_closure_type<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
828                              closure_type: &ty::ClosureTy<'tcx>);
829     fn emit_method_origin<'a>(&mut self,
830                               ecx: &e::EncodeContext<'a, 'tcx>,
831                               method_origin: &ty::MethodOrigin<'tcx>);
832     fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
833     fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
834     fn emit_type_param_def<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
835                                type_param_def: &ty::TypeParameterDef<'tcx>);
836     fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
837                           predicate: &ty::Predicate<'tcx>);
838     fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
839                           ty: &ty::TraitRef<'tcx>);
840     fn emit_type_scheme<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
841                             type_scheme: ty::TypeScheme<'tcx>);
842     fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
843                        substs: &subst::Substs<'tcx>);
844     fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
845                                    bounds: &ty::ExistentialBounds<'tcx>);
846     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
847     fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
848                                 adj: &ty::AutoAdjustment<'tcx>);
849     fn emit_autoref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
850                         autoref: &ty::AutoRef<'tcx>);
851     fn emit_auto_deref_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
852                                auto_deref_ref: &ty::AutoDerefRef<'tcx>);
853     fn emit_unsize_kind<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
854                             uk: &ty::UnsizeKind<'tcx>);
855 }
856
857 impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
858     fn emit_closure_type<'b>(&mut self,
859                              ecx: &e::EncodeContext<'b, 'tcx>,
860                              closure_type: &ty::ClosureTy<'tcx>) {
861         self.emit_opaque(|this| {
862             Ok(e::write_closure_type(ecx, this, closure_type))
863         });
864     }
865
866     fn emit_method_origin<'b>(&mut self,
867                               ecx: &e::EncodeContext<'b, 'tcx>,
868                               method_origin: &ty::MethodOrigin<'tcx>)
869     {
870         use serialize::Encoder;
871
872         self.emit_enum("MethodOrigin", |this| {
873             match *method_origin {
874                 ty::MethodStatic(def_id) => {
875                     this.emit_enum_variant("MethodStatic", 0, 1, |this| {
876                         Ok(this.emit_def_id(def_id))
877                     })
878                 }
879
880                 ty::MethodStaticUnboxedClosure(def_id) => {
881                     this.emit_enum_variant("MethodStaticUnboxedClosure", 1, 1, |this| {
882                         Ok(this.emit_def_id(def_id))
883                     })
884                 }
885
886                 ty::MethodTypeParam(ref p) => {
887                     this.emit_enum_variant("MethodTypeParam", 2, 1, |this| {
888                         this.emit_struct("MethodParam", 2, |this| {
889                             try!(this.emit_struct_field("trait_ref", 0, |this| {
890                                 Ok(this.emit_trait_ref(ecx, &*p.trait_ref))
891                             }));
892                             try!(this.emit_struct_field("method_num", 0, |this| {
893                                 this.emit_uint(p.method_num)
894                             }));
895                             Ok(())
896                         })
897                     })
898                 }
899
900                 ty::MethodTraitObject(ref o) => {
901                     this.emit_enum_variant("MethodTraitObject", 3, 1, |this| {
902                         this.emit_struct("MethodObject", 2, |this| {
903                             try!(this.emit_struct_field("trait_ref", 0, |this| {
904                                 Ok(this.emit_trait_ref(ecx, &*o.trait_ref))
905                             }));
906                             try!(this.emit_struct_field("object_trait_id", 0, |this| {
907                                 Ok(this.emit_def_id(o.object_trait_id))
908                             }));
909                             try!(this.emit_struct_field("method_num", 0, |this| {
910                                 this.emit_uint(o.method_num)
911                             }));
912                             try!(this.emit_struct_field("real_index", 0, |this| {
913                                 this.emit_uint(o.real_index)
914                             }));
915                             Ok(())
916                         })
917                     })
918                 }
919             }
920         });
921     }
922
923     fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
924         self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty)));
925     }
926
927     fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) {
928         self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty)));
929     }
930
931     fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
932                           trait_ref: &ty::TraitRef<'tcx>) {
933         self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref)));
934     }
935
936     fn emit_type_param_def<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
937                                type_param_def: &ty::TypeParameterDef<'tcx>) {
938         self.emit_opaque(|this| {
939             Ok(tyencode::enc_type_param_def(this.writer,
940                                          &ecx.ty_str_ctxt(),
941                                          type_param_def))
942         });
943     }
944
945     fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
946                           predicate: &ty::Predicate<'tcx>) {
947         self.emit_opaque(|this| {
948             Ok(tyencode::enc_predicate(this.writer,
949                                        &ecx.ty_str_ctxt(),
950                                        predicate))
951         });
952     }
953
954     fn emit_type_scheme<'b>(&mut self,
955                             ecx: &e::EncodeContext<'b, 'tcx>,
956                             type_scheme: ty::TypeScheme<'tcx>) {
957         use serialize::Encoder;
958
959         self.emit_struct("TypeScheme", 2, |this| {
960             this.emit_struct_field("generics", 0, |this| {
961                 this.emit_struct("Generics", 2, |this| {
962                     this.emit_struct_field("types", 0, |this| {
963                         Ok(encode_vec_per_param_space(
964                             this, &type_scheme.generics.types,
965                             |this, def| this.emit_type_param_def(ecx, def)))
966                     });
967                     this.emit_struct_field("regions", 1, |this| {
968                         Ok(encode_vec_per_param_space(
969                             this, &type_scheme.generics.regions,
970                             |this, def| def.encode(this).unwrap()))
971                     });
972                     this.emit_struct_field("predicates", 2, |this| {
973                         Ok(encode_vec_per_param_space(
974                             this, &type_scheme.generics.predicates,
975                             |this, def| this.emit_predicate(ecx, def)))
976                     })
977                 })
978             });
979             this.emit_struct_field("ty", 1, |this| {
980                 Ok(this.emit_ty(ecx, type_scheme.ty))
981             })
982         });
983     }
984
985     fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
986                                    bounds: &ty::ExistentialBounds<'tcx>) {
987         self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer,
988                                                                     &ecx.ty_str_ctxt(),
989                                                                     bounds)));
990     }
991
992     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
993         self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this.writer,
994                                                                 &ecx.ty_str_ctxt(),
995                                                                 bounds)));
996     }
997
998     fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
999                        substs: &subst::Substs<'tcx>) {
1000         self.emit_opaque(|this| Ok(tyencode::enc_substs(this.writer,
1001                                                            &ecx.ty_str_ctxt(),
1002                                                            substs)));
1003     }
1004
1005     fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
1006                                 adj: &ty::AutoAdjustment<'tcx>) {
1007         use serialize::Encoder;
1008
1009         self.emit_enum("AutoAdjustment", |this| {
1010             match *adj {
1011                 ty::AdjustReifyFnPointer(def_id) => {
1012                     this.emit_enum_variant("AdjustReifyFnPointer", 1, 2, |this| {
1013                         this.emit_enum_variant_arg(0, |this| def_id.encode(this))
1014                     })
1015                 }
1016
1017                 ty::AdjustDerefRef(ref auto_deref_ref) => {
1018                     this.emit_enum_variant("AdjustDerefRef", 2, 2, |this| {
1019                         this.emit_enum_variant_arg(0,
1020                             |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
1021                     })
1022                 }
1023             }
1024         });
1025     }
1026
1027     fn emit_autoref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
1028                         autoref: &ty::AutoRef<'tcx>) {
1029         use serialize::Encoder;
1030
1031         self.emit_enum("AutoRef", |this| {
1032             match autoref {
1033                 &ty::AutoPtr(r, m, None) => {
1034                     this.emit_enum_variant("AutoPtr", 0, 3, |this| {
1035                         this.emit_enum_variant_arg(0, |this| r.encode(this));
1036                         this.emit_enum_variant_arg(1, |this| m.encode(this));
1037                         this.emit_enum_variant_arg(2,
1038                             |this| this.emit_option(|this| this.emit_option_none()))
1039                     })
1040                 }
1041                 &ty::AutoPtr(r, m, Some(box ref a)) => {
1042                     this.emit_enum_variant("AutoPtr", 0, 3, |this| {
1043                         this.emit_enum_variant_arg(0, |this| r.encode(this));
1044                         this.emit_enum_variant_arg(1, |this| m.encode(this));
1045                         this.emit_enum_variant_arg(2, |this| this.emit_option(
1046                             |this| this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a)))))
1047                     })
1048                 }
1049                 &ty::AutoUnsize(ref uk) => {
1050                     this.emit_enum_variant("AutoUnsize", 1, 1, |this| {
1051                         this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)))
1052                     })
1053                 }
1054                 &ty::AutoUnsizeUniq(ref uk) => {
1055                     this.emit_enum_variant("AutoUnsizeUniq", 2, 1, |this| {
1056                         this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)))
1057                     })
1058                 }
1059                 &ty::AutoUnsafe(m, None) => {
1060                     this.emit_enum_variant("AutoUnsafe", 3, 2, |this| {
1061                         this.emit_enum_variant_arg(0, |this| m.encode(this));
1062                         this.emit_enum_variant_arg(1,
1063                             |this| this.emit_option(|this| this.emit_option_none()))
1064                     })
1065                 }
1066                 &ty::AutoUnsafe(m, Some(box ref a)) => {
1067                     this.emit_enum_variant("AutoUnsafe", 3, 2, |this| {
1068                         this.emit_enum_variant_arg(0, |this| m.encode(this));
1069                         this.emit_enum_variant_arg(1, |this| this.emit_option(
1070                             |this| this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a)))))
1071                     })
1072                 }
1073             }
1074         });
1075     }
1076
1077     fn emit_auto_deref_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
1078                                auto_deref_ref: &ty::AutoDerefRef<'tcx>) {
1079         use serialize::Encoder;
1080
1081         self.emit_struct("AutoDerefRef", 2, |this| {
1082             this.emit_struct_field("autoderefs", 0, |this| auto_deref_ref.autoderefs.encode(this));
1083             this.emit_struct_field("autoref", 1, |this| {
1084                 this.emit_option(|this| {
1085                     match auto_deref_ref.autoref {
1086                         None => this.emit_option_none(),
1087                         Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a))),
1088                     }
1089                 })
1090             })
1091         });
1092     }
1093
1094     fn emit_unsize_kind<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
1095                             uk: &ty::UnsizeKind<'tcx>) {
1096         use serialize::Encoder;
1097
1098         self.emit_enum("UnsizeKind", |this| {
1099             match *uk {
1100                 ty::UnsizeLength(len) => {
1101                     this.emit_enum_variant("UnsizeLength", 0, 1, |this| {
1102                         this.emit_enum_variant_arg(0, |this| len.encode(this))
1103                     })
1104                 }
1105                 ty::UnsizeStruct(box ref uk, idx) => {
1106                     this.emit_enum_variant("UnsizeStruct", 1, 2, |this| {
1107                         this.emit_enum_variant_arg(0, |this| Ok(this.emit_unsize_kind(ecx, uk)));
1108                         this.emit_enum_variant_arg(1, |this| idx.encode(this))
1109                     })
1110                 }
1111                 ty::UnsizeVtable(ty::TyTrait { ref principal,
1112                                                bounds: ref b },
1113                                  self_ty) => {
1114                     this.emit_enum_variant("UnsizeVtable", 2, 4, |this| {
1115                         this.emit_enum_variant_arg(0, |this| {
1116                             try!(this.emit_struct_field("principal", 0, |this| {
1117                                 Ok(this.emit_trait_ref(ecx, &*principal.0))
1118                             }));
1119                             this.emit_struct_field("bounds", 1, |this| {
1120                                 Ok(this.emit_existential_bounds(ecx, b))
1121                             })
1122                         });
1123                         this.emit_enum_variant_arg(1, |this| Ok(this.emit_ty(ecx, self_ty)))
1124                     })
1125                 }
1126             }
1127         });
1128     }
1129 }
1130
1131 trait write_tag_and_id {
1132     fn tag<F>(&mut self, tag_id: c::astencode_tag, f: F) where F: FnOnce(&mut Self);
1133     fn id(&mut self, id: ast::NodeId);
1134 }
1135
1136 impl<'a> write_tag_and_id for Encoder<'a> {
1137     fn tag<F>(&mut self,
1138               tag_id: c::astencode_tag,
1139               f: F) where
1140         F: FnOnce(&mut Encoder<'a>),
1141     {
1142         self.start_tag(tag_id as uint);
1143         f(self);
1144         self.end_tag();
1145     }
1146
1147     fn id(&mut self, id: ast::NodeId) {
1148         self.wr_tagged_u64(c::tag_table_id as uint, id as u64);
1149     }
1150 }
1151
1152 struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
1153     ecx: &'a e::EncodeContext<'c, 'tcx>,
1154     rbml_w: &'a mut Encoder<'b>,
1155 }
1156
1157 impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for
1158         SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
1159     fn visit_id(&mut self, id: ast::NodeId) {
1160         encode_side_tables_for_id(self.ecx, self.rbml_w, id)
1161     }
1162 }
1163
1164 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
1165                              rbml_w: &mut Encoder,
1166                              ii: &ast::InlinedItem) {
1167     rbml_w.start_tag(c::tag_table as uint);
1168     ast_util::visit_ids_for_inlined_item(ii, &mut SideTableEncodingIdVisitor {
1169         ecx: ecx,
1170         rbml_w: rbml_w
1171     });
1172     rbml_w.end_tag();
1173 }
1174
1175 fn encode_side_tables_for_id(ecx: &e::EncodeContext,
1176                              rbml_w: &mut Encoder,
1177                              id: ast::NodeId) {
1178     let tcx = ecx.tcx;
1179
1180     debug!("Encoding side tables for id {}", id);
1181
1182     for def in tcx.def_map.borrow().get(&id).iter() {
1183         rbml_w.tag(c::tag_table_def, |rbml_w| {
1184             rbml_w.id(id);
1185             rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap());
1186         })
1187     }
1188
1189     for &ty in tcx.node_types.borrow().get(&id).iter() {
1190         rbml_w.tag(c::tag_table_node_type, |rbml_w| {
1191             rbml_w.id(id);
1192             rbml_w.tag(c::tag_table_val, |rbml_w| {
1193                 rbml_w.emit_ty(ecx, *ty);
1194             })
1195         })
1196     }
1197
1198     for &item_substs in tcx.item_substs.borrow().get(&id).iter() {
1199         rbml_w.tag(c::tag_table_item_subst, |rbml_w| {
1200             rbml_w.id(id);
1201             rbml_w.tag(c::tag_table_val, |rbml_w| {
1202                 rbml_w.emit_substs(ecx, &item_substs.substs);
1203             })
1204         })
1205     }
1206
1207     for &fv in tcx.freevars.borrow().get(&id).iter() {
1208         rbml_w.tag(c::tag_table_freevars, |rbml_w| {
1209             rbml_w.id(id);
1210             rbml_w.tag(c::tag_table_val, |rbml_w| {
1211                 rbml_w.emit_from_vec(fv.as_slice(), |rbml_w, fv_entry| {
1212                     Ok(encode_freevar_entry(rbml_w, fv_entry))
1213                 });
1214             })
1215         });
1216
1217         for freevar in fv.iter() {
1218             match tcx.capture_mode(id) {
1219                 ast::CaptureByRef => {
1220                     rbml_w.tag(c::tag_table_upvar_borrow_map, |rbml_w| {
1221                         rbml_w.id(id);
1222                         rbml_w.tag(c::tag_table_val, |rbml_w| {
1223                             let var_id = freevar.def.def_id().node;
1224                             let upvar_id = ty::UpvarId {
1225                                 var_id: var_id,
1226                                 closure_expr_id: id
1227                             };
1228                             let upvar_borrow = tcx.upvar_borrow_map.borrow()[upvar_id].clone();
1229                             var_id.encode(rbml_w);
1230                             upvar_borrow.encode(rbml_w);
1231                         })
1232                     })
1233                 }
1234                 _ => {}
1235             }
1236         }
1237     }
1238
1239     for &cm in tcx.capture_modes.borrow().get(&id).iter() {
1240         rbml_w.tag(c::tag_table_capture_modes, |rbml_w| {
1241             rbml_w.id(id);
1242             rbml_w.tag(c::tag_table_val, |rbml_w| {
1243                 encode_capture_mode(rbml_w, *cm);
1244             })
1245         })
1246     }
1247
1248     let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
1249     for &type_scheme in tcx.tcache.borrow().get(&lid).iter() {
1250         rbml_w.tag(c::tag_table_tcache, |rbml_w| {
1251             rbml_w.id(id);
1252             rbml_w.tag(c::tag_table_val, |rbml_w| {
1253                 rbml_w.emit_type_scheme(ecx, type_scheme.clone());
1254             })
1255         })
1256     }
1257
1258     for &type_param_def in tcx.ty_param_defs.borrow().get(&id).iter() {
1259         rbml_w.tag(c::tag_table_param_defs, |rbml_w| {
1260             rbml_w.id(id);
1261             rbml_w.tag(c::tag_table_val, |rbml_w| {
1262                 rbml_w.emit_type_param_def(ecx, type_param_def)
1263             })
1264         })
1265     }
1266
1267     let method_call = MethodCall::expr(id);
1268     for &method in tcx.method_map.borrow().get(&method_call).iter() {
1269         rbml_w.tag(c::tag_table_method_map, |rbml_w| {
1270             rbml_w.id(id);
1271             rbml_w.tag(c::tag_table_val, |rbml_w| {
1272                 encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
1273             })
1274         })
1275     }
1276
1277     for &trait_ref in tcx.object_cast_map.borrow().get(&id).iter() {
1278         rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
1279             rbml_w.id(id);
1280             rbml_w.tag(c::tag_table_val, |rbml_w| {
1281                 rbml_w.emit_trait_ref(ecx, &*trait_ref.0);
1282             })
1283         })
1284     }
1285
1286     for &adjustment in tcx.adjustments.borrow().get(&id).iter() {
1287         match *adjustment {
1288             _ if ty::adjust_is_object(adjustment) => {
1289                 let method_call = MethodCall::autoobject(id);
1290                 for &method in tcx.method_map.borrow().get(&method_call).iter() {
1291                     rbml_w.tag(c::tag_table_method_map, |rbml_w| {
1292                         rbml_w.id(id);
1293                         rbml_w.tag(c::tag_table_val, |rbml_w| {
1294                             encode_method_callee(ecx, rbml_w, method_call.adjustment, method)
1295                         })
1296                     })
1297                 }
1298             }
1299             ty::AdjustDerefRef(ref adj) => {
1300                 assert!(!ty::adjust_is_object(adjustment));
1301                 for autoderef in range(0, adj.autoderefs) {
1302                     let method_call = MethodCall::autoderef(id, autoderef);
1303                     for &method in tcx.method_map.borrow().get(&method_call).iter() {
1304                         rbml_w.tag(c::tag_table_method_map, |rbml_w| {
1305                             rbml_w.id(id);
1306                             rbml_w.tag(c::tag_table_val, |rbml_w| {
1307                                 encode_method_callee(ecx, rbml_w,
1308                                                      method_call.adjustment, method)
1309                             })
1310                         })
1311                     }
1312                 }
1313             }
1314             _ => {
1315                 assert!(!ty::adjust_is_object(adjustment));
1316             }
1317         }
1318
1319         rbml_w.tag(c::tag_table_adjustments, |rbml_w| {
1320             rbml_w.id(id);
1321             rbml_w.tag(c::tag_table_val, |rbml_w| {
1322                 rbml_w.emit_auto_adjustment(ecx, adjustment);
1323             })
1324         })
1325     }
1326
1327     for unboxed_closure in tcx.unboxed_closures
1328                               .borrow()
1329                               .get(&ast_util::local_def(id))
1330                               .iter() {
1331         rbml_w.tag(c::tag_table_unboxed_closures, |rbml_w| {
1332             rbml_w.id(id);
1333             rbml_w.tag(c::tag_table_val, |rbml_w| {
1334                 rbml_w.emit_closure_type(ecx, &unboxed_closure.closure_type);
1335                 encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind)
1336             })
1337         })
1338     }
1339 }
1340
1341 trait doc_decoder_helpers {
1342     fn as_int(&self) -> int;
1343     fn opt_child(&self, tag: c::astencode_tag) -> Option<Self>;
1344 }
1345
1346 impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
1347     fn as_int(&self) -> int { reader::doc_as_u64(*self) as int }
1348     fn opt_child(&self, tag: c::astencode_tag) -> Option<rbml::Doc<'a>> {
1349         reader::maybe_get_doc(*self, tag as uint)
1350     }
1351 }
1352
1353 trait rbml_decoder_decoder_helpers<'tcx> {
1354     fn read_method_origin<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1355                                   -> ty::MethodOrigin<'tcx>;
1356     fn read_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Ty<'tcx>;
1357     fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
1358     fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1359                               -> Rc<ty::TraitRef<'tcx>>;
1360     fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1361                                    -> ty::PolyTraitRef<'tcx>;
1362     fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1363                                    -> ty::TypeParameterDef<'tcx>;
1364     fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1365                               -> ty::Predicate<'tcx>;
1366     fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1367                                 -> ty::TypeScheme<'tcx>;
1368     fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1369                                        -> ty::ExistentialBounds<'tcx>;
1370     fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1371                            -> subst::Substs<'tcx>;
1372     fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1373                                     -> ty::AutoAdjustment<'tcx>;
1374     fn read_unboxed_closure<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1375                                     -> ty::UnboxedClosure<'tcx>;
1376     fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1377                                    -> ty::AutoDerefRef<'tcx>;
1378     fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1379                             -> ty::AutoRef<'tcx>;
1380     fn read_unsize_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1381                                 -> ty::UnsizeKind<'tcx>;
1382     fn convert_def_id(&mut self,
1383                       dcx: &DecodeContext,
1384                       source: DefIdSource,
1385                       did: ast::DefId)
1386                       -> ast::DefId;
1387
1388     // Versions of the type reading functions that don't need the full
1389     // DecodeContext.
1390     fn read_ty_nodcx(&mut self,
1391                      tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata) -> Ty<'tcx>;
1392     fn read_tys_nodcx(&mut self,
1393                       tcx: &ty::ctxt<'tcx>,
1394                       cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
1395     fn read_substs_nodcx(&mut self, tcx: &ty::ctxt<'tcx>,
1396                          cdata: &cstore::crate_metadata)
1397                          -> subst::Substs<'tcx>;
1398 }
1399
1400 impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
1401     fn read_ty_nodcx(&mut self,
1402                      tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata) -> Ty<'tcx> {
1403         self.read_opaque(|_, doc| {
1404             Ok(tydecode::parse_ty_data(
1405                 doc.data,
1406                 cdata.cnum,
1407                 doc.start,
1408                 tcx,
1409                 |_, id| decoder::translate_def_id(cdata, id)))
1410         }).unwrap()
1411     }
1412
1413     fn read_tys_nodcx(&mut self,
1414                       tcx: &ty::ctxt<'tcx>,
1415                       cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>> {
1416         self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
1417             .unwrap()
1418             .into_iter()
1419             .collect()
1420     }
1421
1422     fn read_substs_nodcx(&mut self,
1423                          tcx: &ty::ctxt<'tcx>,
1424                          cdata: &cstore::crate_metadata)
1425                          -> subst::Substs<'tcx>
1426     {
1427         self.read_opaque(|_, doc| {
1428             Ok(tydecode::parse_substs_data(
1429                 doc.data,
1430                 cdata.cnum,
1431                 doc.start,
1432                 tcx,
1433                 |_, id| decoder::translate_def_id(cdata, id)))
1434         }).unwrap()
1435     }
1436
1437     fn read_method_origin<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1438                                   -> ty::MethodOrigin<'tcx>
1439     {
1440         self.read_enum("MethodOrigin", |this| {
1441             let variants = &["MethodStatic", "MethodStaticUnboxedClosure",
1442                              "MethodTypeParam", "MethodTraitObject"];
1443             this.read_enum_variant(variants, |this, i| {
1444                 Ok(match i {
1445                     0 => {
1446                         let def_id = this.read_def_id(dcx);
1447                         ty::MethodStatic(def_id)
1448                     }
1449
1450                     1 => {
1451                         let def_id = this.read_def_id(dcx);
1452                         ty::MethodStaticUnboxedClosure(def_id)
1453                     }
1454
1455                     2 => {
1456                         this.read_struct("MethodTypeParam", 2, |this| {
1457                             Ok(ty::MethodTypeParam(
1458                                 ty::MethodParam {
1459                                     trait_ref: {
1460                                         this.read_struct_field("trait_ref", 0, |this| {
1461                                             Ok(this.read_trait_ref(dcx))
1462                                         }).unwrap()
1463                                     },
1464                                     method_num: {
1465                                         this.read_struct_field("method_num", 1, |this| {
1466                                             this.read_uint()
1467                                         }).unwrap()
1468                                     }
1469                                 }))
1470                         }).unwrap()
1471                     }
1472
1473                     3 => {
1474                         this.read_struct("MethodTraitObject", 2, |this| {
1475                             Ok(ty::MethodTraitObject(
1476                                 ty::MethodObject {
1477                                     trait_ref: {
1478                                         this.read_struct_field("trait_ref", 0, |this| {
1479                                             Ok(this.read_trait_ref(dcx))
1480                                         }).unwrap()
1481                                     },
1482                                     object_trait_id: {
1483                                         this.read_struct_field("object_trait_id", 1, |this| {
1484                                             Ok(this.read_def_id(dcx))
1485                                         }).unwrap()
1486                                     },
1487                                     method_num: {
1488                                         this.read_struct_field("method_num", 2, |this| {
1489                                             this.read_uint()
1490                                         }).unwrap()
1491                                     },
1492                                     real_index: {
1493                                         this.read_struct_field("real_index", 3, |this| {
1494                                             this.read_uint()
1495                                         }).unwrap()
1496                                     },
1497                                 }))
1498                         }).unwrap()
1499                     }
1500
1501                     _ => panic!("..")
1502                 })
1503             })
1504         }).unwrap()
1505     }
1506
1507
1508     fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> {
1509         // Note: regions types embed local node ids.  In principle, we
1510         // should translate these node ids into the new decode
1511         // context.  However, we do not bother, because region types
1512         // are not used during trans.
1513
1514         return self.read_opaque(|this, doc| {
1515             debug!("read_ty({})", type_string(doc));
1516
1517             let ty = tydecode::parse_ty_data(
1518                 doc.data,
1519                 dcx.cdata.cnum,
1520                 doc.start,
1521                 dcx.tcx,
1522                 |s, a| this.convert_def_id(dcx, s, a));
1523
1524             Ok(ty)
1525         }).unwrap();
1526
1527         fn type_string(doc: rbml::Doc) -> String {
1528             let mut str = String::new();
1529             for i in range(doc.start, doc.end) {
1530                 str.push(doc.data[i] as char);
1531             }
1532             str
1533         }
1534     }
1535
1536     fn read_tys<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1537                         -> Vec<Ty<'tcx>> {
1538         self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().into_iter().collect()
1539     }
1540
1541     fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1542                               -> Rc<ty::TraitRef<'tcx>> {
1543         self.read_opaque(|this, doc| {
1544             let ty = tydecode::parse_trait_ref_data(
1545                 doc.data,
1546                 dcx.cdata.cnum,
1547                 doc.start,
1548                 dcx.tcx,
1549                 |s, a| this.convert_def_id(dcx, s, a));
1550             Ok(ty)
1551         }).unwrap()
1552     }
1553
1554     fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1555                                    -> ty::PolyTraitRef<'tcx> {
1556         ty::Binder(self.read_opaque(|this, doc| {
1557             let ty = tydecode::parse_trait_ref_data(
1558                 doc.data,
1559                 dcx.cdata.cnum,
1560                 doc.start,
1561                 dcx.tcx,
1562                 |s, a| this.convert_def_id(dcx, s, a));
1563             Ok(ty)
1564         }).unwrap())
1565     }
1566
1567     fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1568                                    -> ty::TypeParameterDef<'tcx> {
1569         self.read_opaque(|this, doc| {
1570             Ok(tydecode::parse_type_param_def_data(
1571                 doc.data,
1572                 doc.start,
1573                 dcx.cdata.cnum,
1574                 dcx.tcx,
1575                 |s, a| this.convert_def_id(dcx, s, a)))
1576         }).unwrap()
1577     }
1578
1579     fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1580                               -> ty::Predicate<'tcx>
1581     {
1582         self.read_opaque(|this, doc| {
1583             Ok(tydecode::parse_predicate_data(doc.data, doc.start, dcx.cdata.cnum, dcx.tcx,
1584                                               |s, a| this.convert_def_id(dcx, s, a)))
1585         }).unwrap()
1586     }
1587
1588     fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1589                                 -> ty::TypeScheme<'tcx> {
1590         self.read_struct("TypeScheme", 2, |this| {
1591             Ok(ty::TypeScheme {
1592                 generics: this.read_struct_field("generics", 0, |this| {
1593                     this.read_struct("Generics", 2, |this| {
1594                         Ok(ty::Generics {
1595                             types:
1596                             this.read_struct_field("types", 0, |this| {
1597                                 Ok(this.read_vec_per_param_space(
1598                                     |this| this.read_type_param_def(dcx)))
1599                             }).unwrap(),
1600
1601                             regions:
1602                             this.read_struct_field("regions", 1, |this| {
1603                                 Ok(this.read_vec_per_param_space(
1604                                     |this| Decodable::decode(this).unwrap()))
1605                             }).unwrap(),
1606
1607                             predicates:
1608                             this.read_struct_field("predicates", 2, |this| {
1609                                 Ok(this.read_vec_per_param_space(
1610                                     |this| this.read_predicate(dcx)))
1611                             }).unwrap(),
1612                         })
1613                     })
1614                 }).unwrap(),
1615                 ty: this.read_struct_field("ty", 1, |this| {
1616                     Ok(this.read_ty(dcx))
1617                 }).unwrap()
1618             })
1619         }).unwrap()
1620     }
1621
1622     fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1623                                        -> ty::ExistentialBounds<'tcx>
1624     {
1625         self.read_opaque(|this, doc| {
1626             Ok(tydecode::parse_existential_bounds_data(doc.data,
1627                                                        dcx.cdata.cnum,
1628                                                        doc.start,
1629                                                        dcx.tcx,
1630                                                        |s, a| this.convert_def_id(dcx, s, a)))
1631         }).unwrap()
1632     }
1633
1634     fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1635                            -> subst::Substs<'tcx> {
1636         self.read_opaque(|this, doc| {
1637             Ok(tydecode::parse_substs_data(doc.data,
1638                                         dcx.cdata.cnum,
1639                                         doc.start,
1640                                         dcx.tcx,
1641                                         |s, a| this.convert_def_id(dcx, s, a)))
1642         }).unwrap()
1643     }
1644
1645     fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1646                                     -> ty::AutoAdjustment<'tcx> {
1647         self.read_enum("AutoAdjustment", |this| {
1648             let variants = ["AutoAddEnv", "AutoDerefRef"];
1649             this.read_enum_variant(&variants, |this, i| {
1650                 Ok(match i {
1651                     1 => {
1652                         let def_id: ast::DefId =
1653                             this.read_def_id(dcx);
1654
1655                         ty::AdjustReifyFnPointer(def_id)
1656                     }
1657                     2 => {
1658                         let auto_deref_ref: ty::AutoDerefRef =
1659                             this.read_enum_variant_arg(0,
1660                                 |this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
1661
1662                         ty::AdjustDerefRef(auto_deref_ref)
1663                     }
1664                     _ => panic!("bad enum variant for ty::AutoAdjustment")
1665                 })
1666             })
1667         }).unwrap()
1668     }
1669
1670     fn read_auto_deref_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1671                                    -> ty::AutoDerefRef<'tcx> {
1672         self.read_struct("AutoDerefRef", 2, |this| {
1673             Ok(ty::AutoDerefRef {
1674                 autoderefs: this.read_struct_field("autoderefs", 0, |this| {
1675                     Decodable::decode(this)
1676                 }).unwrap(),
1677                 autoref: this.read_struct_field("autoref", 1, |this| {
1678                     this.read_option(|this, b| {
1679                         if b {
1680                             Ok(Some(this.read_autoref(dcx)))
1681                         } else {
1682                             Ok(None)
1683                         }
1684                     })
1685                 }).unwrap(),
1686             })
1687         }).unwrap()
1688     }
1689
1690     fn read_autoref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> ty::AutoRef<'tcx> {
1691         self.read_enum("AutoRef", |this| {
1692             let variants = ["AutoPtr",
1693                             "AutoUnsize",
1694                             "AutoUnsizeUniq",
1695                             "AutoUnsafe"];
1696             this.read_enum_variant(&variants, |this, i| {
1697                 Ok(match i {
1698                     0 => {
1699                         let r: ty::Region =
1700                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
1701                         let m: ast::Mutability =
1702                             this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
1703                         let a: Option<Box<ty::AutoRef>> =
1704                             this.read_enum_variant_arg(2, |this| this.read_option(|this, b| {
1705                                 if b {
1706                                     Ok(Some(box this.read_autoref(dcx)))
1707                                 } else {
1708                                     Ok(None)
1709                                 }
1710                             })).unwrap();
1711
1712                         ty::AutoPtr(r.tr(dcx), m, a)
1713                     }
1714                     1 => {
1715                         let uk: ty::UnsizeKind =
1716                             this.read_enum_variant_arg(0,
1717                                 |this| Ok(this.read_unsize_kind(dcx))).unwrap();
1718
1719                         ty::AutoUnsize(uk)
1720                     }
1721                     2 => {
1722                         let uk: ty::UnsizeKind =
1723                             this.read_enum_variant_arg(0,
1724                                 |this| Ok(this.read_unsize_kind(dcx))).unwrap();
1725
1726                         ty::AutoUnsizeUniq(uk)
1727                     }
1728                     3 => {
1729                         let m: ast::Mutability =
1730                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
1731                         let a: Option<Box<ty::AutoRef>> =
1732                             this.read_enum_variant_arg(1, |this| this.read_option(|this, b| {
1733                                 if b {
1734                                     Ok(Some(box this.read_autoref(dcx)))
1735                                 } else {
1736                                     Ok(None)
1737                                 }
1738                             })).unwrap();
1739
1740                         ty::AutoUnsafe(m, a)
1741                     }
1742                     _ => panic!("bad enum variant for ty::AutoRef")
1743                 })
1744             })
1745         }).unwrap()
1746     }
1747
1748     fn read_unsize_kind<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1749                                 -> ty::UnsizeKind<'tcx> {
1750         self.read_enum("UnsizeKind", |this| {
1751             let variants = &["UnsizeLength", "UnsizeStruct", "UnsizeVtable"];
1752             this.read_enum_variant(variants, |this, i| {
1753                 Ok(match i {
1754                     0 => {
1755                         let len: uint =
1756                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
1757
1758                         ty::UnsizeLength(len)
1759                     }
1760                     1 => {
1761                         let uk: ty::UnsizeKind =
1762                             this.read_enum_variant_arg(0,
1763                                 |this| Ok(this.read_unsize_kind(dcx))).unwrap();
1764                         let idx: uint =
1765                             this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
1766
1767                         ty::UnsizeStruct(box uk, idx)
1768                     }
1769                     2 => {
1770                         let ty_trait = try!(this.read_enum_variant_arg(0, |this| {
1771                             let principal = try!(this.read_struct_field("principal", 0, |this| {
1772                                 Ok(this.read_poly_trait_ref(dcx))
1773                             }));
1774                             Ok(ty::TyTrait {
1775                                 principal: principal,
1776                                 bounds: try!(this.read_struct_field("bounds", 1, |this| {
1777                                     Ok(this.read_existential_bounds(dcx))
1778                                 })),
1779                             })
1780                         }));
1781                         let self_ty =
1782                             this.read_enum_variant_arg(1, |this| Ok(this.read_ty(dcx))).unwrap();
1783                         ty::UnsizeVtable(ty_trait, self_ty)
1784                     }
1785                     _ => panic!("bad enum variant for ty::UnsizeKind")
1786                 })
1787             })
1788         }).unwrap()
1789     }
1790
1791     fn read_unboxed_closure<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1792                                     -> ty::UnboxedClosure<'tcx> {
1793         let closure_type = self.read_opaque(|this, doc| {
1794             Ok(tydecode::parse_ty_closure_data(
1795                 doc.data,
1796                 dcx.cdata.cnum,
1797                 doc.start,
1798                 dcx.tcx,
1799                 |s, a| this.convert_def_id(dcx, s, a)))
1800         }).unwrap();
1801         let variants = &[
1802             "FnUnboxedClosureKind",
1803             "FnMutUnboxedClosureKind",
1804             "FnOnceUnboxedClosureKind"
1805         ];
1806         let kind = self.read_enum("UnboxedClosureKind", |this| {
1807             this.read_enum_variant(variants, |_, i| {
1808                 Ok(match i {
1809                     0 => ty::FnUnboxedClosureKind,
1810                     1 => ty::FnMutUnboxedClosureKind,
1811                     2 => ty::FnOnceUnboxedClosureKind,
1812                     _ => panic!("bad enum variant for ty::UnboxedClosureKind"),
1813                 })
1814             })
1815         }).unwrap();
1816         ty::UnboxedClosure {
1817             closure_type: closure_type,
1818             kind: kind,
1819         }
1820     }
1821
1822     /// Converts a def-id that appears in a type.  The correct
1823     /// translation will depend on what kind of def-id this is.
1824     /// This is a subtle point: type definitions are not
1825     /// inlined into the current crate, so if the def-id names
1826     /// a nominal type or type alias, then it should be
1827     /// translated to refer to the source crate.
1828     ///
1829     /// However, *type parameters* are cloned along with the function
1830     /// they are attached to.  So we should translate those def-ids
1831     /// to refer to the new, cloned copy of the type parameter.
1832     /// We only see references to free type parameters in the body of
1833     /// an inlined function. In such cases, we need the def-id to
1834     /// be a local id so that the TypeContents code is able to lookup
1835     /// the relevant info in the ty_param_defs table.
1836     ///
1837     /// *Region parameters*, unfortunately, are another kettle of fish.
1838     /// In such cases, def_id's can appear in types to distinguish
1839     /// shadowed bound regions and so forth. It doesn't actually
1840     /// matter so much what we do to these, since regions are erased
1841     /// at trans time, but it's good to keep them consistent just in
1842     /// case. We translate them with `tr_def_id()` which will map
1843     /// the crate numbers back to the original source crate.
1844     ///
1845     /// Unboxed closures are cloned along with the function being
1846     /// inlined, and all side tables use interned node IDs, so we
1847     /// translate their def IDs accordingly.
1848     ///
1849     /// It'd be really nice to refactor the type repr to not include
1850     /// def-ids so that all these distinctions were unnecessary.
1851     fn convert_def_id(&mut self,
1852                       dcx: &DecodeContext,
1853                       source: tydecode::DefIdSource,
1854                       did: ast::DefId)
1855                       -> ast::DefId {
1856         let r = match source {
1857             NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
1858             TypeParameter | UnboxedClosureSource => dcx.tr_intern_def_id(did)
1859         };
1860         debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
1861         return r;
1862     }
1863 }
1864
1865 fn decode_side_tables(dcx: &DecodeContext,
1866                       ast_doc: rbml::Doc) {
1867     let tbl_doc = ast_doc.get(c::tag_table as uint);
1868     reader::docs(tbl_doc, |tag, entry_doc| {
1869         let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
1870         let id = dcx.tr_id(id0 as ast::NodeId);
1871
1872         debug!(">> Side table document with tag 0x{:x} \
1873                 found for id {} (orig {})",
1874                tag, id, id0);
1875
1876         match c::astencode_tag::from_uint(tag) {
1877             None => {
1878                 dcx.tcx.sess.bug(
1879                     &format!("unknown tag found in side tables: {:x}",
1880                             tag)[]);
1881             }
1882             Some(value) => {
1883                 let val_doc = entry_doc.get(c::tag_table_val as uint);
1884                 let mut val_dsr = reader::Decoder::new(val_doc);
1885                 let val_dsr = &mut val_dsr;
1886
1887                 match value {
1888                     c::tag_table_def => {
1889                         let def = decode_def(dcx, val_doc);
1890                         dcx.tcx.def_map.borrow_mut().insert(id, def);
1891                     }
1892                     c::tag_table_node_type => {
1893                         let ty = val_dsr.read_ty(dcx);
1894                         debug!("inserting ty for node {}: {}",
1895                                id, ty_to_string(dcx.tcx, ty));
1896                         dcx.tcx.node_types.borrow_mut().insert(id, ty);
1897                     }
1898                     c::tag_table_item_subst => {
1899                         let item_substs = ty::ItemSubsts {
1900                             substs: val_dsr.read_substs(dcx)
1901                         };
1902                         dcx.tcx.item_substs.borrow_mut().insert(
1903                             id, item_substs);
1904                     }
1905                     c::tag_table_freevars => {
1906                         let fv_info = val_dsr.read_to_vec(|val_dsr| {
1907                             Ok(val_dsr.read_freevar_entry(dcx))
1908                         }).unwrap().into_iter().collect();
1909                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
1910                     }
1911                     c::tag_table_upvar_borrow_map => {
1912                         let var_id: ast::NodeId = Decodable::decode(val_dsr).unwrap();
1913                         let upvar_id = ty::UpvarId {
1914                             var_id: dcx.tr_id(var_id),
1915                             closure_expr_id: id
1916                         };
1917                         let ub: ty::UpvarBorrow = Decodable::decode(val_dsr).unwrap();
1918                         dcx.tcx.upvar_borrow_map.borrow_mut().insert(upvar_id, ub.tr(dcx));
1919                     }
1920                     c::tag_table_capture_modes => {
1921                         let capture_mode = val_dsr.read_capture_mode();
1922                         dcx.tcx
1923                            .capture_modes
1924                            .borrow_mut()
1925                            .insert(id, capture_mode);
1926                     }
1927                     c::tag_table_tcache => {
1928                         let type_scheme = val_dsr.read_type_scheme(dcx);
1929                         let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
1930                         dcx.tcx.tcache.borrow_mut().insert(lid, type_scheme);
1931                     }
1932                     c::tag_table_param_defs => {
1933                         let bounds = val_dsr.read_type_param_def(dcx);
1934                         dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
1935                     }
1936                     c::tag_table_method_map => {
1937                         let (adjustment, method) = val_dsr.read_method_callee(dcx);
1938                         let method_call = MethodCall {
1939                             expr_id: id,
1940                             adjustment: adjustment
1941                         };
1942                         dcx.tcx.method_map.borrow_mut().insert(method_call, method);
1943                     }
1944                     c::tag_table_object_cast_map => {
1945                         let trait_ref = val_dsr.read_poly_trait_ref(dcx);
1946                         dcx.tcx.object_cast_map.borrow_mut()
1947                                                .insert(id, trait_ref);
1948                     }
1949                     c::tag_table_adjustments => {
1950                         let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
1951                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
1952                     }
1953                     c::tag_table_unboxed_closures => {
1954                         let unboxed_closure =
1955                             val_dsr.read_unboxed_closure(dcx);
1956                         dcx.tcx
1957                            .unboxed_closures
1958                            .borrow_mut()
1959                            .insert(ast_util::local_def(id),
1960                                    unboxed_closure);
1961                     }
1962                     _ => {
1963                         dcx.tcx.sess.bug(
1964                             &format!("unknown tag found in side tables: {:x}",
1965                                     tag)[]);
1966                     }
1967                 }
1968             }
1969         }
1970
1971         debug!(">< Side table doc loaded");
1972         true
1973     });
1974 }
1975
1976 // ______________________________________________________________________
1977 // Testing of astencode_gen
1978
1979 #[cfg(test)]
1980 fn encode_item_ast(rbml_w: &mut Encoder, item: &ast::Item) {
1981     rbml_w.start_tag(c::tag_tree as uint);
1982     (*item).encode(rbml_w);
1983     rbml_w.end_tag();
1984 }
1985
1986 #[cfg(test)]
1987 fn decode_item_ast(par_doc: rbml::Doc) -> ast::Item {
1988     let chi_doc = par_doc.get(c::tag_tree as uint);
1989     let mut d = reader::Decoder::new(chi_doc);
1990     Decodable::decode(&mut d).unwrap()
1991 }
1992
1993 #[cfg(test)]
1994 trait fake_ext_ctxt {
1995     fn cfg(&self) -> ast::CrateConfig;
1996     fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess;
1997     fn call_site(&self) -> Span;
1998     fn ident_of(&self, st: &str) -> ast::Ident;
1999 }
2000
2001 #[cfg(test)]
2002 impl fake_ext_ctxt for parse::ParseSess {
2003     fn cfg(&self) -> ast::CrateConfig {
2004         Vec::new()
2005     }
2006     fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { self }
2007     fn call_site(&self) -> Span {
2008         codemap::Span {
2009             lo: codemap::BytePos(0),
2010             hi: codemap::BytePos(0),
2011             expn_id: codemap::NO_EXPANSION
2012         }
2013     }
2014     fn ident_of(&self, st: &str) -> ast::Ident {
2015         token::str_to_ident(st)
2016     }
2017 }
2018
2019 #[cfg(test)]
2020 fn mk_ctxt() -> parse::ParseSess {
2021     parse::new_parse_sess()
2022 }
2023
2024 #[cfg(test)]
2025 fn roundtrip(in_item: Option<P<ast::Item>>) {
2026     let in_item = in_item.unwrap();
2027     let mut wr = SeekableMemWriter::new();
2028     encode_item_ast(&mut writer::Encoder::new(&mut wr), &*in_item);
2029     let rbml_doc = rbml::Doc::new(wr.get_ref());
2030     let out_item = decode_item_ast(rbml_doc);
2031
2032     assert!(*in_item == out_item);
2033 }
2034
2035 #[test]
2036 fn test_basic() {
2037     let cx = mk_ctxt();
2038     roundtrip(quote_item!(&cx,
2039         fn foo() {}
2040     ));
2041 }
2042 /* NOTE: When there's a snapshot, update this (yay quasiquoter!)
2043 #[test]
2044 fn test_smalltalk() {
2045     let cx = mk_ctxt();
2046     roundtrip(quote_item!(&cx,
2047         fn foo() -> int { 3 + 4 } // first smalltalk program ever executed.
2048     ));
2049 }
2050 */
2051
2052 #[test]
2053 fn test_more() {
2054     let cx = mk_ctxt();
2055     roundtrip(quote_item!(&cx,
2056         fn foo(x: uint, y: uint) -> uint {
2057             let z = x + y;
2058             return z;
2059         }
2060     ));
2061 }
2062
2063 #[test]
2064 fn test_simplification() {
2065     let cx = mk_ctxt();
2066     let item = quote_item!(&cx,
2067         fn new_int_alist<B>() -> alist<int, B> {
2068             fn eq_int(a: int, b: int) -> bool { a == b }
2069             return alist {eq_fn: eq_int, data: Vec::new()};
2070         }
2071     ).unwrap();
2072     let item_in = e::IIItemRef(&*item);
2073     let item_out = simplify_ast(item_in);
2074     let item_exp = ast::IIItem(quote_item!(&cx,
2075         fn new_int_alist<B>() -> alist<int, B> {
2076             return alist {eq_fn: eq_int, data: Vec::new()};
2077         }
2078     ).unwrap());
2079     match (item_out, item_exp) {
2080       (ast::IIItem(item_out), ast::IIItem(item_exp)) => {
2081         assert!(pprust::item_to_string(&*item_out) ==
2082                 pprust::item_to_string(&*item_exp));
2083       }
2084       _ => panic!()
2085     }
2086 }