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.
14 use rustc::hir::def::{self, CtorKind};
15 use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
16 use rustc::ich::StableHashingContext;
17 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
18 use rustc::middle::lang_items;
20 use rustc::session::CrateDisambiguator;
21 use rustc::ty::{self, Ty, ReprOptions};
22 use rustc_target::spec::{PanicStrategy, TargetTriple};
23 use rustc_data_structures::svh::Svh;
25 use rustc_serialize as serialize;
26 use syntax::{ast, attr};
27 use syntax::edition::Edition;
28 use syntax::symbol::Symbol;
29 use syntax_pos::{self, Span};
31 use std::marker::PhantomData;
34 use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
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: &[u8; 12] =
56 &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
58 /// A value of type T referred to by its absolute position
59 /// in the metadata, and which can be decoded lazily.
61 /// Metadata is effective a tree, encoded in post-order,
62 /// and with the root's position written next to the header.
63 /// That means every single `Lazy` points to some previous
64 /// location in the metadata and is part of a larger node.
66 /// The first `Lazy` in a node is encoded as the backwards
67 /// distance from the position where the containing node
68 /// starts and where the `Lazy` points to, while the rest
69 /// use the forward distance from the previous `Lazy`.
70 /// Distances start at 1, as 0-byte nodes are invalid.
71 /// Also invalid are nodes being referred in a different
72 /// order than they were encoded in.
76 _marker: PhantomData<T>,
80 pub fn with_position(position: usize) -> Lazy<T> {
87 /// Returns the minimum encoded size of a value of type `T`.
88 // FIXME(eddyb) Give better estimates for certain types.
89 pub fn min_size() -> usize {
94 impl<T> Copy for Lazy<T> {}
95 impl<T> Clone for Lazy<T> {
96 fn clone(&self) -> Self {
101 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
102 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
104 impl<CTX, T> HashStable<CTX> for Lazy<T> {
105 fn hash_stable<W: StableHasherResult>(&self,
107 _: &mut StableHasher<W>) {
108 // There's nothing to do. Whatever got encoded within this Lazy<>
109 // wrapper has already been hashed.
113 /// A sequence of type T referred to by its absolute position
114 /// in the metadata and length, and which can be decoded lazily.
115 /// The sequence is a single node for the purposes of `Lazy`.
117 /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
118 /// position, not at the position, which means that the length
119 /// doesn't need to be known before encoding all the elements.
121 /// If the length is 0, no position is encoded, but otherwise,
122 /// the encoding is that of `Lazy`, with the distinction that
123 /// the minimal distance the length of the sequence, i.e.
124 /// it's assumed there's no 0-byte element in the sequence.
126 pub struct LazySeq<T> {
129 _marker: PhantomData<T>,
133 pub fn empty() -> LazySeq<T> {
134 LazySeq::with_position_and_length(0, 0)
137 pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> {
141 _marker: PhantomData,
145 /// Returns the minimum encoded size of `length` values of type `T`.
146 pub fn min_size(length: usize) -> usize {
151 impl<T> Copy for LazySeq<T> {}
152 impl<T> Clone for LazySeq<T> {
153 fn clone(&self) -> Self {
158 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
159 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
161 impl<CTX, T> HashStable<CTX> for LazySeq<T> {
162 fn hash_stable<W: StableHasherResult>(&self,
164 _: &mut StableHasher<W>) {
165 // There's nothing to do. Whatever got encoded within this Lazy<>
166 // wrapper has already been hashed.
170 /// Encoding / decoding state for `Lazy` and `LazySeq`.
171 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
173 /// Outside of a metadata node.
176 /// Inside a metadata node, and before any `Lazy` or `LazySeq`.
177 /// The position is that of the node itself.
180 /// Inside a metadata node, with a previous `Lazy` or `LazySeq`.
181 /// The position is a conservative estimate of where that
182 /// previous `Lazy` / `LazySeq` would end (see their comments).
186 #[derive(RustcEncodable, RustcDecodable)]
187 pub struct CrateRoot {
189 pub triple: TargetTriple,
190 pub extra_filename: String,
192 pub disambiguator: CrateDisambiguator,
193 pub panic_strategy: PanicStrategy,
194 pub edition: Edition,
195 pub has_global_allocator: bool,
196 pub has_panic_handler: bool,
197 pub has_default_lib_allocator: bool,
198 pub plugin_registrar_fn: Option<DefIndex>,
199 pub proc_macro_decls_static: Option<DefIndex>,
201 pub crate_deps: LazySeq<CrateDep>,
202 pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>,
203 pub lib_features: LazySeq<(Symbol, Option<Symbol>)>,
204 pub lang_items: LazySeq<(DefIndex, usize)>,
205 pub lang_items_missing: LazySeq<lang_items::LangItem>,
206 pub native_libraries: LazySeq<NativeLibrary>,
207 pub foreign_modules: LazySeq<ForeignModule>,
208 pub source_map: LazySeq<syntax_pos::SourceFile>,
209 pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
210 pub impls: LazySeq<TraitImpls>,
211 pub exported_symbols: EncodedExportedSymbols,
212 pub interpret_alloc_index: LazySeq<u32>,
214 pub index: LazySeq<index::Index>,
216 pub compiler_builtins: bool,
217 pub needs_allocator: bool,
218 pub needs_panic_runtime: bool,
219 pub no_builtins: bool,
220 pub panic_runtime: bool,
221 pub profiler_runtime: bool,
222 pub sanitizer_runtime: bool,
225 #[derive(RustcEncodable, RustcDecodable)]
226 pub struct CrateDep {
230 pub extra_filename: String,
233 impl_stable_hash_for!(struct CrateDep {
240 #[derive(RustcEncodable, RustcDecodable)]
241 pub struct TraitImpls {
242 pub trait_id: (u32, DefIndex),
243 pub impls: LazySeq<DefIndex>,
246 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TraitImpls {
247 fn hash_stable<W: StableHasherResult>(&self,
248 hcx: &mut StableHashingContext<'a>,
249 hasher: &mut StableHasher<W>) {
251 trait_id: (krate, def_index),
256 krate: CrateNum::from_u32(krate),
258 }.hash_stable(hcx, hasher);
259 impls.hash_stable(hcx, hasher);
263 #[derive(RustcEncodable, RustcDecodable)]
264 pub struct Entry<'tcx> {
265 pub kind: EntryKind<'tcx>,
266 pub visibility: Lazy<ty::Visibility>,
267 pub span: Lazy<Span>,
268 pub attributes: LazySeq<ast::Attribute>,
269 pub children: LazySeq<DefIndex>,
270 pub stability: Option<Lazy<attr::Stability>>,
271 pub deprecation: Option<Lazy<attr::Deprecation>>,
273 pub ty: Option<Lazy<Ty<'tcx>>>,
274 pub inherent_impls: LazySeq<DefIndex>,
275 pub variances: LazySeq<ty::Variance>,
276 pub generics: Option<Lazy<ty::Generics>>,
277 pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
278 pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
280 pub mir: Option<Lazy<mir::Mir<'tcx>>>,
283 impl_stable_hash_for!(struct Entry<'tcx> {
296 predicates_defined_on,
300 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
301 pub enum EntryKind<'tcx> {
302 Const(ConstQualif, Lazy<RenderedConst>),
314 Variant(Lazy<VariantData<'tcx>>),
315 Struct(Lazy<VariantData<'tcx>>, ReprOptions),
316 Union(Lazy<VariantData<'tcx>>, ReprOptions),
317 Fn(Lazy<FnData<'tcx>>),
318 ForeignFn(Lazy<FnData<'tcx>>),
320 MacroDef(Lazy<MacroDef>),
321 Closure(Lazy<ClosureData<'tcx>>),
322 Generator(Lazy<GeneratorData<'tcx>>),
323 Trait(Lazy<TraitData<'tcx>>),
324 Impl(Lazy<ImplData<'tcx>>),
325 Method(Lazy<MethodData<'tcx>>),
326 AssociatedType(AssociatedContainer),
327 AssociatedExistential(AssociatedContainer),
328 AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
331 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
332 fn hash_stable<W: StableHasherResult>(&self,
333 hcx: &mut StableHashingContext<'a>,
334 hasher: &mut StableHasher<W>) {
335 mem::discriminant(self).hash_stable(hcx, hasher);
337 EntryKind::ImmStatic |
338 EntryKind::MutStatic |
339 EntryKind::ForeignImmStatic |
340 EntryKind::ForeignMutStatic |
341 EntryKind::ForeignMod |
342 EntryKind::GlobalAsm |
343 EntryKind::ForeignType |
345 EntryKind::Existential |
347 // Nothing else to hash here.
349 EntryKind::Const(qualif, ref const_data) => {
350 qualif.hash_stable(hcx, hasher);
351 const_data.hash_stable(hcx, hasher);
353 EntryKind::Enum(ref repr_options) => {
354 repr_options.hash_stable(hcx, hasher);
356 EntryKind::Variant(ref variant_data) => {
357 variant_data.hash_stable(hcx, hasher);
359 EntryKind::Struct(ref variant_data, ref repr_options) |
360 EntryKind::Union(ref variant_data, ref repr_options) => {
361 variant_data.hash_stable(hcx, hasher);
362 repr_options.hash_stable(hcx, hasher);
364 EntryKind::Fn(ref fn_data) |
365 EntryKind::ForeignFn(ref fn_data) => {
366 fn_data.hash_stable(hcx, hasher);
368 EntryKind::Mod(ref mod_data) => {
369 mod_data.hash_stable(hcx, hasher);
371 EntryKind::MacroDef(ref macro_def) => {
372 macro_def.hash_stable(hcx, hasher);
374 EntryKind::Generator(data) => {
375 data.hash_stable(hcx, hasher);
377 EntryKind::Closure(closure_data) => {
378 closure_data.hash_stable(hcx, hasher);
380 EntryKind::Trait(ref trait_data) => {
381 trait_data.hash_stable(hcx, hasher);
383 EntryKind::Impl(ref impl_data) => {
384 impl_data.hash_stable(hcx, hasher);
386 EntryKind::Method(ref method_data) => {
387 method_data.hash_stable(hcx, hasher);
389 EntryKind::AssociatedExistential(associated_container) |
390 EntryKind::AssociatedType(associated_container) => {
391 associated_container.hash_stable(hcx, hasher);
393 EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => {
394 associated_container.hash_stable(hcx, hasher);
395 qualif.hash_stable(hcx, hasher);
396 const_data.hash_stable(hcx, hasher);
402 /// Additional data for EntryKind::Const and EntryKind::AssociatedConst
403 #[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
404 pub struct ConstQualif {
406 pub ast_promotable: bool,
409 impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable });
411 /// Contains a constant which has been rendered to a String.
413 #[derive(RustcEncodable, RustcDecodable)]
414 pub struct RenderedConst(pub String);
416 impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
418 fn hash_stable<W: StableHasherResult>(&self,
419 hcx: &mut StableHashingContext<'a>,
420 hasher: &mut StableHasher<W>) {
421 self.0.hash_stable(hcx, hasher);
425 #[derive(RustcEncodable, RustcDecodable)]
427 pub reexports: LazySeq<def::Export>,
430 impl_stable_hash_for!(struct ModData { reexports });
432 #[derive(RustcEncodable, RustcDecodable)]
433 pub struct MacroDef {
438 impl_stable_hash_for!(struct MacroDef { body, legacy });
440 #[derive(RustcEncodable, RustcDecodable)]
441 pub struct FnData<'tcx> {
442 pub constness: hir::Constness,
443 pub arg_names: LazySeq<ast::Name>,
444 pub sig: Lazy<ty::PolyFnSig<'tcx>>,
447 impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
449 #[derive(RustcEncodable, RustcDecodable)]
450 pub struct VariantData<'tcx> {
451 pub ctor_kind: CtorKind,
452 pub discr: ty::VariantDiscr,
454 /// If this is a struct's only variant, this
455 /// is the index of the "struct ctor" item.
456 pub struct_ctor: Option<DefIndex>,
458 /// If this is a tuple struct or variant
459 /// ctor, this is its "function" signature.
460 pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
463 impl_stable_hash_for!(struct VariantData<'tcx> {
470 #[derive(RustcEncodable, RustcDecodable)]
471 pub struct TraitData<'tcx> {
472 pub unsafety: hir::Unsafety,
473 pub paren_sugar: bool,
474 pub has_auto_impl: bool,
476 pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
479 impl_stable_hash_for!(struct TraitData<'tcx> {
487 #[derive(RustcEncodable, RustcDecodable)]
488 pub struct ImplData<'tcx> {
489 pub polarity: hir::ImplPolarity,
490 pub defaultness: hir::Defaultness,
491 pub parent_impl: Option<DefId>,
493 /// This is `Some` only for impls of `CoerceUnsized`.
494 pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
495 pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
498 impl_stable_hash_for!(struct ImplData<'tcx> {
507 /// Describes whether the container of an associated item
508 /// is a trait or an impl and whether, in a trait, it has
509 /// a default, or an in impl, whether it's marked "default".
510 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
511 pub enum AssociatedContainer {
518 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
525 impl AssociatedContainer {
526 pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
528 AssociatedContainer::TraitRequired |
529 AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
531 AssociatedContainer::ImplDefault |
532 AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
536 pub fn defaultness(&self) -> hir::Defaultness {
538 AssociatedContainer::TraitRequired => hir::Defaultness::Default {
542 AssociatedContainer::TraitWithDefault |
543 AssociatedContainer::ImplDefault => hir::Defaultness::Default {
547 AssociatedContainer::ImplFinal => hir::Defaultness::Final,
552 #[derive(RustcEncodable, RustcDecodable)]
553 pub struct MethodData<'tcx> {
554 pub fn_data: FnData<'tcx>,
555 pub container: AssociatedContainer,
558 impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
560 #[derive(RustcEncodable, RustcDecodable)]
561 pub struct ClosureData<'tcx> {
562 pub sig: Lazy<ty::PolyFnSig<'tcx>>,
564 impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
566 #[derive(RustcEncodable, RustcDecodable)]
567 pub struct GeneratorData<'tcx> {
568 pub layout: mir::GeneratorLayout<'tcx>,
570 impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
572 // Tags used for encoding Spans:
573 pub const TAG_VALID_SPAN: u8 = 0;
574 pub const TAG_INVALID_SPAN: u8 = 1;
576 #[derive(RustcEncodable, RustcDecodable)]
577 pub struct EncodedExportedSymbols {