]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/encoder.rs
rustc: Implement the #[global_allocator] attribute
[rust.git] / src / librustc_metadata / encoder.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use index::Index;
12 use index_builder::{FromId, IndexBuilder, Untracked};
13 use isolated_encoder::IsolatedEncoder;
14 use schema::*;
15
16 use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
17                             EncodedMetadata, EncodedMetadataHashes,
18                             EncodedMetadataHash};
19 use rustc::hir::def::CtorKind;
20 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
21 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
22 use rustc::ich::Fingerprint;
23 use rustc::middle::dependency_format::Linkage;
24 use rustc::middle::lang_items;
25 use rustc::mir;
26 use rustc::traits::specialization_graph;
27 use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
28
29 use rustc::session::config::{self, CrateTypeProcMacro};
30 use rustc::util::nodemap::{FxHashMap, NodeSet};
31
32 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
33
34 use std::hash::Hash;
35 use std::intrinsics;
36 use std::io::prelude::*;
37 use std::io::Cursor;
38 use std::path::Path;
39 use std::rc::Rc;
40 use std::u32;
41 use syntax::ast::{self, CRATE_NODE_ID};
42 use syntax::codemap::Spanned;
43 use syntax::attr;
44 use syntax::symbol::Symbol;
45 use syntax_pos;
46
47 use rustc::hir::{self, PatKind};
48 use rustc::hir::itemlikevisit::ItemLikeVisitor;
49 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
50 use rustc::hir::intravisit;
51
52 pub struct EncodeContext<'a, 'tcx: 'a> {
53     opaque: opaque::Encoder<'a>,
54     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
55     link_meta: &'a LinkMeta,
56     exported_symbols: &'a NodeSet,
57
58     lazy_state: LazyState,
59     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
60     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
61
62     pub metadata_hashes: EncodedMetadataHashes,
63     pub compute_ich: bool,
64 }
65
66 macro_rules! encoder_methods {
67     ($($name:ident($ty:ty);)*) => {
68         $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
69             self.opaque.$name(value)
70         })*
71     }
72 }
73
74 impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
75     type Error = <opaque::Encoder<'a> as Encoder>::Error;
76
77     fn emit_nil(&mut self) -> Result<(), Self::Error> {
78         Ok(())
79     }
80
81     encoder_methods! {
82         emit_usize(usize);
83         emit_u128(u128);
84         emit_u64(u64);
85         emit_u32(u32);
86         emit_u16(u16);
87         emit_u8(u8);
88
89         emit_isize(isize);
90         emit_i128(i128);
91         emit_i64(i64);
92         emit_i32(i32);
93         emit_i16(i16);
94         emit_i8(i8);
95
96         emit_bool(bool);
97         emit_f64(f64);
98         emit_f32(f32);
99         emit_char(char);
100         emit_str(&str);
101     }
102 }
103
104 impl<'a, 'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'a, 'tcx> {
105     fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
106         self.emit_lazy_distance(lazy.position, Lazy::<T>::min_size())
107     }
108 }
109
110 impl<'a, 'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'a, 'tcx> {
111     fn specialized_encode(&mut self, seq: &LazySeq<T>) -> Result<(), Self::Error> {
112         self.emit_usize(seq.len)?;
113         if seq.len == 0 {
114             return Ok(());
115         }
116         self.emit_lazy_distance(seq.position, LazySeq::<T>::min_size(seq.len))
117     }
118 }
119
120 impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
121     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
122         self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands)
123     }
124 }
125
126 impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext<'a, 'tcx> {
127     fn specialized_encode(&mut self,
128                           predicates: &ty::GenericPredicates<'tcx>)
129                           -> Result<(), Self::Error> {
130         predicates.parent.encode(self)?;
131         predicates.predicates.len().encode(self)?;
132         for predicate in &predicates.predicates {
133             self.encode_with_shorthand(predicate, predicate, |ecx| &mut ecx.predicate_shorthands)?
134         }
135         Ok(())
136     }
137 }
138
139 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
140
141     pub fn position(&self) -> usize {
142         self.opaque.position()
143     }
144
145     fn emit_node<F: FnOnce(&mut Self, usize) -> R, R>(&mut self, f: F) -> R {
146         assert_eq!(self.lazy_state, LazyState::NoNode);
147         let pos = self.position();
148         self.lazy_state = LazyState::NodeStart(pos);
149         let r = f(self, pos);
150         self.lazy_state = LazyState::NoNode;
151         r
152     }
153
154     fn emit_lazy_distance(&mut self,
155                           position: usize,
156                           min_size: usize)
157                           -> Result<(), <Self as Encoder>::Error> {
158         let min_end = position + min_size;
159         let distance = match self.lazy_state {
160             LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
161             LazyState::NodeStart(start) => {
162                 assert!(min_end <= start);
163                 start - min_end
164             }
165             LazyState::Previous(last_min_end) => {
166                 assert!(last_min_end <= position);
167                 position - last_min_end
168             }
169         };
170         self.lazy_state = LazyState::Previous(min_end);
171         self.emit_usize(distance)
172     }
173
174     pub fn lazy<T: Encodable>(&mut self, value: &T) -> Lazy<T> {
175         self.emit_node(|ecx, pos| {
176             value.encode(ecx).unwrap();
177
178             assert!(pos + Lazy::<T>::min_size() <= ecx.position());
179             Lazy::with_position(pos)
180         })
181     }
182
183     pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
184         where I: IntoIterator<Item = T>,
185               T: Encodable
186     {
187         self.emit_node(|ecx, pos| {
188             let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count();
189
190             assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position());
191             LazySeq::with_position_and_length(pos, len)
192         })
193     }
194
195     pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
196         where I: IntoIterator<Item = &'b T>,
197               T: 'b + Encodable
198     {
199         self.emit_node(|ecx, pos| {
200             let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count();
201
202             assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position());
203             LazySeq::with_position_and_length(pos, len)
204         })
205     }
206
207     /// Encode the given value or a previously cached shorthand.
208     fn encode_with_shorthand<T, U, M>(&mut self,
209                                       value: &T,
210                                       variant: &U,
211                                       map: M)
212                                       -> Result<(), <Self as Encoder>::Error>
213         where M: for<'b> Fn(&'b mut Self) -> &'b mut FxHashMap<T, usize>,
214               T: Clone + Eq + Hash,
215               U: Encodable
216     {
217         let existing_shorthand = map(self).get(value).cloned();
218         if let Some(shorthand) = existing_shorthand {
219             return self.emit_usize(shorthand);
220         }
221
222         let start = self.position();
223         variant.encode(self)?;
224         let len = self.position() - start;
225
226         // The shorthand encoding uses the same usize as the
227         // discriminant, with an offset so they can't conflict.
228         let discriminant = unsafe { intrinsics::discriminant_value(variant) };
229         assert!(discriminant < SHORTHAND_OFFSET as u64);
230         let shorthand = start + SHORTHAND_OFFSET;
231
232         // Get the number of bits that leb128 could fit
233         // in the same space as the fully encoded type.
234         let leb128_bits = len * 7;
235
236         // Check that the shorthand is a not longer than the
237         // full encoding itself, i.e. it's an obvious win.
238         if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
239             map(self).insert(value.clone(), shorthand);
240         }
241
242         Ok(())
243     }
244
245     // Encodes something that corresponds to a single DepNode::GlobalMetaData
246     // and registers the Fingerprint in the `metadata_hashes` map.
247     pub fn tracked<'x, DATA, R>(&'x mut self,
248                                 def_index: DefIndex,
249                                 op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R,
250                                 data: DATA)
251                                 -> Tracked<R> {
252         let mut entry_builder = IsolatedEncoder::new(self);
253         let ret = op(&mut entry_builder, data);
254         let (fingerprint, this) = entry_builder.finish();
255
256         if let Some(fingerprint) = fingerprint {
257             this.metadata_hashes.hashes.push(EncodedMetadataHash {
258                 def_index,
259                 hash: fingerprint,
260             })
261         }
262
263         Tracked::new(ret)
264     }
265
266     fn encode_info_for_items(&mut self) -> Index {
267         let krate = self.tcx.hir.krate();
268         let mut index = IndexBuilder::new(self);
269         index.record(DefId::local(CRATE_DEF_INDEX),
270                      IsolatedEncoder::encode_info_for_mod,
271                      FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
272         let mut visitor = EncodeVisitor { index: index };
273         krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
274         for macro_def in &krate.exported_macros {
275             visitor.visit_macro_def(macro_def);
276         }
277         visitor.index.into_items()
278     }
279
280     fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
281         let definitions = self.tcx.hir.definitions();
282         self.lazy(definitions.def_path_table())
283     }
284
285     fn encode_codemap(&mut self) -> LazySeq<syntax_pos::FileMap> {
286         let codemap = self.tcx.sess.codemap();
287         let all_filemaps = codemap.files();
288
289         let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone();
290
291         let adapted = all_filemaps.iter()
292             .filter(|filemap| {
293                 // No need to re-export imported filemaps, as any downstream
294                 // crate will import them from their original source.
295                 !filemap.is_imported()
296             })
297             .map(|filemap| {
298                 // When exporting FileMaps, we expand all paths to absolute
299                 // paths because any relative paths are potentially relative to
300                 // a wrong directory.
301                 // However, if a path has been modified via
302                 // `-Zremap-path-prefix` we assume the user has already set
303                 // things up the way they want and don't touch the path values
304                 // anymore.
305                 let name = Path::new(&filemap.name);
306                 if filemap.name_was_remapped ||
307                    (name.is_relative() && working_dir_was_remapped) {
308                     // This path of this FileMap has been modified by
309                     // path-remapping, so we use it verbatim (and avoid cloning
310                     // the whole map in the process).
311                     filemap.clone()
312                 } else {
313                     let mut adapted = (**filemap).clone();
314                     let abs_path = Path::new(&working_dir).join(name)
315                                                          .to_string_lossy()
316                                                          .into_owned();
317                     adapted.name = abs_path;
318                     Rc::new(adapted)
319                 }
320             })
321             .collect::<Vec<_>>();
322
323         self.lazy_seq_ref(adapted.iter().map(|rc| &**rc))
324     }
325
326     fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
327         let mut i = self.position();
328
329         let tcx = self.tcx;
330         let global_metadata_def_index = move |kind: GlobalMetaDataKind| {
331             kind.def_index(tcx.hir.definitions().def_path_table())
332         };
333
334         let crate_deps = self.tracked(
335             global_metadata_def_index(GlobalMetaDataKind::CrateDeps),
336             IsolatedEncoder::encode_crate_deps,
337             ());
338         let dylib_dependency_formats = self.tracked(
339             global_metadata_def_index(GlobalMetaDataKind::DylibDependencyFormats),
340             IsolatedEncoder::encode_dylib_dependency_formats,
341             ());
342         let dep_bytes = self.position() - i;
343
344         // Encode the language items.
345         i = self.position();
346         let lang_items = self.tracked(
347             global_metadata_def_index(GlobalMetaDataKind::LangItems),
348             IsolatedEncoder::encode_lang_items,
349             ());
350
351         let lang_items_missing = self.tracked(
352             global_metadata_def_index(GlobalMetaDataKind::LangItemsMissing),
353             IsolatedEncoder::encode_lang_items_missing,
354             ());
355         let lang_item_bytes = self.position() - i;
356
357         // Encode the native libraries used
358         i = self.position();
359         let native_libraries = self.tracked(
360             global_metadata_def_index(GlobalMetaDataKind::NativeLibraries),
361             IsolatedEncoder::encode_native_libraries,
362             ());
363         let native_lib_bytes = self.position() - i;
364
365         // Encode codemap
366         i = self.position();
367         let codemap = self.encode_codemap();
368         let codemap_bytes = self.position() - i;
369
370         // Encode DefPathTable
371         i = self.position();
372         let def_path_table = self.encode_def_path_table();
373         let def_path_table_bytes = self.position() - i;
374
375         // Encode the def IDs of impls, for coherence checking.
376         i = self.position();
377         let impls = self.tracked(
378             global_metadata_def_index(GlobalMetaDataKind::Impls),
379             IsolatedEncoder::encode_impls,
380             ());
381         let impl_bytes = self.position() - i;
382
383         // Encode exported symbols info.
384         i = self.position();
385         let exported_symbols = self.tracked(
386             global_metadata_def_index(GlobalMetaDataKind::ExportedSymbols),
387             IsolatedEncoder::encode_exported_symbols,
388             self.exported_symbols);
389         let exported_symbols_bytes = self.position() - i;
390
391         // Encode and index the items.
392         i = self.position();
393         let items = self.encode_info_for_items();
394         let item_bytes = self.position() - i;
395
396         i = self.position();
397         let index = items.write_index(&mut self.opaque.cursor);
398         let index_bytes = self.position() - i;
399
400         let tcx = self.tcx;
401         let link_meta = self.link_meta;
402         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
403         let has_default_lib_allocator =
404             attr::contains_name(tcx.hir.krate_attrs(), "default_lib_allocator");
405         let has_global_allocator = tcx.sess.has_global_allocator.get();
406         let root = self.lazy(&CrateRoot {
407             name: tcx.crate_name(LOCAL_CRATE),
408             triple: tcx.sess.opts.target_triple.clone(),
409             hash: link_meta.crate_hash,
410             disambiguator: tcx.sess.local_crate_disambiguator(),
411             panic_strategy: Tracked::new(tcx.sess.panic_strategy()),
412             has_global_allocator: Tracked::new(has_global_allocator),
413             has_default_lib_allocator: Tracked::new(has_default_lib_allocator),
414             plugin_registrar_fn: tcx.sess
415                 .plugin_registrar_fn
416                 .get()
417                 .map(|id| tcx.hir.local_def_id(id).index),
418             macro_derive_registrar: if is_proc_macro {
419                 let id = tcx.sess.derive_registrar_fn.get().unwrap();
420                 Some(tcx.hir.local_def_id(id).index)
421             } else {
422                 None
423             },
424
425             crate_deps: crate_deps,
426             dylib_dependency_formats: dylib_dependency_formats,
427             lang_items: lang_items,
428             lang_items_missing: lang_items_missing,
429             native_libraries: native_libraries,
430             codemap: codemap,
431             def_path_table: def_path_table,
432             impls: impls,
433             exported_symbols: exported_symbols,
434             index: index,
435         });
436
437         let total_bytes = self.position();
438
439         self.metadata_hashes.hashes.push(EncodedMetadataHash {
440             def_index: global_metadata_def_index(GlobalMetaDataKind::Krate),
441             hash: Fingerprint::from_smaller_hash(link_meta.crate_hash.as_u64())
442         });
443
444         if self.tcx.sess.meta_stats() {
445             let mut zero_bytes = 0;
446             for e in self.opaque.cursor.get_ref() {
447                 if *e == 0 {
448                     zero_bytes += 1;
449                 }
450             }
451
452             println!("metadata stats:");
453             println!("             dep bytes: {}", dep_bytes);
454             println!("       lang item bytes: {}", lang_item_bytes);
455             println!("          native bytes: {}", native_lib_bytes);
456             println!("         codemap bytes: {}", codemap_bytes);
457             println!("            impl bytes: {}", impl_bytes);
458             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
459             println!("  def-path table bytes: {}", def_path_table_bytes);
460             println!("            item bytes: {}", item_bytes);
461             println!("           index bytes: {}", index_bytes);
462             println!("            zero bytes: {}", zero_bytes);
463             println!("           total bytes: {}", total_bytes);
464         }
465
466         root
467     }
468 }
469
470 // These are methods for encoding various things. They are meant to be used with
471 // IndexBuilder::record() and EncodeContext::tracked(). They actually
472 // would not have to be methods of IsolatedEncoder (free standing functions
473 // taking IsolatedEncoder as first argument would be just fine) but by making
474 // them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>`
475 // clause again and again.
476 impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
477     fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
478         debug!("IsolatedEncoder::encode_variances_of({:?})", def_id);
479         let tcx = self.tcx;
480         self.lazy_seq_from_slice(&tcx.variances_of(def_id))
481     }
482
483     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
484         let tcx = self.tcx;
485         let ty = tcx.type_of(def_id);
486         debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty);
487         self.lazy(&ty)
488     }
489
490     /// Encode data for the given variant of the given ADT. The
491     /// index of the variant is untracked: this is ok because we
492     /// will have to lookup the adt-def by its id, and that gives us
493     /// the right to access any information in the adt-def (including,
494     /// e.g., the length of the various vectors).
495     fn encode_enum_variant_info(&mut self,
496                                 (enum_did, Untracked(index)): (DefId, Untracked<usize>))
497                                 -> Entry<'tcx> {
498         let tcx = self.tcx;
499         let def = tcx.adt_def(enum_did);
500         let variant = &def.variants[index];
501         let def_id = variant.did;
502         debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
503
504         let data = VariantData {
505             ctor_kind: variant.ctor_kind,
506             discr: variant.discr,
507             struct_ctor: None,
508             ctor_sig: if variant.ctor_kind == CtorKind::Fn {
509                 Some(self.lazy(&tcx.fn_sig(def_id)))
510             } else {
511                 None
512             }
513         };
514
515         let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap();
516         let enum_vis = &tcx.hir.expect_item(enum_id).vis;
517
518         Entry {
519             kind: EntryKind::Variant(self.lazy(&data)),
520             visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)),
521             span: self.lazy(&tcx.def_span(def_id)),
522             attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
523             children: self.lazy_seq(variant.fields.iter().map(|f| {
524                 assert!(f.did.is_local());
525                 f.did.index
526             })),
527             stability: self.encode_stability(def_id),
528             deprecation: self.encode_deprecation(def_id),
529
530             ty: Some(self.encode_item_type(def_id)),
531             inherent_impls: LazySeq::empty(),
532             variances: if variant.ctor_kind == CtorKind::Fn {
533                 self.encode_variances_of(def_id)
534             } else {
535                 LazySeq::empty()
536             },
537             generics: Some(self.encode_generics(def_id)),
538             predicates: Some(self.encode_predicates(def_id)),
539
540             ast: None,
541             mir: self.encode_optimized_mir(def_id),
542         }
543     }
544
545     fn encode_info_for_mod(&mut self,
546                            FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
547                                                                  &[ast::Attribute],
548                                                                  &hir::Visibility)>)
549                            -> Entry<'tcx> {
550         let tcx = self.tcx;
551         let def_id = tcx.hir.local_def_id(id);
552         debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id);
553
554         let data = ModData {
555             reexports: match tcx.export_map.get(&id) {
556                 Some(exports) if *vis == hir::Public => {
557                     self.lazy_seq_from_slice(exports.as_slice())
558                 }
559                 _ => LazySeq::empty(),
560             },
561         };
562
563         Entry {
564             kind: EntryKind::Mod(self.lazy(&data)),
565             visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)),
566             span: self.lazy(&md.inner),
567             attributes: self.encode_attributes(attrs),
568             children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
569                 tcx.hir.local_def_id(item_id.id).index
570             })),
571             stability: self.encode_stability(def_id),
572             deprecation: self.encode_deprecation(def_id),
573
574             ty: None,
575             inherent_impls: LazySeq::empty(),
576             variances: LazySeq::empty(),
577             generics: None,
578             predicates: None,
579
580             ast: None,
581             mir: None
582         }
583     }
584
585     /// Encode data for the given field of the given variant of the
586     /// given ADT. The indices of the variant/field are untracked:
587     /// this is ok because we will have to lookup the adt-def by its
588     /// id, and that gives us the right to access any information in
589     /// the adt-def (including, e.g., the length of the various
590     /// vectors).
591     fn encode_field(&mut self,
592                     (adt_def_id, Untracked((variant_index, field_index))): (DefId,
593                                                                             Untracked<(usize,
594                                                                                        usize)>))
595                     -> Entry<'tcx> {
596         let tcx = self.tcx;
597         let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
598         let field = &variant.fields[field_index];
599
600         let def_id = field.did;
601         debug!("IsolatedEncoder::encode_field({:?})", def_id);
602
603         let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap();
604         let variant_data = tcx.hir.expect_variant_data(variant_id);
605
606         Entry {
607             kind: EntryKind::Field,
608             visibility: self.lazy(&field.vis),
609             span: self.lazy(&tcx.def_span(def_id)),
610             attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
611             children: LazySeq::empty(),
612             stability: self.encode_stability(def_id),
613             deprecation: self.encode_deprecation(def_id),
614
615             ty: Some(self.encode_item_type(def_id)),
616             inherent_impls: LazySeq::empty(),
617             variances: LazySeq::empty(),
618             generics: Some(self.encode_generics(def_id)),
619             predicates: Some(self.encode_predicates(def_id)),
620
621             ast: None,
622             mir: None,
623         }
624     }
625
626     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
627         debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
628         let tcx = self.tcx;
629         let variant = tcx.adt_def(adt_def_id).struct_variant();
630
631         let data = VariantData {
632             ctor_kind: variant.ctor_kind,
633             discr: variant.discr,
634             struct_ctor: Some(def_id.index),
635             ctor_sig: if variant.ctor_kind == CtorKind::Fn {
636                 Some(self.lazy(&tcx.fn_sig(def_id)))
637             } else {
638                 None
639             }
640         };
641
642         let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap();
643         let struct_vis = &tcx.hir.expect_item(struct_id).vis;
644         let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
645         for field in &variant.fields {
646             if ctor_vis.is_at_least(field.vis, tcx) {
647                 ctor_vis = field.vis;
648             }
649         }
650
651         let repr_options = get_repr_options(&tcx, adt_def_id);
652
653         Entry {
654             kind: EntryKind::Struct(self.lazy(&data), repr_options),
655             visibility: self.lazy(&ctor_vis),
656             span: self.lazy(&tcx.def_span(def_id)),
657             attributes: LazySeq::empty(),
658             children: LazySeq::empty(),
659             stability: self.encode_stability(def_id),
660             deprecation: self.encode_deprecation(def_id),
661
662             ty: Some(self.encode_item_type(def_id)),
663             inherent_impls: LazySeq::empty(),
664             variances: if variant.ctor_kind == CtorKind::Fn {
665                 self.encode_variances_of(def_id)
666             } else {
667                 LazySeq::empty()
668             },
669             generics: Some(self.encode_generics(def_id)),
670             predicates: Some(self.encode_predicates(def_id)),
671
672             ast: None,
673             mir: self.encode_optimized_mir(def_id),
674         }
675     }
676
677     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
678         debug!("IsolatedEncoder::encode_generics({:?})", def_id);
679         let tcx = self.tcx;
680         self.lazy(tcx.generics_of(def_id))
681     }
682
683     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
684         debug!("IsolatedEncoder::encode_predicates({:?})", def_id);
685         let tcx = self.tcx;
686         self.lazy(&tcx.predicates_of(def_id))
687     }
688
689     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
690         debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
691         let tcx = self.tcx;
692
693         let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
694         let ast_item = tcx.hir.expect_trait_item(node_id);
695         let trait_item = tcx.associated_item(def_id);
696
697         let container = match trait_item.defaultness {
698             hir::Defaultness::Default { has_value: true } =>
699                 AssociatedContainer::TraitWithDefault,
700             hir::Defaultness::Default { has_value: false } =>
701                 AssociatedContainer::TraitRequired,
702             hir::Defaultness::Final =>
703                 span_bug!(ast_item.span, "traits cannot have final items"),
704         };
705
706         let kind = match trait_item.kind {
707             ty::AssociatedKind::Const => {
708                 EntryKind::AssociatedConst(container, 0)
709             }
710             ty::AssociatedKind::Method => {
711                 let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
712                     let arg_names = match *m {
713                         hir::TraitMethod::Required(ref names) => {
714                             self.encode_fn_arg_names(names)
715                         }
716                         hir::TraitMethod::Provided(body) => {
717                             self.encode_fn_arg_names_for_body(body)
718                         }
719                     };
720                     FnData {
721                         constness: hir::Constness::NotConst,
722                         arg_names: arg_names,
723                         sig: self.lazy(&tcx.fn_sig(def_id)),
724                     }
725                 } else {
726                     bug!()
727                 };
728                 EntryKind::Method(self.lazy(&MethodData {
729                     fn_data: fn_data,
730                     container: container,
731                     has_self: trait_item.method_has_self_argument,
732                 }))
733             }
734             ty::AssociatedKind::Type => EntryKind::AssociatedType(container),
735         };
736
737         Entry {
738             kind: kind,
739             visibility: self.lazy(&trait_item.vis),
740             span: self.lazy(&ast_item.span),
741             attributes: self.encode_attributes(&ast_item.attrs),
742             children: LazySeq::empty(),
743             stability: self.encode_stability(def_id),
744             deprecation: self.encode_deprecation(def_id),
745
746             ty: match trait_item.kind {
747                 ty::AssociatedKind::Const |
748                 ty::AssociatedKind::Method => {
749                     Some(self.encode_item_type(def_id))
750                 }
751                 ty::AssociatedKind::Type => {
752                     if trait_item.defaultness.has_value() {
753                         Some(self.encode_item_type(def_id))
754                     } else {
755                         None
756                     }
757                 }
758             },
759             inherent_impls: LazySeq::empty(),
760             variances: if trait_item.kind == ty::AssociatedKind::Method {
761                 self.encode_variances_of(def_id)
762             } else {
763                 LazySeq::empty()
764             },
765             generics: Some(self.encode_generics(def_id)),
766             predicates: Some(self.encode_predicates(def_id)),
767
768             ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node {
769                 Some(self.encode_body(body))
770             } else {
771                 None
772             },
773             mir: self.encode_optimized_mir(def_id),
774         }
775     }
776
777     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
778         debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
779         let tcx = self.tcx;
780
781         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
782         let ast_item = self.tcx.hir.expect_impl_item(node_id);
783         let impl_item = self.tcx.associated_item(def_id);
784
785         let container = match impl_item.defaultness {
786             hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault,
787             hir::Defaultness::Final => AssociatedContainer::ImplFinal,
788             hir::Defaultness::Default { has_value: false } =>
789                 span_bug!(ast_item.span, "impl items always have values (currently)"),
790         };
791
792         let kind = match impl_item.kind {
793             ty::AssociatedKind::Const => {
794                 EntryKind::AssociatedConst(container,
795                     self.tcx.at(ast_item.span).mir_const_qualif(def_id))
796             }
797             ty::AssociatedKind::Method => {
798                 let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
799                     FnData {
800                         constness: sig.constness,
801                         arg_names: self.encode_fn_arg_names_for_body(body),
802                         sig: self.lazy(&tcx.fn_sig(def_id)),
803                     }
804                 } else {
805                     bug!()
806                 };
807                 EntryKind::Method(self.lazy(&MethodData {
808                     fn_data: fn_data,
809                     container: container,
810                     has_self: impl_item.method_has_self_argument,
811                 }))
812             }
813             ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
814         };
815
816         let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node {
817             (Some(body), true)
818         } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
819             let generics = self.tcx.generics_of(def_id);
820             let types = generics.parent_types as usize + generics.types.len();
821             let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
822             let is_const_fn = sig.constness == hir::Constness::Const;
823             let ast = if is_const_fn { Some(body) } else { None };
824             let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
825             (ast, needs_inline || is_const_fn || always_encode_mir)
826         } else {
827             (None, false)
828         };
829
830         Entry {
831             kind: kind,
832             visibility: self.lazy(&impl_item.vis),
833             span: self.lazy(&ast_item.span),
834             attributes: self.encode_attributes(&ast_item.attrs),
835             children: LazySeq::empty(),
836             stability: self.encode_stability(def_id),
837             deprecation: self.encode_deprecation(def_id),
838
839             ty: Some(self.encode_item_type(def_id)),
840             inherent_impls: LazySeq::empty(),
841             variances: if impl_item.kind == ty::AssociatedKind::Method {
842                 self.encode_variances_of(def_id)
843             } else {
844                 LazySeq::empty()
845             },
846             generics: Some(self.encode_generics(def_id)),
847             predicates: Some(self.encode_predicates(def_id)),
848
849             ast: ast.map(|body| self.encode_body(body)),
850             mir: if mir { self.encode_optimized_mir(def_id) } else { None },
851         }
852     }
853
854     fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId)
855                                     -> LazySeq<ast::Name> {
856         let _ignore = self.tcx.dep_graph.in_ignore();
857         let body = self.tcx.hir.body(body_id);
858         self.lazy_seq(body.arguments.iter().map(|arg| {
859             match arg.pat.node {
860                 PatKind::Binding(_, _, name, _) => name.node,
861                 _ => Symbol::intern("")
862             }
863         }))
864     }
865
866     fn encode_fn_arg_names(&mut self, names: &[Spanned<ast::Name>])
867                            -> LazySeq<ast::Name> {
868         self.lazy_seq(names.iter().map(|name| name.node))
869     }
870
871     fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
872         debug!("EntryBuilder::encode_mir({:?})", def_id);
873         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
874             let mir = self.tcx.optimized_mir(def_id);
875             Some(self.lazy(&mir))
876         } else {
877             None
878         }
879     }
880
881     // Encodes the inherent implementations of a structure, enumeration, or trait.
882     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
883         debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id);
884         let implementations = self.tcx.inherent_impls(def_id);
885         if implementations.is_empty() {
886             LazySeq::empty()
887         } else {
888             self.lazy_seq(implementations.iter().map(|&def_id| {
889                 assert!(def_id.is_local());
890                 def_id.index
891             }))
892         }
893     }
894
895     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
896         debug!("IsolatedEncoder::encode_stability({:?})", def_id);
897         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
898     }
899
900     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
901         debug!("IsolatedEncoder::encode_deprecation({:?})", def_id);
902         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
903     }
904
905     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
906         let tcx = self.tcx;
907
908         debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id);
909
910         let kind = match item.node {
911             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
912             hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
913             hir::ItemConst(..) => {
914                 EntryKind::Const(tcx.at(item.span).mir_const_qualif(def_id))
915             }
916             hir::ItemFn(_, _, constness, .., body) => {
917                 let data = FnData {
918                     constness: constness,
919                     arg_names: self.encode_fn_arg_names_for_body(body),
920                     sig: self.lazy(&tcx.fn_sig(def_id)),
921                 };
922
923                 EntryKind::Fn(self.lazy(&data))
924             }
925             hir::ItemMod(ref m) => {
926                 return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
927             }
928             hir::ItemForeignMod(_) => EntryKind::ForeignMod,
929             hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
930             hir::ItemTy(..) => EntryKind::Type,
931             hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
932             hir::ItemStruct(ref struct_def, _) => {
933                 let variant = tcx.adt_def(def_id).struct_variant();
934
935                 // Encode def_ids for each field and method
936                 // for methods, write all the stuff get_trait_method
937                 // needs to know
938                 let struct_ctor = if !struct_def.is_struct() {
939                     Some(tcx.hir.local_def_id(struct_def.id()).index)
940                 } else {
941                     None
942                 };
943
944                 let repr_options = get_repr_options(&tcx, def_id);
945
946                 EntryKind::Struct(self.lazy(&VariantData {
947                     ctor_kind: variant.ctor_kind,
948                     discr: variant.discr,
949                     struct_ctor: struct_ctor,
950                     ctor_sig: None,
951                 }), repr_options)
952             }
953             hir::ItemUnion(..) => {
954                 let variant = tcx.adt_def(def_id).struct_variant();
955                 let repr_options = get_repr_options(&tcx, def_id);
956
957                 EntryKind::Union(self.lazy(&VariantData {
958                     ctor_kind: variant.ctor_kind,
959                     discr: variant.discr,
960                     struct_ctor: None,
961                     ctor_sig: None,
962                 }), repr_options)
963             }
964             hir::ItemDefaultImpl(..) => {
965                 let data = ImplData {
966                     polarity: hir::ImplPolarity::Positive,
967                     defaultness: hir::Defaultness::Final,
968                     parent_impl: None,
969                     coerce_unsized_info: None,
970                     trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
971                 };
972
973                 EntryKind::DefaultImpl(self.lazy(&data))
974             }
975             hir::ItemImpl(_, polarity, defaultness, ..) => {
976                 let trait_ref = tcx.impl_trait_ref(def_id);
977                 let parent = if let Some(trait_ref) = trait_ref {
978                     let trait_def = tcx.trait_def(trait_ref.def_id);
979                     trait_def.ancestors(tcx, def_id).skip(1).next().and_then(|node| {
980                         match node {
981                             specialization_graph::Node::Impl(parent) => Some(parent),
982                             _ => None,
983                         }
984                     })
985                 } else {
986                     None
987                 };
988
989                 // if this is an impl of `CoerceUnsized`, create its
990                 // "unsized info", else just store None
991                 let coerce_unsized_info =
992                     trait_ref.and_then(|t| {
993                         if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() {
994                             Some(tcx.at(item.span).coerce_unsized_info(def_id))
995                         } else {
996                             None
997                         }
998                     });
999
1000                 let data = ImplData {
1001                     polarity: polarity,
1002                     defaultness: defaultness,
1003                     parent_impl: parent,
1004                     coerce_unsized_info: coerce_unsized_info,
1005                     trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
1006                 };
1007
1008                 EntryKind::Impl(self.lazy(&data))
1009             }
1010             hir::ItemTrait(..) => {
1011                 let trait_def = tcx.trait_def(def_id);
1012                 let data = TraitData {
1013                     unsafety: trait_def.unsafety,
1014                     paren_sugar: trait_def.paren_sugar,
1015                     has_default_impl: tcx.trait_has_default_impl(def_id),
1016                     super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
1017                 };
1018
1019                 EntryKind::Trait(self.lazy(&data))
1020             }
1021             hir::ItemExternCrate(_) |
1022             hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item),
1023         };
1024
1025         Entry {
1026             kind: kind,
1027             visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)),
1028             span: self.lazy(&item.span),
1029             attributes: self.encode_attributes(&item.attrs),
1030             children: match item.node {
1031                 hir::ItemForeignMod(ref fm) => {
1032                     self.lazy_seq(fm.items
1033                         .iter()
1034                         .map(|foreign_item| tcx.hir.local_def_id(foreign_item.id).index))
1035                 }
1036                 hir::ItemEnum(..) => {
1037                     let def = self.tcx.adt_def(def_id);
1038                     self.lazy_seq(def.variants.iter().map(|v| {
1039                         assert!(v.did.is_local());
1040                         v.did.index
1041                     }))
1042                 }
1043                 hir::ItemStruct(..) |
1044                 hir::ItemUnion(..) => {
1045                     let def = self.tcx.adt_def(def_id);
1046                     self.lazy_seq(def.struct_variant().fields.iter().map(|f| {
1047                         assert!(f.did.is_local());
1048                         f.did.index
1049                     }))
1050                 }
1051                 hir::ItemImpl(..) |
1052                 hir::ItemTrait(..) => {
1053                     self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| {
1054                         assert!(def_id.is_local());
1055                         def_id.index
1056                     }))
1057                 }
1058                 _ => LazySeq::empty(),
1059             },
1060             stability: self.encode_stability(def_id),
1061             deprecation: self.encode_deprecation(def_id),
1062
1063             ty: match item.node {
1064                 hir::ItemStatic(..) |
1065                 hir::ItemConst(..) |
1066                 hir::ItemFn(..) |
1067                 hir::ItemTy(..) |
1068                 hir::ItemEnum(..) |
1069                 hir::ItemStruct(..) |
1070                 hir::ItemUnion(..) |
1071                 hir::ItemImpl(..) => Some(self.encode_item_type(def_id)),
1072                 _ => None,
1073             },
1074             inherent_impls: self.encode_inherent_implementations(def_id),
1075             variances: match item.node {
1076                 hir::ItemEnum(..) |
1077                 hir::ItemStruct(..) |
1078                 hir::ItemUnion(..) |
1079                 hir::ItemFn(..) => self.encode_variances_of(def_id),
1080                 _ => LazySeq::empty(),
1081             },
1082             generics: match item.node {
1083                 hir::ItemStatic(..) |
1084                 hir::ItemConst(..) |
1085                 hir::ItemFn(..) |
1086                 hir::ItemTy(..) |
1087                 hir::ItemEnum(..) |
1088                 hir::ItemStruct(..) |
1089                 hir::ItemUnion(..) |
1090                 hir::ItemImpl(..) |
1091                 hir::ItemTrait(..) => Some(self.encode_generics(def_id)),
1092                 _ => None,
1093             },
1094             predicates: match item.node {
1095                 hir::ItemStatic(..) |
1096                 hir::ItemConst(..) |
1097                 hir::ItemFn(..) |
1098                 hir::ItemTy(..) |
1099                 hir::ItemEnum(..) |
1100                 hir::ItemStruct(..) |
1101                 hir::ItemUnion(..) |
1102                 hir::ItemImpl(..) |
1103                 hir::ItemTrait(..) => Some(self.encode_predicates(def_id)),
1104                 _ => None,
1105             },
1106
1107             ast: match item.node {
1108                 hir::ItemConst(_, body) |
1109                 hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => {
1110                     Some(self.encode_body(body))
1111                 }
1112                 _ => None,
1113             },
1114             mir: match item.node {
1115                 hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => {
1116                     self.encode_optimized_mir(def_id)
1117                 }
1118                 hir::ItemConst(..) => self.encode_optimized_mir(def_id),
1119                 hir::ItemFn(_, _, constness, _, ref generics, _) => {
1120                     let tps_len = generics.ty_params.len();
1121                     let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
1122                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
1123                     if needs_inline || constness == hir::Constness::Const || always_encode_mir {
1124                         self.encode_optimized_mir(def_id)
1125                     } else {
1126                         None
1127                     }
1128                 }
1129                 _ => None,
1130             },
1131         }
1132     }
1133
1134     /// Serialize the text of exported macros
1135     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> {
1136         use syntax::print::pprust;
1137         Entry {
1138             kind: EntryKind::MacroDef(self.lazy(&MacroDef {
1139                 body: pprust::tts_to_string(&macro_def.body.trees().collect::<Vec<_>>()),
1140                 legacy: macro_def.legacy,
1141             })),
1142             visibility: self.lazy(&ty::Visibility::Public),
1143             span: self.lazy(&macro_def.span),
1144
1145             attributes: self.encode_attributes(&macro_def.attrs),
1146             children: LazySeq::empty(),
1147             stability: None,
1148             deprecation: None,
1149             ty: None,
1150             inherent_impls: LazySeq::empty(),
1151             variances: LazySeq::empty(),
1152             generics: None,
1153             predicates: None,
1154             ast: None,
1155             mir: None,
1156         }
1157     }
1158
1159     fn encode_info_for_ty_param(&mut self,
1160                                 (def_id, Untracked(has_default)): (DefId, Untracked<bool>))
1161                                 -> Entry<'tcx> {
1162         debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id);
1163         let tcx = self.tcx;
1164         Entry {
1165             kind: EntryKind::Type,
1166             visibility: self.lazy(&ty::Visibility::Public),
1167             span: self.lazy(&tcx.def_span(def_id)),
1168             attributes: LazySeq::empty(),
1169             children: LazySeq::empty(),
1170             stability: None,
1171             deprecation: None,
1172
1173             ty: if has_default {
1174                 Some(self.encode_item_type(def_id))
1175             } else {
1176                 None
1177             },
1178             inherent_impls: LazySeq::empty(),
1179             variances: LazySeq::empty(),
1180             generics: None,
1181             predicates: None,
1182
1183             ast: None,
1184             mir: None,
1185         }
1186     }
1187
1188     fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
1189         debug!("IsolatedEncoder::encode_info_for_anon_ty({:?})", def_id);
1190         let tcx = self.tcx;
1191         Entry {
1192             kind: EntryKind::Type,
1193             visibility: self.lazy(&ty::Visibility::Public),
1194             span: self.lazy(&tcx.def_span(def_id)),
1195             attributes: LazySeq::empty(),
1196             children: LazySeq::empty(),
1197             stability: None,
1198             deprecation: None,
1199
1200             ty: Some(self.encode_item_type(def_id)),
1201             inherent_impls: LazySeq::empty(),
1202             variances: LazySeq::empty(),
1203             generics: Some(self.encode_generics(def_id)),
1204             predicates: Some(self.encode_predicates(def_id)),
1205
1206             ast: None,
1207             mir: None,
1208         }
1209     }
1210
1211     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
1212         debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
1213         let tcx = self.tcx;
1214
1215         let data = ClosureData {
1216             kind: tcx.closure_kind(def_id),
1217             sig: self.lazy(&tcx.fn_sig(def_id)),
1218         };
1219
1220         Entry {
1221             kind: EntryKind::Closure(self.lazy(&data)),
1222             visibility: self.lazy(&ty::Visibility::Public),
1223             span: self.lazy(&tcx.def_span(def_id)),
1224             attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
1225             children: LazySeq::empty(),
1226             stability: None,
1227             deprecation: None,
1228
1229             ty: Some(self.encode_item_type(def_id)),
1230             inherent_impls: LazySeq::empty(),
1231             variances: LazySeq::empty(),
1232             generics: Some(self.encode_generics(def_id)),
1233             predicates: None,
1234
1235             ast: None,
1236             mir: self.encode_optimized_mir(def_id),
1237         }
1238     }
1239
1240     fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
1241         debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id);
1242         let tcx = self.tcx;
1243         let id = tcx.hir.as_local_node_id(def_id).unwrap();
1244         let body = tcx.hir.body_owned_by(id);
1245
1246         Entry {
1247             kind: EntryKind::Const(tcx.mir_const_qualif(def_id)),
1248             visibility: self.lazy(&ty::Visibility::Public),
1249             span: self.lazy(&tcx.def_span(def_id)),
1250             attributes: LazySeq::empty(),
1251             children: LazySeq::empty(),
1252             stability: None,
1253             deprecation: None,
1254
1255             ty: Some(self.encode_item_type(def_id)),
1256             inherent_impls: LazySeq::empty(),
1257             variances: LazySeq::empty(),
1258             generics: Some(self.encode_generics(def_id)),
1259             predicates: Some(self.encode_predicates(def_id)),
1260
1261             ast: Some(self.encode_body(body)),
1262             mir: self.encode_optimized_mir(def_id),
1263         }
1264     }
1265
1266     fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
1267         // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
1268         //       we rely on the HashStable specialization for [Attribute]
1269         //       to properly filter things out.
1270         self.lazy_seq_from_slice(attrs)
1271     }
1272
1273     fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> {
1274         let used_libraries = self.tcx.sess.cstore.used_libraries();
1275         self.lazy_seq(used_libraries)
1276     }
1277
1278     fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
1279         let cstore = &*self.tcx.sess.cstore;
1280         let crates = cstore.crates();
1281
1282         let mut deps = crates
1283             .iter()
1284             .map(|&cnum| {
1285                 let dep = CrateDep {
1286                     name: cstore.original_crate_name(cnum),
1287                     hash: cstore.crate_hash(cnum),
1288                     kind: cstore.dep_kind(cnum),
1289                 };
1290                 (cnum, dep)
1291             })
1292             .collect::<Vec<_>>();
1293
1294         deps.sort_by_key(|&(cnum, _)| cnum);
1295
1296         {
1297             // Sanity-check the crate numbers
1298             let mut expected_cnum = 1;
1299             for &(n, _) in &deps {
1300                 assert_eq!(n, CrateNum::new(expected_cnum));
1301                 expected_cnum += 1;
1302             }
1303         }
1304
1305         // We're just going to write a list of crate 'name-hash-version's, with
1306         // the assumption that they are numbered 1 to n.
1307         // FIXME (#2166): This is not nearly enough to support correct versioning
1308         // but is enough to get transitive crate dependencies working.
1309         self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep))
1310     }
1311
1312     fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
1313         let tcx = self.tcx;
1314         let lang_items = tcx.lang_items.items().iter();
1315         self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
1316             if let Some(def_id) = opt_def_id {
1317                 if def_id.is_local() {
1318                     return Some((def_id.index, i));
1319                 }
1320             }
1321             None
1322         }))
1323     }
1324
1325     fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> {
1326         let tcx = self.tcx;
1327         self.lazy_seq_ref(&tcx.lang_items.missing)
1328     }
1329
1330     /// Encodes an index, mapping each trait to its (local) implementations.
1331     fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
1332         debug!("IsolatedEncoder::encode_impls()");
1333         let tcx = self.tcx;
1334         let mut visitor = ImplVisitor {
1335             tcx: tcx,
1336             impls: FxHashMap(),
1337         };
1338         tcx.hir.krate().visit_all_item_likes(&mut visitor);
1339
1340         let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
1341
1342         // Bring everything into deterministic order for hashing
1343         all_impls.sort_unstable_by_key(|&(trait_def_id, _)| {
1344             tcx.def_path_hash(trait_def_id)
1345         });
1346
1347         let all_impls: Vec<_> = all_impls
1348             .into_iter()
1349             .map(|(trait_def_id, mut impls)| {
1350                 // Bring everything into deterministic order for hashing
1351                 impls.sort_unstable_by_key(|&def_index| {
1352                     tcx.hir.definitions().def_path_hash(def_index)
1353                 });
1354
1355                 TraitImpls {
1356                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
1357                     impls: self.lazy_seq_from_slice(&impls[..]),
1358                 }
1359             })
1360             .collect();
1361
1362         self.lazy_seq_from_slice(&all_impls[..])
1363     }
1364
1365     // Encodes all symbols exported from this crate into the metadata.
1366     //
1367     // This pass is seeded off the reachability list calculated in the
1368     // middle::reachable module but filters out items that either don't have a
1369     // symbol associated with them (they weren't translated) or if they're an FFI
1370     // definition (as that's not defined in this crate).
1371     fn encode_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq<DefIndex> {
1372         let tcx = self.tcx;
1373         self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index))
1374     }
1375
1376     fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
1377         match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
1378             Some(arr) => {
1379                 self.lazy_seq(arr.iter().map(|slot| {
1380                     match *slot {
1381                         Linkage::NotLinked |
1382                         Linkage::IncludedFromDylib => None,
1383
1384                         Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
1385                         Linkage::Static => Some(LinkagePreference::RequireStatic),
1386                     }
1387                 }))
1388             }
1389             None => LazySeq::empty(),
1390         }
1391     }
1392
1393     fn encode_info_for_foreign_item(&mut self,
1394                                     (def_id, nitem): (DefId, &hir::ForeignItem))
1395                                     -> Entry<'tcx> {
1396         let tcx = self.tcx;
1397
1398         debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id);
1399
1400         let kind = match nitem.node {
1401             hir::ForeignItemFn(_, ref names, _) => {
1402                 let data = FnData {
1403                     constness: hir::Constness::NotConst,
1404                     arg_names: self.encode_fn_arg_names(names),
1405                     sig: self.lazy(&tcx.fn_sig(def_id)),
1406                 };
1407                 EntryKind::ForeignFn(self.lazy(&data))
1408             }
1409             hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic,
1410             hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic,
1411         };
1412
1413         Entry {
1414             kind: kind,
1415             visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
1416             span: self.lazy(&nitem.span),
1417             attributes: self.encode_attributes(&nitem.attrs),
1418             children: LazySeq::empty(),
1419             stability: self.encode_stability(def_id),
1420             deprecation: self.encode_deprecation(def_id),
1421
1422             ty: Some(self.encode_item_type(def_id)),
1423             inherent_impls: LazySeq::empty(),
1424             variances: match nitem.node {
1425                 hir::ForeignItemFn(..) => self.encode_variances_of(def_id),
1426                 _ => LazySeq::empty(),
1427             },
1428             generics: Some(self.encode_generics(def_id)),
1429             predicates: Some(self.encode_predicates(def_id)),
1430
1431             ast: None,
1432             mir: None,
1433         }
1434     }
1435 }
1436
1437 struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
1438     index: IndexBuilder<'a, 'b, 'tcx>,
1439 }
1440
1441 impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
1442     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
1443         NestedVisitorMap::OnlyBodies(&self.index.tcx.hir)
1444     }
1445     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
1446         intravisit::walk_expr(self, ex);
1447         self.index.encode_info_for_expr(ex);
1448     }
1449     fn visit_item(&mut self, item: &'tcx hir::Item) {
1450         intravisit::walk_item(self, item);
1451         let def_id = self.index.tcx.hir.local_def_id(item.id);
1452         match item.node {
1453             hir::ItemExternCrate(_) |
1454             hir::ItemUse(..) => (), // ignore these
1455             _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)),
1456         }
1457         self.index.encode_addl_info_for_item(item);
1458     }
1459     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
1460         intravisit::walk_foreign_item(self, ni);
1461         let def_id = self.index.tcx.hir.local_def_id(ni.id);
1462         self.index.record(def_id,
1463                           IsolatedEncoder::encode_info_for_foreign_item,
1464                           (def_id, ni));
1465     }
1466     fn visit_variant(&mut self,
1467                      v: &'tcx hir::Variant,
1468                      g: &'tcx hir::Generics,
1469                      id: ast::NodeId) {
1470         intravisit::walk_variant(self, v, g, id);
1471
1472         if let Some(discr) = v.node.disr_expr {
1473             let def_id = self.index.tcx.hir.body_owner_def_id(discr);
1474             self.index.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id);
1475         }
1476     }
1477     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
1478         intravisit::walk_generics(self, generics);
1479         self.index.encode_info_for_generics(generics);
1480     }
1481     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
1482         intravisit::walk_ty(self, ty);
1483         self.index.encode_info_for_ty(ty);
1484     }
1485     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
1486         let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
1487         self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def);
1488     }
1489 }
1490
1491 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
1492     fn encode_fields(&mut self, adt_def_id: DefId) {
1493         let def = self.tcx.adt_def(adt_def_id);
1494         for (variant_index, variant) in def.variants.iter().enumerate() {
1495             for (field_index, field) in variant.fields.iter().enumerate() {
1496                 self.record(field.did,
1497                             IsolatedEncoder::encode_field,
1498                             (adt_def_id, Untracked((variant_index, field_index))));
1499             }
1500         }
1501     }
1502
1503     fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
1504         for ty_param in &generics.ty_params {
1505             let def_id = self.tcx.hir.local_def_id(ty_param.id);
1506             let has_default = Untracked(ty_param.default.is_some());
1507             self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default));
1508         }
1509     }
1510
1511     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
1512         if let hir::TyImplTrait(_) = ty.node {
1513             let def_id = self.tcx.hir.local_def_id(ty.id);
1514             self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
1515         }
1516     }
1517
1518     fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
1519         match expr.node {
1520             hir::ExprClosure(..) => {
1521                 let def_id = self.tcx.hir.local_def_id(expr.id);
1522                 self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id);
1523             }
1524             _ => {}
1525         }
1526     }
1527
1528     /// In some cases, along with the item itself, we also
1529     /// encode some sub-items. Usually we want some info from the item
1530     /// so it's easier to do that here then to wait until we would encounter
1531     /// normally in the visitor walk.
1532     fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
1533         let def_id = self.tcx.hir.local_def_id(item.id);
1534         match item.node {
1535             hir::ItemStatic(..) |
1536             hir::ItemConst(..) |
1537             hir::ItemFn(..) |
1538             hir::ItemMod(..) |
1539             hir::ItemForeignMod(..) |
1540             hir::ItemGlobalAsm(..) |
1541             hir::ItemExternCrate(..) |
1542             hir::ItemUse(..) |
1543             hir::ItemDefaultImpl(..) |
1544             hir::ItemTy(..) => {
1545                 // no sub-item recording needed in these cases
1546             }
1547             hir::ItemEnum(..) => {
1548                 self.encode_fields(def_id);
1549
1550                 let def = self.tcx.adt_def(def_id);
1551                 for (i, variant) in def.variants.iter().enumerate() {
1552                     self.record(variant.did,
1553                                 IsolatedEncoder::encode_enum_variant_info,
1554                                 (def_id, Untracked(i)));
1555                 }
1556             }
1557             hir::ItemStruct(ref struct_def, _) => {
1558                 self.encode_fields(def_id);
1559
1560                 // If the struct has a constructor, encode it.
1561                 if !struct_def.is_struct() {
1562                     let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
1563                     self.record(ctor_def_id,
1564                                 IsolatedEncoder::encode_struct_ctor,
1565                                 (def_id, ctor_def_id));
1566                 }
1567             }
1568             hir::ItemUnion(..) => {
1569                 self.encode_fields(def_id);
1570             }
1571             hir::ItemImpl(..) => {
1572                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
1573                     self.record(trait_item_def_id,
1574                                 IsolatedEncoder::encode_info_for_impl_item,
1575                                 trait_item_def_id);
1576                 }
1577             }
1578             hir::ItemTrait(..) => {
1579                 for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
1580                     self.record(item_def_id,
1581                                 IsolatedEncoder::encode_info_for_trait_item,
1582                                 item_def_id);
1583                 }
1584             }
1585         }
1586     }
1587 }
1588
1589 struct ImplVisitor<'a, 'tcx: 'a> {
1590     tcx: TyCtxt<'a, 'tcx, 'tcx>,
1591     impls: FxHashMap<DefId, Vec<DefIndex>>,
1592 }
1593
1594 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
1595     fn visit_item(&mut self, item: &hir::Item) {
1596         if let hir::ItemImpl(..) = item.node {
1597             let impl_id = self.tcx.hir.local_def_id(item.id);
1598             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
1599                 self.impls
1600                     .entry(trait_ref.def_id)
1601                     .or_insert(vec![])
1602                     .push(impl_id.index);
1603             }
1604         }
1605     }
1606
1607     fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {}
1608
1609     fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) {
1610         // handled in `visit_item` above
1611     }
1612 }
1613
1614 // NOTE(eddyb) The following comment was preserved for posterity, even
1615 // though it's no longer relevant as EBML (which uses nested & tagged
1616 // "documents") was replaced with a scheme that can't go out of bounds.
1617 //
1618 // And here we run into yet another obscure archive bug: in which metadata
1619 // loaded from archives may have trailing garbage bytes. Awhile back one of
1620 // our tests was failing sporadically on the macOS 64-bit builders (both nopt
1621 // and opt) by having ebml generate an out-of-bounds panic when looking at
1622 // metadata.
1623 //
1624 // Upon investigation it turned out that the metadata file inside of an rlib
1625 // (and ar archive) was being corrupted. Some compilations would generate a
1626 // metadata file which would end in a few extra bytes, while other
1627 // compilations would not have these extra bytes appended to the end. These
1628 // extra bytes were interpreted by ebml as an extra tag, so they ended up
1629 // being interpreted causing the out-of-bounds.
1630 //
1631 // The root cause of why these extra bytes were appearing was never
1632 // discovered, and in the meantime the solution we're employing is to insert
1633 // the length of the metadata to the start of the metadata. Later on this
1634 // will allow us to slice the metadata to the precise length that we just
1635 // generated regardless of trailing bytes that end up in it.
1636
1637 pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1638                                  link_meta: &LinkMeta,
1639                                  exported_symbols: &NodeSet)
1640                                  -> EncodedMetadata
1641 {
1642     let mut cursor = Cursor::new(vec![]);
1643     cursor.write_all(METADATA_HEADER).unwrap();
1644
1645     // Will be filled with the root position after encoding everything.
1646     cursor.write_all(&[0, 0, 0, 0]).unwrap();
1647
1648      let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph ||
1649                         tcx.sess.opts.debugging_opts.incremental_cc) &&
1650                         tcx.sess.opts.build_dep_graph();
1651
1652     let (root, metadata_hashes) = {
1653         let mut ecx = EncodeContext {
1654             opaque: opaque::Encoder::new(&mut cursor),
1655             tcx: tcx,
1656             link_meta: link_meta,
1657             exported_symbols: exported_symbols,
1658             lazy_state: LazyState::NoNode,
1659             type_shorthands: Default::default(),
1660             predicate_shorthands: Default::default(),
1661             metadata_hashes: EncodedMetadataHashes::new(),
1662             compute_ich: compute_ich,
1663         };
1664
1665         // Encode the rustc version string in a predictable location.
1666         rustc_version().encode(&mut ecx).unwrap();
1667
1668         // Encode all the entries and extra information in the crate,
1669         // culminating in the `CrateRoot` which points to all of it.
1670         let root = ecx.encode_crate_root();
1671         (root, ecx.metadata_hashes)
1672     };
1673     let mut result = cursor.into_inner();
1674
1675     // Encode the root position.
1676     let header = METADATA_HEADER.len();
1677     let pos = root.position;
1678     result[header + 0] = (pos >> 24) as u8;
1679     result[header + 1] = (pos >> 16) as u8;
1680     result[header + 2] = (pos >> 8) as u8;
1681     result[header + 3] = (pos >> 0) as u8;
1682
1683     EncodedMetadata {
1684         raw_data: result,
1685         hashes: metadata_hashes,
1686     }
1687 }
1688
1689 pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions {
1690     let ty = tcx.type_of(did);
1691     match ty.sty {
1692         ty::TyAdt(ref def, _) => return def.repr,
1693         _ => bug!("{} is not an ADT", ty),
1694     }
1695 }