]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/schema.rs
9ef5b9408303d7f886ad74a3a145e2a872d6665b
[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) -> &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 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, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for TraitImpls {
281     fn hash_stable<W: StableHasherResult>(&self,
282                                           hcx: &mut StableHashingContext<'a, 'gcx, '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<'tcx>>),
347     Struct(Lazy<VariantData<'tcx>>, ReprOptions),
348     Union(Lazy<VariantData<'tcx>>, ReprOptions),
349     Fn(Lazy<FnData<'tcx>>),
350     ForeignFn(Lazy<FnData<'tcx>>),
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<'tcx>>),
358     AssociatedType(AssociatedContainer),
359     AssociatedConst(AssociatedContainer, u8),
360 }
361
362 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for EntryKind<'tcx> {
363     fn hash_stable<W: StableHasherResult>(&self,
364                                           hcx: &mut StableHashingContext<'a, 'gcx, '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     pub legacy: bool,
437 }
438
439 impl_stable_hash_for!(struct MacroDef { body, legacy });
440
441 #[derive(RustcEncodable, RustcDecodable)]
442 pub struct FnData<'tcx> {
443     pub constness: hir::Constness,
444     pub arg_names: LazySeq<ast::Name>,
445     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
446 }
447
448 impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
449
450 #[derive(RustcEncodable, RustcDecodable)]
451 pub struct VariantData<'tcx> {
452     pub ctor_kind: CtorKind,
453     pub discr: ty::VariantDiscr,
454
455     /// If this is a struct's only variant, this
456     /// is the index of the "struct ctor" item.
457     pub struct_ctor: Option<DefIndex>,
458
459     /// If this is a tuple struct or variant
460     /// ctor, this is its "function" signature.
461     pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
462 }
463
464 impl_stable_hash_for!(struct VariantData<'tcx> {
465     ctor_kind,
466     discr,
467     struct_ctor,
468     ctor_sig
469 });
470
471 #[derive(RustcEncodable, RustcDecodable)]
472 pub struct TraitData<'tcx> {
473     pub unsafety: hir::Unsafety,
474     pub paren_sugar: bool,
475     pub has_default_impl: bool,
476     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
477 }
478
479 impl_stable_hash_for!(struct TraitData<'tcx> {
480     unsafety,
481     paren_sugar,
482     has_default_impl,
483     super_predicates
484 });
485
486 #[derive(RustcEncodable, RustcDecodable)]
487 pub struct ImplData<'tcx> {
488     pub polarity: hir::ImplPolarity,
489     pub defaultness: hir::Defaultness,
490     pub parent_impl: Option<DefId>,
491
492     /// This is `Some` only for impls of `CoerceUnsized`.
493     pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
494     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
495 }
496
497 impl_stable_hash_for!(struct ImplData<'tcx> {
498     polarity,
499     defaultness,
500     parent_impl,
501     coerce_unsized_info,
502     trait_ref
503 });
504
505
506 /// Describes whether the container of an associated item
507 /// is a trait or an impl and whether, in a trait, it has
508 /// a default, or an in impl, whether it's marked "default".
509 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
510 pub enum AssociatedContainer {
511     TraitRequired,
512     TraitWithDefault,
513     ImplDefault,
514     ImplFinal,
515 }
516
517 impl_stable_hash_for!(enum ::schema::AssociatedContainer {
518     TraitRequired,
519     TraitWithDefault,
520     ImplDefault,
521     ImplFinal
522 });
523
524 impl AssociatedContainer {
525     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
526         match *self {
527             AssociatedContainer::TraitRequired |
528             AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id),
529
530             AssociatedContainer::ImplDefault |
531             AssociatedContainer::ImplFinal => ty::ImplContainer(def_id),
532         }
533     }
534
535     pub fn defaultness(&self) -> hir::Defaultness {
536         match *self {
537             AssociatedContainer::TraitRequired => hir::Defaultness::Default {
538                 has_value: false,
539             },
540
541             AssociatedContainer::TraitWithDefault |
542             AssociatedContainer::ImplDefault => hir::Defaultness::Default {
543                 has_value: true,
544             },
545
546             AssociatedContainer::ImplFinal => hir::Defaultness::Final,
547         }
548     }
549 }
550
551 #[derive(RustcEncodable, RustcDecodable)]
552 pub struct MethodData<'tcx> {
553     pub fn_data: FnData<'tcx>,
554     pub container: AssociatedContainer,
555     pub has_self: bool,
556 }
557 impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
558
559 #[derive(RustcEncodable, RustcDecodable)]
560 pub struct ClosureData<'tcx> {
561     pub kind: ty::ClosureKind,
562     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
563 }
564 impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig });