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
::front
::map
as ast_map
;
16 use rustc
::session
::Session
;
19 use rustc_front
::fold
;
20 use rustc_front
::fold
::Folder
;
29 use middle
::cstore
::{InlinedItem, InlinedItemRef}
;
30 use middle
::ty
::adjustment
;
32 use middle
::check_const
::ConstQualif
;
34 use middle
::def_id
::DefId
;
35 use middle
::privacy
::{AllPublic, LastMod}
;
38 use middle
::ty
::{self, Ty}
;
40 use syntax
::{ast, ast_util, codemap}
;
41 use syntax
::ast
::NodeIdAssigner
;
42 use syntax
::codemap
::Span
;
46 use std
::io
::SeekFrom
;
47 use std
::io
::prelude
::*;
51 use rbml
::writer
::Encoder
;
54 use serialize
::{Decodable, Decoder, DecoderHelpers, Encodable}
;
55 use serialize
::EncoderHelpers
;
57 #[cfg(test)] use std::io::Cursor;
58 #[cfg(test)] use syntax::parse;
59 #[cfg(test)] use syntax::ast::NodeId;
60 #[cfg(test)] use rustc_front::print::pprust;
61 #[cfg(test)] use rustc_front::lowering::{lower_item, LoweringContext};
63 struct DecodeContext
<'a
, 'b
, 'tcx
: 'a
> {
64 tcx
: &'a ty
::ctxt
<'tcx
>,
65 cdata
: &'b cstore
::crate_metadata
,
66 from_id_range
: ast_util
::IdRange
,
67 to_id_range
: ast_util
::IdRange
,
68 // Cache the last used filemap for translating spans as an optimization.
69 last_filemap_index
: Cell
<usize>,
73 fn tr(&self, dcx
: &DecodeContext
) -> Self;
76 // ______________________________________________________________________
79 pub fn encode_inlined_item(ecx
: &e
::EncodeContext
,
83 InlinedItemRef
::Item(i
) => i
.id
,
84 InlinedItemRef
::Foreign(i
) => i
.id
,
85 InlinedItemRef
::TraitItem(_
, ti
) => ti
.id
,
86 InlinedItemRef
::ImplItem(_
, ii
) => ii
.id
,
88 debug
!("> Encoding inlined item: {} ({:?})",
89 ecx
.tcx
.map
.path_to_string(id
),
90 rbml_w
.writer
.seek(SeekFrom
::Current(0)));
92 // Folding could be avoided with a smarter encoder.
93 let ii
= simplify_ast(ii
);
94 let id_range
= inlined_item_id_range(&ii
);
96 rbml_w
.start_tag(c
::tag_ast
as usize);
97 id_range
.encode(rbml_w
);
98 encode_ast(rbml_w
, &ii
);
99 encode_side_tables_for_ii(ecx
, rbml_w
, &ii
);
102 debug
!("< Encoded inlined fn: {} ({:?})",
103 ecx
.tcx
.map
.path_to_string(id
),
104 rbml_w
.writer
.seek(SeekFrom
::Current(0)));
107 impl<'a
, 'b
, 'c
, 'tcx
> ast_map
::FoldOps
for &'a DecodeContext
<'b
, 'c
, 'tcx
> {
108 fn new_id(&self, id
: ast
::NodeId
) -> ast
::NodeId
{
109 if id
== ast
::DUMMY_NODE_ID
{
110 // Used by ast_map to map the NodeInlinedParent.
111 self.tcx
.sess
.next_node_id()
116 fn new_def_id(&self, def_id
: DefId
) -> DefId
{
117 self.tr_def_id(def_id
)
119 fn new_span(&self, span
: Span
) -> Span
{
124 /// Decodes an item from its AST in the cdata's metadata and adds it to the
126 pub fn decode_inlined_item
<'tcx
>(cdata
: &cstore
::crate_metadata
,
127 tcx
: &ty
::ctxt
<'tcx
>,
128 path
: Vec
<ast_map
::PathElem
>,
129 def_path
: ast_map
::DefPath
,
132 -> Result
<&'tcx InlinedItem
, (Vec
<ast_map
::PathElem
>,
134 match par_doc
.opt_child(c
::tag_ast
) {
135 None
=> Err((path
, def_path
)),
137 let mut path_as_str
= None
;
138 debug
!("> Decoding inlined fn: {:?}::?",
140 // Do an Option dance to use the path after it is moved below.
141 let s
= ast_map
::path_to_string(path
.iter().cloned());
142 path_as_str
= Some(s
);
143 path_as_str
.as_ref().map(|x
| &x
[..])
145 let mut ast_dsr
= reader
::Decoder
::new(ast_doc
);
146 let from_id_range
= Decodable
::decode(&mut ast_dsr
).unwrap();
147 let to_id_range
= reserve_id_range(&tcx
.sess
, from_id_range
);
148 let dcx
= &DecodeContext
{
151 from_id_range
: from_id_range
,
152 to_id_range
: to_id_range
,
153 last_filemap_index
: Cell
::new(0)
155 let raw_ii
= decode_ast(ast_doc
);
156 let ii
= ast_map
::map_decoded_item(&dcx
.tcx
.map
, path
, def_path
, raw_ii
, dcx
);
158 let name
= match *ii
{
159 InlinedItem
::Item(ref i
) => i
.name
,
160 InlinedItem
::Foreign(ref i
) => i
.name
,
161 InlinedItem
::TraitItem(_
, ref ti
) => ti
.name
,
162 InlinedItem
::ImplItem(_
, ref ii
) => ii
.name
164 debug
!("Fn named: {}", name
);
165 debug
!("< Decoded inlined fn: {}::{}",
166 path_as_str
.unwrap(),
168 region
::resolve_inlined_item(&tcx
.sess
, &tcx
.region_maps
, ii
);
169 decode_side_tables(dcx
, ast_doc
);
170 copy_item_types(dcx
, ii
, orig_did
);
172 InlinedItem
::Item(ref i
) => {
173 debug
!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
174 ::rustc_front
::print
::pprust
::item_to_string(&**i
));
183 // ______________________________________________________________________
184 // Enumerating the IDs which appear in an AST
186 fn reserve_id_range(sess
: &Session
,
187 from_id_range
: ast_util
::IdRange
) -> ast_util
::IdRange
{
188 // Handle the case of an empty range:
189 if from_id_range
.empty() { return from_id_range; }
190 let cnt
= from_id_range
.max
- from_id_range
.min
;
191 let to_id_min
= sess
.reserve_node_ids(cnt
);
192 let to_id_max
= to_id_min
+ cnt
;
193 ast_util
::IdRange { min: to_id_min, max: to_id_max }
196 impl<'a
, 'b
, 'tcx
> DecodeContext
<'a
, 'b
, 'tcx
> {
197 /// Translates an internal id, meaning a node id that is known to refer to some part of the
198 /// item currently being inlined, such as a local variable or argument. All naked node-ids
199 /// that appear in types have this property, since if something might refer to an external item
200 /// we would use a def-id to allow for the possibility that the item resides in another crate.
201 pub fn tr_id(&self, id
: ast
::NodeId
) -> ast
::NodeId
{
202 // from_id_range should be non-empty
203 assert
!(!self.from_id_range
.empty());
204 // Use wrapping arithmetic because otherwise it introduces control flow.
205 // Maybe we should just have the control flow? -- aatch
206 (id
.wrapping_sub(self.from_id_range
.min
).wrapping_add(self.to_id_range
.min
))
209 /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
210 /// data to the current crate numbers.. By external, I mean that it be translated to a
211 /// reference to the item in its original crate, as opposed to being translated to a reference
212 /// to the inlined version of the item. This is typically, but not always, what you want,
213 /// because most def-ids refer to external things like types or other fns that may or may not
214 /// be inlined. Note that even when the inlined function is referencing itself recursively, we
215 /// would want `tr_def_id` for that reference--- conceptually the function calls the original,
216 /// non-inlined version, and trans deals with linking that recursive call to the inlined copy.
217 pub fn tr_def_id(&self, did
: DefId
) -> DefId
{
218 decoder
::translate_def_id(self.cdata
, did
)
221 /// Translates a `Span` from an extern crate to the corresponding `Span`
222 /// within the local crate's codemap. `creader::import_codemap()` will
223 /// already have allocated any additionally needed FileMaps in the local
224 /// codemap as a side-effect of creating the crate_metadata's
225 /// `codemap_import_info`.
226 pub fn tr_span(&self, span
: Span
) -> Span
{
227 let span
= if span
.lo
> span
.hi
{
228 // Currently macro expansion sometimes produces invalid Span values
229 // where lo > hi. In order not to crash the compiler when trying to
230 // translate these values, let's transform them into something we
231 // can handle (and which will produce useful debug locations at
232 // least some of the time).
233 // This workaround is only necessary as long as macro expansion is
234 // not fixed. FIXME(#23480)
235 codemap
::mk_sp(span
.lo
, span
.lo
)
240 let imported_filemaps
= self.cdata
.imported_filemaps(self.tcx
.sess
.codemap());
242 // Optimize for the case that most spans within a translated item
243 // originate from the same filemap.
244 let last_filemap_index
= self.last_filemap_index
.get();
245 let last_filemap
= &imported_filemaps
[last_filemap_index
];
247 if span
.lo
>= last_filemap
.original_start_pos
&&
248 span
.lo
<= last_filemap
.original_end_pos
&&
249 span
.hi
>= last_filemap
.original_start_pos
&&
250 span
.hi
<= last_filemap
.original_end_pos
{
254 let mut b
= imported_filemaps
.len();
258 if imported_filemaps
[m
].original_start_pos
> span
.lo
{
265 self.last_filemap_index
.set(a
);
266 &imported_filemaps
[a
]
270 let lo
= (span
.lo
- filemap
.original_start_pos
) +
271 filemap
.translated_filemap
.start_pos
;
272 let hi
= (span
.hi
- filemap
.original_start_pos
) +
273 filemap
.translated_filemap
.start_pos
;
275 codemap
::mk_sp(lo
, hi
)
280 fn tr(&self, dcx
: &DecodeContext
) -> DefId
{
285 impl tr
for Option
<DefId
> {
286 fn tr(&self, dcx
: &DecodeContext
) -> Option
<DefId
> {
287 self.map(|d
| dcx
.tr_def_id(d
))
292 fn tr(&self, dcx
: &DecodeContext
) -> Span
{
297 trait def_id_encoder_helpers
{
298 fn emit_def_id(&mut self, did
: DefId
);
301 impl<S
:serialize
::Encoder
> def_id_encoder_helpers
for S
302 where <S
as serialize
::serialize
::Encoder
>::Error
: Debug
304 fn emit_def_id(&mut self, did
: DefId
) {
305 did
.encode(self).unwrap()
309 trait def_id_decoder_helpers
{
310 fn read_def_id(&mut self, dcx
: &DecodeContext
) -> DefId
;
311 fn read_def_id_nodcx(&mut self,
312 cdata
: &cstore
::crate_metadata
) -> DefId
;
315 impl<D
:serialize
::Decoder
> def_id_decoder_helpers
for D
316 where <D
as serialize
::serialize
::Decoder
>::Error
: Debug
318 fn read_def_id(&mut self, dcx
: &DecodeContext
) -> DefId
{
319 let did
: DefId
= Decodable
::decode(self).unwrap();
323 fn read_def_id_nodcx(&mut self,
324 cdata
: &cstore
::crate_metadata
)
326 let did
: DefId
= Decodable
::decode(self).unwrap();
327 decoder
::translate_def_id(cdata
, did
)
331 // ______________________________________________________________________
332 // Encoding and decoding the AST itself
334 // When decoding, we have to renumber the AST so that the node ids that
335 // appear within are disjoint from the node ids in our existing ASTs.
336 // We also have to adjust the spans: for now we just insert a dummy span,
337 // but eventually we should add entries to the local codemap as required.
339 fn encode_ast(rbml_w
: &mut Encoder
, item
: &InlinedItem
) {
340 rbml_w
.start_tag(c
::tag_tree
as usize);
345 struct NestedItemsDropper
;
347 impl Folder
for NestedItemsDropper
{
348 fn fold_block(&mut self, blk
: P
<hir
::Block
>) -> P
<hir
::Block
> {
349 blk
.and_then(|hir
::Block {id, stmts, expr, rules, span, ..}
| {
350 let stmts_sans_items
= stmts
.into_iter().filter_map(|stmt
| {
351 let use_stmt
= match stmt
.node
{
352 hir
::StmtExpr(_
, _
) | hir
::StmtSemi(_
, _
) => true,
353 hir
::StmtDecl(ref decl
, _
) => {
355 hir
::DeclLocal(_
) => true,
356 hir
::DeclItem(_
) => false,
366 let blk_sans_items
= P(hir
::Block
{
367 stmts
: stmts_sans_items
,
373 fold
::noop_fold_block(blk_sans_items
, self)
378 // Produces a simplified copy of the AST which does not include things
379 // that we do not need to or do not want to export. For example, we
380 // do not include any nested items: if these nested items are to be
381 // inlined, their AST will be exported separately (this only makes
382 // sense because, in Rust, nested items are independent except for
383 // their visibility).
385 // As it happens, trans relies on the fact that we do not export
386 // nested items, as otherwise it would get confused when translating
388 fn simplify_ast(ii
: InlinedItemRef
) -> InlinedItem
{
389 let mut fld
= NestedItemsDropper
;
392 // HACK we're not dropping items.
393 InlinedItemRef
::Item(i
) => {
394 InlinedItem
::Item(P(fold
::noop_fold_item(i
.clone(), &mut fld
)))
396 InlinedItemRef
::TraitItem(d
, ti
) => {
397 InlinedItem
::TraitItem(d
, P(fold
::noop_fold_trait_item(ti
.clone(), &mut fld
)))
399 InlinedItemRef
::ImplItem(d
, ii
) => {
400 InlinedItem
::ImplItem(d
, P(fold
::noop_fold_impl_item(ii
.clone(), &mut fld
)))
402 InlinedItemRef
::Foreign(i
) => {
403 InlinedItem
::Foreign(P(fold
::noop_fold_foreign_item(i
.clone(), &mut fld
)))
408 fn decode_ast(par_doc
: rbml
::Doc
) -> InlinedItem
{
409 let chi_doc
= par_doc
.get(c
::tag_tree
as usize);
410 let mut d
= reader
::Decoder
::new(chi_doc
);
411 Decodable
::decode(&mut d
).unwrap()
414 // ______________________________________________________________________
415 // Encoding and decoding of ast::def
417 fn decode_def(dcx
: &DecodeContext
, dsr
: &mut reader
::Decoder
) -> def
::Def
{
418 let def
: def
::Def
= Decodable
::decode(dsr
).unwrap();
422 impl tr
for def
::Def
{
423 fn tr(&self, dcx
: &DecodeContext
) -> def
::Def
{
425 def
::DefFn(did
, is_ctor
) => def
::DefFn(did
.tr(dcx
), is_ctor
),
426 def
::DefMethod(did
) => def
::DefMethod(did
.tr(dcx
)),
427 def
::DefSelfTy(opt_did
, impl_ids
) => { def
::DefSelfTy(opt_did
.map(|did
| did
.tr(dcx
)),
428 impl_ids
.map(|(nid1
, nid2
)| {
432 def
::DefMod(did
) => { def::DefMod(did.tr(dcx)) }
433 def
::DefForeignMod(did
) => { def::DefForeignMod(did.tr(dcx)) }
434 def
::DefStatic(did
, m
) => { def::DefStatic(did.tr(dcx), m) }
435 def
::DefConst(did
) => { def::DefConst(did.tr(dcx)) }
436 def
::DefAssociatedConst(did
) => def
::DefAssociatedConst(did
.tr(dcx
)),
437 def
::DefLocal(_
, nid
) => {
438 let nid
= dcx
.tr_id(nid
);
439 let did
= dcx
.tcx
.map
.local_def_id(nid
);
440 def
::DefLocal(did
, nid
)
442 def
::DefVariant(e_did
, v_did
, is_s
) => {
443 def
::DefVariant(e_did
.tr(dcx
), v_did
.tr(dcx
), is_s
)
445 def
::DefTrait(did
) => def
::DefTrait(did
.tr(dcx
)),
446 def
::DefTy(did
, is_enum
) => def
::DefTy(did
.tr(dcx
), is_enum
),
447 def
::DefAssociatedTy(trait_did
, did
) =>
448 def
::DefAssociatedTy(trait_did
.tr(dcx
), did
.tr(dcx
)),
449 def
::DefPrimTy(p
) => def
::DefPrimTy(p
),
450 def
::DefTyParam(s
, index
, def_id
, n
) => def
::DefTyParam(s
, index
, def_id
.tr(dcx
), n
),
451 def
::DefUse(did
) => def
::DefUse(did
.tr(dcx
)),
452 def
::DefUpvar(_
, nid1
, index
, nid2
) => {
453 let nid1
= dcx
.tr_id(nid1
);
454 let nid2
= dcx
.tr_id(nid2
);
455 let did1
= dcx
.tcx
.map
.local_def_id(nid1
);
456 def
::DefUpvar(did1
, nid1
, index
, nid2
)
458 def
::DefStruct(did
) => def
::DefStruct(did
.tr(dcx
)),
459 def
::DefLabel(nid
) => def
::DefLabel(dcx
.tr_id(nid
))
464 // ______________________________________________________________________
465 // Encoding and decoding of freevar information
467 fn encode_freevar_entry(rbml_w
: &mut Encoder
, fv
: &ty
::Freevar
) {
468 (*fv
).encode(rbml_w
).unwrap();
471 trait rbml_decoder_helper
{
472 fn read_freevar_entry(&mut self, dcx
: &DecodeContext
)
474 fn read_capture_mode(&mut self) -> hir
::CaptureClause
;
477 impl<'a
> rbml_decoder_helper
for reader
::Decoder
<'a
> {
478 fn read_freevar_entry(&mut self, dcx
: &DecodeContext
)
480 let fv
: ty
::Freevar
= Decodable
::decode(self).unwrap();
484 fn read_capture_mode(&mut self) -> hir
::CaptureClause
{
485 let cm
: hir
::CaptureClause
= Decodable
::decode(self).unwrap();
490 impl tr
for ty
::Freevar
{
491 fn tr(&self, dcx
: &DecodeContext
) -> ty
::Freevar
{
493 def
: self.def
.tr(dcx
),
494 span
: self.span
.tr(dcx
),
499 // ______________________________________________________________________
500 // Encoding and decoding of MethodCallee
502 trait read_method_callee_helper
<'tcx
> {
503 fn read_method_callee
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
504 -> (u32, ty
::MethodCallee
<'tcx
>);
507 fn encode_method_callee
<'a
, 'tcx
>(ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
508 rbml_w
: &mut Encoder
,
510 method
: &ty
::MethodCallee
<'tcx
>) {
511 use serialize
::Encoder
;
513 rbml_w
.emit_struct("MethodCallee", 4, |rbml_w
| {
514 rbml_w
.emit_struct_field("autoderef", 0, |rbml_w
| {
515 autoderef
.encode(rbml_w
)
517 rbml_w
.emit_struct_field("def_id", 1, |rbml_w
| {
518 Ok(rbml_w
.emit_def_id(method
.def_id
))
520 rbml_w
.emit_struct_field("ty", 2, |rbml_w
| {
521 Ok(rbml_w
.emit_ty(ecx
, method
.ty
))
523 rbml_w
.emit_struct_field("substs", 3, |rbml_w
| {
524 Ok(rbml_w
.emit_substs(ecx
, &method
.substs
))
529 impl<'a
, 'tcx
> read_method_callee_helper
<'tcx
> for reader
::Decoder
<'a
> {
530 fn read_method_callee
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
531 -> (u32, ty
::MethodCallee
<'tcx
>) {
533 self.read_struct("MethodCallee", 4, |this
| {
534 let autoderef
= this
.read_struct_field("autoderef", 0,
535 Decodable
::decode
).unwrap();
536 Ok((autoderef
, ty
::MethodCallee
{
537 def_id
: this
.read_struct_field("def_id", 1, |this
| {
538 Ok(this
.read_def_id(dcx
))
540 ty
: this
.read_struct_field("ty", 2, |this
| {
541 Ok(this
.read_ty(dcx
))
543 substs
: this
.read_struct_field("substs", 3, |this
| {
544 Ok(dcx
.tcx
.mk_substs(this
.read_substs(dcx
)))
551 pub fn encode_cast_kind(ebml_w
: &mut Encoder
, kind
: cast
::CastKind
) {
552 kind
.encode(ebml_w
).unwrap();
555 // ______________________________________________________________________
556 // Encoding and decoding the side tables
558 trait get_ty_str_ctxt
<'tcx
> {
559 fn ty_str_ctxt
<'a
>(&'a
self) -> tyencode
::ctxt
<'a
, 'tcx
>;
562 impl<'a
, 'tcx
> get_ty_str_ctxt
<'tcx
> for e
::EncodeContext
<'a
, 'tcx
> {
563 fn ty_str_ctxt
<'b
>(&'b
self) -> tyencode
::ctxt
<'b
, 'tcx
> {
565 diag
: self.tcx
.sess
.diagnostic(),
566 ds
: e
::def_to_string
,
568 abbrevs
: &self.type_abbrevs
573 trait rbml_writer_helpers
<'tcx
> {
574 fn emit_region(&mut self, ecx
: &e
::EncodeContext
, r
: ty
::Region
);
575 fn emit_ty
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>);
576 fn emit_tys
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>, tys
: &[Ty
<'tcx
>]);
577 fn emit_predicate
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
578 predicate
: &ty
::Predicate
<'tcx
>);
579 fn emit_trait_ref
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
580 ty
: &ty
::TraitRef
<'tcx
>);
581 fn emit_substs
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
582 substs
: &subst
::Substs
<'tcx
>);
583 fn emit_existential_bounds
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
,'tcx
>,
584 bounds
: &ty
::ExistentialBounds
<'tcx
>);
585 fn emit_builtin_bounds(&mut self, ecx
: &e
::EncodeContext
, bounds
: &ty
::BuiltinBounds
);
586 fn emit_upvar_capture(&mut self, ecx
: &e
::EncodeContext
, capture
: &ty
::UpvarCapture
);
587 fn emit_auto_adjustment
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
588 adj
: &adjustment
::AutoAdjustment
<'tcx
>);
589 fn emit_autoref
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
590 autoref
: &adjustment
::AutoRef
<'tcx
>);
591 fn emit_auto_deref_ref
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
592 auto_deref_ref
: &adjustment
::AutoDerefRef
<'tcx
>);
595 impl<'a
, 'tcx
> rbml_writer_helpers
<'tcx
> for Encoder
<'a
> {
596 fn emit_region(&mut self, ecx
: &e
::EncodeContext
, r
: ty
::Region
) {
597 self.emit_opaque(|this
| Ok(e
::write_region(ecx
, this
, r
)));
600 fn emit_ty
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>, ty
: Ty
<'tcx
>) {
601 self.emit_opaque(|this
| Ok(e
::write_type(ecx
, this
, ty
)));
604 fn emit_tys
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>, tys
: &[Ty
<'tcx
>]) {
605 self.emit_from_vec(tys
, |this
, ty
| Ok(this
.emit_ty(ecx
, *ty
)));
608 fn emit_trait_ref
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
609 trait_ref
: &ty
::TraitRef
<'tcx
>) {
610 self.emit_opaque(|this
| Ok(e
::write_trait_ref(ecx
, this
, trait_ref
)));
613 fn emit_predicate
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
614 predicate
: &ty
::Predicate
<'tcx
>) {
615 self.emit_opaque(|this
| {
616 Ok(tyencode
::enc_predicate(this
,
622 fn emit_existential_bounds
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
,'tcx
>,
623 bounds
: &ty
::ExistentialBounds
<'tcx
>) {
624 self.emit_opaque(|this
| Ok(tyencode
::enc_existential_bounds(this
,
629 fn emit_builtin_bounds(&mut self, ecx
: &e
::EncodeContext
, bounds
: &ty
::BuiltinBounds
) {
630 self.emit_opaque(|this
| Ok(tyencode
::enc_builtin_bounds(this
,
635 fn emit_upvar_capture(&mut self, ecx
: &e
::EncodeContext
, capture
: &ty
::UpvarCapture
) {
636 use serialize
::Encoder
;
638 self.emit_enum("UpvarCapture", |this
| {
640 ty
::UpvarCapture
::ByValue
=> {
641 this
.emit_enum_variant("ByValue", 1, 0, |_
| Ok(()))
643 ty
::UpvarCapture
::ByRef(ty
::UpvarBorrow { kind, region }
) => {
644 this
.emit_enum_variant("ByRef", 2, 0, |this
| {
645 this
.emit_enum_variant_arg(0,
646 |this
| kind
.encode(this
));
647 this
.emit_enum_variant_arg(1,
648 |this
| Ok(this
.emit_region(ecx
, region
)))
655 fn emit_substs
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
656 substs
: &subst
::Substs
<'tcx
>) {
657 self.emit_opaque(|this
| Ok(tyencode
::enc_substs(this
,
662 fn emit_auto_adjustment
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
663 adj
: &adjustment
::AutoAdjustment
<'tcx
>) {
664 use serialize
::Encoder
;
666 self.emit_enum("AutoAdjustment", |this
| {
668 adjustment
::AdjustReifyFnPointer
=> {
669 this
.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_
| Ok(()))
672 adjustment
::AdjustUnsafeFnPointer
=> {
673 this
.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_
| {
678 adjustment
::AdjustDerefRef(ref auto_deref_ref
) => {
679 this
.emit_enum_variant("AdjustDerefRef", 3, 2, |this
| {
680 this
.emit_enum_variant_arg(0,
681 |this
| Ok(this
.emit_auto_deref_ref(ecx
, auto_deref_ref
)))
688 fn emit_autoref
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
689 autoref
: &adjustment
::AutoRef
<'tcx
>) {
690 use serialize
::Encoder
;
692 self.emit_enum("AutoRef", |this
| {
694 &adjustment
::AutoPtr(r
, m
) => {
695 this
.emit_enum_variant("AutoPtr", 0, 2, |this
| {
696 this
.emit_enum_variant_arg(0,
697 |this
| Ok(this
.emit_region(ecx
, *r
)));
698 this
.emit_enum_variant_arg(1, |this
| m
.encode(this
))
701 &adjustment
::AutoUnsafe(m
) => {
702 this
.emit_enum_variant("AutoUnsafe", 1, 1, |this
| {
703 this
.emit_enum_variant_arg(0, |this
| m
.encode(this
))
710 fn emit_auto_deref_ref
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
711 auto_deref_ref
: &adjustment
::AutoDerefRef
<'tcx
>) {
712 use serialize
::Encoder
;
714 self.emit_struct("AutoDerefRef", 2, |this
| {
715 this
.emit_struct_field("autoderefs", 0, |this
| auto_deref_ref
.autoderefs
.encode(this
));
717 this
.emit_struct_field("autoref", 1, |this
| {
718 this
.emit_option(|this
| {
719 match auto_deref_ref
.autoref
{
720 None
=> this
.emit_option_none(),
721 Some(ref a
) => this
.emit_option_some(|this
| Ok(this
.emit_autoref(ecx
, a
))),
726 this
.emit_struct_field("unsize", 2, |this
| {
727 this
.emit_option(|this
| {
728 match auto_deref_ref
.unsize
{
729 None
=> this
.emit_option_none(),
730 Some(target
) => this
.emit_option_some(|this
| {
731 Ok(this
.emit_ty(ecx
, target
))
740 trait write_tag_and_id
{
741 fn tag
<F
>(&mut self, tag_id
: c
::astencode_tag
, f
: F
) where F
: FnOnce(&mut Self);
742 fn id(&mut self, id
: ast
::NodeId
);
745 impl<'a
> write_tag_and_id
for Encoder
<'a
> {
747 tag_id
: c
::astencode_tag
,
749 F
: FnOnce(&mut Encoder
<'a
>),
751 self.start_tag(tag_id
as usize);
756 fn id(&mut self, id
: ast
::NodeId
) {
757 id
.encode(self).unwrap();
761 struct SideTableEncodingIdVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'c
> {
762 ecx
: &'a e
::EncodeContext
<'c
, 'tcx
>,
763 rbml_w
: &'a
mut Encoder
<'b
>,
766 impl<'a
, 'b
, 'c
, 'tcx
> ast_util
::IdVisitingOperation
for
767 SideTableEncodingIdVisitor
<'a
, 'b
, 'c
, 'tcx
> {
768 fn visit_id(&mut self, id
: ast
::NodeId
) {
769 encode_side_tables_for_id(self.ecx
, self.rbml_w
, id
)
773 fn encode_side_tables_for_ii(ecx
: &e
::EncodeContext
,
774 rbml_w
: &mut Encoder
,
776 rbml_w
.start_tag(c
::tag_table
as usize);
777 ii
.visit_ids(&mut SideTableEncodingIdVisitor
{
784 fn encode_side_tables_for_id(ecx
: &e
::EncodeContext
,
785 rbml_w
: &mut Encoder
,
789 debug
!("Encoding side tables for id {}", id
);
791 if let Some(def
) = tcx
.def_map
.borrow().get(&id
).map(|d
| d
.full_def()) {
792 rbml_w
.tag(c
::tag_table_def
, |rbml_w
| {
794 def
.encode(rbml_w
).unwrap();
798 if let Some(ty
) = tcx
.node_types().get(&id
) {
799 rbml_w
.tag(c
::tag_table_node_type
, |rbml_w
| {
801 rbml_w
.emit_ty(ecx
, *ty
);
805 if let Some(item_substs
) = tcx
.tables
.borrow().item_substs
.get(&id
) {
806 rbml_w
.tag(c
::tag_table_item_subst
, |rbml_w
| {
808 rbml_w
.emit_substs(ecx
, &item_substs
.substs
);
812 if let Some(fv
) = tcx
.freevars
.borrow().get(&id
) {
813 rbml_w
.tag(c
::tag_table_freevars
, |rbml_w
| {
815 rbml_w
.emit_from_vec(fv
, |rbml_w
, fv_entry
| {
816 Ok(encode_freevar_entry(rbml_w
, fv_entry
))
821 rbml_w
.tag(c
::tag_table_upvar_capture_map
, |rbml_w
| {
824 let var_id
= freevar
.def
.var_id();
825 let upvar_id
= ty
::UpvarId
{
829 let upvar_capture
= tcx
.tables
835 var_id
.encode(rbml_w
);
836 rbml_w
.emit_upvar_capture(ecx
, &upvar_capture
);
841 let method_call
= ty
::MethodCall
::expr(id
);
842 if let Some(method
) = tcx
.tables
.borrow().method_map
.get(&method_call
) {
843 rbml_w
.tag(c
::tag_table_method_map
, |rbml_w
| {
845 encode_method_callee(ecx
, rbml_w
, method_call
.autoderef
, method
)
849 if let Some(adjustment
) = tcx
.tables
.borrow().adjustments
.get(&id
) {
851 adjustment
::AdjustDerefRef(ref adj
) => {
852 for autoderef
in 0..adj
.autoderefs
{
853 let method_call
= ty
::MethodCall
::autoderef(id
, autoderef
as u32);
854 if let Some(method
) = tcx
.tables
.borrow().method_map
.get(&method_call
) {
855 rbml_w
.tag(c
::tag_table_method_map
, |rbml_w
| {
857 encode_method_callee(ecx
, rbml_w
,
858 method_call
.autoderef
, method
)
866 rbml_w
.tag(c
::tag_table_adjustments
, |rbml_w
| {
868 rbml_w
.emit_auto_adjustment(ecx
, adjustment
);
872 if let Some(cast_kind
) = tcx
.cast_kinds
.borrow().get(&id
) {
873 rbml_w
.tag(c
::tag_table_cast_kinds
, |rbml_w
| {
875 encode_cast_kind(rbml_w
, *cast_kind
)
879 if let Some(qualif
) = tcx
.const_qualif_map
.borrow().get(&id
) {
880 rbml_w
.tag(c
::tag_table_const_qualif
, |rbml_w
| {
882 qualif
.encode(rbml_w
).unwrap()
887 trait doc_decoder_helpers
: Sized
{
888 fn as_int(&self) -> isize;
889 fn opt_child(&self, tag
: c
::astencode_tag
) -> Option
<Self>;
892 impl<'a
> doc_decoder_helpers
for rbml
::Doc
<'a
> {
893 fn as_int(&self) -> isize { reader::doc_as_u64(*self) as isize }
894 fn opt_child(&self, tag
: c
::astencode_tag
) -> Option
<rbml
::Doc
<'a
>> {
895 reader
::maybe_get_doc(*self, tag
as usize)
899 trait rbml_decoder_decoder_helpers
<'tcx
> {
900 fn read_ty_encoded
<'a
, 'b
, F
, R
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>,
902 where F
: for<'x
> FnOnce(&mut tydecode
::TyDecoder
<'x
, 'tcx
>) -> R
;
904 fn read_region(&mut self, dcx
: &DecodeContext
) -> ty
::Region
;
905 fn read_ty
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>) -> Ty
<'tcx
>;
906 fn read_tys
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>) -> Vec
<Ty
<'tcx
>>;
907 fn read_trait_ref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
908 -> ty
::TraitRef
<'tcx
>;
909 fn read_poly_trait_ref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
910 -> ty
::PolyTraitRef
<'tcx
>;
911 fn read_predicate
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
912 -> ty
::Predicate
<'tcx
>;
913 fn read_existential_bounds
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
914 -> ty
::ExistentialBounds
<'tcx
>;
915 fn read_substs
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
916 -> subst
::Substs
<'tcx
>;
917 fn read_upvar_capture(&mut self, dcx
: &DecodeContext
)
919 fn read_auto_adjustment
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
920 -> adjustment
::AutoAdjustment
<'tcx
>;
921 fn read_cast_kind
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
923 fn read_auto_deref_ref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
924 -> adjustment
::AutoDerefRef
<'tcx
>;
925 fn read_autoref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
926 -> adjustment
::AutoRef
<'tcx
>;
927 fn convert_def_id(&mut self,
932 // Versions of the type reading functions that don't need the full
934 fn read_ty_nodcx(&mut self,
935 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
) -> Ty
<'tcx
>;
936 fn read_tys_nodcx(&mut self,
937 tcx
: &ty
::ctxt
<'tcx
>,
938 cdata
: &cstore
::crate_metadata
) -> Vec
<Ty
<'tcx
>>;
939 fn read_substs_nodcx(&mut self, tcx
: &ty
::ctxt
<'tcx
>,
940 cdata
: &cstore
::crate_metadata
)
941 -> subst
::Substs
<'tcx
>;
944 impl<'a
, 'tcx
> rbml_decoder_decoder_helpers
<'tcx
> for reader
::Decoder
<'a
> {
945 fn read_ty_nodcx(&mut self,
946 tcx
: &ty
::ctxt
<'tcx
>,
947 cdata
: &cstore
::crate_metadata
)
949 self.read_opaque(|_
, doc
| {
951 tydecode
::TyDecoder
::with_doc(tcx
, cdata
.cnum
, doc
,
952 &mut |id
| decoder
::translate_def_id(cdata
, id
))
957 fn read_tys_nodcx(&mut self,
958 tcx
: &ty
::ctxt
<'tcx
>,
959 cdata
: &cstore
::crate_metadata
) -> Vec
<Ty
<'tcx
>> {
960 self.read_to_vec(|this
| Ok(this
.read_ty_nodcx(tcx
, cdata
)) )
966 fn read_substs_nodcx(&mut self,
967 tcx
: &ty
::ctxt
<'tcx
>,
968 cdata
: &cstore
::crate_metadata
)
969 -> subst
::Substs
<'tcx
>
971 self.read_opaque(|_
, doc
| {
973 tydecode
::TyDecoder
::with_doc(tcx
, cdata
.cnum
, doc
,
974 &mut |id
| decoder
::translate_def_id(cdata
, id
))
979 fn read_ty_encoded
<'b
, 'c
, F
, R
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>, op
: F
) -> R
980 where F
: for<'x
> FnOnce(&mut tydecode
::TyDecoder
<'x
,'tcx
>) -> R
982 return self.read_opaque(|this
, doc
| {
983 debug
!("read_ty_encoded({})", type_string(doc
));
985 &mut tydecode
::TyDecoder
::with_doc(
986 dcx
.tcx
, dcx
.cdata
.cnum
, doc
,
987 &mut |a
| this
.convert_def_id(dcx
, a
))))
990 fn type_string(doc
: rbml
::Doc
) -> String
{
991 let mut str = String
::new();
992 for i
in doc
.start
..doc
.end
{
993 str.push(doc
.data
[i
] as char);
998 fn read_region(&mut self, dcx
: &DecodeContext
) -> ty
::Region
{
999 // Note: regions types embed local node ids. In principle, we
1000 // should translate these node ids into the new decode
1001 // context. However, we do not bother, because region types
1002 // are not used during trans. This also applies to read_ty.
1003 return self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_region());
1005 fn read_ty
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>) -> Ty
<'tcx
> {
1006 return self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_ty());
1009 fn read_tys
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1011 self.read_to_vec(|this
| Ok(this
.read_ty(dcx
))).unwrap().into_iter().collect()
1014 fn read_trait_ref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1015 -> ty
::TraitRef
<'tcx
> {
1016 self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_trait_ref())
1019 fn read_poly_trait_ref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1020 -> ty
::PolyTraitRef
<'tcx
> {
1021 ty
::Binder(self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_trait_ref()))
1024 fn read_predicate
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1025 -> ty
::Predicate
<'tcx
>
1027 self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_predicate())
1030 fn read_existential_bounds
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1031 -> ty
::ExistentialBounds
<'tcx
>
1033 self.read_ty_encoded(dcx
, |decoder
| decoder
.parse_existential_bounds())
1036 fn read_substs
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1037 -> subst
::Substs
<'tcx
> {
1038 self.read_opaque(|this
, doc
| {
1039 Ok(tydecode
::TyDecoder
::with_doc(dcx
.tcx
, dcx
.cdata
.cnum
, doc
,
1040 &mut |a
| this
.convert_def_id(dcx
, a
))
1044 fn read_upvar_capture(&mut self, dcx
: &DecodeContext
) -> ty
::UpvarCapture
{
1045 self.read_enum("UpvarCapture", |this
| {
1046 let variants
= ["ByValue", "ByRef"];
1047 this
.read_enum_variant(&variants
, |this
, i
| {
1049 1 => ty
::UpvarCapture
::ByValue
,
1050 2 => ty
::UpvarCapture
::ByRef(ty
::UpvarBorrow
{
1051 kind
: this
.read_enum_variant_arg(0,
1052 |this
| Decodable
::decode(this
)).unwrap(),
1053 region
: this
.read_enum_variant_arg(1,
1054 |this
| Ok(this
.read_region(dcx
))).unwrap()
1056 _
=> panic
!("bad enum variant for ty::UpvarCapture")
1061 fn read_auto_adjustment
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1062 -> adjustment
::AutoAdjustment
<'tcx
> {
1063 self.read_enum("AutoAdjustment", |this
| {
1064 let variants
= ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustDerefRef"];
1065 this
.read_enum_variant(&variants
, |this
, i
| {
1067 1 => adjustment
::AdjustReifyFnPointer
,
1068 2 => adjustment
::AdjustUnsafeFnPointer
,
1070 let auto_deref_ref
: adjustment
::AutoDerefRef
=
1071 this
.read_enum_variant_arg(0,
1072 |this
| Ok(this
.read_auto_deref_ref(dcx
))).unwrap();
1074 adjustment
::AdjustDerefRef(auto_deref_ref
)
1076 _
=> panic
!("bad enum variant for adjustment::AutoAdjustment")
1082 fn read_auto_deref_ref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1083 -> adjustment
::AutoDerefRef
<'tcx
> {
1084 self.read_struct("AutoDerefRef", 2, |this
| {
1085 Ok(adjustment
::AutoDerefRef
{
1086 autoderefs
: this
.read_struct_field("autoderefs", 0, |this
| {
1087 Decodable
::decode(this
)
1089 autoref
: this
.read_struct_field("autoref", 1, |this
| {
1090 this
.read_option(|this
, b
| {
1092 Ok(Some(this
.read_autoref(dcx
)))
1098 unsize
: this
.read_struct_field("unsize", 2, |this
| {
1099 this
.read_option(|this
, b
| {
1101 Ok(Some(this
.read_ty(dcx
)))
1111 fn read_autoref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1112 -> adjustment
::AutoRef
<'tcx
> {
1113 self.read_enum("AutoRef", |this
| {
1114 let variants
= ["AutoPtr", "AutoUnsafe"];
1115 this
.read_enum_variant(&variants
, |this
, i
| {
1119 this
.read_enum_variant_arg(0, |this
| {
1120 Ok(this
.read_region(dcx
))
1122 let m
: hir
::Mutability
=
1123 this
.read_enum_variant_arg(1, |this
| {
1124 Decodable
::decode(this
)
1127 adjustment
::AutoPtr(dcx
.tcx
.mk_region(r
), m
)
1130 let m
: hir
::Mutability
=
1131 this
.read_enum_variant_arg(0, |this
| Decodable
::decode(this
)).unwrap();
1133 adjustment
::AutoUnsafe(m
)
1135 _
=> panic
!("bad enum variant for adjustment::AutoRef")
1141 fn read_cast_kind
<'b
, 'c
>(&mut self, _dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1144 Decodable
::decode(self).unwrap()
1147 /// Converts a def-id that appears in a type. The correct
1148 /// translation will depend on what kind of def-id this is.
1149 /// This is a subtle point: type definitions are not
1150 /// inlined into the current crate, so if the def-id names
1151 /// a nominal type or type alias, then it should be
1152 /// translated to refer to the source crate.
1154 /// However, *type parameters* are cloned along with the function
1155 /// they are attached to. So we should translate those def-ids
1156 /// to refer to the new, cloned copy of the type parameter.
1157 /// We only see references to free type parameters in the body of
1158 /// an inlined function. In such cases, we need the def-id to
1159 /// be a local id so that the TypeContents code is able to lookup
1160 /// the relevant info in the ty_param_defs table.
1162 /// *Region parameters*, unfortunately, are another kettle of fish.
1163 /// In such cases, def_id's can appear in types to distinguish
1164 /// shadowed bound regions and so forth. It doesn't actually
1165 /// matter so much what we do to these, since regions are erased
1166 /// at trans time, but it's good to keep them consistent just in
1167 /// case. We translate them with `tr_def_id()` which will map
1168 /// the crate numbers back to the original source crate.
1170 /// Scopes will end up as being totally bogus. This can actually
1171 /// be fixed though.
1173 /// Unboxed closures are cloned along with the function being
1174 /// inlined, and all side tables use interned node IDs, so we
1175 /// translate their def IDs accordingly.
1177 /// It'd be really nice to refactor the type repr to not include
1178 /// def-ids so that all these distinctions were unnecessary.
1179 fn convert_def_id(&mut self,
1180 dcx
: &DecodeContext
,
1183 let r
= dcx
.tr_def_id(did
);
1184 debug
!("convert_def_id(did={:?})={:?}", did
, r
);
1189 fn decode_side_tables(dcx
: &DecodeContext
,
1190 ast_doc
: rbml
::Doc
) {
1191 let tbl_doc
= ast_doc
.get(c
::tag_table
as usize);
1192 for (tag
, entry_doc
) in reader
::docs(tbl_doc
) {
1193 let mut entry_dsr
= reader
::Decoder
::new(entry_doc
);
1194 let id0
: ast
::NodeId
= Decodable
::decode(&mut entry_dsr
).unwrap();
1195 let id
= dcx
.tr_id(id0
);
1197 debug
!(">> Side table document with tag 0x{:x} \
1198 found for id {} (orig {})",
1200 let tag
= tag
as u32;
1201 let decoded_tag
: Option
<c
::astencode_tag
> = c
::astencode_tag
::from_u32(tag
);
1205 &format
!("unknown tag found in side tables: {:x}",
1209 let val_dsr
= &mut entry_dsr
;
1212 c
::tag_table_def
=> {
1213 let def
= decode_def(dcx
, val_dsr
);
1214 dcx
.tcx
.def_map
.borrow_mut().insert(id
, def
::PathResolution
{
1216 // This doesn't matter cross-crate.
1217 last_private
: LastMod(AllPublic
),
1221 c
::tag_table_node_type
=> {
1222 let ty
= val_dsr
.read_ty(dcx
);
1223 debug
!("inserting ty for node {}: {:?}",
1225 dcx
.tcx
.node_type_insert(id
, ty
);
1227 c
::tag_table_item_subst
=> {
1228 let item_substs
= ty
::ItemSubsts
{
1229 substs
: val_dsr
.read_substs(dcx
)
1231 dcx
.tcx
.tables
.borrow_mut().item_substs
.insert(
1234 c
::tag_table_freevars
=> {
1235 let fv_info
= val_dsr
.read_to_vec(|val_dsr
| {
1236 Ok(val_dsr
.read_freevar_entry(dcx
))
1237 }).unwrap().into_iter().collect();
1238 dcx
.tcx
.freevars
.borrow_mut().insert(id
, fv_info
);
1240 c
::tag_table_upvar_capture_map
=> {
1241 let var_id
: ast
::NodeId
= Decodable
::decode(val_dsr
).unwrap();
1242 let upvar_id
= ty
::UpvarId
{
1243 var_id
: dcx
.tr_id(var_id
),
1246 let ub
= val_dsr
.read_upvar_capture(dcx
);
1247 dcx
.tcx
.tables
.borrow_mut().upvar_capture_map
.insert(upvar_id
, ub
);
1249 c
::tag_table_method_map
=> {
1250 let (autoderef
, method
) = val_dsr
.read_method_callee(dcx
);
1251 let method_call
= ty
::MethodCall
{
1253 autoderef
: autoderef
1255 dcx
.tcx
.tables
.borrow_mut().method_map
.insert(method_call
, method
);
1257 c
::tag_table_adjustments
=> {
1259 val_dsr
.read_auto_adjustment(dcx
);
1260 dcx
.tcx
.tables
.borrow_mut().adjustments
.insert(id
, adj
);
1262 c
::tag_table_cast_kinds
=> {
1264 val_dsr
.read_cast_kind(dcx
);
1265 dcx
.tcx
.cast_kinds
.borrow_mut().insert(id
, cast_kind
);
1267 c
::tag_table_const_qualif
=> {
1268 let qualif
: ConstQualif
= Decodable
::decode(val_dsr
).unwrap();
1269 dcx
.tcx
.const_qualif_map
.borrow_mut().insert(id
, qualif
);
1273 &format
!("unknown tag found in side tables: {:x}",
1280 debug
!(">< Side table doc loaded");
1284 // copy the tcache entries from the original item to the new
1286 fn copy_item_types(dcx
: &DecodeContext
, ii
: &InlinedItem
, orig_did
: DefId
) {
1287 fn copy_item_type(dcx
: &DecodeContext
,
1288 inlined_id
: ast
::NodeId
,
1289 remote_did
: DefId
) {
1290 let inlined_did
= dcx
.tcx
.map
.local_def_id(inlined_id
);
1291 dcx
.tcx
.register_item_type(inlined_did
,
1292 dcx
.tcx
.lookup_item_type(remote_did
));
1295 // copy the entry for the item itself
1296 let item_node_id
= match ii
{
1297 &InlinedItem
::Item(ref i
) => i
.id
,
1298 &InlinedItem
::TraitItem(_
, ref ti
) => ti
.id
,
1299 &InlinedItem
::ImplItem(_
, ref ii
) => ii
.id
,
1300 &InlinedItem
::Foreign(ref fi
) => fi
.id
1302 copy_item_type(dcx
, item_node_id
, orig_did
);
1304 // copy the entries of inner items
1305 if let &InlinedItem
::Item(ref item
) = ii
{
1307 hir
::ItemEnum(ref def
, _
) => {
1308 let orig_def
= dcx
.tcx
.lookup_adt_def(orig_did
);
1309 for (i_variant
, orig_variant
) in
1310 def
.variants
.iter().zip(orig_def
.variants
.iter())
1312 debug
!("astencode: copying variant {:?} => {:?}",
1313 orig_variant
.did
, i_variant
.node
.data
.id());
1314 copy_item_type(dcx
, i_variant
.node
.data
.id(), orig_variant
.did
);
1317 hir
::ItemStruct(ref def
, _
) => {
1318 if !def
.is_struct() {
1319 let ctor_did
= dcx
.tcx
.lookup_adt_def(orig_did
)
1320 .struct_variant().did
;
1321 debug
!("astencode: copying ctor {:?} => {:?}", ctor_did
,
1323 copy_item_type(dcx
, def
.id(), ctor_did
);
1331 fn inlined_item_id_range(v
: &InlinedItem
) -> ast_util
::IdRange
{
1332 let mut visitor
= ast_util
::IdRangeComputingVisitor
::new();
1333 v
.visit_ids(&mut visitor
);
1337 // ______________________________________________________________________
1338 // Testing of astencode_gen
1341 fn encode_item_ast(rbml_w
: &mut Encoder
, item
: &hir
::Item
) {
1342 rbml_w
.start_tag(c
::tag_tree
as usize);
1343 (*item
).encode(rbml_w
);
1348 fn decode_item_ast(par_doc
: rbml
::Doc
) -> hir
::Item
{
1349 let chi_doc
= par_doc
.get(c
::tag_tree
as usize);
1350 let mut d
= reader
::Decoder
::new(chi_doc
);
1351 Decodable
::decode(&mut d
).unwrap()
1356 fn call_site(&self) -> codemap
::Span
;
1357 fn cfg(&self) -> ast
::CrateConfig
;
1358 fn ident_of(&self, st
: &str) -> ast
::Ident
;
1359 fn name_of(&self, st
: &str) -> ast
::Name
;
1360 fn parse_sess(&self) -> &parse
::ParseSess
;
1364 impl FakeExtCtxt
for parse
::ParseSess
{
1365 fn call_site(&self) -> codemap
::Span
{
1367 lo
: codemap
::BytePos(0),
1368 hi
: codemap
::BytePos(0),
1369 expn_id
: codemap
::NO_EXPANSION
,
1372 fn cfg(&self) -> ast
::CrateConfig { Vec::new() }
1373 fn ident_of(&self, st
: &str) -> ast
::Ident
{
1374 parse
::token
::str_to_ident(st
)
1376 fn name_of(&self, st
: &str) -> ast
::Name
{
1377 parse
::token
::intern(st
)
1379 fn parse_sess(&self) -> &parse
::ParseSess { self }
1383 struct FakeNodeIdAssigner
;
1386 // It should go without saying that this may give unexpected results. Avoid
1387 // lowering anything which needs new nodes.
1388 impl NodeIdAssigner
for FakeNodeIdAssigner
{
1389 fn next_node_id(&self) -> NodeId
{
1393 fn peek_node_id(&self) -> NodeId
{
1399 fn mk_ctxt() -> parse
::ParseSess
{
1400 parse
::ParseSess
::new()
1404 fn roundtrip(in_item
: hir
::Item
) {
1405 let mut wr
= Cursor
::new(Vec
::new());
1406 encode_item_ast(&mut Encoder
::new(&mut wr
), &in_item
);
1407 let rbml_doc
= rbml
::Doc
::new(wr
.get_ref());
1408 let out_item
= decode_item_ast(rbml_doc
);
1410 assert
!(in_item
== out_item
);
1416 let fnia
= FakeNodeIdAssigner
;
1417 let lcx
= LoweringContext
::new(&fnia
, None
);
1418 roundtrip(lower_item(&lcx
, "e_item
!(&cx
,
1424 fn test_smalltalk() {
1426 let fnia
= FakeNodeIdAssigner
;
1427 let lcx
= LoweringContext
::new(&fnia
, None
);
1428 roundtrip(lower_item(&lcx
, "e_item
!(&cx
,
1429 fn foo() -> isize { 3 + 4 }
// first smalltalk program ever executed.
1436 let fnia
= FakeNodeIdAssigner
;
1437 let lcx
= LoweringContext
::new(&fnia
, None
);
1438 roundtrip(lower_item(&lcx
, "e_item
!(&cx
,
1439 fn foo(x
: usize, y
: usize) -> usize {
1447 fn test_simplification() {
1449 let item
= quote_item
!(&cx
,
1450 fn new_int_alist
<B
>() -> alist
<isize, B
> {
1451 fn eq_int(a
: isize, b
: isize) -> bool { a == b }
1452 return alist {eq_fn: eq_int, data: Vec::new()}
;
1455 let fnia
= FakeNodeIdAssigner
;
1456 let lcx
= LoweringContext
::new(&fnia
, None
);
1457 let hir_item
= lower_item(&lcx
, &item
);
1458 let item_in
= InlinedItemRef
::Item(&hir_item
);
1459 let item_out
= simplify_ast(item_in
);
1460 let item_exp
= InlinedItem
::Item(P(lower_item(&lcx
, "e_item
!(&cx
,
1461 fn new_int_alist
<B
>() -> alist
<isize, B
> {
1462 return alist {eq_fn: eq_int, data: Vec::new()}
;
1465 match (item_out
, item_exp
) {
1466 (InlinedItem
::Item(item_out
), InlinedItem
::Item(item_exp
)) => {
1467 assert
!(pprust
::item_to_string(&*item_out
) ==
1468 pprust
::item_to_string(&*item_exp
));