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