]>
Commit | Line | Data |
---|---|---|
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 | 15 | use rustc::hir::map as ast_map; |
92a42be0 SL |
16 | use rustc::session::Session; |
17 | ||
54a0048b SL |
18 | use rustc::hir; |
19 | use rustc::hir::fold; | |
20 | use rustc::hir::fold::Folder; | |
21 | use rustc::hir::intravisit::{IdRange, IdRangeComputingVisitor, IdVisitingOperation}; | |
e9174d1e | 22 | |
92a42be0 SL |
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}; | |
54a0048b SL |
31 | use rustc::ty::adjustment; |
32 | use rustc::ty::cast; | |
7453a54e | 33 | use middle::const_qualif::ConstQualif; |
54a0048b SL |
34 | use rustc::hir::def::{self, Def}; |
35 | use rustc::hir::def_id::DefId; | |
e9174d1e | 36 | use middle::region; |
54a0048b SL |
37 | use rustc::ty::subst; |
38 | use rustc::ty::{self, Ty, TyCtxt}; | |
1a4d82fc | 39 | |
54a0048b | 40 | use syntax::{ast, codemap}; |
b039eaaf | 41 | use syntax::ast::NodeIdAssigner; |
1a4d82fc | 42 | use syntax::ptr::P; |
970d7e83 | 43 | |
c34b1796 AL |
44 | use std::cell::Cell; |
45 | use std::io::SeekFrom; | |
46 | use std::io::prelude::*; | |
c34b1796 | 47 | use std::fmt::Debug; |
1a4d82fc | 48 | |
c34b1796 AL |
49 | use rbml::reader; |
50 | use rbml::writer::Encoder; | |
1a4d82fc JJ |
51 | use rbml; |
52 | use serialize; | |
53 | use serialize::{Decodable, Decoder, DecoderHelpers, Encodable}; | |
c34b1796 | 54 | use 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 | 62 | struct 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 | ||
71 | trait tr { | |
1a4d82fc | 72 | fn tr(&self, dcx: &DecodeContext) -> Self; |
223e47cc LB |
73 | } |
74 | ||
223e47cc LB |
75 | // ______________________________________________________________________ |
76 | // Top-level methods. | |
77 | ||
970d7e83 | 78 | pub 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 | ||
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 | } | |
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 | 125 | pub 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 | 172 | fn 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 |
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 { | |
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 |
217 | impl tr for DefId { |
218 | fn tr(&self, dcx: &DecodeContext) -> DefId { | |
1a4d82fc | 219 | dcx.tr_def_id(*self) |
223e47cc LB |
220 | } |
221 | } | |
222 | ||
e9174d1e SL |
223 | impl 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 |
229 | impl tr for codemap::Span { |
230 | fn tr(&self, dcx: &DecodeContext) -> codemap::Span { | |
1a4d82fc | 231 | dcx.tr_span(*self) |
223e47cc LB |
232 | } |
233 | } | |
234 | ||
235 | trait def_id_encoder_helpers { | |
e9174d1e | 236 | fn emit_def_id(&mut self, did: DefId); |
223e47cc LB |
237 | } |
238 | ||
c34b1796 | 239 | impl<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 | ||
247 | trait 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 | 253 | impl<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 | 277 | fn 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 | ||
283 | struct NestedItemsDropper; | |
284 | ||
285 | impl 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 | 326 | fn 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 |
346 | fn 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 |
355 | fn 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 |
360 | impl 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 | 404 | fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &hir::Freevar) { |
1a4d82fc | 405 | (*fv).encode(rbml_w).unwrap(); |
223e47cc LB |
406 | } |
407 | ||
1a4d82fc JJ |
408 | trait 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 |
414 | impl<'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 |
427 | impl 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 |
439 | trait 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 |
444 | fn 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 |
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>) | |
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 | 488 | pub 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 | 495 | trait 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 | ||
517 | impl<'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 | ||
674 | trait 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 |
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 | { | |
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 | ||
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 | ||
54a0048b | 700 | impl<'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 | 707 | fn 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 | ||
718 | fn 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 | 821 | trait 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 | 826 | impl<'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 | 833 | trait 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 | ||
874 | impl<'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. | |
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; | |
223e47cc LB |
1118 | } |
1119 | ||
1a4d82fc JJ |
1120 | fn 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 | |
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 | ||
54a0048b SL |
1256 | fn 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 | 1266 | fn 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 |
1273 | fn 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 |
1280 | trait 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 |
1289 | impl 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)] |
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 | ||
223e47cc | 1323 | #[cfg(test)] |
1a4d82fc | 1324 | fn mk_ctxt() -> parse::ParseSess { |
62682a34 | 1325 | parse::ParseSess::new() |
223e47cc LB |
1326 | } |
1327 | ||
1328 | #[cfg(test)] | |
92a42be0 | 1329 | fn 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] | |
1339 | fn 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, "e_item!(&cx, | |
223e47cc | 1344 | fn foo() {} |
e9174d1e | 1345 | ).unwrap())); |
223e47cc | 1346 | } |
d9579d0f | 1347 | |
223e47cc LB |
1348 | #[test] |
1349 | fn 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, "e_item!(&cx, | |
c34b1796 | 1354 | fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed. |
e9174d1e | 1355 | ).unwrap())); |
223e47cc LB |
1356 | } |
1357 | ||
1358 | #[test] | |
1359 | fn 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, "e_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] | |
1372 | fn 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, "e_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 | } |