]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/schema.rs
Auto merge of #44060 - taleks:issue-43205, r=arielb1
[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::ty::{self, Ty, ReprOptions};
22 use rustc_back::PanicStrategy;
23
24 use rustc_serialize as serialize;
25 use syntax::{ast, attr};
26 use syntax::symbol::Symbol;
27 use syntax_pos::{self, Span};
28
29 use std::marker::PhantomData;
30 use std::mem;
31
32 use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
33                                            StableHasherResult};
34
35 use rustc::dep_graph::{DepGraph, DepNode};
36
37 pub fn rustc_version() -> String {
38     format!("rustc {}",
39             option_env!("CFG_VERSION").unwrap_or("unknown version"))
40 }
41
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;
46
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.
51 ///
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];
57
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;
62
63 /// A value of type T referred to by its absolute position
64 /// in the metadata, and which can be decoded lazily.
65 ///
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.
70 ///
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.
78 #[must_use]
79 pub struct Lazy<T> {
80     pub position: usize,
81     _marker: PhantomData<T>,
82 }
83
84 impl<T> Lazy<T> {
85     pub fn with_position(position: usize) -> Lazy<T> {
86         Lazy {
87             position,
88             _marker: PhantomData,
89         }
90     }
91
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 {
95         1
96     }
97 }
98
99 impl<T> Copy for Lazy<T> {}
100 impl<T> Clone for Lazy<T> {
101     fn clone(&self) -> Self {
102         *self
103     }
104 }
105
106 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
107 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
108
109 impl<CTX, T> HashStable<CTX> for Lazy<T> {
110     fn hash_stable<W: StableHasherResult>(&self,
111                                           _: &mut CTX,
112                                           _: &mut StableHasher<W>) {
113         // There's nothing to do. Whatever got encoded within this Lazy<>
114         // wrapper has already been hashed.
115     }
116 }
117
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`.
121 ///
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.
125 ///
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.
130 #[must_use]
131 pub struct LazySeq<T> {
132     pub len: usize,
133     pub position: usize,
134     _marker: PhantomData<T>,
135 }
136
137 impl<T> LazySeq<T> {
138     pub fn empty() -> LazySeq<T> {
139         LazySeq::with_position_and_length(0, 0)
140     }
141
142     pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> {
143         LazySeq {
144             len,
145             position,
146             _marker: PhantomData,
147         }
148     }
149
150     /// Returns the minimum encoded size of `length` values of type `T`.
151     pub fn min_size(length: usize) -> usize {
152         length
153     }
154 }
155
156 impl<T> Copy for LazySeq<T> {}
157 impl<T> Clone for LazySeq<T> {
158     fn clone(&self) -> Self {
159         *self
160     }
161 }
162
163 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
164 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
165
166 impl<CTX, T> HashStable<CTX> for LazySeq<T> {
167     fn hash_stable<W: StableHasherResult>(&self,
168                                           _: &mut CTX,
169                                           _: &mut StableHasher<W>) {
170         // There's nothing to do. Whatever got encoded within this Lazy<>
171         // wrapper has already been hashed.
172     }
173 }
174
175 /// Encoding / decoding state for `Lazy` and `LazySeq`.
176 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
177 pub enum LazyState {
178     /// Outside of a metadata node.
179     NoNode,
180
181     /// Inside a metadata node, and before any `Lazy` or `LazySeq`.
182     /// The position is that of the node itself.
183     NodeStart(usize),
184
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).
188     Previous(usize),
189 }
190
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
193 /// reads.
194 #[derive(RustcEncodable, RustcDecodable)]
195 pub struct Tracked<T> {
196     state: T,
197 }
198
199 impl<T> Tracked<T> {
200     pub fn new(state: T) -> Tracked<T> {
201         Tracked {
202             state,
203         }
204     }
205
206     pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode) -> &T {
207         dep_graph.read(dep_node);
208         &self.state
209     }
210
211     pub fn get_untracked(&self) -> &T {
212         &self.state
213     }
214
215     pub fn map<F, R>(&self, f: F) -> Tracked<R>
216         where F: FnOnce(&T) -> R
217     {
218         Tracked {
219             state: f(&self.state),
220         }
221     }
222 }
223
224 impl<'a, 'gcx, 'tcx, T> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for Tracked<T>
225     where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
226 {
227     fn hash_stable<W: StableHasherResult>(&self,
228                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
229                                           hasher: &mut StableHasher<W>) {
230         let Tracked {
231             ref state
232         } = *self;
233
234         state.hash_stable(hcx, hasher);
235     }
236 }
237
238
239 #[derive(RustcEncodable, RustcDecodable)]
240 pub struct CrateRoot {
241     pub name: Symbol,
242     pub triple: String,
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>,
250
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>,
261 }
262
263 #[derive(RustcEncodable, RustcDecodable)]
264 pub struct CrateDep {
265     pub name: ast::Name,
266     pub hash: hir::svh::Svh,
267     pub kind: DepKind,
268 }
269
270 impl_stable_hash_for!(struct CrateDep {
271     name,
272     hash,
273     kind
274 });
275
276 #[derive(RustcEncodable, RustcDecodable)]
277 pub struct TraitImpls {
278     pub trait_id: (u32, DefIndex),
279     pub impls: LazySeq<DefIndex>,
280 }
281
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>) {
286         let TraitImpls {
287             trait_id: (krate, def_index),
288             ref impls,
289         } = *self;
290
291         DefId {
292             krate: CrateNum::from_u32(krate),
293             index: def_index
294         }.hash_stable(hcx, hasher);
295         impls.hash_stable(hcx, hasher);
296     }
297 }
298
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>>,
308
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>>>,
314
315     pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
316     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
317 }
318
319 impl_stable_hash_for!(struct Entry<'tcx> {
320     kind,
321     visibility,
322     span,
323     attributes,
324     children,
325     stability,
326     deprecation,
327     ty,
328     inherent_impls,
329     variances,
330     generics,
331     predicates,
332     ast,
333     mir
334 });
335
336 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
337 pub enum EntryKind<'tcx> {
338     Const(u8),
339     ImmStatic,
340     MutStatic,
341     ForeignImmStatic,
342     ForeignMutStatic,
343     ForeignMod,
344     GlobalAsm,
345     Type,
346     Enum(ReprOptions),
347     Field,
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>>),
353     Mod(Lazy<ModData>),
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),
362 }
363
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);
369         match *self {
370             EntryKind::ImmStatic        |
371             EntryKind::MutStatic        |
372             EntryKind::ForeignImmStatic |
373             EntryKind::ForeignMutStatic |
374             EntryKind::ForeignMod       |
375             EntryKind::GlobalAsm        |
376             EntryKind::Field |
377             EntryKind::Type => {
378                 // Nothing else to hash here.
379             }
380             EntryKind::Const(qualif) => {
381                 qualif.hash_stable(hcx, hasher);
382             }
383             EntryKind::Enum(ref repr_options) => {
384                 repr_options.hash_stable(hcx, hasher);
385             }
386             EntryKind::Variant(ref variant_data) => {
387                 variant_data.hash_stable(hcx, hasher);
388             }
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);
393             }
394             EntryKind::Fn(ref fn_data) |
395             EntryKind::ForeignFn(ref fn_data) => {
396                 fn_data.hash_stable(hcx, hasher);
397             }
398             EntryKind::Mod(ref mod_data) => {
399                 mod_data.hash_stable(hcx, hasher);
400             }
401             EntryKind::MacroDef(ref macro_def) => {
402                 macro_def.hash_stable(hcx, hasher);
403             }
404             EntryKind::Closure(closure_data) => {
405                 closure_data.hash_stable(hcx, hasher);
406             }
407             EntryKind::Trait(ref trait_data) => {
408                 trait_data.hash_stable(hcx, hasher);
409             }
410             EntryKind::DefaultImpl(ref impl_data) |
411             EntryKind::Impl(ref impl_data) => {
412                 impl_data.hash_stable(hcx, hasher);
413             }
414             EntryKind::Method(ref method_data) => {
415                 method_data.hash_stable(hcx, hasher);
416             }
417             EntryKind::AssociatedType(associated_container) => {
418                 associated_container.hash_stable(hcx, hasher);
419             }
420             EntryKind::AssociatedConst(associated_container, qualif) => {
421                 associated_container.hash_stable(hcx, hasher);
422                 qualif.hash_stable(hcx, hasher);
423             }
424         }
425     }
426 }
427
428 #[derive(RustcEncodable, RustcDecodable)]
429 pub struct ModData {
430     pub reexports: LazySeq<def::Export>,
431 }
432
433 impl_stable_hash_for!(struct ModData { reexports });
434
435 #[derive(RustcEncodable, RustcDecodable)]
436 pub struct MacroDef {
437     pub body: String,
438     pub legacy: bool,
439 }
440
441 impl_stable_hash_for!(struct MacroDef { body, legacy });
442
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>>,
448 }
449
450 impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
451
452 #[derive(RustcEncodable, RustcDecodable)]
453 pub struct VariantData<'tcx> {
454     pub ctor_kind: CtorKind,
455     pub discr: ty::VariantDiscr,
456
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>,
460
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>>>,
464 }
465
466 impl_stable_hash_for!(struct VariantData<'tcx> {
467     ctor_kind,
468     discr,
469     struct_ctor,
470     ctor_sig
471 });
472
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>>,
479 }
480
481 impl_stable_hash_for!(struct TraitData<'tcx> {
482     unsafety,
483     paren_sugar,
484     has_default_impl,
485     super_predicates
486 });
487
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>,
493
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>>>,
497 }
498
499 impl_stable_hash_for!(struct ImplData<'tcx> {
500     polarity,
501     defaultness,
502     parent_impl,
503     coerce_unsized_info,
504     trait_ref
505 });
506
507
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 {
513     TraitRequired,
514     TraitWithDefault,
515     ImplDefault,
516     ImplFinal,
517 }
518
519 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
520     TraitRequired,
521     TraitWithDefault,
522     ImplDefault,
523     ImplFinal
524 });
525
526 impl AssociatedContainer {
527     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
528         match *self {
529             AssociatedContainer::TraitRequired |
530             AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
531
532             AssociatedContainer::ImplDefault |
533             AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
534         }
535     }
536
537     pub fn defaultness(&self) -> hir::Defaultness {
538         match *self {
539             AssociatedContainer::TraitRequired => hir::Defaultness::Default {
540                 has_value: false,
541             },
542
543             AssociatedContainer::TraitWithDefault |
544             AssociatedContainer::ImplDefault => hir::Defaultness::Default {
545                 has_value: true,
546             },
547
548             AssociatedContainer::ImplFinal => hir::Defaultness::Final,
549         }
550     }
551 }
552
553 #[derive(RustcEncodable, RustcDecodable)]
554 pub struct MethodData<'tcx> {
555     pub fn_data: FnData<'tcx>,
556     pub container: AssociatedContainer,
557     pub has_self: bool,
558 }
559 impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
560
561 #[derive(RustcEncodable, RustcDecodable)]
562 pub struct ClosureData<'tcx> {
563     pub kind: ty::ClosureKind,
564     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
565 }
566 impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig });