]> git.proxmox.com Git - rustc.git/blob - src/librustc_metadata/astencode.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.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::{IdRange, IdRangeComputingVisitor, IdVisitingOperation};
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;
38 use rustc::ty::{self, Ty, TyCtxt};
39
40 use syntax::{ast, codemap};
41 use syntax::ast::NodeIdAssigner;
42 use syntax::ptr::P;
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 serialize;
53 use serialize::{Decodable, Decoder, DecoderHelpers, Encodable};
54 use serialize::EncoderHelpers;
55
56 #[cfg(test)] use std::io::Cursor;
57 #[cfg(test)] use syntax::parse;
58 #[cfg(test)] use syntax::ast::NodeId;
59 #[cfg(test)] use rustc::hir::print as pprust;
60 #[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext};
61
62 struct DecodeContext<'a, 'b, 'tcx: 'a> {
63 tcx: &'a TyCtxt<'tcx>,
64 cdata: &'b cstore::crate_metadata,
65 from_id_range: IdRange,
66 to_id_range: IdRange,
67 // Cache the last used filemap for translating spans as an optimization.
68 last_filemap_index: Cell<usize>,
69 }
70
71 trait tr {
72 fn tr(&self, dcx: &DecodeContext) -> Self;
73 }
74
75 // ______________________________________________________________________
76 // Top-level methods.
77
78 pub fn encode_inlined_item(ecx: &e::EncodeContext,
79 rbml_w: &mut Encoder,
80 ii: InlinedItemRef) {
81 let id = match ii {
82 InlinedItemRef::Item(i) => i.id,
83 InlinedItemRef::Foreign(i) => i.id,
84 InlinedItemRef::TraitItem(_, ti) => ti.id,
85 InlinedItemRef::ImplItem(_, ii) => ii.id,
86 };
87 debug!("> Encoding inlined item: {} ({:?})",
88 ecx.tcx.node_path_str(id),
89 rbml_w.writer.seek(SeekFrom::Current(0)));
90
91 // Folding could be avoided with a smarter encoder.
92 let ii = simplify_ast(ii);
93 let id_range = inlined_item_id_range(&ii);
94
95 rbml_w.start_tag(c::tag_ast as usize);
96 id_range.encode(rbml_w);
97 encode_ast(rbml_w, &ii);
98 encode_side_tables_for_ii(ecx, rbml_w, &ii);
99 rbml_w.end_tag();
100
101 debug!("< Encoded inlined fn: {} ({:?})",
102 ecx.tcx.node_path_str(id),
103 rbml_w.writer.seek(SeekFrom::Current(0)));
104 }
105
106 impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
107 fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
108 if id == ast::DUMMY_NODE_ID {
109 // Used by ast_map to map the NodeInlinedParent.
110 self.tcx.sess.next_node_id()
111 } else {
112 self.tr_id(id)
113 }
114 }
115 fn new_def_id(&self, def_id: DefId) -> DefId {
116 self.tr_def_id(def_id)
117 }
118 fn new_span(&self, span: codemap::Span) -> codemap::Span {
119 self.tr_span(span)
120 }
121 }
122
123 /// Decodes an item from its AST in the cdata's metadata and adds it to the
124 /// ast-map.
125 pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
126 tcx: &TyCtxt<'tcx>,
127 parent_def_path: ast_map::DefPath,
128 parent_did: DefId,
129 ast_doc: rbml::Doc,
130 orig_did: DefId)
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
167 }
168
169 // ______________________________________________________________________
170 // Enumerating the IDs which appear in an AST
171
172 fn reserve_id_range(sess: &Session,
173 from_id_range: IdRange) -> IdRange {
174 // Handle the case of an empty range:
175 if from_id_range.empty() { return from_id_range; }
176 let cnt = from_id_range.max - from_id_range.min;
177 let to_id_min = sess.reserve_node_ids(cnt);
178 let to_id_max = to_id_min + cnt;
179 IdRange { min: to_id_min, max: to_id_max }
180 }
181
182 impl<'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 {
188 // from_id_range should be non-empty
189 assert!(!self.from_id_range.empty());
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))
193 }
194
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.
203 pub fn tr_def_id(&self, did: DefId) -> DefId {
204 decoder::translate_def_id(self.cdata, did)
205 }
206
207 /// Translates a `Span` from an extern crate to the corresponding `Span`
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)
214 }
215 }
216
217 impl tr for DefId {
218 fn tr(&self, dcx: &DecodeContext) -> DefId {
219 dcx.tr_def_id(*self)
220 }
221 }
222
223 impl tr for Option<DefId> {
224 fn tr(&self, dcx: &DecodeContext) -> Option<DefId> {
225 self.map(|d| dcx.tr_def_id(d))
226 }
227 }
228
229 impl tr for codemap::Span {
230 fn tr(&self, dcx: &DecodeContext) -> codemap::Span {
231 dcx.tr_span(*self)
232 }
233 }
234
235 trait def_id_encoder_helpers {
236 fn emit_def_id(&mut self, did: DefId);
237 }
238
239 impl<S:serialize::Encoder> def_id_encoder_helpers for S
240 where <S as serialize::Encoder>::Error: Debug
241 {
242 fn emit_def_id(&mut self, did: DefId) {
243 did.encode(self).unwrap()
244 }
245 }
246
247 trait def_id_decoder_helpers {
248 fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId;
249 fn read_def_id_nodcx(&mut self,
250 cdata: &cstore::crate_metadata) -> DefId;
251 }
252
253 impl<D:serialize::Decoder> def_id_decoder_helpers for D
254 where <D as serialize::Decoder>::Error: Debug
255 {
256 fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId {
257 let did: DefId = Decodable::decode(self).unwrap();
258 did.tr(dcx)
259 }
260
261 fn read_def_id_nodcx(&mut self,
262 cdata: &cstore::crate_metadata)
263 -> DefId {
264 let did: DefId = Decodable::decode(self).unwrap();
265 decoder::translate_def_id(cdata, did)
266 }
267 }
268
269 // ______________________________________________________________________
270 // Encoding and decoding the AST itself
271 //
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
277 fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) {
278 rbml_w.start_tag(c::tag_tree as usize);
279 rbml_w.emit_opaque(|this| item.encode(this));
280 rbml_w.end_tag();
281 }
282
283 struct NestedItemsDropper;
284
285 impl Folder for NestedItemsDropper {
286 fn fold_block(&mut self, blk: P<hir::Block>) -> P<hir::Block> {
287 blk.and_then(|hir::Block {id, stmts, expr, rules, span, ..}| {
288 let stmts_sans_items = stmts.into_iter().filter_map(|stmt| {
289 let use_stmt = match stmt.node {
290 hir::StmtExpr(_, _) | hir::StmtSemi(_, _) => true,
291 hir::StmtDecl(ref decl, _) => {
292 match decl.node {
293 hir::DeclLocal(_) => true,
294 hir::DeclItem(_) => false,
295 }
296 }
297 };
298 if use_stmt {
299 Some(stmt)
300 } else {
301 None
302 }
303 }).collect();
304 let blk_sans_items = P(hir::Block {
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 }
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.
326 fn simplify_ast(ii: InlinedItemRef) -> InlinedItem {
327 let mut fld = NestedItemsDropper;
328
329 match ii {
330 // HACK we're not dropping items.
331 InlinedItemRef::Item(i) => {
332 InlinedItem::Item(P(fold::noop_fold_item(i.clone(), &mut fld)))
333 }
334 InlinedItemRef::TraitItem(d, ti) => {
335 InlinedItem::TraitItem(d, P(fold::noop_fold_trait_item(ti.clone(), &mut fld)))
336 }
337 InlinedItemRef::ImplItem(d, ii) => {
338 InlinedItem::ImplItem(d, P(fold::noop_fold_impl_item(ii.clone(), &mut fld)))
339 }
340 InlinedItemRef::Foreign(i) => {
341 InlinedItem::Foreign(P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
342 }
343 }
344 }
345
346 fn decode_ast(item_doc: rbml::Doc) -> InlinedItem {
347 let chi_doc = item_doc.get(c::tag_tree as usize);
348 let mut rbml_r = reader::Decoder::new(chi_doc);
349 rbml_r.read_opaque(|decoder, _| Decodable::decode(decoder)).unwrap()
350 }
351
352 // ______________________________________________________________________
353 // Encoding and decoding of ast::def
354
355 fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> Def {
356 let def: Def = Decodable::decode(dsr).unwrap();
357 def.tr(dcx)
358 }
359
360 impl tr for Def {
361 fn tr(&self, dcx: &DecodeContext) -> Def {
362 match *self {
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)),
366 impl_ids.map(|(nid1, nid2)| {
367 (dcx.tr_id(nid1),
368 dcx.tr_id(nid2))
369 })) }
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) => {
376 let nid = dcx.tr_id(nid);
377 let did = dcx.tcx.map.local_def_id(nid);
378 Def::Local(did, nid)
379 }
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) => {
389 let nid1 = dcx.tr_id(nid1);
390 let nid2 = dcx.tr_id(nid2);
391 let did1 = dcx.tcx.map.local_def_id(nid1);
392 Def::Upvar(did1, nid1, index, nid2)
393 }
394 Def::Struct(did) => Def::Struct(did.tr(dcx)),
395 Def::Label(nid) => Def::Label(dcx.tr_id(nid)),
396 Def::Err => Def::Err,
397 }
398 }
399 }
400
401 // ______________________________________________________________________
402 // Encoding and decoding of freevar information
403
404 fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &hir::Freevar) {
405 (*fv).encode(rbml_w).unwrap();
406 }
407
408 trait rbml_decoder_helper {
409 fn read_freevar_entry(&mut self, dcx: &DecodeContext)
410 -> hir::Freevar;
411 fn read_capture_mode(&mut self) -> hir::CaptureClause;
412 }
413
414 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
415 fn read_freevar_entry(&mut self, dcx: &DecodeContext)
416 -> hir::Freevar {
417 let fv: hir::Freevar = Decodable::decode(self).unwrap();
418 fv.tr(dcx)
419 }
420
421 fn read_capture_mode(&mut self) -> hir::CaptureClause {
422 let cm: hir::CaptureClause = Decodable::decode(self).unwrap();
423 cm
424 }
425 }
426
427 impl tr for hir::Freevar {
428 fn tr(&self, dcx: &DecodeContext) -> hir::Freevar {
429 hir::Freevar {
430 def: self.def.tr(dcx),
431 span: self.span.tr(dcx),
432 }
433 }
434 }
435
436 // ______________________________________________________________________
437 // Encoding and decoding of MethodCallee
438
439 trait read_method_callee_helper<'tcx> {
440 fn read_method_callee<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
441 -> (u32, ty::MethodCallee<'tcx>);
442 }
443
444 fn encode_method_callee<'a, 'tcx>(ecx: &e::EncodeContext<'a, 'tcx>,
445 rbml_w: &mut Encoder,
446 autoderef: u32,
447 method: &ty::MethodCallee<'tcx>) {
448 use serialize::Encoder;
449
450 rbml_w.emit_struct("MethodCallee", 4, |rbml_w| {
451 rbml_w.emit_struct_field("autoderef", 0, |rbml_w| {
452 autoderef.encode(rbml_w)
453 });
454 rbml_w.emit_struct_field("def_id", 1, |rbml_w| {
455 Ok(rbml_w.emit_def_id(method.def_id))
456 });
457 rbml_w.emit_struct_field("ty", 2, |rbml_w| {
458 Ok(rbml_w.emit_ty(ecx, method.ty))
459 });
460 rbml_w.emit_struct_field("substs", 3, |rbml_w| {
461 Ok(rbml_w.emit_substs(ecx, &method.substs))
462 })
463 }).unwrap();
464 }
465
466 impl<'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>)
468 -> (u32, ty::MethodCallee<'tcx>) {
469
470 self.read_struct("MethodCallee", 4, |this| {
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))
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| {
481 Ok(dcx.tcx.mk_substs(this.read_substs(dcx)))
482 }).unwrap()
483 }))
484 }).unwrap()
485 }
486 }
487
488 pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
489 kind.encode(ebml_w).unwrap();
490 }
491
492 // ______________________________________________________________________
493 // Encoding and decoding the side tables
494
495 trait rbml_writer_helpers<'tcx> {
496 fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
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>]);
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>);
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);
508 fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture);
509 fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
510 adj: &adjustment::AutoAdjustment<'tcx>);
511 fn emit_autoref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
512 autoref: &adjustment::AutoRef<'tcx>);
513 fn emit_auto_deref_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
514 auto_deref_ref: &adjustment::AutoDerefRef<'tcx>);
515 }
516
517 impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
518 fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) {
519 self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor,
520 &ecx.ty_str_ctxt(),
521 r)));
522 }
523
524 fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
525 self.emit_opaque(|this| Ok(tyencode::enc_ty(&mut this.cursor,
526 &ecx.ty_str_ctxt(),
527 ty)));
528 }
529
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)));
532 }
533
534 fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
535 trait_ref: &ty::TraitRef<'tcx>) {
536 self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor,
537 &ecx.ty_str_ctxt(),
538 *trait_ref)));
539 }
540
541 fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
542 predicate: &ty::Predicate<'tcx>) {
543 self.emit_opaque(|this| {
544 Ok(tyencode::enc_predicate(&mut this.cursor,
545 &ecx.ty_str_ctxt(),
546 predicate))
547 });
548 }
549
550 fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
551 bounds: &ty::ExistentialBounds<'tcx>) {
552 self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor,
553 &ecx.ty_str_ctxt(),
554 bounds)));
555 }
556
557 fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
558 self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor,
559 &ecx.ty_str_ctxt(),
560 bounds)));
561 }
562
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
583 fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
584 substs: &subst::Substs<'tcx>) {
585 self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor,
586 &ecx.ty_str_ctxt(),
587 substs)));
588 }
589
590 fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
591 adj: &adjustment::AutoAdjustment<'tcx>) {
592 use serialize::Encoder;
593
594 self.emit_enum("AutoAdjustment", |this| {
595 match *adj {
596 adjustment::AdjustReifyFnPointer => {
597 this.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_| Ok(()))
598 }
599
600 adjustment::AdjustUnsafeFnPointer => {
601 this.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_| {
602 Ok(())
603 })
604 }
605
606 adjustment::AdjustMutToConstPointer => {
607 this.emit_enum_variant("AdjustMutToConstPointer", 3, 0, |_| {
608 Ok(())
609 })
610 }
611
612 adjustment::AdjustDerefRef(ref auto_deref_ref) => {
613 this.emit_enum_variant("AdjustDerefRef", 4, 2, |this| {
614 this.emit_enum_variant_arg(0,
615 |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
616 })
617 }
618 }
619 });
620 }
621
622 fn emit_autoref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
623 autoref: &adjustment::AutoRef<'tcx>) {
624 use serialize::Encoder;
625
626 self.emit_enum("AutoRef", |this| {
627 match autoref {
628 &adjustment::AutoPtr(r, m) => {
629 this.emit_enum_variant("AutoPtr", 0, 2, |this| {
630 this.emit_enum_variant_arg(0,
631 |this| Ok(this.emit_region(ecx, *r)));
632 this.emit_enum_variant_arg(1, |this| m.encode(this))
633 })
634 }
635 &adjustment::AutoUnsafe(m) => {
636 this.emit_enum_variant("AutoUnsafe", 1, 1, |this| {
637 this.emit_enum_variant_arg(0, |this| m.encode(this))
638 })
639 }
640 }
641 });
642 }
643
644 fn emit_auto_deref_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
645 auto_deref_ref: &adjustment::AutoDerefRef<'tcx>) {
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));
650
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(),
655 Some(ref a) => this.emit_option_some(|this| Ok(this.emit_autoref(ecx, a))),
656 }
657 })
658 });
659
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 })
670 });
671 }
672 }
673
674 trait write_tag_and_id {
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);
677 }
678
679 impl<'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 {
685 self.start_tag(tag_id as usize);
686 f(self);
687 self.end_tag();
688 }
689
690 fn id(&mut self, id: ast::NodeId) {
691 id.encode(self).unwrap();
692 }
693 }
694
695 struct SideTableEncodingIdVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
696 ecx: &'a e::EncodeContext<'c, 'tcx>,
697 rbml_w: &'a mut Encoder<'b>,
698 }
699
700 impl<'a, 'b, 'c, 'tcx> IdVisitingOperation for
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)
704 }
705 }
706
707 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
708 rbml_w: &mut Encoder,
709 ii: &InlinedItem) {
710 rbml_w.start_tag(c::tag_table as usize);
711 ii.visit_ids(&mut SideTableEncodingIdVisitor {
712 ecx: ecx,
713 rbml_w: rbml_w
714 });
715 rbml_w.end_tag();
716 }
717
718 fn encode_side_tables_for_id(ecx: &e::EncodeContext,
719 rbml_w: &mut Encoder,
720 id: ast::NodeId) {
721 let tcx = ecx.tcx;
722
723 debug!("Encoding side tables for id {}", id);
724
725 if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
726 rbml_w.tag(c::tag_table_def, |rbml_w| {
727 rbml_w.id(id);
728 def.encode(rbml_w).unwrap();
729 })
730 }
731
732 if let Some(ty) = tcx.node_types().get(&id) {
733 rbml_w.tag(c::tag_table_node_type, |rbml_w| {
734 rbml_w.id(id);
735 rbml_w.emit_ty(ecx, *ty);
736 })
737 }
738
739 if let Some(item_substs) = tcx.tables.borrow().item_substs.get(&id) {
740 rbml_w.tag(c::tag_table_item_subst, |rbml_w| {
741 rbml_w.id(id);
742 rbml_w.emit_substs(ecx, &item_substs.substs);
743 })
744 }
745
746 if let Some(fv) = tcx.freevars.borrow().get(&id) {
747 rbml_w.tag(c::tag_table_freevars, |rbml_w| {
748 rbml_w.id(id);
749 rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| {
750 Ok(encode_freevar_entry(rbml_w, fv_entry))
751 });
752 });
753
754 for freevar in fv {
755 rbml_w.tag(c::tag_table_upvar_capture_map, |rbml_w| {
756 rbml_w.id(id);
757
758 let var_id = freevar.def.var_id();
759 let upvar_id = ty::UpvarId {
760 var_id: var_id,
761 closure_expr_id: id
762 };
763 let upvar_capture = tcx.tables
764 .borrow()
765 .upvar_capture_map
766 .get(&upvar_id)
767 .unwrap()
768 .clone();
769 var_id.encode(rbml_w);
770 rbml_w.emit_upvar_capture(ecx, &upvar_capture);
771 })
772 }
773 }
774
775 let method_call = ty::MethodCall::expr(id);
776 if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
777 rbml_w.tag(c::tag_table_method_map, |rbml_w| {
778 rbml_w.id(id);
779 encode_method_callee(ecx, rbml_w, method_call.autoderef, method)
780 })
781 }
782
783 if let Some(adjustment) = tcx.tables.borrow().adjustments.get(&id) {
784 match *adjustment {
785 adjustment::AdjustDerefRef(ref adj) => {
786 for autoderef in 0..adj.autoderefs {
787 let method_call = ty::MethodCall::autoderef(id, autoderef as u32);
788 if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
789 rbml_w.tag(c::tag_table_method_map, |rbml_w| {
790 rbml_w.id(id);
791 encode_method_callee(ecx, rbml_w,
792 method_call.autoderef, method)
793 })
794 }
795 }
796 }
797 _ => {}
798 }
799
800 rbml_w.tag(c::tag_table_adjustments, |rbml_w| {
801 rbml_w.id(id);
802 rbml_w.emit_auto_adjustment(ecx, adjustment);
803 })
804 }
805
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) {
814 rbml_w.tag(c::tag_table_const_qualif, |rbml_w| {
815 rbml_w.id(id);
816 qualif.encode(rbml_w).unwrap()
817 })
818 }
819 }
820
821 trait doc_decoder_helpers: Sized {
822 fn as_int(&self) -> isize;
823 fn opt_child(&self, tag: c::astencode_tag) -> Option<Self>;
824 }
825
826 impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
827 fn as_int(&self) -> isize { reader::doc_as_u64(*self) as isize }
828 fn opt_child(&self, tag: c::astencode_tag) -> Option<rbml::Doc<'a>> {
829 reader::maybe_get_doc(*self, tag as usize)
830 }
831 }
832
833 trait rbml_decoder_decoder_helpers<'tcx> {
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;
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>)
842 -> ty::TraitRef<'tcx>;
843 fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
844 -> ty::PolyTraitRef<'tcx>;
845 fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
846 -> ty::Predicate<'tcx>;
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>;
851 fn read_upvar_capture(&mut self, dcx: &DecodeContext)
852 -> ty::UpvarCapture;
853 fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
854 -> adjustment::AutoAdjustment<'tcx>;
855 fn read_cast_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
856 -> cast::CastKind;
857 fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
858 -> adjustment::AutoDerefRef<'tcx>;
859 fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
860 -> adjustment::AutoRef<'tcx>;
861
862 // Versions of the type reading functions that don't need the full
863 // DecodeContext.
864 fn read_ty_nodcx(&mut self,
865 tcx: &TyCtxt<'tcx>, cdata: &cstore::crate_metadata) -> Ty<'tcx>;
866 fn read_tys_nodcx(&mut self,
867 tcx: &TyCtxt<'tcx>,
868 cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
869 fn read_substs_nodcx(&mut self, tcx: &TyCtxt<'tcx>,
870 cdata: &cstore::crate_metadata)
871 -> subst::Substs<'tcx>;
872 }
873
874 impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
875 fn read_ty_nodcx(&mut self,
876 tcx: &TyCtxt<'tcx>,
877 cdata: &cstore::crate_metadata)
878 -> Ty<'tcx> {
879 self.read_opaque(|_, doc| {
880 Ok(
881 tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
882 &mut |id| decoder::translate_def_id(cdata, id))
883 .parse_ty())
884 }).unwrap()
885 }
886
887 fn read_tys_nodcx(&mut self,
888 tcx: &TyCtxt<'tcx>,
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,
897 tcx: &TyCtxt<'tcx>,
898 cdata: &cstore::crate_metadata)
899 -> subst::Substs<'tcx>
900 {
901 self.read_opaque(|_, doc| {
902 Ok(
903 tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
904 &mut |id| decoder::translate_def_id(cdata, id))
905 .parse_substs())
906 }).unwrap()
907 }
908
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 {
912 return self.read_opaque(|_, doc| {
913 debug!("read_ty_encoded({})", type_string(doc));
914 Ok(op(
915 &mut tydecode::TyDecoder::with_doc(
916 dcx.tcx, dcx.cdata.cnum, doc,
917 &mut |d| convert_def_id(dcx, d))))
918 }).unwrap();
919
920 fn type_string(doc: rbml::Doc) -> String {
921 let mut str = String::new();
922 for i in doc.start..doc.end {
923 str.push(doc.data[i] as char);
924 }
925 str
926 }
927 }
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 }
938
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()
942 }
943
944 fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
945 -> ty::TraitRef<'tcx> {
946 self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref())
947 }
948
949 fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
950 -> ty::PolyTraitRef<'tcx> {
951 ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref()))
952 }
953
954 fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
955 -> ty::Predicate<'tcx>
956 {
957 self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate())
958 }
959
960 fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
961 -> ty::ExistentialBounds<'tcx>
962 {
963 self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds())
964 }
965
966 fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
967 -> subst::Substs<'tcx> {
968 self.read_opaque(|_, doc| {
969 Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc,
970 &mut |d| convert_def_id(dcx, d))
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 }),
986 _ => bug!("bad enum variant for ty::UpvarCapture")
987 })
988 })
989 }).unwrap()
990 }
991 fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
992 -> adjustment::AutoAdjustment<'tcx> {
993 self.read_enum("AutoAdjustment", |this| {
994 let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer",
995 "AdjustMutToConstPointer", "AdjustDerefRef"];
996 this.read_enum_variant(&variants, |this, i| {
997 Ok(match i {
998 1 => adjustment::AdjustReifyFnPointer,
999 2 => adjustment::AdjustUnsafeFnPointer,
1000 3 => adjustment::AdjustMutToConstPointer,
1001 4 => {
1002 let auto_deref_ref: adjustment::AutoDerefRef =
1003 this.read_enum_variant_arg(0,
1004 |this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
1005
1006 adjustment::AdjustDerefRef(auto_deref_ref)
1007 }
1008 _ => bug!("bad enum variant for adjustment::AutoAdjustment")
1009 })
1010 })
1011 }).unwrap()
1012 }
1013
1014 fn read_auto_deref_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1015 -> adjustment::AutoDerefRef<'tcx> {
1016 self.read_struct("AutoDerefRef", 2, |this| {
1017 Ok(adjustment::AutoDerefRef {
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)
1027 }
1028 })
1029 }).unwrap(),
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(),
1039 })
1040 }).unwrap()
1041 }
1042
1043 fn read_autoref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1044 -> adjustment::AutoRef<'tcx> {
1045 self.read_enum("AutoRef", |this| {
1046 let variants = ["AutoPtr", "AutoUnsafe"];
1047 this.read_enum_variant(&variants, |this, i| {
1048 Ok(match i {
1049 0 => {
1050 let r: ty::Region =
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)
1060 }
1061 1 => {
1062 let m: hir::Mutability =
1063 this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
1064
1065 adjustment::AutoUnsafe(m)
1066 }
1067 _ => bug!("bad enum variant for adjustment::AutoRef")
1068 })
1069 })
1070 }).unwrap()
1071 }
1072
1073 fn read_cast_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
1074 -> cast::CastKind
1075 {
1076 Decodable::decode(self).unwrap()
1077 }
1078 }
1079
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.
1112 fn 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;
1118 }
1119
1120 fn decode_side_tables(dcx: &DecodeContext,
1121 ast_doc: rbml::Doc) {
1122 let tbl_doc = ast_doc.get(c::tag_table as usize);
1123 for (tag, entry_doc) in reader::docs(tbl_doc) {
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);
1127
1128 debug!(">> Side table document with tag 0x{:x} \
1129 found for id {} (orig {})",
1130 tag, id, id0);
1131 let tag = tag as u32;
1132 let decoded_tag: Option<c::astencode_tag> = c::astencode_tag::from_u32(tag);
1133 match decoded_tag {
1134 None => {
1135 bug!("unknown tag found in side tables: {:x}", tag);
1136 }
1137 Some(value) => {
1138 let val_dsr = &mut entry_dsr;
1139
1140 match value {
1141 c::tag_table_def => {
1142 let def = decode_def(dcx, val_dsr);
1143 dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
1144 base_def: def,
1145 depth: 0
1146 });
1147 }
1148 c::tag_table_node_type => {
1149 let ty = val_dsr.read_ty(dcx);
1150 debug!("inserting ty for node {}: {:?}",
1151 id, ty);
1152 dcx.tcx.node_type_insert(id, ty);
1153 }
1154 c::tag_table_item_subst => {
1155 let item_substs = ty::ItemSubsts {
1156 substs: val_dsr.read_substs(dcx)
1157 };
1158 dcx.tcx.tables.borrow_mut().item_substs.insert(
1159 id, item_substs);
1160 }
1161 c::tag_table_freevars => {
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 }
1167 c::tag_table_upvar_capture_map => {
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 };
1173 let ub = val_dsr.read_upvar_capture(dcx);
1174 dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub);
1175 }
1176 c::tag_table_method_map => {
1177 let (autoderef, method) = val_dsr.read_method_callee(dcx);
1178 let method_call = ty::MethodCall {
1179 expr_id: id,
1180 autoderef: autoderef
1181 };
1182 dcx.tcx.tables.borrow_mut().method_map.insert(method_call, method);
1183 }
1184 c::tag_table_adjustments => {
1185 let adj =
1186 val_dsr.read_auto_adjustment(dcx);
1187 dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj);
1188 }
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 }
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);
1197 }
1198 _ => {
1199 bug!("unknown tag found in side tables: {:x}", tag);
1200 }
1201 }
1202 }
1203 }
1204
1205 debug!(">< Side table doc loaded");
1206 }
1207 }
1208
1209 // copy the tcache entries from the original item to the new
1210 // inlined item
1211 fn 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
1256 fn inlined_item_id_range(v: &InlinedItem) -> IdRange {
1257 let mut visitor = IdRangeComputingVisitor::new();
1258 v.visit_ids(&mut visitor);
1259 visitor.result()
1260 }
1261
1262 // ______________________________________________________________________
1263 // Testing of astencode_gen
1264
1265 #[cfg(test)]
1266 fn encode_item_ast(rbml_w: &mut Encoder, item: &hir::Item) {
1267 rbml_w.start_tag(c::tag_tree as usize);
1268 (*item).encode(rbml_w);
1269 rbml_w.end_tag();
1270 }
1271
1272 #[cfg(test)]
1273 fn decode_item_ast(item_doc: rbml::Doc) -> hir::Item {
1274 let chi_doc = item_doc.get(c::tag_tree as usize);
1275 let mut d = reader::Decoder::new(chi_doc);
1276 Decodable::decode(&mut d).unwrap()
1277 }
1278
1279 #[cfg(test)]
1280 trait FakeExtCtxt {
1281 fn call_site(&self) -> codemap::Span;
1282 fn cfg(&self) -> ast::CrateConfig;
1283 fn ident_of(&self, st: &str) -> ast::Ident;
1284 fn name_of(&self, st: &str) -> ast::Name;
1285 fn parse_sess(&self) -> &parse::ParseSess;
1286 }
1287
1288 #[cfg(test)]
1289 impl FakeExtCtxt for parse::ParseSess {
1290 fn call_site(&self) -> codemap::Span {
1291 codemap::Span {
1292 lo: codemap::BytePos(0),
1293 hi: codemap::BytePos(0),
1294 expn_id: codemap::NO_EXPANSION,
1295 }
1296 }
1297 fn cfg(&self) -> ast::CrateConfig { Vec::new() }
1298 fn ident_of(&self, st: &str) -> ast::Ident {
1299 parse::token::str_to_ident(st)
1300 }
1301 fn name_of(&self, st: &str) -> ast::Name {
1302 parse::token::intern(st)
1303 }
1304 fn parse_sess(&self) -> &parse::ParseSess { self }
1305 }
1306
1307 #[cfg(test)]
1308 struct 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.
1313 impl 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
1323 #[cfg(test)]
1324 fn mk_ctxt() -> parse::ParseSess {
1325 parse::ParseSess::new()
1326 }
1327
1328 #[cfg(test)]
1329 fn roundtrip(in_item: hir::Item) {
1330 let mut wr = Cursor::new(Vec::new());
1331 encode_item_ast(&mut Encoder::new(&mut wr), &in_item);
1332 let rbml_doc = rbml::Doc::new(wr.get_ref());
1333 let out_item = decode_item_ast(rbml_doc);
1334
1335 assert!(in_item == out_item);
1336 }
1337
1338 #[test]
1339 fn test_basic() {
1340 let cx = mk_ctxt();
1341 let fnia = FakeNodeIdAssigner;
1342 let lcx = LoweringContext::new(&fnia, None);
1343 roundtrip(lower_item(&lcx, &quote_item!(&cx,
1344 fn foo() {}
1345 ).unwrap()));
1346 }
1347
1348 #[test]
1349 fn test_smalltalk() {
1350 let cx = mk_ctxt();
1351 let fnia = FakeNodeIdAssigner;
1352 let lcx = LoweringContext::new(&fnia, None);
1353 roundtrip(lower_item(&lcx, &quote_item!(&cx,
1354 fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
1355 ).unwrap()));
1356 }
1357
1358 #[test]
1359 fn test_more() {
1360 let cx = mk_ctxt();
1361 let fnia = FakeNodeIdAssigner;
1362 let lcx = LoweringContext::new(&fnia, None);
1363 roundtrip(lower_item(&lcx, &quote_item!(&cx,
1364 fn foo(x: usize, y: usize) -> usize {
1365 let z = x + y;
1366 return z;
1367 }
1368 ).unwrap()));
1369 }
1370
1371 #[test]
1372 fn test_simplification() {
1373 let cx = mk_ctxt();
1374 let item = quote_item!(&cx,
1375 fn new_int_alist<B>() -> alist<isize, B> {
1376 fn eq_int(a: isize, b: isize) -> bool { a == b }
1377 return alist {eq_fn: eq_int, data: Vec::new()};
1378 }
1379 ).unwrap();
1380 let fnia = FakeNodeIdAssigner;
1381 let lcx = LoweringContext::new(&fnia, None);
1382 let hir_item = lower_item(&lcx, &item);
1383 let item_in = InlinedItemRef::Item(&hir_item);
1384 let item_out = simplify_ast(item_in);
1385 let item_exp = InlinedItem::Item(P(lower_item(&lcx, &quote_item!(&cx,
1386 fn new_int_alist<B>() -> alist<isize, B> {
1387 return alist {eq_fn: eq_int, data: Vec::new()};
1388 }
1389 ).unwrap())));
1390 match (item_out, item_exp) {
1391 (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
1392 assert!(pprust::item_to_string(&item_out) ==
1393 pprust::item_to_string(&item_exp));
1394 }
1395 _ => bug!()
1396 }
1397 }