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