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