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.
12 use index_builder
::{FromId, IndexBuilder, Untracked}
;
13 use isolated_encoder
::IsolatedEncoder
;
16 use rustc
::middle
::cstore
::{LinkMeta
, LinkagePreference
, NativeLibrary
,
17 EncodedMetadata
, EncodedMetadataHashes
,
19 use rustc
::hir
::def
::CtorKind
;
20 use rustc
::hir
::def_id
::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE}
;
21 use rustc
::hir
::map
::definitions
::{DefPathTable, GlobalMetaDataKind}
;
22 use rustc
::ich
::Fingerprint
;
23 use rustc
::middle
::dependency_format
::Linkage
;
24 use rustc
::middle
::lang_items
;
26 use rustc
::traits
::specialization_graph
;
27 use rustc
::ty
::{self, Ty, TyCtxt, ReprOptions}
;
29 use rustc
::session
::config
::{self, CrateTypeProcMacro}
;
30 use rustc
::util
::nodemap
::{FxHashMap, NodeSet}
;
32 use rustc_serialize
::{Encodable, Encoder, SpecializedEncoder, opaque}
;
36 use std
::io
::prelude
::*;
41 use syntax
::ast
::{self, CRATE_NODE_ID}
;
42 use syntax
::codemap
::Spanned
;
44 use syntax
::symbol
::Symbol
;
47 use rustc
::hir
::{self, PatKind}
;
48 use rustc
::hir
::itemlikevisit
::ItemLikeVisitor
;
49 use rustc
::hir
::intravisit
::{Visitor, NestedVisitorMap}
;
50 use rustc
::hir
::intravisit
;
52 pub struct EncodeContext
<'a
, 'tcx
: 'a
> {
53 opaque
: opaque
::Encoder
<'a
>,
54 pub tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
55 link_meta
: &'a LinkMeta
,
56 exported_symbols
: &'a NodeSet
,
58 lazy_state
: LazyState
,
59 type_shorthands
: FxHashMap
<Ty
<'tcx
>, usize>,
60 predicate_shorthands
: FxHashMap
<ty
::Predicate
<'tcx
>, usize>,
62 pub metadata_hashes
: EncodedMetadataHashes
,
63 pub compute_ich
: bool
,
66 macro_rules
! encoder_methods
{
67 ($
($name
:ident($ty
:ty
);)*) => {
68 $
(fn $
name(&mut self, value
: $ty
) -> Result
<(), Self::Error
> {
69 self.opaque
.$
name(value
)
74 impl<'a
, 'tcx
> Encoder
for EncodeContext
<'a
, 'tcx
> {
75 type Error
= <opaque
::Encoder
<'a
> as Encoder
>::Error
;
77 fn emit_nil(&mut self) -> Result
<(), Self::Error
> {
104 impl<'a
, 'tcx
, T
> SpecializedEncoder
<Lazy
<T
>> for EncodeContext
<'a
, 'tcx
> {
105 fn specialized_encode(&mut self, lazy
: &Lazy
<T
>) -> Result
<(), Self::Error
> {
106 self.emit_lazy_distance(lazy
.position
, Lazy
::<T
>::min_size())
110 impl<'a
, 'tcx
, T
> SpecializedEncoder
<LazySeq
<T
>> for EncodeContext
<'a
, 'tcx
> {
111 fn specialized_encode(&mut self, seq
: &LazySeq
<T
>) -> Result
<(), Self::Error
> {
112 self.emit_usize(seq
.len
)?
;
116 self.emit_lazy_distance(seq
.position
, LazySeq
::<T
>::min_size(seq
.len
))
120 impl<'a
, 'tcx
> SpecializedEncoder
<Ty
<'tcx
>> for EncodeContext
<'a
, 'tcx
> {
121 fn specialized_encode(&mut self, ty
: &Ty
<'tcx
>) -> Result
<(), Self::Error
> {
122 self.encode_with_shorthand(ty
, &ty
.sty
, |ecx
| &mut ecx
.type_shorthands
)
126 impl<'a
, 'tcx
> SpecializedEncoder
<ty
::GenericPredicates
<'tcx
>> for EncodeContext
<'a
, 'tcx
> {
127 fn specialized_encode(&mut self,
128 predicates
: &ty
::GenericPredicates
<'tcx
>)
129 -> Result
<(), Self::Error
> {
130 predicates
.parent
.encode(self)?
;
131 predicates
.predicates
.len().encode(self)?
;
132 for predicate
in &predicates
.predicates
{
133 self.encode_with_shorthand(predicate
, predicate
, |ecx
| &mut ecx
.predicate_shorthands
)?
139 impl<'a
, 'tcx
> EncodeContext
<'a
, 'tcx
> {
141 pub fn position(&self) -> usize {
142 self.opaque
.position()
145 fn emit_node
<F
: FnOnce(&mut Self, usize) -> R
, R
>(&mut self, f
: F
) -> R
{
146 assert_eq
!(self.lazy_state
, LazyState
::NoNode
);
147 let pos
= self.position();
148 self.lazy_state
= LazyState
::NodeStart(pos
);
149 let r
= f(self, pos
);
150 self.lazy_state
= LazyState
::NoNode
;
154 fn emit_lazy_distance(&mut self,
157 -> Result
<(), <Self as Encoder
>::Error
> {
158 let min_end
= position
+ min_size
;
159 let distance
= match self.lazy_state
{
160 LazyState
::NoNode
=> bug
!("emit_lazy_distance: outside of a metadata node"),
161 LazyState
::NodeStart(start
) => {
162 assert
!(min_end
<= start
);
165 LazyState
::Previous(last_min_end
) => {
166 assert
!(last_min_end
<= position
);
167 position
- last_min_end
170 self.lazy_state
= LazyState
::Previous(min_end
);
171 self.emit_usize(distance
)
174 pub fn lazy
<T
: Encodable
>(&mut self, value
: &T
) -> Lazy
<T
> {
175 self.emit_node(|ecx
, pos
| {
176 value
.encode(ecx
).unwrap();
178 assert
!(pos
+ Lazy
::<T
>::min_size() <= ecx
.position());
179 Lazy
::with_position(pos
)
183 pub fn lazy_seq
<I
, T
>(&mut self, iter
: I
) -> LazySeq
<T
>
184 where I
: IntoIterator
<Item
= T
>,
187 self.emit_node(|ecx
, pos
| {
188 let len
= iter
.into_iter().map(|value
| value
.encode(ecx
).unwrap()).count();
190 assert
!(pos
+ LazySeq
::<T
>::min_size(len
) <= ecx
.position());
191 LazySeq
::with_position_and_length(pos
, len
)
195 pub fn lazy_seq_ref
<'b
, I
, T
>(&mut self, iter
: I
) -> LazySeq
<T
>
196 where I
: IntoIterator
<Item
= &'b T
>,
199 self.emit_node(|ecx
, pos
| {
200 let len
= iter
.into_iter().map(|value
| value
.encode(ecx
).unwrap()).count();
202 assert
!(pos
+ LazySeq
::<T
>::min_size(len
) <= ecx
.position());
203 LazySeq
::with_position_and_length(pos
, len
)
207 /// Encode the given value or a previously cached shorthand.
208 fn encode_with_shorthand
<T
, U
, M
>(&mut self,
212 -> Result
<(), <Self as Encoder
>::Error
>
213 where M
: for<'b
> Fn(&'b
mut Self) -> &'b
mut FxHashMap
<T
, usize>,
214 T
: Clone
+ Eq
+ Hash
,
217 let existing_shorthand
= map(self).get(value
).cloned();
218 if let Some(shorthand
) = existing_shorthand
{
219 return self.emit_usize(shorthand
);
222 let start
= self.position();
223 variant
.encode(self)?
;
224 let len
= self.position() - start
;
226 // The shorthand encoding uses the same usize as the
227 // discriminant, with an offset so they can't conflict.
228 let discriminant
= unsafe { intrinsics::discriminant_value(variant) }
;
229 assert
!(discriminant
< SHORTHAND_OFFSET
as u64);
230 let shorthand
= start
+ SHORTHAND_OFFSET
;
232 // Get the number of bits that leb128 could fit
233 // in the same space as the fully encoded type.
234 let leb128_bits
= len
* 7;
236 // Check that the shorthand is a not longer than the
237 // full encoding itself, i.e. it's an obvious win.
238 if leb128_bits
>= 64 || (shorthand
as u64) < (1 << leb128_bits
) {
239 map(self).insert(value
.clone(), shorthand
);
245 // Encodes something that corresponds to a single DepNode::GlobalMetaData
246 // and registers the Fingerprint in the `metadata_hashes` map.
247 pub fn tracked
<'x
, DATA
, R
>(&'x
mut self,
249 op
: fn(&mut IsolatedEncoder
<'x
, 'a
, 'tcx
>, DATA
) -> R
,
252 let mut entry_builder
= IsolatedEncoder
::new(self);
253 let ret
= op(&mut entry_builder
, data
);
254 let (fingerprint
, this
) = entry_builder
.finish();
256 if let Some(fingerprint
) = fingerprint
{
257 this
.metadata_hashes
.hashes
.push(EncodedMetadataHash
{
266 fn encode_info_for_items(&mut self) -> Index
{
267 let krate
= self.tcx
.hir
.krate();
268 let mut index
= IndexBuilder
::new(self);
269 index
.record(DefId
::local(CRATE_DEF_INDEX
),
270 IsolatedEncoder
::encode_info_for_mod
,
271 FromId(CRATE_NODE_ID
, (&krate
.module
, &krate
.attrs
, &hir
::Public
)));
272 let mut visitor
= EncodeVisitor { index: index }
;
273 krate
.visit_all_item_likes(&mut visitor
.as_deep_visitor());
274 for macro_def
in &krate
.exported_macros
{
275 visitor
.visit_macro_def(macro_def
);
277 visitor
.index
.into_items()
280 fn encode_def_path_table(&mut self) -> Lazy
<DefPathTable
> {
281 let definitions
= self.tcx
.hir
.definitions();
282 self.lazy(definitions
.def_path_table())
285 fn encode_codemap(&mut self) -> LazySeq
<syntax_pos
::FileMap
> {
286 let codemap
= self.tcx
.sess
.codemap();
287 let all_filemaps
= codemap
.files();
289 let (working_dir
, working_dir_was_remapped
) = self.tcx
.sess
.working_dir
.clone();
291 let adapted
= all_filemaps
.iter()
293 // No need to re-export imported filemaps, as any downstream
294 // crate will import them from their original source.
295 !filemap
.is_imported()
298 // When exporting FileMaps, we expand all paths to absolute
299 // paths because any relative paths are potentially relative to
300 // a wrong directory.
301 // However, if a path has been modified via
302 // `-Zremap-path-prefix` we assume the user has already set
303 // things up the way they want and don't touch the path values
305 let name
= Path
::new(&filemap
.name
);
306 if filemap
.name_was_remapped
||
307 (name
.is_relative() && working_dir_was_remapped
) {
308 // This path of this FileMap has been modified by
309 // path-remapping, so we use it verbatim (and avoid cloning
310 // the whole map in the process).
313 let mut adapted
= (**filemap
).clone();
314 let abs_path
= Path
::new(&working_dir
).join(name
)
317 adapted
.name
= abs_path
;
321 .collect
::<Vec
<_
>>();
323 self.lazy_seq_ref(adapted
.iter().map(|rc
| &**rc
))
326 fn encode_crate_root(&mut self) -> Lazy
<CrateRoot
> {
327 let mut i
= self.position();
330 let global_metadata_def_index
= move |kind
: GlobalMetaDataKind
| {
331 kind
.def_index(tcx
.hir
.definitions().def_path_table())
334 let crate_deps
= self.tracked(
335 global_metadata_def_index(GlobalMetaDataKind
::CrateDeps
),
336 IsolatedEncoder
::encode_crate_deps
,
338 let dylib_dependency_formats
= self.tracked(
339 global_metadata_def_index(GlobalMetaDataKind
::DylibDependencyFormats
),
340 IsolatedEncoder
::encode_dylib_dependency_formats
,
342 let dep_bytes
= self.position() - i
;
344 // Encode the language items.
346 let lang_items
= self.tracked(
347 global_metadata_def_index(GlobalMetaDataKind
::LangItems
),
348 IsolatedEncoder
::encode_lang_items
,
351 let lang_items_missing
= self.tracked(
352 global_metadata_def_index(GlobalMetaDataKind
::LangItemsMissing
),
353 IsolatedEncoder
::encode_lang_items_missing
,
355 let lang_item_bytes
= self.position() - i
;
357 // Encode the native libraries used
359 let native_libraries
= self.tracked(
360 global_metadata_def_index(GlobalMetaDataKind
::NativeLibraries
),
361 IsolatedEncoder
::encode_native_libraries
,
363 let native_lib_bytes
= self.position() - i
;
367 let codemap
= self.encode_codemap();
368 let codemap_bytes
= self.position() - i
;
370 // Encode DefPathTable
372 let def_path_table
= self.encode_def_path_table();
373 let def_path_table_bytes
= self.position() - i
;
375 // Encode the def IDs of impls, for coherence checking.
377 let impls
= self.tracked(
378 global_metadata_def_index(GlobalMetaDataKind
::Impls
),
379 IsolatedEncoder
::encode_impls
,
381 let impl_bytes
= self.position() - i
;
383 // Encode exported symbols info.
385 let exported_symbols
= self.tracked(
386 global_metadata_def_index(GlobalMetaDataKind
::ExportedSymbols
),
387 IsolatedEncoder
::encode_exported_symbols
,
388 self.exported_symbols
);
389 let exported_symbols_bytes
= self.position() - i
;
391 // Encode and index the items.
393 let items
= self.encode_info_for_items();
394 let item_bytes
= self.position() - i
;
397 let index
= items
.write_index(&mut self.opaque
.cursor
);
398 let index_bytes
= self.position() - i
;
401 let link_meta
= self.link_meta
;
402 let is_proc_macro
= tcx
.sess
.crate_types
.borrow().contains(&CrateTypeProcMacro
);
403 let has_default_lib_allocator
=
404 attr
::contains_name(tcx
.hir
.krate_attrs(), "default_lib_allocator");
405 let has_global_allocator
= tcx
.sess
.has_global_allocator
.get();
406 let root
= self.lazy(&CrateRoot
{
407 name
: tcx
.crate_name(LOCAL_CRATE
),
408 triple
: tcx
.sess
.opts
.target_triple
.clone(),
409 hash
: link_meta
.crate_hash
,
410 disambiguator
: tcx
.sess
.local_crate_disambiguator(),
411 panic_strategy
: Tracked
::new(tcx
.sess
.panic_strategy()),
412 has_global_allocator
: Tracked
::new(has_global_allocator
),
413 has_default_lib_allocator
: Tracked
::new(has_default_lib_allocator
),
414 plugin_registrar_fn
: tcx
.sess
417 .map(|id
| tcx
.hir
.local_def_id(id
).index
),
418 macro_derive_registrar
: if is_proc_macro
{
419 let id
= tcx
.sess
.derive_registrar_fn
.get().unwrap();
420 Some(tcx
.hir
.local_def_id(id
).index
)
426 dylib_dependency_formats
,
437 let total_bytes
= self.position();
439 self.metadata_hashes
.hashes
.push(EncodedMetadataHash
{
440 def_index
: global_metadata_def_index(GlobalMetaDataKind
::Krate
),
441 hash
: Fingerprint
::from_smaller_hash(link_meta
.crate_hash
.as_u64())
444 if self.tcx
.sess
.meta_stats() {
445 let mut zero_bytes
= 0;
446 for e
in self.opaque
.cursor
.get_ref() {
452 println
!("metadata stats:");
453 println
!(" dep bytes: {}", dep_bytes
);
454 println
!(" lang item bytes: {}", lang_item_bytes
);
455 println
!(" native bytes: {}", native_lib_bytes
);
456 println
!(" codemap bytes: {}", codemap_bytes
);
457 println
!(" impl bytes: {}", impl_bytes
);
458 println
!(" exp. symbols bytes: {}", exported_symbols_bytes
);
459 println
!(" def-path table bytes: {}", def_path_table_bytes
);
460 println
!(" item bytes: {}", item_bytes
);
461 println
!(" index bytes: {}", index_bytes
);
462 println
!(" zero bytes: {}", zero_bytes
);
463 println
!(" total bytes: {}", total_bytes
);
470 // These are methods for encoding various things. They are meant to be used with
471 // IndexBuilder::record() and EncodeContext::tracked(). They actually
472 // would not have to be methods of IsolatedEncoder (free standing functions
473 // taking IsolatedEncoder as first argument would be just fine) but by making
474 // them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>`
475 // clause again and again.
476 impl<'a
, 'b
: 'a
, 'tcx
: 'b
> IsolatedEncoder
<'a
, 'b
, 'tcx
> {
477 fn encode_variances_of(&mut self, def_id
: DefId
) -> LazySeq
<ty
::Variance
> {
478 debug
!("IsolatedEncoder::encode_variances_of({:?})", def_id
);
480 self.lazy_seq_from_slice(&tcx
.variances_of(def_id
))
483 fn encode_item_type(&mut self, def_id
: DefId
) -> Lazy
<Ty
<'tcx
>> {
485 let ty
= tcx
.type_of(def_id
);
486 debug
!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id
, ty
);
490 /// Encode data for the given variant of the given ADT. The
491 /// index of the variant is untracked: this is ok because we
492 /// will have to lookup the adt-def by its id, and that gives us
493 /// the right to access any information in the adt-def (including,
494 /// e.g., the length of the various vectors).
495 fn encode_enum_variant_info(&mut self,
496 (enum_did
, Untracked(index
)): (DefId
, Untracked
<usize>))
499 let def
= tcx
.adt_def(enum_did
);
500 let variant
= &def
.variants
[index
];
501 let def_id
= variant
.did
;
502 debug
!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id
);
504 let data
= VariantData
{
505 ctor_kind
: variant
.ctor_kind
,
506 discr
: variant
.discr
,
508 ctor_sig
: if variant
.ctor_kind
== CtorKind
::Fn
{
509 Some(self.lazy(&tcx
.fn_sig(def_id
)))
515 let enum_id
= tcx
.hir
.as_local_node_id(enum_did
).unwrap();
516 let enum_vis
= &tcx
.hir
.expect_item(enum_id
).vis
;
519 kind
: EntryKind
::Variant(self.lazy(&data
)),
520 visibility
: self.lazy(&ty
::Visibility
::from_hir(enum_vis
, enum_id
, tcx
)),
521 span
: self.lazy(&tcx
.def_span(def_id
)),
522 attributes
: self.encode_attributes(&tcx
.get_attrs(def_id
)),
523 children
: self.lazy_seq(variant
.fields
.iter().map(|f
| {
524 assert
!(f
.did
.is_local());
527 stability
: self.encode_stability(def_id
),
528 deprecation
: self.encode_deprecation(def_id
),
530 ty
: Some(self.encode_item_type(def_id
)),
531 inherent_impls
: LazySeq
::empty(),
532 variances
: if variant
.ctor_kind
== CtorKind
::Fn
{
533 self.encode_variances_of(def_id
)
537 generics
: Some(self.encode_generics(def_id
)),
538 predicates
: Some(self.encode_predicates(def_id
)),
541 mir
: self.encode_optimized_mir(def_id
),
545 fn encode_info_for_mod(&mut self,
546 FromId(id
, (md
, attrs
, vis
)): FromId
<(&hir
::Mod
,
551 let def_id
= tcx
.hir
.local_def_id(id
);
552 debug
!("IsolatedEncoder::encode_info_for_mod({:?})", def_id
);
555 reexports
: match tcx
.export_map
.get(&id
) {
556 Some(exports
) if *vis
== hir
::Public
=> {
557 self.lazy_seq_from_slice(exports
.as_slice())
559 _
=> LazySeq
::empty(),
564 kind
: EntryKind
::Mod(self.lazy(&data
)),
565 visibility
: self.lazy(&ty
::Visibility
::from_hir(vis
, id
, tcx
)),
566 span
: self.lazy(&tcx
.def_span(def_id
)),
567 attributes
: self.encode_attributes(attrs
),
568 children
: self.lazy_seq(md
.item_ids
.iter().map(|item_id
| {
569 tcx
.hir
.local_def_id(item_id
.id
).index
571 stability
: self.encode_stability(def_id
),
572 deprecation
: self.encode_deprecation(def_id
),
575 inherent_impls
: LazySeq
::empty(),
576 variances
: LazySeq
::empty(),
585 /// Encode data for the given field of the given variant of the
586 /// given ADT. The indices of the variant/field are untracked:
587 /// this is ok because we will have to lookup the adt-def by its
588 /// id, and that gives us the right to access any information in
589 /// the adt-def (including, e.g., the length of the various
591 fn encode_field(&mut self,
592 (adt_def_id
, Untracked((variant_index
, field_index
))): (DefId
,
597 let variant
= &tcx
.adt_def(adt_def_id
).variants
[variant_index
];
598 let field
= &variant
.fields
[field_index
];
600 let def_id
= field
.did
;
601 debug
!("IsolatedEncoder::encode_field({:?})", def_id
);
603 let variant_id
= tcx
.hir
.as_local_node_id(variant
.did
).unwrap();
604 let variant_data
= tcx
.hir
.expect_variant_data(variant_id
);
607 kind
: EntryKind
::Field
,
608 visibility
: self.lazy(&field
.vis
),
609 span
: self.lazy(&tcx
.def_span(def_id
)),
610 attributes
: self.encode_attributes(&variant_data
.fields()[field_index
].attrs
),
611 children
: LazySeq
::empty(),
612 stability
: self.encode_stability(def_id
),
613 deprecation
: self.encode_deprecation(def_id
),
615 ty
: Some(self.encode_item_type(def_id
)),
616 inherent_impls
: LazySeq
::empty(),
617 variances
: LazySeq
::empty(),
618 generics
: Some(self.encode_generics(def_id
)),
619 predicates
: Some(self.encode_predicates(def_id
)),
626 fn encode_struct_ctor(&mut self, (adt_def_id
, def_id
): (DefId
, DefId
)) -> Entry
<'tcx
> {
627 debug
!("IsolatedEncoder::encode_struct_ctor({:?})", def_id
);
629 let variant
= tcx
.adt_def(adt_def_id
).struct_variant();
631 let data
= VariantData
{
632 ctor_kind
: variant
.ctor_kind
,
633 discr
: variant
.discr
,
634 struct_ctor
: Some(def_id
.index
),
635 ctor_sig
: if variant
.ctor_kind
== CtorKind
::Fn
{
636 Some(self.lazy(&tcx
.fn_sig(def_id
)))
642 let struct_id
= tcx
.hir
.as_local_node_id(adt_def_id
).unwrap();
643 let struct_vis
= &tcx
.hir
.expect_item(struct_id
).vis
;
644 let mut ctor_vis
= ty
::Visibility
::from_hir(struct_vis
, struct_id
, tcx
);
645 for field
in &variant
.fields
{
646 if ctor_vis
.is_at_least(field
.vis
, tcx
) {
647 ctor_vis
= field
.vis
;
651 let repr_options
= get_repr_options(&tcx
, adt_def_id
);
654 kind
: EntryKind
::Struct(self.lazy(&data
), repr_options
),
655 visibility
: self.lazy(&ctor_vis
),
656 span
: self.lazy(&tcx
.def_span(def_id
)),
657 attributes
: LazySeq
::empty(),
658 children
: LazySeq
::empty(),
659 stability
: self.encode_stability(def_id
),
660 deprecation
: self.encode_deprecation(def_id
),
662 ty
: Some(self.encode_item_type(def_id
)),
663 inherent_impls
: LazySeq
::empty(),
664 variances
: if variant
.ctor_kind
== CtorKind
::Fn
{
665 self.encode_variances_of(def_id
)
669 generics
: Some(self.encode_generics(def_id
)),
670 predicates
: Some(self.encode_predicates(def_id
)),
673 mir
: self.encode_optimized_mir(def_id
),
677 fn encode_generics(&mut self, def_id
: DefId
) -> Lazy
<ty
::Generics
> {
678 debug
!("IsolatedEncoder::encode_generics({:?})", def_id
);
680 self.lazy(tcx
.generics_of(def_id
))
683 fn encode_predicates(&mut self, def_id
: DefId
) -> Lazy
<ty
::GenericPredicates
<'tcx
>> {
684 debug
!("IsolatedEncoder::encode_predicates({:?})", def_id
);
686 self.lazy(&tcx
.predicates_of(def_id
))
689 fn encode_info_for_trait_item(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
690 debug
!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id
);
693 let node_id
= tcx
.hir
.as_local_node_id(def_id
).unwrap();
694 let ast_item
= tcx
.hir
.expect_trait_item(node_id
);
695 let trait_item
= tcx
.associated_item(def_id
);
697 let container
= match trait_item
.defaultness
{
698 hir
::Defaultness
::Default { has_value: true }
=>
699 AssociatedContainer
::TraitWithDefault
,
700 hir
::Defaultness
::Default { has_value: false }
=>
701 AssociatedContainer
::TraitRequired
,
702 hir
::Defaultness
::Final
=>
703 span_bug
!(ast_item
.span
, "traits cannot have final items"),
706 let kind
= match trait_item
.kind
{
707 ty
::AssociatedKind
::Const
=> {
708 EntryKind
::AssociatedConst(container
, 0)
710 ty
::AssociatedKind
::Method
=> {
711 let fn_data
= if let hir
::TraitItemKind
::Method(_
, ref m
) = ast_item
.node
{
712 let arg_names
= match *m
{
713 hir
::TraitMethod
::Required(ref names
) => {
714 self.encode_fn_arg_names(names
)
716 hir
::TraitMethod
::Provided(body
) => {
717 self.encode_fn_arg_names_for_body(body
)
721 constness
: hir
::Constness
::NotConst
,
723 sig
: self.lazy(&tcx
.fn_sig(def_id
)),
728 EntryKind
::Method(self.lazy(&MethodData
{
731 has_self
: trait_item
.method_has_self_argument
,
734 ty
::AssociatedKind
::Type
=> EntryKind
::AssociatedType(container
),
739 visibility
: self.lazy(&trait_item
.vis
),
740 span
: self.lazy(&ast_item
.span
),
741 attributes
: self.encode_attributes(&ast_item
.attrs
),
742 children
: LazySeq
::empty(),
743 stability
: self.encode_stability(def_id
),
744 deprecation
: self.encode_deprecation(def_id
),
746 ty
: match trait_item
.kind
{
747 ty
::AssociatedKind
::Const
|
748 ty
::AssociatedKind
::Method
=> {
749 Some(self.encode_item_type(def_id
))
751 ty
::AssociatedKind
::Type
=> {
752 if trait_item
.defaultness
.has_value() {
753 Some(self.encode_item_type(def_id
))
759 inherent_impls
: LazySeq
::empty(),
760 variances
: if trait_item
.kind
== ty
::AssociatedKind
::Method
{
761 self.encode_variances_of(def_id
)
765 generics
: Some(self.encode_generics(def_id
)),
766 predicates
: Some(self.encode_predicates(def_id
)),
768 ast
: if let hir
::TraitItemKind
::Const(_
, Some(body
)) = ast_item
.node
{
769 Some(self.encode_body(body
))
773 mir
: self.encode_optimized_mir(def_id
),
777 fn encode_info_for_impl_item(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
778 debug
!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id
);
781 let node_id
= self.tcx
.hir
.as_local_node_id(def_id
).unwrap();
782 let ast_item
= self.tcx
.hir
.expect_impl_item(node_id
);
783 let impl_item
= self.tcx
.associated_item(def_id
);
785 let container
= match impl_item
.defaultness
{
786 hir
::Defaultness
::Default { has_value: true }
=> AssociatedContainer
::ImplDefault
,
787 hir
::Defaultness
::Final
=> AssociatedContainer
::ImplFinal
,
788 hir
::Defaultness
::Default { has_value: false }
=>
789 span_bug
!(ast_item
.span
, "impl items always have values (currently)"),
792 let kind
= match impl_item
.kind
{
793 ty
::AssociatedKind
::Const
=> {
794 EntryKind
::AssociatedConst(container
,
795 self.tcx
.at(ast_item
.span
).mir_const_qualif(def_id
))
797 ty
::AssociatedKind
::Method
=> {
798 let fn_data
= if let hir
::ImplItemKind
::Method(ref sig
, body
) = ast_item
.node
{
800 constness
: sig
.constness
,
801 arg_names
: self.encode_fn_arg_names_for_body(body
),
802 sig
: self.lazy(&tcx
.fn_sig(def_id
)),
807 EntryKind
::Method(self.lazy(&MethodData
{
810 has_self
: impl_item
.method_has_self_argument
,
813 ty
::AssociatedKind
::Type
=> EntryKind
::AssociatedType(container
)
816 let (ast
, mir
) = if let hir
::ImplItemKind
::Const(_
, body
) = ast_item
.node
{
818 } else if let hir
::ImplItemKind
::Method(ref sig
, body
) = ast_item
.node
{
819 let generics
= self.tcx
.generics_of(def_id
);
820 let types
= generics
.parent_types
as usize + generics
.types
.len();
821 let needs_inline
= types
> 0 || attr
::requests_inline(&ast_item
.attrs
);
822 let is_const_fn
= sig
.constness
== hir
::Constness
::Const
;
823 let ast
= if is_const_fn { Some(body) }
else { None }
;
824 let always_encode_mir
= self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
825 (ast
, needs_inline
|| is_const_fn
|| always_encode_mir
)
832 visibility
: self.lazy(&impl_item
.vis
),
833 span
: self.lazy(&ast_item
.span
),
834 attributes
: self.encode_attributes(&ast_item
.attrs
),
835 children
: LazySeq
::empty(),
836 stability
: self.encode_stability(def_id
),
837 deprecation
: self.encode_deprecation(def_id
),
839 ty
: Some(self.encode_item_type(def_id
)),
840 inherent_impls
: LazySeq
::empty(),
841 variances
: if impl_item
.kind
== ty
::AssociatedKind
::Method
{
842 self.encode_variances_of(def_id
)
846 generics
: Some(self.encode_generics(def_id
)),
847 predicates
: Some(self.encode_predicates(def_id
)),
849 ast
: ast
.map(|body
| self.encode_body(body
)),
850 mir
: if mir { self.encode_optimized_mir(def_id) }
else { None }
,
854 fn encode_fn_arg_names_for_body(&mut self, body_id
: hir
::BodyId
)
855 -> LazySeq
<ast
::Name
> {
856 let _ignore
= self.tcx
.dep_graph
.in_ignore();
857 let body
= self.tcx
.hir
.body(body_id
);
858 self.lazy_seq(body
.arguments
.iter().map(|arg
| {
860 PatKind
::Binding(_
, _
, name
, _
) => name
.node
,
861 _
=> Symbol
::intern("")
866 fn encode_fn_arg_names(&mut self, names
: &[Spanned
<ast
::Name
>])
867 -> LazySeq
<ast
::Name
> {
868 self.lazy_seq(names
.iter().map(|name
| name
.node
))
871 fn encode_optimized_mir(&mut self, def_id
: DefId
) -> Option
<Lazy
<mir
::Mir
<'tcx
>>> {
872 debug
!("EntryBuilder::encode_mir({:?})", def_id
);
873 if self.tcx
.mir_keys(LOCAL_CRATE
).contains(&def_id
) {
874 let mir
= self.tcx
.optimized_mir(def_id
);
875 Some(self.lazy(&mir
))
881 // Encodes the inherent implementations of a structure, enumeration, or trait.
882 fn encode_inherent_implementations(&mut self, def_id
: DefId
) -> LazySeq
<DefIndex
> {
883 debug
!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id
);
884 let implementations
= self.tcx
.inherent_impls(def_id
);
885 if implementations
.is_empty() {
888 self.lazy_seq(implementations
.iter().map(|&def_id
| {
889 assert
!(def_id
.is_local());
895 fn encode_stability(&mut self, def_id
: DefId
) -> Option
<Lazy
<attr
::Stability
>> {
896 debug
!("IsolatedEncoder::encode_stability({:?})", def_id
);
897 self.tcx
.lookup_stability(def_id
).map(|stab
| self.lazy(stab
))
900 fn encode_deprecation(&mut self, def_id
: DefId
) -> Option
<Lazy
<attr
::Deprecation
>> {
901 debug
!("IsolatedEncoder::encode_deprecation({:?})", def_id
);
902 self.tcx
.lookup_deprecation(def_id
).map(|depr
| self.lazy(&depr
))
905 fn encode_info_for_item(&mut self, (def_id
, item
): (DefId
, &'tcx hir
::Item
)) -> Entry
<'tcx
> {
908 debug
!("IsolatedEncoder::encode_info_for_item({:?})", def_id
);
910 let kind
= match item
.node
{
911 hir
::ItemStatic(_
, hir
::MutMutable
, _
) => EntryKind
::MutStatic
,
912 hir
::ItemStatic(_
, hir
::MutImmutable
, _
) => EntryKind
::ImmStatic
,
913 hir
::ItemConst(..) => {
914 EntryKind
::Const(tcx
.at(item
.span
).mir_const_qualif(def_id
))
916 hir
::ItemFn(_
, _
, constness
, .., body
) => {
919 arg_names
: self.encode_fn_arg_names_for_body(body
),
920 sig
: self.lazy(&tcx
.fn_sig(def_id
)),
923 EntryKind
::Fn(self.lazy(&data
))
925 hir
::ItemMod(ref m
) => {
926 return self.encode_info_for_mod(FromId(item
.id
, (m
, &item
.attrs
, &item
.vis
)));
928 hir
::ItemForeignMod(_
) => EntryKind
::ForeignMod
,
929 hir
::ItemGlobalAsm(..) => EntryKind
::GlobalAsm
,
930 hir
::ItemTy(..) => EntryKind
::Type
,
931 hir
::ItemEnum(..) => EntryKind
::Enum(get_repr_options(&tcx
, def_id
)),
932 hir
::ItemStruct(ref struct_def
, _
) => {
933 let variant
= tcx
.adt_def(def_id
).struct_variant();
935 // Encode def_ids for each field and method
936 // for methods, write all the stuff get_trait_method
938 let struct_ctor
= if !struct_def
.is_struct() {
939 Some(tcx
.hir
.local_def_id(struct_def
.id()).index
)
944 let repr_options
= get_repr_options(&tcx
, def_id
);
946 EntryKind
::Struct(self.lazy(&VariantData
{
947 ctor_kind
: variant
.ctor_kind
,
948 discr
: variant
.discr
,
953 hir
::ItemUnion(..) => {
954 let variant
= tcx
.adt_def(def_id
).struct_variant();
955 let repr_options
= get_repr_options(&tcx
, def_id
);
957 EntryKind
::Union(self.lazy(&VariantData
{
958 ctor_kind
: variant
.ctor_kind
,
959 discr
: variant
.discr
,
964 hir
::ItemDefaultImpl(..) => {
965 let data
= ImplData
{
966 polarity
: hir
::ImplPolarity
::Positive
,
967 defaultness
: hir
::Defaultness
::Final
,
969 coerce_unsized_info
: None
,
970 trait_ref
: tcx
.impl_trait_ref(def_id
).map(|trait_ref
| self.lazy(&trait_ref
)),
973 EntryKind
::DefaultImpl(self.lazy(&data
))
975 hir
::ItemImpl(_
, polarity
, defaultness
, ..) => {
976 let trait_ref
= tcx
.impl_trait_ref(def_id
);
977 let parent
= if let Some(trait_ref
) = trait_ref
{
978 let trait_def
= tcx
.trait_def(trait_ref
.def_id
);
979 trait_def
.ancestors(tcx
, def_id
).skip(1).next().and_then(|node
| {
981 specialization_graph
::Node
::Impl(parent
) => Some(parent
),
989 // if this is an impl of `CoerceUnsized`, create its
990 // "unsized info", else just store None
991 let coerce_unsized_info
=
992 trait_ref
.and_then(|t
| {
993 if Some(t
.def_id
) == tcx
.lang_items
.coerce_unsized_trait() {
994 Some(tcx
.at(item
.span
).coerce_unsized_info(def_id
))
1000 let data
= ImplData
{
1003 parent_impl
: parent
,
1004 coerce_unsized_info
,
1005 trait_ref
: trait_ref
.map(|trait_ref
| self.lazy(&trait_ref
)),
1008 EntryKind
::Impl(self.lazy(&data
))
1010 hir
::ItemTrait(..) => {
1011 let trait_def
= tcx
.trait_def(def_id
);
1012 let data
= TraitData
{
1013 unsafety
: trait_def
.unsafety
,
1014 paren_sugar
: trait_def
.paren_sugar
,
1015 has_default_impl
: tcx
.trait_has_default_impl(def_id
),
1016 super_predicates
: self.lazy(&tcx
.super_predicates_of(def_id
)),
1019 EntryKind
::Trait(self.lazy(&data
))
1021 hir
::ItemExternCrate(_
) |
1022 hir
::ItemUse(..) => bug
!("cannot encode info for item {:?}", item
),
1027 visibility
: self.lazy(&ty
::Visibility
::from_hir(&item
.vis
, item
.id
, tcx
)),
1028 span
: self.lazy(&item
.span
),
1029 attributes
: self.encode_attributes(&item
.attrs
),
1030 children
: match item
.node
{
1031 hir
::ItemForeignMod(ref fm
) => {
1032 self.lazy_seq(fm
.items
1034 .map(|foreign_item
| tcx
.hir
.local_def_id(foreign_item
.id
).index
))
1036 hir
::ItemEnum(..) => {
1037 let def
= self.tcx
.adt_def(def_id
);
1038 self.lazy_seq(def
.variants
.iter().map(|v
| {
1039 assert
!(v
.did
.is_local());
1043 hir
::ItemStruct(..) |
1044 hir
::ItemUnion(..) => {
1045 let def
= self.tcx
.adt_def(def_id
);
1046 self.lazy_seq(def
.struct_variant().fields
.iter().map(|f
| {
1047 assert
!(f
.did
.is_local());
1052 hir
::ItemTrait(..) => {
1053 self.lazy_seq(tcx
.associated_item_def_ids(def_id
).iter().map(|&def_id
| {
1054 assert
!(def_id
.is_local());
1058 _
=> LazySeq
::empty(),
1060 stability
: self.encode_stability(def_id
),
1061 deprecation
: self.encode_deprecation(def_id
),
1063 ty
: match item
.node
{
1064 hir
::ItemStatic(..) |
1065 hir
::ItemConst(..) |
1069 hir
::ItemStruct(..) |
1070 hir
::ItemUnion(..) |
1071 hir
::ItemImpl(..) => Some(self.encode_item_type(def_id
)),
1074 inherent_impls
: self.encode_inherent_implementations(def_id
),
1075 variances
: match item
.node
{
1077 hir
::ItemStruct(..) |
1078 hir
::ItemUnion(..) |
1079 hir
::ItemFn(..) => self.encode_variances_of(def_id
),
1080 _
=> LazySeq
::empty(),
1082 generics
: match item
.node
{
1083 hir
::ItemStatic(..) |
1084 hir
::ItemConst(..) |
1088 hir
::ItemStruct(..) |
1089 hir
::ItemUnion(..) |
1091 hir
::ItemTrait(..) => Some(self.encode_generics(def_id
)),
1094 predicates
: match item
.node
{
1095 hir
::ItemStatic(..) |
1096 hir
::ItemConst(..) |
1100 hir
::ItemStruct(..) |
1101 hir
::ItemUnion(..) |
1103 hir
::ItemTrait(..) => Some(self.encode_predicates(def_id
)),
1107 ast
: match item
.node
{
1108 hir
::ItemConst(_
, body
) |
1109 hir
::ItemFn(_
, _
, hir
::Constness
::Const
, _
, _
, body
) => {
1110 Some(self.encode_body(body
))
1114 mir
: match item
.node
{
1115 hir
::ItemStatic(..) if self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
=> {
1116 self.encode_optimized_mir(def_id
)
1118 hir
::ItemConst(..) => self.encode_optimized_mir(def_id
),
1119 hir
::ItemFn(_
, _
, constness
, _
, ref generics
, _
) => {
1120 let tps_len
= generics
.ty_params
.len();
1121 let needs_inline
= tps_len
> 0 || attr
::requests_inline(&item
.attrs
);
1122 let always_encode_mir
= self.tcx
.sess
.opts
.debugging_opts
.always_encode_mir
;
1123 if needs_inline
|| constness
== hir
::Constness
::Const
|| always_encode_mir
{
1124 self.encode_optimized_mir(def_id
)
1134 /// Serialize the text of exported macros
1135 fn encode_info_for_macro_def(&mut self, macro_def
: &hir
::MacroDef
) -> Entry
<'tcx
> {
1136 use syntax
::print
::pprust
;
1137 let def_id
= self.tcx
.hir
.local_def_id(macro_def
.id
);
1139 kind
: EntryKind
::MacroDef(self.lazy(&MacroDef
{
1140 body
: pprust
::tts_to_string(¯o_def
.body
.trees().collect
::<Vec
<_
>>()),
1141 legacy
: macro_def
.legacy
,
1143 visibility
: self.lazy(&ty
::Visibility
::Public
),
1144 span
: self.lazy(¯o_def
.span
),
1145 attributes
: self.encode_attributes(¯o_def
.attrs
),
1146 stability
: self.encode_stability(def_id
),
1147 deprecation
: self.encode_deprecation(def_id
),
1149 children
: LazySeq
::empty(),
1151 inherent_impls
: LazySeq
::empty(),
1152 variances
: LazySeq
::empty(),
1160 fn encode_info_for_ty_param(&mut self,
1161 (def_id
, Untracked(has_default
)): (DefId
, Untracked
<bool
>))
1163 debug
!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id
);
1166 kind
: EntryKind
::Type
,
1167 visibility
: self.lazy(&ty
::Visibility
::Public
),
1168 span
: self.lazy(&tcx
.def_span(def_id
)),
1169 attributes
: LazySeq
::empty(),
1170 children
: LazySeq
::empty(),
1174 ty
: if has_default
{
1175 Some(self.encode_item_type(def_id
))
1179 inherent_impls
: LazySeq
::empty(),
1180 variances
: LazySeq
::empty(),
1189 fn encode_info_for_anon_ty(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
1190 debug
!("IsolatedEncoder::encode_info_for_anon_ty({:?})", def_id
);
1193 kind
: EntryKind
::Type
,
1194 visibility
: self.lazy(&ty
::Visibility
::Public
),
1195 span
: self.lazy(&tcx
.def_span(def_id
)),
1196 attributes
: LazySeq
::empty(),
1197 children
: LazySeq
::empty(),
1201 ty
: Some(self.encode_item_type(def_id
)),
1202 inherent_impls
: LazySeq
::empty(),
1203 variances
: LazySeq
::empty(),
1204 generics
: Some(self.encode_generics(def_id
)),
1205 predicates
: Some(self.encode_predicates(def_id
)),
1212 fn encode_info_for_closure(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
1213 debug
!("IsolatedEncoder::encode_info_for_closure({:?})", def_id
);
1216 let data
= ClosureData
{
1217 kind
: tcx
.closure_kind(def_id
),
1218 sig
: self.lazy(&tcx
.fn_sig(def_id
)),
1222 kind
: EntryKind
::Closure(self.lazy(&data
)),
1223 visibility
: self.lazy(&ty
::Visibility
::Public
),
1224 span
: self.lazy(&tcx
.def_span(def_id
)),
1225 attributes
: self.encode_attributes(&tcx
.get_attrs(def_id
)),
1226 children
: LazySeq
::empty(),
1230 ty
: Some(self.encode_item_type(def_id
)),
1231 inherent_impls
: LazySeq
::empty(),
1232 variances
: LazySeq
::empty(),
1233 generics
: Some(self.encode_generics(def_id
)),
1237 mir
: self.encode_optimized_mir(def_id
),
1241 fn encode_info_for_embedded_const(&mut self, def_id
: DefId
) -> Entry
<'tcx
> {
1242 debug
!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id
);
1244 let id
= tcx
.hir
.as_local_node_id(def_id
).unwrap();
1245 let body
= tcx
.hir
.body_owned_by(id
);
1248 kind
: EntryKind
::Const(tcx
.mir_const_qualif(def_id
)),
1249 visibility
: self.lazy(&ty
::Visibility
::Public
),
1250 span
: self.lazy(&tcx
.def_span(def_id
)),
1251 attributes
: LazySeq
::empty(),
1252 children
: LazySeq
::empty(),
1256 ty
: Some(self.encode_item_type(def_id
)),
1257 inherent_impls
: LazySeq
::empty(),
1258 variances
: LazySeq
::empty(),
1259 generics
: Some(self.encode_generics(def_id
)),
1260 predicates
: Some(self.encode_predicates(def_id
)),
1262 ast
: Some(self.encode_body(body
)),
1263 mir
: self.encode_optimized_mir(def_id
),
1267 fn encode_attributes(&mut self, attrs
: &[ast
::Attribute
]) -> LazySeq
<ast
::Attribute
> {
1268 // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
1269 // we rely on the HashStable specialization for [Attribute]
1270 // to properly filter things out.
1271 self.lazy_seq_from_slice(attrs
)
1274 fn encode_native_libraries(&mut self, _
: ()) -> LazySeq
<NativeLibrary
> {
1275 let used_libraries
= self.tcx
.sess
.cstore
.used_libraries();
1276 self.lazy_seq(used_libraries
)
1279 fn encode_crate_deps(&mut self, _
: ()) -> LazySeq
<CrateDep
> {
1280 let cstore
= &*self.tcx
.sess
.cstore
;
1281 let crates
= cstore
.crates();
1283 let mut deps
= crates
1286 let dep
= CrateDep
{
1287 name
: cstore
.original_crate_name(cnum
),
1288 hash
: cstore
.crate_hash(cnum
),
1289 kind
: cstore
.dep_kind(cnum
),
1293 .collect
::<Vec
<_
>>();
1295 deps
.sort_by_key(|&(cnum
, _
)| cnum
);
1298 // Sanity-check the crate numbers
1299 let mut expected_cnum
= 1;
1300 for &(n
, _
) in &deps
{
1301 assert_eq
!(n
, CrateNum
::new(expected_cnum
));
1306 // We're just going to write a list of crate 'name-hash-version's, with
1307 // the assumption that they are numbered 1 to n.
1308 // FIXME (#2166): This is not nearly enough to support correct versioning
1309 // but is enough to get transitive crate dependencies working.
1310 self.lazy_seq_ref(deps
.iter().map(|&(_
, ref dep
)| dep
))
1313 fn encode_lang_items(&mut self, _
: ()) -> LazySeq
<(DefIndex
, usize)> {
1315 let lang_items
= tcx
.lang_items
.items().iter();
1316 self.lazy_seq(lang_items
.enumerate().filter_map(|(i
, &opt_def_id
)| {
1317 if let Some(def_id
) = opt_def_id
{
1318 if def_id
.is_local() {
1319 return Some((def_id
.index
, i
));
1326 fn encode_lang_items_missing(&mut self, _
: ()) -> LazySeq
<lang_items
::LangItem
> {
1328 self.lazy_seq_ref(&tcx
.lang_items
.missing
)
1331 /// Encodes an index, mapping each trait to its (local) implementations.
1332 fn encode_impls(&mut self, _
: ()) -> LazySeq
<TraitImpls
> {
1333 debug
!("IsolatedEncoder::encode_impls()");
1335 let mut visitor
= ImplVisitor
{
1339 tcx
.hir
.krate().visit_all_item_likes(&mut visitor
);
1341 let mut all_impls
: Vec
<_
> = visitor
.impls
.into_iter().collect();
1343 // Bring everything into deterministic order for hashing
1344 all_impls
.sort_unstable_by_key(|&(trait_def_id
, _
)| {
1345 tcx
.def_path_hash(trait_def_id
)
1348 let all_impls
: Vec
<_
> = all_impls
1350 .map(|(trait_def_id
, mut impls
)| {
1351 // Bring everything into deterministic order for hashing
1352 impls
.sort_unstable_by_key(|&def_index
| {
1353 tcx
.hir
.definitions().def_path_hash(def_index
)
1357 trait_id
: (trait_def_id
.krate
.as_u32(), trait_def_id
.index
),
1358 impls
: self.lazy_seq_from_slice(&impls
[..]),
1363 self.lazy_seq_from_slice(&all_impls
[..])
1366 // Encodes all symbols exported from this crate into the metadata.
1368 // This pass is seeded off the reachability list calculated in the
1369 // middle::reachable module but filters out items that either don't have a
1370 // symbol associated with them (they weren't translated) or if they're an FFI
1371 // definition (as that's not defined in this crate).
1372 fn encode_exported_symbols(&mut self, exported_symbols
: &NodeSet
) -> LazySeq
<DefIndex
> {
1374 self.lazy_seq(exported_symbols
.iter().map(|&id
| tcx
.hir
.local_def_id(id
).index
))
1377 fn encode_dylib_dependency_formats(&mut self, _
: ()) -> LazySeq
<Option
<LinkagePreference
>> {
1378 match self.tcx
.sess
.dependency_formats
.borrow().get(&config
::CrateTypeDylib
) {
1380 self.lazy_seq(arr
.iter().map(|slot
| {
1382 Linkage
::NotLinked
|
1383 Linkage
::IncludedFromDylib
=> None
,
1385 Linkage
::Dynamic
=> Some(LinkagePreference
::RequireDynamic
),
1386 Linkage
::Static
=> Some(LinkagePreference
::RequireStatic
),
1390 None
=> LazySeq
::empty(),
1394 fn encode_info_for_foreign_item(&mut self,
1395 (def_id
, nitem
): (DefId
, &hir
::ForeignItem
))
1399 debug
!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id
);
1401 let kind
= match nitem
.node
{
1402 hir
::ForeignItemFn(_
, ref names
, _
) => {
1404 constness
: hir
::Constness
::NotConst
,
1405 arg_names
: self.encode_fn_arg_names(names
),
1406 sig
: self.lazy(&tcx
.fn_sig(def_id
)),
1408 EntryKind
::ForeignFn(self.lazy(&data
))
1410 hir
::ForeignItemStatic(_
, true) => EntryKind
::ForeignMutStatic
,
1411 hir
::ForeignItemStatic(_
, false) => EntryKind
::ForeignImmStatic
,
1416 visibility
: self.lazy(&ty
::Visibility
::from_hir(&nitem
.vis
, nitem
.id
, tcx
)),
1417 span
: self.lazy(&nitem
.span
),
1418 attributes
: self.encode_attributes(&nitem
.attrs
),
1419 children
: LazySeq
::empty(),
1420 stability
: self.encode_stability(def_id
),
1421 deprecation
: self.encode_deprecation(def_id
),
1423 ty
: Some(self.encode_item_type(def_id
)),
1424 inherent_impls
: LazySeq
::empty(),
1425 variances
: match nitem
.node
{
1426 hir
::ForeignItemFn(..) => self.encode_variances_of(def_id
),
1427 _
=> LazySeq
::empty(),
1429 generics
: Some(self.encode_generics(def_id
)),
1430 predicates
: Some(self.encode_predicates(def_id
)),
1438 struct EncodeVisitor
<'a
, 'b
: 'a
, 'tcx
: 'b
> {
1439 index
: IndexBuilder
<'a
, 'b
, 'tcx
>,
1442 impl<'a
, 'b
, 'tcx
> Visitor
<'tcx
> for EncodeVisitor
<'a
, 'b
, 'tcx
> {
1443 fn nested_visit_map
<'this
>(&'this
mut self) -> NestedVisitorMap
<'this
, 'tcx
> {
1444 NestedVisitorMap
::OnlyBodies(&self.index
.tcx
.hir
)
1446 fn visit_expr(&mut self, ex
: &'tcx hir
::Expr
) {
1447 intravisit
::walk_expr(self, ex
);
1448 self.index
.encode_info_for_expr(ex
);
1450 fn visit_item(&mut self, item
: &'tcx hir
::Item
) {
1451 intravisit
::walk_item(self, item
);
1452 let def_id
= self.index
.tcx
.hir
.local_def_id(item
.id
);
1454 hir
::ItemExternCrate(_
) |
1455 hir
::ItemUse(..) => (), // ignore these
1456 _
=> self.index
.record(def_id
, IsolatedEncoder
::encode_info_for_item
, (def_id
, item
)),
1458 self.index
.encode_addl_info_for_item(item
);
1460 fn visit_foreign_item(&mut self, ni
: &'tcx hir
::ForeignItem
) {
1461 intravisit
::walk_foreign_item(self, ni
);
1462 let def_id
= self.index
.tcx
.hir
.local_def_id(ni
.id
);
1463 self.index
.record(def_id
,
1464 IsolatedEncoder
::encode_info_for_foreign_item
,
1467 fn visit_variant(&mut self,
1468 v
: &'tcx hir
::Variant
,
1469 g
: &'tcx hir
::Generics
,
1471 intravisit
::walk_variant(self, v
, g
, id
);
1473 if let Some(discr
) = v
.node
.disr_expr
{
1474 let def_id
= self.index
.tcx
.hir
.body_owner_def_id(discr
);
1475 self.index
.record(def_id
, IsolatedEncoder
::encode_info_for_embedded_const
, def_id
);
1478 fn visit_generics(&mut self, generics
: &'tcx hir
::Generics
) {
1479 intravisit
::walk_generics(self, generics
);
1480 self.index
.encode_info_for_generics(generics
);
1482 fn visit_ty(&mut self, ty
: &'tcx hir
::Ty
) {
1483 intravisit
::walk_ty(self, ty
);
1484 self.index
.encode_info_for_ty(ty
);
1486 fn visit_macro_def(&mut self, macro_def
: &'tcx hir
::MacroDef
) {
1487 let def_id
= self.index
.tcx
.hir
.local_def_id(macro_def
.id
);
1488 self.index
.record(def_id
, IsolatedEncoder
::encode_info_for_macro_def
, macro_def
);
1492 impl<'a
, 'b
, 'tcx
> IndexBuilder
<'a
, 'b
, 'tcx
> {
1493 fn encode_fields(&mut self, adt_def_id
: DefId
) {
1494 let def
= self.tcx
.adt_def(adt_def_id
);
1495 for (variant_index
, variant
) in def
.variants
.iter().enumerate() {
1496 for (field_index
, field
) in variant
.fields
.iter().enumerate() {
1497 self.record(field
.did
,
1498 IsolatedEncoder
::encode_field
,
1499 (adt_def_id
, Untracked((variant_index
, field_index
))));
1504 fn encode_info_for_generics(&mut self, generics
: &hir
::Generics
) {
1505 for ty_param
in &generics
.ty_params
{
1506 let def_id
= self.tcx
.hir
.local_def_id(ty_param
.id
);
1507 let has_default
= Untracked(ty_param
.default.is_some());
1508 self.record(def_id
, IsolatedEncoder
::encode_info_for_ty_param
, (def_id
, has_default
));
1512 fn encode_info_for_ty(&mut self, ty
: &hir
::Ty
) {
1513 if let hir
::TyImplTrait(_
) = ty
.node
{
1514 let def_id
= self.tcx
.hir
.local_def_id(ty
.id
);
1515 self.record(def_id
, IsolatedEncoder
::encode_info_for_anon_ty
, def_id
);
1519 fn encode_info_for_expr(&mut self, expr
: &hir
::Expr
) {
1521 hir
::ExprClosure(..) => {
1522 let def_id
= self.tcx
.hir
.local_def_id(expr
.id
);
1523 self.record(def_id
, IsolatedEncoder
::encode_info_for_closure
, def_id
);
1529 /// In some cases, along with the item itself, we also
1530 /// encode some sub-items. Usually we want some info from the item
1531 /// so it's easier to do that here then to wait until we would encounter
1532 /// normally in the visitor walk.
1533 fn encode_addl_info_for_item(&mut self, item
: &hir
::Item
) {
1534 let def_id
= self.tcx
.hir
.local_def_id(item
.id
);
1536 hir
::ItemStatic(..) |
1537 hir
::ItemConst(..) |
1540 hir
::ItemForeignMod(..) |
1541 hir
::ItemGlobalAsm(..) |
1542 hir
::ItemExternCrate(..) |
1544 hir
::ItemDefaultImpl(..) |
1545 hir
::ItemTy(..) => {
1546 // no sub-item recording needed in these cases
1548 hir
::ItemEnum(..) => {
1549 self.encode_fields(def_id
);
1551 let def
= self.tcx
.adt_def(def_id
);
1552 for (i
, variant
) in def
.variants
.iter().enumerate() {
1553 self.record(variant
.did
,
1554 IsolatedEncoder
::encode_enum_variant_info
,
1555 (def_id
, Untracked(i
)));
1558 hir
::ItemStruct(ref struct_def
, _
) => {
1559 self.encode_fields(def_id
);
1561 // If the struct has a constructor, encode it.
1562 if !struct_def
.is_struct() {
1563 let ctor_def_id
= self.tcx
.hir
.local_def_id(struct_def
.id());
1564 self.record(ctor_def_id
,
1565 IsolatedEncoder
::encode_struct_ctor
,
1566 (def_id
, ctor_def_id
));
1569 hir
::ItemUnion(..) => {
1570 self.encode_fields(def_id
);
1572 hir
::ItemImpl(..) => {
1573 for &trait_item_def_id
in self.tcx
.associated_item_def_ids(def_id
).iter() {
1574 self.record(trait_item_def_id
,
1575 IsolatedEncoder
::encode_info_for_impl_item
,
1579 hir
::ItemTrait(..) => {
1580 for &item_def_id
in self.tcx
.associated_item_def_ids(def_id
).iter() {
1581 self.record(item_def_id
,
1582 IsolatedEncoder
::encode_info_for_trait_item
,
1590 struct ImplVisitor
<'a
, 'tcx
: 'a
> {
1591 tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1592 impls
: FxHashMap
<DefId
, Vec
<DefIndex
>>,
1595 impl<'a
, 'tcx
, 'v
> ItemLikeVisitor
<'v
> for ImplVisitor
<'a
, 'tcx
> {
1596 fn visit_item(&mut self, item
: &hir
::Item
) {
1597 if let hir
::ItemImpl(..) = item
.node
{
1598 let impl_id
= self.tcx
.hir
.local_def_id(item
.id
);
1599 if let Some(trait_ref
) = self.tcx
.impl_trait_ref(impl_id
) {
1601 .entry(trait_ref
.def_id
)
1603 .push(impl_id
.index
);
1608 fn visit_trait_item(&mut self, _trait_item
: &'v hir
::TraitItem
) {}
1610 fn visit_impl_item(&mut self, _impl_item
: &'v hir
::ImplItem
) {
1611 // handled in `visit_item` above
1615 // NOTE(eddyb) The following comment was preserved for posterity, even
1616 // though it's no longer relevant as EBML (which uses nested & tagged
1617 // "documents") was replaced with a scheme that can't go out of bounds.
1619 // And here we run into yet another obscure archive bug: in which metadata
1620 // loaded from archives may have trailing garbage bytes. Awhile back one of
1621 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
1622 // and opt) by having ebml generate an out-of-bounds panic when looking at
1625 // Upon investigation it turned out that the metadata file inside of an rlib
1626 // (and ar archive) was being corrupted. Some compilations would generate a
1627 // metadata file which would end in a few extra bytes, while other
1628 // compilations would not have these extra bytes appended to the end. These
1629 // extra bytes were interpreted by ebml as an extra tag, so they ended up
1630 // being interpreted causing the out-of-bounds.
1632 // The root cause of why these extra bytes were appearing was never
1633 // discovered, and in the meantime the solution we're employing is to insert
1634 // the length of the metadata to the start of the metadata. Later on this
1635 // will allow us to slice the metadata to the precise length that we just
1636 // generated regardless of trailing bytes that end up in it.
1638 pub fn encode_metadata
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
1639 link_meta
: &LinkMeta
,
1640 exported_symbols
: &NodeSet
)
1641 -> (EncodedMetadata
, EncodedMetadataHashes
)
1643 let mut cursor
= Cursor
::new(vec
![]);
1644 cursor
.write_all(METADATA_HEADER
).unwrap();
1646 // Will be filled with the root position after encoding everything.
1647 cursor
.write_all(&[0, 0, 0, 0]).unwrap();
1649 let compute_ich
= (tcx
.sess
.opts
.debugging_opts
.query_dep_graph
||
1650 tcx
.sess
.opts
.debugging_opts
.incremental_cc
) &&
1651 tcx
.sess
.opts
.build_dep_graph();
1653 let (root
, metadata_hashes
) = {
1654 let mut ecx
= EncodeContext
{
1655 opaque
: opaque
::Encoder
::new(&mut cursor
),
1659 lazy_state
: LazyState
::NoNode
,
1660 type_shorthands
: Default
::default(),
1661 predicate_shorthands
: Default
::default(),
1662 metadata_hashes
: EncodedMetadataHashes
::new(),
1666 // Encode the rustc version string in a predictable location.
1667 rustc_version().encode(&mut ecx
).unwrap();
1669 // Encode all the entries and extra information in the crate,
1670 // culminating in the `CrateRoot` which points to all of it.
1671 let root
= ecx
.encode_crate_root();
1672 (root
, ecx
.metadata_hashes
)
1674 let mut result
= cursor
.into_inner();
1676 // Encode the root position.
1677 let header
= METADATA_HEADER
.len();
1678 let pos
= root
.position
;
1679 result
[header
+ 0] = (pos
>> 24) as u8;
1680 result
[header
+ 1] = (pos
>> 16) as u8;
1681 result
[header
+ 2] = (pos
>> 8) as u8;
1682 result
[header
+ 3] = (pos
>> 0) as u8;
1684 (EncodedMetadata { raw_data: result }
, metadata_hashes
)
1687 pub fn get_repr_options
<'a
, 'tcx
, 'gcx
>(tcx
: &TyCtxt
<'a
, 'tcx
, 'gcx
>, did
: DefId
) -> ReprOptions
{
1688 let ty
= tcx
.type_of(did
);
1690 ty
::TyAdt(ref def
, _
) => return def
.repr
,
1691 _
=> bug
!("{} is not an ADT", ty
),