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