]>
Commit | Line | Data |
---|---|---|
9fa01778 XL |
1 | use crate::index::Index; |
2 | use crate::index_builder::{FromId, IndexBuilder, Untracked}; | |
3 | use crate::isolated_encoder::IsolatedEncoder; | |
4 | use crate::schema::*; | |
92a42be0 | 5 | |
b7449926 | 6 | use rustc::middle::cstore::{LinkagePreference, NativeLibrary, |
0531ce1d | 7 | EncodedMetadata, ForeignModule}; |
041b39d2 | 8 | use rustc::hir::def::CtorKind; |
0531ce1d | 9 | use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; |
ff7c6d11 | 10 | use rustc::hir::map::definitions::DefPathTable; |
b7449926 | 11 | use rustc_data_structures::fingerprint::Fingerprint; |
9e0c209e | 12 | use rustc::middle::dependency_format::Linkage; |
0531ce1d XL |
13 | use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, |
14 | metadata_symbol_name}; | |
9e0c209e | 15 | use rustc::middle::lang_items; |
0531ce1d | 16 | use rustc::mir::{self, interpret}; |
54a0048b | 17 | use rustc::traits::specialization_graph; |
0531ce1d | 18 | use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; |
abe05a73 | 19 | use rustc::ty::codec::{self as ty_codec, TyEncoder}; |
a1dfa0c6 | 20 | use rustc::ty::layout::VariantIdx; |
92a42be0 | 21 | |
b7449926 | 22 | use rustc::session::config::{self, CrateType}; |
0531ce1d | 23 | use rustc::util::nodemap::FxHashMap; |
1a4d82fc | 24 | |
ff7c6d11 | 25 | use rustc_data_structures::stable_hasher::StableHasher; |
9e0c209e | 26 | use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; |
7cac9316 | 27 | |
ff7c6d11 | 28 | use std::hash::Hash; |
7cac9316 | 29 | use std::path::Path; |
0531ce1d | 30 | use rustc_data_structures::sync::Lrc; |
b039eaaf | 31 | use std::u32; |
9e0c209e SL |
32 | use syntax::ast::{self, CRATE_NODE_ID}; |
33 | use syntax::attr; | |
b7449926 | 34 | use syntax::source_map::Spanned; |
8faf50e0 | 35 | use syntax::symbol::keywords; |
b7449926 | 36 | use syntax_pos::{self, hygiene, FileName, SourceFile, Span}; |
9fa01778 | 37 | use log::{debug, trace}; |
1a4d82fc | 38 | |
54a0048b | 39 | use rustc::hir::{self, PatKind}; |
476ff2be SL |
40 | use rustc::hir::itemlikevisit::ItemLikeVisitor; |
41 | use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; | |
54a0048b | 42 | use rustc::hir::intravisit; |
9e0c209e | 43 | |
1a4d82fc | 44 | pub struct EncodeContext<'a, 'tcx: 'a> { |
8faf50e0 | 45 | opaque: opaque::Encoder, |
a7813a04 | 46 | pub tcx: TyCtxt<'a, 'tcx, 'tcx>, |
9e0c209e SL |
47 | |
48 | lazy_state: LazyState, | |
476ff2be SL |
49 | type_shorthands: FxHashMap<Ty<'tcx>, usize>, |
50 | predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>, | |
2c00a5a8 | 51 | |
0531ce1d XL |
52 | interpret_allocs: FxHashMap<interpret::AllocId, usize>, |
53 | interpret_allocs_inverse: Vec<interpret::AllocId>, | |
54 | ||
2c00a5a8 | 55 | // This is used to speed up Span encoding. |
b7449926 | 56 | source_file_cache: Lrc<SourceFile>, |
9e0c209e SL |
57 | } |
58 | ||
59 | macro_rules! encoder_methods { | |
60 | ($($name:ident($ty:ty);)*) => { | |
61 | $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { | |
62 | self.opaque.$name(value) | |
63 | })* | |
b039eaaf SL |
64 | } |
65 | } | |
66 | ||
9e0c209e | 67 | impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { |
8faf50e0 | 68 | type Error = <opaque::Encoder as Encoder>::Error; |
b039eaaf | 69 | |
b7449926 | 70 | fn emit_unit(&mut self) -> Result<(), Self::Error> { |
9e0c209e | 71 | Ok(()) |
b039eaaf SL |
72 | } |
73 | ||
9e0c209e SL |
74 | encoder_methods! { |
75 | emit_usize(usize); | |
32a655c1 | 76 | emit_u128(u128); |
9e0c209e SL |
77 | emit_u64(u64); |
78 | emit_u32(u32); | |
79 | emit_u16(u16); | |
80 | emit_u8(u8); | |
81 | ||
82 | emit_isize(isize); | |
32a655c1 | 83 | emit_i128(i128); |
9e0c209e SL |
84 | emit_i64(i64); |
85 | emit_i32(i32); | |
86 | emit_i16(i16); | |
87 | emit_i8(i8); | |
88 | ||
89 | emit_bool(bool); | |
90 | emit_f64(f64); | |
91 | emit_f32(f32); | |
92 | emit_char(char); | |
93 | emit_str(&str); | |
b039eaaf SL |
94 | } |
95 | } | |
96 | ||
9e0c209e SL |
97 | impl<'a, 'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'a, 'tcx> { |
98 | fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> { | |
99 | self.emit_lazy_distance(lazy.position, Lazy::<T>::min_size()) | |
100 | } | |
223e47cc LB |
101 | } |
102 | ||
9e0c209e SL |
103 | impl<'a, 'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'a, 'tcx> { |
104 | fn specialized_encode(&mut self, seq: &LazySeq<T>) -> Result<(), Self::Error> { | |
105 | self.emit_usize(seq.len)?; | |
106 | if seq.len == 0 { | |
107 | return Ok(()); | |
108 | } | |
109 | self.emit_lazy_distance(seq.position, LazySeq::<T>::min_size(seq.len)) | |
110 | } | |
223e47cc LB |
111 | } |
112 | ||
abe05a73 XL |
113 | impl<'a, 'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'a, 'tcx> { |
114 | #[inline] | |
115 | fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { | |
116 | self.emit_u32(cnum.as_u32()) | |
117 | } | |
118 | } | |
119 | ||
120 | impl<'a, 'tcx> SpecializedEncoder<DefId> for EncodeContext<'a, 'tcx> { | |
121 | #[inline] | |
122 | fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> { | |
123 | let DefId { | |
124 | krate, | |
125 | index, | |
126 | } = *def_id; | |
127 | ||
128 | krate.encode(self)?; | |
129 | index.encode(self) | |
130 | } | |
131 | } | |
132 | ||
133 | impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> { | |
134 | #[inline] | |
135 | fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> { | |
2c00a5a8 XL |
136 | self.emit_u32(def_index.as_raw_u32()) |
137 | } | |
138 | } | |
139 | ||
140 | impl<'a, 'tcx> SpecializedEncoder<Span> for EncodeContext<'a, 'tcx> { | |
141 | fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> { | |
8faf50e0 | 142 | if span.is_dummy() { |
2c00a5a8 XL |
143 | return TAG_INVALID_SPAN.encode(self) |
144 | } | |
145 | ||
146 | let span = span.data(); | |
147 | ||
148 | // The Span infrastructure should make sure that this invariant holds: | |
149 | debug_assert!(span.lo <= span.hi); | |
150 | ||
b7449926 XL |
151 | if !self.source_file_cache.contains(span.lo) { |
152 | let source_map = self.tcx.sess.source_map(); | |
153 | let source_file_index = source_map.lookup_source_file_idx(span.lo); | |
154 | self.source_file_cache = source_map.files()[source_file_index].clone(); | |
2c00a5a8 XL |
155 | } |
156 | ||
b7449926 | 157 | if !self.source_file_cache.contains(span.hi) { |
2c00a5a8 XL |
158 | // Unfortunately, macro expansion still sometimes generates Spans |
159 | // that malformed in this way. | |
160 | return TAG_INVALID_SPAN.encode(self) | |
161 | } | |
162 | ||
163 | TAG_VALID_SPAN.encode(self)?; | |
164 | span.lo.encode(self)?; | |
165 | ||
166 | // Encode length which is usually less than span.hi and profits more | |
167 | // from the variable-length integer encoding that we use. | |
168 | let len = span.hi - span.lo; | |
169 | len.encode(self) | |
170 | ||
171 | // Don't encode the expansion context. | |
abe05a73 XL |
172 | } |
173 | } | |
174 | ||
0531ce1d XL |
175 | impl<'a, 'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'a, 'tcx> { |
176 | #[inline] | |
177 | fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> { | |
178 | self.specialized_encode(&def_id.to_def_id()) | |
179 | } | |
180 | } | |
181 | ||
9e0c209e SL |
182 | impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> { |
183 | fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> { | |
abe05a73 | 184 | ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands) |
9e0c209e | 185 | } |
d9579d0f AL |
186 | } |
187 | ||
0531ce1d XL |
188 | impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> { |
189 | fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { | |
190 | use std::collections::hash_map::Entry; | |
191 | let index = match self.interpret_allocs.entry(*alloc_id) { | |
192 | Entry::Occupied(e) => *e.get(), | |
193 | Entry::Vacant(e) => { | |
194 | let idx = self.interpret_allocs_inverse.len(); | |
195 | self.interpret_allocs_inverse.push(*alloc_id); | |
196 | e.insert(idx); | |
197 | idx | |
198 | }, | |
199 | }; | |
200 | ||
201 | index.encode(self) | |
202 | } | |
203 | } | |
204 | ||
9e0c209e | 205 | impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext<'a, 'tcx> { |
c30ab7b3 SL |
206 | fn specialized_encode(&mut self, |
207 | predicates: &ty::GenericPredicates<'tcx>) | |
9e0c209e | 208 | -> Result<(), Self::Error> { |
abe05a73 | 209 | ty_codec::encode_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands) |
9e0c209e | 210 | } |
970d7e83 | 211 | } |
223e47cc | 212 | |
2c00a5a8 XL |
213 | impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'a, 'tcx> { |
214 | fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { | |
215 | f.encode_opaque(&mut self.opaque) | |
216 | } | |
217 | } | |
218 | ||
ff7c6d11 XL |
219 | impl<'a, 'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>> |
220 | for EncodeContext<'a, 'tcx> { | |
221 | fn specialized_encode(&mut self, | |
222 | _: &mir::ClearCrossCrate<T>) | |
223 | -> Result<(), Self::Error> { | |
224 | Ok(()) | |
225 | } | |
226 | } | |
227 | ||
abe05a73 XL |
228 | impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { |
229 | fn position(&self) -> usize { | |
9e0c209e SL |
230 | self.opaque.position() |
231 | } | |
abe05a73 XL |
232 | } |
233 | ||
234 | impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | |
1a4d82fc | 235 | |
9e0c209e SL |
236 | fn emit_node<F: FnOnce(&mut Self, usize) -> R, R>(&mut self, f: F) -> R { |
237 | assert_eq!(self.lazy_state, LazyState::NoNode); | |
238 | let pos = self.position(); | |
239 | self.lazy_state = LazyState::NodeStart(pos); | |
240 | let r = f(self, pos); | |
241 | self.lazy_state = LazyState::NoNode; | |
242 | r | |
243 | } | |
85aaf69f | 244 | |
c30ab7b3 SL |
245 | fn emit_lazy_distance(&mut self, |
246 | position: usize, | |
247 | min_size: usize) | |
9e0c209e SL |
248 | -> Result<(), <Self as Encoder>::Error> { |
249 | let min_end = position + min_size; | |
250 | let distance = match self.lazy_state { | |
c30ab7b3 | 251 | LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), |
9e0c209e SL |
252 | LazyState::NodeStart(start) => { |
253 | assert!(min_end <= start); | |
254 | start - min_end | |
255 | } | |
256 | LazyState::Previous(last_min_end) => { | |
0531ce1d XL |
257 | assert!( |
258 | last_min_end <= position, | |
259 | "make sure that the calls to `lazy*` \ | |
260 | are in the same order as the metadata fields", | |
261 | ); | |
9e0c209e SL |
262 | position - last_min_end |
263 | } | |
264 | }; | |
265 | self.lazy_state = LazyState::Previous(min_end); | |
266 | self.emit_usize(distance) | |
267 | } | |
1a4d82fc | 268 | |
9e0c209e SL |
269 | pub fn lazy<T: Encodable>(&mut self, value: &T) -> Lazy<T> { |
270 | self.emit_node(|ecx, pos| { | |
271 | value.encode(ecx).unwrap(); | |
1a4d82fc | 272 | |
9e0c209e SL |
273 | assert!(pos + Lazy::<T>::min_size() <= ecx.position()); |
274 | Lazy::with_position(pos) | |
275 | }) | |
276 | } | |
223e47cc | 277 | |
cc61c64b | 278 | pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T> |
c30ab7b3 SL |
279 | where I: IntoIterator<Item = T>, |
280 | T: Encodable | |
281 | { | |
9e0c209e SL |
282 | self.emit_node(|ecx, pos| { |
283 | let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); | |
223e47cc | 284 | |
9e0c209e SL |
285 | assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position()); |
286 | LazySeq::with_position_and_length(pos, len) | |
287 | }) | |
288 | } | |
1a4d82fc | 289 | |
cc61c64b | 290 | pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T> |
c30ab7b3 SL |
291 | where I: IntoIterator<Item = &'b T>, |
292 | T: 'b + Encodable | |
293 | { | |
9e0c209e SL |
294 | self.emit_node(|ecx, pos| { |
295 | let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); | |
1a4d82fc | 296 | |
9e0c209e SL |
297 | assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position()); |
298 | LazySeq::with_position_and_length(pos, len) | |
299 | }) | |
1a4d82fc | 300 | } |
223e47cc | 301 | |
7cac9316 XL |
302 | // Encodes something that corresponds to a single DepNode::GlobalMetaData |
303 | // and registers the Fingerprint in the `metadata_hashes` map. | |
304 | pub fn tracked<'x, DATA, R>(&'x mut self, | |
7cac9316 XL |
305 | op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R, |
306 | data: DATA) | |
ea8adc8c | 307 | -> R { |
ff7c6d11 | 308 | op(&mut IsolatedEncoder::new(self), data) |
7cac9316 XL |
309 | } |
310 | ||
311 | fn encode_info_for_items(&mut self) -> Index { | |
0731742a | 312 | let krate = self.tcx.hir().krate(); |
7cac9316 | 313 | let mut index = IndexBuilder::new(self); |
8faf50e0 | 314 | let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; |
7cac9316 XL |
315 | index.record(DefId::local(CRATE_DEF_INDEX), |
316 | IsolatedEncoder::encode_info_for_mod, | |
8faf50e0 | 317 | FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &vis))); |
a1dfa0c6 | 318 | let mut visitor = EncodeVisitor { index }; |
7cac9316 XL |
319 | krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); |
320 | for macro_def in &krate.exported_macros { | |
321 | visitor.visit_macro_def(macro_def); | |
322 | } | |
323 | visitor.index.into_items() | |
324 | } | |
325 | ||
326 | fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> { | |
0731742a | 327 | let definitions = self.tcx.hir().definitions(); |
7cac9316 XL |
328 | self.lazy(definitions.def_path_table()) |
329 | } | |
330 | ||
b7449926 XL |
331 | fn encode_source_map(&mut self) -> LazySeq<syntax_pos::SourceFile> { |
332 | let source_map = self.tcx.sess.source_map(); | |
333 | let all_source_files = source_map.files(); | |
7cac9316 | 334 | |
a1dfa0c6 | 335 | let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone(); |
7cac9316 | 336 | |
b7449926 XL |
337 | let adapted = all_source_files.iter() |
338 | .filter(|source_file| { | |
339 | // No need to re-export imported source_files, as any downstream | |
7cac9316 | 340 | // crate will import them from their original source. |
b7449926 | 341 | !source_file.is_imported() |
7cac9316 | 342 | }) |
b7449926 | 343 | .map(|source_file| { |
b7449926 | 344 | match source_file.name { |
a1dfa0c6 XL |
345 | // This path of this SourceFile has been modified by |
346 | // path-remapping, so we use it verbatim (and avoid | |
347 | // cloning the whole map in the process). | |
348 | _ if source_file.name_was_remapped => source_file.clone(), | |
349 | ||
350 | // Otherwise expand all paths to absolute paths because | |
351 | // any relative paths are potentially relative to a | |
352 | // wrong directory. | |
ff7c6d11 | 353 | FileName::Real(ref name) => { |
a1dfa0c6 XL |
354 | let mut adapted = (**source_file).clone(); |
355 | adapted.name = Path::new(&working_dir).join(name).into(); | |
356 | adapted.name_hash = { | |
357 | let mut hasher: StableHasher<u128> = StableHasher::new(); | |
358 | adapted.name.hash(&mut hasher); | |
359 | hasher.finish() | |
360 | }; | |
361 | Lrc::new(adapted) | |
ff7c6d11 | 362 | }, |
a1dfa0c6 | 363 | |
ff7c6d11 | 364 | // expanded code, not from a file |
b7449926 | 365 | _ => source_file.clone(), |
7cac9316 XL |
366 | } |
367 | }) | |
368 | .collect::<Vec<_>>(); | |
369 | ||
370 | self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) | |
371 | } | |
372 | ||
373 | fn encode_crate_root(&mut self) -> Lazy<CrateRoot> { | |
374 | let mut i = self.position(); | |
375 | ||
ff7c6d11 | 376 | let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ()); |
7cac9316 | 377 | let dylib_dependency_formats = self.tracked( |
7cac9316 XL |
378 | IsolatedEncoder::encode_dylib_dependency_formats, |
379 | ()); | |
380 | let dep_bytes = self.position() - i; | |
381 | ||
b7449926 XL |
382 | // Encode the lib features. |
383 | i = self.position(); | |
384 | let lib_features = self.tracked(IsolatedEncoder::encode_lib_features, ()); | |
385 | let lib_feature_bytes = self.position() - i; | |
386 | ||
7cac9316 XL |
387 | // Encode the language items. |
388 | i = self.position(); | |
ff7c6d11 | 389 | let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ()); |
7cac9316 | 390 | let lang_items_missing = self.tracked( |
7cac9316 XL |
391 | IsolatedEncoder::encode_lang_items_missing, |
392 | ()); | |
393 | let lang_item_bytes = self.position() - i; | |
394 | ||
395 | // Encode the native libraries used | |
396 | i = self.position(); | |
397 | let native_libraries = self.tracked( | |
7cac9316 XL |
398 | IsolatedEncoder::encode_native_libraries, |
399 | ()); | |
400 | let native_lib_bytes = self.position() - i; | |
401 | ||
0531ce1d XL |
402 | let foreign_modules = self.tracked( |
403 | IsolatedEncoder::encode_foreign_modules, | |
404 | ()); | |
405 | ||
b7449926 | 406 | // Encode source_map |
7cac9316 | 407 | i = self.position(); |
b7449926 XL |
408 | let source_map = self.encode_source_map(); |
409 | let source_map_bytes = self.position() - i; | |
7cac9316 XL |
410 | |
411 | // Encode DefPathTable | |
412 | i = self.position(); | |
413 | let def_path_table = self.encode_def_path_table(); | |
414 | let def_path_table_bytes = self.position() - i; | |
415 | ||
416 | // Encode the def IDs of impls, for coherence checking. | |
417 | i = self.position(); | |
ff7c6d11 | 418 | let impls = self.tracked(IsolatedEncoder::encode_impls, ()); |
7cac9316 XL |
419 | let impl_bytes = self.position() - i; |
420 | ||
421 | // Encode exported symbols info. | |
422 | i = self.position(); | |
0531ce1d | 423 | let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); |
7cac9316 | 424 | let exported_symbols = self.tracked( |
7cac9316 | 425 | IsolatedEncoder::encode_exported_symbols, |
0531ce1d | 426 | &exported_symbols); |
7cac9316 XL |
427 | let exported_symbols_bytes = self.position() - i; |
428 | ||
0531ce1d XL |
429 | let tcx = self.tcx; |
430 | ||
431 | // Encode the items. | |
7cac9316 XL |
432 | i = self.position(); |
433 | let items = self.encode_info_for_items(); | |
434 | let item_bytes = self.position() - i; | |
435 | ||
0531ce1d XL |
436 | // Encode the allocation index |
437 | let interpret_alloc_index = { | |
438 | let mut interpret_alloc_index = Vec::new(); | |
439 | let mut n = 0; | |
440 | trace!("beginning to encode alloc ids"); | |
441 | loop { | |
442 | let new_n = self.interpret_allocs_inverse.len(); | |
443 | // if we have found new ids, serialize those, too | |
444 | if n == new_n { | |
445 | // otherwise, abort | |
446 | break; | |
447 | } | |
448 | trace!("encoding {} further alloc ids", new_n - n); | |
449 | for idx in n..new_n { | |
450 | let id = self.interpret_allocs_inverse[idx]; | |
451 | let pos = self.position() as u32; | |
452 | interpret_alloc_index.push(pos); | |
453 | interpret::specialized_encode_alloc_id( | |
454 | self, | |
455 | tcx, | |
456 | id, | |
457 | ).unwrap(); | |
458 | } | |
459 | n = new_n; | |
460 | } | |
461 | self.lazy_seq(interpret_alloc_index) | |
462 | }; | |
463 | ||
464 | // Index the items | |
7cac9316 | 465 | i = self.position(); |
8faf50e0 | 466 | let index = items.write_index(&mut self.opaque); |
7cac9316 XL |
467 | let index_bytes = self.position() - i; |
468 | ||
0731742a | 469 | let attrs = tcx.hir().krate_attrs(); |
b7449926 | 470 | let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); |
94b46f34 | 471 | let has_default_lib_allocator = attr::contains_name(&attrs, "default_lib_allocator"); |
83c7162d | 472 | let has_global_allocator = *tcx.sess.has_global_allocator.get(); |
b7449926 | 473 | let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); |
0531ce1d | 474 | |
7cac9316 XL |
475 | let root = self.lazy(&CrateRoot { |
476 | name: tcx.crate_name(LOCAL_CRATE), | |
83c7162d | 477 | extra_filename: tcx.sess.opts.cg.extra_filename.clone(), |
7cac9316 | 478 | triple: tcx.sess.opts.target_triple.clone(), |
b7449926 | 479 | hash: tcx.crate_hash(LOCAL_CRATE), |
7cac9316 | 480 | disambiguator: tcx.sess.local_crate_disambiguator(), |
ea8adc8c | 481 | panic_strategy: tcx.sess.panic_strategy(), |
94b46f34 | 482 | edition: hygiene::default_edition(), |
ea8adc8c | 483 | has_global_allocator: has_global_allocator, |
b7449926 | 484 | has_panic_handler: has_panic_handler, |
ea8adc8c | 485 | has_default_lib_allocator: has_default_lib_allocator, |
0731742a | 486 | plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index), |
a1dfa0c6 | 487 | proc_macro_decls_static: if is_proc_macro { |
0731742a XL |
488 | let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap(); |
489 | Some(id.index) | |
7cac9316 XL |
490 | } else { |
491 | None | |
492 | }, | |
493 | ||
94b46f34 XL |
494 | compiler_builtins: attr::contains_name(&attrs, "compiler_builtins"), |
495 | needs_allocator: attr::contains_name(&attrs, "needs_allocator"), | |
496 | needs_panic_runtime: attr::contains_name(&attrs, "needs_panic_runtime"), | |
497 | no_builtins: attr::contains_name(&attrs, "no_builtins"), | |
498 | panic_runtime: attr::contains_name(&attrs, "panic_runtime"), | |
499 | profiler_runtime: attr::contains_name(&attrs, "profiler_runtime"), | |
500 | sanitizer_runtime: attr::contains_name(&attrs, "sanitizer_runtime"), | |
501 | ||
3b2f2976 XL |
502 | crate_deps, |
503 | dylib_dependency_formats, | |
b7449926 | 504 | lib_features, |
3b2f2976 XL |
505 | lang_items, |
506 | lang_items_missing, | |
507 | native_libraries, | |
0531ce1d | 508 | foreign_modules, |
b7449926 | 509 | source_map, |
3b2f2976 XL |
510 | def_path_table, |
511 | impls, | |
512 | exported_symbols, | |
0531ce1d | 513 | interpret_alloc_index, |
3b2f2976 | 514 | index, |
7cac9316 XL |
515 | }); |
516 | ||
517 | let total_bytes = self.position(); | |
518 | ||
7cac9316 XL |
519 | if self.tcx.sess.meta_stats() { |
520 | let mut zero_bytes = 0; | |
8faf50e0 | 521 | for e in self.opaque.data.iter() { |
7cac9316 XL |
522 | if *e == 0 { |
523 | zero_bytes += 1; | |
524 | } | |
525 | } | |
526 | ||
527 | println!("metadata stats:"); | |
528 | println!(" dep bytes: {}", dep_bytes); | |
b7449926 | 529 | println!(" lib feature bytes: {}", lib_feature_bytes); |
7cac9316 XL |
530 | println!(" lang item bytes: {}", lang_item_bytes); |
531 | println!(" native bytes: {}", native_lib_bytes); | |
b7449926 | 532 | println!(" source_map bytes: {}", source_map_bytes); |
7cac9316 XL |
533 | println!(" impl bytes: {}", impl_bytes); |
534 | println!(" exp. symbols bytes: {}", exported_symbols_bytes); | |
535 | println!(" def-path table bytes: {}", def_path_table_bytes); | |
536 | println!(" item bytes: {}", item_bytes); | |
537 | println!(" index bytes: {}", index_bytes); | |
538 | println!(" zero bytes: {}", zero_bytes); | |
539 | println!(" total bytes: {}", total_bytes); | |
540 | } | |
541 | ||
542 | root | |
543 | } | |
cc61c64b | 544 | } |
1a4d82fc | 545 | |
7cac9316 XL |
546 | // These are methods for encoding various things. They are meant to be used with |
547 | // IndexBuilder::record() and EncodeContext::tracked(). They actually | |
548 | // would not have to be methods of IsolatedEncoder (free standing functions | |
549 | // taking IsolatedEncoder as first argument would be just fine) but by making | |
550 | // them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>` | |
551 | // clause again and again. | |
552 | impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { | |
553 | fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> { | |
554 | debug!("IsolatedEncoder::encode_variances_of({:?})", def_id); | |
9e0c209e | 555 | let tcx = self.tcx; |
7cac9316 | 556 | self.lazy_seq_from_slice(&tcx.variances_of(def_id)) |
223e47cc | 557 | } |
970d7e83 | 558 | |
9e0c209e SL |
559 | fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> { |
560 | let tcx = self.tcx; | |
7cac9316 XL |
561 | let ty = tcx.type_of(def_id); |
562 | debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty); | |
cc61c64b | 563 | self.lazy(&ty) |
970d7e83 LB |
564 | } |
565 | ||
9e0c209e SL |
566 | /// Encode data for the given variant of the given ADT. The |
567 | /// index of the variant is untracked: this is ok because we | |
568 | /// will have to lookup the adt-def by its id, and that gives us | |
569 | /// the right to access any information in the adt-def (including, | |
570 | /// e.g., the length of the various vectors). | |
571 | fn encode_enum_variant_info(&mut self, | |
a1dfa0c6 | 572 | (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>)) |
c30ab7b3 | 573 | -> Entry<'tcx> { |
9e0c209e | 574 | let tcx = self.tcx; |
7cac9316 | 575 | let def = tcx.adt_def(enum_did); |
9e0c209e SL |
576 | let variant = &def.variants[index]; |
577 | let def_id = variant.did; | |
7cac9316 | 578 | debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id); |
9e0c209e SL |
579 | |
580 | let data = VariantData { | |
c30ab7b3 | 581 | ctor_kind: variant.ctor_kind, |
8bb4bdeb | 582 | discr: variant.discr, |
c30ab7b3 | 583 | struct_ctor: None, |
041b39d2 XL |
584 | ctor_sig: if variant.ctor_kind == CtorKind::Fn { |
585 | Some(self.lazy(&tcx.fn_sig(def_id))) | |
586 | } else { | |
587 | None | |
588 | } | |
9e0c209e | 589 | }; |
970d7e83 | 590 | |
0731742a XL |
591 | let enum_id = tcx.hir().as_local_node_id(enum_did).unwrap(); |
592 | let enum_vis = &tcx.hir().expect_item(enum_id).vis; | |
9e0c209e SL |
593 | |
594 | Entry { | |
595 | kind: EntryKind::Variant(self.lazy(&data)), | |
32a655c1 | 596 | visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)), |
476ff2be | 597 | span: self.lazy(&tcx.def_span(def_id)), |
9e0c209e SL |
598 | attributes: self.encode_attributes(&tcx.get_attrs(def_id)), |
599 | children: self.lazy_seq(variant.fields.iter().map(|f| { | |
600 | assert!(f.did.is_local()); | |
601 | f.did.index | |
602 | })), | |
603 | stability: self.encode_stability(def_id), | |
604 | deprecation: self.encode_deprecation(def_id), | |
605 | ||
606 | ty: Some(self.encode_item_type(def_id)), | |
607 | inherent_impls: LazySeq::empty(), | |
041b39d2 XL |
608 | variances: if variant.ctor_kind == CtorKind::Fn { |
609 | self.encode_variances_of(def_id) | |
610 | } else { | |
611 | LazySeq::empty() | |
612 | }, | |
9e0c209e SL |
613 | generics: Some(self.encode_generics(def_id)), |
614 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 615 | predicates_defined_on: None, |
9e0c209e | 616 | |
7cac9316 | 617 | mir: self.encode_optimized_mir(def_id), |
9e0c209e | 618 | } |
970d7e83 | 619 | } |
223e47cc | 620 | |
9e0c209e | 621 | fn encode_info_for_mod(&mut self, |
c30ab7b3 SL |
622 | FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, |
623 | &[ast::Attribute], | |
624 | &hir::Visibility)>) | |
9e0c209e SL |
625 | -> Entry<'tcx> { |
626 | let tcx = self.tcx; | |
0731742a | 627 | let def_id = tcx.hir().local_def_id(id); |
7cac9316 | 628 | debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id); |
9e0c209e SL |
629 | |
630 | let data = ModData { | |
ea8adc8c | 631 | reexports: match tcx.module_exports(def_id) { |
ff7c6d11 | 632 | Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()), |
c30ab7b3 SL |
633 | _ => LazySeq::empty(), |
634 | }, | |
9e0c209e | 635 | }; |
223e47cc | 636 | |
9e0c209e SL |
637 | Entry { |
638 | kind: EntryKind::Mod(self.lazy(&data)), | |
32a655c1 | 639 | visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)), |
3b2f2976 | 640 | span: self.lazy(&tcx.def_span(def_id)), |
9e0c209e SL |
641 | attributes: self.encode_attributes(attrs), |
642 | children: self.lazy_seq(md.item_ids.iter().map(|item_id| { | |
0731742a | 643 | tcx.hir().local_def_id(item_id.id).index |
9e0c209e SL |
644 | })), |
645 | stability: self.encode_stability(def_id), | |
646 | deprecation: self.encode_deprecation(def_id), | |
647 | ||
648 | ty: None, | |
649 | inherent_impls: LazySeq::empty(), | |
650 | variances: LazySeq::empty(), | |
651 | generics: None, | |
652 | predicates: None, | |
8faf50e0 | 653 | predicates_defined_on: None, |
9e0c209e | 654 | |
9e0c209e SL |
655 | mir: None |
656 | } | |
657 | } | |
223e47cc | 658 | |
9e0c209e SL |
659 | /// Encode data for the given field of the given variant of the |
660 | /// given ADT. The indices of the variant/field are untracked: | |
661 | /// this is ok because we will have to lookup the adt-def by its | |
662 | /// id, and that gives us the right to access any information in | |
663 | /// the adt-def (including, e.g., the length of the various | |
664 | /// vectors). | |
665 | fn encode_field(&mut self, | |
c30ab7b3 | 666 | (adt_def_id, Untracked((variant_index, field_index))): (DefId, |
a1dfa0c6 | 667 | Untracked<(VariantIdx, |
c30ab7b3 SL |
668 | usize)>)) |
669 | -> Entry<'tcx> { | |
9e0c209e | 670 | let tcx = self.tcx; |
7cac9316 | 671 | let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; |
9e0c209e SL |
672 | let field = &variant.fields[field_index]; |
673 | ||
674 | let def_id = field.did; | |
7cac9316 | 675 | debug!("IsolatedEncoder::encode_field({:?})", def_id); |
cc61c64b | 676 | |
9fa01778 | 677 | let variant_id = tcx.hir().as_local_hir_id(variant.did).unwrap(); |
0731742a | 678 | let variant_data = tcx.hir().expect_variant_data(variant_id); |
9e0c209e SL |
679 | |
680 | Entry { | |
681 | kind: EntryKind::Field, | |
32a655c1 | 682 | visibility: self.lazy(&field.vis), |
476ff2be | 683 | span: self.lazy(&tcx.def_span(def_id)), |
9e0c209e SL |
684 | attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), |
685 | children: LazySeq::empty(), | |
686 | stability: self.encode_stability(def_id), | |
687 | deprecation: self.encode_deprecation(def_id), | |
688 | ||
689 | ty: Some(self.encode_item_type(def_id)), | |
690 | inherent_impls: LazySeq::empty(), | |
691 | variances: LazySeq::empty(), | |
692 | generics: Some(self.encode_generics(def_id)), | |
693 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 694 | predicates_defined_on: None, |
9e0c209e | 695 | |
c30ab7b3 | 696 | mir: None, |
223e47cc LB |
697 | } |
698 | } | |
223e47cc | 699 | |
c30ab7b3 | 700 | fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { |
7cac9316 | 701 | debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id); |
c30ab7b3 | 702 | let tcx = self.tcx; |
abe05a73 | 703 | let adt_def = tcx.adt_def(adt_def_id); |
2c00a5a8 | 704 | let variant = adt_def.non_enum_variant(); |
1a4d82fc | 705 | |
9e0c209e | 706 | let data = VariantData { |
c30ab7b3 | 707 | ctor_kind: variant.ctor_kind, |
8bb4bdeb | 708 | discr: variant.discr, |
c30ab7b3 | 709 | struct_ctor: Some(def_id.index), |
041b39d2 XL |
710 | ctor_sig: if variant.ctor_kind == CtorKind::Fn { |
711 | Some(self.lazy(&tcx.fn_sig(def_id))) | |
712 | } else { | |
713 | None | |
714 | } | |
9e0c209e | 715 | }; |
223e47cc | 716 | |
0731742a XL |
717 | let struct_id = tcx.hir().as_local_node_id(adt_def_id).unwrap(); |
718 | let struct_vis = &tcx.hir().expect_item(struct_id).vis; | |
8bb4bdeb XL |
719 | let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx); |
720 | for field in &variant.fields { | |
721 | if ctor_vis.is_at_least(field.vis, tcx) { | |
722 | ctor_vis = field.vis; | |
723 | } | |
724 | } | |
725 | ||
abe05a73 XL |
726 | // If the structure is marked as non_exhaustive then lower the visibility |
727 | // to within the crate. | |
b7449926 XL |
728 | if adt_def.non_enum_variant().is_field_list_non_exhaustive() && |
729 | ctor_vis == ty::Visibility::Public | |
730 | { | |
abe05a73 XL |
731 | ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); |
732 | } | |
733 | ||
8bb4bdeb | 734 | let repr_options = get_repr_options(&tcx, adt_def_id); |
c30ab7b3 | 735 | |
9e0c209e | 736 | Entry { |
8bb4bdeb XL |
737 | kind: EntryKind::Struct(self.lazy(&data), repr_options), |
738 | visibility: self.lazy(&ctor_vis), | |
476ff2be | 739 | span: self.lazy(&tcx.def_span(def_id)), |
9e0c209e SL |
740 | attributes: LazySeq::empty(), |
741 | children: LazySeq::empty(), | |
742 | stability: self.encode_stability(def_id), | |
743 | deprecation: self.encode_deprecation(def_id), | |
744 | ||
745 | ty: Some(self.encode_item_type(def_id)), | |
746 | inherent_impls: LazySeq::empty(), | |
041b39d2 XL |
747 | variances: if variant.ctor_kind == CtorKind::Fn { |
748 | self.encode_variances_of(def_id) | |
749 | } else { | |
750 | LazySeq::empty() | |
751 | }, | |
9e0c209e SL |
752 | generics: Some(self.encode_generics(def_id)), |
753 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 754 | predicates_defined_on: None, |
9e0c209e | 755 | |
7cac9316 | 756 | mir: self.encode_optimized_mir(def_id), |
9e0c209e SL |
757 | } |
758 | } | |
1a4d82fc | 759 | |
8bb4bdeb | 760 | fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> { |
7cac9316 | 761 | debug!("IsolatedEncoder::encode_generics({:?})", def_id); |
9e0c209e | 762 | let tcx = self.tcx; |
7cac9316 | 763 | self.lazy(tcx.generics_of(def_id)) |
1a4d82fc JJ |
764 | } |
765 | ||
9e0c209e | 766 | fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> { |
7cac9316 | 767 | debug!("IsolatedEncoder::encode_predicates({:?})", def_id); |
9e0c209e | 768 | let tcx = self.tcx; |
7cac9316 | 769 | self.lazy(&tcx.predicates_of(def_id)) |
1a4d82fc JJ |
770 | } |
771 | ||
8faf50e0 XL |
772 | fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> { |
773 | debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id); | |
774 | let tcx = self.tcx; | |
775 | self.lazy(&tcx.predicates_defined_on(def_id)) | |
776 | } | |
777 | ||
9e0c209e | 778 | fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { |
7cac9316 | 779 | debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id); |
9e0c209e | 780 | let tcx = self.tcx; |
c34b1796 | 781 | |
0731742a XL |
782 | let node_id = tcx.hir().as_local_node_id(def_id).unwrap(); |
783 | let ast_item = tcx.hir().expect_trait_item(node_id); | |
476ff2be SL |
784 | let trait_item = tcx.associated_item(def_id); |
785 | ||
786 | let container = match trait_item.defaultness { | |
787 | hir::Defaultness::Default { has_value: true } => | |
788 | AssociatedContainer::TraitWithDefault, | |
789 | hir::Defaultness::Default { has_value: false } => | |
790 | AssociatedContainer::TraitRequired, | |
791 | hir::Defaultness::Final => | |
792 | span_bug!(ast_item.span, "traits cannot have final items"), | |
b039eaaf | 793 | }; |
1a4d82fc | 794 | |
476ff2be | 795 | let kind = match trait_item.kind { |
8bb4bdeb | 796 | ty::AssociatedKind::Const => { |
83c7162d XL |
797 | let const_qualif = |
798 | if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { | |
799 | self.const_qualif(0, body) | |
800 | } else { | |
801 | ConstQualif { mir: 0, ast_promotable: false } | |
802 | }; | |
803 | ||
804 | let rendered = | |
0731742a | 805 | hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); |
83c7162d XL |
806 | let rendered_const = self.lazy(&RenderedConst(rendered)); |
807 | ||
808 | EntryKind::AssociatedConst(container, const_qualif, rendered_const) | |
8bb4bdeb | 809 | } |
476ff2be | 810 | ty::AssociatedKind::Method => { |
32a655c1 SL |
811 | let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { |
812 | let arg_names = match *m { | |
813 | hir::TraitMethod::Required(ref names) => { | |
814 | self.encode_fn_arg_names(names) | |
815 | } | |
816 | hir::TraitMethod::Provided(body) => { | |
817 | self.encode_fn_arg_names_for_body(body) | |
818 | } | |
819 | }; | |
9e0c209e SL |
820 | FnData { |
821 | constness: hir::Constness::NotConst, | |
3b2f2976 | 822 | arg_names, |
041b39d2 | 823 | sig: self.lazy(&tcx.fn_sig(def_id)), |
9e0c209e SL |
824 | } |
825 | } else { | |
826 | bug!() | |
827 | }; | |
476ff2be | 828 | EntryKind::Method(self.lazy(&MethodData { |
3b2f2976 XL |
829 | fn_data, |
830 | container, | |
476ff2be SL |
831 | has_self: trait_item.method_has_self_argument, |
832 | })) | |
9e0c209e | 833 | } |
476ff2be | 834 | ty::AssociatedKind::Type => EntryKind::AssociatedType(container), |
8faf50e0 XL |
835 | ty::AssociatedKind::Existential => |
836 | span_bug!(ast_item.span, "existential type in trait"), | |
9e0c209e | 837 | }; |
1a4d82fc | 838 | |
9e0c209e | 839 | Entry { |
3b2f2976 | 840 | kind, |
32a655c1 | 841 | visibility: self.lazy(&trait_item.vis), |
476ff2be | 842 | span: self.lazy(&ast_item.span), |
9e0c209e SL |
843 | attributes: self.encode_attributes(&ast_item.attrs), |
844 | children: LazySeq::empty(), | |
845 | stability: self.encode_stability(def_id), | |
846 | deprecation: self.encode_deprecation(def_id), | |
847 | ||
476ff2be SL |
848 | ty: match trait_item.kind { |
849 | ty::AssociatedKind::Const | | |
850 | ty::AssociatedKind::Method => { | |
851 | Some(self.encode_item_type(def_id)) | |
852 | } | |
853 | ty::AssociatedKind::Type => { | |
854 | if trait_item.defaultness.has_value() { | |
855 | Some(self.encode_item_type(def_id)) | |
856 | } else { | |
857 | None | |
858 | } | |
9e0c209e | 859 | } |
8faf50e0 | 860 | ty::AssociatedKind::Existential => unreachable!(), |
9e0c209e SL |
861 | }, |
862 | inherent_impls: LazySeq::empty(), | |
041b39d2 XL |
863 | variances: if trait_item.kind == ty::AssociatedKind::Method { |
864 | self.encode_variances_of(def_id) | |
865 | } else { | |
866 | LazySeq::empty() | |
867 | }, | |
9e0c209e SL |
868 | generics: Some(self.encode_generics(def_id)), |
869 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 870 | predicates_defined_on: None, |
9e0c209e | 871 | |
7cac9316 | 872 | mir: self.encode_optimized_mir(def_id), |
1a4d82fc | 873 | } |
1a4d82fc | 874 | } |
1a4d82fc | 875 | |
83c7162d XL |
876 | fn metadata_output_only(&self) -> bool { |
877 | // MIR optimisation can be skipped when we're just interested in the metadata. | |
94b46f34 | 878 | !self.tcx.sess.opts.output_types.should_codegen() |
83c7162d XL |
879 | } |
880 | ||
881 | fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif { | |
0731742a | 882 | let body_owner_def_id = self.tcx.hir().body_owner_def_id(body_id); |
83c7162d XL |
883 | let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id); |
884 | ||
885 | ConstQualif { mir, ast_promotable } | |
886 | } | |
887 | ||
9e0c209e | 888 | fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { |
7cac9316 | 889 | debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); |
041b39d2 XL |
890 | let tcx = self.tcx; |
891 | ||
0731742a XL |
892 | let node_id = self.tcx.hir().as_local_node_id(def_id).unwrap(); |
893 | let ast_item = self.tcx.hir().expect_impl_item(node_id); | |
476ff2be | 894 | let impl_item = self.tcx.associated_item(def_id); |
d9579d0f | 895 | |
476ff2be SL |
896 | let container = match impl_item.defaultness { |
897 | hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault, | |
c30ab7b3 | 898 | hir::Defaultness::Final => AssociatedContainer::ImplFinal, |
476ff2be SL |
899 | hir::Defaultness::Default { has_value: false } => |
900 | span_bug!(ast_item.span, "impl items always have values (currently)"), | |
9e0c209e | 901 | }; |
d9579d0f | 902 | |
476ff2be | 903 | let kind = match impl_item.kind { |
8bb4bdeb | 904 | ty::AssociatedKind::Const => { |
83c7162d XL |
905 | if let hir::ImplItemKind::Const(_, body_id) = ast_item.node { |
906 | let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; | |
907 | ||
908 | EntryKind::AssociatedConst(container, | |
909 | self.const_qualif(mir, body_id), | |
910 | self.encode_rendered_const_for_body(body_id)) | |
911 | } else { | |
912 | bug!() | |
913 | } | |
8bb4bdeb | 914 | } |
476ff2be | 915 | ty::AssociatedKind::Method => { |
32a655c1 | 916 | let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { |
9e0c209e | 917 | FnData { |
8faf50e0 | 918 | constness: sig.header.constness, |
32a655c1 | 919 | arg_names: self.encode_fn_arg_names_for_body(body), |
041b39d2 | 920 | sig: self.lazy(&tcx.fn_sig(def_id)), |
9e0c209e SL |
921 | } |
922 | } else { | |
923 | bug!() | |
924 | }; | |
476ff2be | 925 | EntryKind::Method(self.lazy(&MethodData { |
3b2f2976 XL |
926 | fn_data, |
927 | container, | |
476ff2be SL |
928 | has_self: impl_item.method_has_self_argument, |
929 | })) | |
9e0c209e | 930 | } |
8faf50e0 | 931 | ty::AssociatedKind::Existential => EntryKind::AssociatedExistential(container), |
476ff2be | 932 | ty::AssociatedKind::Type => EntryKind::AssociatedType(container) |
9e0c209e | 933 | }; |
223e47cc | 934 | |
83c7162d XL |
935 | let mir = |
936 | match ast_item.node { | |
937 | hir::ImplItemKind::Const(..) => true, | |
938 | hir::ImplItemKind::Method(ref sig, _) => { | |
939 | let generics = self.tcx.generics_of(def_id); | |
94b46f34 XL |
940 | let needs_inline = (generics.requires_monomorphization(self.tcx) || |
941 | tcx.codegen_fn_attrs(def_id).requests_inline()) && | |
942 | !self.metadata_output_only(); | |
8faf50e0 | 943 | let is_const_fn = sig.header.constness == hir::Constness::Const; |
83c7162d XL |
944 | let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; |
945 | needs_inline || is_const_fn || always_encode_mir | |
946 | }, | |
8faf50e0 | 947 | hir::ImplItemKind::Existential(..) | |
83c7162d XL |
948 | hir::ImplItemKind::Type(..) => false, |
949 | }; | |
9e0c209e SL |
950 | |
951 | Entry { | |
3b2f2976 | 952 | kind, |
32a655c1 | 953 | visibility: self.lazy(&impl_item.vis), |
476ff2be | 954 | span: self.lazy(&ast_item.span), |
9e0c209e SL |
955 | attributes: self.encode_attributes(&ast_item.attrs), |
956 | children: LazySeq::empty(), | |
957 | stability: self.encode_stability(def_id), | |
958 | deprecation: self.encode_deprecation(def_id), | |
959 | ||
476ff2be | 960 | ty: Some(self.encode_item_type(def_id)), |
9e0c209e | 961 | inherent_impls: LazySeq::empty(), |
041b39d2 XL |
962 | variances: if impl_item.kind == ty::AssociatedKind::Method { |
963 | self.encode_variances_of(def_id) | |
964 | } else { | |
965 | LazySeq::empty() | |
966 | }, | |
9e0c209e SL |
967 | generics: Some(self.encode_generics(def_id)), |
968 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 969 | predicates_defined_on: None, |
9e0c209e | 970 | |
7cac9316 | 971 | mir: if mir { self.encode_optimized_mir(def_id) } else { None }, |
1a4d82fc | 972 | } |
223e47cc | 973 | } |
1a4d82fc | 974 | |
32a655c1 SL |
975 | fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) |
976 | -> LazySeq<ast::Name> { | |
2c00a5a8 | 977 | self.tcx.dep_graph.with_ignore(|| { |
0731742a | 978 | let body = self.tcx.hir().body(body_id); |
2c00a5a8 XL |
979 | self.lazy_seq(body.arguments.iter().map(|arg| { |
980 | match arg.pat.node { | |
9fa01778 | 981 | PatKind::Binding(_, _, _, ident, _) => ident.name, |
8faf50e0 | 982 | _ => keywords::Invalid.name(), |
2c00a5a8 XL |
983 | } |
984 | })) | |
985 | }) | |
1a4d82fc | 986 | } |
1a4d82fc | 987 | |
8faf50e0 XL |
988 | fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> LazySeq<ast::Name> { |
989 | self.lazy_seq(param_names.iter().map(|ident| ident.name)) | |
32a655c1 SL |
990 | } |
991 | ||
7cac9316 | 992 | fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> { |
cc61c64b | 993 | debug!("EntryBuilder::encode_mir({:?})", def_id); |
7cac9316 XL |
994 | if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { |
995 | let mir = self.tcx.optimized_mir(def_id); | |
996 | Some(self.lazy(&mir)) | |
997 | } else { | |
998 | None | |
999 | } | |
9cc50fc6 | 1000 | } |
223e47cc | 1001 | |
9e0c209e SL |
1002 | // Encodes the inherent implementations of a structure, enumeration, or trait. |
1003 | fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> { | |
7cac9316 XL |
1004 | debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id); |
1005 | let implementations = self.tcx.inherent_impls(def_id); | |
1006 | if implementations.is_empty() { | |
1007 | LazySeq::empty() | |
1008 | } else { | |
1009 | self.lazy_seq(implementations.iter().map(|&def_id| { | |
1010 | assert!(def_id.is_local()); | |
1011 | def_id.index | |
1012 | })) | |
1a4d82fc JJ |
1013 | } |
1014 | } | |
223e47cc | 1015 | |
9e0c209e | 1016 | fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> { |
7cac9316 | 1017 | debug!("IsolatedEncoder::encode_stability({:?})", def_id); |
9e0c209e SL |
1018 | self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) |
1019 | } | |
1a4d82fc | 1020 | |
9e0c209e | 1021 | fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> { |
7cac9316 | 1022 | debug!("IsolatedEncoder::encode_deprecation({:?})", def_id); |
9e0c209e SL |
1023 | self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) |
1024 | } | |
9cc50fc6 | 1025 | |
83c7162d | 1026 | fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> { |
0731742a XL |
1027 | let body = self.tcx.hir().body(body_id); |
1028 | let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_expr(&body.value)); | |
83c7162d XL |
1029 | let rendered_const = &RenderedConst(rendered); |
1030 | self.lazy(rendered_const) | |
1031 | } | |
1032 | ||
476ff2be | 1033 | fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { |
9e0c209e SL |
1034 | let tcx = self.tcx; |
1035 | ||
7cac9316 | 1036 | debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id); |
9e0c209e SL |
1037 | |
1038 | let kind = match item.node { | |
8faf50e0 XL |
1039 | hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, |
1040 | hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, | |
1041 | hir::ItemKind::Const(_, body_id) => { | |
83c7162d XL |
1042 | let mir = tcx.at(item.span).mir_const_qualif(def_id).0; |
1043 | EntryKind::Const( | |
1044 | self.const_qualif(mir, body_id), | |
1045 | self.encode_rendered_const_for_body(body_id) | |
1046 | ) | |
8bb4bdeb | 1047 | } |
8faf50e0 | 1048 | hir::ItemKind::Fn(_, header, .., body) => { |
9e0c209e | 1049 | let data = FnData { |
8faf50e0 | 1050 | constness: header.constness, |
32a655c1 | 1051 | arg_names: self.encode_fn_arg_names_for_body(body), |
041b39d2 | 1052 | sig: self.lazy(&tcx.fn_sig(def_id)), |
9e0c209e | 1053 | }; |
54a0048b | 1054 | |
9e0c209e | 1055 | EntryKind::Fn(self.lazy(&data)) |
b039eaaf | 1056 | } |
8faf50e0 | 1057 | hir::ItemKind::Mod(ref m) => { |
9e0c209e SL |
1058 | return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis))); |
1059 | } | |
8faf50e0 XL |
1060 | hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, |
1061 | hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, | |
1062 | hir::ItemKind::Ty(..) => EntryKind::Type, | |
1063 | hir::ItemKind::Existential(..) => EntryKind::Existential, | |
1064 | hir::ItemKind::Enum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)), | |
1065 | hir::ItemKind::Struct(ref struct_def, _) => { | |
2c00a5a8 | 1066 | let variant = tcx.adt_def(def_id).non_enum_variant(); |
9e0c209e | 1067 | |
c30ab7b3 SL |
1068 | // Encode def_ids for each field and method |
1069 | // for methods, write all the stuff get_trait_method | |
1070 | // needs to know | |
9e0c209e | 1071 | let struct_ctor = if !struct_def.is_struct() { |
0731742a | 1072 | Some(tcx.hir().local_def_id(struct_def.id()).index) |
9e0c209e SL |
1073 | } else { |
1074 | None | |
1075 | }; | |
8bb4bdeb XL |
1076 | |
1077 | let repr_options = get_repr_options(&tcx, def_id); | |
1078 | ||
9e0c209e | 1079 | EntryKind::Struct(self.lazy(&VariantData { |
c30ab7b3 | 1080 | ctor_kind: variant.ctor_kind, |
8bb4bdeb | 1081 | discr: variant.discr, |
3b2f2976 | 1082 | struct_ctor, |
041b39d2 | 1083 | ctor_sig: None, |
8bb4bdeb | 1084 | }), repr_options) |
9e0c209e | 1085 | } |
8faf50e0 | 1086 | hir::ItemKind::Union(..) => { |
2c00a5a8 | 1087 | let variant = tcx.adt_def(def_id).non_enum_variant(); |
8bb4bdeb | 1088 | let repr_options = get_repr_options(&tcx, def_id); |
9e0c209e SL |
1089 | |
1090 | EntryKind::Union(self.lazy(&VariantData { | |
c30ab7b3 | 1091 | ctor_kind: variant.ctor_kind, |
8bb4bdeb | 1092 | discr: variant.discr, |
c30ab7b3 | 1093 | struct_ctor: None, |
041b39d2 | 1094 | ctor_sig: None, |
8bb4bdeb | 1095 | }), repr_options) |
9e0c209e | 1096 | } |
8faf50e0 | 1097 | hir::ItemKind::Impl(_, polarity, defaultness, ..) => { |
9e0c209e SL |
1098 | let trait_ref = tcx.impl_trait_ref(def_id); |
1099 | let parent = if let Some(trait_ref) = trait_ref { | |
7cac9316 | 1100 | let trait_def = tcx.trait_def(trait_ref.def_id); |
b7449926 | 1101 | trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { |
9e0c209e SL |
1102 | match node { |
1103 | specialization_graph::Node::Impl(parent) => Some(parent), | |
1104 | _ => None, | |
1105 | } | |
1106 | }) | |
1107 | } else { | |
1108 | None | |
1109 | }; | |
b039eaaf | 1110 | |
cc61c64b XL |
1111 | // if this is an impl of `CoerceUnsized`, create its |
1112 | // "unsized info", else just store None | |
1113 | let coerce_unsized_info = | |
1114 | trait_ref.and_then(|t| { | |
ea8adc8c | 1115 | if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() { |
7cac9316 | 1116 | Some(tcx.at(item.span).coerce_unsized_info(def_id)) |
cc61c64b XL |
1117 | } else { |
1118 | None | |
1119 | } | |
1120 | }); | |
1121 | ||
9e0c209e | 1122 | let data = ImplData { |
3b2f2976 XL |
1123 | polarity, |
1124 | defaultness, | |
9e0c209e | 1125 | parent_impl: parent, |
3b2f2976 | 1126 | coerce_unsized_info, |
c30ab7b3 | 1127 | trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)), |
9e0c209e | 1128 | }; |
1a4d82fc | 1129 | |
9e0c209e SL |
1130 | EntryKind::Impl(self.lazy(&data)) |
1131 | } | |
9fa01778 | 1132 | hir::ItemKind::Trait(..) => { |
7cac9316 | 1133 | let trait_def = tcx.trait_def(def_id); |
9e0c209e SL |
1134 | let data = TraitData { |
1135 | unsafety: trait_def.unsafety, | |
1136 | paren_sugar: trait_def.paren_sugar, | |
abe05a73 | 1137 | has_auto_impl: tcx.trait_is_auto(def_id), |
0bf4aa26 | 1138 | is_marker: trait_def.is_marker, |
7cac9316 | 1139 | super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), |
9e0c209e | 1140 | }; |
b039eaaf | 1141 | |
9e0c209e | 1142 | EntryKind::Trait(self.lazy(&data)) |
d9579d0f | 1143 | } |
9fa01778 XL |
1144 | hir::ItemKind::TraitAlias(..) => { |
1145 | let data = TraitAliasData { | |
1146 | super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), | |
1147 | }; | |
1148 | ||
1149 | EntryKind::TraitAlias(self.lazy(&data)) | |
1150 | } | |
8faf50e0 | 1151 | hir::ItemKind::ExternCrate(_) | |
8faf50e0 | 1152 | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), |
9e0c209e | 1153 | }; |
d9579d0f | 1154 | |
9e0c209e | 1155 | Entry { |
3b2f2976 | 1156 | kind, |
32a655c1 | 1157 | visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)), |
476ff2be | 1158 | span: self.lazy(&item.span), |
9e0c209e SL |
1159 | attributes: self.encode_attributes(&item.attrs), |
1160 | children: match item.node { | |
8faf50e0 | 1161 | hir::ItemKind::ForeignMod(ref fm) => { |
c30ab7b3 SL |
1162 | self.lazy_seq(fm.items |
1163 | .iter() | |
0731742a | 1164 | .map(|foreign_item| tcx.hir().local_def_id(foreign_item.id).index)) |
d9579d0f | 1165 | } |
8faf50e0 | 1166 | hir::ItemKind::Enum(..) => { |
7cac9316 | 1167 | let def = self.tcx.adt_def(def_id); |
9e0c209e SL |
1168 | self.lazy_seq(def.variants.iter().map(|v| { |
1169 | assert!(v.did.is_local()); | |
1170 | v.did.index | |
1171 | })) | |
1a4d82fc | 1172 | } |
8faf50e0 XL |
1173 | hir::ItemKind::Struct(..) | |
1174 | hir::ItemKind::Union(..) => { | |
7cac9316 | 1175 | let def = self.tcx.adt_def(def_id); |
2c00a5a8 | 1176 | self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| { |
9e0c209e SL |
1177 | assert!(f.did.is_local()); |
1178 | f.did.index | |
1179 | })) | |
1a4d82fc | 1180 | } |
8faf50e0 XL |
1181 | hir::ItemKind::Impl(..) | |
1182 | hir::ItemKind::Trait(..) => { | |
476ff2be | 1183 | self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { |
9e0c209e SL |
1184 | assert!(def_id.is_local()); |
1185 | def_id.index | |
1186 | })) | |
d9579d0f | 1187 | } |
c30ab7b3 | 1188 | _ => LazySeq::empty(), |
9e0c209e SL |
1189 | }, |
1190 | stability: self.encode_stability(def_id), | |
1191 | deprecation: self.encode_deprecation(def_id), | |
1192 | ||
1193 | ty: match item.node { | |
8faf50e0 XL |
1194 | hir::ItemKind::Static(..) | |
1195 | hir::ItemKind::Const(..) | | |
1196 | hir::ItemKind::Fn(..) | | |
1197 | hir::ItemKind::Ty(..) | | |
1198 | hir::ItemKind::Existential(..) | | |
1199 | hir::ItemKind::Enum(..) | | |
1200 | hir::ItemKind::Struct(..) | | |
1201 | hir::ItemKind::Union(..) | | |
1202 | hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), | |
c30ab7b3 | 1203 | _ => None, |
9e0c209e SL |
1204 | }, |
1205 | inherent_impls: self.encode_inherent_implementations(def_id), | |
1206 | variances: match item.node { | |
8faf50e0 XL |
1207 | hir::ItemKind::Enum(..) | |
1208 | hir::ItemKind::Struct(..) | | |
1209 | hir::ItemKind::Union(..) | | |
1210 | hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), | |
c30ab7b3 | 1211 | _ => LazySeq::empty(), |
9e0c209e SL |
1212 | }, |
1213 | generics: match item.node { | |
8faf50e0 XL |
1214 | hir::ItemKind::Static(..) | |
1215 | hir::ItemKind::Const(..) | | |
1216 | hir::ItemKind::Fn(..) | | |
1217 | hir::ItemKind::Ty(..) | | |
1218 | hir::ItemKind::Enum(..) | | |
1219 | hir::ItemKind::Struct(..) | | |
1220 | hir::ItemKind::Union(..) | | |
1221 | hir::ItemKind::Impl(..) | | |
1222 | hir::ItemKind::Existential(..) | | |
1223 | hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), | |
9fa01778 | 1224 | hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), |
c30ab7b3 | 1225 | _ => None, |
9e0c209e SL |
1226 | }, |
1227 | predicates: match item.node { | |
8faf50e0 XL |
1228 | hir::ItemKind::Static(..) | |
1229 | hir::ItemKind::Const(..) | | |
1230 | hir::ItemKind::Fn(..) | | |
1231 | hir::ItemKind::Ty(..) | | |
1232 | hir::ItemKind::Enum(..) | | |
1233 | hir::ItemKind::Struct(..) | | |
1234 | hir::ItemKind::Union(..) | | |
1235 | hir::ItemKind::Impl(..) | | |
1236 | hir::ItemKind::Existential(..) | | |
9fa01778 XL |
1237 | hir::ItemKind::Trait(..) | |
1238 | hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), | |
c30ab7b3 | 1239 | _ => None, |
9e0c209e SL |
1240 | }, |
1241 | ||
8faf50e0 XL |
1242 | // The only time that `predicates_defined_on` is used (on |
1243 | // an external item) is for traits, during chalk lowering, | |
1244 | // so only encode it in that case as an efficiency | |
1245 | // hack. (No reason not to expand it in the future if | |
1246 | // necessary.) | |
1247 | predicates_defined_on: match item.node { | |
9fa01778 XL |
1248 | hir::ItemKind::Trait(..) | |
1249 | hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)), | |
8faf50e0 XL |
1250 | _ => None, // not *wrong* for other kinds of items, but not needed |
1251 | }, | |
1252 | ||
9e0c209e | 1253 | mir: match item.node { |
8faf50e0 | 1254 | hir::ItemKind::Static(..) => { |
7cac9316 | 1255 | self.encode_optimized_mir(def_id) |
32a655c1 | 1256 | } |
8faf50e0 XL |
1257 | hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), |
1258 | hir::ItemKind::Fn(_, header, ..) => { | |
1259 | let generics = tcx.generics_of(def_id); | |
94b46f34 | 1260 | let needs_inline = |
b7449926 XL |
1261 | (generics.requires_monomorphization(tcx) || |
1262 | tcx.codegen_fn_attrs(def_id).requests_inline()) && | |
94b46f34 | 1263 | !self.metadata_output_only(); |
476ff2be | 1264 | let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; |
8faf50e0 XL |
1265 | if needs_inline |
1266 | || header.constness == hir::Constness::Const | |
1267 | || always_encode_mir | |
1268 | { | |
7cac9316 | 1269 | self.encode_optimized_mir(def_id) |
9e0c209e SL |
1270 | } else { |
1271 | None | |
1272 | } | |
1a4d82fc | 1273 | } |
c30ab7b3 SL |
1274 | _ => None, |
1275 | }, | |
223e47cc | 1276 | } |
9e0c209e | 1277 | } |
476ff2be SL |
1278 | |
1279 | /// Serialize the text of exported macros | |
1280 | fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { | |
8bb4bdeb | 1281 | use syntax::print::pprust; |
0731742a | 1282 | let def_id = self.tcx.hir().local_def_id(macro_def.id); |
476ff2be SL |
1283 | Entry { |
1284 | kind: EntryKind::MacroDef(self.lazy(&MacroDef { | |
8bb4bdeb | 1285 | body: pprust::tts_to_string(¯o_def.body.trees().collect::<Vec<_>>()), |
7cac9316 | 1286 | legacy: macro_def.legacy, |
476ff2be | 1287 | })), |
32a655c1 | 1288 | visibility: self.lazy(&ty::Visibility::Public), |
476ff2be | 1289 | span: self.lazy(¯o_def.span), |
476ff2be | 1290 | attributes: self.encode_attributes(¯o_def.attrs), |
041b39d2 XL |
1291 | stability: self.encode_stability(def_id), |
1292 | deprecation: self.encode_deprecation(def_id), | |
1293 | ||
476ff2be | 1294 | children: LazySeq::empty(), |
476ff2be SL |
1295 | ty: None, |
1296 | inherent_impls: LazySeq::empty(), | |
1297 | variances: LazySeq::empty(), | |
1298 | generics: None, | |
1299 | predicates: None, | |
8faf50e0 | 1300 | predicates_defined_on: None, |
476ff2be SL |
1301 | mir: None, |
1302 | } | |
1303 | } | |
223e47cc | 1304 | |
7cac9316 XL |
1305 | fn encode_info_for_ty_param(&mut self, |
1306 | (def_id, Untracked(has_default)): (DefId, Untracked<bool>)) | |
1307 | -> Entry<'tcx> { | |
1308 | debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id); | |
1309 | let tcx = self.tcx; | |
1310 | Entry { | |
1311 | kind: EntryKind::Type, | |
1312 | visibility: self.lazy(&ty::Visibility::Public), | |
1313 | span: self.lazy(&tcx.def_span(def_id)), | |
1314 | attributes: LazySeq::empty(), | |
1315 | children: LazySeq::empty(), | |
1316 | stability: None, | |
1317 | deprecation: None, | |
9e0c209e | 1318 | |
7cac9316 XL |
1319 | ty: if has_default { |
1320 | Some(self.encode_item_type(def_id)) | |
1321 | } else { | |
1322 | None | |
1323 | }, | |
1324 | inherent_impls: LazySeq::empty(), | |
1325 | variances: LazySeq::empty(), | |
1326 | generics: None, | |
1327 | predicates: None, | |
8faf50e0 | 1328 | predicates_defined_on: None, |
970d7e83 | 1329 | |
7cac9316 | 1330 | mir: None, |
223e47cc | 1331 | } |
223e47cc | 1332 | } |
223e47cc | 1333 | |
9fa01778 XL |
1334 | fn encode_info_for_const_param(&mut self, def_id: DefId) -> Entry<'tcx> { |
1335 | debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id); | |
1336 | let tcx = self.tcx; | |
1337 | Entry { | |
1338 | kind: EntryKind::Type, | |
1339 | visibility: self.lazy(&ty::Visibility::Public), | |
1340 | span: self.lazy(&tcx.def_span(def_id)), | |
1341 | attributes: LazySeq::empty(), | |
1342 | children: LazySeq::empty(), | |
1343 | stability: None, | |
1344 | deprecation: None, | |
1345 | ||
1346 | ty: Some(self.encode_item_type(def_id)), | |
1347 | inherent_impls: LazySeq::empty(), | |
1348 | variances: LazySeq::empty(), | |
1349 | generics: None, | |
1350 | predicates: None, | |
1351 | predicates_defined_on: None, | |
1352 | ||
1353 | mir: None, | |
1354 | } | |
1355 | } | |
1356 | ||
9e0c209e | 1357 | fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { |
7cac9316 | 1358 | debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id); |
9e0c209e | 1359 | let tcx = self.tcx; |
223e47cc | 1360 | |
ff7c6d11 | 1361 | let tables = self.tcx.typeck_tables_of(def_id); |
0731742a XL |
1362 | let node_id = self.tcx.hir().as_local_node_id(def_id).unwrap(); |
1363 | let hir_id = self.tcx.hir().node_to_hir_id(node_id); | |
9fa01778 | 1364 | let kind = match tables.node_type(hir_id).sty { |
b7449926 | 1365 | ty::Generator(def_id, ..) => { |
ff7c6d11 XL |
1366 | let layout = self.tcx.generator_layout(def_id); |
1367 | let data = GeneratorData { | |
1368 | layout: layout.clone(), | |
1369 | }; | |
1370 | EntryKind::Generator(self.lazy(&data)) | |
1371 | } | |
1372 | ||
b7449926 | 1373 | ty::Closure(def_id, substs) => { |
ff7c6d11 XL |
1374 | let sig = substs.closure_sig(def_id, self.tcx); |
1375 | let data = ClosureData { sig: self.lazy(&sig) }; | |
1376 | EntryKind::Closure(self.lazy(&data)) | |
1377 | } | |
1378 | ||
1379 | _ => bug!("closure that is neither generator nor closure") | |
9e0c209e | 1380 | }; |
223e47cc | 1381 | |
9e0c209e | 1382 | Entry { |
ea8adc8c | 1383 | kind, |
32a655c1 | 1384 | visibility: self.lazy(&ty::Visibility::Public), |
476ff2be | 1385 | span: self.lazy(&tcx.def_span(def_id)), |
9e0c209e SL |
1386 | attributes: self.encode_attributes(&tcx.get_attrs(def_id)), |
1387 | children: LazySeq::empty(), | |
1388 | stability: None, | |
1389 | deprecation: None, | |
1390 | ||
476ff2be | 1391 | ty: Some(self.encode_item_type(def_id)), |
9e0c209e SL |
1392 | inherent_impls: LazySeq::empty(), |
1393 | variances: LazySeq::empty(), | |
476ff2be | 1394 | generics: Some(self.encode_generics(def_id)), |
9e0c209e | 1395 | predicates: None, |
8faf50e0 | 1396 | predicates_defined_on: None, |
9e0c209e | 1397 | |
7cac9316 | 1398 | mir: self.encode_optimized_mir(def_id), |
223e47cc | 1399 | } |
223e47cc LB |
1400 | } |
1401 | ||
94b46f34 XL |
1402 | fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { |
1403 | debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id); | |
cc61c64b | 1404 | let tcx = self.tcx; |
0731742a XL |
1405 | let id = tcx.hir().as_local_node_id(def_id).unwrap(); |
1406 | let body_id = tcx.hir().body_owned_by(id); | |
83c7162d XL |
1407 | let const_data = self.encode_rendered_const_for_body(body_id); |
1408 | let mir = tcx.mir_const_qualif(def_id).0; | |
cc61c64b XL |
1409 | |
1410 | Entry { | |
83c7162d | 1411 | kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), |
cc61c64b XL |
1412 | visibility: self.lazy(&ty::Visibility::Public), |
1413 | span: self.lazy(&tcx.def_span(def_id)), | |
1414 | attributes: LazySeq::empty(), | |
1415 | children: LazySeq::empty(), | |
1416 | stability: None, | |
1417 | deprecation: None, | |
1418 | ||
1419 | ty: Some(self.encode_item_type(def_id)), | |
1420 | inherent_impls: LazySeq::empty(), | |
1421 | variances: LazySeq::empty(), | |
1422 | generics: Some(self.encode_generics(def_id)), | |
1423 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 1424 | predicates_defined_on: None, |
cc61c64b | 1425 | |
7cac9316 | 1426 | mir: self.encode_optimized_mir(def_id), |
cc61c64b XL |
1427 | } |
1428 | } | |
1429 | ||
1430 | fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> { | |
1431 | // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because | |
7cac9316 | 1432 | // we rely on the HashStable specialization for [Attribute] |
cc61c64b XL |
1433 | // to properly filter things out. |
1434 | self.lazy_seq_from_slice(attrs) | |
1435 | } | |
cc61c64b | 1436 | |
7cac9316 | 1437 | fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> { |
ea8adc8c XL |
1438 | let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); |
1439 | self.lazy_seq(used_libraries.iter().cloned()) | |
1a4d82fc | 1440 | } |
1a4d82fc | 1441 | |
0531ce1d XL |
1442 | fn encode_foreign_modules(&mut self, _: ()) -> LazySeq<ForeignModule> { |
1443 | let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); | |
1444 | self.lazy_seq(foreign_modules.iter().cloned()) | |
1445 | } | |
1446 | ||
7cac9316 | 1447 | fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> { |
ea8adc8c | 1448 | let crates = self.tcx.crates(); |
9e0c209e | 1449 | |
7cac9316 XL |
1450 | let mut deps = crates |
1451 | .iter() | |
1452 | .map(|&cnum| { | |
1453 | let dep = CrateDep { | |
ea8adc8c XL |
1454 | name: self.tcx.original_crate_name(cnum), |
1455 | hash: self.tcx.crate_hash(cnum), | |
1456 | kind: self.tcx.dep_kind(cnum), | |
83c7162d | 1457 | extra_filename: self.tcx.extra_filename(cnum), |
7cac9316 XL |
1458 | }; |
1459 | (cnum, dep) | |
1460 | }) | |
1461 | .collect::<Vec<_>>(); | |
1462 | ||
1463 | deps.sort_by_key(|&(cnum, _)| cnum); | |
9e0c209e | 1464 | |
7cac9316 | 1465 | { |
9e0c209e SL |
1466 | // Sanity-check the crate numbers |
1467 | let mut expected_cnum = 1; | |
1468 | for &(n, _) in &deps { | |
1469 | assert_eq!(n, CrateNum::new(expected_cnum)); | |
1470 | expected_cnum += 1; | |
1a4d82fc JJ |
1471 | } |
1472 | } | |
1a4d82fc | 1473 | |
9e0c209e SL |
1474 | // We're just going to write a list of crate 'name-hash-version's, with |
1475 | // the assumption that they are numbered 1 to n. | |
1476 | // FIXME (#2166): This is not nearly enough to support correct versioning | |
1477 | // but is enough to get transitive crate dependencies working. | |
7cac9316 | 1478 | self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) |
223e47cc | 1479 | } |
1a4d82fc | 1480 | |
b7449926 XL |
1481 | fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option<ast::Name>)> { |
1482 | let tcx = self.tcx; | |
1483 | let lib_features = tcx.lib_features(); | |
1484 | self.lazy_seq(lib_features.to_vec()) | |
1485 | } | |
1486 | ||
7cac9316 | 1487 | fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> { |
9e0c209e | 1488 | let tcx = self.tcx; |
ea8adc8c XL |
1489 | let lang_items = tcx.lang_items(); |
1490 | let lang_items = lang_items.items().iter(); | |
7cac9316 | 1491 | self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { |
9e0c209e SL |
1492 | if let Some(def_id) = opt_def_id { |
1493 | if def_id.is_local() { | |
1494 | return Some((def_id.index, i)); | |
1495 | } | |
1a4d82fc | 1496 | } |
9e0c209e | 1497 | None |
7cac9316 | 1498 | })) |
1a4d82fc | 1499 | } |
476ff2be | 1500 | |
7cac9316 XL |
1501 | fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> { |
1502 | let tcx = self.tcx; | |
ea8adc8c | 1503 | self.lazy_seq_ref(&tcx.lang_items().missing) |
476ff2be | 1504 | } |
1a4d82fc | 1505 | |
9e0c209e | 1506 | /// Encodes an index, mapping each trait to its (local) implementations. |
7cac9316 XL |
1507 | fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> { |
1508 | debug!("IsolatedEncoder::encode_impls()"); | |
1509 | let tcx = self.tcx; | |
9e0c209e | 1510 | let mut visitor = ImplVisitor { |
3b2f2976 | 1511 | tcx, |
0bf4aa26 | 1512 | impls: FxHashMap::default(), |
9e0c209e | 1513 | }; |
0731742a | 1514 | tcx.hir().krate().visit_all_item_likes(&mut visitor); |
1a4d82fc | 1515 | |
7cac9316 XL |
1516 | let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); |
1517 | ||
1518 | // Bring everything into deterministic order for hashing | |
83c7162d | 1519 | all_impls.sort_by_cached_key(|&(trait_def_id, _)| { |
7cac9316 XL |
1520 | tcx.def_path_hash(trait_def_id) |
1521 | }); | |
1522 | ||
1523 | let all_impls: Vec<_> = all_impls | |
c30ab7b3 | 1524 | .into_iter() |
7cac9316 XL |
1525 | .map(|(trait_def_id, mut impls)| { |
1526 | // Bring everything into deterministic order for hashing | |
83c7162d | 1527 | impls.sort_by_cached_key(|&def_index| { |
0731742a | 1528 | tcx.hir().definitions().def_path_hash(def_index) |
7cac9316 XL |
1529 | }); |
1530 | ||
c30ab7b3 SL |
1531 | TraitImpls { |
1532 | trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), | |
7cac9316 | 1533 | impls: self.lazy_seq_from_slice(&impls[..]), |
c30ab7b3 SL |
1534 | } |
1535 | }) | |
1536 | .collect(); | |
1a4d82fc | 1537 | |
7cac9316 | 1538 | self.lazy_seq_from_slice(&all_impls[..]) |
1a4d82fc | 1539 | } |
970d7e83 | 1540 | |
476ff2be | 1541 | // Encodes all symbols exported from this crate into the metadata. |
9e0c209e SL |
1542 | // |
1543 | // This pass is seeded off the reachability list calculated in the | |
1544 | // middle::reachable module but filters out items that either don't have a | |
1545 | // symbol associated with them (they weren't translated) or if they're an FFI | |
1546 | // definition (as that's not defined in this crate). | |
0531ce1d | 1547 | fn encode_exported_symbols(&mut self, |
9fa01778 | 1548 | exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)]) |
83c7162d | 1549 | -> EncodedExportedSymbols { |
0531ce1d XL |
1550 | // The metadata symbol name is special. It should not show up in |
1551 | // downstream crates. | |
1552 | let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); | |
1553 | ||
83c7162d | 1554 | let lazy_seq = self.lazy_seq(exported_symbols |
0531ce1d XL |
1555 | .iter() |
1556 | .filter(|&&(ref exported_symbol, _)| { | |
1557 | match *exported_symbol { | |
1558 | ExportedSymbol::NoDefId(symbol_name) => { | |
1559 | symbol_name != metadata_symbol_name | |
1560 | }, | |
1561 | _ => true, | |
1562 | } | |
1563 | }) | |
83c7162d XL |
1564 | .cloned()); |
1565 | ||
1566 | EncodedExportedSymbols { | |
1567 | len: lazy_seq.len, | |
1568 | position: lazy_seq.position, | |
1569 | } | |
0531ce1d XL |
1570 | } |
1571 | ||
7cac9316 | 1572 | fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> { |
b7449926 | 1573 | match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { |
9e0c209e SL |
1574 | Some(arr) => { |
1575 | self.lazy_seq(arr.iter().map(|slot| { | |
1576 | match *slot { | |
1577 | Linkage::NotLinked | | |
1578 | Linkage::IncludedFromDylib => None, | |
1579 | ||
1580 | Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), | |
1581 | Linkage::Static => Some(LinkagePreference::RequireStatic), | |
1582 | } | |
1583 | })) | |
1584 | } | |
c30ab7b3 | 1585 | None => LazySeq::empty(), |
a7813a04 XL |
1586 | } |
1587 | } | |
1a4d82fc | 1588 | |
7cac9316 XL |
1589 | fn encode_info_for_foreign_item(&mut self, |
1590 | (def_id, nitem): (DefId, &hir::ForeignItem)) | |
1591 | -> Entry<'tcx> { | |
1592 | let tcx = self.tcx; | |
9e0c209e | 1593 | |
7cac9316 | 1594 | debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id); |
9e0c209e | 1595 | |
7cac9316 | 1596 | let kind = match nitem.node { |
8faf50e0 | 1597 | hir::ForeignItemKind::Fn(_, ref names, _) => { |
7cac9316 XL |
1598 | let data = FnData { |
1599 | constness: hir::Constness::NotConst, | |
1600 | arg_names: self.encode_fn_arg_names(names), | |
041b39d2 | 1601 | sig: self.lazy(&tcx.fn_sig(def_id)), |
7cac9316 XL |
1602 | }; |
1603 | EntryKind::ForeignFn(self.lazy(&data)) | |
1604 | } | |
8faf50e0 XL |
1605 | hir::ForeignItemKind::Static(_, true) => EntryKind::ForeignMutStatic, |
1606 | hir::ForeignItemKind::Static(_, false) => EntryKind::ForeignImmStatic, | |
1607 | hir::ForeignItemKind::Type => EntryKind::ForeignType, | |
7cac9316 | 1608 | }; |
9e0c209e | 1609 | |
7cac9316 | 1610 | Entry { |
3b2f2976 | 1611 | kind, |
7cac9316 XL |
1612 | visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)), |
1613 | span: self.lazy(&nitem.span), | |
1614 | attributes: self.encode_attributes(&nitem.attrs), | |
1615 | children: LazySeq::empty(), | |
1616 | stability: self.encode_stability(def_id), | |
1617 | deprecation: self.encode_deprecation(def_id), | |
9e0c209e | 1618 | |
7cac9316 XL |
1619 | ty: Some(self.encode_item_type(def_id)), |
1620 | inherent_impls: LazySeq::empty(), | |
041b39d2 | 1621 | variances: match nitem.node { |
8faf50e0 | 1622 | hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), |
041b39d2 XL |
1623 | _ => LazySeq::empty(), |
1624 | }, | |
7cac9316 XL |
1625 | generics: Some(self.encode_generics(def_id)), |
1626 | predicates: Some(self.encode_predicates(def_id)), | |
8faf50e0 | 1627 | predicates_defined_on: None, |
32a655c1 | 1628 | |
7cac9316 XL |
1629 | mir: None, |
1630 | } | |
1631 | } | |
1632 | } | |
9e0c209e | 1633 | |
7cac9316 XL |
1634 | struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { |
1635 | index: IndexBuilder<'a, 'b, 'tcx>, | |
1636 | } | |
9e0c209e | 1637 | |
7cac9316 XL |
1638 | impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { |
1639 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { | |
0731742a | 1640 | NestedVisitorMap::OnlyBodies(&self.index.tcx.hir()) |
7cac9316 XL |
1641 | } |
1642 | fn visit_expr(&mut self, ex: &'tcx hir::Expr) { | |
1643 | intravisit::walk_expr(self, ex); | |
1644 | self.index.encode_info_for_expr(ex); | |
1645 | } | |
1646 | fn visit_item(&mut self, item: &'tcx hir::Item) { | |
1647 | intravisit::walk_item(self, item); | |
0731742a | 1648 | let def_id = self.index.tcx.hir().local_def_id(item.id); |
7cac9316 | 1649 | match item.node { |
8faf50e0 XL |
1650 | hir::ItemKind::ExternCrate(_) | |
1651 | hir::ItemKind::Use(..) => (), // ignore these | |
7cac9316 XL |
1652 | _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)), |
1653 | } | |
1654 | self.index.encode_addl_info_for_item(item); | |
1655 | } | |
1656 | fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { | |
1657 | intravisit::walk_foreign_item(self, ni); | |
0731742a | 1658 | let def_id = self.index.tcx.hir().local_def_id(ni.id); |
7cac9316 XL |
1659 | self.index.record(def_id, |
1660 | IsolatedEncoder::encode_info_for_foreign_item, | |
1661 | (def_id, ni)); | |
1662 | } | |
1663 | fn visit_variant(&mut self, | |
1664 | v: &'tcx hir::Variant, | |
1665 | g: &'tcx hir::Generics, | |
9fa01778 | 1666 | id: hir::HirId) { |
7cac9316 | 1667 | intravisit::walk_variant(self, v, g, id); |
9e0c209e | 1668 | |
94b46f34 | 1669 | if let Some(ref discr) = v.node.disr_expr { |
0731742a | 1670 | let def_id = self.index.tcx.hir().local_def_id(discr.id); |
94b46f34 | 1671 | self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); |
7cac9316 XL |
1672 | } |
1673 | } | |
1674 | fn visit_generics(&mut self, generics: &'tcx hir::Generics) { | |
1675 | intravisit::walk_generics(self, generics); | |
1676 | self.index.encode_info_for_generics(generics); | |
1677 | } | |
1678 | fn visit_ty(&mut self, ty: &'tcx hir::Ty) { | |
1679 | intravisit::walk_ty(self, ty); | |
1680 | self.index.encode_info_for_ty(ty); | |
1681 | } | |
1682 | fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { | |
0731742a | 1683 | let def_id = self.index.tcx.hir().local_def_id(macro_def.id); |
7cac9316 XL |
1684 | self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def); |
1685 | } | |
1686 | } | |
9e0c209e | 1687 | |
7cac9316 XL |
1688 | impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { |
1689 | fn encode_fields(&mut self, adt_def_id: DefId) { | |
1690 | let def = self.tcx.adt_def(adt_def_id); | |
a1dfa0c6 | 1691 | for (variant_index, variant) in def.variants.iter_enumerated() { |
7cac9316 XL |
1692 | for (field_index, field) in variant.fields.iter().enumerate() { |
1693 | self.record(field.did, | |
1694 | IsolatedEncoder::encode_field, | |
1695 | (adt_def_id, Untracked((variant_index, field_index)))); | |
1696 | } | |
1697 | } | |
1698 | } | |
9e0c209e | 1699 | |
7cac9316 | 1700 | fn encode_info_for_generics(&mut self, generics: &hir::Generics) { |
b7449926 XL |
1701 | for param in &generics.params { |
1702 | match param.kind { | |
1703 | hir::GenericParamKind::Lifetime { .. } => {} | |
1704 | hir::GenericParamKind::Type { ref default, .. } => { | |
0731742a | 1705 | let def_id = self.tcx.hir().local_def_id(param.id); |
b7449926 XL |
1706 | let has_default = Untracked(default.is_some()); |
1707 | let encode_info = IsolatedEncoder::encode_info_for_ty_param; | |
1708 | self.record(def_id, encode_info, (def_id, has_default)); | |
1709 | } | |
9fa01778 XL |
1710 | hir::GenericParamKind::Const { .. } => { |
1711 | let def_id = self.tcx.hir().local_def_id(param.id); | |
1712 | let encode_info = IsolatedEncoder::encode_info_for_const_param; | |
1713 | self.record(def_id, encode_info, def_id); | |
1714 | } | |
8faf50e0 | 1715 | } |
b7449926 | 1716 | } |
7cac9316 | 1717 | } |
9cc50fc6 | 1718 | |
7cac9316 | 1719 | fn encode_info_for_ty(&mut self, ty: &hir::Ty) { |
ea8adc8c | 1720 | match ty.node { |
8faf50e0 | 1721 | hir::TyKind::Array(_, ref length) => { |
0731742a | 1722 | let def_id = self.tcx.hir().local_def_id(length.id); |
94b46f34 | 1723 | self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); |
ea8adc8c XL |
1724 | } |
1725 | _ => {} | |
7cac9316 XL |
1726 | } |
1727 | } | |
c34b1796 | 1728 | |
7cac9316 XL |
1729 | fn encode_info_for_expr(&mut self, expr: &hir::Expr) { |
1730 | match expr.node { | |
8faf50e0 | 1731 | hir::ExprKind::Closure(..) => { |
0731742a | 1732 | let def_id = self.tcx.hir().local_def_id(expr.id); |
7cac9316 XL |
1733 | self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id); |
1734 | } | |
1735 | _ => {} | |
1736 | } | |
1737 | } | |
1738 | ||
1739 | /// In some cases, along with the item itself, we also | |
1740 | /// encode some sub-items. Usually we want some info from the item | |
1741 | /// so it's easier to do that here then to wait until we would encounter | |
1742 | /// normally in the visitor walk. | |
1743 | fn encode_addl_info_for_item(&mut self, item: &hir::Item) { | |
0731742a | 1744 | let def_id = self.tcx.hir().local_def_id(item.id); |
7cac9316 | 1745 | match item.node { |
8faf50e0 XL |
1746 | hir::ItemKind::Static(..) | |
1747 | hir::ItemKind::Const(..) | | |
1748 | hir::ItemKind::Fn(..) | | |
1749 | hir::ItemKind::Mod(..) | | |
1750 | hir::ItemKind::ForeignMod(..) | | |
1751 | hir::ItemKind::GlobalAsm(..) | | |
1752 | hir::ItemKind::ExternCrate(..) | | |
1753 | hir::ItemKind::Use(..) | | |
1754 | hir::ItemKind::Ty(..) | | |
1755 | hir::ItemKind::Existential(..) | | |
1756 | hir::ItemKind::TraitAlias(..) => { | |
7cac9316 XL |
1757 | // no sub-item recording needed in these cases |
1758 | } | |
8faf50e0 | 1759 | hir::ItemKind::Enum(..) => { |
7cac9316 XL |
1760 | self.encode_fields(def_id); |
1761 | ||
1762 | let def = self.tcx.adt_def(def_id); | |
a1dfa0c6 | 1763 | for (i, variant) in def.variants.iter_enumerated() { |
7cac9316 XL |
1764 | self.record(variant.did, |
1765 | IsolatedEncoder::encode_enum_variant_info, | |
1766 | (def_id, Untracked(i))); | |
1767 | } | |
1768 | } | |
8faf50e0 | 1769 | hir::ItemKind::Struct(ref struct_def, _) => { |
7cac9316 XL |
1770 | self.encode_fields(def_id); |
1771 | ||
1772 | // If the struct has a constructor, encode it. | |
1773 | if !struct_def.is_struct() { | |
0731742a | 1774 | let ctor_def_id = self.tcx.hir().local_def_id(struct_def.id()); |
7cac9316 XL |
1775 | self.record(ctor_def_id, |
1776 | IsolatedEncoder::encode_struct_ctor, | |
1777 | (def_id, ctor_def_id)); | |
1778 | } | |
1779 | } | |
8faf50e0 | 1780 | hir::ItemKind::Union(..) => { |
7cac9316 XL |
1781 | self.encode_fields(def_id); |
1782 | } | |
8faf50e0 | 1783 | hir::ItemKind::Impl(..) => { |
7cac9316 XL |
1784 | for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { |
1785 | self.record(trait_item_def_id, | |
1786 | IsolatedEncoder::encode_info_for_impl_item, | |
1787 | trait_item_def_id); | |
1788 | } | |
1789 | } | |
8faf50e0 | 1790 | hir::ItemKind::Trait(..) => { |
7cac9316 XL |
1791 | for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { |
1792 | self.record(item_def_id, | |
1793 | IsolatedEncoder::encode_info_for_trait_item, | |
1794 | item_def_id); | |
9e0c209e | 1795 | } |
223e47cc | 1796 | } |
7cac9316 XL |
1797 | } |
1798 | } | |
1799 | } | |
9e0c209e | 1800 | |
7cac9316 XL |
1801 | struct ImplVisitor<'a, 'tcx: 'a> { |
1802 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
1803 | impls: FxHashMap<DefId, Vec<DefIndex>>, | |
1804 | } | |
1805 | ||
1806 | impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { | |
1807 | fn visit_item(&mut self, item: &hir::Item) { | |
8faf50e0 | 1808 | if let hir::ItemKind::Impl(..) = item.node { |
0731742a | 1809 | let impl_id = self.tcx.hir().local_def_id(item.id); |
7cac9316 XL |
1810 | if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { |
1811 | self.impls | |
1812 | .entry(trait_ref.def_id) | |
b7449926 | 1813 | .or_default() |
7cac9316 XL |
1814 | .push(impl_id.index); |
1815 | } | |
223e47cc | 1816 | } |
7cac9316 | 1817 | } |
223e47cc | 1818 | |
7cac9316 XL |
1819 | fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {} |
1820 | ||
1821 | fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { | |
1822 | // handled in `visit_item` above | |
223e47cc | 1823 | } |
223e47cc LB |
1824 | } |
1825 | ||
9e0c209e SL |
1826 | // NOTE(eddyb) The following comment was preserved for posterity, even |
1827 | // though it's no longer relevant as EBML (which uses nested & tagged | |
1828 | // "documents") was replaced with a scheme that can't go out of bounds. | |
1829 | // | |
1830 | // And here we run into yet another obscure archive bug: in which metadata | |
1831 | // loaded from archives may have trailing garbage bytes. Awhile back one of | |
cc61c64b | 1832 | // our tests was failing sporadically on the macOS 64-bit builders (both nopt |
9e0c209e SL |
1833 | // and opt) by having ebml generate an out-of-bounds panic when looking at |
1834 | // metadata. | |
1835 | // | |
1836 | // Upon investigation it turned out that the metadata file inside of an rlib | |
1837 | // (and ar archive) was being corrupted. Some compilations would generate a | |
1838 | // metadata file which would end in a few extra bytes, while other | |
1839 | // compilations would not have these extra bytes appended to the end. These | |
1840 | // extra bytes were interpreted by ebml as an extra tag, so they ended up | |
1841 | // being interpreted causing the out-of-bounds. | |
1842 | // | |
1843 | // The root cause of why these extra bytes were appearing was never | |
1844 | // discovered, and in the meantime the solution we're employing is to insert | |
1845 | // the length of the metadata to the start of the metadata. Later on this | |
1846 | // will allow us to slice the metadata to the precise length that we just | |
1847 | // generated regardless of trailing bytes that end up in it. | |
1848 | ||
b7449926 | 1849 | pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) |
ff7c6d11 | 1850 | -> EncodedMetadata |
cc61c64b | 1851 | { |
8faf50e0 XL |
1852 | let mut encoder = opaque::Encoder::new(vec![]); |
1853 | encoder.emit_raw_bytes(METADATA_HEADER); | |
9e0c209e | 1854 | |
7cac9316 | 1855 | // Will be filled with the root position after encoding everything. |
8faf50e0 | 1856 | encoder.emit_raw_bytes(&[0, 0, 0, 0]); |
9e0c209e | 1857 | |
8faf50e0 | 1858 | let (root, mut result) = { |
476ff2be | 1859 | let mut ecx = EncodeContext { |
8faf50e0 | 1860 | opaque: encoder, |
3b2f2976 | 1861 | tcx, |
c30ab7b3 SL |
1862 | lazy_state: LazyState::NoNode, |
1863 | type_shorthands: Default::default(), | |
1864 | predicate_shorthands: Default::default(), | |
b7449926 | 1865 | source_file_cache: tcx.sess.source_map().files()[0].clone(), |
0531ce1d XL |
1866 | interpret_allocs: Default::default(), |
1867 | interpret_allocs_inverse: Default::default(), | |
476ff2be SL |
1868 | }; |
1869 | ||
1870 | // Encode the rustc version string in a predictable location. | |
1871 | rustc_version().encode(&mut ecx).unwrap(); | |
1872 | ||
1873 | // Encode all the entries and extra information in the crate, | |
1874 | // culminating in the `CrateRoot` which points to all of it. | |
8faf50e0 XL |
1875 | let root = ecx.encode_crate_root(); |
1876 | (root, ecx.opaque.into_inner()) | |
476ff2be | 1877 | }; |
9e0c209e SL |
1878 | |
1879 | // Encode the root position. | |
1880 | let header = METADATA_HEADER.len(); | |
1881 | let pos = root.position; | |
1882 | result[header + 0] = (pos >> 24) as u8; | |
1883 | result[header + 1] = (pos >> 16) as u8; | |
c30ab7b3 SL |
1884 | result[header + 2] = (pos >> 8) as u8; |
1885 | result[header + 3] = (pos >> 0) as u8; | |
9e0c209e | 1886 | |
ff7c6d11 | 1887 | EncodedMetadata { raw_data: result } |
223e47cc | 1888 | } |
8bb4bdeb XL |
1889 | |
1890 | pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions { | |
7cac9316 | 1891 | let ty = tcx.type_of(did); |
8bb4bdeb | 1892 | match ty.sty { |
b7449926 | 1893 | ty::Adt(ref def, _) => return def.repr, |
8bb4bdeb XL |
1894 | _ => bug!("{} is not an ADT", ty), |
1895 | } | |
1896 | } |