]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/schema.rs
Auto merge of #46696 - kennytm:rollup, r=kennytm
[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 astencode;
12 use index;
13
14 use rustc::hir;
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;
20 use rustc::mir;
21 use rustc::session::CrateDisambiguator;
22 use rustc::ty::{self, Ty, ReprOptions};
23 use rustc_back::PanicStrategy;
24
25 use rustc_serialize as serialize;
26 use syntax::{ast, attr};
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: String,
189     pub hash: hir::svh::Svh,
190     pub disambiguator: CrateDisambiguator,
191     pub panic_strategy: PanicStrategy,
192     pub has_global_allocator: bool,
193     pub has_default_lib_allocator: bool,
194     pub plugin_registrar_fn: Option<DefIndex>,
195     pub macro_derive_registrar: Option<DefIndex>,
196
197     pub crate_deps: LazySeq<CrateDep>,
198     pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>,
199     pub lang_items: LazySeq<(DefIndex, usize)>,
200     pub lang_items_missing: LazySeq<lang_items::LangItem>,
201     pub native_libraries: LazySeq<NativeLibrary>,
202     pub codemap: LazySeq<syntax_pos::FileMap>,
203     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
204     pub impls: LazySeq<TraitImpls>,
205     pub exported_symbols: LazySeq<DefIndex>,
206     pub index: LazySeq<index::Index>,
207 }
208
209 #[derive(RustcEncodable, RustcDecodable)]
210 pub struct CrateDep {
211     pub name: ast::Name,
212     pub hash: hir::svh::Svh,
213     pub kind: DepKind,
214 }
215
216 impl_stable_hash_for!(struct CrateDep {
217     name,
218     hash,
219     kind
220 });
221
222 #[derive(RustcEncodable, RustcDecodable)]
223 pub struct TraitImpls {
224     pub trait_id: (u32, DefIndex),
225     pub impls: LazySeq<DefIndex>,
226 }
227
228 impl<'gcx> HashStable<StableHashingContext<'gcx>> for TraitImpls {
229     fn hash_stable<W: StableHasherResult>(&self,
230                                           hcx: &mut StableHashingContext<'gcx>,
231                                           hasher: &mut StableHasher<W>) {
232         let TraitImpls {
233             trait_id: (krate, def_index),
234             ref impls,
235         } = *self;
236
237         DefId {
238             krate: CrateNum::from_u32(krate),
239             index: def_index
240         }.hash_stable(hcx, hasher);
241         impls.hash_stable(hcx, hasher);
242     }
243 }
244
245 #[derive(RustcEncodable, RustcDecodable)]
246 pub struct Entry<'tcx> {
247     pub kind: EntryKind<'tcx>,
248     pub visibility: Lazy<ty::Visibility>,
249     pub span: Lazy<Span>,
250     pub attributes: LazySeq<ast::Attribute>,
251     pub children: LazySeq<DefIndex>,
252     pub stability: Option<Lazy<attr::Stability>>,
253     pub deprecation: Option<Lazy<attr::Deprecation>>,
254
255     pub ty: Option<Lazy<Ty<'tcx>>>,
256     pub inherent_impls: LazySeq<DefIndex>,
257     pub variances: LazySeq<ty::Variance>,
258     pub generics: Option<Lazy<ty::Generics>>,
259     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
260
261     pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
262     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
263 }
264
265 impl_stable_hash_for!(struct Entry<'tcx> {
266     kind,
267     visibility,
268     span,
269     attributes,
270     children,
271     stability,
272     deprecation,
273     ty,
274     inherent_impls,
275     variances,
276     generics,
277     predicates,
278     ast,
279     mir
280 });
281
282 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
283 pub enum EntryKind<'tcx> {
284     Const(u8),
285     ImmStatic,
286     MutStatic,
287     ForeignImmStatic,
288     ForeignMutStatic,
289     ForeignMod,
290     ForeignType,
291     GlobalAsm,
292     Type,
293     Enum(ReprOptions),
294     Field,
295     Variant(Lazy<VariantData<'tcx>>),
296     Struct(Lazy<VariantData<'tcx>>, ReprOptions),
297     Union(Lazy<VariantData<'tcx>>, ReprOptions),
298     Fn(Lazy<FnData<'tcx>>),
299     ForeignFn(Lazy<FnData<'tcx>>),
300     Mod(Lazy<ModData>),
301     MacroDef(Lazy<MacroDef>),
302     Closure(Lazy<ClosureData<'tcx>>),
303     Generator(Lazy<GeneratorData<'tcx>>),
304     Trait(Lazy<TraitData<'tcx>>),
305     Impl(Lazy<ImplData<'tcx>>),
306     AutoImpl(Lazy<ImplData<'tcx>>),
307     Method(Lazy<MethodData<'tcx>>),
308     AssociatedType(AssociatedContainer),
309     AssociatedConst(AssociatedContainer, u8),
310 }
311
312 impl<'gcx> HashStable<StableHashingContext<'gcx>> for EntryKind<'gcx> {
313     fn hash_stable<W: StableHasherResult>(&self,
314                                           hcx: &mut StableHashingContext<'gcx>,
315                                           hasher: &mut StableHasher<W>) {
316         mem::discriminant(self).hash_stable(hcx, hasher);
317         match *self {
318             EntryKind::ImmStatic        |
319             EntryKind::MutStatic        |
320             EntryKind::ForeignImmStatic |
321             EntryKind::ForeignMutStatic |
322             EntryKind::ForeignMod       |
323             EntryKind::GlobalAsm        |
324             EntryKind::ForeignType      |
325             EntryKind::Field |
326             EntryKind::Type => {
327                 // Nothing else to hash here.
328             }
329             EntryKind::Const(qualif) => {
330                 qualif.hash_stable(hcx, hasher);
331             }
332             EntryKind::Enum(ref repr_options) => {
333                 repr_options.hash_stable(hcx, hasher);
334             }
335             EntryKind::Variant(ref variant_data) => {
336                 variant_data.hash_stable(hcx, hasher);
337             }
338             EntryKind::Struct(ref variant_data, ref repr_options) |
339             EntryKind::Union(ref variant_data, ref repr_options)  => {
340                 variant_data.hash_stable(hcx, hasher);
341                 repr_options.hash_stable(hcx, hasher);
342             }
343             EntryKind::Fn(ref fn_data) |
344             EntryKind::ForeignFn(ref fn_data) => {
345                 fn_data.hash_stable(hcx, hasher);
346             }
347             EntryKind::Mod(ref mod_data) => {
348                 mod_data.hash_stable(hcx, hasher);
349             }
350             EntryKind::MacroDef(ref macro_def) => {
351                 macro_def.hash_stable(hcx, hasher);
352             }
353             EntryKind::Generator(data) => {
354                 data.hash_stable(hcx, hasher);
355             }
356             EntryKind::Closure(closure_data) => {
357                 closure_data.hash_stable(hcx, hasher);
358             }
359             EntryKind::Trait(ref trait_data) => {
360                 trait_data.hash_stable(hcx, hasher);
361             }
362             EntryKind::AutoImpl(ref impl_data) |
363             EntryKind::Impl(ref impl_data) => {
364                 impl_data.hash_stable(hcx, hasher);
365             }
366             EntryKind::Method(ref method_data) => {
367                 method_data.hash_stable(hcx, hasher);
368             }
369             EntryKind::AssociatedType(associated_container) => {
370                 associated_container.hash_stable(hcx, hasher);
371             }
372             EntryKind::AssociatedConst(associated_container, qualif) => {
373                 associated_container.hash_stable(hcx, hasher);
374                 qualif.hash_stable(hcx, hasher);
375             }
376         }
377     }
378 }
379
380 #[derive(RustcEncodable, RustcDecodable)]
381 pub struct ModData {
382     pub reexports: LazySeq<def::Export>,
383 }
384
385 impl_stable_hash_for!(struct ModData { reexports });
386
387 #[derive(RustcEncodable, RustcDecodable)]
388 pub struct MacroDef {
389     pub body: String,
390     pub legacy: bool,
391 }
392
393 impl_stable_hash_for!(struct MacroDef { body, legacy });
394
395 #[derive(RustcEncodable, RustcDecodable)]
396 pub struct FnData<'tcx> {
397     pub constness: hir::Constness,
398     pub arg_names: LazySeq<ast::Name>,
399     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
400 }
401
402 impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
403
404 #[derive(RustcEncodable, RustcDecodable)]
405 pub struct VariantData<'tcx> {
406     pub ctor_kind: CtorKind,
407     pub discr: ty::VariantDiscr,
408
409     /// If this is a struct's only variant, this
410     /// is the index of the "struct ctor" item.
411     pub struct_ctor: Option<DefIndex>,
412
413     /// If this is a tuple struct or variant
414     /// ctor, this is its "function" signature.
415     pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
416 }
417
418 impl_stable_hash_for!(struct VariantData<'tcx> {
419     ctor_kind,
420     discr,
421     struct_ctor,
422     ctor_sig
423 });
424
425 #[derive(RustcEncodable, RustcDecodable)]
426 pub struct TraitData<'tcx> {
427     pub unsafety: hir::Unsafety,
428     pub paren_sugar: bool,
429     pub has_auto_impl: bool,
430     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
431 }
432
433 impl_stable_hash_for!(struct TraitData<'tcx> {
434     unsafety,
435     paren_sugar,
436     has_auto_impl,
437     super_predicates
438 });
439
440 #[derive(RustcEncodable, RustcDecodable)]
441 pub struct ImplData<'tcx> {
442     pub polarity: hir::ImplPolarity,
443     pub defaultness: hir::Defaultness,
444     pub parent_impl: Option<DefId>,
445
446     /// This is `Some` only for impls of `CoerceUnsized`.
447     pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
448     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
449 }
450
451 impl_stable_hash_for!(struct ImplData<'tcx> {
452     polarity,
453     defaultness,
454     parent_impl,
455     coerce_unsized_info,
456     trait_ref
457 });
458
459
460 /// Describes whether the container of an associated item
461 /// is a trait or an impl and whether, in a trait, it has
462 /// a default, or an in impl, whether it's marked "default".
463 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
464 pub enum AssociatedContainer {
465     TraitRequired,
466     TraitWithDefault,
467     ImplDefault,
468     ImplFinal,
469 }
470
471 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
472     TraitRequired,
473     TraitWithDefault,
474     ImplDefault,
475     ImplFinal
476 });
477
478 impl AssociatedContainer {
479     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
480         match *self {
481             AssociatedContainer::TraitRequired |
482             AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
483
484             AssociatedContainer::ImplDefault |
485             AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
486         }
487     }
488
489     pub fn defaultness(&self) -> hir::Defaultness {
490         match *self {
491             AssociatedContainer::TraitRequired => hir::Defaultness::Default {
492                 has_value: false,
493             },
494
495             AssociatedContainer::TraitWithDefault |
496             AssociatedContainer::ImplDefault => hir::Defaultness::Default {
497                 has_value: true,
498             },
499
500             AssociatedContainer::ImplFinal => hir::Defaultness::Final,
501         }
502     }
503 }
504
505 #[derive(RustcEncodable, RustcDecodable)]
506 pub struct MethodData<'tcx> {
507     pub fn_data: FnData<'tcx>,
508     pub container: AssociatedContainer,
509     pub has_self: bool,
510 }
511 impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
512
513 #[derive(RustcEncodable, RustcDecodable)]
514 pub struct ClosureData<'tcx> {
515     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
516 }
517 impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
518
519 #[derive(RustcEncodable, RustcDecodable)]
520 pub struct GeneratorData<'tcx> {
521     pub layout: mir::GeneratorLayout<'tcx>,
522 }
523 impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });