]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/schema.rs
430cbf9b529fbecef55869fe74664a64b69f1a1c
[rust.git] / src / librustc_metadata / schema.rs
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.
4 //
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.
10
11 use index;
12
13 use rustc::hir;
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;
19 use rustc::mir;
20 use rustc::session::CrateDisambiguator;
21 use rustc::ty::{self, Ty, ReprOptions};
22 use rustc_target::spec::{PanicStrategy, TargetTriple};
23
24 use rustc_serialize as serialize;
25 use syntax::{ast, attr};
26 use syntax::edition::Edition;
27 use syntax::symbol::Symbol;
28 use syntax_pos::{self, Span};
29
30 use std::marker::PhantomData;
31 use std::mem;
32
33 use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
34                                            StableHasherResult};
35
36 pub fn rustc_version() -> String {
37     format!("rustc {}",
38             option_env!("CFG_VERSION").unwrap_or("unknown version"))
39 }
40
41 /// Metadata encoding version.
42 /// NB: increment this if you change the format of metadata such that
43 /// the rustc version can't be found to compare with `rustc_version()`.
44 pub const METADATA_VERSION: u8 = 4;
45
46 /// Metadata header which includes `METADATA_VERSION`.
47 /// To get older versions of rustc to ignore this metadata,
48 /// there are 4 zero bytes at the start, which are treated
49 /// as a length of 0 by old compilers.
50 ///
51 /// This header is followed by the position of the `CrateRoot`,
52 /// which is encoded as a 32-bit big-endian unsigned integer,
53 /// and further followed by the rustc version string.
54 pub const METADATA_HEADER: &'static [u8; 12] =
55     &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
56
57 /// A value of type T referred to by its absolute position
58 /// in the metadata, and which can be decoded lazily.
59 ///
60 /// Metadata is effective a tree, encoded in post-order,
61 /// and with the root's position written next to the header.
62 /// That means every single `Lazy` points to some previous
63 /// location in the metadata and is part of a larger node.
64 ///
65 /// The first `Lazy` in a node is encoded as the backwards
66 /// distance from the position where the containing node
67 /// starts and where the `Lazy` points to, while the rest
68 /// use the forward distance from the previous `Lazy`.
69 /// Distances start at 1, as 0-byte nodes are invalid.
70 /// Also invalid are nodes being referred in a different
71 /// order than they were encoded in.
72 #[must_use]
73 pub struct Lazy<T> {
74     pub position: usize,
75     _marker: PhantomData<T>,
76 }
77
78 impl<T> Lazy<T> {
79     pub fn with_position(position: usize) -> Lazy<T> {
80         Lazy {
81             position,
82             _marker: PhantomData,
83         }
84     }
85
86     /// Returns the minimum encoded size of a value of type `T`.
87     // FIXME(eddyb) Give better estimates for certain types.
88     pub fn min_size() -> usize {
89         1
90     }
91 }
92
93 impl<T> Copy for Lazy<T> {}
94 impl<T> Clone for Lazy<T> {
95     fn clone(&self) -> Self {
96         *self
97     }
98 }
99
100 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
101 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
102
103 impl<CTX, T> HashStable<CTX> for Lazy<T> {
104     fn hash_stable<W: StableHasherResult>(&self,
105                                           _: &mut CTX,
106                                           _: &mut StableHasher<W>) {
107         // There's nothing to do. Whatever got encoded within this Lazy<>
108         // wrapper has already been hashed.
109     }
110 }
111
112 /// A sequence of type T referred to by its absolute position
113 /// in the metadata and length, and which can be decoded lazily.
114 /// The sequence is a single node for the purposes of `Lazy`.
115 ///
116 /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
117 /// position, not at the position, which means that the length
118 /// doesn't need to be known before encoding all the elements.
119 ///
120 /// If the length is 0, no position is encoded, but otherwise,
121 /// the encoding is that of `Lazy`, with the distinction that
122 /// the minimal distance the length of the sequence, i.e.
123 /// it's assumed there's no 0-byte element in the sequence.
124 #[must_use]
125 pub struct LazySeq<T> {
126     pub len: usize,
127     pub position: usize,
128     _marker: PhantomData<T>,
129 }
130
131 impl<T> LazySeq<T> {
132     pub fn empty() -> LazySeq<T> {
133         LazySeq::with_position_and_length(0, 0)
134     }
135
136     pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> {
137         LazySeq {
138             len,
139             position,
140             _marker: PhantomData,
141         }
142     }
143
144     /// Returns the minimum encoded size of `length` values of type `T`.
145     pub fn min_size(length: usize) -> usize {
146         length
147     }
148 }
149
150 impl<T> Copy for LazySeq<T> {}
151 impl<T> Clone for LazySeq<T> {
152     fn clone(&self) -> Self {
153         *self
154     }
155 }
156
157 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
158 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
159
160 impl<CTX, T> HashStable<CTX> for LazySeq<T> {
161     fn hash_stable<W: StableHasherResult>(&self,
162                                           _: &mut CTX,
163                                           _: &mut StableHasher<W>) {
164         // There's nothing to do. Whatever got encoded within this Lazy<>
165         // wrapper has already been hashed.
166     }
167 }
168
169 /// Encoding / decoding state for `Lazy` and `LazySeq`.
170 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
171 pub enum LazyState {
172     /// Outside of a metadata node.
173     NoNode,
174
175     /// Inside a metadata node, and before any `Lazy` or `LazySeq`.
176     /// The position is that of the node itself.
177     NodeStart(usize),
178
179     /// Inside a metadata node, with a previous `Lazy` or `LazySeq`.
180     /// The position is a conservative estimate of where that
181     /// previous `Lazy` / `LazySeq` would end (see their comments).
182     Previous(usize),
183 }
184
185 #[derive(RustcEncodable, RustcDecodable)]
186 pub struct CrateRoot {
187     pub name: Symbol,
188     pub triple: TargetTriple,
189     pub extra_filename: String,
190     pub hash: hir::svh::Svh,
191     pub disambiguator: CrateDisambiguator,
192     pub panic_strategy: PanicStrategy,
193     pub edition: Edition,
194     pub has_global_allocator: bool,
195     pub has_default_lib_allocator: bool,
196     pub plugin_registrar_fn: Option<DefIndex>,
197     pub macro_derive_registrar: Option<DefIndex>,
198
199     pub crate_deps: LazySeq<CrateDep>,
200     pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>,
201     pub lang_items: LazySeq<(DefIndex, usize)>,
202     pub lang_items_missing: LazySeq<lang_items::LangItem>,
203     pub native_libraries: LazySeq<NativeLibrary>,
204     pub foreign_modules: LazySeq<ForeignModule>,
205     pub codemap: LazySeq<syntax_pos::FileMap>,
206     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
207     pub impls: LazySeq<TraitImpls>,
208     pub exported_symbols: EncodedExportedSymbols,
209     pub interpret_alloc_index: LazySeq<u32>,
210
211     pub index: LazySeq<index::Index>,
212
213     pub compiler_builtins: bool,
214     pub needs_allocator: bool,
215     pub needs_panic_runtime: bool,
216     pub no_builtins: bool,
217     pub panic_runtime: bool,
218     pub profiler_runtime: bool,
219     pub sanitizer_runtime: bool,
220 }
221
222 #[derive(RustcEncodable, RustcDecodable)]
223 pub struct CrateDep {
224     pub name: ast::Name,
225     pub hash: hir::svh::Svh,
226     pub kind: DepKind,
227     pub extra_filename: String,
228 }
229
230 impl_stable_hash_for!(struct CrateDep {
231     name,
232     hash,
233     kind,
234     extra_filename
235 });
236
237 #[derive(RustcEncodable, RustcDecodable)]
238 pub struct TraitImpls {
239     pub trait_id: (u32, DefIndex),
240     pub impls: LazySeq<DefIndex>,
241 }
242
243 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TraitImpls {
244     fn hash_stable<W: StableHasherResult>(&self,
245                                           hcx: &mut StableHashingContext<'a>,
246                                           hasher: &mut StableHasher<W>) {
247         let TraitImpls {
248             trait_id: (krate, def_index),
249             ref impls,
250         } = *self;
251
252         DefId {
253             krate: CrateNum::from_u32(krate),
254             index: def_index
255         }.hash_stable(hcx, hasher);
256         impls.hash_stable(hcx, hasher);
257     }
258 }
259
260 #[derive(RustcEncodable, RustcDecodable)]
261 pub struct Entry<'tcx> {
262     pub kind: EntryKind<'tcx>,
263     pub visibility: Lazy<ty::Visibility>,
264     pub span: Lazy<Span>,
265     pub attributes: LazySeq<ast::Attribute>,
266     pub children: LazySeq<DefIndex>,
267     pub stability: Option<Lazy<attr::Stability>>,
268     pub deprecation: Option<Lazy<attr::Deprecation>>,
269
270     pub ty: Option<Lazy<Ty<'tcx>>>,
271     pub inherent_impls: LazySeq<DefIndex>,
272     pub variances: LazySeq<ty::Variance>,
273     pub generics: Option<Lazy<ty::Generics>>,
274     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
275     pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
276
277     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
278 }
279
280 impl_stable_hash_for!(struct Entry<'tcx> {
281     kind,
282     visibility,
283     span,
284     attributes,
285     children,
286     stability,
287     deprecation,
288     ty,
289     inherent_impls,
290     variances,
291     generics,
292     predicates,
293     predicates_defined_on,
294     mir
295 });
296
297 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
298 pub enum EntryKind<'tcx> {
299     Const(ConstQualif, Lazy<RenderedConst>),
300     ImmStatic,
301     MutStatic,
302     ForeignImmStatic,
303     ForeignMutStatic,
304     ForeignMod,
305     ForeignType,
306     GlobalAsm,
307     Type,
308     Existential,
309     Enum(ReprOptions),
310     Field,
311     Variant(Lazy<VariantData<'tcx>>),
312     Struct(Lazy<VariantData<'tcx>>, ReprOptions),
313     Union(Lazy<VariantData<'tcx>>, ReprOptions),
314     Fn(Lazy<FnData<'tcx>>),
315     ForeignFn(Lazy<FnData<'tcx>>),
316     Mod(Lazy<ModData>),
317     MacroDef(Lazy<MacroDef>),
318     Closure(Lazy<ClosureData<'tcx>>),
319     Generator(Lazy<GeneratorData<'tcx>>),
320     Trait(Lazy<TraitData<'tcx>>),
321     Impl(Lazy<ImplData<'tcx>>),
322     Method(Lazy<MethodData<'tcx>>),
323     AssociatedType(AssociatedContainer),
324     AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
325 }
326
327 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
328     fn hash_stable<W: StableHasherResult>(&self,
329                                           hcx: &mut StableHashingContext<'a>,
330                                           hasher: &mut StableHasher<W>) {
331         mem::discriminant(self).hash_stable(hcx, hasher);
332         match *self {
333             EntryKind::ImmStatic        |
334             EntryKind::MutStatic        |
335             EntryKind::ForeignImmStatic |
336             EntryKind::ForeignMutStatic |
337             EntryKind::ForeignMod       |
338             EntryKind::GlobalAsm        |
339             EntryKind::ForeignType      |
340             EntryKind::Field |
341             EntryKind::Existential |
342             EntryKind::Type => {
343                 // Nothing else to hash here.
344             }
345             EntryKind::Const(qualif, ref const_data) => {
346                 qualif.hash_stable(hcx, hasher);
347                 const_data.hash_stable(hcx, hasher);
348             }
349             EntryKind::Enum(ref repr_options) => {
350                 repr_options.hash_stable(hcx, hasher);
351             }
352             EntryKind::Variant(ref variant_data) => {
353                 variant_data.hash_stable(hcx, hasher);
354             }
355             EntryKind::Struct(ref variant_data, ref repr_options) |
356             EntryKind::Union(ref variant_data, ref repr_options)  => {
357                 variant_data.hash_stable(hcx, hasher);
358                 repr_options.hash_stable(hcx, hasher);
359             }
360             EntryKind::Fn(ref fn_data) |
361             EntryKind::ForeignFn(ref fn_data) => {
362                 fn_data.hash_stable(hcx, hasher);
363             }
364             EntryKind::Mod(ref mod_data) => {
365                 mod_data.hash_stable(hcx, hasher);
366             }
367             EntryKind::MacroDef(ref macro_def) => {
368                 macro_def.hash_stable(hcx, hasher);
369             }
370             EntryKind::Generator(data) => {
371                 data.hash_stable(hcx, hasher);
372             }
373             EntryKind::Closure(closure_data) => {
374                 closure_data.hash_stable(hcx, hasher);
375             }
376             EntryKind::Trait(ref trait_data) => {
377                 trait_data.hash_stable(hcx, hasher);
378             }
379             EntryKind::Impl(ref impl_data) => {
380                 impl_data.hash_stable(hcx, hasher);
381             }
382             EntryKind::Method(ref method_data) => {
383                 method_data.hash_stable(hcx, hasher);
384             }
385             EntryKind::AssociatedType(associated_container) => {
386                 associated_container.hash_stable(hcx, hasher);
387             }
388             EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => {
389                 associated_container.hash_stable(hcx, hasher);
390                 qualif.hash_stable(hcx, hasher);
391                 const_data.hash_stable(hcx, hasher);
392             }
393         }
394     }
395 }
396
397 /// Additional data for EntryKind::Const and EntryKind::AssociatedConst
398 #[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
399 pub struct ConstQualif {
400     pub mir: u8,
401     pub ast_promotable: bool,
402 }
403
404 impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable });
405
406 /// Contains a constant which has been rendered to a String.
407 /// Used by rustdoc.
408 #[derive(RustcEncodable, RustcDecodable)]
409 pub struct RenderedConst(pub String);
410
411 impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
412     #[inline]
413     fn hash_stable<W: StableHasherResult>(&self,
414                                           hcx: &mut StableHashingContext<'a>,
415                                           hasher: &mut StableHasher<W>) {
416         self.0.hash_stable(hcx, hasher);
417     }
418 }
419
420 #[derive(RustcEncodable, RustcDecodable)]
421 pub struct ModData {
422     pub reexports: LazySeq<def::Export>,
423 }
424
425 impl_stable_hash_for!(struct ModData { reexports });
426
427 #[derive(RustcEncodable, RustcDecodable)]
428 pub struct MacroDef {
429     pub body: String,
430     pub legacy: bool,
431 }
432
433 impl_stable_hash_for!(struct MacroDef { body, legacy });
434
435 #[derive(RustcEncodable, RustcDecodable)]
436 pub struct FnData<'tcx> {
437     pub constness: hir::Constness,
438     pub arg_names: LazySeq<ast::Name>,
439     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
440 }
441
442 impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
443
444 #[derive(RustcEncodable, RustcDecodable)]
445 pub struct VariantData<'tcx> {
446     pub ctor_kind: CtorKind,
447     pub discr: ty::VariantDiscr,
448
449     /// If this is a struct's only variant, this
450     /// is the index of the "struct ctor" item.
451     pub struct_ctor: Option<DefIndex>,
452
453     /// If this is a tuple struct or variant
454     /// ctor, this is its "function" signature.
455     pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
456 }
457
458 impl_stable_hash_for!(struct VariantData<'tcx> {
459     ctor_kind,
460     discr,
461     struct_ctor,
462     ctor_sig
463 });
464
465 #[derive(RustcEncodable, RustcDecodable)]
466 pub struct TraitData<'tcx> {
467     pub unsafety: hir::Unsafety,
468     pub paren_sugar: bool,
469     pub has_auto_impl: bool,
470     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
471 }
472
473 impl_stable_hash_for!(struct TraitData<'tcx> {
474     unsafety,
475     paren_sugar,
476     has_auto_impl,
477     super_predicates
478 });
479
480 #[derive(RustcEncodable, RustcDecodable)]
481 pub struct ImplData<'tcx> {
482     pub polarity: hir::ImplPolarity,
483     pub defaultness: hir::Defaultness,
484     pub parent_impl: Option<DefId>,
485
486     /// This is `Some` only for impls of `CoerceUnsized`.
487     pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
488     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
489 }
490
491 impl_stable_hash_for!(struct ImplData<'tcx> {
492     polarity,
493     defaultness,
494     parent_impl,
495     coerce_unsized_info,
496     trait_ref
497 });
498
499
500 /// Describes whether the container of an associated item
501 /// is a trait or an impl and whether, in a trait, it has
502 /// a default, or an in impl, whether it's marked "default".
503 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
504 pub enum AssociatedContainer {
505     TraitRequired,
506     TraitWithDefault,
507     ImplDefault,
508     ImplFinal,
509 }
510
511 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
512     TraitRequired,
513     TraitWithDefault,
514     ImplDefault,
515     ImplFinal
516 });
517
518 impl AssociatedContainer {
519     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
520         match *self {
521             AssociatedContainer::TraitRequired |
522             AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
523
524             AssociatedContainer::ImplDefault |
525             AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
526         }
527     }
528
529     pub fn defaultness(&self) -> hir::Defaultness {
530         match *self {
531             AssociatedContainer::TraitRequired => hir::Defaultness::Default {
532                 has_value: false,
533             },
534
535             AssociatedContainer::TraitWithDefault |
536             AssociatedContainer::ImplDefault => hir::Defaultness::Default {
537                 has_value: true,
538             },
539
540             AssociatedContainer::ImplFinal => hir::Defaultness::Final,
541         }
542     }
543 }
544
545 #[derive(RustcEncodable, RustcDecodable)]
546 pub struct MethodData<'tcx> {
547     pub fn_data: FnData<'tcx>,
548     pub container: AssociatedContainer,
549     pub has_self: bool,
550 }
551 impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
552
553 #[derive(RustcEncodable, RustcDecodable)]
554 pub struct ClosureData<'tcx> {
555     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
556 }
557 impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
558
559 #[derive(RustcEncodable, RustcDecodable)]
560 pub struct GeneratorData<'tcx> {
561     pub layout: mir::GeneratorLayout<'tcx>,
562 }
563 impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
564
565 // Tags used for encoding Spans:
566 pub const TAG_VALID_SPAN: u8 = 0;
567 pub const TAG_INVALID_SPAN: u8 = 1;
568
569 #[derive(RustcEncodable, RustcDecodable)]
570 pub struct EncodedExportedSymbols {
571     pub position: usize,
572     pub len: usize,
573 }