]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/schema.rs
91a22d922199da6d2e6f3e35192ec9957a9491e1
[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: 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: len,
145             position: 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: state,
203         }
204     }
205
206     pub fn get(&self, dep_graph: &DepGraph, dep_node: DepNode<DefId>) -> &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, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for Tracked<T>
225     where T: HashStable<StableHashingContext<'a, 'tcx>>
226 {
227     fn hash_stable<W: StableHasherResult>(&self,
228                                           hcx: &mut StableHashingContext<'a, '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 plugin_registrar_fn: Option<DefIndex>,
247     pub macro_derive_registrar: Option<DefIndex>,
248
249     pub crate_deps: Tracked<LazySeq<CrateDep>>,
250     pub dylib_dependency_formats: Tracked<LazySeq<Option<LinkagePreference>>>,
251     pub lang_items: Tracked<LazySeq<(DefIndex, usize)>>,
252     pub lang_items_missing: Tracked<LazySeq<lang_items::LangItem>>,
253     pub native_libraries: Tracked<LazySeq<NativeLibrary>>,
254     pub codemap: LazySeq<syntax_pos::FileMap>,
255     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
256     pub impls: Tracked<LazySeq<TraitImpls>>,
257     pub exported_symbols: Tracked<LazySeq<DefIndex>>,
258     pub index: LazySeq<index::Index>,
259 }
260
261 #[derive(RustcEncodable, RustcDecodable)]
262 pub struct CrateDep {
263     pub name: ast::Name,
264     pub hash: hir::svh::Svh,
265     pub kind: DepKind,
266 }
267
268 impl_stable_hash_for!(struct CrateDep {
269     name,
270     hash,
271     kind
272 });
273
274 #[derive(RustcEncodable, RustcDecodable)]
275 pub struct TraitImpls {
276     pub trait_id: (u32, DefIndex),
277     pub impls: LazySeq<DefIndex>,
278 }
279
280 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for TraitImpls {
281     fn hash_stable<W: StableHasherResult>(&self,
282                                           hcx: &mut StableHashingContext<'a, 'tcx>,
283                                           hasher: &mut StableHasher<W>) {
284         let TraitImpls {
285             trait_id: (krate, def_index),
286             ref impls,
287         } = *self;
288
289         DefId {
290             krate: CrateNum::from_u32(krate),
291             index: def_index
292         }.hash_stable(hcx, hasher);
293         impls.hash_stable(hcx, hasher);
294     }
295 }
296
297 #[derive(RustcEncodable, RustcDecodable)]
298 pub struct Entry<'tcx> {
299     pub kind: EntryKind<'tcx>,
300     pub visibility: Lazy<ty::Visibility>,
301     pub span: Lazy<Span>,
302     pub attributes: LazySeq<ast::Attribute>,
303     pub children: LazySeq<DefIndex>,
304     pub stability: Option<Lazy<attr::Stability>>,
305     pub deprecation: Option<Lazy<attr::Deprecation>>,
306
307     pub ty: Option<Lazy<Ty<'tcx>>>,
308     pub inherent_impls: LazySeq<DefIndex>,
309     pub variances: LazySeq<ty::Variance>,
310     pub generics: Option<Lazy<ty::Generics>>,
311     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
312
313     pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
314     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
315 }
316
317 impl_stable_hash_for!(struct Entry<'tcx> {
318     kind,
319     visibility,
320     span,
321     attributes,
322     children,
323     stability,
324     deprecation,
325     ty,
326     inherent_impls,
327     variances,
328     generics,
329     predicates,
330     ast,
331     mir
332 });
333
334 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
335 pub enum EntryKind<'tcx> {
336     Const(u8),
337     ImmStatic,
338     MutStatic,
339     ForeignImmStatic,
340     ForeignMutStatic,
341     ForeignMod,
342     GlobalAsm,
343     Type,
344     Enum(ReprOptions),
345     Field,
346     Variant(Lazy<VariantData>),
347     Struct(Lazy<VariantData>, ReprOptions),
348     Union(Lazy<VariantData>, ReprOptions),
349     Fn(Lazy<FnData>),
350     ForeignFn(Lazy<FnData>),
351     Mod(Lazy<ModData>),
352     MacroDef(Lazy<MacroDef>),
353     Closure(Lazy<ClosureData<'tcx>>),
354     Trait(Lazy<TraitData<'tcx>>),
355     Impl(Lazy<ImplData<'tcx>>),
356     DefaultImpl(Lazy<ImplData<'tcx>>),
357     Method(Lazy<MethodData>),
358     AssociatedType(AssociatedContainer),
359     AssociatedConst(AssociatedContainer, u8),
360 }
361
362 impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for EntryKind<'tcx> {
363     fn hash_stable<W: StableHasherResult>(&self,
364                                           hcx: &mut StableHashingContext<'a, 'tcx>,
365                                           hasher: &mut StableHasher<W>) {
366         mem::discriminant(self).hash_stable(hcx, hasher);
367         match *self {
368             EntryKind::ImmStatic        |
369             EntryKind::MutStatic        |
370             EntryKind::ForeignImmStatic |
371             EntryKind::ForeignMutStatic |
372             EntryKind::ForeignMod       |
373             EntryKind::GlobalAsm        |
374             EntryKind::Field |
375             EntryKind::Type => {
376                 // Nothing else to hash here.
377             }
378             EntryKind::Const(qualif) => {
379                 qualif.hash_stable(hcx, hasher);
380             }
381             EntryKind::Enum(ref repr_options) => {
382                 repr_options.hash_stable(hcx, hasher);
383             }
384             EntryKind::Variant(ref variant_data) => {
385                 variant_data.hash_stable(hcx, hasher);
386             }
387             EntryKind::Struct(ref variant_data, ref repr_options) |
388             EntryKind::Union(ref variant_data, ref repr_options)  => {
389                 variant_data.hash_stable(hcx, hasher);
390                 repr_options.hash_stable(hcx, hasher);
391             }
392             EntryKind::Fn(ref fn_data) |
393             EntryKind::ForeignFn(ref fn_data) => {
394                 fn_data.hash_stable(hcx, hasher);
395             }
396             EntryKind::Mod(ref mod_data) => {
397                 mod_data.hash_stable(hcx, hasher);
398             }
399             EntryKind::MacroDef(ref macro_def) => {
400                 macro_def.hash_stable(hcx, hasher);
401             }
402             EntryKind::Closure(closure_data) => {
403                 closure_data.hash_stable(hcx, hasher);
404             }
405             EntryKind::Trait(ref trait_data) => {
406                 trait_data.hash_stable(hcx, hasher);
407             }
408             EntryKind::DefaultImpl(ref impl_data) |
409             EntryKind::Impl(ref impl_data) => {
410                 impl_data.hash_stable(hcx, hasher);
411             }
412             EntryKind::Method(ref method_data) => {
413                 method_data.hash_stable(hcx, hasher);
414             }
415             EntryKind::AssociatedType(associated_container) => {
416                 associated_container.hash_stable(hcx, hasher);
417             }
418             EntryKind::AssociatedConst(associated_container, qualif) => {
419                 associated_container.hash_stable(hcx, hasher);
420                 qualif.hash_stable(hcx, hasher);
421             }
422         }
423     }
424 }
425
426 #[derive(RustcEncodable, RustcDecodable)]
427 pub struct ModData {
428     pub reexports: LazySeq<def::Export>,
429 }
430
431 impl_stable_hash_for!(struct ModData { reexports });
432
433 #[derive(RustcEncodable, RustcDecodable)]
434 pub struct MacroDef {
435     pub body: String,
436 }
437
438 impl_stable_hash_for!(struct MacroDef { body });
439
440 #[derive(RustcEncodable, RustcDecodable)]
441 pub struct FnData {
442     pub constness: hir::Constness,
443     pub arg_names: LazySeq<ast::Name>,
444 }
445
446 impl_stable_hash_for!(struct FnData { constness, arg_names });
447
448 #[derive(RustcEncodable, RustcDecodable)]
449 pub struct VariantData {
450     pub ctor_kind: CtorKind,
451     pub discr: ty::VariantDiscr,
452
453     /// If this is a struct's only variant, this
454     /// is the index of the "struct ctor" item.
455     pub struct_ctor: Option<DefIndex>,
456 }
457
458 impl_stable_hash_for!(struct VariantData {
459     ctor_kind,
460     discr,
461     struct_ctor
462 });
463
464 #[derive(RustcEncodable, RustcDecodable)]
465 pub struct TraitData<'tcx> {
466     pub unsafety: hir::Unsafety,
467     pub paren_sugar: bool,
468     pub has_default_impl: bool,
469     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
470 }
471
472 impl_stable_hash_for!(struct TraitData<'tcx> {
473     unsafety,
474     paren_sugar,
475     has_default_impl,
476     super_predicates
477 });
478
479 #[derive(RustcEncodable, RustcDecodable)]
480 pub struct ImplData<'tcx> {
481     pub polarity: hir::ImplPolarity,
482     pub defaultness: hir::Defaultness,
483     pub parent_impl: Option<DefId>,
484
485     /// This is `Some` only for impls of `CoerceUnsized`.
486     pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
487     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
488 }
489
490 impl_stable_hash_for!(struct ImplData<'tcx> {
491     polarity,
492     defaultness,
493     parent_impl,
494     coerce_unsized_info,
495     trait_ref
496 });
497
498
499 /// Describes whether the container of an associated item
500 /// is a trait or an impl and whether, in a trait, it has
501 /// a default, or an in impl, whether it's marked "default".
502 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
503 pub enum AssociatedContainer {
504     TraitRequired,
505     TraitWithDefault,
506     ImplDefault,
507     ImplFinal,
508 }
509
510 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
511     TraitRequired,
512     TraitWithDefault,
513     ImplDefault,
514     ImplFinal
515 });
516
517 impl AssociatedContainer {
518     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
519         match *self {
520             AssociatedContainer::TraitRequired |
521             AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
522
523             AssociatedContainer::ImplDefault |
524             AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
525         }
526     }
527
528     pub fn defaultness(&self) -> hir::Defaultness {
529         match *self {
530             AssociatedContainer::TraitRequired => hir::Defaultness::Default {
531                 has_value: false,
532             },
533
534             AssociatedContainer::TraitWithDefault |
535             AssociatedContainer::ImplDefault => hir::Defaultness::Default {
536                 has_value: true,
537             },
538
539             AssociatedContainer::ImplFinal => hir::Defaultness::Final,
540         }
541     }
542 }
543
544 #[derive(RustcEncodable, RustcDecodable)]
545 pub struct MethodData {
546     pub fn_data: FnData,
547     pub container: AssociatedContainer,
548     pub has_self: bool,
549 }
550 impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
551
552 #[derive(RustcEncodable, RustcDecodable)]
553 pub struct ClosureData<'tcx> {
554     pub kind: ty::ClosureKind,
555     pub ty: Lazy<ty::PolyFnSig<'tcx>>,
556 }
557 impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });