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