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