]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/astencode.rs
6c23307c67776570279eecaf7d967e81a161f34b
[rust.git] / src / librustc / middle / astencode.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(non_camel_case_types)]
12 // FIXME: remove this after snapshot, and Results are handled
13 #![allow(unused_must_use)]
14
15 use front::map as ast_map;
16 use rustc_front::hir;
17 use rustc_front::fold;
18 use rustc_front::fold::Folder;
19
20 use metadata::common as c;
21 use metadata::cstore as cstore;
22 use session::Session;
23 use metadata::decoder;
24 use metadata::encoder as e;
25 use metadata::inline::{InlinedItem, InlinedItemRef};
26 use metadata::tydecode;
27 use metadata::tyencode;
28 use middle::ty::adjustment;
29 use middle::ty::cast;
30 use middle::check_const::ConstQualif;
31 use middle::def;
32 use middle::def_id::DefId;
33 use middle::privacy::{AllPublic, LastMod};
34 use middle::region;
35 use middle::subst;
36 use middle::ty::{self, Ty};
37
38 use syntax::{ast, ast_util, codemap};
39 use syntax::codemap::Span;
40 use syntax::ptr::P;
41
42 use std::cell::Cell;
43 use std::io::SeekFrom;
44 use std::io::prelude::*;
45 use std::fmt::Debug;
46
47 use rbml::reader;
48 use rbml::writer::Encoder;
49 use rbml;
50 use serialize;
51 use serialize::{Decodable, Decoder, DecoderHelpers, Encodable};
52 use serialize::EncoderHelpers;
53
54 #[cfg(test)] use std::io::Cursor;
55 #[cfg(test)] use syntax::parse;
56 #[cfg(test)] use rustc_front::print::pprust;
57 #[cfg(test)] use rustc_front::lowering::lower_item;
58
59 struct DecodeContext<'a, 'b, 'tcx: 'a> {
60     tcx: &'a ty::ctxt<'tcx>,
61     cdata: &'b cstore::crate_metadata,
62     from_id_range: ast_util::IdRange,
63     to_id_range: ast_util::IdRange,
64     // Cache the last used filemap for translating spans as an optimization.
65     last_filemap_index: Cell<usize>,
66 }
67
68 trait tr {
69     fn tr(&self, dcx: &DecodeContext) -> Self;
70 }
71
72 // ______________________________________________________________________
73 // Top-level methods.
74
75 pub fn encode_inlined_item(ecx: &e::EncodeContext,
76                            rbml_w: &mut Encoder,
77                            ii: InlinedItemRef) {
78     let id = match ii {
79         InlinedItemRef::Item(i) => i.id,
80         InlinedItemRef::Foreign(i) => i.id,
81         InlinedItemRef::TraitItem(_, ti) => ti.id,
82         InlinedItemRef::ImplItem(_, ii) => ii.id,
83     };
84     debug!("> Encoding inlined item: {} ({:?})",
85            ecx.tcx.map.path_to_string(id),
86            rbml_w.writer.seek(SeekFrom::Current(0)));
87
88     // Folding could be avoided with a smarter encoder.
89     let ii = simplify_ast(ii);
90     let id_range = ii.compute_id_range();
91
92     rbml_w.start_tag(c::tag_ast as usize);
93     id_range.encode(rbml_w);
94     encode_ast(rbml_w, &ii);
95     encode_side_tables_for_ii(ecx, rbml_w, &ii);
96     rbml_w.end_tag();
97
98     debug!("< Encoded inlined fn: {} ({:?})",
99            ecx.tcx.map.path_to_string(id),
100            rbml_w.writer.seek(SeekFrom::Current(0)));
101 }
102
103 impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
104     fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
105         if id == ast::DUMMY_NODE_ID {
106             // Used by ast_map to map the NodeInlinedParent.
107             self.tcx.sess.next_node_id()
108         } else {
109             self.tr_id(id)
110         }
111     }
112     fn new_def_id(&self, def_id: DefId) -> DefId {
113         self.tr_def_id(def_id)
114     }
115     fn new_span(&self, span: Span) -> Span {
116         self.tr_span(span)
117     }
118 }
119
120 /// Decodes an item from its AST in the cdata's metadata and adds it to the
121 /// ast-map.
122 pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
123                                  tcx: &ty::ctxt<'tcx>,
124                                  path: Vec<ast_map::PathElem>,
125                                  def_path: ast_map::DefPath,
126                                  par_doc: rbml::Doc,
127                                  orig_did: DefId)
128                                  -> Result<&'tcx InlinedItem, (Vec<ast_map::PathElem>,
129                                                                ast_map::DefPath)> {
130     match par_doc.opt_child(c::tag_ast) {
131       None => Err((path, def_path)),
132       Some(ast_doc) => {
133         let mut path_as_str = None;
134         debug!("> Decoding inlined fn: {:?}::?",
135         {
136             // Do an Option dance to use the path after it is moved below.
137             let s = ast_map::path_to_string(path.iter().cloned());
138             path_as_str = Some(s);
139             path_as_str.as_ref().map(|x| &x[..])
140         });
141         let mut ast_dsr = reader::Decoder::new(ast_doc);
142         let from_id_range = Decodable::decode(&mut ast_dsr).unwrap();
143         let to_id_range = reserve_id_range(&tcx.sess, from_id_range);
144         let dcx = &DecodeContext {
145             cdata: cdata,
146             tcx: tcx,
147             from_id_range: from_id_range,
148             to_id_range: to_id_range,
149             last_filemap_index: Cell::new(0)
150         };
151         let raw_ii = decode_ast(ast_doc);
152         let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, def_path, raw_ii, dcx);
153
154         let name = match *ii {
155             InlinedItem::Item(ref i) => i.name,
156             InlinedItem::Foreign(ref i) => i.name,
157             InlinedItem::TraitItem(_, ref ti) => ti.name,
158             InlinedItem::ImplItem(_, ref ii) => ii.name
159         };
160         debug!("Fn named: {}", name);
161         debug!("< Decoded inlined fn: {}::{}",
162                path_as_str.unwrap(),
163                name);
164         region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii);
165         decode_side_tables(dcx, ast_doc);
166         copy_item_types(dcx, ii, orig_did);
167         match *ii {
168           InlinedItem::Item(ref i) => {
169             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
170                    ::rustc_front::print::pprust::item_to_string(&**i));
171           }
172           _ => { }
173         }
174         Ok(ii)
175       }
176     }
177 }
178
179 // ______________________________________________________________________
180 // Enumerating the IDs which appear in an AST
181
182 fn reserve_id_range(sess: &Session,
183                     from_id_range: ast_util::IdRange) -> ast_util::IdRange {
184     // Handle the case of an empty range:
185     if from_id_range.empty() { return from_id_range; }
186     let cnt = from_id_range.max - from_id_range.min;
187     let to_id_min = sess.reserve_node_ids(cnt);
188     let to_id_max = to_id_min + cnt;
189     ast_util::IdRange { min: to_id_min, max: to_id_max }
190 }
191
192 impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
193     /// Translates an internal id, meaning a node id that is known to refer to some part of the
194     /// item currently being inlined, such as a local variable or argument.  All naked node-ids
195     /// that appear in types have this property, since if something might refer to an external item
196     /// we would use a def-id to allow for the possibility that the item resides in another crate.
197     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
198         // from_id_range should be non-empty
199         assert!(!self.from_id_range.empty());
200         // Use wrapping arithmetic because otherwise it introduces control flow.
201         // Maybe we should just have the control flow? -- aatch
202         (id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min))
203     }
204
205     /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
206     /// data to the current crate numbers..  By external, I mean that it be translated to a
207     /// reference to the item in its original crate, as opposed to being translated to a reference
208     /// to the inlined version of the item.  This is typically, but not always, what you want,
209     /// because most def-ids refer to external things like types or other fns that may or may not
210     /// be inlined.  Note that even when the inlined function is referencing itself recursively, we
211     /// would want `tr_def_id` for that reference--- conceptually the function calls the original,
212     /// non-inlined version, and trans deals with linking that recursive call to the inlined copy.
213     pub fn tr_def_id(&self, did: DefId) -> DefId {
214         decoder::translate_def_id(self.cdata, did)
215     }
216
217     /// Translates a `Span` from an extern crate to the corresponding `Span`
218     /// within the local crate's codemap. `creader::import_codemap()` will
219     /// already have allocated any additionally needed FileMaps in the local
220     /// codemap as a side-effect of creating the crate_metadata's
221     /// `codemap_import_info`.
222     pub fn tr_span(&self, span: Span) -> Span {
223         let span = if span.lo > span.hi {
224             // Currently macro expansion sometimes produces invalid Span values
225             // where lo > hi. In order not to crash the compiler when trying to
226             // translate these values, let's transform them into something we
227             // can handle (and which will produce useful debug locations at
228             // least some of the time).
229             // This workaround is only necessary as long as macro expansion is
230             // not fixed. FIXME(#23480)
231             codemap::mk_sp(span.lo, span.lo)
232         } else {
233             span
234         };
235
236         let imported_filemaps = self.cdata.imported_filemaps(self.tcx.sess.codemap());
237         let filemap = {
238             // Optimize for the case that most spans within a translated item
239             // originate from the same filemap.
240             let last_filemap_index = self.last_filemap_index.get();
241             let last_filemap = &imported_filemaps[last_filemap_index];
242
243             if span.lo >= last_filemap.original_start_pos &&
244                span.lo <= last_filemap.original_end_pos &&
245                span.hi >= last_filemap.original_start_pos &&
246                span.hi <= last_filemap.original_end_pos {
247                 last_filemap
248             } else {
249                 let mut a = 0;
250                 let mut b = imported_filemaps.len();
251
252                 while b - a > 1 {
253                     let m = (a + b) / 2;
254                     if imported_filemaps[m].original_start_pos > span.lo {
255                         b = m;
256                     } else {
257                         a = m;
258                     }
259                 }
260
261                 self.last_filemap_index.set(a);
262                 &imported_filemaps[a]
263             }
264         };
265
266         let lo = (span.lo - filemap.original_start_pos) +
267                   filemap.translated_filemap.start_pos;
268         let hi = (span.hi - filemap.original_start_pos) +
269                   filemap.translated_filemap.start_pos;
270
271         codemap::mk_sp(lo, hi)
272     }
273 }
274
275 impl tr for DefId {
276     fn tr(&self, dcx: &DecodeContext) -> DefId {
277         dcx.tr_def_id(*self)
278     }
279 }
280
281 impl tr for Option<DefId> {
282     fn tr(&self, dcx: &DecodeContext) -> Option<DefId> {
283         self.map(|d| dcx.tr_def_id(d))
284     }
285 }
286
287 impl tr for Span {
288     fn tr(&self, dcx: &DecodeContext) -> Span {
289         dcx.tr_span(*self)
290     }
291 }
292
293 trait def_id_encoder_helpers {
294     fn emit_def_id(&mut self, did: DefId);
295 }
296
297 impl<S:serialize::Encoder> def_id_encoder_helpers for S
298     where <S as serialize::serialize::Encoder>::Error: Debug
299 {
300     fn emit_def_id(&mut self, did: DefId) {
301         did.encode(self).unwrap()
302     }
303 }
304
305 trait def_id_decoder_helpers {
306     fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId;
307     fn read_def_id_nodcx(&mut self,
308                          cdata: &cstore::crate_metadata) -> DefId;
309 }
310
311 impl<D:serialize::Decoder> def_id_decoder_helpers for D
312     where <D as serialize::serialize::Decoder>::Error: Debug
313 {
314     fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId {
315         let did: DefId = Decodable::decode(self).unwrap();
316         did.tr(dcx)
317     }
318
319     fn read_def_id_nodcx(&mut self,
320                          cdata: &cstore::crate_metadata)
321                          -> DefId {
322         let did: DefId = Decodable::decode(self).unwrap();
323         decoder::translate_def_id(cdata, did)
324     }
325 }
326
327 // ______________________________________________________________________
328 // Encoding and decoding the AST itself
329 //
330 // When decoding, we have to renumber the AST so that the node ids that
331 // appear within are disjoint from the node ids in our existing ASTs.
332 // We also have to adjust the spans: for now we just insert a dummy span,
333 // but eventually we should add entries to the local codemap as required.
334
335 fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
336     rbml_w.start_tag(c::tag_tree as usize);
337     item.encode(rbml_w);
338     rbml_w.end_tag();
339 }
340
341 struct NestedItemsDropper;
342
343 impl Folder for NestedItemsDropper {
344     fn fold_block(&mut self, blk: P<hir::Block>) -> P<hir::Block> {
345         blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| {
346             let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
347                 let use_stmt = match stmt.node {
348                     hir::StmtExpr(_, _) | hir::StmtSemi(_, _) => true,
349                     hir::StmtDecl(ref decl, _) => {
350                         match decl.node {
351                             hir::DeclLocal(_) => true,
352                             hir::DeclItem(_) => false,
353                         }
354                     }
355                 };
356                 if use_stmt {
357                     Some(stmt)
358                 } else {
359                     None
360                 }
361             }).collect();
362             let blk_sans_items = P(hir::Block {
363                 stmts: stmts_sans_items,
364                 expr: expr,
365                 id: id,
366                 rules: rules,
367                 span: span,
368             });
369             fold::noop_fold_block(blk_sans_items, self)
370         })
371     }
372 }
373
374 // Produces a simplified copy of the AST which does not include things
375 // that we do not need to or do not want to export.  For example, we
376 // do not include any nested items: if these nested items are to be
377 // inlined, their AST will be exported separately (this only makes
378 // sense because, in Rust, nested items are independent except for
379 // their visibility).
380 //
381 // As it happens, trans relies on the fact that we do not export
382 // nested items, as otherwise it would get confused when translating
383 // inlined items.
384 fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
385     let mut fld = NestedItemsDropper;
386
387     match ii {
388         // HACK we're not dropping items.
389         InlinedItemRef::Item(i) => {
390             InlinedItem::Item(fold::noop_fold_item(P(i.clone()), &mut fld)
391                             .expect_one("expected one item"))
392         }
393         InlinedItemRef::TraitItem(d, ti) => {
394             InlinedItem::TraitItem(d,
395                 fold::noop_fold_trait_item(P(ti.clone()), &mut fld)
396                     .expect_one("noop_fold_trait_item must produce \
397                                  exactly one trait item"))
398         }
399         InlinedItemRef::ImplItem(d, ii) => {
400             InlinedItem::ImplItem(d,
401                 fold::noop_fold_impl_item(P(ii.clone()), &mut fld)
402                     .expect_one("noop_fold_impl_item must produce \
403                                  exactly one impl item"))
404         }
405         InlinedItemRef::Foreign(i) => {
406             InlinedItem::Foreign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld))
407         }
408     }
409 }
410
411 fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
412     let chi_doc = par_doc.get(c::tag_tree as usize);
413     let mut d = reader::Decoder::new(chi_doc);
414     Decodable::decode(&mut d).unwrap()
415 }
416
417 // ______________________________________________________________________
418 // Encoding and decoding of ast::def
419
420 fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> def::Def {
421     let def: def::Def = Decodable::decode(dsr).unwrap();
422     def.tr(dcx)
423 }
424
425 impl tr for def::Def {
426     fn tr(&self, dcx: &DecodeContext) -> def::Def {
427         match *self {
428           def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
429           def::DefMethod(did) => def::DefMethod(did.tr(dcx)),
430           def::DefSelfTy(opt_did, impl_ids) => { def::DefSelfTy(opt_did.map(|did| did.tr(dcx)),
431                                                                 impl_ids.map(|(nid1, nid2)| {
432                                                                     (dcx.tr_id(nid1),
433                                                                      dcx.tr_id(nid2))
434                                                                 })) }
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::DefAssociatedConst(did) => def::DefAssociatedConst(did.tr(dcx)),
440           def::DefLocal(_, nid) => {
441               let nid = dcx.tr_id(nid);
442               let did = dcx.tcx.map.local_def_id(nid);
443               def::DefLocal(did, nid)
444           }
445           def::DefVariant(e_did, v_did, is_s) => {
446             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
447           },
448           def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
449           def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
450           def::DefAssociatedTy(trait_did, did) =>
451               def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
452           def::DefPrimTy(p) => def::DefPrimTy(p),
453           def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
454           def::DefUse(did) => def::DefUse(did.tr(dcx)),
455           def::DefUpvar(_, nid1, index, nid2) => {
456               let nid1 = dcx.tr_id(nid1);
457               let nid2 = dcx.tr_id(nid2);
458               let did1 = dcx.tcx.map.local_def_id(nid1);
459               def::DefUpvar(did1, nid1, index, nid2)
460           }
461           def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
462           def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
463         }
464     }
465 }
466
467 // ______________________________________________________________________
468 // Encoding and decoding of freevar information
469
470 fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &ty::Freevar) {
471     (*fv).encode(rbml_w).unwrap();
472 }
473
474 trait rbml_decoder_helper {
475     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
476                           -> ty::Freevar;
477     fn read_capture_mode(&mut self) -> hir::CaptureClause;
478 }
479
480 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
481     fn read_freevar_entry(&mut self, dcx: &DecodeContext)
482                           -> ty::Freevar {
483         let fv: ty::Freevar = Decodable::decode(self).unwrap();
484         fv.tr(dcx)
485     }
486
487     fn read_capture_mode(&mut self) -> hir::CaptureClause {
488         let cm: hir::CaptureClause = Decodable::decode(self).unwrap();
489         cm
490     }
491 }
492
493 impl tr for ty::Freevar {
494     fn tr(&self, dcx: &DecodeContext) -> ty::Freevar {
495         ty::Freevar {
496             def: self.def.tr(dcx),
497             span: self.span.tr(dcx),
498         }
499     }
500 }
501
502 // ______________________________________________________________________
503 // Encoding and decoding of MethodCallee
504
505 trait read_method_callee_helper<'tcx> {
506     fn read_method_callee<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
507                                   -> (u32, ty::MethodCallee<'tcx>);
508 }
509
510 fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>,
511                                   rbml_w: &mut Encoder,
512                                   autoderef: u32,
513                                   method: &ty::MethodCallee<'tcx>) {
514     use serialize::Encoder;
515
516     rbml_w.emit_struct("MethodCallee", 4, |rbml_w| {
517         rbml_w.emit_struct_field("autoderef", 0, |rbml_w| {
518             autoderef.encode(rbml_w)
519         });
520         rbml_w.emit_struct_field("def_id", 1, |rbml_w| {
521             Ok(rbml_w.emit_def_id(method.def_id))
522         });
523         rbml_w.emit_struct_field("ty", 2, |rbml_w| {
524             Ok(rbml_w.emit_ty(ecx, method.ty))
525         });
526         rbml_w.emit_struct_field("substs", 3, |rbml_w| {
527             Ok(rbml_w.emit_substs(ecx, &method.substs))
528         })
529     }).unwrap();
530 }
531
532 impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
533     fn read_method_callee<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
534                                   -> (u32, ty::MethodCallee<'tcx>) {
535
536         self.read_struct("MethodCallee", 4, |this| {
537             let autoderef = this.read_struct_field("autoderef", 0,
538                                                    Decodable::decode).unwrap();
539             Ok((autoderef, ty::MethodCallee {
540                 def_id: this.read_struct_field("def_id", 1, |this| {
541                     Ok(this.read_def_id(dcx))
542                 }).unwrap(),
543                 ty: this.read_struct_field("ty", 2, |this| {
544                     Ok(this.read_ty(dcx))
545                 }).unwrap(),
546                 substs: this.read_struct_field("substs", 3, |this| {
547                     Ok(dcx.tcx.mk_substs(this.read_substs(dcx)))
548                 }).unwrap()
549             }))
550         }).unwrap()
551     }
552 }
553
554 pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
555     kind.encode(ebml_w).unwrap();
556 }
557
558 // ______________________________________________________________________
559 // Encoding and decoding the side tables
560
561 trait get_ty_str_ctxt<'tcx> {
562     fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a, 'tcx>;
563 }
564
565 impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> {
566     fn ty_str_ctxt<'b>(&'b self) -> tyencode::ctxt<'b, 'tcx> {
567         tyencode::ctxt {
568             diag: self.tcx.sess.diagnostic(),
569             ds: e::def_to_string,
570             tcx: self.tcx,
571             abbrevs: &self.type_abbrevs
572         }
573     }
574 }
575
576 trait rbml_writer_helpers<'tcx> {
577     fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
578     fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
579     fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
580     fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
581                           predicate: &ty::Predicate<'tcx>);
582     fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
583                           ty: &ty::TraitRef<'tcx>);
584     fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
585                        substs: &subst::Substs<'tcx>);
586     fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
587                                    bounds: &ty::ExistentialBounds<'tcx>);
588     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
589     fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture);
590     fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
591                                 adj: &adjustment::AutoAdjustment<'tcx>);
592     fn emit_autoref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
593                         autoref: &adjustment::AutoRef<'tcx>);
594     fn emit_auto_deref_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
595                                auto_deref_ref: &adjustment::AutoDerefRef<'tcx>);
596 }
597
598 impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
599     fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) {
600         self.emit_opaque(|this| Ok(e::write_region(ecx, this, r)));
601     }
602
603     fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
604         self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty)));
605     }
606
607     fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) {
608         self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty)));
609     }
610
611     fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
612                           trait_ref: &ty::TraitRef<'tcx>) {
613         self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref)));
614     }
615
616     fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
617                           predicate: &ty::Predicate<'tcx>) {
618         self.emit_opaque(|this| {
619             Ok(tyencode::enc_predicate(this,
620                                        &ecx.ty_str_ctxt(),
621                                        predicate))
622         });
623     }
624
625     fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
626                                    bounds: &ty::ExistentialBounds<'tcx>) {
627         self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this,
628                                                                     &ecx.ty_str_ctxt(),
629                                                                     bounds)));
630     }
631
632     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
633         self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this,
634                                                                 &ecx.ty_str_ctxt(),
635                                                                 bounds)));
636     }
637
638     fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture) {
639         use serialize::Encoder;
640
641         self.emit_enum("UpvarCapture", |this| {
642             match *capture {
643                 ty::UpvarCapture::ByValue => {
644                     this.emit_enum_variant("ByValue", 1, 0, |_| Ok(()))
645                 }
646                 ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind, region }) => {
647                     this.emit_enum_variant("ByRef", 2, 0, |this| {
648                         this.emit_enum_variant_arg(0,
649                             |this| kind.encode(this));
650                         this.emit_enum_variant_arg(1,
651                             |this| Ok(this.emit_region(ecx, region)))
652                     })
653                 }
654             }
655         }).unwrap()
656     }
657
658     fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
659                        substs: &subst::Substs<'tcx>) {
660         self.emit_opaque(|this| Ok(tyencode::enc_substs(this,
661                                                            &ecx.ty_str_ctxt(),
662                                                            substs)));
663     }
664
665     fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
666                                 adj: &adjustment::AutoAdjustment<'tcx>) {
667         use serialize::Encoder;
668
669         self.emit_enum("AutoAdjustment", |this| {
670             match *adj {
671                 adjustment::AdjustReifyFnPointer=> {
672                     this.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_| Ok(()))
673                 }
674
675                 adjustment::AdjustUnsafeFnPointer => {
676                     this.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_| {
677                         Ok(())
678                     })
679                 }
680
681                 adjustment::AdjustDerefRef(ref auto_deref_ref) => {
682                     this.emit_enum_variant("AdjustDerefRef", 3, 2, |this| {
683                         this.emit_enum_variant_arg(0,
684                             |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
685                     })
686                 }
687             }
688         });
689     }
690
691     fn emit_autoref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
692                         autoref: &adjustment::AutoRef<'tcx>) {
693         use serialize::Encoder;
694
695         self.emit_enum("AutoRef", |this| {
696             match autoref {
697                 &adjustment::AutoPtr(r, m) => {
698                     this.emit_enum_variant("AutoPtr", 0, 2, |this| {
699                         this.emit_enum_variant_arg(0,
700                             |this| Ok(this.emit_region(ecx, *r)));
701                         this.emit_enum_variant_arg(1, |this| m.encode(this))
702                     })
703                 }
704                 &adjustment::AutoUnsafe(m) => {
705                     this.emit_enum_variant("AutoUnsafe", 1, 1, |this| {
706                         this.emit_enum_variant_arg(0, |this| m.encode(this))
707                     })
708                 }
709             }
710         });
711     }
712
713     fn emit_auto_deref_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
714                                auto_deref_ref: &adjustment::AutoDerefRef<'tcx>) {
715         use serialize::Encoder;
716
717         self.emit_struct("AutoDerefRef", 2, |this| {
718             this.emit_struct_field("autoderefs", 0, |this| auto_deref_ref.autoderefs.encode(this));
719
720             this.emit_struct_field("autoref", 1, |this| {
721                 this.emit_option(|this| {
722                     match auto_deref_ref.autoref {
723                         None => this.emit_option_none(),
724                         Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a))),
725                     }
726                 })
727             });
728
729             this.emit_struct_field("unsize", 2, |this| {
730                 this.emit_option(|this| {
731                     match auto_deref_ref.unsize {
732                         None => this.emit_option_none(),
733                         Some(target) => this.emit_option_some(|this| {
734                             Ok(this.emit_ty(ecx, target))
735                         })
736                     }
737                 })
738             })
739         });
740     }
741 }
742
743 trait write_tag_and_id {
744     fn tag<F>(&mut self, tag_id: c::astencode_tag, f: F) where F: FnOnce(&mut Self);
745     fn id(&mut self, id: ast::NodeId);
746 }
747
748 impl<'a> write_tag_and_id for Encoder<'a> {
749     fn tag<F>(&mut self,
750               tag_id: c::astencode_tag,
751               f: F) where
752         F: FnOnce(&mut Encoder<'a>),
753     {
754         self.start_tag(tag_id as usize);
755         f(self);
756         self.end_tag();
757     }
758
759     fn id(&mut self, id: ast::NodeId) {
760         id.encode(self).unwrap();
761     }
762 }
763
764 struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
765     ecx: &'a e::EncodeContext<'c, 'tcx>,
766     rbml_w: &'a mut Encoder<'b>,
767 }
768
769 impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for
770         SideTableEncodingIdVisitor<'a, 'b, 'c, 'tcx> {
771     fn visit_id(&mut self, id: ast::NodeId) {
772         encode_side_tables_for_id(self.ecx, self.rbml_w, id)
773     }
774 }
775
776 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
777                              rbml_w: &mut Encoder,
778                              ii: &InlinedItem) {
779     rbml_w.start_tag(c::tag_table as usize);
780     ii.visit_ids(&mut SideTableEncodingIdVisitor {
781         ecx: ecx,
782         rbml_w: rbml_w
783     });
784     rbml_w.end_tag();
785 }
786
787 fn encode_side_tables_for_id(ecx: &e::EncodeContext,
788                              rbml_w: &mut Encoder,
789                              id: ast::NodeId) {
790     let tcx = ecx.tcx;
791
792     debug!("Encoding side tables for id {}", id);
793
794     if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
795         rbml_w.tag(c::tag_table_def, |rbml_w| {
796             rbml_w.id(id);
797             def.encode(rbml_w).unwrap();
798         })
799     }
800
801     if let Some(ty) = tcx.node_types().get(&id) {
802         rbml_w.tag(c::tag_table_node_type, |rbml_w| {
803             rbml_w.id(id);
804             rbml_w.emit_ty(ecx, *ty);
805         })
806     }
807
808     if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) {
809         rbml_w.tag(c::tag_table_item_subst, |rbml_w| {
810             rbml_w.id(id);
811             rbml_w.emit_substs(ecx, &item_substs.substs);
812         })
813     }
814
815     if let Some(fv) = tcx.freevars.borrow().get(&id) {
816         rbml_w.tag(c::tag_table_freevars, |rbml_w| {
817             rbml_w.id(id);
818             rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| {
819                 Ok(encode_freevar_entry(rbml_w, fv_entry))
820             });
821         });
822
823         for freevar in fv {
824             rbml_w.tag(c::tag_table_upvar_capture_map, |rbml_w| {
825                 rbml_w.id(id);
826
827                 let var_id = freevar.def.var_id();
828                 let upvar_id = ty::UpvarId {
829                     var_id: var_id,
830                     closure_expr_id: id
831                 };
832                 let upvar_capture = tcx.tables
833                                        .borrow()
834                                        .upvar_capture_map
835                                        .get(&upvar_id)
836                                        .unwrap()
837                                        .clone();
838                 var_id.encode(rbml_w);
839                 rbml_w.emit_upvar_capture(ecx, &upvar_capture);
840             })
841         }
842     }
843
844     let method_call = ty::MethodCall::expr(id);
845     if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
846         rbml_w.tag(c::tag_table_method_map, |rbml_w| {
847             rbml_w.id(id);
848             encode_method_callee(ecx, rbml_w, method_call.autoderef, method)
849         })
850     }
851
852     if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) {
853         match *adjustment {
854             adjustment::AdjustDerefRef(ref adj) => {
855                 for autoderef in 0..adj.autoderefs {
856                     let method_call = ty::MethodCall::autoderef(id, autoderef as u32);
857                     if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
858                         rbml_w.tag(c::tag_table_method_map, |rbml_w| {
859                             rbml_w.id(id);
860                             encode_method_callee(ecx, rbml_w,
861                                                  method_call.autoderef, method)
862                         })
863                     }
864                 }
865             }
866             _ => {}
867         }
868
869         rbml_w.tag(c::tag_table_adjustments, |rbml_w| {
870             rbml_w.id(id);
871             rbml_w.emit_auto_adjustment(ecx, adjustment);
872         })
873     }
874
875     if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) {
876         rbml_w.tag(c::tag_table_cast_kinds, |rbml_w| {
877             rbml_w.id(id);
878             encode_cast_kind(rbml_w, *cast_kind)
879         })
880     }
881
882     if let Some(qualif) = tcx.const_qualif_map.borrow().get(&id) {
883         rbml_w.tag(c::tag_table_const_qualif, |rbml_w| {
884             rbml_w.id(id);
885             qualif.encode(rbml_w).unwrap()
886         })
887     }
888 }
889
890 trait doc_decoder_helpers: Sized {
891     fn as_int(&self) -> isize;
892     fn opt_child(&self, tag: c::astencode_tag) -> Option<Self>;
893 }
894
895 impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
896     fn as_int(&self) -> isize { reader::doc_as_u64(*self) as isize }
897     fn opt_child(&self, tag: c::astencode_tag) -> Option<rbml::Doc<'a>> {
898         reader::maybe_get_doc(*self, tag as usize)
899     }
900 }
901
902 trait rbml_decoder_decoder_helpers<'tcx> {
903     fn read_ty_encoded<'a, 'b, F, R>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>,
904                                      f: F) -> R
905         where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x, 'tcx>) -> R;
906
907     fn read_region(&mut self, dcx: &DecodeContext) -> ty::Region;
908     fn read_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Ty<'tcx>;
909     fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
910     fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
911                               -> ty::TraitRef<'tcx>;
912     fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
913                                    -> ty::PolyTraitRef<'tcx>;
914     fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
915                               -> ty::Predicate<'tcx>;
916     fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
917                                        -> ty::ExistentialBounds<'tcx>;
918     fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
919                            -> subst::Substs<'tcx>;
920     fn read_upvar_capture(&mut self, dcx: &DecodeContext)
921                           -> ty::UpvarCapture;
922     fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
923                                     -> adjustment::AutoAdjustment<'tcx>;
924     fn read_cast_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
925                                  -> cast::CastKind;
926     fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
927                                    -> adjustment::AutoDerefRef<'tcx>;
928     fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
929                             -> adjustment::AutoRef<'tcx>;
930     fn convert_def_id(&mut self,
931                       dcx: &DecodeContext,
932                       did: DefId)
933                       -> DefId;
934
935     // Versions of the type reading functions that don't need the full
936     // DecodeContext.
937     fn read_ty_nodcx(&mut self,
938                      tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata) -> Ty<'tcx>;
939     fn read_tys_nodcx(&mut self,
940                       tcx: &ty::ctxt<'tcx>,
941                       cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
942     fn read_substs_nodcx(&mut self, tcx: &ty::ctxt<'tcx>,
943                          cdata: &cstore::crate_metadata)
944                          -> subst::Substs<'tcx>;
945 }
946
947 impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
948     fn read_ty_nodcx(&mut self,
949                      tcx: &ty::ctxt<'tcx>,
950                      cdata: &cstore::crate_metadata)
951                      -> Ty<'tcx> {
952         self.read_opaque(|_, doc| {
953             Ok(
954                 tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
955                                               &mut |id| decoder::translate_def_id(cdata, id))
956                     .parse_ty())
957         }).unwrap()
958     }
959
960     fn read_tys_nodcx(&mut self,
961                       tcx: &ty::ctxt<'tcx>,
962                       cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>> {
963         self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
964             .unwrap()
965             .into_iter()
966             .collect()
967     }
968
969     fn read_substs_nodcx(&mut self,
970                          tcx: &ty::ctxt<'tcx>,
971                          cdata: &cstore::crate_metadata)
972                          -> subst::Substs<'tcx>
973     {
974         self.read_opaque(|_, doc| {
975             Ok(
976                 tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
977                                               &mut |id| decoder::translate_def_id(cdata, id))
978                     .parse_substs())
979         }).unwrap()
980     }
981
982     fn read_ty_encoded<'b, 'c, F, R>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>, op: F) -> R
983         where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R
984     {
985         return self.read_opaque(|this, doc| {
986             debug!("read_ty_encoded({})", type_string(doc));
987             Ok(op(
988                 &mut tydecode::TyDecoder::with_doc(
989                     dcx.tcx, dcx.cdata.cnum, doc,
990                     &mut |a| this.convert_def_id(dcx, a))))
991         }).unwrap();
992
993         fn type_string(doc: rbml::Doc) -> String {
994             let mut str = String::new();
995             for i in doc.start..doc.end {
996                 str.push(doc.data[i] as char);
997             }
998             str
999         }
1000     }
1001     fn read_region(&mut self, dcx: &DecodeContext) -> ty::Region {
1002         // Note: regions types embed local node ids.  In principle, we
1003         // should translate these node ids into the new decode
1004         // context.  However, we do not bother, because region types
1005         // are not used during trans. This also applies to read_ty.
1006         return self.read_ty_encoded(dcx, |decoder| decoder.parse_region());
1007     }
1008     fn read_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> Ty<'tcx> {
1009         return self.read_ty_encoded(dcx, |decoder| decoder.parse_ty());
1010     }
1011
1012     fn read_tys<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1013                         -> Vec<Ty<'tcx>> {
1014         self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().into_iter().collect()
1015     }
1016
1017     fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1018                               -> ty::TraitRef<'tcx> {
1019         self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())
1020     }
1021
1022     fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1023                                    -> ty::PolyTraitRef<'tcx> {
1024         ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref()))
1025     }
1026
1027     fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1028                               -> ty::Predicate<'tcx>
1029     {
1030         self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate())
1031     }
1032
1033     fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1034                                        -> ty::ExistentialBounds<'tcx>
1035     {
1036         self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds())
1037     }
1038
1039     fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1040                            -> subst::Substs<'tcx> {
1041         self.read_opaque(|this, doc| {
1042             Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc,
1043                                              &mut |a| this.convert_def_id(dcx, a))
1044                .parse_substs())
1045         }).unwrap()
1046     }
1047     fn read_upvar_capture(&mut self, dcx: &DecodeContext) -> ty::UpvarCapture {
1048         self.read_enum("UpvarCapture", |this| {
1049             let variants = ["ByValue", "ByRef"];
1050             this.read_enum_variant(&variants, |this, i| {
1051                 Ok(match i {
1052                     1 => ty::UpvarCapture::ByValue,
1053                     2 => ty::UpvarCapture::ByRef(ty::UpvarBorrow {
1054                         kind: this.read_enum_variant_arg(0,
1055                                   |this| Decodable::decode(this)).unwrap(),
1056                         region: this.read_enum_variant_arg(1,
1057                                     |this| Ok(this.read_region(dcx))).unwrap()
1058                     }),
1059                     _ => panic!("bad enum variant for ty::UpvarCapture")
1060                 })
1061             })
1062         }).unwrap()
1063     }
1064     fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1065                                     -> adjustment::AutoAdjustment<'tcx> {
1066         self.read_enum("AutoAdjustment", |this| {
1067             let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustDerefRef"];
1068             this.read_enum_variant(&variants, |this, i| {
1069                 Ok(match i {
1070                     1 => adjustment::AdjustReifyFnPointer,
1071                     2 => adjustment::AdjustUnsafeFnPointer,
1072                     3 => {
1073                         let auto_deref_ref: adjustment::AutoDerefRef =
1074                             this.read_enum_variant_arg(0,
1075                                 |this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
1076
1077                         adjustment::AdjustDerefRef(auto_deref_ref)
1078                     }
1079                     _ => panic!("bad enum variant for adjustment::AutoAdjustment")
1080                 })
1081             })
1082         }).unwrap()
1083     }
1084
1085     fn read_auto_deref_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1086                                    -> adjustment::AutoDerefRef<'tcx> {
1087         self.read_struct("AutoDerefRef", 2, |this| {
1088             Ok(adjustment::AutoDerefRef {
1089                 autoderefs: this.read_struct_field("autoderefs", 0, |this| {
1090                     Decodable::decode(this)
1091                 }).unwrap(),
1092                 autoref: this.read_struct_field("autoref", 1, |this| {
1093                     this.read_option(|this, b| {
1094                         if b {
1095                             Ok(Some(this.read_autoref(dcx)))
1096                         } else {
1097                             Ok(None)
1098                         }
1099                     })
1100                 }).unwrap(),
1101                 unsize: this.read_struct_field("unsize", 2, |this| {
1102                     this.read_option(|this, b| {
1103                         if b {
1104                             Ok(Some(this.read_ty(dcx)))
1105                         } else {
1106                             Ok(None)
1107                         }
1108                     })
1109                 }).unwrap(),
1110             })
1111         }).unwrap()
1112     }
1113
1114     fn read_autoref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1115                             -> adjustment::AutoRef<'tcx> {
1116         self.read_enum("AutoRef", |this| {
1117             let variants = ["AutoPtr", "AutoUnsafe"];
1118             this.read_enum_variant(&variants, |this, i| {
1119                 Ok(match i {
1120                     0 => {
1121                         let r: ty::Region =
1122                             this.read_enum_variant_arg(0, |this| {
1123                                 Ok(this.read_region(dcx))
1124                             }).unwrap();
1125                         let m: hir::Mutability =
1126                             this.read_enum_variant_arg(1, |this| {
1127                                 Decodable::decode(this)
1128                             }).unwrap();
1129
1130                         adjustment::AutoPtr(dcx.tcx.mk_region(r), m)
1131                     }
1132                     1 => {
1133                         let m: hir::Mutability =
1134                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
1135
1136                         adjustment::AutoUnsafe(m)
1137                     }
1138                     _ => panic!("bad enum variant for adjustment::AutoRef")
1139                 })
1140             })
1141         }).unwrap()
1142     }
1143
1144     fn read_cast_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
1145                               -> cast::CastKind
1146     {
1147         Decodable::decode(self).unwrap()
1148     }
1149
1150     /// Converts a def-id that appears in a type.  The correct
1151     /// translation will depend on what kind of def-id this is.
1152     /// This is a subtle point: type definitions are not
1153     /// inlined into the current crate, so if the def-id names
1154     /// a nominal type or type alias, then it should be
1155     /// translated to refer to the source crate.
1156     ///
1157     /// However, *type parameters* are cloned along with the function
1158     /// they are attached to.  So we should translate those def-ids
1159     /// to refer to the new, cloned copy of the type parameter.
1160     /// We only see references to free type parameters in the body of
1161     /// an inlined function. In such cases, we need the def-id to
1162     /// be a local id so that the TypeContents code is able to lookup
1163     /// the relevant info in the ty_param_defs table.
1164     ///
1165     /// *Region parameters*, unfortunately, are another kettle of fish.
1166     /// In such cases, def_id's can appear in types to distinguish
1167     /// shadowed bound regions and so forth. It doesn't actually
1168     /// matter so much what we do to these, since regions are erased
1169     /// at trans time, but it's good to keep them consistent just in
1170     /// case. We translate them with `tr_def_id()` which will map
1171     /// the crate numbers back to the original source crate.
1172     ///
1173     /// Scopes will end up as being totally bogus. This can actually
1174     /// be fixed though.
1175     ///
1176     /// Unboxed closures are cloned along with the function being
1177     /// inlined, and all side tables use interned node IDs, so we
1178     /// translate their def IDs accordingly.
1179     ///
1180     /// It'd be really nice to refactor the type repr to not include
1181     /// def-ids so that all these distinctions were unnecessary.
1182     fn convert_def_id(&mut self,
1183                       dcx: &DecodeContext,
1184                       did: DefId)
1185                       -> DefId {
1186         let r = dcx.tr_def_id(did);
1187         debug!("convert_def_id(did={:?})={:?}", did, r);
1188         return r;
1189     }
1190 }
1191
1192 fn decode_side_tables(dcx: &DecodeContext,
1193                       ast_doc: rbml::Doc) {
1194     let tbl_doc = ast_doc.get(c::tag_table as usize);
1195     for (tag, entry_doc) in reader::docs(tbl_doc) {
1196         let mut entry_dsr = reader::Decoder::new(entry_doc);
1197         let id0: ast::NodeId = Decodable::decode(&mut entry_dsr).unwrap();
1198         let id = dcx.tr_id(id0);
1199
1200         debug!(">> Side table document with tag 0x{:x} \
1201                 found for id {} (orig {})",
1202                tag, id, id0);
1203         let tag = tag as u32;
1204         let decoded_tag: Option<c::astencode_tag> = c::astencode_tag::from_u32(tag);
1205         match decoded_tag {
1206             None => {
1207                 dcx.tcx.sess.bug(
1208                     &format!("unknown tag found in side tables: {:x}",
1209                             tag));
1210             }
1211             Some(value) => {
1212                 let val_dsr = &mut entry_dsr;
1213
1214                 match value {
1215                     c::tag_table_def => {
1216                         let def = decode_def(dcx, val_dsr);
1217                         dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
1218                             base_def: def,
1219                             // This doesn't matter cross-crate.
1220                             last_private: LastMod(AllPublic),
1221                             depth: 0
1222                         });
1223                     }
1224                     c::tag_table_node_type => {
1225                         let ty = val_dsr.read_ty(dcx);
1226                         debug!("inserting ty for node {}: {:?}",
1227                                id,  ty);
1228                         dcx.tcx.node_type_insert(id, ty);
1229                     }
1230                     c::tag_table_item_subst => {
1231                         let item_substs = ty::ItemSubsts {
1232                             substs: val_dsr.read_substs(dcx)
1233                         };
1234                         dcx.tcx.tables.borrow_mut().item_substs.insert(
1235                             id, item_substs);
1236                     }
1237                     c::tag_table_freevars => {
1238                         let fv_info = val_dsr.read_to_vec(|val_dsr| {
1239                             Ok(val_dsr.read_freevar_entry(dcx))
1240                         }).unwrap().into_iter().collect();
1241                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
1242                     }
1243                     c::tag_table_upvar_capture_map => {
1244                         let var_id: ast::NodeId = Decodable::decode(val_dsr).unwrap();
1245                         let upvar_id = ty::UpvarId {
1246                             var_id: dcx.tr_id(var_id),
1247                             closure_expr_id: id
1248                         };
1249                         let ub = val_dsr.read_upvar_capture(dcx);
1250                         dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub);
1251                     }
1252                     c::tag_table_method_map => {
1253                         let (autoderef, method) = val_dsr.read_method_callee(dcx);
1254                         let method_call = ty::MethodCall {
1255                             expr_id: id,
1256                             autoderef: autoderef
1257                         };
1258                         dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method);
1259                     }
1260                     c::tag_table_adjustments => {
1261                         let adj =
1262                             val_dsr.read_auto_adjustment(dcx);
1263                         dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj);
1264                     }
1265                     c::tag_table_cast_kinds => {
1266                         let cast_kind =
1267                             val_dsr.read_cast_kind(dcx);
1268                         dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind);
1269                     }
1270                     c::tag_table_const_qualif => {
1271                         let qualif: ConstQualif = Decodable::decode(val_dsr).unwrap();
1272                         dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif);
1273                     }
1274                     _ => {
1275                         dcx.tcx.sess.bug(
1276                             &format!("unknown tag found in side tables: {:x}",
1277                                     tag));
1278                     }
1279                 }
1280             }
1281         }
1282
1283         debug!(">< Side table doc loaded");
1284     }
1285 }
1286
1287 // copy the tcache entries from the original item to the new
1288 // inlined item
1289 fn copy_item_types(dcx: &DecodeContext, ii: &InlinedItem, orig_did: DefId) {
1290     fn copy_item_type(dcx: &DecodeContext,
1291                       inlined_id: ast::NodeId,
1292                       remote_did: DefId) {
1293         let inlined_did = dcx.tcx.map.local_def_id(inlined_id);
1294         dcx.tcx.register_item_type(inlined_did,
1295                                    dcx.tcx.lookup_item_type(remote_did));
1296
1297     }
1298     // copy the entry for the item itself
1299     let item_node_id = match ii {
1300         &InlinedItem::Item(ref i) => i.id,
1301         &InlinedItem::TraitItem(_, ref ti) => ti.id,
1302         &InlinedItem::ImplItem(_, ref ii) => ii.id,
1303         &InlinedItem::Foreign(ref fi) => fi.id
1304     };
1305     copy_item_type(dcx, item_node_id, orig_did);
1306
1307     // copy the entries of inner items
1308     if let &InlinedItem::Item(ref item) = ii {
1309         match item.node {
1310             hir::ItemEnum(ref def, _) => {
1311                 let orig_def = dcx.tcx.lookup_adt_def(orig_did);
1312                 for (i_variant, orig_variant) in
1313                     def.variants.iter().zip(orig_def.variants.iter())
1314                 {
1315                     copy_item_type(dcx, i_variant.node.id, orig_variant.did);
1316                 }
1317             }
1318             hir::ItemStruct(ref def, _) => {
1319                 if let Some(ctor_id) = def.ctor_id {
1320                     let ctor_did = dcx.tcx.lookup_adt_def(orig_did)
1321                         .struct_variant().ctor_id;
1322                     debug!("copying ctor {:?}", ctor_did);
1323                     copy_item_type(dcx, ctor_id, ctor_did);
1324                 }
1325             }
1326             _ => {}
1327         }
1328     }
1329 }
1330
1331 // ______________________________________________________________________
1332 // Testing of astencode_gen
1333
1334 #[cfg(test)]
1335 fn encode_item_ast(rbml_w: &mut Encoder, item: &hir::Item) {
1336     rbml_w.start_tag(c::tag_tree as usize);
1337     (*item).encode(rbml_w);
1338     rbml_w.end_tag();
1339 }
1340
1341 #[cfg(test)]
1342 fn decode_item_ast(par_doc: rbml::Doc) -> hir::Item {
1343     let chi_doc = par_doc.get(c::tag_tree as usize);
1344     let mut d = reader::Decoder::new(chi_doc);
1345     Decodable::decode(&mut d).unwrap()
1346 }
1347
1348 #[cfg(test)]
1349 trait FakeExtCtxt {
1350     fn call_site(&self) -> codemap::Span;
1351     fn cfg(&self) -> ast::CrateConfig;
1352     fn ident_of(&self, st: &str) -> ast::Ident;
1353     fn name_of(&self, st: &str) -> ast::Name;
1354     fn parse_sess(&self) -> &parse::ParseSess;
1355 }
1356
1357 #[cfg(test)]
1358 impl FakeExtCtxt for parse::ParseSess {
1359     fn call_site(&self) -> codemap::Span {
1360         codemap::Span {
1361             lo: codemap::BytePos(0),
1362             hi: codemap::BytePos(0),
1363             expn_id: codemap::NO_EXPANSION,
1364         }
1365     }
1366     fn cfg(&self) -> ast::CrateConfig { Vec::new() }
1367     fn ident_of(&self, st: &str) -> ast::Ident {
1368         parse::token::str_to_ident(st)
1369     }
1370     fn name_of(&self, st: &str) -> ast::Name {
1371         parse::token::intern(st)
1372     }
1373     fn parse_sess(&self) -> &parse::ParseSess { self }
1374 }
1375
1376 #[cfg(test)]
1377 fn mk_ctxt() -> parse::ParseSess {
1378     parse::ParseSess::new()
1379 }
1380
1381 #[cfg(test)]
1382 fn roundtrip(in_item: P<hir::Item>) {
1383     let mut wr = Cursor::new(Vec::new());
1384     encode_item_ast(&mut Encoder::new(&mut wr), &*in_item);
1385     let rbml_doc = rbml::Doc::new(wr.get_ref());
1386     let out_item = decode_item_ast(rbml_doc);
1387
1388     assert!(*in_item == out_item);
1389 }
1390
1391 #[test]
1392 fn test_basic() {
1393     let cx = mk_ctxt();
1394     roundtrip(lower_item(&quote_item!(&cx,
1395         fn foo() {}
1396     ).unwrap()));
1397 }
1398
1399 #[test]
1400 fn test_smalltalk() {
1401     let cx = mk_ctxt();
1402     roundtrip(lower_item(&quote_item!(&cx,
1403         fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
1404     ).unwrap()));
1405 }
1406
1407 #[test]
1408 fn test_more() {
1409     let cx = mk_ctxt();
1410     roundtrip(lower_item(&quote_item!(&cx,
1411         fn foo(x: usize, y: usize) -> usize {
1412             let z = x + y;
1413             return z;
1414         }
1415     ).unwrap()));
1416 }
1417
1418 #[test]
1419 fn test_simplification() {
1420     let cx = mk_ctxt();
1421     let item = quote_item!(&cx,
1422         fn new_int_alist<B>() -> alist<isize, B> {
1423             fn eq_int(a: isize, b: isize) -> bool { a == b }
1424             return alist {eq_fn: eq_int, data: Vec::new()};
1425         }
1426     ).unwrap();
1427     let hir_item = lower_item(&item);
1428     let item_in = InlinedItemRef::Item(&hir_item);
1429     let item_out = simplify_ast(item_in);
1430     let item_exp = InlinedItem::Item(lower_item(&quote_item!(&cx,
1431         fn new_int_alist<B>() -> alist<isize, B> {
1432             return alist {eq_fn: eq_int, data: Vec::new()};
1433         }
1434     ).unwrap()));
1435     match (item_out, item_exp) {
1436       (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
1437         assert!(pprust::item_to_string(&*item_out) ==
1438                 pprust::item_to_string(&*item_exp));
1439       }
1440       _ => panic!()
1441     }
1442 }