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