]>
Commit | Line | Data |
---|---|---|
60c5eb7d XL |
1 | use decoder::Metadata; |
2 | use table::{Table, TableBuilder}; | |
9e0c209e | 3 | |
dfeec247 XL |
4 | use rustc::hir::exports::Export; |
5 | use rustc::hir::map; | |
6 | use rustc::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLibrary}; | |
dc9dc135 | 7 | use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; |
9e0c209e SL |
8 | use rustc::middle::lang_items; |
9 | use rustc::mir; | |
dc9dc135 | 10 | use rustc::session::config::SymbolManglingVersion; |
dfeec247 XL |
11 | use rustc::session::CrateDisambiguator; |
12 | use rustc::ty::{self, ReprOptions, Ty}; | |
74b04a01 XL |
13 | use rustc_ast::ast; |
14 | use rustc_attr as attr; | |
b7449926 | 15 | use rustc_data_structures::svh::Svh; |
60c5eb7d | 16 | use rustc_data_structures::sync::MetadataRef; |
dfeec247 XL |
17 | use rustc_hir as hir; |
18 | use rustc_hir::def::CtorKind; | |
19 | use rustc_hir::def_id::{DefId, DefIndex}; | |
20 | use rustc_index::vec::IndexVec; | |
60c5eb7d | 21 | use rustc_serialize::opaque::Encoder; |
dfeec247 XL |
22 | use rustc_span::edition::Edition; |
23 | use rustc_span::symbol::Symbol; | |
24 | use rustc_span::{self, Span}; | |
25 | use rustc_target::spec::{PanicStrategy, TargetTriple}; | |
9e0c209e SL |
26 | |
27 | use std::marker::PhantomData; | |
e74abb32 | 28 | use std::num::NonZeroUsize; |
9e0c209e | 29 | |
60c5eb7d XL |
30 | pub use decoder::{provide, provide_extern}; |
31 | crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; | |
32 | ||
33 | mod decoder; | |
34 | mod encoder; | |
35 | mod table; | |
36 | ||
e74abb32 | 37 | crate 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 | 44 | const 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 | 51 | crate 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 | 55 | trait 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 | 63 | impl<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 | 72 | impl<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 | 109 | struct Lazy<T, Meta = <T as LazyMeta>::Meta> |
dfeec247 XL |
110 | where |
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 | 119 | impl<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 |
125 | impl<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 |
131 | impl<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 | ||
137 | impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {} | |
138 | impl<T: ?Sized + LazyMeta> Clone for Lazy<T> { | |
c30ab7b3 SL |
139 | fn clone(&self) -> Self { |
140 | *self | |
141 | } | |
9e0c209e SL |
142 | } |
143 | ||
e1599b0c XL |
144 | impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedEncodable for Lazy<T> {} |
145 | impl<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 | 149 | enum 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`). | |
166 | macro_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 | 173 | crate 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 | 217 | crate 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 | 226 | crate 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. |
232 | macro_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 | ||
254 | define_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 | 282 | enum 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 | 318 | struct RenderedConst(String); |
83c7162d | 319 | |
9e0c209e | 320 | #[derive(RustcEncodable, RustcDecodable)] |
60c5eb7d | 321 | struct ModData { |
dfeec247 | 322 | reexports: Lazy<[Export<hir::HirId>]>, |
9e0c209e SL |
323 | } |
324 | ||
476ff2be | 325 | #[derive(RustcEncodable, RustcDecodable)] |
60c5eb7d XL |
326 | struct MacroDef { |
327 | body: String, | |
328 | legacy: bool, | |
476ff2be SL |
329 | } |
330 | ||
9e0c209e | 331 | #[derive(RustcEncodable, RustcDecodable)] |
60c5eb7d XL |
332 | struct 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 |
339 | struct 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 |
347 | struct 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 |
355 | struct 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 | 369 | enum AssocContainer { |
9e0c209e SL |
370 | TraitRequired, |
371 | TraitWithDefault, | |
372 | ImplDefault, | |
c30ab7b3 | 373 | ImplFinal, |
9e0c209e SL |
374 | } |
375 | ||
dc9dc135 | 376 | impl 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 |
401 | struct MethodData { |
402 | fn_data: FnData, | |
403 | container: AssocContainer, | |
404 | has_self: bool, | |
9e0c209e SL |
405 | } |
406 | ||
407 | #[derive(RustcEncodable, RustcDecodable)] | |
60c5eb7d XL |
408 | struct GeneratorData<'tcx> { |
409 | layout: mir::GeneratorLayout<'tcx>, | |
ea8adc8c | 410 | } |
2c00a5a8 XL |
411 | |
412 | // Tags used for encoding Spans: | |
60c5eb7d XL |
413 | const TAG_VALID_SPAN: u8 = 0; |
414 | const TAG_INVALID_SPAN: u8 = 1; |