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