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.
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.
11 #![allow(non_camel_case_types)]
12 // FIXME: remove this after snapshot, and Results are handled
13 #![allow(unused_must_use)]
15 use rustc
::hir
::map
as ast_map
;
16 use rustc
::session
::Session
;
20 use rustc
::hir
::fold
::Folder
;
21 use rustc
::hir
::intravisit
::{IdRange, IdRangeComputingVisitor, IdVisitingOperation}
;
30 use middle
::cstore
::{InlinedItem, InlinedItemRef}
;
31 use rustc
::ty
::adjustment
;
33 use middle
::const_qualif
::ConstQualif
;
34 use rustc
::hir
::def
::{self, Def}
;
35 use rustc
::hir
::def_id
::DefId
;
38 use rustc
::ty
::{self, Ty, TyCtxt}
;
40 use syntax
::{ast, codemap}
;
41 use syntax
::ast
::NodeIdAssigner
;
45 use std
::io
::SeekFrom
;
46 use std
::io
::prelude
::*;
50 use rbml
::writer
::Encoder
;
53 use serialize
::{Decodable, Decoder, DecoderHelpers, Encodable}
;
54 use serialize
::EncoderHelpers
;
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};
62 struct DecodeContext
<'a
, 'b
, 'tcx
: 'a
> {
63 tcx
: &'a TyCtxt
<'tcx
>,
64 cdata
: &'b cstore
::crate_metadata
,
65 from_id_range
: IdRange
,
67 // Cache the last used filemap for translating spans as an optimization.
68 last_filemap_index
: Cell
<usize>,
72 fn tr(&self, dcx
: &DecodeContext
) -> Self;
75 // ______________________________________________________________________
78 pub fn encode_inlined_item(ecx
: &e
::EncodeContext
,
82 InlinedItemRef
::Item(i
) => i
.id
,
83 InlinedItemRef
::Foreign(i
) => i
.id
,
84 InlinedItemRef
::TraitItem(_
, ti
) => ti
.id
,
85 InlinedItemRef
::ImplItem(_
, ii
) => ii
.id
,
87 debug
!("> Encoding inlined item: {} ({:?})",
88 ecx
.tcx
.node_path_str(id
),
89 rbml_w
.writer
.seek(SeekFrom
::Current(0)));
91 // Folding could be avoided with a smarter encoder.
92 let ii
= simplify_ast(ii
);
93 let id_range
= inlined_item_id_range(&ii
);
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
);
101 debug
!("< Encoded inlined fn: {} ({:?})",
102 ecx
.tcx
.node_path_str(id
),
103 rbml_w
.writer
.seek(SeekFrom
::Current(0)));
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()
115 fn new_def_id(&self, def_id
: DefId
) -> DefId
{
116 self.tr_def_id(def_id
)
118 fn new_span(&self, span
: codemap
::Span
) -> codemap
::Span
{
123 /// Decodes an item from its AST in the cdata's metadata and adds it to the
125 pub fn decode_inlined_item
<'tcx
>(cdata
: &cstore
::crate_metadata
,
127 parent_def_path
: ast_map
::DefPath
,
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
{
139 from_id_range
: from_id_range
,
140 to_id_range
: to_id_range
,
141 last_filemap_index
: Cell
::new(0)
143 let ii
= ast_map
::map_decoded_item(&dcx
.tcx
.map
,
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
154 debug
!("Fn named: {}", name
);
155 debug
!("< Decoded inlined fn: {}::{}",
156 tcx
.item_path_str(parent_did
),
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
));
169 // ______________________________________________________________________
170 // Enumerating the IDs which appear in an AST
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 }
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
))
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
)
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
,
218 fn tr(&self, dcx
: &DecodeContext
) -> DefId
{
223 impl tr
for Option
<DefId
> {
224 fn tr(&self, dcx
: &DecodeContext
) -> Option
<DefId
> {
225 self.map(|d
| dcx
.tr_def_id(d
))
229 impl tr
for codemap
::Span
{
230 fn tr(&self, dcx
: &DecodeContext
) -> codemap
::Span
{
235 trait def_id_encoder_helpers
{
236 fn emit_def_id(&mut self, did
: DefId
);
239 impl<S
:serialize
::Encoder
> def_id_encoder_helpers
for S
240 where <S
as serialize
::Encoder
>::Error
: Debug
242 fn emit_def_id(&mut self, did
: DefId
) {
243 did
.encode(self).unwrap()
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
;
253 impl<D
:serialize
::Decoder
> def_id_decoder_helpers
for D
254 where <D
as serialize
::Decoder
>::Error
: Debug
256 fn read_def_id(&mut self, dcx
: &DecodeContext
) -> DefId
{
257 let did
: DefId
= Decodable
::decode(self).unwrap();
261 fn read_def_id_nodcx(&mut self,
262 cdata
: &cstore
::crate_metadata
)
264 let did
: DefId
= Decodable
::decode(self).unwrap();
265 decoder
::translate_def_id(cdata
, did
)
269 // ______________________________________________________________________
270 // Encoding and decoding the AST itself
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.
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
));
283 struct NestedItemsDropper
;
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
, _
) => {
293 hir
::DeclLocal(_
) => true,
294 hir
::DeclItem(_
) => false,
304 let blk_sans_items
= P(hir
::Block
{
305 stmts
: stmts_sans_items
,
311 fold
::noop_fold_block(blk_sans_items
, self)
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).
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
326 fn simplify_ast(ii
: InlinedItemRef
) -> InlinedItem
{
327 let mut fld
= NestedItemsDropper
;
330 // HACK we're not dropping items.
331 InlinedItemRef
::Item(i
) => {
332 InlinedItem
::Item(P(fold
::noop_fold_item(i
.clone(), &mut fld
)))
334 InlinedItemRef
::TraitItem(d
, ti
) => {
335 InlinedItem
::TraitItem(d
, P(fold
::noop_fold_trait_item(ti
.clone(), &mut fld
)))
337 InlinedItemRef
::ImplItem(d
, ii
) => {
338 InlinedItem
::ImplItem(d
, P(fold
::noop_fold_impl_item(ii
.clone(), &mut fld
)))
340 InlinedItemRef
::Foreign(i
) => {
341 InlinedItem
::Foreign(P(fold
::noop_fold_foreign_item(i
.clone(), &mut fld
)))
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()
352 // ______________________________________________________________________
353 // Encoding and decoding of ast::def
355 fn decode_def(dcx
: &DecodeContext
, dsr
: &mut reader
::Decoder
) -> Def
{
356 let def
: Def
= Decodable
::decode(dsr
).unwrap();
361 fn tr(&self, dcx
: &DecodeContext
) -> Def
{
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
)| {
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
);
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
)
394 Def
::Struct(did
) => Def
::Struct(did
.tr(dcx
)),
395 Def
::Label(nid
) => Def
::Label(dcx
.tr_id(nid
)),
396 Def
::Err
=> Def
::Err
,
401 // ______________________________________________________________________
402 // Encoding and decoding of freevar information
404 fn encode_freevar_entry(rbml_w
: &mut Encoder
, fv
: &hir
::Freevar
) {
405 (*fv
).encode(rbml_w
).unwrap();
408 trait rbml_decoder_helper
{
409 fn read_freevar_entry(&mut self, dcx
: &DecodeContext
)
411 fn read_capture_mode(&mut self) -> hir
::CaptureClause
;
414 impl<'a
> rbml_decoder_helper
for reader
::Decoder
<'a
> {
415 fn read_freevar_entry(&mut self, dcx
: &DecodeContext
)
417 let fv
: hir
::Freevar
= Decodable
::decode(self).unwrap();
421 fn read_capture_mode(&mut self) -> hir
::CaptureClause
{
422 let cm
: hir
::CaptureClause
= Decodable
::decode(self).unwrap();
427 impl tr
for hir
::Freevar
{
428 fn tr(&self, dcx
: &DecodeContext
) -> hir
::Freevar
{
430 def
: self.def
.tr(dcx
),
431 span
: self.span
.tr(dcx
),
436 // ______________________________________________________________________
437 // Encoding and decoding of MethodCallee
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
>);
444 fn encode_method_callee
<'a
, 'tcx
>(ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
445 rbml_w
: &mut Encoder
,
447 method
: &ty
::MethodCallee
<'tcx
>) {
448 use serialize
::Encoder
;
450 rbml_w
.emit_struct("MethodCallee", 4, |rbml_w
| {
451 rbml_w
.emit_struct_field("autoderef", 0, |rbml_w
| {
452 autoderef
.encode(rbml_w
)
454 rbml_w
.emit_struct_field("def_id", 1, |rbml_w
| {
455 Ok(rbml_w
.emit_def_id(method
.def_id
))
457 rbml_w
.emit_struct_field("ty", 2, |rbml_w
| {
458 Ok(rbml_w
.emit_ty(ecx
, method
.ty
))
460 rbml_w
.emit_struct_field("substs", 3, |rbml_w
| {
461 Ok(rbml_w
.emit_substs(ecx
, &method
.substs
))
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
>) {
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
))
477 ty
: this
.read_struct_field("ty", 2, |this
| {
478 Ok(this
.read_ty(dcx
))
480 substs
: this
.read_struct_field("substs", 3, |this
| {
481 Ok(dcx
.tcx
.mk_substs(this
.read_substs(dcx
)))
488 pub fn encode_cast_kind(ebml_w
: &mut Encoder
, kind
: cast
::CastKind
) {
489 kind
.encode(ebml_w
).unwrap();
492 // ______________________________________________________________________
493 // Encoding and decoding the side tables
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
>);
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
,
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
,
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
)));
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
,
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
,
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
,
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
,
563 fn emit_upvar_capture(&mut self, ecx
: &e
::EncodeContext
, capture
: &ty
::UpvarCapture
) {
564 use serialize
::Encoder
;
566 self.emit_enum("UpvarCapture", |this
| {
568 ty
::UpvarCapture
::ByValue
=> {
569 this
.emit_enum_variant("ByValue", 1, 0, |_
| Ok(()))
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
)))
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
,
590 fn emit_auto_adjustment
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
591 adj
: &adjustment
::AutoAdjustment
<'tcx
>) {
592 use serialize
::Encoder
;
594 self.emit_enum("AutoAdjustment", |this
| {
596 adjustment
::AdjustReifyFnPointer
=> {
597 this
.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_
| Ok(()))
600 adjustment
::AdjustUnsafeFnPointer
=> {
601 this
.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_
| {
606 adjustment
::AdjustMutToConstPointer
=> {
607 this
.emit_enum_variant("AdjustMutToConstPointer", 3, 0, |_
| {
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
)))
622 fn emit_autoref
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
623 autoref
: &adjustment
::AutoRef
<'tcx
>) {
624 use serialize
::Encoder
;
626 self.emit_enum("AutoRef", |this
| {
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
))
635 &adjustment
::AutoUnsafe(m
) => {
636 this
.emit_enum_variant("AutoUnsafe", 1, 1, |this
| {
637 this
.emit_enum_variant_arg(0, |this
| m
.encode(this
))
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
;
648 self.emit_struct("AutoDerefRef", 2, |this
| {
649 this
.emit_struct_field("autoderefs", 0, |this
| auto_deref_ref
.autoderefs
.encode(this
));
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
))),
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
))
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
);
679 impl<'a
> write_tag_and_id
for Encoder
<'a
> {
681 tag_id
: c
::astencode_tag
,
683 F
: FnOnce(&mut Encoder
<'a
>),
685 self.start_tag(tag_id
as usize);
690 fn id(&mut self, id
: ast
::NodeId
) {
691 id
.encode(self).unwrap();
695 struct SideTableEncodingIdVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'c
> {
696 ecx
: &'a e
::EncodeContext
<'c
, 'tcx
>,
697 rbml_w
: &'a
mut Encoder
<'b
>,
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
)
707 fn encode_side_tables_for_ii(ecx
: &e
::EncodeContext
,
708 rbml_w
: &mut Encoder
,
710 rbml_w
.start_tag(c
::tag_table
as usize);
711 ii
.visit_ids(&mut SideTableEncodingIdVisitor
{
718 fn encode_side_tables_for_id(ecx
: &e
::EncodeContext
,
719 rbml_w
: &mut Encoder
,
723 debug
!("Encoding side tables for id {}", id
);
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
| {
728 def
.encode(rbml_w
).unwrap();
732 if let Some(ty
) = tcx
.node_types().get(&id
) {
733 rbml_w
.tag(c
::tag_table_node_type
, |rbml_w
| {
735 rbml_w
.emit_ty(ecx
, *ty
);
739 if let Some(item_substs
) = tcx
.tables
.borrow().item_substs
.get(&id
) {
740 rbml_w
.tag(c
::tag_table_item_subst
, |rbml_w
| {
742 rbml_w
.emit_substs(ecx
, &item_substs
.substs
);
746 if let Some(fv
) = tcx
.freevars
.borrow().get(&id
) {
747 rbml_w
.tag(c
::tag_table_freevars
, |rbml_w
| {
749 rbml_w
.emit_from_vec(fv
, |rbml_w
, fv_entry
| {
750 Ok(encode_freevar_entry(rbml_w
, fv_entry
))
755 rbml_w
.tag(c
::tag_table_upvar_capture_map
, |rbml_w
| {
758 let var_id
= freevar
.def
.var_id();
759 let upvar_id
= ty
::UpvarId
{
763 let upvar_capture
= tcx
.tables
769 var_id
.encode(rbml_w
);
770 rbml_w
.emit_upvar_capture(ecx
, &upvar_capture
);
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
| {
779 encode_method_callee(ecx
, rbml_w
, method_call
.autoderef
, method
)
783 if let Some(adjustment
) = tcx
.tables
.borrow().adjustments
.get(&id
) {
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
| {
791 encode_method_callee(ecx
, rbml_w
,
792 method_call
.autoderef
, method
)
800 rbml_w
.tag(c
::tag_table_adjustments
, |rbml_w
| {
802 rbml_w
.emit_auto_adjustment(ecx
, adjustment
);
806 if let Some(cast_kind
) = tcx
.cast_kinds
.borrow().get(&id
) {
807 rbml_w
.tag(c
::tag_table_cast_kinds
, |rbml_w
| {
809 encode_cast_kind(rbml_w
, *cast_kind
)
813 if let Some(qualif
) = tcx
.const_qualif_map
.borrow().get(&id
) {
814 rbml_w
.tag(c
::tag_table_const_qualif
, |rbml_w
| {
816 qualif
.encode(rbml_w
).unwrap()
821 trait doc_decoder_helpers
: Sized
{
822 fn as_int(&self) -> isize;
823 fn opt_child(&self, tag
: c
::astencode_tag
) -> Option
<Self>;
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)
833 trait rbml_decoder_decoder_helpers
<'tcx
> {
834 fn read_ty_encoded
<'a
, 'b
, F
, R
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>,
836 where F
: for<'x
> FnOnce(&mut tydecode
::TyDecoder
<'x
, 'tcx
>) -> R
;
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
)
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
>)
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
>;
862 // Versions of the type reading functions that don't need the full
864 fn read_ty_nodcx(&mut self,
865 tcx
: &TyCtxt
<'tcx
>, cdata
: &cstore
::crate_metadata
) -> Ty
<'tcx
>;
866 fn read_tys_nodcx(&mut self,
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
>;
874 impl<'a
, 'tcx
> rbml_decoder_decoder_helpers
<'tcx
> for reader
::Decoder
<'a
> {
875 fn read_ty_nodcx(&mut self,
877 cdata
: &cstore
::crate_metadata
)
879 self.read_opaque(|_
, doc
| {
881 tydecode
::TyDecoder
::with_doc(tcx
, cdata
.cnum
, doc
,
882 &mut |id
| decoder
::translate_def_id(cdata
, id
))
887 fn read_tys_nodcx(&mut self,
889 cdata
: &cstore
::crate_metadata
) -> Vec
<Ty
<'tcx
>> {
890 self.read_to_vec(|this
| Ok(this
.read_ty_nodcx(tcx
, cdata
)) )
896 fn read_substs_nodcx(&mut self,
898 cdata
: &cstore
::crate_metadata
)
899 -> subst
::Substs
<'tcx
>
901 self.read_opaque(|_
, doc
| {
903 tydecode
::TyDecoder
::with_doc(tcx
, cdata
.cnum
, doc
,
904 &mut |id
| decoder
::translate_def_id(cdata
, id
))
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
912 return self.read_opaque(|_
, doc
| {
913 debug
!("read_ty_encoded({})", type_string(doc
));
915 &mut tydecode
::TyDecoder
::with_doc(
916 dcx
.tcx
, dcx
.cdata
.cnum
, doc
,
917 &mut |d
| convert_def_id(dcx
, d
))))
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);
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());
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());
939 fn read_tys
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
941 self.read_to_vec(|this
| Ok(this
.read_ty(dcx
))).unwrap().into_iter().collect()
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())
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()))
954 fn read_predicate
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
955 -> ty
::Predicate
<'tcx
>
957 self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_predicate())
960 fn read_existential_bounds
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
961 -> ty
::ExistentialBounds
<'tcx
>
963 self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_existential_bounds())
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
))
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
| {
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()
986 _
=> bug
!("bad enum variant for ty::UpvarCapture")
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
| {
998 1 => adjustment
::AdjustReifyFnPointer
,
999 2 => adjustment
::AdjustUnsafeFnPointer
,
1000 3 => adjustment
::AdjustMutToConstPointer
,
1002 let auto_deref_ref
: adjustment
::AutoDerefRef
=
1003 this
.read_enum_variant_arg(0,
1004 |this
| Ok(this
.read_auto_deref_ref(dcx
))).unwrap();
1006 adjustment
::AdjustDerefRef(auto_deref_ref
)
1008 _
=> bug
!("bad enum variant for adjustment::AutoAdjustment")
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
)
1021 autoref
: this
.read_struct_field("autoref", 1, |this
| {
1022 this
.read_option(|this
, b
| {
1024 Ok(Some(this
.read_autoref(dcx
)))
1030 unsize
: this
.read_struct_field("unsize", 2, |this
| {
1031 this
.read_option(|this
, b
| {
1033 Ok(Some(this
.read_ty(dcx
)))
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
| {
1051 this
.read_enum_variant_arg(0, |this
| {
1052 Ok(this
.read_region(dcx
))
1054 let m
: hir
::Mutability
=
1055 this
.read_enum_variant_arg(1, |this
| {
1056 Decodable
::decode(this
)
1059 adjustment
::AutoPtr(dcx
.tcx
.mk_region(r
), m
)
1062 let m
: hir
::Mutability
=
1063 this
.read_enum_variant_arg(0, |this
| Decodable
::decode(this
)).unwrap();
1065 adjustment
::AutoUnsafe(m
)
1067 _
=> bug
!("bad enum variant for adjustment::AutoRef")
1073 fn read_cast_kind
<'b
, 'c
>(&mut self, _dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1076 Decodable
::decode(self).unwrap()
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.
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.
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.
1103 // Scopes will end up as being totally bogus. This can actually
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.
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
,
1115 let r
= dcx
.tr_def_id(did
);
1116 debug
!("convert_def_id(did={:?})={:?}", did
, r
);
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
);
1128 debug
!(">> Side table document with tag 0x{:x} \
1129 found for id {} (orig {})",
1131 let tag
= tag
as u32;
1132 let decoded_tag
: Option
<c
::astencode_tag
> = c
::astencode_tag
::from_u32(tag
);
1135 bug
!("unknown tag found in side tables: {:x}", tag
);
1138 let val_dsr
= &mut entry_dsr
;
1141 c
::tag_table_def
=> {
1142 let def
= decode_def(dcx
, val_dsr
);
1143 dcx
.tcx
.def_map
.borrow_mut().insert(id
, def
::PathResolution
{
1148 c
::tag_table_node_type
=> {
1149 let ty
= val_dsr
.read_ty(dcx
);
1150 debug
!("inserting ty for node {}: {:?}",
1152 dcx
.tcx
.node_type_insert(id
, ty
);
1154 c
::tag_table_item_subst
=> {
1155 let item_substs
= ty
::ItemSubsts
{
1156 substs
: val_dsr
.read_substs(dcx
)
1158 dcx
.tcx
.tables
.borrow_mut().item_substs
.insert(
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
);
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
),
1173 let ub
= val_dsr
.read_upvar_capture(dcx
);
1174 dcx
.tcx
.tables
.borrow_mut().upvar_capture_map
.insert(upvar_id
, ub
);
1176 c
::tag_table_method_map
=> {
1177 let (autoderef
, method
) = val_dsr
.read_method_callee(dcx
);
1178 let method_call
= ty
::MethodCall
{
1180 autoderef
: autoderef
1182 dcx
.tcx
.tables
.borrow_mut().method_map
.insert(method_call
, method
);
1184 c
::tag_table_adjustments
=> {
1186 val_dsr
.read_auto_adjustment(dcx
);
1187 dcx
.tcx
.tables
.borrow_mut().adjustments
.insert(id
, adj
);
1189 c
::tag_table_cast_kinds
=> {
1191 val_dsr
.read_cast_kind(dcx
);
1192 dcx
.tcx
.cast_kinds
.borrow_mut().insert(id
, cast_kind
);
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
);
1199 bug
!("unknown tag found in side tables: {:x}", tag
);
1205 debug
!(">< Side table doc loaded");
1209 // copy the tcache entries from the original item to the new
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
));
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
1227 copy_item_type(dcx
, item_node_id
, orig_did
);
1229 // copy the entries of inner items
1230 if let &InlinedItem
::Item(ref item
) = ii
{
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())
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
);
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
,
1248 copy_item_type(dcx
, def
.id(), ctor_did
);
1256 fn inlined_item_id_range(v
: &InlinedItem
) -> IdRange
{
1257 let mut visitor
= IdRangeComputingVisitor
::new();
1258 v
.visit_ids(&mut visitor
);
1262 // ______________________________________________________________________
1263 // Testing of astencode_gen
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
);
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()
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
;
1289 impl FakeExtCtxt
for parse
::ParseSess
{
1290 fn call_site(&self) -> codemap
::Span
{
1292 lo
: codemap
::BytePos(0),
1293 hi
: codemap
::BytePos(0),
1294 expn_id
: codemap
::NO_EXPANSION
,
1297 fn cfg(&self) -> ast
::CrateConfig { Vec::new() }
1298 fn ident_of(&self, st
: &str) -> ast
::Ident
{
1299 parse
::token
::str_to_ident(st
)
1301 fn name_of(&self, st
: &str) -> ast
::Name
{
1302 parse
::token
::intern(st
)
1304 fn parse_sess(&self) -> &parse
::ParseSess { self }
1308 struct FakeNodeIdAssigner
;
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
{
1318 fn peek_node_id(&self) -> NodeId
{
1324 fn mk_ctxt() -> parse
::ParseSess
{
1325 parse
::ParseSess
::new()
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
);
1335 assert
!(in_item
== out_item
);
1341 let fnia
= FakeNodeIdAssigner
;
1342 let lcx
= LoweringContext
::new(&fnia
, None
);
1343 roundtrip(lower_item(&lcx
, "e_item
!(&cx
,
1349 fn test_smalltalk() {
1351 let fnia
= FakeNodeIdAssigner
;
1352 let lcx
= LoweringContext
::new(&fnia
, None
);
1353 roundtrip(lower_item(&lcx
, "e_item
!(&cx
,
1354 fn foo() -> isize { 3 + 4 }
// first smalltalk program ever executed.
1361 let fnia
= FakeNodeIdAssigner
;
1362 let lcx
= LoweringContext
::new(&fnia
, None
);
1363 roundtrip(lower_item(&lcx
, "e_item
!(&cx
,
1364 fn foo(x
: usize, y
: usize) -> usize {
1372 fn test_simplification() {
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()}
;
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
, "e_item
!(&cx
,
1386 fn new_int_alist
<B
>() -> alist
<isize, B
> {
1387 return alist {eq_fn: eq_int, data: Vec::new()}
;
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
));