1 // Copyright 2012-2016 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
::hir
::def
::{self, CtorKind}
;
16 use rustc
::hir
::def_id
::{DefIndex, DefId, CrateNum}
;
17 use rustc
::ich
::StableHashingContext
;
18 use rustc
::middle
::cstore
::{DepKind, LinkagePreference, NativeLibrary}
;
19 use rustc
::middle
::lang_items
;
21 use rustc
::ty
::{self, Ty, ReprOptions}
;
22 use rustc_back
::PanicStrategy
;
24 use rustc_serialize
as serialize
;
25 use syntax
::{ast, attr}
;
26 use syntax
::symbol
::Symbol
;
27 use syntax_pos
::{self, Span}
;
29 use std
::marker
::PhantomData
;
32 use rustc_data_structures
::stable_hasher
::{StableHasher
, HashStable
,
35 use rustc
::dep_graph
::{DepGraph, DepNode}
;
37 pub fn rustc_version() -> String
{
39 option_env
!("CFG_VERSION").unwrap_or("unknown version"))
42 /// Metadata encoding version.
43 /// NB: increment this if you change the format of metadata such that
44 /// the rustc version can't be found to compare with `rustc_version()`.
45 pub const METADATA_VERSION
: u8 = 4;
47 /// Metadata header which includes `METADATA_VERSION`.
48 /// To get older versions of rustc to ignore this metadata,
49 /// there are 4 zero bytes at the start, which are treated
50 /// as a length of 0 by old compilers.
52 /// This header is followed by the position of the `CrateRoot`,
53 /// which is encoded as a 32-bit big-endian unsigned integer,
54 /// and further followed by the rustc version string.
55 pub const METADATA_HEADER
: &'
static [u8; 12] =
56 &[0, 0, 0, 0, b'r'
, b'u'
, b's'
, b't'
, 0, 0, 0, METADATA_VERSION
];
58 /// The shorthand encoding uses an enum's variant index `usize`
59 /// and is offset by this value so it never matches a real variant.
60 /// This offset is also chosen so that the first byte is never < 0x80.
61 pub const SHORTHAND_OFFSET
: usize = 0x80;
63 /// A value of type T referred to by its absolute position
64 /// in the metadata, and which can be decoded lazily.
66 /// Metadata is effective a tree, encoded in post-order,
67 /// and with the root's position written next to the header.
68 /// That means every single `Lazy` points to some previous
69 /// location in the metadata and is part of a larger node.
71 /// The first `Lazy` in a node is encoded as the backwards
72 /// distance from the position where the containing node
73 /// starts and where the `Lazy` points to, while the rest
74 /// use the forward distance from the previous `Lazy`.
75 /// Distances start at 1, as 0-byte nodes are invalid.
76 /// Also invalid are nodes being referred in a different
77 /// order than they were encoded in.
81 _marker
: PhantomData
<T
>,
85 pub fn with_position(position
: usize) -> Lazy
<T
> {
92 /// Returns the minimum encoded size of a value of type `T`.
93 // FIXME(eddyb) Give better estimates for certain types.
94 pub fn min_size() -> usize {
99 impl<T
> Copy
for Lazy
<T
> {}
100 impl<T
> Clone
for Lazy
<T
> {
101 fn clone(&self) -> Self {
106 impl<T
> serialize
::UseSpecializedEncodable
for Lazy
<T
> {}
107 impl<T
> serialize
::UseSpecializedDecodable
for Lazy
<T
> {}
109 impl<CTX
, T
> HashStable
<CTX
> for Lazy
<T
> {
110 fn hash_stable
<W
: StableHasherResult
>(&self,
112 _
: &mut StableHasher
<W
>) {
113 // There's nothing to do. Whatever got encoded within this Lazy<>
114 // wrapper has already been hashed.
118 /// A sequence of type T referred to by its absolute position
119 /// in the metadata and length, and which can be decoded lazily.
120 /// The sequence is a single node for the purposes of `Lazy`.
122 /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
123 /// position, not at the position, which means that the length
124 /// doesn't need to be known before encoding all the elements.
126 /// If the length is 0, no position is encoded, but otherwise,
127 /// the encoding is that of `Lazy`, with the distinction that
128 /// the minimal distance the length of the sequence, i.e.
129 /// it's assumed there's no 0-byte element in the sequence.
131 pub struct LazySeq
<T
> {
134 _marker
: PhantomData
<T
>,
138 pub fn empty() -> LazySeq
<T
> {
139 LazySeq
::with_position_and_length(0, 0)
142 pub fn with_position_and_length(position
: usize, len
: usize) -> LazySeq
<T
> {
146 _marker
: PhantomData
,
150 /// Returns the minimum encoded size of `length` values of type `T`.
151 pub fn min_size(length
: usize) -> usize {
156 impl<T
> Copy
for LazySeq
<T
> {}
157 impl<T
> Clone
for LazySeq
<T
> {
158 fn clone(&self) -> Self {
163 impl<T
> serialize
::UseSpecializedEncodable
for LazySeq
<T
> {}
164 impl<T
> serialize
::UseSpecializedDecodable
for LazySeq
<T
> {}
166 impl<CTX
, T
> HashStable
<CTX
> for LazySeq
<T
> {
167 fn hash_stable
<W
: StableHasherResult
>(&self,
169 _
: &mut StableHasher
<W
>) {
170 // There's nothing to do. Whatever got encoded within this Lazy<>
171 // wrapper has already been hashed.
175 /// Encoding / decoding state for `Lazy` and `LazySeq`.
176 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
178 /// Outside of a metadata node.
181 /// Inside a metadata node, and before any `Lazy` or `LazySeq`.
182 /// The position is that of the node itself.
185 /// Inside a metadata node, with a previous `Lazy` or `LazySeq`.
186 /// The position is a conservative estimate of where that
187 /// previous `Lazy` / `LazySeq` would end (see their comments).
191 /// A `Tracked<T>` wraps a value so that one can only access it when specifying
192 /// the `DepNode` for that value. This makes it harder to forget registering
194 #[derive(RustcEncodable, RustcDecodable)]
195 pub struct Tracked
<T
> {
200 pub fn new(state
: T
) -> Tracked
<T
> {
206 pub fn get(&self, dep_graph
: &DepGraph
, dep_node
: DepNode
) -> &T
{
207 dep_graph
.read(dep_node
);
211 pub fn get_untracked(&self) -> &T
{
215 pub fn map
<F
, R
>(&self, f
: F
) -> Tracked
<R
>
216 where F
: FnOnce(&T
) -> R
219 state
: f(&self.state
),
224 impl<'a
, 'gcx
, 'tcx
, T
> HashStable
<StableHashingContext
<'a
, 'gcx
, 'tcx
>> for Tracked
<T
>
225 where T
: HashStable
<StableHashingContext
<'a
, 'gcx
, 'tcx
>>
227 fn hash_stable
<W
: StableHasherResult
>(&self,
228 hcx
: &mut StableHashingContext
<'a
, 'gcx
, 'tcx
>,
229 hasher
: &mut StableHasher
<W
>) {
234 state
.hash_stable(hcx
, hasher
);
239 #[derive(RustcEncodable, RustcDecodable)]
240 pub struct CrateRoot
{
243 pub hash
: hir
::svh
::Svh
,
244 pub disambiguator
: Symbol
,
245 pub panic_strategy
: Tracked
<PanicStrategy
>,
246 pub has_global_allocator
: Tracked
<bool
>,
247 pub has_default_lib_allocator
: Tracked
<bool
>,
248 pub plugin_registrar_fn
: Option
<DefIndex
>,
249 pub macro_derive_registrar
: Option
<DefIndex
>,
251 pub crate_deps
: Tracked
<LazySeq
<CrateDep
>>,
252 pub dylib_dependency_formats
: Tracked
<LazySeq
<Option
<LinkagePreference
>>>,
253 pub lang_items
: Tracked
<LazySeq
<(DefIndex
, usize)>>,
254 pub lang_items_missing
: Tracked
<LazySeq
<lang_items
::LangItem
>>,
255 pub native_libraries
: Tracked
<LazySeq
<NativeLibrary
>>,
256 pub codemap
: LazySeq
<syntax_pos
::FileMap
>,
257 pub def_path_table
: Lazy
<hir
::map
::definitions
::DefPathTable
>,
258 pub impls
: Tracked
<LazySeq
<TraitImpls
>>,
259 pub exported_symbols
: Tracked
<LazySeq
<DefIndex
>>,
260 pub index
: LazySeq
<index
::Index
>,
263 #[derive(RustcEncodable, RustcDecodable)]
264 pub struct CrateDep
{
266 pub hash
: hir
::svh
::Svh
,
270 impl_stable_hash_for
!(struct CrateDep
{
276 #[derive(RustcEncodable, RustcDecodable)]
277 pub struct TraitImpls
{
278 pub trait_id
: (u32, DefIndex
),
279 pub impls
: LazySeq
<DefIndex
>,
282 impl<'a
, 'gcx
, 'tcx
> HashStable
<StableHashingContext
<'a
, 'gcx
, 'tcx
>> for TraitImpls
{
283 fn hash_stable
<W
: StableHasherResult
>(&self,
284 hcx
: &mut StableHashingContext
<'a
, 'gcx
, 'tcx
>,
285 hasher
: &mut StableHasher
<W
>) {
287 trait_id
: (krate
, def_index
),
292 krate
: CrateNum
::from_u32(krate
),
294 }.hash_stable(hcx
, hasher
);
295 impls
.hash_stable(hcx
, hasher
);
299 #[derive(RustcEncodable, RustcDecodable)]
300 pub struct Entry
<'tcx
> {
301 pub kind
: EntryKind
<'tcx
>,
302 pub visibility
: Lazy
<ty
::Visibility
>,
303 pub span
: Lazy
<Span
>,
304 pub attributes
: LazySeq
<ast
::Attribute
>,
305 pub children
: LazySeq
<DefIndex
>,
306 pub stability
: Option
<Lazy
<attr
::Stability
>>,
307 pub deprecation
: Option
<Lazy
<attr
::Deprecation
>>,
309 pub ty
: Option
<Lazy
<Ty
<'tcx
>>>,
310 pub inherent_impls
: LazySeq
<DefIndex
>,
311 pub variances
: LazySeq
<ty
::Variance
>,
312 pub generics
: Option
<Lazy
<ty
::Generics
>>,
313 pub predicates
: Option
<Lazy
<ty
::GenericPredicates
<'tcx
>>>,
315 pub ast
: Option
<Lazy
<astencode
::Ast
<'tcx
>>>,
316 pub mir
: Option
<Lazy
<mir
::Mir
<'tcx
>>>,
319 impl_stable_hash_for
!(struct Entry
<'tcx
> {
336 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
337 pub enum EntryKind
<'tcx
> {
348 Variant(Lazy
<VariantData
<'tcx
>>),
349 Struct(Lazy
<VariantData
<'tcx
>>, ReprOptions
),
350 Union(Lazy
<VariantData
<'tcx
>>, ReprOptions
),
351 Fn(Lazy
<FnData
<'tcx
>>),
352 ForeignFn(Lazy
<FnData
<'tcx
>>),
354 MacroDef(Lazy
<MacroDef
>),
355 Closure(Lazy
<ClosureData
<'tcx
>>),
356 Trait(Lazy
<TraitData
<'tcx
>>),
357 Impl(Lazy
<ImplData
<'tcx
>>),
358 DefaultImpl(Lazy
<ImplData
<'tcx
>>),
359 Method(Lazy
<MethodData
<'tcx
>>),
360 AssociatedType(AssociatedContainer
),
361 AssociatedConst(AssociatedContainer
, u8),
364 impl<'a
, 'gcx
, 'tcx
> HashStable
<StableHashingContext
<'a
, 'gcx
, 'tcx
>> for EntryKind
<'tcx
> {
365 fn hash_stable
<W
: StableHasherResult
>(&self,
366 hcx
: &mut StableHashingContext
<'a
, 'gcx
, 'tcx
>,
367 hasher
: &mut StableHasher
<W
>) {
368 mem
::discriminant(self).hash_stable(hcx
, hasher
);
370 EntryKind
::ImmStatic
|
371 EntryKind
::MutStatic
|
372 EntryKind
::ForeignImmStatic
|
373 EntryKind
::ForeignMutStatic
|
374 EntryKind
::ForeignMod
|
375 EntryKind
::GlobalAsm
|
378 // Nothing else to hash here.
380 EntryKind
::Const(qualif
) => {
381 qualif
.hash_stable(hcx
, hasher
);
383 EntryKind
::Enum(ref repr_options
) => {
384 repr_options
.hash_stable(hcx
, hasher
);
386 EntryKind
::Variant(ref variant_data
) => {
387 variant_data
.hash_stable(hcx
, hasher
);
389 EntryKind
::Struct(ref variant_data
, ref repr_options
) |
390 EntryKind
::Union(ref variant_data
, ref repr_options
) => {
391 variant_data
.hash_stable(hcx
, hasher
);
392 repr_options
.hash_stable(hcx
, hasher
);
394 EntryKind
::Fn(ref fn_data
) |
395 EntryKind
::ForeignFn(ref fn_data
) => {
396 fn_data
.hash_stable(hcx
, hasher
);
398 EntryKind
::Mod(ref mod_data
) => {
399 mod_data
.hash_stable(hcx
, hasher
);
401 EntryKind
::MacroDef(ref macro_def
) => {
402 macro_def
.hash_stable(hcx
, hasher
);
404 EntryKind
::Closure(closure_data
) => {
405 closure_data
.hash_stable(hcx
, hasher
);
407 EntryKind
::Trait(ref trait_data
) => {
408 trait_data
.hash_stable(hcx
, hasher
);
410 EntryKind
::DefaultImpl(ref impl_data
) |
411 EntryKind
::Impl(ref impl_data
) => {
412 impl_data
.hash_stable(hcx
, hasher
);
414 EntryKind
::Method(ref method_data
) => {
415 method_data
.hash_stable(hcx
, hasher
);
417 EntryKind
::AssociatedType(associated_container
) => {
418 associated_container
.hash_stable(hcx
, hasher
);
420 EntryKind
::AssociatedConst(associated_container
, qualif
) => {
421 associated_container
.hash_stable(hcx
, hasher
);
422 qualif
.hash_stable(hcx
, hasher
);
428 #[derive(RustcEncodable, RustcDecodable)]
430 pub reexports
: LazySeq
<def
::Export
>,
433 impl_stable_hash_for
!(struct ModData { reexports }
);
435 #[derive(RustcEncodable, RustcDecodable)]
436 pub struct MacroDef
{
441 impl_stable_hash_for
!(struct MacroDef { body, legacy }
);
443 #[derive(RustcEncodable, RustcDecodable)]
444 pub struct FnData
<'tcx
> {
445 pub constness
: hir
::Constness
,
446 pub arg_names
: LazySeq
<ast
::Name
>,
447 pub sig
: Lazy
<ty
::PolyFnSig
<'tcx
>>,
450 impl_stable_hash_for
!(struct FnData
<'tcx
> { constness, arg_names, sig }
);
452 #[derive(RustcEncodable, RustcDecodable)]
453 pub struct VariantData
<'tcx
> {
454 pub ctor_kind
: CtorKind
,
455 pub discr
: ty
::VariantDiscr
,
457 /// If this is a struct's only variant, this
458 /// is the index of the "struct ctor" item.
459 pub struct_ctor
: Option
<DefIndex
>,
461 /// If this is a tuple struct or variant
462 /// ctor, this is its "function" signature.
463 pub ctor_sig
: Option
<Lazy
<ty
::PolyFnSig
<'tcx
>>>,
466 impl_stable_hash_for
!(struct VariantData
<'tcx
> {
473 #[derive(RustcEncodable, RustcDecodable)]
474 pub struct TraitData
<'tcx
> {
475 pub unsafety
: hir
::Unsafety
,
476 pub paren_sugar
: bool
,
477 pub has_default_impl
: bool
,
478 pub super_predicates
: Lazy
<ty
::GenericPredicates
<'tcx
>>,
481 impl_stable_hash_for
!(struct TraitData
<'tcx
> {
488 #[derive(RustcEncodable, RustcDecodable)]
489 pub struct ImplData
<'tcx
> {
490 pub polarity
: hir
::ImplPolarity
,
491 pub defaultness
: hir
::Defaultness
,
492 pub parent_impl
: Option
<DefId
>,
494 /// This is `Some` only for impls of `CoerceUnsized`.
495 pub coerce_unsized_info
: Option
<ty
::adjustment
::CoerceUnsizedInfo
>,
496 pub trait_ref
: Option
<Lazy
<ty
::TraitRef
<'tcx
>>>,
499 impl_stable_hash_for
!(struct ImplData
<'tcx
> {
508 /// Describes whether the container of an associated item
509 /// is a trait or an impl and whether, in a trait, it has
510 /// a default, or an in impl, whether it's marked "default".
511 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
512 pub enum AssociatedContainer
{
519 impl_stable_hash_for
!(enum ::schema
::AssociatedContainer
{
526 impl AssociatedContainer
{
527 pub fn with_def_id(&self, def_id
: DefId
) -> ty
::AssociatedItemContainer
{
529 AssociatedContainer
::TraitRequired
|
530 AssociatedContainer
::TraitWithDefault
=> ty
::TraitContainer(def_id
),
532 AssociatedContainer
::ImplDefault
|
533 AssociatedContainer
::ImplFinal
=> ty
::ImplContainer(def_id
),
537 pub fn defaultness(&self) -> hir
::Defaultness
{
539 AssociatedContainer
::TraitRequired
=> hir
::Defaultness
::Default
{
543 AssociatedContainer
::TraitWithDefault
|
544 AssociatedContainer
::ImplDefault
=> hir
::Defaultness
::Default
{
548 AssociatedContainer
::ImplFinal
=> hir
::Defaultness
::Final
,
553 #[derive(RustcEncodable, RustcDecodable)]
554 pub struct MethodData
<'tcx
> {
555 pub fn_data
: FnData
<'tcx
>,
556 pub container
: AssociatedContainer
,
559 impl_stable_hash_for
!(struct MethodData
<'tcx
> { fn_data, container, has_self }
);
561 #[derive(RustcEncodable, RustcDecodable)]
562 pub struct ClosureData
<'tcx
> {
563 pub kind
: ty
::ClosureKind
,
564 pub sig
: Lazy
<ty
::PolyFnSig
<'tcx
>>,
566 impl_stable_hash_for
!(struct ClosureData
<'tcx
> { kind, sig }
);