]>
Commit | Line | Data |
---|---|---|
60c5eb7d XL |
1 | use decoder::Metadata; |
2 | use table::{Table, TableBuilder}; | |
9e0c209e SL |
3 | |
4 | use rustc::hir; | |
c30ab7b3 | 5 | use rustc::hir::def::{self, CtorKind}; |
dc9dc135 XL |
6 | use rustc::hir::def_id::{DefIndex, DefId}; |
7 | use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; | |
0531ce1d | 8 | use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule}; |
9e0c209e SL |
9 | use rustc::middle::lang_items; |
10 | use rustc::mir; | |
abe05a73 | 11 | use rustc::session::CrateDisambiguator; |
dc9dc135 | 12 | use rustc::session::config::SymbolManglingVersion; |
8bb4bdeb | 13 | use rustc::ty::{self, Ty, ReprOptions}; |
83c7162d | 14 | use rustc_target::spec::{PanicStrategy, TargetTriple}; |
e74abb32 | 15 | use rustc_index::vec::IndexVec; |
b7449926 | 16 | use rustc_data_structures::svh::Svh; |
60c5eb7d XL |
17 | use rustc_data_structures::sync::MetadataRef; |
18 | use rustc_serialize::opaque::Encoder; | |
9e0c209e | 19 | use syntax::{ast, attr}; |
94b46f34 | 20 | use syntax::edition::Edition; |
476ff2be | 21 | use syntax::symbol::Symbol; |
9e0c209e SL |
22 | use syntax_pos::{self, Span}; |
23 | ||
24 | use std::marker::PhantomData; | |
e74abb32 | 25 | use std::num::NonZeroUsize; |
9e0c209e | 26 | |
60c5eb7d XL |
27 | pub use decoder::{provide, provide_extern}; |
28 | crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; | |
29 | ||
30 | mod decoder; | |
31 | mod encoder; | |
32 | mod table; | |
33 | ||
e74abb32 | 34 | crate 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 | 42 | const 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 |
49 | crate 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 | 54 | trait 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 | 62 | impl<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 | 71 | impl<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 | 108 | struct 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 | 117 | impl<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 |
127 | impl<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 |
133 | impl<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 | ||
139 | impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {} | |
140 | impl<T: ?Sized + LazyMeta> Clone for Lazy<T> { | |
c30ab7b3 SL |
141 | fn clone(&self) -> Self { |
142 | *self | |
143 | } | |
9e0c209e SL |
144 | } |
145 | ||
e1599b0c XL |
146 | impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedEncodable for Lazy<T> {} |
147 | impl<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 | 151 | enum 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`). | |
168 | macro_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 | 175 | crate 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 | 220 | crate 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 | 229 | crate 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. |
235 | macro_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 | ||
257 | define_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 |
285 | enum 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 | 321 | struct RenderedConst(String); |
83c7162d | 322 | |
9e0c209e | 323 | #[derive(RustcEncodable, RustcDecodable)] |
60c5eb7d XL |
324 | struct ModData { |
325 | reexports: Lazy<[def::Export<hir::HirId>]>, | |
9e0c209e SL |
326 | } |
327 | ||
476ff2be | 328 | #[derive(RustcEncodable, RustcDecodable)] |
60c5eb7d XL |
329 | struct MacroDef { |
330 | body: String, | |
331 | legacy: bool, | |
476ff2be SL |
332 | } |
333 | ||
9e0c209e | 334 | #[derive(RustcEncodable, RustcDecodable)] |
60c5eb7d XL |
335 | struct 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 |
342 | struct 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 |
350 | struct 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 |
358 | struct 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 | 373 | enum AssocContainer { |
9e0c209e SL |
374 | TraitRequired, |
375 | TraitWithDefault, | |
376 | ImplDefault, | |
c30ab7b3 | 377 | ImplFinal, |
9e0c209e SL |
378 | } |
379 | ||
dc9dc135 | 380 | impl 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 |
408 | struct MethodData { |
409 | fn_data: FnData, | |
410 | container: AssocContainer, | |
411 | has_self: bool, | |
9e0c209e SL |
412 | } |
413 | ||
414 | #[derive(RustcEncodable, RustcDecodable)] | |
60c5eb7d XL |
415 | struct GeneratorData<'tcx> { |
416 | layout: mir::GeneratorLayout<'tcx>, | |
ea8adc8c | 417 | } |
2c00a5a8 XL |
418 | |
419 | // Tags used for encoding Spans: | |
60c5eb7d XL |
420 | const TAG_VALID_SPAN: u8 = 0; |
421 | const TAG_INVALID_SPAN: u8 = 1; |