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 metadata
::common
as c
;
16 use metadata
::cstore
as cstore
;
18 use metadata
::decoder
;
20 use metadata
::encoder
as e
;
22 use metadata
::tydecode
;
23 use metadata
::tydecode
::{DefIdSource, NominalType, TypeWithId, TypeParameter}
;
24 use metadata
::tydecode
::{RegionParameter, ClosureSource}
;
25 use metadata
::tyencode
;
26 use middle
::check_const
::ConstQualif
;
27 use middle
::mem_categorization
::Typer
;
28 use middle
::privacy
::{AllPublic, LastMod}
;
30 use middle
::subst
::VecPerParamSpace
;
31 use middle
::ty
::{self, Ty, MethodCall, MethodCallee, MethodOrigin}
;
32 use util
::ppaux
::ty_to_string
;
34 use syntax
::{ast, ast_map, ast_util, codemap, fold}
;
35 use syntax
::codemap
::Span
;
36 use syntax
::fold
::Folder
;
37 use syntax
::parse
::token
;
42 use std
::io
::SeekFrom
;
43 use std
::io
::prelude
::*;
47 use rbml
::writer
::Encoder
;
50 use serialize
::{Decodable, Decoder, DecoderHelpers, Encodable}
;
51 use serialize
::EncoderHelpers
;
53 #[cfg(test)] use std::io::Cursor;
54 #[cfg(test)] use syntax::parse;
55 #[cfg(test)] use syntax::print::pprust;
57 struct DecodeContext
<'a
, 'b
, 'tcx
: 'a
> {
58 tcx
: &'a ty
::ctxt
<'tcx
>,
59 cdata
: &'b cstore
::crate_metadata
,
60 from_id_range
: ast_util
::IdRange
,
61 to_id_range
: ast_util
::IdRange
,
62 // Cache the last used filemap for translating spans as an optimization.
63 last_filemap_index
: Cell
<usize>,
67 fn tr(&self, dcx
: &DecodeContext
) -> Self;
71 fn tr_intern(&self, dcx
: &DecodeContext
) -> ast
::DefId
;
74 // ______________________________________________________________________
77 pub fn encode_inlined_item(ecx
: &e
::EncodeContext
,
79 ii
: e
::InlinedItemRef
) {
81 e
::IIItemRef(i
) => i
.id
,
82 e
::IIForeignRef(i
) => i
.id
,
83 e
::IITraitItemRef(_
, ti
) => ti
.id
,
84 e
::IIImplItemRef(_
, ii
) => ii
.id
,
86 debug
!("> Encoding inlined item: {} ({:?})",
87 ecx
.tcx
.map
.path_to_string(id
),
88 rbml_w
.writer
.seek(SeekFrom
::Current(0)));
90 // Folding could be avoided with a smarter encoder.
91 let ii
= simplify_ast(ii
);
92 let id_range
= ast_util
::compute_id_range_for_inlined_item(&ii
);
94 rbml_w
.start_tag(c
::tag_ast
as usize);
95 id_range
.encode(rbml_w
);
96 encode_ast(rbml_w
, &ii
);
97 encode_side_tables_for_ii(ecx
, rbml_w
, &ii
);
100 debug
!("< Encoded inlined fn: {} ({:?})",
101 ecx
.tcx
.map
.path_to_string(id
),
102 rbml_w
.writer
.seek(SeekFrom
::Current(0)));
105 impl<'a
, 'b
, 'c
, 'tcx
> ast_map
::FoldOps
for &'a DecodeContext
<'b
, 'c
, 'tcx
> {
106 fn new_id(&self, id
: ast
::NodeId
) -> ast
::NodeId
{
107 if id
== ast
::DUMMY_NODE_ID
{
108 // Used by ast_map to map the NodeInlinedParent.
109 self.tcx
.sess
.next_node_id()
114 fn new_def_id(&self, def_id
: ast
::DefId
) -> ast
::DefId
{
115 self.tr_def_id(def_id
)
117 fn new_span(&self, span
: Span
) -> Span
{
122 /// Decodes an item from its AST in the cdata's metadata and adds it to the
124 pub fn decode_inlined_item
<'tcx
>(cdata
: &cstore
::crate_metadata
,
125 tcx
: &ty
::ctxt
<'tcx
>,
126 path
: Vec
<ast_map
::PathElem
>,
128 -> Result
<&'tcx ast
::InlinedItem
, Vec
<ast_map
::PathElem
>> {
129 match par_doc
.opt_child(c
::tag_ast
) {
132 let mut path_as_str
= None
;
133 debug
!("> Decoding inlined fn: {:?}::?",
135 // Do an Option dance to use the path after it is moved below.
136 let s
= ast_map
::path_to_string(path
.iter().cloned());
137 path_as_str
= Some(s
);
138 path_as_str
.as_ref().map(|x
| &x
[..])
140 let mut ast_dsr
= reader
::Decoder
::new(ast_doc
);
141 let from_id_range
= Decodable
::decode(&mut ast_dsr
).unwrap();
142 let to_id_range
= reserve_id_range(&tcx
.sess
, from_id_range
);
143 let dcx
= &DecodeContext
{
146 from_id_range
: from_id_range
,
147 to_id_range
: to_id_range
,
148 last_filemap_index
: Cell
::new(0)
150 let raw_ii
= decode_ast(ast_doc
);
151 let ii
= ast_map
::map_decoded_item(&dcx
.tcx
.map
, path
, raw_ii
, dcx
);
153 let ident
= match *ii
{
154 ast
::IIItem(ref i
) => i
.ident
,
155 ast
::IIForeign(ref i
) => i
.ident
,
156 ast
::IITraitItem(_
, ref ti
) => ti
.ident
,
157 ast
::IIImplItem(_
, ref ii
) => ii
.ident
159 debug
!("Fn named: {}", token
::get_ident(ident
));
160 debug
!("< Decoded inlined fn: {}::{}",
161 path_as_str
.unwrap(),
162 token
::get_ident(ident
));
163 region
::resolve_inlined_item(&tcx
.sess
, &tcx
.region_maps
, ii
);
164 decode_side_tables(dcx
, ast_doc
);
166 ast
::IIItem(ref i
) => {
167 debug
!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
168 syntax
::print
::pprust
::item_to_string(&**i
));
177 // ______________________________________________________________________
178 // Enumerating the IDs which appear in an AST
180 fn reserve_id_range(sess
: &Session
,
181 from_id_range
: ast_util
::IdRange
) -> ast_util
::IdRange
{
182 // Handle the case of an empty range:
183 if from_id_range
.empty() { return from_id_range; }
184 let cnt
= from_id_range
.max
- from_id_range
.min
;
185 let to_id_min
= sess
.reserve_node_ids(cnt
);
186 let to_id_max
= to_id_min
+ cnt
;
187 ast_util
::IdRange { min: to_id_min, max: to_id_max }
190 impl<'a
, 'b
, 'tcx
> DecodeContext
<'a
, 'b
, 'tcx
> {
191 /// Translates an internal id, meaning a node id that is known to refer to some part of the
192 /// item currently being inlined, such as a local variable or argument. All naked node-ids
193 /// that appear in types have this property, since if something might refer to an external item
194 /// we would use a def-id to allow for the possibility that the item resides in another crate.
195 pub fn tr_id(&self, id
: ast
::NodeId
) -> ast
::NodeId
{
196 // from_id_range should be non-empty
197 assert
!(!self.from_id_range
.empty());
198 // Use wrapping arithmetic because otherwise it introduces control flow.
199 // Maybe we should just have the control flow? -- aatch
200 (id
.wrapping_sub(self.from_id_range
.min
).wrapping_add(self.to_id_range
.min
))
203 /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
204 /// data to the current crate numbers.. By external, I mean that it be translated to a
205 /// reference to the item in its original crate, as opposed to being translated to a reference
206 /// to the inlined version of the item. This is typically, but not always, what you want,
207 /// because most def-ids refer to external things like types or other fns that may or may not
208 /// be inlined. Note that even when the inlined function is referencing itself recursively, we
209 /// would want `tr_def_id` for that reference--- conceptually the function calls the original,
210 /// non-inlined version, and trans deals with linking that recursive call to the inlined copy.
212 /// However, there are a *few* cases where def-ids are used but we know that the thing being
213 /// referenced is in fact *internal* to the item being inlined. In those cases, you should use
214 /// `tr_intern_def_id()` below.
215 pub fn tr_def_id(&self, did
: ast
::DefId
) -> ast
::DefId
{
217 decoder
::translate_def_id(self.cdata
, did
)
220 /// Translates an INTERNAL def-id, meaning a def-id that is
221 /// known to refer to some part of the item currently being
222 /// inlined. In that case, we want to convert the def-id to
223 /// refer to the current crate and to the new, inlined node-id.
224 pub fn tr_intern_def_id(&self, did
: ast
::DefId
) -> ast
::DefId
{
225 assert_eq
!(did
.krate
, ast
::LOCAL_CRATE
);
226 ast
::DefId { krate: ast::LOCAL_CRATE, node: self.tr_id(did.node) }
229 /// Translates a `Span` from an extern crate to the corresponding `Span`
230 /// within the local crate's codemap. `creader::import_codemap()` will
231 /// already have allocated any additionally needed FileMaps in the local
232 /// codemap as a side-effect of creating the crate_metadata's
233 /// `codemap_import_info`.
234 pub fn tr_span(&self, span
: Span
) -> Span
{
235 let imported_filemaps
= &self.cdata
.codemap_import_info
[..];
237 let span
= if span
.lo
> span
.hi
{
238 // Currently macro expansion sometimes produces invalid Span values
239 // where lo > hi. In order not to crash the compiler when trying to
240 // translate these values, let's transform them into something we
241 // can handle (and which will produce useful debug locations at
242 // least some of the time).
243 // This workaround is only necessary as long as macro expansion is
244 // not fixed. FIXME(#23480)
245 codemap
::mk_sp(span
.lo
, span
.lo
)
250 let filemap_index
= {
251 // Optimize for the case that most spans within a translated item
252 // originate from the same filemap.
253 let last_filemap_index
= self.last_filemap_index
.get();
255 if span
.lo
>= imported_filemaps
[last_filemap_index
].original_start_pos
&&
256 span
.lo
<= imported_filemaps
[last_filemap_index
].original_end_pos
&&
257 span
.hi
>= imported_filemaps
[last_filemap_index
].original_start_pos
&&
258 span
.hi
<= imported_filemaps
[last_filemap_index
].original_end_pos
{
262 let mut b
= imported_filemaps
.len();
266 if imported_filemaps
[m
].original_start_pos
> span
.lo
{
273 self.last_filemap_index
.set(a
);
278 let lo
= (span
.lo
- imported_filemaps
[filemap_index
].original_start_pos
) +
279 imported_filemaps
[filemap_index
].translated_filemap
.start_pos
;
280 let hi
= (span
.hi
- imported_filemaps
[filemap_index
].original_start_pos
) +
281 imported_filemaps
[filemap_index
].translated_filemap
.start_pos
;
283 codemap
::mk_sp(lo
, hi
)
287 impl tr_intern
for ast
::DefId
{
288 fn tr_intern(&self, dcx
: &DecodeContext
) -> ast
::DefId
{
289 dcx
.tr_intern_def_id(*self)
293 impl tr
for ast
::DefId
{
294 fn tr(&self, dcx
: &DecodeContext
) -> ast
::DefId
{
299 impl tr
for Option
<ast
::DefId
> {
300 fn tr(&self, dcx
: &DecodeContext
) -> Option
<ast
::DefId
> {
301 self.map(|d
| dcx
.tr_def_id(d
))
306 fn tr(&self, dcx
: &DecodeContext
) -> Span
{
311 trait def_id_encoder_helpers
{
312 fn emit_def_id(&mut self, did
: ast
::DefId
);
315 impl<S
:serialize
::Encoder
> def_id_encoder_helpers
for S
316 where <S
as serialize
::serialize
::Encoder
>::Error
: Debug
318 fn emit_def_id(&mut self, did
: ast
::DefId
) {
319 did
.encode(self).unwrap()
323 trait def_id_decoder_helpers
{
324 fn read_def_id(&mut self, dcx
: &DecodeContext
) -> ast
::DefId
;
325 fn read_def_id_nodcx(&mut self,
326 cdata
: &cstore
::crate_metadata
) -> ast
::DefId
;
329 impl<D
:serialize
::Decoder
> def_id_decoder_helpers
for D
330 where <D
as serialize
::serialize
::Decoder
>::Error
: Debug
332 fn read_def_id(&mut self, dcx
: &DecodeContext
) -> ast
::DefId
{
333 let did
: ast
::DefId
= Decodable
::decode(self).unwrap();
337 fn read_def_id_nodcx(&mut self,
338 cdata
: &cstore
::crate_metadata
)
340 let did
: ast
::DefId
= Decodable
::decode(self).unwrap();
341 decoder
::translate_def_id(cdata
, did
)
345 // ______________________________________________________________________
346 // Encoding and decoding the AST itself
348 // The hard work is done by an autogenerated module astencode_gen. To
349 // regenerate astencode_gen, run src/etc/gen-astencode. It will
350 // replace astencode_gen with a dummy file and regenerate its
351 // contents. If you get compile errors, the dummy file
352 // remains---resolve the errors and then rerun astencode_gen.
353 // Annoying, I know, but hopefully only temporary.
355 // When decoding, we have to renumber the AST so that the node ids that
356 // appear within are disjoint from the node ids in our existing ASTs.
357 // We also have to adjust the spans: for now we just insert a dummy span,
358 // but eventually we should add entries to the local codemap as required.
360 fn encode_ast(rbml_w
: &mut Encoder
, item
: &ast
::InlinedItem
) {
361 rbml_w
.start_tag(c
::tag_tree
as usize);
366 struct NestedItemsDropper
;
368 impl Folder
for NestedItemsDropper
{
369 fn fold_block(&mut self, blk
: P
<ast
::Block
>) -> P
<ast
::Block
> {
370 blk
.and_then(|ast
::Block {id, stmts, expr, rules, span, ..}
| {
371 let stmts_sans_items
= stmts
.into_iter().filter_map(|stmt
| {
372 let use_stmt
= match stmt
.node
{
373 ast
::StmtExpr(_
, _
) | ast
::StmtSemi(_
, _
) => true,
374 ast
::StmtDecl(ref decl
, _
) => {
376 ast
::DeclLocal(_
) => true,
377 ast
::DeclItem(_
) => false,
380 ast
::StmtMac(..) => panic
!("unexpanded macro in astencode")
388 let blk_sans_items
= P(ast
::Block
{
389 stmts
: stmts_sans_items
,
395 fold
::noop_fold_block(blk_sans_items
, self)
400 // Produces a simplified copy of the AST which does not include things
401 // that we do not need to or do not want to export. For example, we
402 // do not include any nested items: if these nested items are to be
403 // inlined, their AST will be exported separately (this only makes
404 // sense because, in Rust, nested items are independent except for
405 // their visibility).
407 // As it happens, trans relies on the fact that we do not export
408 // nested items, as otherwise it would get confused when translating
410 fn simplify_ast(ii
: e
::InlinedItemRef
) -> ast
::InlinedItem
{
411 let mut fld
= NestedItemsDropper
;
414 // HACK we're not dropping items.
416 ast
::IIItem(fold
::noop_fold_item(P(i
.clone()), &mut fld
)
417 .expect_one("expected one item"))
419 e
::IITraitItemRef(d
, ti
) => {
421 fold
::noop_fold_trait_item(P(ti
.clone()), &mut fld
)
422 .expect_one("noop_fold_trait_item must produce \
423 exactly one trait item"))
425 e
::IIImplItemRef(d
, ii
) => {
427 fold
::noop_fold_impl_item(P(ii
.clone()), &mut fld
)
428 .expect_one("noop_fold_impl_item must produce \
429 exactly one impl item"))
431 e
::IIForeignRef(i
) => {
432 ast
::IIForeign(fold
::noop_fold_foreign_item(P(i
.clone()), &mut fld
))
437 fn decode_ast(par_doc
: rbml
::Doc
) -> ast
::InlinedItem
{
438 let chi_doc
= par_doc
.get(c
::tag_tree
as usize);
439 let mut d
= reader
::Decoder
::new(chi_doc
);
440 Decodable
::decode(&mut d
).unwrap()
443 // ______________________________________________________________________
444 // Encoding and decoding of ast::def
446 fn decode_def(dcx
: &DecodeContext
, dsr
: &mut reader
::Decoder
) -> def
::Def
{
447 let def
: def
::Def
= Decodable
::decode(dsr
).unwrap();
451 impl tr
for def
::Def
{
452 fn tr(&self, dcx
: &DecodeContext
) -> def
::Def
{
454 def
::DefFn(did
, is_ctor
) => def
::DefFn(did
.tr(dcx
), is_ctor
),
455 def
::DefMethod(did
, p
) => {
456 def
::DefMethod(did
.tr(dcx
), p
.map(|did2
| did2
.tr(dcx
)))
458 def
::DefSelfTy(opt_did
, impl_ids
) => { def
::DefSelfTy(opt_did
.map(|did
| did
.tr(dcx
)),
459 impl_ids
.map(|(nid1
, nid2
)| {
463 def
::DefMod(did
) => { def::DefMod(did.tr(dcx)) }
464 def
::DefForeignMod(did
) => { def::DefForeignMod(did.tr(dcx)) }
465 def
::DefStatic(did
, m
) => { def::DefStatic(did.tr(dcx), m) }
466 def
::DefConst(did
) => { def::DefConst(did.tr(dcx)) }
467 def
::DefAssociatedConst(did
, p
) => {
468 def
::DefAssociatedConst(did
.tr(dcx
), p
.map(|did2
| did2
.tr(dcx
)))
470 def
::DefLocal(nid
) => { def::DefLocal(dcx.tr_id(nid)) }
471 def
::DefVariant(e_did
, v_did
, is_s
) => {
472 def
::DefVariant(e_did
.tr(dcx
), v_did
.tr(dcx
), is_s
)
474 def
::DefTrait(did
) => def
::DefTrait(did
.tr(dcx
)),
475 def
::DefTy(did
, is_enum
) => def
::DefTy(did
.tr(dcx
), is_enum
),
476 def
::DefAssociatedTy(trait_did
, did
) =>
477 def
::DefAssociatedTy(trait_did
.tr(dcx
), did
.tr(dcx
)),
478 def
::DefPrimTy(p
) => def
::DefPrimTy(p
),
479 def
::DefTyParam(s
, index
, def_id
, n
) => def
::DefTyParam(s
, index
, def_id
.tr(dcx
), n
),
480 def
::DefUse(did
) => def
::DefUse(did
.tr(dcx
)),
481 def
::DefUpvar(nid1
, nid2
) => {
482 def
::DefUpvar(dcx
.tr_id(nid1
), dcx
.tr_id(nid2
))
484 def
::DefStruct(did
) => def
::DefStruct(did
.tr(dcx
)),
485 def
::DefRegion(nid
) => def
::DefRegion(dcx
.tr_id(nid
)),
486 def
::DefLabel(nid
) => def
::DefLabel(dcx
.tr_id(nid
))
491 // ______________________________________________________________________
492 // Encoding and decoding of ancillary information
494 impl tr
for ty
::Region
{
495 fn tr(&self, dcx
: &DecodeContext
) -> ty
::Region
{
497 ty
::ReLateBound(debruijn
, br
) => {
498 ty
::ReLateBound(debruijn
, br
.tr(dcx
))
500 ty
::ReEarlyBound(data
) => {
501 ty
::ReEarlyBound(ty
::EarlyBoundRegion
{
502 param_id
: dcx
.tr_id(data
.param_id
),
508 ty
::ReScope(scope
) => {
509 ty
::ReScope(scope
.tr(dcx
))
511 ty
::ReEmpty
| ty
::ReStatic
| ty
::ReInfer(..) => {
514 ty
::ReFree(ref fr
) => {
515 ty
::ReFree(fr
.tr(dcx
))
521 impl tr
for ty
::FreeRegion
{
522 fn tr(&self, dcx
: &DecodeContext
) -> ty
::FreeRegion
{
523 ty
::FreeRegion
{ scope
: self.scope
.tr(dcx
),
524 bound_region
: self.bound_region
.tr(dcx
) }
528 impl tr
for region
::CodeExtent
{
529 fn tr(&self, dcx
: &DecodeContext
) -> region
::CodeExtent
{
530 self.map_id(|id
| dcx
.tr_id(id
))
534 impl tr
for region
::DestructionScopeData
{
535 fn tr(&self, dcx
: &DecodeContext
) -> region
::DestructionScopeData
{
536 region
::DestructionScopeData { node_id: dcx.tr_id(self.node_id) }
540 impl tr
for ty
::BoundRegion
{
541 fn tr(&self, dcx
: &DecodeContext
) -> ty
::BoundRegion
{
546 ty
::BrNamed(id
, ident
) => ty
::BrNamed(dcx
.tr_def_id(id
),
552 // ______________________________________________________________________
553 // Encoding and decoding of freevar information
555 fn encode_freevar_entry(rbml_w
: &mut Encoder
, fv
: &ty
::Freevar
) {
556 (*fv
).encode(rbml_w
).unwrap();
559 trait rbml_decoder_helper
{
560 fn read_freevar_entry(&mut self, dcx
: &DecodeContext
)
562 fn read_capture_mode(&mut self) -> ast
::CaptureClause
;
565 impl<'a
> rbml_decoder_helper
for reader
::Decoder
<'a
> {
566 fn read_freevar_entry(&mut self, dcx
: &DecodeContext
)
568 let fv
: ty
::Freevar
= Decodable
::decode(self).unwrap();
572 fn read_capture_mode(&mut self) -> ast
::CaptureClause
{
573 let cm
: ast
::CaptureClause
= Decodable
::decode(self).unwrap();
578 impl tr
for ty
::Freevar
{
579 fn tr(&self, dcx
: &DecodeContext
) -> ty
::Freevar
{
581 def
: self.def
.tr(dcx
),
582 span
: self.span
.tr(dcx
),
587 impl tr
for ty
::UpvarBorrow
{
588 fn tr(&self, dcx
: &DecodeContext
) -> ty
::UpvarBorrow
{
591 region
: self.region
.tr(dcx
)
596 impl tr
for ty
::UpvarCapture
{
597 fn tr(&self, dcx
: &DecodeContext
) -> ty
::UpvarCapture
{
599 ty
::UpvarCapture
::ByValue
=> ty
::UpvarCapture
::ByValue
,
600 ty
::UpvarCapture
::ByRef(ref data
) => ty
::UpvarCapture
::ByRef(data
.tr(dcx
)),
605 // ______________________________________________________________________
606 // Encoding and decoding of MethodCallee
608 trait read_method_callee_helper
<'tcx
> {
609 fn read_method_callee
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
610 -> (u32, MethodCallee
<'tcx
>);
613 fn encode_method_callee
<'a
, 'tcx
>(ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
614 rbml_w
: &mut Encoder
,
616 method
: &MethodCallee
<'tcx
>) {
617 use serialize
::Encoder
;
619 rbml_w
.emit_struct("MethodCallee", 4, |rbml_w
| {
620 rbml_w
.emit_struct_field("autoderef", 0, |rbml_w
| {
621 autoderef
.encode(rbml_w
)
623 rbml_w
.emit_struct_field("origin", 1, |rbml_w
| {
624 Ok(rbml_w
.emit_method_origin(ecx
, &method
.origin
))
626 rbml_w
.emit_struct_field("ty", 2, |rbml_w
| {
627 Ok(rbml_w
.emit_ty(ecx
, method
.ty
))
629 rbml_w
.emit_struct_field("substs", 3, |rbml_w
| {
630 Ok(rbml_w
.emit_substs(ecx
, &method
.substs
))
635 impl<'a
, 'tcx
> read_method_callee_helper
<'tcx
> for reader
::Decoder
<'a
> {
636 fn read_method_callee
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
637 -> (u32, MethodCallee
<'tcx
>) {
639 self.read_struct("MethodCallee", 4, |this
| {
640 let autoderef
= this
.read_struct_field("autoderef", 0, |this
| {
641 Decodable
::decode(this
)
643 Ok((autoderef
, MethodCallee
{
644 origin
: this
.read_struct_field("origin", 1, |this
| {
645 Ok(this
.read_method_origin(dcx
))
647 ty
: this
.read_struct_field("ty", 2, |this
| {
648 Ok(this
.read_ty(dcx
))
650 substs
: this
.read_struct_field("substs", 3, |this
| {
651 Ok(this
.read_substs(dcx
))
658 impl<'tcx
> tr
for MethodOrigin
<'tcx
> {
659 fn tr(&self, dcx
: &DecodeContext
) -> MethodOrigin
<'tcx
> {
661 ty
::MethodStatic(did
) => ty
::MethodStatic(did
.tr(dcx
)),
662 ty
::MethodStaticClosure(did
) => {
663 ty
::MethodStaticClosure(did
.tr(dcx
))
665 ty
::MethodTypeParam(ref mp
) => {
668 // def-id is already translated when we read it out
669 trait_ref
: mp
.trait_ref
.clone(),
670 method_num
: mp
.method_num
,
671 impl_def_id
: mp
.impl_def_id
.tr(dcx
),
675 ty
::MethodTraitObject(ref mo
) => {
676 ty
::MethodTraitObject(
678 trait_ref
: mo
.trait_ref
.clone(),
687 pub fn encode_closure_kind(ebml_w
: &mut Encoder
, kind
: ty
::ClosureKind
) {
688 kind
.encode(ebml_w
).unwrap();
691 pub trait vtable_decoder_helpers
<'tcx
> {
692 fn read_vec_per_param_space
<T
, F
>(&mut self, f
: F
) -> VecPerParamSpace
<T
> where
693 F
: FnMut(&mut Self) -> T
;
694 fn read_vtable_res_with_key(&mut self,
695 tcx
: &ty
::ctxt
<'tcx
>,
696 cdata
: &cstore
::crate_metadata
)
697 -> (u32, ty
::vtable_res
<'tcx
>);
698 fn read_vtable_res(&mut self,
699 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
)
700 -> ty
::vtable_res
<'tcx
>;
701 fn read_vtable_param_res(&mut self,
702 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
)
703 -> ty
::vtable_param_res
<'tcx
>;
704 fn read_vtable_origin(&mut self,
705 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
)
706 -> ty
::vtable_origin
<'tcx
>;
709 impl<'tcx
, 'a
> vtable_decoder_helpers
<'tcx
> for reader
::Decoder
<'a
> {
710 fn read_vec_per_param_space
<T
, F
>(&mut self, mut f
: F
) -> VecPerParamSpace
<T
> where
711 F
: FnMut(&mut reader
::Decoder
<'a
>) -> T
,
713 let types
= self.read_to_vec(|this
| Ok(f(this
))).unwrap();
714 let selfs
= self.read_to_vec(|this
| Ok(f(this
))).unwrap();
715 let fns
= self.read_to_vec(|this
| Ok(f(this
))).unwrap();
716 VecPerParamSpace
::new(types
, selfs
, fns
)
719 fn read_vtable_res_with_key(&mut self,
720 tcx
: &ty
::ctxt
<'tcx
>,
721 cdata
: &cstore
::crate_metadata
)
722 -> (u32, ty
::vtable_res
<'tcx
>) {
723 self.read_struct("VtableWithKey", 2, |this
| {
724 let autoderef
= this
.read_struct_field("autoderef", 0, |this
| {
725 Decodable
::decode(this
)
727 Ok((autoderef
, this
.read_struct_field("vtable_res", 1, |this
| {
728 Ok(this
.read_vtable_res(tcx
, cdata
))
733 fn read_vtable_res(&mut self,
734 tcx
: &ty
::ctxt
<'tcx
>,
735 cdata
: &cstore
::crate_metadata
)
736 -> ty
::vtable_res
<'tcx
>
738 self.read_vec_per_param_space(
739 |this
| this
.read_vtable_param_res(tcx
, cdata
))
742 fn read_vtable_param_res(&mut self,
743 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
)
744 -> ty
::vtable_param_res
<'tcx
> {
745 self.read_to_vec(|this
| Ok(this
.read_vtable_origin(tcx
, cdata
)))
746 .unwrap().into_iter().collect()
749 fn read_vtable_origin(&mut self,
750 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
)
751 -> ty
::vtable_origin
<'tcx
> {
752 self.read_enum("vtable_origin", |this
| {
753 this
.read_enum_variant(&["vtable_static",
761 this
.read_enum_variant_arg(0, |this
| {
762 Ok(this
.read_def_id_nodcx(cdata
))
764 this
.read_enum_variant_arg(1, |this
| {
765 Ok(this
.read_substs_nodcx(tcx
, cdata
))
767 this
.read_enum_variant_arg(2, |this
| {
768 Ok(this
.read_vtable_res(tcx
, cdata
))
774 this
.read_enum_variant_arg(0, |this
| {
775 Decodable
::decode(this
)
777 this
.read_enum_variant_arg(1, |this
| {
784 this
.read_enum_variant_arg(0, |this
| {
785 Ok(this
.read_def_id_nodcx(cdata
))
792 _
=> panic
!("bad enum variant")
799 // ___________________________________________________________________________
802 fn encode_vec_per_param_space
<T
, F
>(rbml_w
: &mut Encoder
,
803 v
: &subst
::VecPerParamSpace
<T
>,
805 F
: FnMut(&mut Encoder
, &T
),
807 for &space
in &subst
::ParamSpace
::all() {
808 rbml_w
.emit_from_vec(v
.get_slice(space
),
809 |rbml_w
, n
| Ok(f(rbml_w
, n
))).unwrap();
813 // ______________________________________________________________________
814 // Encoding and decoding the side tables
816 trait get_ty_str_ctxt
<'tcx
> {
817 fn ty_str_ctxt
<'a
>(&'a
self) -> tyencode
::ctxt
<'a
, 'tcx
>;
820 impl<'a
, 'tcx
> get_ty_str_ctxt
<'tcx
> for e
::EncodeContext
<'a
, 'tcx
> {
821 fn ty_str_ctxt
<'b
>(&'b
self) -> tyencode
::ctxt
<'b
, 'tcx
> {
823 diag
: self.tcx
.sess
.diagnostic(),
824 ds
: e
::def_to_string
,
826 abbrevs
: &self.type_abbrevs
831 trait rbml_writer_helpers
<'tcx
> {
832 fn emit_closure_type
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
833 closure_type
: &ty
::ClosureTy
<'tcx
>);
834 fn emit_method_origin
<'a
>(&mut self,
835 ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
836 method_origin
: &ty
::MethodOrigin
<'tcx
>);
837 fn emit_ty
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>);
838 fn emit_tys
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>, tys
: &[Ty
<'tcx
>]);
839 fn emit_type_param_def
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
840 type_param_def
: &ty
::TypeParameterDef
<'tcx
>);
841 fn emit_predicate
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
842 predicate
: &ty
::Predicate
<'tcx
>);
843 fn emit_trait_ref
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
844 ty
: &ty
::TraitRef
<'tcx
>);
845 fn emit_type_scheme
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
846 type_scheme
: ty
::TypeScheme
<'tcx
>);
847 fn emit_substs
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
848 substs
: &subst
::Substs
<'tcx
>);
849 fn emit_existential_bounds
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
,'tcx
>,
850 bounds
: &ty
::ExistentialBounds
<'tcx
>);
851 fn emit_builtin_bounds(&mut self, ecx
: &e
::EncodeContext
, bounds
: &ty
::BuiltinBounds
);
852 fn emit_auto_adjustment
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
853 adj
: &ty
::AutoAdjustment
<'tcx
>);
854 fn emit_autoref
<'a
>(&mut self, autoref
: &ty
::AutoRef
<'tcx
>);
855 fn emit_auto_deref_ref
<'a
>(&mut self, ecx
: &e
::EncodeContext
<'a
, 'tcx
>,
856 auto_deref_ref
: &ty
::AutoDerefRef
<'tcx
>);
859 impl<'a
, 'tcx
> rbml_writer_helpers
<'tcx
> for Encoder
<'a
> {
860 fn emit_closure_type
<'b
>(&mut self,
861 ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
862 closure_type
: &ty
::ClosureTy
<'tcx
>) {
863 self.emit_opaque(|this
| {
864 Ok(e
::write_closure_type(ecx
, this
, closure_type
))
868 fn emit_method_origin
<'b
>(&mut self,
869 ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
870 method_origin
: &ty
::MethodOrigin
<'tcx
>)
872 use serialize
::Encoder
;
874 self.emit_enum("MethodOrigin", |this
| {
875 match *method_origin
{
876 ty
::MethodStatic(def_id
) => {
877 this
.emit_enum_variant("MethodStatic", 0, 1, |this
| {
878 Ok(this
.emit_def_id(def_id
))
882 ty
::MethodStaticClosure(def_id
) => {
883 this
.emit_enum_variant("MethodStaticClosure", 1, 1, |this
| {
884 Ok(this
.emit_def_id(def_id
))
888 ty
::MethodTypeParam(ref p
) => {
889 this
.emit_enum_variant("MethodTypeParam", 2, 1, |this
| {
890 this
.emit_struct("MethodParam", 2, |this
| {
891 try
!(this
.emit_struct_field("trait_ref", 0, |this
| {
892 Ok(this
.emit_trait_ref(ecx
, &p
.trait_ref
))
894 try
!(this
.emit_struct_field("method_num", 0, |this
| {
895 this
.emit_uint(p
.method_num
)
897 try
!(this
.emit_struct_field("impl_def_id", 0, |this
| {
898 this
.emit_option(|this
| {
899 match p
.impl_def_id
{
900 None
=> this
.emit_option_none(),
901 Some(did
) => this
.emit_option_some(|this
| {
902 Ok(this
.emit_def_id(did
))
912 ty
::MethodTraitObject(ref o
) => {
913 this
.emit_enum_variant("MethodTraitObject", 3, 1, |this
| {
914 this
.emit_struct("MethodObject", 2, |this
| {
915 try
!(this
.emit_struct_field("trait_ref", 0, |this
| {
916 Ok(this
.emit_trait_ref(ecx
, &o
.trait_ref
))
918 try
!(this
.emit_struct_field("object_trait_id", 0, |this
| {
919 Ok(this
.emit_def_id(o
.object_trait_id
))
921 try
!(this
.emit_struct_field("method_num", 0, |this
| {
922 this
.emit_uint(o
.method_num
)
924 try
!(this
.emit_struct_field("vtable_index", 0, |this
| {
925 this
.emit_uint(o
.vtable_index
)
935 fn emit_ty
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>, ty
: Ty
<'tcx
>) {
936 self.emit_opaque(|this
| Ok(e
::write_type(ecx
, this
, ty
)));
939 fn emit_tys
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>, tys
: &[Ty
<'tcx
>]) {
940 self.emit_from_vec(tys
, |this
, ty
| Ok(this
.emit_ty(ecx
, *ty
)));
943 fn emit_trait_ref
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
944 trait_ref
: &ty
::TraitRef
<'tcx
>) {
945 self.emit_opaque(|this
| Ok(e
::write_trait_ref(ecx
, this
, trait_ref
)));
948 fn emit_type_param_def
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
949 type_param_def
: &ty
::TypeParameterDef
<'tcx
>) {
950 self.emit_opaque(|this
| {
951 Ok(tyencode
::enc_type_param_def(this
,
957 fn emit_predicate
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
958 predicate
: &ty
::Predicate
<'tcx
>) {
959 self.emit_opaque(|this
| {
960 Ok(tyencode
::enc_predicate(this
,
966 fn emit_type_scheme
<'b
>(&mut self,
967 ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
968 type_scheme
: ty
::TypeScheme
<'tcx
>) {
969 use serialize
::Encoder
;
971 self.emit_struct("TypeScheme", 2, |this
| {
972 this
.emit_struct_field("generics", 0, |this
| {
973 this
.emit_struct("Generics", 2, |this
| {
974 this
.emit_struct_field("types", 0, |this
| {
975 Ok(encode_vec_per_param_space(
976 this
, &type_scheme
.generics
.types
,
977 |this
, def
| this
.emit_type_param_def(ecx
, def
)))
979 this
.emit_struct_field("regions", 1, |this
| {
980 Ok(encode_vec_per_param_space(
981 this
, &type_scheme
.generics
.regions
,
982 |this
, def
| def
.encode(this
).unwrap()))
986 this
.emit_struct_field("ty", 1, |this
| {
987 Ok(this
.emit_ty(ecx
, type_scheme
.ty
))
992 fn emit_existential_bounds
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
,'tcx
>,
993 bounds
: &ty
::ExistentialBounds
<'tcx
>) {
994 self.emit_opaque(|this
| Ok(tyencode
::enc_existential_bounds(this
,
999 fn emit_builtin_bounds(&mut self, ecx
: &e
::EncodeContext
, bounds
: &ty
::BuiltinBounds
) {
1000 self.emit_opaque(|this
| Ok(tyencode
::enc_builtin_bounds(this
,
1005 fn emit_substs
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
1006 substs
: &subst
::Substs
<'tcx
>) {
1007 self.emit_opaque(|this
| Ok(tyencode
::enc_substs(this
,
1012 fn emit_auto_adjustment
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
1013 adj
: &ty
::AutoAdjustment
<'tcx
>) {
1014 use serialize
::Encoder
;
1016 self.emit_enum("AutoAdjustment", |this
| {
1018 ty
::AdjustReifyFnPointer
=> {
1019 this
.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_
| Ok(()))
1022 ty
::AdjustUnsafeFnPointer
=> {
1023 this
.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_
| {
1028 ty
::AdjustDerefRef(ref auto_deref_ref
) => {
1029 this
.emit_enum_variant("AdjustDerefRef", 3, 2, |this
| {
1030 this
.emit_enum_variant_arg(0,
1031 |this
| Ok(this
.emit_auto_deref_ref(ecx
, auto_deref_ref
)))
1038 fn emit_autoref
<'b
>(&mut self, autoref
: &ty
::AutoRef
<'tcx
>) {
1039 use serialize
::Encoder
;
1041 self.emit_enum("AutoRef", |this
| {
1043 &ty
::AutoPtr(r
, m
) => {
1044 this
.emit_enum_variant("AutoPtr", 0, 2, |this
| {
1045 this
.emit_enum_variant_arg(0, |this
| r
.encode(this
));
1046 this
.emit_enum_variant_arg(1, |this
| m
.encode(this
))
1049 &ty
::AutoUnsafe(m
) => {
1050 this
.emit_enum_variant("AutoUnsafe", 1, 1, |this
| {
1051 this
.emit_enum_variant_arg(0, |this
| m
.encode(this
))
1058 fn emit_auto_deref_ref
<'b
>(&mut self, ecx
: &e
::EncodeContext
<'b
, 'tcx
>,
1059 auto_deref_ref
: &ty
::AutoDerefRef
<'tcx
>) {
1060 use serialize
::Encoder
;
1062 self.emit_struct("AutoDerefRef", 2, |this
| {
1063 this
.emit_struct_field("autoderefs", 0, |this
| auto_deref_ref
.autoderefs
.encode(this
));
1065 this
.emit_struct_field("autoref", 1, |this
| {
1066 this
.emit_option(|this
| {
1067 match auto_deref_ref
.autoref
{
1068 None
=> this
.emit_option_none(),
1069 Some(ref a
) => this
.emit_option_some(|this
| Ok(this
.emit_autoref(a
))),
1074 this
.emit_struct_field("unsize", 2, |this
| {
1075 this
.emit_option(|this
| {
1076 match auto_deref_ref
.unsize
{
1077 None
=> this
.emit_option_none(),
1078 Some(target
) => this
.emit_option_some(|this
| {
1079 Ok(this
.emit_ty(ecx
, target
))
1088 trait write_tag_and_id
{
1089 fn tag
<F
>(&mut self, tag_id
: c
::astencode_tag
, f
: F
) where F
: FnOnce(&mut Self);
1090 fn id(&mut self, id
: ast
::NodeId
);
1093 impl<'a
> write_tag_and_id
for Encoder
<'a
> {
1094 fn tag
<F
>(&mut self,
1095 tag_id
: c
::astencode_tag
,
1097 F
: FnOnce(&mut Encoder
<'a
>),
1099 self.start_tag(tag_id
as usize);
1104 fn id(&mut self, id
: ast
::NodeId
) {
1105 id
.encode(self).unwrap();
1109 struct SideTableEncodingIdVisitor
<'a
, 'b
:'a
, 'c
:'a
, 'tcx
:'c
> {
1110 ecx
: &'a e
::EncodeContext
<'c
, 'tcx
>,
1111 rbml_w
: &'a
mut Encoder
<'b
>,
1114 impl<'a
, 'b
, 'c
, 'tcx
> ast_util
::IdVisitingOperation
for
1115 SideTableEncodingIdVisitor
<'a
, 'b
, 'c
, 'tcx
> {
1116 fn visit_id(&mut self, id
: ast
::NodeId
) {
1117 encode_side_tables_for_id(self.ecx
, self.rbml_w
, id
)
1121 fn encode_side_tables_for_ii(ecx
: &e
::EncodeContext
,
1122 rbml_w
: &mut Encoder
,
1123 ii
: &ast
::InlinedItem
) {
1124 rbml_w
.start_tag(c
::tag_table
as usize);
1125 ast_util
::visit_ids_for_inlined_item(ii
, &mut SideTableEncodingIdVisitor
{
1132 fn encode_side_tables_for_id(ecx
: &e
::EncodeContext
,
1133 rbml_w
: &mut Encoder
,
1137 debug
!("Encoding side tables for id {}", id
);
1139 if let Some(def
) = tcx
.def_map
.borrow().get(&id
).map(|d
| d
.full_def()) {
1140 rbml_w
.tag(c
::tag_table_def
, |rbml_w
| {
1142 def
.encode(rbml_w
).unwrap();
1146 if let Some(ty
) = tcx
.node_types().get(&id
) {
1147 rbml_w
.tag(c
::tag_table_node_type
, |rbml_w
| {
1149 rbml_w
.emit_ty(ecx
, *ty
);
1153 if let Some(item_substs
) = tcx
.item_substs
.borrow().get(&id
) {
1154 rbml_w
.tag(c
::tag_table_item_subst
, |rbml_w
| {
1156 rbml_w
.emit_substs(ecx
, &item_substs
.substs
);
1160 if let Some(fv
) = tcx
.freevars
.borrow().get(&id
) {
1161 rbml_w
.tag(c
::tag_table_freevars
, |rbml_w
| {
1163 rbml_w
.emit_from_vec(fv
, |rbml_w
, fv_entry
| {
1164 Ok(encode_freevar_entry(rbml_w
, fv_entry
))
1169 rbml_w
.tag(c
::tag_table_upvar_capture_map
, |rbml_w
| {
1172 let var_id
= freevar
.def
.def_id().node
;
1173 let upvar_id
= ty
::UpvarId
{
1177 let upvar_capture
= tcx
.upvar_capture_map
.borrow().get(&upvar_id
).unwrap().clone();
1178 var_id
.encode(rbml_w
);
1179 upvar_capture
.encode(rbml_w
);
1184 let lid
= ast
::DefId { krate: ast::LOCAL_CRATE, node: id }
;
1185 if let Some(type_scheme
) = tcx
.tcache
.borrow().get(&lid
) {
1186 rbml_w
.tag(c
::tag_table_tcache
, |rbml_w
| {
1188 rbml_w
.emit_type_scheme(ecx
, type_scheme
.clone());
1192 if let Some(type_param_def
) = tcx
.ty_param_defs
.borrow().get(&id
) {
1193 rbml_w
.tag(c
::tag_table_param_defs
, |rbml_w
| {
1195 rbml_w
.emit_type_param_def(ecx
, type_param_def
)
1199 let method_call
= MethodCall
::expr(id
);
1200 if let Some(method
) = tcx
.method_map
.borrow().get(&method_call
) {
1201 rbml_w
.tag(c
::tag_table_method_map
, |rbml_w
| {
1203 encode_method_callee(ecx
, rbml_w
, method_call
.autoderef
, method
)
1207 if let Some(trait_ref
) = tcx
.object_cast_map
.borrow().get(&id
) {
1208 rbml_w
.tag(c
::tag_table_object_cast_map
, |rbml_w
| {
1210 rbml_w
.emit_trait_ref(ecx
, &trait_ref
.0);
1214 if let Some(adjustment
) = tcx
.adjustments
.borrow().get(&id
) {
1216 ty
::AdjustDerefRef(ref adj
) => {
1217 for autoderef
in 0..adj
.autoderefs
{
1218 let method_call
= MethodCall
::autoderef(id
, autoderef
as u32);
1219 if let Some(method
) = tcx
.method_map
.borrow().get(&method_call
) {
1220 rbml_w
.tag(c
::tag_table_method_map
, |rbml_w
| {
1222 encode_method_callee(ecx
, rbml_w
,
1223 method_call
.autoderef
, method
)
1231 rbml_w
.tag(c
::tag_table_adjustments
, |rbml_w
| {
1233 rbml_w
.emit_auto_adjustment(ecx
, adjustment
);
1237 if let Some(closure_type
) = tcx
.closure_tys
.borrow().get(&ast_util
::local_def(id
)) {
1238 rbml_w
.tag(c
::tag_table_closure_tys
, |rbml_w
| {
1240 rbml_w
.emit_closure_type(ecx
, closure_type
);
1244 if let Some(closure_kind
) = tcx
.closure_kinds
.borrow().get(&ast_util
::local_def(id
)) {
1245 rbml_w
.tag(c
::tag_table_closure_kinds
, |rbml_w
| {
1247 encode_closure_kind(rbml_w
, *closure_kind
)
1251 for &qualif
in tcx
.const_qualif_map
.borrow().get(&id
).iter() {
1252 rbml_w
.tag(c
::tag_table_const_qualif
, |rbml_w
| {
1254 qualif
.encode(rbml_w
).unwrap()
1259 trait doc_decoder_helpers
{
1260 fn as_int(&self) -> isize;
1261 fn opt_child(&self, tag
: c
::astencode_tag
) -> Option
<Self>;
1264 impl<'a
> doc_decoder_helpers
for rbml
::Doc
<'a
> {
1265 fn as_int(&self) -> isize { reader::doc_as_u64(*self) as isize }
1266 fn opt_child(&self, tag
: c
::astencode_tag
) -> Option
<rbml
::Doc
<'a
>> {
1267 reader
::maybe_get_doc(*self, tag
as usize)
1271 trait rbml_decoder_decoder_helpers
<'tcx
> {
1272 fn read_method_origin
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1273 -> ty
::MethodOrigin
<'tcx
>;
1274 fn read_ty
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>) -> Ty
<'tcx
>;
1275 fn read_tys
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>) -> Vec
<Ty
<'tcx
>>;
1276 fn read_trait_ref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1277 -> ty
::TraitRef
<'tcx
>;
1278 fn read_poly_trait_ref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1279 -> ty
::PolyTraitRef
<'tcx
>;
1280 fn read_type_param_def
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1281 -> ty
::TypeParameterDef
<'tcx
>;
1282 fn read_predicate
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1283 -> ty
::Predicate
<'tcx
>;
1284 fn read_type_scheme
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1285 -> ty
::TypeScheme
<'tcx
>;
1286 fn read_existential_bounds
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1287 -> ty
::ExistentialBounds
<'tcx
>;
1288 fn read_substs
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1289 -> subst
::Substs
<'tcx
>;
1290 fn read_auto_adjustment
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1291 -> ty
::AutoAdjustment
<'tcx
>;
1292 fn read_closure_kind
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1294 fn read_closure_ty
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1295 -> ty
::ClosureTy
<'tcx
>;
1296 fn read_auto_deref_ref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1297 -> ty
::AutoDerefRef
<'tcx
>;
1298 fn read_autoref
<'a
, 'b
>(&mut self, dcx
: &DecodeContext
<'a
, 'b
, 'tcx
>)
1299 -> ty
::AutoRef
<'tcx
>;
1300 fn convert_def_id(&mut self,
1301 dcx
: &DecodeContext
,
1302 source
: DefIdSource
,
1306 // Versions of the type reading functions that don't need the full
1308 fn read_ty_nodcx(&mut self,
1309 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
) -> Ty
<'tcx
>;
1310 fn read_tys_nodcx(&mut self,
1311 tcx
: &ty
::ctxt
<'tcx
>,
1312 cdata
: &cstore
::crate_metadata
) -> Vec
<Ty
<'tcx
>>;
1313 fn read_substs_nodcx(&mut self, tcx
: &ty
::ctxt
<'tcx
>,
1314 cdata
: &cstore
::crate_metadata
)
1315 -> subst
::Substs
<'tcx
>;
1318 impl<'a
, 'tcx
> rbml_decoder_decoder_helpers
<'tcx
> for reader
::Decoder
<'a
> {
1319 fn read_ty_nodcx(&mut self,
1320 tcx
: &ty
::ctxt
<'tcx
>, cdata
: &cstore
::crate_metadata
) -> Ty
<'tcx
> {
1321 self.read_opaque(|_
, doc
| {
1322 Ok(tydecode
::parse_ty_data(
1327 |_
, id
| decoder
::translate_def_id(cdata
, id
)))
1331 fn read_tys_nodcx(&mut self,
1332 tcx
: &ty
::ctxt
<'tcx
>,
1333 cdata
: &cstore
::crate_metadata
) -> Vec
<Ty
<'tcx
>> {
1334 self.read_to_vec(|this
| Ok(this
.read_ty_nodcx(tcx
, cdata
)) )
1340 fn read_substs_nodcx(&mut self,
1341 tcx
: &ty
::ctxt
<'tcx
>,
1342 cdata
: &cstore
::crate_metadata
)
1343 -> subst
::Substs
<'tcx
>
1345 self.read_opaque(|_
, doc
| {
1346 Ok(tydecode
::parse_substs_data(
1351 |_
, id
| decoder
::translate_def_id(cdata
, id
)))
1355 fn read_method_origin
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1356 -> ty
::MethodOrigin
<'tcx
>
1358 self.read_enum("MethodOrigin", |this
| {
1359 let variants
= &["MethodStatic", "MethodStaticClosure",
1360 "MethodTypeParam", "MethodTraitObject"];
1361 this
.read_enum_variant(variants
, |this
, i
| {
1364 let def_id
= this
.read_def_id(dcx
);
1365 ty
::MethodStatic(def_id
)
1369 let def_id
= this
.read_def_id(dcx
);
1370 ty
::MethodStaticClosure(def_id
)
1374 this
.read_struct("MethodTypeParam", 2, |this
| {
1375 Ok(ty
::MethodTypeParam(
1378 this
.read_struct_field("trait_ref", 0, |this
| {
1379 Ok(this
.read_trait_ref(dcx
))
1383 this
.read_struct_field("method_num", 1, |this
| {
1388 this
.read_struct_field("impl_def_id", 2, |this
| {
1389 this
.read_option(|this
, b
| {
1391 Ok(Some(this
.read_def_id(dcx
)))
1403 this
.read_struct("MethodTraitObject", 2, |this
| {
1404 Ok(ty
::MethodTraitObject(
1407 this
.read_struct_field("trait_ref", 0, |this
| {
1408 Ok(this
.read_trait_ref(dcx
))
1412 this
.read_struct_field("object_trait_id", 1, |this
| {
1413 Ok(this
.read_def_id(dcx
))
1417 this
.read_struct_field("method_num", 2, |this
| {
1422 this
.read_struct_field("vtable_index", 3, |this
| {
1437 fn read_ty
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>) -> Ty
<'tcx
> {
1438 // Note: regions types embed local node ids. In principle, we
1439 // should translate these node ids into the new decode
1440 // context. However, we do not bother, because region types
1441 // are not used during trans.
1443 return self.read_opaque(|this
, doc
| {
1444 debug
!("read_ty({})", type_string(doc
));
1446 let ty
= tydecode
::parse_ty_data(
1451 |s
, a
| this
.convert_def_id(dcx
, s
, a
));
1456 fn type_string(doc
: rbml
::Doc
) -> String
{
1457 let mut str = String
::new();
1458 for i
in doc
.start
..doc
.end
{
1459 str.push(doc
.data
[i
] as char);
1465 fn read_tys
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1467 self.read_to_vec(|this
| Ok(this
.read_ty(dcx
))).unwrap().into_iter().collect()
1470 fn read_trait_ref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1471 -> ty
::TraitRef
<'tcx
> {
1472 self.read_opaque(|this
, doc
| {
1473 let ty
= tydecode
::parse_trait_ref_data(
1478 |s
, a
| this
.convert_def_id(dcx
, s
, a
));
1483 fn read_poly_trait_ref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1484 -> ty
::PolyTraitRef
<'tcx
> {
1485 ty
::Binder(self.read_opaque(|this
, doc
| {
1486 let ty
= tydecode
::parse_trait_ref_data(
1491 |s
, a
| this
.convert_def_id(dcx
, s
, a
));
1496 fn read_type_param_def
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1497 -> ty
::TypeParameterDef
<'tcx
> {
1498 self.read_opaque(|this
, doc
| {
1499 Ok(tydecode
::parse_type_param_def_data(
1504 |s
, a
| this
.convert_def_id(dcx
, s
, a
)))
1508 fn read_predicate
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1509 -> ty
::Predicate
<'tcx
>
1511 self.read_opaque(|this
, doc
| {
1512 Ok(tydecode
::parse_predicate_data(doc
.data
, doc
.start
, dcx
.cdata
.cnum
, dcx
.tcx
,
1513 |s
, a
| this
.convert_def_id(dcx
, s
, a
)))
1517 fn read_type_scheme
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1518 -> ty
::TypeScheme
<'tcx
> {
1519 self.read_struct("TypeScheme", 3, |this
| {
1521 generics
: this
.read_struct_field("generics", 0, |this
| {
1522 this
.read_struct("Generics", 2, |this
| {
1525 this
.read_struct_field("types", 0, |this
| {
1526 Ok(this
.read_vec_per_param_space(
1527 |this
| this
.read_type_param_def(dcx
)))
1531 this
.read_struct_field("regions", 1, |this
| {
1532 Ok(this
.read_vec_per_param_space(
1533 |this
| Decodable
::decode(this
).unwrap()))
1538 ty
: this
.read_struct_field("ty", 1, |this
| {
1539 Ok(this
.read_ty(dcx
))
1545 fn read_existential_bounds
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1546 -> ty
::ExistentialBounds
<'tcx
>
1548 self.read_opaque(|this
, doc
| {
1549 Ok(tydecode
::parse_existential_bounds_data(doc
.data
,
1553 |s
, a
| this
.convert_def_id(dcx
, s
, a
)))
1557 fn read_substs
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1558 -> subst
::Substs
<'tcx
> {
1559 self.read_opaque(|this
, doc
| {
1560 Ok(tydecode
::parse_substs_data(doc
.data
,
1564 |s
, a
| this
.convert_def_id(dcx
, s
, a
)))
1568 fn read_auto_adjustment
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1569 -> ty
::AutoAdjustment
<'tcx
> {
1570 self.read_enum("AutoAdjustment", |this
| {
1571 let variants
= ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustDerefRef"];
1572 this
.read_enum_variant(&variants
, |this
, i
| {
1574 1 => ty
::AdjustReifyFnPointer
,
1575 2 => ty
::AdjustUnsafeFnPointer
,
1577 let auto_deref_ref
: ty
::AutoDerefRef
=
1578 this
.read_enum_variant_arg(0,
1579 |this
| Ok(this
.read_auto_deref_ref(dcx
))).unwrap();
1581 ty
::AdjustDerefRef(auto_deref_ref
)
1583 _
=> panic
!("bad enum variant for ty::AutoAdjustment")
1589 fn read_auto_deref_ref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1590 -> ty
::AutoDerefRef
<'tcx
> {
1591 self.read_struct("AutoDerefRef", 2, |this
| {
1592 Ok(ty
::AutoDerefRef
{
1593 autoderefs
: this
.read_struct_field("autoderefs", 0, |this
| {
1594 Decodable
::decode(this
)
1596 autoref
: this
.read_struct_field("autoref", 1, |this
| {
1597 this
.read_option(|this
, b
| {
1599 Ok(Some(this
.read_autoref(dcx
)))
1605 unsize
: this
.read_struct_field("unsize", 2, |this
| {
1606 this
.read_option(|this
, b
| {
1608 Ok(Some(this
.read_ty(dcx
)))
1618 fn read_autoref
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1619 -> ty
::AutoRef
<'tcx
> {
1620 self.read_enum("AutoRef", |this
| {
1621 let variants
= ["AutoPtr", "AutoUnsafe"];
1622 this
.read_enum_variant(&variants
, |this
, i
| {
1626 this
.read_enum_variant_arg(0, |this
| Decodable
::decode(this
)).unwrap();
1627 let m
: ast
::Mutability
=
1628 this
.read_enum_variant_arg(1, |this
| Decodable
::decode(this
)).unwrap();
1630 ty
::AutoPtr(dcx
.tcx
.mk_region(r
.tr(dcx
)), m
)
1633 let m
: ast
::Mutability
=
1634 this
.read_enum_variant_arg(0, |this
| Decodable
::decode(this
)).unwrap();
1638 _
=> panic
!("bad enum variant for ty::AutoRef")
1644 fn read_closure_kind
<'b
, 'c
>(&mut self, _dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1647 Decodable
::decode(self).unwrap()
1650 fn read_closure_ty
<'b
, 'c
>(&mut self, dcx
: &DecodeContext
<'b
, 'c
, 'tcx
>)
1651 -> ty
::ClosureTy
<'tcx
>
1653 self.read_opaque(|this
, doc
| {
1654 Ok(tydecode
::parse_ty_closure_data(
1659 |s
, a
| this
.convert_def_id(dcx
, s
, a
)))
1663 /// Converts a def-id that appears in a type. The correct
1664 /// translation will depend on what kind of def-id this is.
1665 /// This is a subtle point: type definitions are not
1666 /// inlined into the current crate, so if the def-id names
1667 /// a nominal type or type alias, then it should be
1668 /// translated to refer to the source crate.
1670 /// However, *type parameters* are cloned along with the function
1671 /// they are attached to. So we should translate those def-ids
1672 /// to refer to the new, cloned copy of the type parameter.
1673 /// We only see references to free type parameters in the body of
1674 /// an inlined function. In such cases, we need the def-id to
1675 /// be a local id so that the TypeContents code is able to lookup
1676 /// the relevant info in the ty_param_defs table.
1678 /// *Region parameters*, unfortunately, are another kettle of fish.
1679 /// In such cases, def_id's can appear in types to distinguish
1680 /// shadowed bound regions and so forth. It doesn't actually
1681 /// matter so much what we do to these, since regions are erased
1682 /// at trans time, but it's good to keep them consistent just in
1683 /// case. We translate them with `tr_def_id()` which will map
1684 /// the crate numbers back to the original source crate.
1686 /// Unboxed closures are cloned along with the function being
1687 /// inlined, and all side tables use interned node IDs, so we
1688 /// translate their def IDs accordingly.
1690 /// It'd be really nice to refactor the type repr to not include
1691 /// def-ids so that all these distinctions were unnecessary.
1692 fn convert_def_id(&mut self,
1693 dcx
: &DecodeContext
,
1694 source
: tydecode
::DefIdSource
,
1697 let r
= match source
{
1698 NominalType
| TypeWithId
| RegionParameter
=> dcx
.tr_def_id(did
),
1699 TypeParameter
| ClosureSource
=> dcx
.tr_intern_def_id(did
)
1701 debug
!("convert_def_id(source={:?}, did={:?})={:?}", source
, did
, r
);
1706 fn decode_side_tables(dcx
: &DecodeContext
,
1707 ast_doc
: rbml
::Doc
) {
1708 let tbl_doc
= ast_doc
.get(c
::tag_table
as usize);
1709 reader
::docs(tbl_doc
, |tag
, entry_doc
| {
1710 let mut entry_dsr
= reader
::Decoder
::new(entry_doc
);
1711 let id0
: ast
::NodeId
= Decodable
::decode(&mut entry_dsr
).unwrap();
1712 let id
= dcx
.tr_id(id0
);
1714 debug
!(">> Side table document with tag 0x{:x} \
1715 found for id {} (orig {})",
1717 let tag
= tag
as u32;
1718 let decoded_tag
: Option
<c
::astencode_tag
> = c
::astencode_tag
::from_u32(tag
);
1722 &format
!("unknown tag found in side tables: {:x}",
1726 let val_dsr
= &mut entry_dsr
;
1729 c
::tag_table_def
=> {
1730 let def
= decode_def(dcx
, val_dsr
);
1731 dcx
.tcx
.def_map
.borrow_mut().insert(id
, def
::PathResolution
{
1733 // This doesn't matter cross-crate.
1734 last_private
: LastMod(AllPublic
),
1738 c
::tag_table_node_type
=> {
1739 let ty
= val_dsr
.read_ty(dcx
);
1740 debug
!("inserting ty for node {}: {}",
1741 id
, ty_to_string(dcx
.tcx
, ty
));
1742 dcx
.tcx
.node_type_insert(id
, ty
);
1744 c
::tag_table_item_subst
=> {
1745 let item_substs
= ty
::ItemSubsts
{
1746 substs
: val_dsr
.read_substs(dcx
)
1748 dcx
.tcx
.item_substs
.borrow_mut().insert(
1751 c
::tag_table_freevars
=> {
1752 let fv_info
= val_dsr
.read_to_vec(|val_dsr
| {
1753 Ok(val_dsr
.read_freevar_entry(dcx
))
1754 }).unwrap().into_iter().collect();
1755 dcx
.tcx
.freevars
.borrow_mut().insert(id
, fv_info
);
1757 c
::tag_table_upvar_capture_map
=> {
1758 let var_id
: ast
::NodeId
= Decodable
::decode(val_dsr
).unwrap();
1759 let upvar_id
= ty
::UpvarId
{
1760 var_id
: dcx
.tr_id(var_id
),
1763 let ub
: ty
::UpvarCapture
= Decodable
::decode(val_dsr
).unwrap();
1764 dcx
.tcx
.upvar_capture_map
.borrow_mut().insert(upvar_id
, ub
.tr(dcx
));
1766 c
::tag_table_tcache
=> {
1767 let type_scheme
= val_dsr
.read_type_scheme(dcx
);
1768 let lid
= ast
::DefId { krate: ast::LOCAL_CRATE, node: id }
;
1769 dcx
.tcx
.tcache
.borrow_mut().insert(lid
, type_scheme
);
1771 c
::tag_table_param_defs
=> {
1772 let bounds
= val_dsr
.read_type_param_def(dcx
);
1773 dcx
.tcx
.ty_param_defs
.borrow_mut().insert(id
, bounds
);
1775 c
::tag_table_method_map
=> {
1776 let (autoderef
, method
) = val_dsr
.read_method_callee(dcx
);
1777 let method_call
= MethodCall
{
1779 autoderef
: autoderef
1781 dcx
.tcx
.method_map
.borrow_mut().insert(method_call
, method
);
1783 c
::tag_table_object_cast_map
=> {
1784 let trait_ref
= val_dsr
.read_poly_trait_ref(dcx
);
1785 dcx
.tcx
.object_cast_map
.borrow_mut()
1786 .insert(id
, trait_ref
);
1788 c
::tag_table_adjustments
=> {
1789 let adj
: ty
::AutoAdjustment
= val_dsr
.read_auto_adjustment(dcx
);
1790 dcx
.tcx
.adjustments
.borrow_mut().insert(id
, adj
);
1792 c
::tag_table_closure_tys
=> {
1794 val_dsr
.read_closure_ty(dcx
);
1795 dcx
.tcx
.closure_tys
.borrow_mut().insert(ast_util
::local_def(id
),
1798 c
::tag_table_closure_kinds
=> {
1800 val_dsr
.read_closure_kind(dcx
);
1801 dcx
.tcx
.closure_kinds
.borrow_mut().insert(ast_util
::local_def(id
),
1804 c
::tag_table_const_qualif
=> {
1805 let qualif
: ConstQualif
= Decodable
::decode(val_dsr
).unwrap();
1806 dcx
.tcx
.const_qualif_map
.borrow_mut().insert(id
, qualif
);
1810 &format
!("unknown tag found in side tables: {:x}",
1817 debug
!(">< Side table doc loaded");
1822 // ______________________________________________________________________
1823 // Testing of astencode_gen
1826 fn encode_item_ast(rbml_w
: &mut Encoder
, item
: &ast
::Item
) {
1827 rbml_w
.start_tag(c
::tag_tree
as usize);
1828 (*item
).encode(rbml_w
);
1833 fn decode_item_ast(par_doc
: rbml
::Doc
) -> ast
::Item
{
1834 let chi_doc
= par_doc
.get(c
::tag_tree
as usize);
1835 let mut d
= reader
::Decoder
::new(chi_doc
);
1836 Decodable
::decode(&mut d
).unwrap()
1841 fn call_site(&self) -> codemap
::Span
;
1842 fn cfg(&self) -> ast
::CrateConfig
;
1843 fn ident_of(&self, st
: &str) -> ast
::Ident
;
1844 fn name_of(&self, st
: &str) -> ast
::Name
;
1845 fn parse_sess(&self) -> &parse
::ParseSess
;
1849 impl FakeExtCtxt
for parse
::ParseSess
{
1850 fn call_site(&self) -> codemap
::Span
{
1852 lo
: codemap
::BytePos(0),
1853 hi
: codemap
::BytePos(0),
1854 expn_id
: codemap
::NO_EXPANSION
,
1857 fn cfg(&self) -> ast
::CrateConfig { Vec::new() }
1858 fn ident_of(&self, st
: &str) -> ast
::Ident
{
1859 parse
::token
::str_to_ident(st
)
1861 fn name_of(&self, st
: &str) -> ast
::Name
{
1862 parse
::token
::intern(st
)
1864 fn parse_sess(&self) -> &parse
::ParseSess { self }
1868 fn mk_ctxt() -> parse
::ParseSess
{
1869 parse
::new_parse_sess()
1873 fn roundtrip(in_item
: Option
<P
<ast
::Item
>>) {
1874 let in_item
= in_item
.unwrap();
1875 let mut wr
= Cursor
::new(Vec
::new());
1876 encode_item_ast(&mut Encoder
::new(&mut wr
), &*in_item
);
1877 let rbml_doc
= rbml
::Doc
::new(wr
.get_ref());
1878 let out_item
= decode_item_ast(rbml_doc
);
1880 assert
!(*in_item
== out_item
);
1886 roundtrip(quote_item
!(&cx
,
1892 fn test_smalltalk() {
1894 roundtrip(quote_item
!(&cx
,
1895 fn foo() -> isize { 3 + 4 }
// first smalltalk program ever executed.
1902 roundtrip(quote_item
!(&cx
,
1903 fn foo(x
: usize, y
: usize) -> usize {
1911 fn test_simplification() {
1913 let item
= quote_item
!(&cx
,
1914 fn new_int_alist
<B
>() -> alist
<isize, B
> {
1915 fn eq_int(a
: isize, b
: isize) -> bool { a == b }
1916 return alist {eq_fn: eq_int, data: Vec::new()}
;
1919 let item_in
= e
::IIItemRef(&*item
);
1920 let item_out
= simplify_ast(item_in
);
1921 let item_exp
= ast
::IIItem(quote_item
!(&cx
,
1922 fn new_int_alist
<B
>() -> alist
<isize, B
> {
1923 return alist {eq_fn: eq_int, data: Vec::new()}
;
1926 match (item_out
, item_exp
) {
1927 (ast
::IIItem(item_out
), ast
::IIItem(item_exp
)) => {
1928 assert
!(pprust
::item_to_string(&*item_out
) ==
1929 pprust
::item_to_string(&*item_exp
));