]> git.proxmox.com Git - rustc.git/blame - src/librustc_metadata/rmeta/mod.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_metadata / rmeta / mod.rs
CommitLineData
60c5eb7d
XL
1use decoder::Metadata;
2use table::{Table, TableBuilder};
9e0c209e
SL
3
4use rustc::hir;
c30ab7b3 5use rustc::hir::def::{self, CtorKind};
dc9dc135
XL
6use rustc::hir::def_id::{DefIndex, DefId};
7use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
0531ce1d 8use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
9e0c209e
SL
9use rustc::middle::lang_items;
10use rustc::mir;
abe05a73 11use rustc::session::CrateDisambiguator;
dc9dc135 12use rustc::session::config::SymbolManglingVersion;
8bb4bdeb 13use rustc::ty::{self, Ty, ReprOptions};
83c7162d 14use rustc_target::spec::{PanicStrategy, TargetTriple};
e74abb32 15use rustc_index::vec::IndexVec;
b7449926 16use rustc_data_structures::svh::Svh;
60c5eb7d
XL
17use rustc_data_structures::sync::MetadataRef;
18use rustc_serialize::opaque::Encoder;
9e0c209e 19use syntax::{ast, attr};
94b46f34 20use syntax::edition::Edition;
476ff2be 21use syntax::symbol::Symbol;
9e0c209e
SL
22use syntax_pos::{self, Span};
23
24use std::marker::PhantomData;
e74abb32 25use std::num::NonZeroUsize;
9e0c209e 26
60c5eb7d
XL
27pub use decoder::{provide, provide_extern};
28crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
29
30mod decoder;
31mod encoder;
32mod table;
33
e74abb32 34crate fn rustc_version() -> String {
c30ab7b3
SL
35 format!("rustc {}",
36 option_env!("CFG_VERSION").unwrap_or("unknown version"))
37}
9e0c209e
SL
38
39/// Metadata encoding version.
0731742a 40/// N.B., increment this if you change the format of metadata such that
476ff2be 41/// the rustc version can't be found to compare with `rustc_version()`.
60c5eb7d 42const METADATA_VERSION: u8 = 5;
9e0c209e
SL
43
44/// Metadata header which includes `METADATA_VERSION`.
9e0c209e 45///
476ff2be
SL
46/// This header is followed by the position of the `CrateRoot`,
47/// which is encoded as a 32-bit big-endian unsigned integer,
48/// and further followed by the rustc version string.
60c5eb7d
XL
49crate const METADATA_HEADER: &[u8; 8] =
50 &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
9e0c209e 51
e1599b0c
XL
52/// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`,
53/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values).
60c5eb7d 54trait LazyMeta {
e1599b0c
XL
55 type Meta: Copy + 'static;
56
57 /// Returns the minimum encoded size.
58 // FIXME(eddyb) Give better estimates for certain types.
59 fn min_size(meta: Self::Meta) -> usize;
60}
61
60c5eb7d 62impl<T> LazyMeta for T {
e1599b0c
XL
63 type Meta = ();
64
65 fn min_size(_: ()) -> usize {
66 assert_ne!(std::mem::size_of::<T>(), 0);
67 1
68 }
69}
70
60c5eb7d 71impl<T> LazyMeta for [T] {
e1599b0c
XL
72 type Meta = usize;
73
74 fn min_size(len: usize) -> usize {
75 len * T::min_size(())
76 }
77}
78
9e0c209e
SL
79/// A value of type T referred to by its absolute position
80/// in the metadata, and which can be decoded lazily.
81///
82/// Metadata is effective a tree, encoded in post-order,
83/// and with the root's position written next to the header.
84/// That means every single `Lazy` points to some previous
85/// location in the metadata and is part of a larger node.
86///
87/// The first `Lazy` in a node is encoded as the backwards
88/// distance from the position where the containing node
89/// starts and where the `Lazy` points to, while the rest
90/// use the forward distance from the previous `Lazy`.
91/// Distances start at 1, as 0-byte nodes are invalid.
92/// Also invalid are nodes being referred in a different
93/// order than they were encoded in.
e1599b0c
XL
94///
95/// # Sequences (`Lazy<[T]>`)
9e0c209e
SL
96///
97/// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
98/// position, not at the position, which means that the length
99/// doesn't need to be known before encoding all the elements.
100///
101/// If the length is 0, no position is encoded, but otherwise,
102/// the encoding is that of `Lazy`, with the distinction that
103/// the minimal distance the length of the sequence, i.e.
104/// it's assumed there's no 0-byte element in the sequence.
105#[must_use]
e1599b0c
XL
106// FIXME(#59875) the `Meta` parameter only exists to dodge
107// invariance wrt `T` (coming from the `meta: T::Meta` field).
60c5eb7d 108struct Lazy<T, Meta = <T as LazyMeta>::Meta>
e1599b0c
XL
109 where T: ?Sized + LazyMeta<Meta = Meta>,
110 Meta: 'static + Copy,
111{
60c5eb7d
XL
112 position: NonZeroUsize,
113 meta: Meta,
c30ab7b3 114 _marker: PhantomData<T>,
9e0c209e
SL
115}
116
e1599b0c 117impl<T: ?Sized + LazyMeta> Lazy<T> {
60c5eb7d 118 fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy<T> {
e1599b0c 119 Lazy {
3b2f2976 120 position,
e1599b0c 121 meta,
c30ab7b3 122 _marker: PhantomData,
9e0c209e
SL
123 }
124 }
e1599b0c 125}
9e0c209e 126
60c5eb7d
XL
127impl<T> Lazy<T> {
128 fn from_position(position: NonZeroUsize) -> Lazy<T> {
e1599b0c 129 Lazy::from_position_and_meta(position, ())
9e0c209e
SL
130 }
131}
132
60c5eb7d
XL
133impl<T> Lazy<[T]> {
134 fn empty() -> Lazy<[T]> {
e74abb32 135 Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0)
e1599b0c
XL
136 }
137}
138
139impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {}
140impl<T: ?Sized + LazyMeta> Clone for Lazy<T> {
c30ab7b3
SL
141 fn clone(&self) -> Self {
142 *self
143 }
9e0c209e
SL
144}
145
e1599b0c
XL
146impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedEncodable for Lazy<T> {}
147impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedDecodable for Lazy<T> {}
9e0c209e 148
e1599b0c 149/// Encoding / decoding state for `Lazy`.
9e0c209e 150#[derive(Copy, Clone, PartialEq, Eq, Debug)]
60c5eb7d 151enum LazyState {
9e0c209e
SL
152 /// Outside of a metadata node.
153 NoNode,
154
e1599b0c 155 /// Inside a metadata node, and before any `Lazy`.
9e0c209e 156 /// The position is that of the node itself.
e74abb32 157 NodeStart(NonZeroUsize),
9e0c209e 158
e1599b0c 159 /// Inside a metadata node, with a previous `Lazy`.
9e0c209e 160 /// The position is a conservative estimate of where that
e1599b0c 161 /// previous `Lazy` would end (see their comments).
e74abb32
XL
162 Previous(NonZeroUsize),
163}
164
165// FIXME(#59875) `Lazy!(T)` replaces `Lazy<T>`, passing the `Meta` parameter
166// manually, instead of relying on the default, to get the correct variance.
167// Only needed when `T` itself contains a parameter (e.g. `'tcx`).
168macro_rules! Lazy {
60c5eb7d 169 (Table<$I:ty, $T:ty>) => {Lazy<Table<$I, $T>, usize>};
e74abb32
XL
170 ([$T:ty]) => {Lazy<[$T], usize>};
171 ($T:ty) => {Lazy<$T, ()>};
9e0c209e
SL
172}
173
174#[derive(RustcEncodable, RustcDecodable)]
e74abb32 175crate struct CrateRoot<'tcx> {
60c5eb7d
XL
176 name: Symbol,
177 triple: TargetTriple,
178 extra_filename: String,
179 hash: Svh,
180 disambiguator: CrateDisambiguator,
181 panic_strategy: PanicStrategy,
182 edition: Edition,
183 has_global_allocator: bool,
184 has_panic_handler: bool,
185 has_default_lib_allocator: bool,
186 plugin_registrar_fn: Option<DefIndex>,
187 proc_macro_decls_static: Option<DefIndex>,
188 proc_macro_stability: Option<attr::Stability>,
189
190 crate_deps: Lazy<[CrateDep]>,
191 dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>,
192 lib_features: Lazy<[(Symbol, Option<Symbol>)]>,
193 lang_items: Lazy<[(DefIndex, usize)]>,
194 lang_items_missing: Lazy<[lang_items::LangItem]>,
195 diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
196 native_libraries: Lazy<[NativeLibrary]>,
197 foreign_modules: Lazy<[ForeignModule]>,
198 source_map: Lazy<[syntax_pos::SourceFile]>,
199 def_path_table: Lazy<hir::map::definitions::DefPathTable>,
200 impls: Lazy<[TraitImpls]>,
201 exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
202 interpret_alloc_index: Lazy<[u32]>,
203
204 per_def: LazyPerDefTables<'tcx>,
205
206 /// The DefIndex's of any proc macros delcared by this crate.
207 proc_macro_data: Option<Lazy<[DefIndex]>>,
208
209 compiler_builtins: bool,
210 needs_allocator: bool,
211 needs_panic_runtime: bool,
212 no_builtins: bool,
213 panic_runtime: bool,
214 profiler_runtime: bool,
215 sanitizer_runtime: bool,
216 symbol_mangling_version: SymbolManglingVersion,
9e0c209e
SL
217}
218
219#[derive(RustcEncodable, RustcDecodable)]
e74abb32 220crate struct CrateDep {
9e0c209e 221 pub name: ast::Name,
b7449926 222 pub hash: Svh,
e74abb32 223 pub host_hash: Option<Svh>,
476ff2be 224 pub kind: DepKind,
83c7162d 225 pub extra_filename: String,
9e0c209e
SL
226}
227
228#[derive(RustcEncodable, RustcDecodable)]
e74abb32 229crate struct TraitImpls {
60c5eb7d
XL
230 trait_id: (u32, DefIndex),
231 impls: Lazy<[DefIndex]>,
9e0c209e
SL
232}
233
60c5eb7d
XL
234/// Define `LazyPerDefTables` and `PerDefTableBuilders` at the same time.
235macro_rules! define_per_def_tables {
236 ($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
237 #[derive(RustcEncodable, RustcDecodable)]
238 crate struct LazyPerDefTables<'tcx> {
239 $($name: Lazy!(Table<DefIndex, $T>)),+
240 }
241
242 #[derive(Default)]
243 struct PerDefTableBuilders<'tcx> {
244 $($name: TableBuilder<DefIndex, $T>),+
245 }
246
247 impl PerDefTableBuilders<'tcx> {
248 fn encode(&self, buf: &mut Encoder) -> LazyPerDefTables<'tcx> {
249 LazyPerDefTables {
250 $($name: self.$name.encode(buf)),+
251 }
252 }
253 }
254 }
255}
256
257define_per_def_tables! {
258 kind: Table<DefIndex, Lazy!(EntryKind<'tcx>)>,
259 visibility: Table<DefIndex, Lazy<ty::Visibility>>,
260 span: Table<DefIndex, Lazy<Span>>,
261 attributes: Table<DefIndex, Lazy<[ast::Attribute]>>,
262 children: Table<DefIndex, Lazy<[DefIndex]>>,
263 stability: Table<DefIndex, Lazy<attr::Stability>>,
264 const_stability: Table<DefIndex, Lazy<attr::ConstStability>>,
265 deprecation: Table<DefIndex, Lazy<attr::Deprecation>>,
266 ty: Table<DefIndex, Lazy!(Ty<'tcx>)>,
267 fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
268 impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
269 inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
270 variances: Table<DefIndex, Lazy<[ty::Variance]>>,
271 generics: Table<DefIndex, Lazy<ty::Generics>>,
272 explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
273 // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
274 // doesn't handle shorthands in its own (de)serialization impls,
275 // as it's an `enum` for which we want to derive (de)serialization,
276 // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
277 // Also, as an optimization, a missing entry indicates an empty `&[]`.
278 inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
279 super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
280 mir: Table<DefIndex, Lazy!(mir::BodyAndCache<'tcx>)>,
281 promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::BodyAndCache<'tcx>>)>,
9e0c209e
SL
282}
283
284#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
60c5eb7d
XL
285enum EntryKind<'tcx> {
286 Const(mir::ConstQualifs, Lazy<RenderedConst>),
9e0c209e
SL
287 ImmStatic,
288 MutStatic,
289 ForeignImmStatic,
290 ForeignMutStatic,
291 ForeignMod,
abe05a73 292 ForeignType,
cc61c64b 293 GlobalAsm,
9e0c209e 294 Type,
532ac7d7
XL
295 TypeParam,
296 ConstParam,
416331ca 297 OpaqueTy,
8bb4bdeb 298 Enum(ReprOptions),
9e0c209e 299 Field,
e74abb32
XL
300 Variant(Lazy<VariantData>),
301 Struct(Lazy<VariantData>, ReprOptions),
302 Union(Lazy<VariantData>, ReprOptions),
303 Fn(Lazy<FnData>),
304 ForeignFn(Lazy<FnData>),
9e0c209e 305 Mod(Lazy<ModData>),
476ff2be 306 MacroDef(Lazy<MacroDef>),
e74abb32
XL
307 Closure,
308 Generator(Lazy!(GeneratorData<'tcx>)),
309 Trait(Lazy<TraitData>),
310 Impl(Lazy<ImplData>),
311 Method(Lazy<MethodData>),
dc9dc135 312 AssocType(AssocContainer),
416331ca 313 AssocOpaqueTy(AssocContainer),
60c5eb7d 314 AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
e74abb32 315 TraitAlias,
32a655c1
SL
316}
317
83c7162d
XL
318/// Contains a constant which has been rendered to a String.
319/// Used by rustdoc.
320#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d 321struct RenderedConst(String);
83c7162d 322
9e0c209e 323#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
324struct ModData {
325 reexports: Lazy<[def::Export<hir::HirId>]>,
9e0c209e
SL
326}
327
476ff2be 328#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
329struct MacroDef {
330 body: String,
331 legacy: bool,
476ff2be
SL
332}
333
9e0c209e 334#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
335struct FnData {
336 asyncness: hir::IsAsync,
337 constness: hir::Constness,
338 param_names: Lazy<[ast::Name]>,
9e0c209e
SL
339}
340
341#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
342struct VariantData {
343 ctor_kind: CtorKind,
344 discr: ty::VariantDiscr,
532ac7d7 345 /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
60c5eb7d 346 ctor: Option<DefIndex>,
9e0c209e
SL
347}
348
349#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
350struct TraitData {
351 unsafety: hir::Unsafety,
352 paren_sugar: bool,
353 has_auto_impl: bool,
354 is_marker: bool,
9fa01778
XL
355}
356
9e0c209e 357#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
358struct ImplData {
359 polarity: ty::ImplPolarity,
360 defaultness: hir::Defaultness,
361 parent_impl: Option<DefId>,
cc61c64b
XL
362
363 /// This is `Some` only for impls of `CoerceUnsized`.
e74abb32 364 // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
60c5eb7d 365 coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
9e0c209e
SL
366}
367
cc61c64b 368
9e0c209e
SL
369/// Describes whether the container of an associated item
370/// is a trait or an impl and whether, in a trait, it has
371/// a default, or an in impl, whether it's marked "default".
372#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
60c5eb7d 373enum AssocContainer {
9e0c209e
SL
374 TraitRequired,
375 TraitWithDefault,
376 ImplDefault,
c30ab7b3 377 ImplFinal,
9e0c209e
SL
378}
379
dc9dc135 380impl AssocContainer {
60c5eb7d 381 fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer {
9e0c209e 382 match *self {
dc9dc135
XL
383 AssocContainer::TraitRequired |
384 AssocContainer::TraitWithDefault => ty::TraitContainer(def_id),
9e0c209e 385
dc9dc135
XL
386 AssocContainer::ImplDefault |
387 AssocContainer::ImplFinal => ty::ImplContainer(def_id),
9e0c209e
SL
388 }
389 }
390
60c5eb7d 391 fn defaultness(&self) -> hir::Defaultness {
9e0c209e 392 match *self {
dc9dc135 393 AssocContainer::TraitRequired => hir::Defaultness::Default {
476ff2be
SL
394 has_value: false,
395 },
396
dc9dc135
XL
397 AssocContainer::TraitWithDefault |
398 AssocContainer::ImplDefault => hir::Defaultness::Default {
476ff2be
SL
399 has_value: true,
400 },
9e0c209e 401
dc9dc135 402 AssocContainer::ImplFinal => hir::Defaultness::Final,
9e0c209e
SL
403 }
404 }
405}
406
407#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
408struct MethodData {
409 fn_data: FnData,
410 container: AssocContainer,
411 has_self: bool,
9e0c209e
SL
412}
413
414#[derive(RustcEncodable, RustcDecodable)]
60c5eb7d
XL
415struct GeneratorData<'tcx> {
416 layout: mir::GeneratorLayout<'tcx>,
ea8adc8c 417}
2c00a5a8
XL
418
419// Tags used for encoding Spans:
60c5eb7d
XL
420const TAG_VALID_SPAN: u8 = 0;
421const TAG_INVALID_SPAN: u8 = 1;