]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/schema.rs
Rollup merge of #41141 - michaelwoerister:direct-metadata-ich-final, r=nikomatsakis
[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};
17 use rustc::ich::StableHashingContext;
18 use rustc::middle::const_val::ConstVal;
19 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
20 use rustc::middle::lang_items;
21 use rustc::mir;
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 /// The shorthand encoding uses an enum's variant index `usize`
58 /// and is offset by this value so it never matches a real variant.
59 /// This offset is also chosen so that the first byte is never < 0x80.
60 pub const SHORTHAND_OFFSET: usize = 0x80;
61
62 /// A value of type T referred to by its absolute position
63 /// in the metadata, and which can be decoded lazily.
64 ///
65 /// Metadata is effective a tree, encoded in post-order,
66 /// and with the root's position written next to the header.
67 /// That means every single `Lazy` points to some previous
68 /// location in the metadata and is part of a larger node.
69 ///
70 /// The first `Lazy` in a node is encoded as the backwards
71 /// distance from the position where the containing node
72 /// starts and where the `Lazy` points to, while the rest
73 /// use the forward distance from the previous `Lazy`.
74 /// Distances start at 1, as 0-byte nodes are invalid.
75 /// Also invalid are nodes being referred in a different
76 /// order than they were encoded in.
77 #[must_use]
78 pub struct Lazy<T> {
79     pub position: usize,
80     _marker: PhantomData<T>,
81 }
82
83 impl<T> Lazy<T> {
84     pub fn with_position(position: usize) -> Lazy<T> {
85         Lazy {
86             position: position,
87             _marker: PhantomData,
88         }
89     }
90
91     /// Returns the minimum encoded size of a value of type `T`.
92     // FIXME(eddyb) Give better estimates for certain types.
93     pub fn min_size() -> usize {
94         1
95     }
96 }
97
98 impl<T> Copy for Lazy<T> {}
99 impl<T> Clone for Lazy<T> {
100     fn clone(&self) -> Self {
101         *self
102     }
103 }
104
105 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
106 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
107
108 impl<CTX, T> HashStable<CTX> for Lazy<T> {
109     fn hash_stable<W: StableHasherResult>(&self,
110                                           _: &mut CTX,
111                                           _: &mut StableHasher<W>) {
112         // There's nothing to do. Whatever got encoded within this Lazy<>
113         // wrapper has already been hashed.
114     }
115 }
116
117 /// A sequence of type T referred to by its absolute position
118 /// in the metadata and length, and which can be decoded lazily.
119 /// The sequence is a single node for the purposes of `Lazy`.
120 ///
121 /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
122 /// position, not at the position, which means that the length
123 /// doesn't need to be known before encoding all the elements.
124 ///
125 /// If the length is 0, no position is encoded, but otherwise,
126 /// the encoding is that of `Lazy`, with the distinction that
127 /// the minimal distance the length of the sequence, i.e.
128 /// it's assumed there's no 0-byte element in the sequence.
129 #[must_use]
130 pub struct LazySeq<T> {
131     pub len: usize,
132     pub position: usize,
133     _marker: PhantomData<T>,
134 }
135
136 impl<T> LazySeq<T> {
137     pub fn empty() -> LazySeq<T> {
138         LazySeq::with_position_and_length(0, 0)
139     }
140
141     pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> {
142         LazySeq {
143             len: len,
144             position: position,
145             _marker: PhantomData,
146         }
147     }
148
149     /// Returns the minimum encoded size of `length` values of type `T`.
150     pub fn min_size(length: usize) -> usize {
151         length
152     }
153 }
154
155 impl<T> Copy for LazySeq<T> {}
156 impl<T> Clone for LazySeq<T> {
157     fn clone(&self) -> Self {
158         *self
159     }
160 }
161
162 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
163 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
164
165 impl<CTX, T> HashStable<CTX> for LazySeq<T> {
166     fn hash_stable<W: StableHasherResult>(&self,
167                                           _: &mut CTX,
168                                           _: &mut StableHasher<W>) {
169         // There's nothing to do. Whatever got encoded within this Lazy<>
170         // wrapper has already been hashed.
171     }
172 }
173
174 /// Encoding / decoding state for `Lazy` and `LazySeq`.
175 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
176 pub enum LazyState {
177     /// Outside of a metadata node.
178     NoNode,
179
180     /// Inside a metadata node, and before any `Lazy` or `LazySeq`.
181     /// The position is that of the node itself.
182     NodeStart(usize),
183
184     /// Inside a metadata node, with a previous `Lazy` or `LazySeq`.
185     /// The position is a conservative estimate of where that
186     /// previous `Lazy` / `LazySeq` would end (see their comments).
187     Previous(usize),
188 }
189
190 #[derive(RustcEncodable, RustcDecodable)]
191 pub struct CrateRoot {
192     pub name: Symbol,
193     pub triple: String,
194     pub hash: hir::svh::Svh,
195     pub disambiguator: Symbol,
196     pub panic_strategy: PanicStrategy,
197     pub plugin_registrar_fn: Option<DefIndex>,
198     pub macro_derive_registrar: Option<DefIndex>,
199
200     pub crate_deps: LazySeq<CrateDep>,
201     pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>,
202     pub lang_items: LazySeq<(DefIndex, usize)>,
203     pub lang_items_missing: LazySeq<lang_items::LangItem>,
204     pub native_libraries: LazySeq<NativeLibrary>,
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: LazySeq<DefIndex>,
209     pub index: LazySeq<index::Index>,
210 }
211
212 #[derive(RustcEncodable, RustcDecodable)]
213 pub struct CrateDep {
214     pub name: ast::Name,
215     pub hash: hir::svh::Svh,
216     pub kind: DepKind,
217 }
218
219 #[derive(RustcEncodable, RustcDecodable)]
220 pub struct TraitImpls {
221     pub trait_id: (u32, DefIndex),
222     pub impls: LazySeq<DefIndex>,
223 }
224
225 #[derive(RustcEncodable, RustcDecodable)]
226 pub struct Entry<'tcx> {
227     pub kind: EntryKind<'tcx>,
228     pub visibility: Lazy<ty::Visibility>,
229     pub span: Lazy<Span>,
230     pub attributes: LazySeq<ast::Attribute>,
231     pub children: LazySeq<DefIndex>,
232     pub stability: Option<Lazy<attr::Stability>>,
233     pub deprecation: Option<Lazy<attr::Deprecation>>,
234
235     pub ty: Option<Lazy<Ty<'tcx>>>,
236     pub inherent_impls: LazySeq<DefIndex>,
237     pub variances: LazySeq<ty::Variance>,
238     pub generics: Option<Lazy<ty::Generics>>,
239     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
240
241     pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
242     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
243 }
244
245 impl_stable_hash_for!(struct Entry<'tcx> {
246     kind,
247     visibility,
248     span,
249     attributes,
250     children,
251     stability,
252     deprecation,
253     ty,
254     inherent_impls,
255     variances,
256     generics,
257     predicates,
258     ast,
259     mir
260 });
261
262 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
263 pub enum EntryKind<'tcx> {
264     Const(u8),
265     ImmStatic,
266     MutStatic,
267     ForeignImmStatic,
268     ForeignMutStatic,
269     ForeignMod,
270     Type,
271     Enum(ReprOptions),
272     Field,
273     Variant(Lazy<VariantData<'tcx>>),
274     Struct(Lazy<VariantData<'tcx>>, ReprOptions),
275     Union(Lazy<VariantData<'tcx>>, ReprOptions),
276     Fn(Lazy<FnData>),
277     ForeignFn(Lazy<FnData>),
278     Mod(Lazy<ModData>),
279     MacroDef(Lazy<MacroDef>),
280     Closure(Lazy<ClosureData<'tcx>>),
281     Trait(Lazy<TraitData<'tcx>>),
282     Impl(Lazy<ImplData<'tcx>>),
283     DefaultImpl(Lazy<ImplData<'tcx>>),
284     Method(Lazy<MethodData>),
285     AssociatedType(AssociatedContainer),
286     AssociatedConst(AssociatedContainer, u8),
287 }
288
289 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for EntryKind<'tcx> {
290     fn hash_stable<W: StableHasherResult>(&self,
291                                           hcx: &mut StableHashingContext<'a, 'tcx>,
292                                           hasher: &mut StableHasher<W>) {
293         mem::discriminant(self).hash_stable(hcx, hasher);
294         match *self {
295             EntryKind::ImmStatic        |
296             EntryKind::MutStatic        |
297             EntryKind::ForeignImmStatic |
298             EntryKind::ForeignMutStatic |
299             EntryKind::ForeignMod       |
300             EntryKind::Field |
301             EntryKind::Type => {
302                 // Nothing else to hash here.
303             }
304             EntryKind::Const(qualif) => {
305                 qualif.hash_stable(hcx, hasher);
306             }
307             EntryKind::Enum(ref repr_options) => {
308                 repr_options.hash_stable(hcx, hasher);
309             }
310             EntryKind::Variant(ref variant_data) => {
311                 variant_data.hash_stable(hcx, hasher);
312             }
313             EntryKind::Struct(ref variant_data, ref repr_options) |
314             EntryKind::Union(ref variant_data, ref repr_options)  => {
315                 variant_data.hash_stable(hcx, hasher);
316                 repr_options.hash_stable(hcx, hasher);
317             }
318             EntryKind::Fn(ref fn_data) |
319             EntryKind::ForeignFn(ref fn_data) => {
320                 fn_data.hash_stable(hcx, hasher);
321             }
322             EntryKind::Mod(ref mod_data) => {
323                 mod_data.hash_stable(hcx, hasher);
324             }
325             EntryKind::MacroDef(ref macro_def) => {
326                 macro_def.hash_stable(hcx, hasher);
327             }
328             EntryKind::Closure(closure_data) => {
329                 closure_data.hash_stable(hcx, hasher);
330             }
331             EntryKind::Trait(ref trait_data) => {
332                 trait_data.hash_stable(hcx, hasher);
333             }
334             EntryKind::DefaultImpl(ref impl_data) |
335             EntryKind::Impl(ref impl_data) => {
336                 impl_data.hash_stable(hcx, hasher);
337             }
338             EntryKind::Method(ref method_data) => {
339                 method_data.hash_stable(hcx, hasher);
340             }
341             EntryKind::AssociatedType(associated_container) => {
342                 associated_container.hash_stable(hcx, hasher);
343             }
344             EntryKind::AssociatedConst(associated_container, qualif) => {
345                 associated_container.hash_stable(hcx, hasher);
346                 qualif.hash_stable(hcx, hasher);
347             }
348         }
349     }
350 }
351
352 #[derive(RustcEncodable, RustcDecodable)]
353 pub struct ModData {
354     pub reexports: LazySeq<def::Export>,
355 }
356
357 impl_stable_hash_for!(struct ModData { reexports });
358
359 #[derive(RustcEncodable, RustcDecodable)]
360 pub struct MacroDef {
361     pub body: String,
362 }
363
364 impl_stable_hash_for!(struct MacroDef { body });
365
366 #[derive(RustcEncodable, RustcDecodable)]
367 pub struct FnData {
368     pub constness: hir::Constness,
369     pub arg_names: LazySeq<ast::Name>,
370 }
371
372 impl_stable_hash_for!(struct FnData { constness, arg_names });
373
374 #[derive(RustcEncodable, RustcDecodable)]
375 pub struct VariantData<'tcx> {
376     pub ctor_kind: CtorKind,
377     pub discr: ty::VariantDiscr,
378     pub evaluated_discr: Option<ConstVal<'tcx>>,
379
380     /// If this is a struct's only variant, this
381     /// is the index of the "struct ctor" item.
382     pub struct_ctor: Option<DefIndex>,
383 }
384
385 impl_stable_hash_for!(struct VariantData<'tcx> {
386     ctor_kind,
387     discr,
388     evaluated_discr,
389     struct_ctor
390 });
391
392 #[derive(RustcEncodable, RustcDecodable)]
393 pub struct TraitData<'tcx> {
394     pub unsafety: hir::Unsafety,
395     pub paren_sugar: bool,
396     pub has_default_impl: bool,
397     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
398 }
399
400 impl_stable_hash_for!(struct TraitData<'tcx> {
401     unsafety,
402     paren_sugar,
403     has_default_impl,
404     super_predicates
405 });
406
407 #[derive(RustcEncodable, RustcDecodable)]
408 pub struct ImplData<'tcx> {
409     pub polarity: hir::ImplPolarity,
410     pub parent_impl: Option<DefId>,
411
412     /// This is `Some` only for impls of `CoerceUnsized`.
413     pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
414     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
415 }
416
417 impl_stable_hash_for!(struct ImplData<'tcx> {
418     polarity,
419     parent_impl,
420     coerce_unsized_info,
421     trait_ref
422 });
423
424
425 /// Describes whether the container of an associated item
426 /// is a trait or an impl and whether, in a trait, it has
427 /// a default, or an in impl, whether it's marked "default".
428 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
429 pub enum AssociatedContainer {
430     TraitRequired,
431     TraitWithDefault,
432     ImplDefault,
433     ImplFinal,
434 }
435
436 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
437     TraitRequired,
438     TraitWithDefault,
439     ImplDefault,
440     ImplFinal
441 });
442
443 impl AssociatedContainer {
444     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
445         match *self {
446             AssociatedContainer::TraitRequired |
447             AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
448
449             AssociatedContainer::ImplDefault |
450             AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
451         }
452     }
453
454     pub fn defaultness(&self) -> hir::Defaultness {
455         match *self {
456             AssociatedContainer::TraitRequired => hir::Defaultness::Default {
457                 has_value: false,
458             },
459
460             AssociatedContainer::TraitWithDefault |
461             AssociatedContainer::ImplDefault => hir::Defaultness::Default {
462                 has_value: true,
463             },
464
465             AssociatedContainer::ImplFinal => hir::Defaultness::Final,
466         }
467     }
468 }
469
470 #[derive(RustcEncodable, RustcDecodable)]
471 pub struct MethodData {
472     pub fn_data: FnData,
473     pub container: AssociatedContainer,
474     pub has_self: bool,
475 }
476 impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
477
478 #[derive(RustcEncodable, RustcDecodable)]
479 pub struct ClosureData<'tcx> {
480     pub kind: ty::ClosureKind,
481     pub ty: Lazy<ty::PolyFnSig<'tcx>>,
482 }
483 impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });