]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_metadata/src/rmeta/mod.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / compiler / rustc_metadata / src / rmeta / mod.rs
1 use decoder::Metadata;
2 use table::{Table, TableBuilder};
3
4 use rustc_ast::{self as ast, MacroDef};
5 use rustc_attr as attr;
6 use rustc_data_structures::svh::Svh;
7 use rustc_data_structures::sync::MetadataRef;
8 use rustc_hir as hir;
9 use rustc_hir::def::CtorKind;
10 use rustc_hir::def_id::{DefId, DefIndex, DefPathHash};
11 use rustc_hir::definitions::DefKey;
12 use rustc_hir::lang_items;
13 use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
14 use rustc_middle::hir::exports::Export;
15 use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
16 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
17 use rustc_middle::mir;
18 use rustc_middle::ty::{self, ReprOptions, Ty};
19 use rustc_serialize::opaque::Encoder;
20 use rustc_session::config::SymbolManglingVersion;
21 use rustc_session::CrateDisambiguator;
22 use rustc_span::edition::Edition;
23 use rustc_span::symbol::{Ident, Symbol};
24 use rustc_span::{self, ExpnData, ExpnId, Span};
25 use rustc_target::spec::{PanicStrategy, TargetTriple};
26
27 use std::marker::PhantomData;
28 use std::num::NonZeroUsize;
29
30 use decoder::DecodeContext;
31 pub use decoder::{provide, provide_extern};
32 crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
33 use encoder::EncodeContext;
34 use rustc_span::hygiene::SyntaxContextData;
35
36 mod decoder;
37 mod encoder;
38 mod table;
39
40 crate fn rustc_version() -> String {
41 format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version"))
42 }
43
44 /// Metadata encoding version.
45 /// N.B., increment this if you change the format of metadata such that
46 /// the rustc version can't be found to compare with `rustc_version()`.
47 const METADATA_VERSION: u8 = 5;
48
49 /// Metadata header which includes `METADATA_VERSION`.
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 crate const METADATA_HEADER: &[u8; 8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
55
56 /// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`,
57 /// e.g. for `Lazy<[T]>`, this is the length (count of `T` values).
58 trait LazyMeta {
59 type Meta: Copy + 'static;
60
61 /// Returns the minimum encoded size.
62 // FIXME(eddyb) Give better estimates for certain types.
63 fn min_size(meta: Self::Meta) -> usize;
64 }
65
66 impl<T> LazyMeta for T {
67 type Meta = ();
68
69 fn min_size(_: ()) -> usize {
70 assert_ne!(std::mem::size_of::<T>(), 0);
71 1
72 }
73 }
74
75 impl<T> LazyMeta for [T] {
76 type Meta = usize;
77
78 fn min_size(len: usize) -> usize {
79 len * T::min_size(())
80 }
81 }
82
83 /// A value of type T referred to by its absolute position
84 /// in the metadata, and which can be decoded lazily.
85 ///
86 /// Metadata is effective a tree, encoded in post-order,
87 /// and with the root's position written next to the header.
88 /// That means every single `Lazy` points to some previous
89 /// location in the metadata and is part of a larger node.
90 ///
91 /// The first `Lazy` in a node is encoded as the backwards
92 /// distance from the position where the containing node
93 /// starts and where the `Lazy` points to, while the rest
94 /// use the forward distance from the previous `Lazy`.
95 /// Distances start at 1, as 0-byte nodes are invalid.
96 /// Also invalid are nodes being referred in a different
97 /// order than they were encoded in.
98 ///
99 /// # Sequences (`Lazy<[T]>`)
100 ///
101 /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the
102 /// position, not at the position, which means that the length
103 /// doesn't need to be known before encoding all the elements.
104 ///
105 /// If the length is 0, no position is encoded, but otherwise,
106 /// the encoding is that of `Lazy`, with the distinction that
107 /// the minimal distance the length of the sequence, i.e.
108 /// it's assumed there's no 0-byte element in the sequence.
109 #[must_use]
110 // FIXME(#59875) the `Meta` parameter only exists to dodge
111 // invariance wrt `T` (coming from the `meta: T::Meta` field).
112 struct Lazy<T, Meta = <T as LazyMeta>::Meta>
113 where
114 T: ?Sized + LazyMeta<Meta = Meta>,
115 Meta: 'static + Copy,
116 {
117 position: NonZeroUsize,
118 meta: Meta,
119 _marker: PhantomData<T>,
120 }
121
122 impl<T: ?Sized + LazyMeta> Lazy<T> {
123 fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy<T> {
124 Lazy { position, meta, _marker: PhantomData }
125 }
126 }
127
128 impl<T> Lazy<T> {
129 fn from_position(position: NonZeroUsize) -> Lazy<T> {
130 Lazy::from_position_and_meta(position, ())
131 }
132 }
133
134 impl<T> Lazy<[T]> {
135 fn empty() -> Lazy<[T]> {
136 Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0)
137 }
138 }
139
140 impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {}
141 impl<T: ?Sized + LazyMeta> Clone for Lazy<T> {
142 fn clone(&self) -> Self {
143 *self
144 }
145 }
146
147 /// Encoding / decoding state for `Lazy`.
148 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
149 enum LazyState {
150 /// Outside of a metadata node.
151 NoNode,
152
153 /// Inside a metadata node, and before any `Lazy`.
154 /// The position is that of the node itself.
155 NodeStart(NonZeroUsize),
156
157 /// Inside a metadata node, with a previous `Lazy`.
158 /// The position is a conservative estimate of where that
159 /// previous `Lazy` would end (see their comments).
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`).
166 macro_rules! Lazy {
167 (Table<$I:ty, $T:ty>) => {Lazy<Table<$I, $T>, usize>};
168 ([$T:ty]) => {Lazy<[$T], usize>};
169 ($T:ty) => {Lazy<$T, ()>};
170 }
171
172 type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
173 type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
174
175 #[derive(MetadataEncodable, MetadataDecodable)]
176 crate struct ProcMacroData {
177 proc_macro_decls_static: DefIndex,
178 stability: Option<attr::Stability>,
179 macros: Lazy<[DefIndex]>,
180 }
181
182 /// Serialized metadata for a crate.
183 /// When compiling a proc-macro crate, we encode many of
184 /// the `Lazy<[T]>` fields as `Lazy::empty()`. This serves two purposes:
185 ///
186 /// 1. We avoid performing unnecessary work. Proc-macro crates can only
187 /// export proc-macros functions, which are compiled into a shared library.
188 /// As a result, a large amount of the information we normally store
189 /// (e.g. optimized MIR) is unneeded by downstream crates.
190 /// 2. We avoid serializing invalid `CrateNum`s. When we deserialize
191 /// a proc-macro crate, we don't load any of its dependencies (since we
192 /// just need to invoke a native function from the shared library).
193 /// This means that any foreign `CrateNum`s that we serialize cannot be
194 /// deserialized, since we will not know how to map them into the current
195 /// compilation session. If we were to serialize a proc-macro crate like
196 /// a normal crate, much of what we serialized would be unusable in addition
197 /// to being unused.
198 #[derive(MetadataEncodable, MetadataDecodable)]
199 crate struct CrateRoot<'tcx> {
200 name: Symbol,
201 triple: TargetTriple,
202 extra_filename: String,
203 hash: Svh,
204 disambiguator: CrateDisambiguator,
205 panic_strategy: PanicStrategy,
206 edition: Edition,
207 has_global_allocator: bool,
208 has_panic_handler: bool,
209 has_default_lib_allocator: bool,
210 plugin_registrar_fn: Option<DefIndex>,
211
212 crate_deps: Lazy<[CrateDep]>,
213 dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>,
214 lib_features: Lazy<[(Symbol, Option<Symbol>)]>,
215 lang_items: Lazy<[(DefIndex, usize)]>,
216 lang_items_missing: Lazy<[lang_items::LangItem]>,
217 diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
218 native_libraries: Lazy<[NativeLib]>,
219 foreign_modules: Lazy<[ForeignModule]>,
220 impls: Lazy<[TraitImpls]>,
221 interpret_alloc_index: Lazy<[u32]>,
222 proc_macro_data: Option<ProcMacroData>,
223
224 tables: LazyTables<'tcx>,
225
226 exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
227
228 syntax_contexts: SyntaxContextTable,
229 expn_data: ExpnDataTable,
230
231 source_map: Lazy<[rustc_span::SourceFile]>,
232
233 compiler_builtins: bool,
234 needs_allocator: bool,
235 needs_panic_runtime: bool,
236 no_builtins: bool,
237 panic_runtime: bool,
238 profiler_runtime: bool,
239 symbol_mangling_version: SymbolManglingVersion,
240 }
241
242 #[derive(Encodable, Decodable)]
243 crate struct CrateDep {
244 pub name: Symbol,
245 pub hash: Svh,
246 pub host_hash: Option<Svh>,
247 pub kind: CrateDepKind,
248 pub extra_filename: String,
249 }
250
251 #[derive(MetadataEncodable, MetadataDecodable)]
252 crate struct TraitImpls {
253 trait_id: (u32, DefIndex),
254 impls: Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>,
255 }
256
257 /// Define `LazyTables` and `TableBuilders` at the same time.
258 macro_rules! define_tables {
259 ($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
260 #[derive(MetadataEncodable, MetadataDecodable)]
261 crate struct LazyTables<'tcx> {
262 $($name: Lazy!(Table<DefIndex, $T>)),+
263 }
264
265 #[derive(Default)]
266 struct TableBuilders<'tcx> {
267 $($name: TableBuilder<DefIndex, $T>),+
268 }
269
270 impl TableBuilders<'tcx> {
271 fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
272 LazyTables {
273 $($name: self.$name.encode(buf)),+
274 }
275 }
276 }
277 }
278 }
279
280 define_tables! {
281 kind: Table<DefIndex, Lazy<EntryKind>>,
282 visibility: Table<DefIndex, Lazy<ty::Visibility>>,
283 span: Table<DefIndex, Lazy<Span>>,
284 ident_span: Table<DefIndex, Lazy<Span>>,
285 attributes: Table<DefIndex, Lazy<[ast::Attribute]>>,
286 children: Table<DefIndex, Lazy<[DefIndex]>>,
287 stability: Table<DefIndex, Lazy<attr::Stability>>,
288 const_stability: Table<DefIndex, Lazy<attr::ConstStability>>,
289 deprecation: Table<DefIndex, Lazy<attr::Deprecation>>,
290 ty: Table<DefIndex, Lazy!(Ty<'tcx>)>,
291 fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
292 impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
293 inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
294 variances: Table<DefIndex, Lazy<[ty::Variance]>>,
295 generics: Table<DefIndex, Lazy<ty::Generics>>,
296 explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
297 // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
298 // doesn't handle shorthands in its own (de)serialization impls,
299 // as it's an `enum` for which we want to derive (de)serialization,
300 // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
301 // Also, as an optimization, a missing entry indicates an empty `&[]`.
302 inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
303 super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
304 mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
305 promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
306 mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
307 unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
308 // `def_keys` and `def_path_hashes` represent a lazy version of a
309 // `DefPathTable`. This allows us to avoid deserializing an entire
310 // `DefPathTable` up front, since we may only ever use a few
311 // definitions from any given crate.
312 def_keys: Table<DefIndex, Lazy<DefKey>>,
313 def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>
314 }
315
316 #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
317 enum EntryKind {
318 AnonConst(mir::ConstQualifs, Lazy<RenderedConst>),
319 Const(mir::ConstQualifs, Lazy<RenderedConst>),
320 ImmStatic,
321 MutStatic,
322 ForeignImmStatic,
323 ForeignMutStatic,
324 ForeignMod,
325 ForeignType,
326 GlobalAsm,
327 Type,
328 TypeParam,
329 ConstParam,
330 OpaqueTy,
331 Enum(ReprOptions),
332 Field,
333 Variant(Lazy<VariantData>),
334 Struct(Lazy<VariantData>, ReprOptions),
335 Union(Lazy<VariantData>, ReprOptions),
336 Fn(Lazy<FnData>),
337 ForeignFn(Lazy<FnData>),
338 Mod(Lazy<ModData>),
339 MacroDef(Lazy<MacroDef>),
340 Closure,
341 Generator(hir::GeneratorKind),
342 Trait(Lazy<TraitData>),
343 Impl(Lazy<ImplData>),
344 AssocFn(Lazy<AssocFnData>),
345 AssocType(AssocContainer),
346 AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
347 TraitAlias,
348 }
349
350 /// Contains a constant which has been rendered to a String.
351 /// Used by rustdoc.
352 #[derive(Encodable, Decodable)]
353 struct RenderedConst(String);
354
355 #[derive(MetadataEncodable, MetadataDecodable)]
356 struct ModData {
357 reexports: Lazy<[Export<hir::HirId>]>,
358 expansion: ExpnId,
359 }
360
361 #[derive(MetadataEncodable, MetadataDecodable)]
362 struct FnData {
363 asyncness: hir::IsAsync,
364 constness: hir::Constness,
365 param_names: Lazy<[Ident]>,
366 }
367
368 #[derive(TyEncodable, TyDecodable)]
369 struct VariantData {
370 ctor_kind: CtorKind,
371 discr: ty::VariantDiscr,
372 /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
373 ctor: Option<DefIndex>,
374 is_non_exhaustive: bool,
375 }
376
377 #[derive(TyEncodable, TyDecodable)]
378 struct TraitData {
379 unsafety: hir::Unsafety,
380 paren_sugar: bool,
381 has_auto_impl: bool,
382 is_marker: bool,
383 specialization_kind: ty::trait_def::TraitSpecializationKind,
384 }
385
386 #[derive(TyEncodable, TyDecodable)]
387 struct ImplData {
388 polarity: ty::ImplPolarity,
389 defaultness: hir::Defaultness,
390 parent_impl: Option<DefId>,
391
392 /// This is `Some` only for impls of `CoerceUnsized`.
393 // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
394 coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
395 }
396
397 /// Describes whether the container of an associated item
398 /// is a trait or an impl and whether, in a trait, it has
399 /// a default, or an in impl, whether it's marked "default".
400 #[derive(Copy, Clone, TyEncodable, TyDecodable)]
401 enum AssocContainer {
402 TraitRequired,
403 TraitWithDefault,
404 ImplDefault,
405 ImplFinal,
406 }
407
408 impl AssocContainer {
409 fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer {
410 match *self {
411 AssocContainer::TraitRequired | AssocContainer::TraitWithDefault => {
412 ty::TraitContainer(def_id)
413 }
414
415 AssocContainer::ImplDefault | AssocContainer::ImplFinal => ty::ImplContainer(def_id),
416 }
417 }
418
419 fn defaultness(&self) -> hir::Defaultness {
420 match *self {
421 AssocContainer::TraitRequired => hir::Defaultness::Default { has_value: false },
422
423 AssocContainer::TraitWithDefault | AssocContainer::ImplDefault => {
424 hir::Defaultness::Default { has_value: true }
425 }
426
427 AssocContainer::ImplFinal => hir::Defaultness::Final,
428 }
429 }
430 }
431
432 #[derive(MetadataEncodable, MetadataDecodable)]
433 struct AssocFnData {
434 fn_data: FnData,
435 container: AssocContainer,
436 has_self: bool,
437 }
438
439 #[derive(TyEncodable, TyDecodable)]
440 struct GeneratorData<'tcx> {
441 layout: mir::GeneratorLayout<'tcx>,
442 }
443
444 // Tags used for encoding Spans:
445 const TAG_VALID_SPAN_LOCAL: u8 = 0;
446 const TAG_VALID_SPAN_FOREIGN: u8 = 1;
447 const TAG_INVALID_SPAN: u8 = 2;