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