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.
15 use rustc
::middle
::cstore
::{LinkMeta
, LinkagePreference
, NativeLibrary
,
16 EncodedMetadata
, EncodedMetadataHash
};
17 use rustc
::hir
::def_id
::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}
;
18 use rustc
::hir
::map
::definitions
::DefPathTable
;
19 use rustc
::middle
::dependency_format
::Linkage
;
20 use rustc
::middle
::lang_items
;
22 use rustc
::traits
::specialization_graph
;
23 use rustc
::ty
::{self, Ty, TyCtxt, ReprOptions}
;
25 use rustc
::session
::config
::{self, CrateTypeProcMacro}
;
26 use rustc
::util
::nodemap
::{FxHashMap, NodeSet}
;
28 use rustc_serialize
::{Encodable, Encoder, SpecializedEncoder, opaque}
;
31 use std
::io
::prelude
::*;
35 use syntax
::ast
::{self, CRATE_NODE_ID}
;
36 use syntax
::codemap
::Spanned
;
38 use syntax
::symbol
::Symbol
;
39 use syntax_pos
::{self, DUMMY_SP}
;
41 use rustc
::hir
::{self, PatKind}
;
42 use rustc
::hir
::itemlikevisit
::ItemLikeVisitor
;
43 use rustc
::hir
::intravisit
::{Visitor, NestedVisitorMap}
;
44 use rustc
::hir
::intravisit
;
46 use super::index_builder
::{FromId, IndexBuilder, Untracked, EntryBuilder}
;
48 pub struct EncodeContext
<'a
, 'tcx
: 'a
> {
49 opaque
: opaque
::Encoder
<'a
>,
50 pub tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
51 link_meta
: &'a LinkMeta
,
52 cstore
: &'a cstore
::CStore
,
53 exported_symbols
: &'a NodeSet
,
55 lazy_state
: LazyState
,
56 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
57 predicate_shorthands
: FxHashMap
<ty
::Predicate
<'tcx
>, usize>,
59 pub metadata_hashes
: Vec
<EncodedMetadataHash
>,
62 macro_rules
! encoder_methods
{
63 ($
($name
:ident($ty
:ty
);)*) => {
64 $
(fn $
name(&mut self, value
: $ty
) -> Result
<(), Self::Error
> {
65 self.opaque
.$
name(value
)
70 impl<'a
, 'tcx
> Encoder
for EncodeContext
<'a
, 'tcx
> {
71 type Error
= <opaque
::Encoder
<'a
> as Encoder
>::Error
;
73 fn emit_nil(&mut self) -> Result
<(), Self::Error
> {
100 impl<'a
, 'tcx
, T
> SpecializedEncoder
<Lazy
<T
>> for EncodeContext
<'a
, 'tcx
> {
101 fn specialized_encode(&mut self, lazy
: &Lazy
<T
>) -> Result
<(), Self::Error
> {
102 self.emit_lazy_distance(lazy
.position
, Lazy
::<T
>::min_size())
106 impl<'a
, 'tcx
, T
> SpecializedEncoder
<LazySeq
<T
>> for EncodeContext
<'a
, 'tcx
> {
107 fn specialized_encode(&mut self, seq
: &LazySeq
<T
>) -> Result
<(), Self::Error
> {
108 self.emit_usize(seq
.len
)?
;
112 self.emit_lazy_distance(seq
.position
, LazySeq
::<T
>::min_size(seq
.len
))
116 impl<'a
, 'tcx
> SpecializedEncoder
<Ty
<'tcx
>> for EncodeContext
<'a
, 'tcx
> {
117 fn specialized_encode(&mut self, ty
: &Ty
<'tcx
>) -> Result
<(), Self::Error
> {
118 self.encode_with_shorthand(ty
, &ty
.sty
, |ecx
| &mut ecx
.type_shorthands
)
122 impl<'a
, 'tcx
> SpecializedEncoder
<ty
::GenericPredicates
<'tcx
>> for EncodeContext
<'a
, 'tcx
> {
123 fn specialized_encode(&mut self,
124 predicates
: &ty
::GenericPredicates
<'tcx
>)
125 -> Result
<(), Self::Error
> {
126 predicates
.parent
.encode(self)?
;
127 predicates
.predicates
.len().encode(self)?
;
128 for predicate
in &predicates
.predicates
{
129 self.encode_with_shorthand(predicate
, predicate
, |ecx
| &mut ecx
.predicate_shorthands
)?
135 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
136 pub fn position(&self) -> usize {
137 self.opaque
.position()
140 fn emit_node
<F
: FnOnce(&mut Self, usize) -> R
, R
>(&mut self, f
: F
) -> R
{
141 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
142 let pos
= self.position();
143 self.lazy_state
= LazyState
::NodeStart(pos
);
144 let r
= f(self, pos
);
145 self.lazy_state
= LazyState
::NoNode
;
149 fn emit_lazy_distance(&mut self,
152 -> Result
<(), <Self as Encoder
>::Error
> {
153 let min_end
= position
+ min_size
;
154 let distance
= match self.lazy_state
{
155 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
156 LazyState
::NodeStart(start
) => {
157 assert
!(min_end
<= start
);
160 LazyState
::Previous(last_min_end
) => {
161 assert
!(last_min_end
<= position
);
162 position
- last_min_end
165 self.lazy_state
= LazyState
::Previous(min_end
);
166 self.emit_usize(distance
)
169 pub fn lazy
<T
: Encodable
>(&mut self, value
: &T
) -> Lazy
<T
> {
170 self.emit_node(|ecx
, pos
| {
171 value
.encode(ecx
).unwrap();
173 assert
!(pos
+ Lazy
::<T
>::min_size() <= ecx
.position());
174 Lazy
::with_position(pos
)
178 pub fn lazy_seq
<I
, T
>(&mut self, iter
: I
) -> LazySeq
<T
>
179 where I
: IntoIterator
<Item
= T
>,
182 self.emit_node(|ecx
, pos
| {
183 let len
= iter
.into_iter().map(|value
| value
.encode(ecx
).unwrap()).count();
185 assert
!(pos
+ LazySeq
::<T
>::min_size(len
) <= ecx
.position());
186 LazySeq
::with_position_and_length(pos
, len
)
190 pub fn lazy_seq_ref
<'b
, I
, T
>(&mut self, iter
: I
) -> LazySeq
<T
>
191 where I
: IntoIterator
<Item
= &'b T
>,
194 self.emit_node(|ecx
, pos
| {
195 let len
= iter
.into_iter().map(|value
| value
.encode(ecx
).unwrap()).count();
197 assert
!(pos
+ LazySeq
::<T
>::min_size(len
) <= ecx
.position());
198 LazySeq
::with_position_and_length(pos
, len
)
202 /// Encode the given value or a previously cached shorthand.
203 fn encode_with_shorthand
<T
, U
, M
>(&mut self,
207 -> Result
<(), <Self as Encoder
>::Error
>
208 where M
: for<'b
> Fn(&'b
mut Self) -> &'b
mut FxHashMap
<T
, usize>,
209 T
: Clone
+ Eq
+ Hash
,
212 let existing_shorthand
= map(self).get(value
).cloned();
213 if let Some(shorthand
) = existing_shorthand
{
214 return self.emit_usize(shorthand
);
217 let start
= self.position();
218 variant
.encode(self)?
;
219 let len
= self.position() - start
;
221 // The shorthand encoding uses the same usize as the
222 // discriminant, with an offset so they can't conflict.
223 let discriminant
= unsafe { intrinsics::discriminant_value(variant) }
;
224 assert
!(discriminant
< SHORTHAND_OFFSET
as u64);
225 let shorthand
= start
+ SHORTHAND_OFFSET
;
227 // Get the number of bits that leb128 could fit
228 // in the same space as the fully encoded type.
229 let leb128_bits
= len
* 7;
231 // Check that the shorthand is a not longer than the
232 // full encoding itself, i.e. it's an obvious win.
233 if leb128_bits
>= 64 || (shorthand
as u64) < (1 << leb128_bits
) {
234 map(self).insert(value
.clone(), shorthand
);
241 impl<'a
, 'b
: 'a
, 'tcx
: 'b
> EntryBuilder
<'a
, 'b
, 'tcx
> {
242 fn encode_item_variances(&mut self, def_id
: DefId
) -> LazySeq
<ty
::Variance
> {
243 debug
!("EntryBuilder::encode_item_variances({:?})", def_id
);
245 self.lazy_seq_from_slice(&tcx
.item_variances(def_id
))
248 fn encode_item_type(&mut self, def_id
: DefId
) -> Lazy
<Ty
<'tcx
>> {
250 let ty
= tcx
.item_type(def_id
);
251 debug
!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id
, ty
);
255 /// Encode data for the given variant of the given ADT. The
256 /// index of the variant is untracked: this is ok because we
257 /// will have to lookup the adt-def by its id, and that gives us
258 /// the right to access any information in the adt-def (including,
259 /// e.g., the length of the various vectors).
260 fn encode_enum_variant_info(&mut self,
261 (enum_did
, Untracked(index
)): (DefId
, Untracked
<usize>))
264 let def
= tcx
.lookup_adt_def(enum_did
);
265 let variant
= &def
.variants
[index
];
266 let def_id
= variant
.did
;
267 debug
!("EntryBuilder::encode_enum_variant_info({:?})", def_id
);
269 let data
= VariantData
{
270 ctor_kind
: variant
.ctor_kind
,
271 discr
: variant
.discr
,
275 let enum_id
= tcx
.hir
.as_local_node_id(enum_did
).unwrap();
276 let enum_vis
= &tcx
.hir
.expect_item(enum_id
).vis
;
279 kind
: EntryKind
::Variant(self.lazy(&data
)),
280 visibility
: self.lazy(&ty
::Visibility
::from_hir(enum_vis
, enum_id
, tcx
)),
281 span
: self.lazy(&tcx
.def_span(def_id
)),
282 attributes
: self.encode_attributes(&tcx
.get_attrs(def_id
)),
283 children
: self.lazy_seq(variant
.fields
.iter().map(|f
| {
284 assert
!(f
.did
.is_local());
287 stability
: self.encode_stability(def_id
),
288 deprecation
: self.encode_deprecation(def_id
),
290 ty
: Some(self.encode_item_type(def_id
)),
291 inherent_impls
: LazySeq
::empty(),
292 variances
: LazySeq
::empty(),
293 generics
: Some(self.encode_generics(def_id
)),
294 predicates
: Some(self.encode_predicates(def_id
)),
297 mir
: self.encode_mir(def_id
),
301 fn encode_info_for_mod(&mut self,
302 FromId(id
, (md
, attrs
, vis
)): FromId
<(&hir
::Mod
,
307 let def_id
= tcx
.hir
.local_def_id(id
);
308 debug
!("EntryBuilder::encode_info_for_mod({:?})", def_id
);
311 reexports
: match tcx
.export_map
.get(&id
) {
312 Some(exports
) if *vis
== hir
::Public
=> {
313 self.lazy_seq_from_slice(exports
.as_slice())
315 _
=> LazySeq
::empty(),
320 kind
: EntryKind
::Mod(self.lazy(&data
)),
321 visibility
: self.lazy(&ty
::Visibility
::from_hir(vis
, id
, tcx
)),
322 span
: self.lazy(&md
.inner
),
323 attributes
: self.encode_attributes(attrs
),
324 children
: self.lazy_seq(md
.item_ids
.iter().map(|item_id
| {
325 tcx
.hir
.local_def_id(item_id
.id
).index
327 stability
: self.encode_stability(def_id
),
328 deprecation
: self.encode_deprecation(def_id
),
331 inherent_impls
: LazySeq
::empty(),
332 variances
: LazySeq
::empty(),
342 impl<'a
, 'b
, 'tcx
> IndexBuilder
<'a
, 'b
, 'tcx
> {
343 fn encode_fields(&mut self, adt_def_id
: DefId
) {
344 let def
= self.tcx
.lookup_adt_def(adt_def_id
);
345 for (variant_index
, variant
) in def
.variants
.iter().enumerate() {
346 for (field_index
, field
) in variant
.fields
.iter().enumerate() {
347 self.record(field
.did
,
348 EntryBuilder
::encode_field
,
349 (adt_def_id
, Untracked((variant_index
, field_index
))));
355 impl<'a
, 'b
: 'a
, 'tcx
: 'b
> EntryBuilder
<'a
, 'b
, 'tcx
> {
356 /// Encode data for the given field of the given variant of the
357 /// given ADT. The indices of the variant/field are untracked:
358 /// this is ok because we will have to lookup the adt-def by its
359 /// id, and that gives us the right to access any information in
360 /// the adt-def (including, e.g., the length of the various
362 fn encode_field(&mut self,
363 (adt_def_id
, Untracked((variant_index
, field_index
))): (DefId
,
368 let variant
= &tcx
.lookup_adt_def(adt_def_id
).variants
[variant_index
];
369 let field
= &variant
.fields
[field_index
];
371 let def_id
= field
.did
;
372 debug
!("EntryBuilder::encode_field({:?})", def_id
);
374 let variant_id
= tcx
.hir
.as_local_node_id(variant
.did
).unwrap();
375 let variant_data
= tcx
.hir
.expect_variant_data(variant_id
);
378 kind
: EntryKind
::Field
,
379 visibility
: self.lazy(&field
.vis
),
380 span
: self.lazy(&tcx
.def_span(def_id
)),
381 attributes
: self.encode_attributes(&variant_data
.fields()[field_index
].attrs
),
382 children
: LazySeq
::empty(),
383 stability
: self.encode_stability(def_id
),
384 deprecation
: self.encode_deprecation(def_id
),
386 ty
: Some(self.encode_item_type(def_id
)),
387 inherent_impls
: LazySeq
::empty(),
388 variances
: LazySeq
::empty(),
389 generics
: Some(self.encode_generics(def_id
)),
390 predicates
: Some(self.encode_predicates(def_id
)),
397 fn encode_struct_ctor(&mut self, (adt_def_id
, def_id
): (DefId
, DefId
)) -> Entry
<'tcx
> {
398 debug
!("EntryBuilder::encode_struct_ctor({:?})", def_id
);
400 let variant
= tcx
.lookup_adt_def(adt_def_id
).struct_variant();
402 let data
= VariantData
{
403 ctor_kind
: variant
.ctor_kind
,
404 discr
: variant
.discr
,
405 struct_ctor
: Some(def_id
.index
),
408 let struct_id
= tcx
.hir
.as_local_node_id(adt_def_id
).unwrap();
409 let struct_vis
= &tcx
.hir
.expect_item(struct_id
).vis
;
410 let mut ctor_vis
= ty
::Visibility
::from_hir(struct_vis
, struct_id
, tcx
);
411 for field
in &variant
.fields
{
412 if ctor_vis
.is_at_least(field
.vis
, tcx
) {
413 ctor_vis
= field
.vis
;
417 let repr_options
= get_repr_options(&tcx
, adt_def_id
);
420 kind
: EntryKind
::Struct(self.lazy(&data
), repr_options
),
421 visibility
: self.lazy(&ctor_vis
),
422 span
: self.lazy(&tcx
.def_span(def_id
)),
423 attributes
: LazySeq
::empty(),
424 children
: LazySeq
::empty(),
425 stability
: self.encode_stability(def_id
),
426 deprecation
: self.encode_deprecation(def_id
),
428 ty
: Some(self.encode_item_type(def_id
)),
429 inherent_impls
: LazySeq
::empty(),
430 variances
: LazySeq
::empty(),
431 generics
: Some(self.encode_generics(def_id
)),
432 predicates
: Some(self.encode_predicates(def_id
)),
435 mir
: self.encode_mir(def_id
),
439 fn encode_generics(&mut self, def_id
: DefId
) -> Lazy
<ty
::Generics
> {
440 debug
!("EntryBuilder::encode_generics({:?})", def_id
);
442 self.lazy(tcx
.item_generics(def_id
))
445 fn encode_predicates(&mut self, def_id
: DefId
) -> Lazy
<ty
::GenericPredicates
<'tcx
>> {
446 debug
!("EntryBuilder::encode_predicates({:?})", def_id
);
448 self.lazy(&tcx
.item_predicates(def_id
))
451 fn encode_info_for_trait_item(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
452 debug
!("EntryBuilder::encode_info_for_trait_item({:?})", def_id
);
455 let node_id
= tcx
.hir
.as_local_node_id(def_id
).unwrap();
456 let ast_item
= tcx
.hir
.expect_trait_item(node_id
);
457 let trait_item
= tcx
.associated_item(def_id
);
459 let container
= match trait_item
.defaultness
{
460 hir
::Defaultness
::Default { has_value: true }
=>
461 AssociatedContainer
::TraitWithDefault
,
462 hir
::Defaultness
::Default { has_value: false }
=>
463 AssociatedContainer
::TraitRequired
,
464 hir
::Defaultness
::Final
=>
465 span_bug
!(ast_item
.span
, "traits cannot have final items"),
468 let kind
= match trait_item
.kind
{
469 ty
::AssociatedKind
::Const
=> {
470 EntryKind
::AssociatedConst(container
, 0)
472 ty
::AssociatedKind
::Method
=> {
473 let fn_data
= if let hir
::TraitItemKind
::Method(_
, ref m
) = ast_item
.node
{
474 let arg_names
= match *m
{
475 hir
::TraitMethod
::Required(ref names
) => {
476 self.encode_fn_arg_names(names
)
478 hir
::TraitMethod
::Provided(body
) => {
479 self.encode_fn_arg_names_for_body(body
)
483 constness
: hir
::Constness
::NotConst
,
489 EntryKind
::Method(self.lazy(&MethodData
{
491 container
: container
,
492 has_self
: trait_item
.method_has_self_argument
,
495 ty
::AssociatedKind
::Type
=> EntryKind
::AssociatedType(container
),
500 visibility
: self.lazy(&trait_item
.vis
),
501 span
: self.lazy(&ast_item
.span
),
502 attributes
: self.encode_attributes(&ast_item
.attrs
),
503 children
: LazySeq
::empty(),
504 stability
: self.encode_stability(def_id
),
505 deprecation
: self.encode_deprecation(def_id
),
507 ty
: match trait_item
.kind
{
508 ty
::AssociatedKind
::Const
|
509 ty
::AssociatedKind
::Method
=> {
510 Some(self.encode_item_type(def_id
))
512 ty
::AssociatedKind
::Type
=> {
513 if trait_item
.defaultness
.has_value() {
514 Some(self.encode_item_type(def_id
))
520 inherent_impls
: LazySeq
::empty(),
521 variances
: LazySeq
::empty(),
522 generics
: Some(self.encode_generics(def_id
)),
523 predicates
: Some(self.encode_predicates(def_id
)),
525 ast
: if let hir
::TraitItemKind
::Const(_
, Some(body
)) = ast_item
.node
{
526 Some(self.encode_body(body
))
530 mir
: self.encode_mir(def_id
),
534 fn encode_info_for_impl_item(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
535 debug
!("EntryBuilder::encode_info_for_impl_item({:?})", def_id
);
536 let node_id
= self.tcx
.hir
.as_local_node_id(def_id
).unwrap();
537 let ast_item
= self.tcx
.hir
.expect_impl_item(node_id
);
538 let impl_item
= self.tcx
.associated_item(def_id
);
540 let container
= match impl_item
.defaultness
{
541 hir
::Defaultness
::Default { has_value: true }
=> AssociatedContainer
::ImplDefault
,
542 hir
::Defaultness
::Final
=> AssociatedContainer
::ImplFinal
,
543 hir
::Defaultness
::Default { has_value: false }
=>
544 span_bug
!(ast_item
.span
, "impl items always have values (currently)"),
547 let kind
= match impl_item
.kind
{
548 ty
::AssociatedKind
::Const
=> {
549 EntryKind
::AssociatedConst(container
,
550 ty
::queries
::mir_const_qualif
::get(self.tcx
, ast_item
.span
, def_id
))
552 ty
::AssociatedKind
::Method
=> {
553 let fn_data
= if let hir
::ImplItemKind
::Method(ref sig
, body
) = ast_item
.node
{
555 constness
: sig
.constness
,
556 arg_names
: self.encode_fn_arg_names_for_body(body
),
561 EntryKind
::Method(self.lazy(&MethodData
{
563 container
: container
,
564 has_self
: impl_item
.method_has_self_argument
,
567 ty
::AssociatedKind
::Type
=> EntryKind
::AssociatedType(container
)
570 let (ast
, mir
) = if let hir
::ImplItemKind
::Const(_
, body
) = ast_item
.node
{
572 } else if let hir
::ImplItemKind
::Method(ref sig
, body
) = ast_item
.node
{
573 let generics
= self.tcx
.item_generics(def_id
);
574 let types
= generics
.parent_types
as usize + generics
.types
.len();
575 let needs_inline
= types
> 0 || attr
::requests_inline(&ast_item
.attrs
);
576 let is_const_fn
= sig
.constness
== hir
::Constness
::Const
;
577 let ast
= if is_const_fn { Some(body) }
else { None }
;
578 let always_encode_mir
= self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
579 (ast
, needs_inline
|| is_const_fn
|| always_encode_mir
)
586 visibility
: self.lazy(&impl_item
.vis
),
587 span
: self.lazy(&ast_item
.span
),
588 attributes
: self.encode_attributes(&ast_item
.attrs
),
589 children
: LazySeq
::empty(),
590 stability
: self.encode_stability(def_id
),
591 deprecation
: self.encode_deprecation(def_id
),
593 ty
: Some(self.encode_item_type(def_id
)),
594 inherent_impls
: LazySeq
::empty(),
595 variances
: LazySeq
::empty(),
596 generics
: Some(self.encode_generics(def_id
)),
597 predicates
: Some(self.encode_predicates(def_id
)),
599 ast
: ast
.map(|body
| self.encode_body(body
)),
600 mir
: if mir { self.encode_mir(def_id) }
else { None }
,
604 fn encode_fn_arg_names_for_body(&mut self, body_id
: hir
::BodyId
)
605 -> LazySeq
<ast
::Name
> {
606 let _ignore
= self.tcx
.dep_graph
.in_ignore();
607 let body
= self.tcx
.hir
.body(body_id
);
608 self.lazy_seq(body
.arguments
.iter().map(|arg
| {
610 PatKind
::Binding(_
, _
, name
, _
) => name
.node
,
611 _
=> Symbol
::intern("")
616 fn encode_fn_arg_names(&mut self, names
: &[Spanned
<ast
::Name
>])
617 -> LazySeq
<ast
::Name
> {
618 self.lazy_seq(names
.iter().map(|name
| name
.node
))
621 fn encode_mir(&mut self, def_id
: DefId
) -> Option
<Lazy
<mir
::Mir
<'tcx
>>> {
622 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
623 self.tcx
.maps
.mir
.borrow().get(&def_id
).map(|mir
| self.lazy(&*mir
.borrow()))
626 // Encodes the inherent implementations of a structure, enumeration, or trait.
627 fn encode_inherent_implementations(&mut self, def_id
: DefId
) -> LazySeq
<DefIndex
> {
628 debug
!("EntryBuilder::encode_inherent_implementations({:?})", def_id
);
629 match self.tcx
.maps
.inherent_impls
.borrow().get(&def_id
) {
630 None
=> LazySeq
::empty(),
631 Some(implementations
) => {
632 self.lazy_seq(implementations
.iter().map(|&def_id
| {
633 assert
!(def_id
.is_local());
640 fn encode_stability(&mut self, def_id
: DefId
) -> Option
<Lazy
<attr
::Stability
>> {
641 debug
!("EntryBuilder::encode_stability({:?})", def_id
);
642 self.tcx
.lookup_stability(def_id
).map(|stab
| self.lazy(stab
))
645 fn encode_deprecation(&mut self, def_id
: DefId
) -> Option
<Lazy
<attr
::Deprecation
>> {
646 debug
!("EntryBuilder::encode_deprecation({:?})", def_id
);
647 self.tcx
.lookup_deprecation(def_id
).map(|depr
| self.lazy(&depr
))
650 fn encode_info_for_item(&mut self, (def_id
, item
): (DefId
, &'tcx hir
::Item
)) -> Entry
<'tcx
> {
653 debug
!("EntryBuilder::encode_info_for_item({:?})", def_id
);
655 let kind
= match item
.node
{
656 hir
::ItemStatic(_
, hir
::MutMutable
, _
) => EntryKind
::MutStatic
,
657 hir
::ItemStatic(_
, hir
::MutImmutable
, _
) => EntryKind
::ImmStatic
,
658 hir
::ItemConst(..) => {
659 EntryKind
::Const(ty
::queries
::mir_const_qualif
::get(tcx
, item
.span
, def_id
))
661 hir
::ItemFn(_
, _
, constness
, .., body
) => {
663 constness
: constness
,
664 arg_names
: self.encode_fn_arg_names_for_body(body
),
667 EntryKind
::Fn(self.lazy(&data
))
669 hir
::ItemMod(ref m
) => {
670 return self.encode_info_for_mod(FromId(item
.id
, (m
, &item
.attrs
, &item
.vis
)));
672 hir
::ItemForeignMod(_
) => EntryKind
::ForeignMod
,
673 hir
::ItemGlobalAsm(..) => EntryKind
::GlobalAsm
,
674 hir
::ItemTy(..) => EntryKind
::Type
,
675 hir
::ItemEnum(..) => EntryKind
::Enum(get_repr_options(&tcx
, def_id
)),
676 hir
::ItemStruct(ref struct_def
, _
) => {
677 let variant
= tcx
.lookup_adt_def(def_id
).struct_variant();
679 // Encode def_ids for each field and method
680 // for methods, write all the stuff get_trait_method
682 let struct_ctor
= if !struct_def
.is_struct() {
683 Some(tcx
.hir
.local_def_id(struct_def
.id()).index
)
688 let repr_options
= get_repr_options(&tcx
, def_id
);
690 EntryKind
::Struct(self.lazy(&VariantData
{
691 ctor_kind
: variant
.ctor_kind
,
692 discr
: variant
.discr
,
693 struct_ctor
: struct_ctor
,
696 hir
::ItemUnion(..) => {
697 let variant
= tcx
.lookup_adt_def(def_id
).struct_variant();
698 let repr_options
= get_repr_options(&tcx
, def_id
);
700 EntryKind
::Union(self.lazy(&VariantData
{
701 ctor_kind
: variant
.ctor_kind
,
702 discr
: variant
.discr
,
706 hir
::ItemDefaultImpl(..) => {
707 let data
= ImplData
{
708 polarity
: hir
::ImplPolarity
::Positive
,
710 coerce_unsized_info
: None
,
711 trait_ref
: tcx
.impl_trait_ref(def_id
).map(|trait_ref
| self.lazy(&trait_ref
)),
714 EntryKind
::DefaultImpl(self.lazy(&data
))
716 hir
::ItemImpl(_
, polarity
, ..) => {
717 let trait_ref
= tcx
.impl_trait_ref(def_id
);
718 let parent
= if let Some(trait_ref
) = trait_ref
{
719 let trait_def
= tcx
.lookup_trait_def(trait_ref
.def_id
);
720 trait_def
.ancestors(def_id
).skip(1).next().and_then(|node
| {
722 specialization_graph
::Node
::Impl(parent
) => Some(parent
),
730 // if this is an impl of `CoerceUnsized`, create its
731 // "unsized info", else just store None
732 let coerce_unsized_info
=
733 trait_ref
.and_then(|t
| {
734 if Some(t
.def_id
) == tcx
.lang_items
.coerce_unsized_trait() {
735 Some(ty
::queries
::coerce_unsized_info
::get(tcx
, item
.span
, def_id
))
741 let data
= ImplData
{
744 coerce_unsized_info
: coerce_unsized_info
,
745 trait_ref
: trait_ref
.map(|trait_ref
| self.lazy(&trait_ref
)),
748 EntryKind
::Impl(self.lazy(&data
))
750 hir
::ItemTrait(..) => {
751 let trait_def
= tcx
.lookup_trait_def(def_id
);
752 let data
= TraitData
{
753 unsafety
: trait_def
.unsafety
,
754 paren_sugar
: trait_def
.paren_sugar
,
755 has_default_impl
: tcx
.trait_has_default_impl(def_id
),
756 super_predicates
: self.lazy(&tcx
.item_super_predicates(def_id
)),
759 EntryKind
::Trait(self.lazy(&data
))
761 hir
::ItemExternCrate(_
) |
762 hir
::ItemUse(..) => bug
!("cannot encode info for item {:?}", item
),
767 visibility
: self.lazy(&ty
::Visibility
::from_hir(&item
.vis
, item
.id
, tcx
)),
768 span
: self.lazy(&item
.span
),
769 attributes
: self.encode_attributes(&item
.attrs
),
770 children
: match item
.node
{
771 hir
::ItemForeignMod(ref fm
) => {
772 self.lazy_seq(fm
.items
774 .map(|foreign_item
| tcx
.hir
.local_def_id(foreign_item
.id
).index
))
776 hir
::ItemEnum(..) => {
777 let def
= self.tcx
.lookup_adt_def(def_id
);
778 self.lazy_seq(def
.variants
.iter().map(|v
| {
779 assert
!(v
.did
.is_local());
783 hir
::ItemStruct(..) |
784 hir
::ItemUnion(..) => {
785 let def
= self.tcx
.lookup_adt_def(def_id
);
786 self.lazy_seq(def
.struct_variant().fields
.iter().map(|f
| {
787 assert
!(f
.did
.is_local());
792 hir
::ItemTrait(..) => {
793 self.lazy_seq(tcx
.associated_item_def_ids(def_id
).iter().map(|&def_id
| {
794 assert
!(def_id
.is_local());
798 _
=> LazySeq
::empty(),
800 stability
: self.encode_stability(def_id
),
801 deprecation
: self.encode_deprecation(def_id
),
803 ty
: match item
.node
{
804 hir
::ItemStatic(..) |
809 hir
::ItemStruct(..) |
811 hir
::ItemImpl(..) => Some(self.encode_item_type(def_id
)),
814 inherent_impls
: self.encode_inherent_implementations(def_id
),
815 variances
: match item
.node
{
817 hir
::ItemStruct(..) |
819 hir
::ItemTrait(..) => self.encode_item_variances(def_id
),
820 _
=> LazySeq
::empty(),
822 generics
: match item
.node
{
823 hir
::ItemStatic(..) |
828 hir
::ItemStruct(..) |
831 hir
::ItemTrait(..) => Some(self.encode_generics(def_id
)),
834 predicates
: match item
.node
{
835 hir
::ItemStatic(..) |
840 hir
::ItemStruct(..) |
843 hir
::ItemTrait(..) => Some(self.encode_predicates(def_id
)),
847 ast
: match item
.node
{
848 hir
::ItemConst(_
, body
) |
849 hir
::ItemFn(_
, _
, hir
::Constness
::Const
, _
, _
, body
) => {
850 Some(self.encode_body(body
))
854 mir
: match item
.node
{
855 hir
::ItemStatic(..) if self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
=> {
856 self.encode_mir(def_id
)
858 hir
::ItemConst(..) => self.encode_mir(def_id
),
859 hir
::ItemFn(_
, _
, constness
, _
, ref generics
, _
) => {
860 let tps_len
= generics
.ty_params
.len();
861 let needs_inline
= tps_len
> 0 || attr
::requests_inline(&item
.attrs
);
862 let always_encode_mir
= self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
863 if needs_inline
|| constness
== hir
::Constness
::Const
|| always_encode_mir
{
864 self.encode_mir(def_id
)
874 /// Serialize the text of exported macros
875 fn encode_info_for_macro_def(&mut self, macro_def
: &hir
::MacroDef
) -> Entry
<'tcx
> {
876 use syntax
::print
::pprust
;
878 kind
: EntryKind
::MacroDef(self.lazy(&MacroDef
{
879 body
: pprust
::tts_to_string(¯o_def
.body
.trees().collect
::<Vec
<_
>>()),
881 visibility
: self.lazy(&ty
::Visibility
::Public
),
882 span
: self.lazy(¯o_def
.span
),
884 attributes
: self.encode_attributes(¯o_def
.attrs
),
885 children
: LazySeq
::empty(),
889 inherent_impls
: LazySeq
::empty(),
890 variances
: LazySeq
::empty(),
899 impl<'a
, 'b
, 'tcx
> IndexBuilder
<'a
, 'b
, 'tcx
> {
900 /// In some cases, along with the item itself, we also
901 /// encode some sub-items. Usually we want some info from the item
902 /// so it's easier to do that here then to wait until we would encounter
903 /// normally in the visitor walk.
904 fn encode_addl_info_for_item(&mut self, item
: &hir
::Item
) {
905 let def_id
= self.tcx
.hir
.local_def_id(item
.id
);
907 hir
::ItemStatic(..) |
911 hir
::ItemForeignMod(..) |
912 hir
::ItemGlobalAsm(..) |
913 hir
::ItemExternCrate(..) |
915 hir
::ItemDefaultImpl(..) |
917 // no sub-item recording needed in these cases
919 hir
::ItemEnum(..) => {
920 self.encode_fields(def_id
);
922 let def
= self.tcx
.lookup_adt_def(def_id
);
923 for (i
, variant
) in def
.variants
.iter().enumerate() {
924 self.record(variant
.did
,
925 EntryBuilder
::encode_enum_variant_info
,
926 (def_id
, Untracked(i
)));
929 hir
::ItemStruct(ref struct_def
, _
) => {
930 self.encode_fields(def_id
);
932 // If the struct has a constructor, encode it.
933 if !struct_def
.is_struct() {
934 let ctor_def_id
= self.tcx
.hir
.local_def_id(struct_def
.id());
935 self.record(ctor_def_id
,
936 EntryBuilder
::encode_struct_ctor
,
937 (def_id
, ctor_def_id
));
940 hir
::ItemUnion(..) => {
941 self.encode_fields(def_id
);
943 hir
::ItemImpl(..) => {
944 for &trait_item_def_id
in self.tcx
.associated_item_def_ids(def_id
).iter() {
945 self.record(trait_item_def_id
,
946 EntryBuilder
::encode_info_for_impl_item
,
950 hir
::ItemTrait(..) => {
951 for &item_def_id
in self.tcx
.associated_item_def_ids(def_id
).iter() {
952 self.record(item_def_id
,
953 EntryBuilder
::encode_info_for_trait_item
,
961 impl<'a
, 'b
: 'a
, 'tcx
: 'b
> EntryBuilder
<'a
, 'b
, 'tcx
> {
962 fn encode_info_for_foreign_item(&mut self,
963 (def_id
, nitem
): (DefId
, &hir
::ForeignItem
))
967 debug
!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id
);
969 let kind
= match nitem
.node
{
970 hir
::ForeignItemFn(_
, ref names
, _
) => {
972 constness
: hir
::Constness
::NotConst
,
973 arg_names
: self.encode_fn_arg_names(names
),
975 EntryKind
::ForeignFn(self.lazy(&data
))
977 hir
::ForeignItemStatic(_
, true) => EntryKind
::ForeignMutStatic
,
978 hir
::ForeignItemStatic(_
, false) => EntryKind
::ForeignImmStatic
,
983 visibility
: self.lazy(&ty
::Visibility
::from_hir(&nitem
.vis
, nitem
.id
, tcx
)),
984 span
: self.lazy(&nitem
.span
),
985 attributes
: self.encode_attributes(&nitem
.attrs
),
986 children
: LazySeq
::empty(),
987 stability
: self.encode_stability(def_id
),
988 deprecation
: self.encode_deprecation(def_id
),
990 ty
: Some(self.encode_item_type(def_id
)),
991 inherent_impls
: LazySeq
::empty(),
992 variances
: LazySeq
::empty(),
993 generics
: Some(self.encode_generics(def_id
)),
994 predicates
: Some(self.encode_predicates(def_id
)),
1002 struct EncodeVisitor
<'a
, 'b
: 'a
, 'tcx
: 'b
> {
1003 index
: IndexBuilder
<'a
, 'b
, 'tcx
>,
1006 impl<'a
, 'b
, 'tcx
> Visitor
<'tcx
> for EncodeVisitor
<'a
, 'b
, 'tcx
> {
1007 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
1008 NestedVisitorMap
::OnlyBodies(&self.index
.tcx
.hir
)
1010 fn visit_expr(&mut self, ex
: &'tcx hir
::Expr
) {
1011 intravisit
::walk_expr(self, ex
);
1012 self.index
.encode_info_for_expr(ex
);
1014 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
1015 intravisit
::walk_item(self, item
);
1016 let def_id
= self.index
.tcx
.hir
.local_def_id(item
.id
);
1018 hir
::ItemExternCrate(_
) |
1019 hir
::ItemUse(..) => (), // ignore these
1020 _
=> self.index
.record(def_id
, EntryBuilder
::encode_info_for_item
, (def_id
, item
)),
1022 self.index
.encode_addl_info_for_item(item
);
1024 fn visit_foreign_item(&mut self, ni
: &'tcx hir
::ForeignItem
) {
1025 intravisit
::walk_foreign_item(self, ni
);
1026 let def_id
= self.index
.tcx
.hir
.local_def_id(ni
.id
);
1027 self.index
.record(def_id
,
1028 EntryBuilder
::encode_info_for_foreign_item
,
1031 fn visit_variant(&mut self,
1032 v
: &'tcx hir
::Variant
,
1033 g
: &'tcx hir
::Generics
,
1035 intravisit
::walk_variant(self, v
, g
, id
);
1037 if let Some(discr
) = v
.node
.disr_expr
{
1038 let def_id
= self.index
.tcx
.hir
.body_owner_def_id(discr
);
1039 self.index
.record(def_id
, EntryBuilder
::encode_info_for_embedded_const
, def_id
);
1042 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
) {
1043 intravisit
::walk_generics(self, generics
);
1044 self.index
.encode_info_for_generics(generics
);
1046 fn visit_ty(&mut self, ty
: &'tcx hir
::Ty
) {
1047 intravisit
::walk_ty(self, ty
);
1048 self.index
.encode_info_for_ty(ty
);
1050 fn visit_macro_def(&mut self, macro_def
: &'tcx hir
::MacroDef
) {
1051 let def_id
= self.index
.tcx
.hir
.local_def_id(macro_def
.id
);
1052 self.index
.record(def_id
, EntryBuilder
::encode_info_for_macro_def
, macro_def
);
1056 impl<'a
, 'b
, 'tcx
> IndexBuilder
<'a
, 'b
, 'tcx
> {
1057 fn encode_info_for_generics(&mut self, generics
: &hir
::Generics
) {
1058 for ty_param
in &generics
.ty_params
{
1059 let def_id
= self.tcx
.hir
.local_def_id(ty_param
.id
);
1060 let has_default
= Untracked(ty_param
.default.is_some());
1061 self.record(def_id
, EntryBuilder
::encode_info_for_ty_param
, (def_id
, has_default
));
1065 fn encode_info_for_ty(&mut self, ty
: &hir
::Ty
) {
1066 if let hir
::TyImplTrait(_
) = ty
.node
{
1067 let def_id
= self.tcx
.hir
.local_def_id(ty
.id
);
1068 self.record(def_id
, EntryBuilder
::encode_info_for_anon_ty
, def_id
);
1072 fn encode_info_for_expr(&mut self, expr
: &hir
::Expr
) {
1074 hir
::ExprClosure(..) => {
1075 let def_id
= self.tcx
.hir
.local_def_id(expr
.id
);
1076 self.record(def_id
, EntryBuilder
::encode_info_for_closure
, def_id
);
1083 impl<'a
, 'b
: 'a
, 'tcx
: 'b
> EntryBuilder
<'a
, 'b
, 'tcx
> {
1084 fn encode_info_for_ty_param(&mut self,
1085 (def_id
, Untracked(has_default
)): (DefId
, Untracked
<bool
>))
1087 debug
!("EntryBuilder::encode_info_for_ty_param({:?})", def_id
);
1090 kind
: EntryKind
::Type
,
1091 visibility
: self.lazy(&ty
::Visibility
::Public
),
1092 span
: self.lazy(&tcx
.def_span(def_id
)),
1093 attributes
: LazySeq
::empty(),
1094 children
: LazySeq
::empty(),
1098 ty
: if has_default
{
1099 Some(self.encode_item_type(def_id
))
1103 inherent_impls
: LazySeq
::empty(),
1104 variances
: LazySeq
::empty(),
1113 fn encode_info_for_anon_ty(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
1114 debug
!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id
);
1117 kind
: EntryKind
::Type
,
1118 visibility
: self.lazy(&ty
::Visibility
::Public
),
1119 span
: self.lazy(&tcx
.def_span(def_id
)),
1120 attributes
: LazySeq
::empty(),
1121 children
: LazySeq
::empty(),
1125 ty
: Some(self.encode_item_type(def_id
)),
1126 inherent_impls
: LazySeq
::empty(),
1127 variances
: LazySeq
::empty(),
1128 generics
: Some(self.encode_generics(def_id
)),
1129 predicates
: Some(self.encode_predicates(def_id
)),
1136 fn encode_info_for_closure(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
1137 debug
!("EntryBuilder::encode_info_for_closure({:?})", def_id
);
1140 let data
= ClosureData
{
1141 kind
: tcx
.closure_kind(def_id
),
1142 ty
: self.lazy(&tcx
.closure_type(def_id
)),
1146 kind
: EntryKind
::Closure(self.lazy(&data
)),
1147 visibility
: self.lazy(&ty
::Visibility
::Public
),
1148 span
: self.lazy(&tcx
.def_span(def_id
)),
1149 attributes
: self.encode_attributes(&tcx
.get_attrs(def_id
)),
1150 children
: LazySeq
::empty(),
1154 ty
: Some(self.encode_item_type(def_id
)),
1155 inherent_impls
: LazySeq
::empty(),
1156 variances
: LazySeq
::empty(),
1157 generics
: Some(self.encode_generics(def_id
)),
1161 mir
: self.encode_mir(def_id
),
1165 fn encode_info_for_embedded_const(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
1166 debug
!("EntryBuilder::encode_info_for_embedded_const({:?})", def_id
);
1168 let id
= tcx
.hir
.as_local_node_id(def_id
).unwrap();
1169 let body
= tcx
.hir
.body_owned_by(id
);
1172 kind
: EntryKind
::Const(ty
::queries
::mir_const_qualif
::get(tcx
, DUMMY_SP
, def_id
)),
1173 visibility
: self.lazy(&ty
::Visibility
::Public
),
1174 span
: self.lazy(&tcx
.def_span(def_id
)),
1175 attributes
: LazySeq
::empty(),
1176 children
: LazySeq
::empty(),
1180 ty
: Some(self.encode_item_type(def_id
)),
1181 inherent_impls
: LazySeq
::empty(),
1182 variances
: LazySeq
::empty(),
1183 generics
: Some(self.encode_generics(def_id
)),
1184 predicates
: Some(self.encode_predicates(def_id
)),
1186 ast
: Some(self.encode_body(body
)),
1187 mir
: self.encode_mir(def_id
),
1191 fn encode_attributes(&mut self, attrs
: &[ast
::Attribute
]) -> LazySeq
<ast
::Attribute
> {
1192 // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
1193 // we really on the HashStable specialization for [Attribute]
1194 // to properly filter things out.
1195 self.lazy_seq_from_slice(attrs
)
1199 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
1200 fn encode_info_for_items(&mut self) -> Index
{
1201 let krate
= self.tcx
.hir
.krate();
1202 let mut index
= IndexBuilder
::new(self);
1203 index
.record(DefId
::local(CRATE_DEF_INDEX
),
1204 EntryBuilder
::encode_info_for_mod
,
1205 FromId(CRATE_NODE_ID
, (&krate
.module
, &krate
.attrs
, &hir
::Public
)));
1206 let mut visitor
= EncodeVisitor { index: index }
;
1207 krate
.visit_all_item_likes(&mut visitor
.as_deep_visitor());
1208 for macro_def
in &krate
.exported_macros
{
1209 visitor
.visit_macro_def(macro_def
);
1211 visitor
.index
.into_items()
1214 fn encode_crate_deps(&mut self) -> LazySeq
<CrateDep
> {
1215 fn get_ordered_deps(cstore
: &cstore
::CStore
) -> Vec
<(CrateNum
, Rc
<cstore
::CrateMetadata
>)> {
1216 // Pull the cnums and name,vers,hash out of cstore
1217 let mut deps
= Vec
::new();
1218 cstore
.iter_crate_data(|cnum
, val
| {
1219 deps
.push((cnum
, val
.clone()));
1223 deps
.sort_by(|kv1
, kv2
| kv1
.0
.cmp(&kv2
.0
));
1225 // Sanity-check the crate numbers
1226 let mut expected_cnum
= 1;
1227 for &(n
, _
) in &deps
{
1228 assert_eq
!(n
, CrateNum
::new(expected_cnum
));
1235 // We're just going to write a list of crate 'name-hash-version's, with
1236 // the assumption that they are numbered 1 to n.
1237 // FIXME (#2166): This is not nearly enough to support correct versioning
1238 // but is enough to get transitive crate dependencies working.
1239 let deps
= get_ordered_deps(self.cstore
);
1240 self.lazy_seq(deps
.iter().map(|&(_
, ref dep
)| {
1244 kind
: dep
.dep_kind
.get(),
1249 fn encode_lang_items(&mut self) -> (LazySeq
<(DefIndex
, usize)>, LazySeq
<lang_items
::LangItem
>) {
1251 let lang_items
= tcx
.lang_items
.items().iter();
1252 (self.lazy_seq(lang_items
.enumerate().filter_map(|(i
, &opt_def_id
)| {
1253 if let Some(def_id
) = opt_def_id
{
1254 if def_id
.is_local() {
1255 return Some((def_id
.index
, i
));
1260 self.lazy_seq_ref(&tcx
.lang_items
.missing
))
1263 fn encode_native_libraries(&mut self) -> LazySeq
<NativeLibrary
> {
1264 let used_libraries
= self.tcx
.sess
.cstore
.used_libraries();
1265 self.lazy_seq(used_libraries
)
1268 fn encode_codemap(&mut self) -> LazySeq
<syntax_pos
::FileMap
> {
1269 let codemap
= self.tcx
.sess
.codemap();
1270 let all_filemaps
= codemap
.files
.borrow();
1271 self.lazy_seq_ref(all_filemaps
.iter()
1273 // No need to re-export imported filemaps, as any downstream
1274 // crate will import them from their original source.
1275 !filemap
.is_imported()
1277 .map(|filemap
| &**filemap
))
1280 fn encode_def_path_table(&mut self) -> Lazy
<DefPathTable
> {
1281 let definitions
= self.tcx
.hir
.definitions();
1282 self.lazy(definitions
.def_path_table())
1286 struct ImplVisitor
<'a
, 'tcx
: 'a
> {
1287 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1288 impls
: FxHashMap
<DefId
, Vec
<DefIndex
>>,
1291 impl<'a
, 'tcx
, 'v
> ItemLikeVisitor
<'v
> for ImplVisitor
<'a
, 'tcx
> {
1292 fn visit_item(&mut self, item
: &hir
::Item
) {
1293 if let hir
::ItemImpl(..) = item
.node
{
1294 let impl_id
= self.tcx
.hir
.local_def_id(item
.id
);
1295 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(impl_id
) {
1297 .entry(trait_ref
.def_id
)
1299 .push(impl_id
.index
);
1304 fn visit_trait_item(&mut self, _trait_item
: &'v hir
::TraitItem
) {}
1306 fn visit_impl_item(&mut self, _impl_item
: &'v hir
::ImplItem
) {
1307 // handled in `visit_item` above
1311 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
1312 /// Encodes an index, mapping each trait to its (local) implementations.
1313 fn encode_impls(&mut self) -> LazySeq
<TraitImpls
> {
1314 let mut visitor
= ImplVisitor
{
1318 self.tcx
.hir
.krate().visit_all_item_likes(&mut visitor
);
1320 let all_impls
: Vec
<_
> = visitor
.impls
1322 .map(|(trait_def_id
, impls
)| {
1324 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
1325 impls
: self.lazy_seq(impls
),
1330 self.lazy_seq(all_impls
)
1333 // Encodes all symbols exported from this crate into the metadata.
1335 // This pass is seeded off the reachability list calculated in the
1336 // middle::reachable module but filters out items that either don't have a
1337 // symbol associated with them (they weren't translated) or if they're an FFI
1338 // definition (as that's not defined in this crate).
1339 fn encode_exported_symbols(&mut self) -> LazySeq
<DefIndex
> {
1340 let exported_symbols
= self.exported_symbols
;
1342 self.lazy_seq(exported_symbols
.iter().map(|&id
| tcx
.hir
.local_def_id(id
).index
))
1345 fn encode_dylib_dependency_formats(&mut self) -> LazySeq
<Option
<LinkagePreference
>> {
1346 match self.tcx
.sess
.dependency_formats
.borrow().get(&config
::CrateTypeDylib
) {
1348 self.lazy_seq(arr
.iter().map(|slot
| {
1350 Linkage
::NotLinked
|
1351 Linkage
::IncludedFromDylib
=> None
,
1353 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
1354 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
1358 None
=> LazySeq
::empty(),
1363 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
1364 fn encode_crate_root(&mut self) -> Lazy
<CrateRoot
> {
1365 let mut i
= self.position();
1366 let crate_deps
= self.encode_crate_deps();
1367 let dylib_dependency_formats
= self.encode_dylib_dependency_formats();
1368 let dep_bytes
= self.position() - i
;
1370 // Encode the language items.
1371 i
= self.position();
1372 let (lang_items
, lang_items_missing
) = self.encode_lang_items();
1373 let lang_item_bytes
= self.position() - i
;
1375 // Encode the native libraries used
1376 i
= self.position();
1377 let native_libraries
= self.encode_native_libraries();
1378 let native_lib_bytes
= self.position() - i
;
1381 i
= self.position();
1382 let codemap
= self.encode_codemap();
1383 let codemap_bytes
= self.position() - i
;
1385 // Encode DefPathTable
1386 i
= self.position();
1387 let def_path_table
= self.encode_def_path_table();
1388 let def_path_table_bytes
= self.position() - i
;
1390 // Encode the def IDs of impls, for coherence checking.
1391 i
= self.position();
1392 let impls
= self.encode_impls();
1393 let impl_bytes
= self.position() - i
;
1395 // Encode exported symbols info.
1396 i
= self.position();
1397 let exported_symbols
= self.encode_exported_symbols();
1398 let exported_symbols_bytes
= self.position() - i
;
1400 // Encode and index the items.
1401 i
= self.position();
1402 let items
= self.encode_info_for_items();
1403 let item_bytes
= self.position() - i
;
1405 i
= self.position();
1406 let index
= items
.write_index(&mut self.opaque
.cursor
);
1407 let index_bytes
= self.position() - i
;
1410 let link_meta
= self.link_meta
;
1411 let is_proc_macro
= tcx
.sess
.crate_types
.borrow().contains(&CrateTypeProcMacro
);
1412 let root
= self.lazy(&CrateRoot
{
1413 name
: tcx
.crate_name(LOCAL_CRATE
),
1414 triple
: tcx
.sess
.opts
.target_triple
.clone(),
1415 hash
: link_meta
.crate_hash
,
1416 disambiguator
: tcx
.sess
.local_crate_disambiguator(),
1417 panic_strategy
: tcx
.sess
.panic_strategy(),
1418 plugin_registrar_fn
: tcx
.sess
1419 .plugin_registrar_fn
1421 .map(|id
| tcx
.hir
.local_def_id(id
).index
),
1422 macro_derive_registrar
: if is_proc_macro
{
1423 let id
= tcx
.sess
.derive_registrar_fn
.get().unwrap();
1424 Some(tcx
.hir
.local_def_id(id
).index
)
1429 crate_deps
: crate_deps
,
1430 dylib_dependency_formats
: dylib_dependency_formats
,
1431 lang_items
: lang_items
,
1432 lang_items_missing
: lang_items_missing
,
1433 native_libraries
: native_libraries
,
1435 def_path_table
: def_path_table
,
1437 exported_symbols
: exported_symbols
,
1441 let total_bytes
= self.position();
1443 if self.tcx
.sess
.meta_stats() {
1444 let mut zero_bytes
= 0;
1445 for e
in self.opaque
.cursor
.get_ref() {
1451 println
!("metadata stats:");
1452 println
!(" dep bytes: {}", dep_bytes
);
1453 println
!(" lang item bytes: {}", lang_item_bytes
);
1454 println
!(" native bytes: {}", native_lib_bytes
);
1455 println
!(" codemap bytes: {}", codemap_bytes
);
1456 println
!(" impl bytes: {}", impl_bytes
);
1457 println
!(" exp. symbols bytes: {}", exported_symbols_bytes
);
1458 println
!(" def-path table bytes: {}", def_path_table_bytes
);
1459 println
!(" item bytes: {}", item_bytes
);
1460 println
!(" index bytes: {}", index_bytes
);
1461 println
!(" zero bytes: {}", zero_bytes
);
1462 println
!(" total bytes: {}", total_bytes
);
1469 // NOTE(eddyb) The following comment was preserved for posterity, even
1470 // though it's no longer relevant as EBML (which uses nested & tagged
1471 // "documents") was replaced with a scheme that can't go out of bounds.
1473 // And here we run into yet another obscure archive bug: in which metadata
1474 // loaded from archives may have trailing garbage bytes. Awhile back one of
1475 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
1476 // and opt) by having ebml generate an out-of-bounds panic when looking at
1479 // Upon investigation it turned out that the metadata file inside of an rlib
1480 // (and ar archive) was being corrupted. Some compilations would generate a
1481 // metadata file which would end in a few extra bytes, while other
1482 // compilations would not have these extra bytes appended to the end. These
1483 // extra bytes were interpreted by ebml as an extra tag, so they ended up
1484 // being interpreted causing the out-of-bounds.
1486 // The root cause of why these extra bytes were appearing was never
1487 // discovered, and in the meantime the solution we're employing is to insert
1488 // the length of the metadata to the start of the metadata. Later on this
1489 // will allow us to slice the metadata to the precise length that we just
1490 // generated regardless of trailing bytes that end up in it.
1492 pub fn encode_metadata
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1493 cstore
: &cstore
::CStore
,
1494 link_meta
: &LinkMeta
,
1495 exported_symbols
: &NodeSet
)
1498 let mut cursor
= Cursor
::new(vec
![]);
1499 cursor
.write_all(METADATA_HEADER
).unwrap();
1501 // Will be filed with the root position after encoding everything.
1502 cursor
.write_all(&[0, 0, 0, 0]).unwrap();
1504 let (root
, metadata_hashes
) = {
1505 let mut ecx
= EncodeContext
{
1506 opaque
: opaque
::Encoder
::new(&mut cursor
),
1508 link_meta
: link_meta
,
1510 exported_symbols
: exported_symbols
,
1511 lazy_state
: LazyState
::NoNode
,
1512 type_shorthands
: Default
::default(),
1513 predicate_shorthands
: Default
::default(),
1514 metadata_hashes
: Vec
::new(),
1517 // Encode the rustc version string in a predictable location.
1518 rustc_version().encode(&mut ecx
).unwrap();
1520 // Encode all the entries and extra information in the crate,
1521 // culminating in the `CrateRoot` which points to all of it.
1522 let root
= ecx
.encode_crate_root();
1523 (root
, ecx
.metadata_hashes
)
1525 let mut result
= cursor
.into_inner();
1527 // Encode the root position.
1528 let header
= METADATA_HEADER
.len();
1529 let pos
= root
.position
;
1530 result
[header
+ 0] = (pos
>> 24) as u8;
1531 result
[header
+ 1] = (pos
>> 16) as u8;
1532 result
[header
+ 2] = (pos
>> 8) as u8;
1533 result
[header
+ 3] = (pos
>> 0) as u8;
1537 hashes
: metadata_hashes
,
1541 pub fn get_repr_options
<'a
, 'tcx
, 'gcx
>(tcx
: &TyCtxt
<'a
, 'tcx
, 'gcx
>, did
: DefId
) -> ReprOptions
{
1542 let ty
= tcx
.item_type(did
);
1544 ty
::TyAdt(ref def
, _
) => return def
.repr
,
1545 _
=> bug
!("{} is not an ADT", ty
),