]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_metadata/src/rmeta/mod.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_metadata / src / rmeta / mod.rs
CommitLineData
60c5eb7d
XL
1use decoder::Metadata;
2use table::{Table, TableBuilder};
9e0c209e 3
3dfed10e 4use rustc_ast::{self as ast, MacroDef};
74b04a01 5use rustc_attr as attr;
b7449926 6use rustc_data_structures::svh::Svh;
60c5eb7d 7use rustc_data_structures::sync::MetadataRef;
dfeec247 8use rustc_hir as hir;
5869c6ff 9use rustc_hir::def::{CtorKind, DefKind};
6a06907d 10use rustc_hir::def_id::{DefId, DefIndex, DefPathHash, StableCrateId};
3dfed10e 11use rustc_hir::definitions::DefKey;
ba9703b0 12use rustc_hir::lang_items;
3dfed10e 13use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
ba9703b0 14use rustc_middle::hir::exports::Export;
3dfed10e 15use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
ba9703b0
XL
16use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
17use rustc_middle::mir;
18use rustc_middle::ty::{self, ReprOptions, Ty};
60c5eb7d 19use rustc_serialize::opaque::Encoder;
ba9703b0 20use rustc_session::config::SymbolManglingVersion;
dfeec247 21use rustc_span::edition::Edition;
136023e0 22use rustc_span::hygiene::{ExpnIndex, MacroKind};
f035d41b 23use rustc_span::symbol::{Ident, Symbol};
136023e0 24use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
dfeec247 25use rustc_target::spec::{PanicStrategy, TargetTriple};
9e0c209e
SL
26
27use std::marker::PhantomData;
e74abb32 28use std::num::NonZeroUsize;
9e0c209e 29
3dfed10e 30use decoder::DecodeContext;
60c5eb7d
XL
31pub use decoder::{provide, provide_extern};
32crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
3dfed10e
XL
33use encoder::EncodeContext;
34use rustc_span::hygiene::SyntaxContextData;
60c5eb7d
XL
35
36mod decoder;
37mod encoder;
38mod table;
39
e74abb32 40crate fn rustc_version() -> String {
dfeec247 41 format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version"))
c30ab7b3 42}
9e0c209e
SL
43
44/// Metadata encoding version.
0731742a 45/// N.B., increment this if you change the format of metadata such that
476ff2be 46/// the rustc version can't be found to compare with `rustc_version()`.
60c5eb7d 47const METADATA_VERSION: u8 = 5;
9e0c209e
SL
48
49/// Metadata header which includes `METADATA_VERSION`.
9e0c209e 50///
476ff2be
SL
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.
17df50a5 54pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
9e0c209e 55
e1599b0c
XL
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).
60c5eb7d 58trait LazyMeta {
e1599b0c
XL
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
60c5eb7d 66impl<T> LazyMeta for T {
e1599b0c
XL
67 type Meta = ();
68
69 fn min_size(_: ()) -> usize {
70 assert_ne!(std::mem::size_of::<T>(), 0);
71 1
72 }
73}
74
60c5eb7d 75impl<T> LazyMeta for [T] {
e1599b0c
XL
76 type Meta = usize;
77
78 fn min_size(len: usize) -> usize {
79 len * T::min_size(())
80 }
81}
82
9e0c209e
SL
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.
e1599b0c
XL
98///
99/// # Sequences (`Lazy<[T]>`)
9e0c209e
SL
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]
e1599b0c
XL
110// FIXME(#59875) the `Meta` parameter only exists to dodge
111// invariance wrt `T` (coming from the `meta: T::Meta` field).
60c5eb7d 112struct Lazy<T, Meta = <T as LazyMeta>::Meta>
dfeec247
XL
113where
114 T: ?Sized + LazyMeta<Meta = Meta>,
115 Meta: 'static + Copy,
e1599b0c 116{
60c5eb7d
XL
117 position: NonZeroUsize,
118 meta: Meta,
c30ab7b3 119 _marker: PhantomData<T>,
9e0c209e
SL
120}
121
e1599b0c 122impl<T: ?Sized + LazyMeta> Lazy<T> {
dfeec247
XL
123 fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy<T> {
124 Lazy { position, meta, _marker: PhantomData }
9e0c209e 125 }
e1599b0c 126}
9e0c209e 127
60c5eb7d
XL
128impl<T> Lazy<T> {
129 fn from_position(position: NonZeroUsize) -> Lazy<T> {
e1599b0c 130 Lazy::from_position_and_meta(position, ())
9e0c209e
SL
131 }
132}
133
60c5eb7d
XL
134impl<T> Lazy<[T]> {
135 fn empty() -> Lazy<[T]> {
e74abb32 136 Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0)
e1599b0c
XL
137 }
138}
139
140impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {}
141impl<T: ?Sized + LazyMeta> Clone for Lazy<T> {
c30ab7b3
SL
142 fn clone(&self) -> Self {
143 *self
144 }
9e0c209e
SL
145}
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
3dfed10e 172type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
136023e0
XL
173type ExpnDataTable = Lazy<Table<ExpnIndex, Lazy<ExpnData>>>;
174type ExpnHashTable = Lazy<Table<ExpnIndex, Lazy<ExpnHash>>>;
3dfed10e 175
1b1a35ee
XL
176#[derive(MetadataEncodable, MetadataDecodable)]
177crate struct ProcMacroData {
178 proc_macro_decls_static: DefIndex,
179 stability: Option<attr::Stability>,
180 macros: Lazy<[DefIndex]>,
181}
182
183/// Serialized metadata for a crate.
184/// When compiling a proc-macro crate, we encode many of
185/// the `Lazy<[T]>` fields as `Lazy::empty()`. This serves two purposes:
186///
187/// 1. We avoid performing unnecessary work. Proc-macro crates can only
188/// export proc-macros functions, which are compiled into a shared library.
189/// As a result, a large amount of the information we normally store
190/// (e.g. optimized MIR) is unneeded by downstream crates.
191/// 2. We avoid serializing invalid `CrateNum`s. When we deserialize
192/// a proc-macro crate, we don't load any of its dependencies (since we
193/// just need to invoke a native function from the shared library).
194/// This means that any foreign `CrateNum`s that we serialize cannot be
195/// deserialized, since we will not know how to map them into the current
196/// compilation session. If we were to serialize a proc-macro crate like
197/// a normal crate, much of what we serialized would be unusable in addition
198/// to being unused.
3dfed10e 199#[derive(MetadataEncodable, MetadataDecodable)]
e74abb32 200crate struct CrateRoot<'tcx> {
60c5eb7d
XL
201 name: Symbol,
202 triple: TargetTriple,
203 extra_filename: String,
204 hash: Svh,
6a06907d 205 stable_crate_id: StableCrateId,
60c5eb7d
XL
206 panic_strategy: PanicStrategy,
207 edition: Edition,
208 has_global_allocator: bool,
209 has_panic_handler: bool,
210 has_default_lib_allocator: bool,
60c5eb7d
XL
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)]>,
f9f354fc 218 native_libraries: Lazy<[NativeLib]>,
60c5eb7d 219 foreign_modules: Lazy<[ForeignModule]>,
60c5eb7d 220 impls: Lazy<[TraitImpls]>,
60c5eb7d 221 interpret_alloc_index: Lazy<[u32]>,
1b1a35ee 222 proc_macro_data: Option<ProcMacroData>,
60c5eb7d 223
ba9703b0 224 tables: LazyTables<'tcx>,
60c5eb7d 225
ba9703b0 226 exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
3dfed10e
XL
227
228 syntax_contexts: SyntaxContextTable,
229 expn_data: ExpnDataTable,
136023e0 230 expn_hashes: ExpnHashTable,
3dfed10e 231
f035d41b 232 source_map: Lazy<[rustc_span::SourceFile]>,
ba9703b0 233
60c5eb7d
XL
234 compiler_builtins: bool,
235 needs_allocator: bool,
236 needs_panic_runtime: bool,
237 no_builtins: bool,
238 panic_runtime: bool,
239 profiler_runtime: bool,
60c5eb7d 240 symbol_mangling_version: SymbolManglingVersion,
9e0c209e
SL
241}
242
3dfed10e 243#[derive(Encodable, Decodable)]
e74abb32 244crate struct CrateDep {
f9f354fc 245 pub name: Symbol,
b7449926 246 pub hash: Svh,
e74abb32 247 pub host_hash: Option<Svh>,
3dfed10e 248 pub kind: CrateDepKind,
83c7162d 249 pub extra_filename: String,
9e0c209e
SL
250}
251
3dfed10e 252#[derive(MetadataEncodable, MetadataDecodable)]
e74abb32 253crate struct TraitImpls {
60c5eb7d 254 trait_id: (u32, DefIndex),
3dfed10e 255 impls: Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>,
9e0c209e
SL
256}
257
ba9703b0
XL
258/// Define `LazyTables` and `TableBuilders` at the same time.
259macro_rules! define_tables {
17df50a5 260 ($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => {
3dfed10e 261 #[derive(MetadataEncodable, MetadataDecodable)]
ba9703b0 262 crate struct LazyTables<'tcx> {
17df50a5 263 $($name: Lazy!(Table<$IDX, $T>)),+
60c5eb7d
XL
264 }
265
266 #[derive(Default)]
ba9703b0 267 struct TableBuilders<'tcx> {
17df50a5 268 $($name: TableBuilder<$IDX, $T>),+
60c5eb7d
XL
269 }
270
ba9703b0
XL
271 impl TableBuilders<'tcx> {
272 fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
273 LazyTables {
60c5eb7d
XL
274 $($name: self.$name.encode(buf)),+
275 }
276 }
277 }
278 }
279}
280
ba9703b0 281define_tables! {
5869c6ff 282 def_kind: Table<DefIndex, Lazy<DefKind>>,
74b04a01 283 kind: Table<DefIndex, Lazy<EntryKind>>,
60c5eb7d
XL
284 visibility: Table<DefIndex, Lazy<ty::Visibility>>,
285 span: Table<DefIndex, Lazy<Span>>,
ba9703b0 286 ident_span: Table<DefIndex, Lazy<Span>>,
60c5eb7d
XL
287 attributes: Table<DefIndex, Lazy<[ast::Attribute]>>,
288 children: Table<DefIndex, Lazy<[DefIndex]>>,
289 stability: Table<DefIndex, Lazy<attr::Stability>>,
290 const_stability: Table<DefIndex, Lazy<attr::ConstStability>>,
291 deprecation: Table<DefIndex, Lazy<attr::Deprecation>>,
292 ty: Table<DefIndex, Lazy!(Ty<'tcx>)>,
293 fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
294 impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
295 inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
296 variances: Table<DefIndex, Lazy<[ty::Variance]>>,
297 generics: Table<DefIndex, Lazy<ty::Generics>>,
298 explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
29967ef6
XL
299 expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
300 // As an optimization, a missing entry indicates an empty `&[]`.
301 inferred_outlives: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
60c5eb7d 302 super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
29967ef6
XL
303 // As an optimization, a missing entry indicates an empty `&[]`.
304 explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
f9f354fc 305 mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
5869c6ff 306 mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
f9f354fc 307 promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
1b1a35ee 308 mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
cdc7bbd5 309 const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
3dfed10e
XL
310 unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
311 // `def_keys` and `def_path_hashes` represent a lazy version of a
312 // `DefPathTable`. This allows us to avoid deserializing an entire
313 // `DefPathTable` up front, since we may only ever use a few
314 // definitions from any given crate.
315 def_keys: Table<DefIndex, Lazy<DefKey>>,
cdc7bbd5 316 def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>,
17df50a5 317 proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
9e0c209e
SL
318}
319
3dfed10e 320#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
74b04a01 321enum EntryKind {
f035d41b 322 AnonConst(mir::ConstQualifs, Lazy<RenderedConst>),
60c5eb7d 323 Const(mir::ConstQualifs, Lazy<RenderedConst>),
9e0c209e
SL
324 ImmStatic,
325 MutStatic,
326 ForeignImmStatic,
327 ForeignMutStatic,
328 ForeignMod,
abe05a73 329 ForeignType,
cc61c64b 330 GlobalAsm,
9e0c209e 331 Type,
532ac7d7
XL
332 TypeParam,
333 ConstParam,
416331ca 334 OpaqueTy,
8bb4bdeb 335 Enum(ReprOptions),
9e0c209e 336 Field,
e74abb32
XL
337 Variant(Lazy<VariantData>),
338 Struct(Lazy<VariantData>, ReprOptions),
339 Union(Lazy<VariantData>, ReprOptions),
340 Fn(Lazy<FnData>),
341 ForeignFn(Lazy<FnData>),
9e0c209e 342 Mod(Lazy<ModData>),
476ff2be 343 MacroDef(Lazy<MacroDef>),
fc512014 344 ProcMacro(MacroKind),
e74abb32 345 Closure,
74b04a01 346 Generator(hir::GeneratorKind),
e74abb32
XL
347 Trait(Lazy<TraitData>),
348 Impl(Lazy<ImplData>),
ba9703b0 349 AssocFn(Lazy<AssocFnData>),
dc9dc135 350 AssocType(AssocContainer),
60c5eb7d 351 AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
e74abb32 352 TraitAlias,
32a655c1
SL
353}
354
83c7162d
XL
355/// Contains a constant which has been rendered to a String.
356/// Used by rustdoc.
3dfed10e 357#[derive(Encodable, Decodable)]
60c5eb7d 358struct RenderedConst(String);
83c7162d 359
3dfed10e 360#[derive(MetadataEncodable, MetadataDecodable)]
60c5eb7d 361struct ModData {
dfeec247 362 reexports: Lazy<[Export<hir::HirId>]>,
3dfed10e 363 expansion: ExpnId,
9e0c209e
SL
364}
365
3dfed10e 366#[derive(MetadataEncodable, MetadataDecodable)]
60c5eb7d
XL
367struct FnData {
368 asyncness: hir::IsAsync,
369 constness: hir::Constness,
f035d41b 370 param_names: Lazy<[Ident]>,
9e0c209e
SL
371}
372
3dfed10e 373#[derive(TyEncodable, TyDecodable)]
60c5eb7d
XL
374struct VariantData {
375 ctor_kind: CtorKind,
376 discr: ty::VariantDiscr,
532ac7d7 377 /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
60c5eb7d 378 ctor: Option<DefIndex>,
3dfed10e 379 is_non_exhaustive: bool,
9e0c209e
SL
380}
381
3dfed10e 382#[derive(TyEncodable, TyDecodable)]
60c5eb7d
XL
383struct TraitData {
384 unsafety: hir::Unsafety,
385 paren_sugar: bool,
386 has_auto_impl: bool,
387 is_marker: bool,
cdc7bbd5 388 skip_array_during_method_dispatch: bool,
ba9703b0 389 specialization_kind: ty::trait_def::TraitSpecializationKind,
9fa01778
XL
390}
391
3dfed10e 392#[derive(TyEncodable, TyDecodable)]
60c5eb7d
XL
393struct ImplData {
394 polarity: ty::ImplPolarity,
136023e0 395 constness: hir::Constness,
60c5eb7d
XL
396 defaultness: hir::Defaultness,
397 parent_impl: Option<DefId>,
cc61c64b
XL
398
399 /// This is `Some` only for impls of `CoerceUnsized`.
e74abb32 400 // FIXME(eddyb) perhaps compute this on the fly if cheap enough?
60c5eb7d 401 coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
9e0c209e
SL
402}
403
404/// Describes whether the container of an associated item
405/// is a trait or an impl and whether, in a trait, it has
406/// a default, or an in impl, whether it's marked "default".
3dfed10e 407#[derive(Copy, Clone, TyEncodable, TyDecodable)]
60c5eb7d 408enum AssocContainer {
9e0c209e
SL
409 TraitRequired,
410 TraitWithDefault,
411 ImplDefault,
c30ab7b3 412 ImplFinal,
9e0c209e
SL
413}
414
dc9dc135 415impl AssocContainer {
60c5eb7d 416 fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer {
9e0c209e 417 match *self {
dfeec247
XL
418 AssocContainer::TraitRequired | AssocContainer::TraitWithDefault => {
419 ty::TraitContainer(def_id)
420 }
9e0c209e 421
dfeec247 422 AssocContainer::ImplDefault | AssocContainer::ImplFinal => ty::ImplContainer(def_id),
9e0c209e
SL
423 }
424 }
425
60c5eb7d 426 fn defaultness(&self) -> hir::Defaultness {
9e0c209e 427 match *self {
dfeec247
XL
428 AssocContainer::TraitRequired => hir::Defaultness::Default { has_value: false },
429
430 AssocContainer::TraitWithDefault | AssocContainer::ImplDefault => {
431 hir::Defaultness::Default { has_value: true }
432 }
9e0c209e 433
dc9dc135 434 AssocContainer::ImplFinal => hir::Defaultness::Final,
9e0c209e
SL
435 }
436 }
437}
438
3dfed10e 439#[derive(MetadataEncodable, MetadataDecodable)]
ba9703b0 440struct AssocFnData {
60c5eb7d
XL
441 fn_data: FnData,
442 container: AssocContainer,
443 has_self: bool,
9e0c209e
SL
444}
445
3dfed10e 446#[derive(TyEncodable, TyDecodable)]
60c5eb7d
XL
447struct GeneratorData<'tcx> {
448 layout: mir::GeneratorLayout<'tcx>,
ea8adc8c 449}
2c00a5a8
XL
450
451// Tags used for encoding Spans:
ba9703b0
XL
452const TAG_VALID_SPAN_LOCAL: u8 = 0;
453const TAG_VALID_SPAN_FOREIGN: u8 = 1;
cdc7bbd5 454const TAG_PARTIAL_SPAN: u8 = 2;