encoder.rs 75.4 KB
Newer Older
1
use crate::rmeta::table::FixedSizeEncoding;
M
Mark Rousskov 已提交
2
use crate::rmeta::*;
3

4
use log::{debug, trace};
5
use rustc_ast::ast;
6
use rustc_ast::attr;
M
Mark Rousskov 已提交
7
use rustc_data_structures::fingerprint::Fingerprint;
8
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
9
use rustc_data_structures::stable_hasher::StableHasher;
10
use rustc_data_structures::sync::{join, Lrc};
11
use rustc_hir as hir;
12 13
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
14
use rustc_hir::definitions::DefPathTable;
15
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
16
use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
17
use rustc_hir::lang_items;
18
use rustc_hir::{AnonConst, GenericParamKind};
M
Mark Rousskov 已提交
19
use rustc_index::vec::Idx;
20
use rustc_middle::hir::map::Map;
21
use rustc_middle::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib};
22 23 24 25 26 27 28 29
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{
    metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
};
use rustc_middle::mir::{self, interpret};
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
30
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
31
use rustc_session::config::CrateType;
32
use rustc_span::source_map::Spanned;
33
use rustc_span::symbol::{kw, sym, Ident, Symbol};
34
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
35
use rustc_target::abi::VariantIdx;
36
use std::hash::Hash;
37
use std::num::NonZeroUsize;
38
use std::path::Path;
39

40
struct EncodeContext<'tcx> {
41
    opaque: opaque::Encoder,
42
    tcx: TyCtxt<'tcx>,
43

44
    tables: TableBuilders<'tcx>,
45

46
    lazy_state: LazyState,
47 48
    type_shorthands: FxHashMap<Ty<'tcx>, usize>,
    predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
49 50 51

    interpret_allocs: FxHashMap<interpret::AllocId, usize>,
    interpret_allocs_inverse: Vec<interpret::AllocId>,
52 53

    // This is used to speed up Span encoding.
D
Donato Sciarra 已提交
54
    source_file_cache: Lrc<SourceFile>,
55 56
}

57 58 59 60 61 62 63 64
macro_rules! encoder_methods {
    ($($name:ident($ty:ty);)*) => {
        $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
            self.opaque.$name(value)
        })*
    }
}

65
impl<'tcx> Encoder for EncodeContext<'tcx> {
66
    type Error = <opaque::Encoder as Encoder>::Error;
67

D
Dylan MacKenzie 已提交
68
    #[inline]
K
kenta7777 已提交
69
    fn emit_unit(&mut self) -> Result<(), Self::Error> {
70 71 72 73 74
        Ok(())
    }

    encoder_methods! {
        emit_usize(usize);
S
Simonas Kazlauskas 已提交
75
        emit_u128(u128);
76 77 78 79 80 81
        emit_u64(u64);
        emit_u32(u32);
        emit_u16(u16);
        emit_u8(u8);

        emit_isize(isize);
S
Simonas Kazlauskas 已提交
82
        emit_i128(i128);
83 84 85 86 87 88 89 90 91 92 93 94 95
        emit_i64(i64);
        emit_i32(i32);
        emit_i16(i16);
        emit_i8(i8);

        emit_bool(bool);
        emit_f64(f64);
        emit_f32(f32);
        emit_char(char);
        emit_str(&str);
    }
}

96
impl<'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'tcx> {
97
    fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
98
        self.emit_lazy_distance(*lazy)
99 100 101
    }
}

102
impl<'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'tcx> {
103 104 105
    fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
        self.emit_usize(lazy.meta)?;
        if lazy.meta == 0 {
106 107
            return Ok(());
        }
108
        self.emit_lazy_distance(*lazy)
109 110 111
    }
}

112
impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'tcx>
M
Mark Rousskov 已提交
113 114
where
    Option<T>: FixedSizeEncoding,
115
{
116
    fn specialized_encode(&mut self, lazy: &Lazy<Table<I, T>>) -> Result<(), Self::Error> {
117 118 119 120 121
        self.emit_usize(lazy.meta)?;
        self.emit_lazy_distance(*lazy)
    }
}

122
impl<'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'tcx> {
123 124 125 126 127 128
    #[inline]
    fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
        self.emit_u32(cnum.as_u32())
    }
}

129
impl<'tcx> SpecializedEncoder<DefId> for EncodeContext<'tcx> {
130 131
    #[inline]
    fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
M
Mark Rousskov 已提交
132
        let DefId { krate, index } = *def_id;
133 134 135 136 137 138

        krate.encode(self)?;
        index.encode(self)
    }
}

139
impl<'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'tcx> {
140 141
    #[inline]
    fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
142
        self.emit_u32(def_index.as_u32())
143 144 145
    }
}

146
impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
147
    fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
V
Vadim Petrochenkov 已提交
148
        if span.is_dummy() {
M
Mark Rousskov 已提交
149
            return TAG_INVALID_SPAN.encode(self);
150 151 152 153
        }

        let span = span.data();

154 155
        // The Span infrastructure should make sure that this invariant holds:
        debug_assert!(span.lo <= span.hi);
156

D
Donato Sciarra 已提交
157
        if !self.source_file_cache.contains(span.lo) {
D
Donato Sciarra 已提交
158 159 160
            let source_map = self.tcx.sess.source_map();
            let source_file_index = source_map.lookup_source_file_idx(span.lo);
            self.source_file_cache = source_map.files()[source_file_index].clone();
161 162
        }

D
Donato Sciarra 已提交
163
        if !self.source_file_cache.contains(span.hi) {
164 165
            // Unfortunately, macro expansion still sometimes generates Spans
            // that malformed in this way.
M
Mark Rousskov 已提交
166
            return TAG_INVALID_SPAN.encode(self);
167 168
        }

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
        // There are two possible cases here:
        // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
        // crate we are writing metadata for. When the metadata for *this* crate gets
        // deserialized, the deserializer will need to know which crate it originally came
        // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should
        // be deserialized after the rest of the span data, which tells the deserializer
        // which crate contains the source map information.
        // 2. This span comes from our own crate. No special hamdling is needed - we just
        // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use
        // our own source map information.
        let (tag, lo, hi) = if self.source_file_cache.is_imported() {
            // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
            // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
            // are relative to the source map information for the 'foreign' crate whose CrateNum
            // we write into the metadata. This allows `imported_source_files` to binary
            // search through the 'foreign' crate's source map information, using the
            // deserialized 'lo' and 'hi' values directly.
            //
            // All of this logic ensures that the final result of deserialization is a 'normal'
            // Span that can be used without any additional trouble.
            let external_start_pos = {
                // Introduce a new scope so that we drop the 'lock()' temporary
                match &*self.source_file_cache.external_src.lock() {
                    ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
                    src => panic!("Unexpected external source {:?}", src),
                }
            };
            let lo = (span.lo - self.source_file_cache.start_pos) + external_start_pos;
            let hi = (span.hi - self.source_file_cache.start_pos) + external_start_pos;

            (TAG_VALID_SPAN_FOREIGN, lo, hi)
        } else {
            (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
        };

        tag.encode(self)?;
        lo.encode(self)?;
206 207 208

        // Encode length which is usually less than span.hi and profits more
        // from the variable-length integer encoding that we use.
209 210 211 212 213 214 215 216 217 218
        let len = hi - lo;
        len.encode(self)?;

        if tag == TAG_VALID_SPAN_FOREIGN {
            // This needs to be two lines to avoid holding the `self.source_file_cache`
            // while calling `cnum.encode(self)`
            let cnum = self.source_file_cache.cnum;
            cnum.encode(self)?;
        }
        Ok(())
219 220 221 222 223

        // Don't encode the expansion context.
    }
}

224
impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
225 226 227 228 229 230
    #[inline]
    fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
        self.specialized_encode(&def_id.to_def_id())
    }
}

231 232 233 234 235 236 237
impl<'a, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx>
where
    &'a ty::TyS<'b>: UseSpecializedEncodable,
{
    fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
        debug_assert!(self.tcx.lift(ty).is_some());
        let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
238
        ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
239 240 241
    }
}

242
impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
243
    fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
244 245 246 247 248 249 250 251
        use std::collections::hash_map::Entry;
        let index = match self.interpret_allocs.entry(*alloc_id) {
            Entry::Occupied(e) => *e.get(),
            Entry::Vacant(e) => {
                let idx = self.interpret_allocs_inverse.len();
                self.interpret_allocs_inverse.push(*alloc_id);
                e.insert(idx);
                idx
M
Mark Rousskov 已提交
252
            }
253
        };
254 255

        index.encode(self)
256 257 258
    }
}

259
impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> {
M
Mark Rousskov 已提交
260 261
    fn specialized_encode(
        &mut self,
262
        predicates: &&'a [(ty::Predicate<'b>, Span)],
M
Mark Rousskov 已提交
263
    ) -> Result<(), Self::Error> {
264 265 266 267 268 269 270 271
        debug_assert!(self.tcx.lift(*predicates).is_some());
        let predicates = unsafe {
            std::mem::transmute::<
                &&'a [(ty::Predicate<'b>, Span)],
                &&'tcx [(ty::Predicate<'tcx>, Span)],
            >(predicates)
        };
        ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands)
272 273 274
    }
}

275
impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
276 277 278 279 280
    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
        f.encode_opaque(&mut self.opaque)
    }
}

281 282 283 284
impl<'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx>
where
    mir::ClearCrossCrate<T>: UseSpecializedEncodable,
{
M
Mark Rousskov 已提交
285
    fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
286 287 288 289
        Ok(())
    }
}

290
impl<'tcx> TyEncoder for EncodeContext<'tcx> {
291
    fn position(&self) -> usize {
292 293
        self.opaque.position()
    }
294 295
}

296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
/// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
trait EncodeContentsForLazy<T: ?Sized + LazyMeta> {
    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> T::Meta;
}

impl<T: Encodable> EncodeContentsForLazy<T> for &T {
    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) {
        self.encode(ecx).unwrap()
    }
}

impl<T: Encodable> EncodeContentsForLazy<T> for T {
    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) {
        self.encode(ecx).unwrap()
    }
}

313
impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I
M
Mark Rousskov 已提交
314 315 316
where
    I: IntoIterator,
    I::Item: EncodeContentsForLazy<T>,
317 318 319
{
    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize {
        self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
320
    }
321
}
322

323
// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
324 325
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record {
326
    ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
327 328 329
        {
            let value = $value;
            let lazy = $self.lazy(value);
330
            $self.$tables.$table.set($def_id.index, lazy);
331
        }
M
Mark Rousskov 已提交
332
    }};
333 334
}

335 336 337 338 339
impl<'tcx> EncodeContext<'tcx> {
    fn emit_lazy_distance<T: ?Sized + LazyMeta>(
        &mut self,
        lazy: Lazy<T>,
    ) -> Result<(), <Self as Encoder>::Error> {
340
        let min_end = lazy.position.get() + T::min_size(lazy.meta);
341
        let distance = match self.lazy_state {
342
            LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
343
            LazyState::NodeStart(start) => {
344
                let start = start.get();
345 346 347 348
                assert!(min_end <= start);
                start - min_end
            }
            LazyState::Previous(last_min_end) => {
349
                assert!(
350
                    last_min_end <= lazy.position,
351
                    "make sure that the calls to `lazy*` \
M
Mark Mansi 已提交
352
                     are in the same order as the metadata fields",
353
                );
354
                lazy.position.get() - last_min_end.get()
355 356
            }
        };
357
        self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap());
358 359 360
        self.emit_usize(distance)
    }

M
Mark Rousskov 已提交
361
    fn lazy<T: ?Sized + LazyMeta>(&mut self, value: impl EncodeContentsForLazy<T>) -> Lazy<T> {
362
        let pos = NonZeroUsize::new(self.position()).unwrap();
363

364 365 366 367
        assert_eq!(self.lazy_state, LazyState::NoNode);
        self.lazy_state = LazyState::NodeStart(pos);
        let meta = value.encode_contents_for_lazy(self);
        self.lazy_state = LazyState::NoNode;
368

369
        assert!(pos.get() + <T>::min_size(meta) <= self.position());
370

371
        Lazy::from_position_and_meta(pos, meta)
372 373
    }

374
    fn encode_info_for_items(&mut self) {
375
        let krate = self.tcx.hir().krate();
376
        let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public };
377
        self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis);
378
        krate.visit_all_item_likes(&mut self.as_deep_visitor());
C
Camille GILLOT 已提交
379
        for macro_def in krate.exported_macros {
380
            self.visit_macro_def(macro_def);
381 382 383 384
        }
    }

    fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
385
        let definitions = self.tcx.hir().definitions();
386 387 388
        self.lazy(definitions.def_path_table())
    }

389
    fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
D
Donato Sciarra 已提交
390 391
        let source_map = self.tcx.sess.source_map();
        let all_source_files = source_map.files();
392

393
        let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone();
394

M
Mark Rousskov 已提交
395 396
        let adapted = all_source_files
            .iter()
D
Donato Sciarra 已提交
397 398
            .filter(|source_file| {
                // No need to re-export imported source_files, as any downstream
399
                // crate will import them from their original source.
400
                // FIXME(eddyb) the `Span` encoding should take that into account.
D
Donato Sciarra 已提交
401
                !source_file.is_imported()
402
            })
D
Donato Sciarra 已提交
403 404
            .map(|source_file| {
                match source_file.name {
405 406 407
                    // This path of this SourceFile has been modified by
                    // path-remapping, so we use it verbatim (and avoid
                    // cloning the whole map in the process).
M
Mark Rousskov 已提交
408
                    _ if source_file.name_was_remapped => source_file.clone(),
409 410 411 412

                    // Otherwise expand all paths to absolute paths because
                    // any relative paths are potentially relative to a
                    // wrong directory.
413
                    FileName::Real(ref name) => {
414
                        let name = name.stable_name();
415 416 417
                        let mut adapted = (**source_file).clone();
                        adapted.name = Path::new(&working_dir).join(name).into();
                        adapted.name_hash = {
418
                            let mut hasher: StableHasher = StableHasher::new();
419
                            adapted.name.hash(&mut hasher);
420
                            hasher.finish::<u128>()
421 422
                        };
                        Lrc::new(adapted)
M
Mark Rousskov 已提交
423
                    }
424

425
                    // expanded code, not from a file
D
Donato Sciarra 已提交
426
                    _ => source_file.clone(),
427
                }
428 429
            })
            .collect::<Vec<_>>();
430

431
        self.lazy(adapted.iter().map(|rc| &**rc))
432 433
    }

434
    fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
435
        let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
436

437 438
        let mut i = self.position();

439 440
        let crate_deps = self.encode_crate_deps();
        let dylib_dependency_formats = self.encode_dylib_dependency_formats();
441 442
        let dep_bytes = self.position() - i;

V
varkor 已提交
443 444
        // Encode the lib features.
        i = self.position();
445
        let lib_features = self.encode_lib_features();
V
varkor 已提交
446 447
        let lib_feature_bytes = self.position() - i;

448 449
        // Encode the language items.
        i = self.position();
450 451
        let lang_items = self.encode_lang_items();
        let lang_items_missing = self.encode_lang_items_missing();
452 453
        let lang_item_bytes = self.position() - i;

O
Oliver Scherer 已提交
454 455 456 457 458
        // Encode the diagnostic items.
        i = self.position();
        let diagnostic_items = self.encode_diagnostic_items();
        let diagnostic_item_bytes = self.position() - i;

459 460
        // Encode the native libraries used
        i = self.position();
461
        let native_libraries = self.encode_native_libraries();
462 463
        let native_lib_bytes = self.position() - i;

464
        let foreign_modules = self.encode_foreign_modules();
465

D
Donato Sciarra 已提交
466
        // Encode source_map
467
        i = self.position();
D
Donato Sciarra 已提交
468 469
        let source_map = self.encode_source_map();
        let source_map_bytes = self.position() - i;
470 471 472 473 474 475 476 477

        // Encode DefPathTable
        i = self.position();
        let def_path_table = self.encode_def_path_table();
        let def_path_table_bytes = self.position() - i;

        // Encode the def IDs of impls, for coherence checking.
        i = self.position();
478
        let impls = self.encode_impls();
479 480 481
        let impl_bytes = self.position() - i;

        let tcx = self.tcx;
482

483 484
        // Encode the items.
        i = self.position();
485
        self.encode_info_for_items();
486 487
        let item_bytes = self.position() - i;

488 489 490 491
        // Encode the allocation index
        let interpret_alloc_index = {
            let mut interpret_alloc_index = Vec::new();
            let mut n = 0;
492
            trace!("beginning to encode alloc ids");
493
            loop {
494
                let new_n = self.interpret_allocs_inverse.len();
495 496 497 498 499 500
                // if we have found new ids, serialize those, too
                if n == new_n {
                    // otherwise, abort
                    break;
                }
                trace!("encoding {} further alloc ids", new_n - n);
501 502 503 504
                for idx in n..new_n {
                    let id = self.interpret_allocs_inverse[idx];
                    let pos = self.position() as u32;
                    interpret_alloc_index.push(pos);
M
Mark Rousskov 已提交
505
                    interpret::specialized_encode_alloc_id(self, tcx, id).unwrap();
506 507 508
                }
                n = new_n;
            }
509
            self.lazy(interpret_alloc_index)
510 511
        };

512
        i = self.position();
513 514
        let tables = self.tables.encode(&mut self.opaque);
        let tables_bytes = self.position() - i;
515

516 517 518 519 520
        // Encode the proc macro data
        i = self.position();
        let proc_macro_data = self.encode_proc_macros();
        let proc_macro_data_bytes = self.position() - i;

J
John Kåre Alsaker 已提交
521 522
        // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
        // this last to give the prefetching as much time as possible to complete.
523 524 525 526 527
        i = self.position();
        let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
        let exported_symbols = self.encode_exported_symbols(&exported_symbols);
        let exported_symbols_bytes = self.position() - i;

528
        let attrs = tcx.hir().krate_attrs();
529
        let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator);
530

531
        let root = self.lazy(CrateRoot {
532
            name: tcx.crate_name(LOCAL_CRATE),
533
            extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
534
            triple: tcx.sess.opts.target_triple.clone(),
B
bjorn3 已提交
535
            hash: tcx.crate_hash(LOCAL_CRATE),
536
            disambiguator: tcx.sess.local_crate_disambiguator(),
537
            panic_strategy: tcx.sess.panic_strategy(),
538
            edition: tcx.sess.edition(),
539
            has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
M
Mark Rousskov 已提交
540
            has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
541
            has_default_lib_allocator,
542
            plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index),
543
            proc_macro_decls_static: if is_proc_macro {
544 545
                let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap();
                Some(id.index)
546 547 548
            } else {
                None
            },
549
            proc_macro_data,
J
John Kåre Alsaker 已提交
550
            proc_macro_stability: if is_proc_macro {
551
                tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied()
J
John Kåre Alsaker 已提交
552 553 554
            } else {
                None
            },
555 556 557 558 559 560
            compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins),
            needs_allocator: attr::contains_name(&attrs, sym::needs_allocator),
            needs_panic_runtime: attr::contains_name(&attrs, sym::needs_panic_runtime),
            no_builtins: attr::contains_name(&attrs, sym::no_builtins),
            panic_runtime: attr::contains_name(&attrs, sym::panic_runtime),
            profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime),
561
            symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
562

563 564
            crate_deps,
            dylib_dependency_formats,
V
varkor 已提交
565
            lib_features,
566
            lang_items,
O
Oliver Scherer 已提交
567
            diagnostic_items,
568 569
            lang_items_missing,
            native_libraries,
570
            foreign_modules,
D
Donato Sciarra 已提交
571
            source_map,
572 573
            def_path_table,
            impls,
574
            exported_symbols,
575
            interpret_alloc_index,
576
            tables,
577 578 579 580 581 582
        });

        let total_bytes = self.position();

        if self.tcx.sess.meta_stats() {
            let mut zero_bytes = 0;
583
            for e in self.opaque.data.iter() {
584 585 586 587 588 589 590
                if *e == 0 {
                    zero_bytes += 1;
                }
            }

            println!("metadata stats:");
            println!("             dep bytes: {}", dep_bytes);
V
varkor 已提交
591
            println!("     lib feature bytes: {}", lib_feature_bytes);
592
            println!("       lang item bytes: {}", lang_item_bytes);
O
Oliver Scherer 已提交
593
            println!(" diagnostic item bytes: {}", diagnostic_item_bytes);
594
            println!("          native bytes: {}", native_lib_bytes);
D
Donato Sciarra 已提交
595
            println!("         source_map bytes: {}", source_map_bytes);
596
            println!("            impl bytes: {}", impl_bytes);
597
            println!("    exp. symbols bytes: {}", exported_symbols_bytes);
598
            println!("  def-path table bytes: {}", def_path_table_bytes);
599
            println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
600
            println!("            item bytes: {}", item_bytes);
601
            println!("           table bytes: {}", tables_bytes);
602 603 604 605 606 607
            println!("            zero bytes: {}", zero_bytes);
            println!("           total bytes: {}", total_bytes);
        }

        root
    }
608
}
609

610
impl EncodeContext<'tcx> {
611
    fn encode_variances_of(&mut self, def_id: DefId) {
612
        debug!("EncodeContext::encode_variances_of({:?})", def_id);
613
        record!(self.tables.variances[def_id] <- &self.tcx.variances_of(def_id)[..]);
614
    }
615

616 617
    fn encode_item_type(&mut self, def_id: DefId) {
        debug!("EncodeContext::encode_item_type({:?})", def_id);
618
        record!(self.tables.ty[def_id] <- self.tcx.type_of(def_id));
619
    }
A
Aaron Turon 已提交
620

621
    fn encode_enum_variant_info(&mut self, def: &ty::AdtDef, index: VariantIdx) {
622
        let tcx = self.tcx;
623
        let variant = &def.variants[index];
624
        let def_id = variant.def_id;
625
        debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
626 627

        let data = VariantData {
628
            ctor_kind: variant.ctor_kind,
629
            discr: variant.discr,
630
            ctor: variant.ctor_def_id.map(|did| did.index),
631
        };
632

633
        let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
634
        let enum_vis = &tcx.hir().expect_item(enum_id).vis;
635

636 637
        record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
        record!(self.tables.visibility[def_id] <-
638
            ty::Visibility::from_hir(enum_vis, enum_id, self.tcx));
639 640 641
        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
        record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
        record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
642 643 644
            assert!(f.did.is_local());
            f.did.index
        }));
645
        self.encode_ident_span(def_id, variant.ident);
646 647 648 649
        self.encode_stability(def_id);
        self.encode_deprecation(def_id);
        self.encode_item_type(def_id);
        if variant.ctor_kind == CtorKind::Fn {
650 651
            // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
            if let Some(ctor_def_id) = variant.ctor_def_id {
652
                record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
653 654
            }
            // FIXME(eddyb) is this ever used?
655 656 657
            self.encode_variances_of(def_id);
        }
        self.encode_generics(def_id);
658 659
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
660 661
        self.encode_optimized_mir(def_id.expect_local());
        self.encode_promoted_mir(def_id.expect_local());
662 663
    }

664
    fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) {
665 666
        let tcx = self.tcx;
        let variant = &def.variants[index];
667
        let def_id = variant.ctor_def_id.unwrap();
668
        debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
669

670
        // FIXME(eddyb) encode only the `CtorKind` for constructors.
671 672 673 674 675 676
        let data = VariantData {
            ctor_kind: variant.ctor_kind,
            discr: variant.discr,
            ctor: Some(def_id.index),
        };

677 678
        // Variant constructors have the same visibility as the parent enums, unless marked as
        // non-exhaustive, in which case they are lowered to `pub(crate)`.
679
        let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
680
        let enum_vis = &tcx.hir().expect_item(enum_id).vis;
681 682 683 684
        let mut ctor_vis = ty::Visibility::from_hir(enum_vis, enum_id, tcx);
        if variant.is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public {
            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
        }
685

686 687 688
        record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
        record!(self.tables.visibility[def_id] <- ctor_vis);
        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
689 690 691 692
        self.encode_stability(def_id);
        self.encode_deprecation(def_id);
        self.encode_item_type(def_id);
        if variant.ctor_kind == CtorKind::Fn {
693
            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
694 695 696
            self.encode_variances_of(def_id);
        }
        self.encode_generics(def_id);
697 698
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
699 700
        self.encode_optimized_mir(def_id.expect_local());
        self.encode_promoted_mir(def_id.expect_local());
701 702
    }

703 704
    fn encode_info_for_mod(
        &mut self,
705
        id: hir::HirId,
C
Camille GILLOT 已提交
706
        md: &hir::Mod<'_>,
707
        attrs: &[ast::Attribute],
C
Camille GILLOT 已提交
708
        vis: &hir::Visibility<'_>,
709
    ) {
710
        let tcx = self.tcx;
711
        let def_id = tcx.hir().local_def_id(id);
712
        debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
713

714
        let data = ModData {
A
Alex Crichton 已提交
715
            reexports: match tcx.module_exports(def_id) {
716 717 718 719 720 721 722 723
                Some(exports) => {
                    let hir_map = self.tcx.hir();
                    self.lazy(
                        exports
                            .iter()
                            .map(|export| export.map_id(|id| hir_map.as_local_hir_id(id))),
                    )
                }
724
                _ => Lazy::empty(),
725
            },
726
        };
727

728 729
        let def_id = def_id.to_def_id();

730 731 732 733 734
        record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
        record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
        record!(self.tables.attributes[def_id] <- attrs);
        record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
735
            tcx.hir().local_def_id(item_id.id).local_def_index
736 737 738
        }));
        self.encode_stability(def_id);
        self.encode_deprecation(def_id);
739
    }
N
Niko Matsakis 已提交
740

741 742 743 744 745 746
    fn encode_field(
        &mut self,
        adt_def: &ty::AdtDef,
        variant_index: VariantIdx,
        field_index: usize,
    ) {
747
        let tcx = self.tcx;
748
        let variant = &adt_def.variants[variant_index];
N
Niko Matsakis 已提交
749
        let field = &variant.fields[field_index];
750

751
        let def_id = field.did;
752
        debug!("EncodeContext::encode_field({:?})", def_id);
753

754
        let variant_id = tcx.hir().as_local_hir_id(variant.def_id.expect_local());
755
        let variant_data = tcx.hir().expect_variant_data(variant_id);
756

757 758 759 760
        record!(self.tables.kind[def_id] <- EntryKind::Field);
        record!(self.tables.visibility[def_id] <- field.vis);
        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
        record!(self.tables.attributes[def_id] <- variant_data.fields()[field_index].attrs);
761
        self.encode_ident_span(def_id, field.ident);
762 763 764 765
        self.encode_stability(def_id);
        self.encode_deprecation(def_id);
        self.encode_item_type(def_id);
        self.encode_generics(def_id);
766 767
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
768
    }
769

770
    fn encode_struct_ctor(&mut self, adt_def: &ty::AdtDef, def_id: DefId) {
771
        debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
772
        let tcx = self.tcx;
773
        let variant = adt_def.non_enum_variant();
774

775
        let data = VariantData {
776
            ctor_kind: variant.ctor_kind,
777
            discr: variant.discr,
778
            ctor: Some(def_id.index),
779 780
        };

781
        let struct_id = tcx.hir().as_local_hir_id(adt_def.did.expect_local());
782
        let struct_vis = &tcx.hir().expect_item(struct_id).vis;
783 784 785 786 787 788
        let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
        for field in &variant.fields {
            if ctor_vis.is_at_least(field.vis, tcx) {
                ctor_vis = field.vis;
            }
        }
789

790 791
        // If the structure is marked as non_exhaustive then lower the visibility
        // to within the crate.
M
Mark Rousskov 已提交
792 793
        if adt_def.non_enum_variant().is_field_list_non_exhaustive()
            && ctor_vis == ty::Visibility::Public
794
        {
795 796 797
            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
        }

798 799 800
        record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
        record!(self.tables.visibility[def_id] <- ctor_vis);
        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
801 802 803 804
        self.encode_stability(def_id);
        self.encode_deprecation(def_id);
        self.encode_item_type(def_id);
        if variant.ctor_kind == CtorKind::Fn {
805
            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
806 807 808
            self.encode_variances_of(def_id);
        }
        self.encode_generics(def_id);
809 810
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
811 812
        self.encode_optimized_mir(def_id.expect_local());
        self.encode_promoted_mir(def_id.expect_local());
813
    }
814

815
    fn encode_generics(&mut self, def_id: DefId) {
816
        debug!("EncodeContext::encode_generics({:?})", def_id);
817
        record!(self.tables.generics[def_id] <- self.tcx.generics_of(def_id));
818
    }
819

820 821
    fn encode_explicit_predicates(&mut self, def_id: DefId) {
        debug!("EncodeContext::encode_explicit_predicates({:?})", def_id);
822
        record!(self.tables.explicit_predicates[def_id] <-
823
            self.tcx.explicit_predicates_of(def_id));
824
    }
825

826 827
    fn encode_inferred_outlives(&mut self, def_id: DefId) {
        debug!("EncodeContext::encode_inferred_outlives({:?})", def_id);
828 829
        let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
        if !inferred_outlives.is_empty() {
830
            record!(self.tables.inferred_outlives[def_id] <- inferred_outlives);
831
        }
832 833
    }

834 835
    fn encode_super_predicates(&mut self, def_id: DefId) {
        debug!("EncodeContext::encode_super_predicates({:?})", def_id);
836
        record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
837 838
    }

839
    fn encode_info_for_trait_item(&mut self, def_id: DefId) {
840
        debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
841
        let tcx = self.tcx;
842

843
        let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
844
        let ast_item = tcx.hir().expect_trait_item(hir_id);
845
        let trait_item = tcx.associated_item(def_id);
846

847
        let container = match trait_item.defaultness {
M
Mark Rousskov 已提交
848 849 850
            hir::Defaultness::Default { has_value: true } => AssocContainer::TraitWithDefault,
            hir::Defaultness::Default { has_value: false } => AssocContainer::TraitRequired,
            hir::Defaultness::Final => span_bug!(ast_item.span, "traits cannot have final items"),
851
        };
852

853
        record!(self.tables.kind[def_id] <- match trait_item.kind {
A
Andrew Xu 已提交
854
            ty::AssocKind::Const => {
855 856 857 858
                let rendered = rustc_hir_pretty::to_string(
                    &(&self.tcx.hir() as &dyn intravisit::Map<'_>),
                    |s| s.print_trait_item(ast_item)
                );
859
                let rendered_const = self.lazy(RenderedConst(rendered));
W
Wesley Wiser 已提交
860

861 862
                EntryKind::AssocConst(
                    container,
863
                    Default::default(),
864 865
                    rendered_const,
                )
866
            }
867
            ty::AssocKind::Fn => {
M
Mark Mansi 已提交
868
                let fn_data = if let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind {
869
                    let param_names = match *m {
M
Mark Mansi 已提交
870
                        hir::TraitFn::Required(ref names) => {
871
                            self.encode_fn_param_names(names)
872
                        }
M
Mark Mansi 已提交
873
                        hir::TraitFn::Provided(body) => {
874
                            self.encode_fn_param_names_for_body(body)
875 876
                        }
                    };
877
                    FnData {
878
                        asyncness: m_sig.header.asyncness,
879
                        constness: hir::Constness::NotConst,
880
                        param_names,
881 882 883 884
                    }
                } else {
                    bug!()
                };
M
Mark Mansi 已提交
885
                EntryKind::AssocFn(self.lazy(AssocFnData {
886 887
                    fn_data,
                    container,
888
                    has_self: trait_item.fn_has_self_parameter,
889
                }))
890
            }
A
Andrew Xu 已提交
891
            ty::AssocKind::Type => EntryKind::AssocType(container),
892
        });
893 894 895
        record!(self.tables.visibility[def_id] <- trait_item.vis);
        record!(self.tables.span[def_id] <- ast_item.span);
        record!(self.tables.attributes[def_id] <- ast_item.attrs);
896
        self.encode_ident_span(def_id, ast_item.ident);
897
        self.encode_stability(def_id);
898
        self.encode_const_stability(def_id);
899 900
        self.encode_deprecation(def_id);
        match trait_item.kind {
901
            ty::AssocKind::Const | ty::AssocKind::Fn => {
902 903 904 905 906
                self.encode_item_type(def_id);
            }
            ty::AssocKind::Type => {
                if trait_item.defaultness.has_value() {
                    self.encode_item_type(def_id);
907
                }
908 909
            }
        }
910
        if trait_item.kind == ty::AssocKind::Fn {
911
            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
912 913 914
            self.encode_variances_of(def_id);
        }
        self.encode_generics(def_id);
915 916
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
J
John Kåre Alsaker 已提交
917 918

        // This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
919 920
        self.encode_optimized_mir(def_id.expect_local());
        self.encode_promoted_mir(def_id.expect_local());
921 922
    }

V
varkor 已提交
923 924
    fn metadata_output_only(&self) -> bool {
        // MIR optimisation can be skipped when we're just interested in the metadata.
I
Irina Popa 已提交
925
        !self.tcx.sess.opts.output_types.should_codegen()
V
varkor 已提交
926 927
    }

928
    fn encode_info_for_impl_item(&mut self, def_id: DefId) {
929
        debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
930 931
        let tcx = self.tcx;

932
        let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
933
        let ast_item = self.tcx.hir().expect_impl_item(hir_id);
934
        let impl_item = self.tcx.associated_item(def_id);
935

936
        let container = match impl_item.defaultness {
A
Andrew Xu 已提交
937 938
            hir::Defaultness::Default { has_value: true } => AssocContainer::ImplDefault,
            hir::Defaultness::Final => AssocContainer::ImplFinal,
M
Mark Rousskov 已提交
939 940 941
            hir::Defaultness::Default { has_value: false } => {
                span_bug!(ast_item.span, "impl items always have values (currently)")
            }
942
        };
943

944
        record!(self.tables.kind[def_id] <- match impl_item.kind {
A
Andrew Xu 已提交
945
            ty::AssocKind::Const => {
946
                if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
947
                    let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
W
Wesley Wiser 已提交
948

949 950 951
                    EntryKind::AssocConst(
                        container,
                        qualifs,
W
Wesley Wiser 已提交
952 953 954 955
                        self.encode_rendered_const_for_body(body_id))
                } else {
                    bug!()
                }
956
            }
957
            ty::AssocKind::Fn => {
M
Mark Mansi 已提交
958
                let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind {
959
                    FnData {
C
csmoe 已提交
960
                        asyncness: sig.header.asyncness,
W
Without Boats 已提交
961
                        constness: sig.header.constness,
962
                        param_names: self.encode_fn_param_names_for_body(body),
963 964 965 966
                    }
                } else {
                    bug!()
                };
M
Mark Mansi 已提交
967
                EntryKind::AssocFn(self.lazy(AssocFnData {
968 969
                    fn_data,
                    container,
970
                    has_self: impl_item.fn_has_self_parameter,
971
                }))
972
            }
A
Andrew Xu 已提交
973
            ty::AssocKind::Type => EntryKind::AssocType(container)
974
        });
975 976 977
        record!(self.tables.visibility[def_id] <- impl_item.vis);
        record!(self.tables.span[def_id] <- ast_item.span);
        record!(self.tables.attributes[def_id] <- ast_item.attrs);
978
        self.encode_ident_span(def_id, impl_item.ident);
979
        self.encode_stability(def_id);
980
        self.encode_const_stability(def_id);
981 982
        self.encode_deprecation(def_id);
        self.encode_item_type(def_id);
983
        if impl_item.kind == ty::AssocKind::Fn {
984
            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
985 986 987
            self.encode_variances_of(def_id);
        }
        self.encode_generics(def_id);
988 989
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
J
John Kåre Alsaker 已提交
990 991 992

        // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.

993 994
        let mir = match ast_item.kind {
            hir::ImplItemKind::Const(..) => true,
M
Mark Mansi 已提交
995
            hir::ImplItemKind::Fn(ref sig, _) => {
996
                let generics = self.tcx.generics_of(def_id);
M
Mark Rousskov 已提交
997 998 999
                let needs_inline = (generics.requires_monomorphization(self.tcx)
                    || tcx.codegen_fn_attrs(def_id).requests_inline())
                    && !self.metadata_output_only();
1000 1001 1002
                let is_const_fn = sig.header.constness == hir::Constness::Const;
                let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                needs_inline || is_const_fn || always_encode_mir
M
Mark Rousskov 已提交
1003
            }
M
Matthew Jasper 已提交
1004
            hir::ImplItemKind::TyAlias(..) => false,
1005
        };
1006
        if mir {
1007 1008
            self.encode_optimized_mir(def_id.expect_local());
            self.encode_promoted_mir(def_id.expect_local());
1009
        }
T
Tim Chevalier 已提交
1010 1011
    }

1012
    fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Symbol]> {
1013
        self.tcx.dep_graph.with_ignore(|| {
1014
            let body = self.tcx.hir().body(body_id);
M
Mark Rousskov 已提交
1015
            self.lazy(body.params.iter().map(|arg| match arg.pat.kind {
1016
                hir::PatKind::Binding(_, _, ident, _) => ident.name,
M
Mark Rousskov 已提交
1017
                _ => kw::Invalid,
1018 1019
            }))
        })
1020 1021
    }

1022
    fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Symbol]> {
1023
        self.lazy(param_names.iter().map(|ident| ident.name))
1024 1025
    }

1026
    fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
1027
        debug!("EntryBuilder::encode_mir({:?})", def_id);
N
Niko Matsakis 已提交
1028
        if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
1029
            record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
N
Niko Matsakis 已提交
1030
        }
1031
    }
1032

1033
    fn encode_promoted_mir(&mut self, def_id: LocalDefId) {
W
Wesley Wiser 已提交
1034 1035
        debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
        if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
1036
            record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
W
Wesley Wiser 已提交
1037 1038 1039
        }
    }

1040
    // Encodes the inherent implementations of a structure, enumeration, or trait.
1041
    fn encode_inherent_implementations(&mut self, def_id: DefId) {
1042
        debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
1043
        let implementations = self.tcx.inherent_impls(def_id);
1044
        if !implementations.is_empty() {
1045
            record!(self.tables.inherent_impls[def_id] <- implementations.iter().map(|&def_id| {
1046 1047
                assert!(def_id.is_local());
                def_id.index
1048
            }));
1049
        }
1050 1051
    }

1052
    fn encode_stability(&mut self, def_id: DefId) {
1053
        debug!("EncodeContext::encode_stability({:?})", def_id);
1054
        if let Some(stab) = self.tcx.lookup_stability(def_id) {
1055
            record!(self.tables.stability[def_id] <- stab)
1056
        }
1057 1058
    }

1059 1060 1061
    fn encode_const_stability(&mut self, def_id: DefId) {
        debug!("EncodeContext::encode_const_stability({:?})", def_id);
        if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
1062
            record!(self.tables.const_stability[def_id] <- stab)
1063 1064 1065
        }
    }

1066
    fn encode_deprecation(&mut self, def_id: DefId) {
1067
        debug!("EncodeContext::encode_deprecation({:?})", def_id);
1068
        if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
1069
            record!(self.tables.deprecation[def_id] <- depr);
1070
        }
1071
    }
1072

W
Wesley Wiser 已提交
1073
    fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> {
1074 1075 1076 1077 1078
        let hir = self.tcx.hir();
        let body = hir.body(body_id);
        let rendered = rustc_hir_pretty::to_string(&(&hir as &dyn intravisit::Map<'_>), |s| {
            s.print_expr(&body.value)
        });
W
Wesley Wiser 已提交
1079 1080 1081 1082
        let rendered_const = &RenderedConst(rendered);
        self.lazy(rendered_const)
    }

C
Camille GILLOT 已提交
1083
    fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
1084
        let tcx = self.tcx;
1085

1086
        debug!("EncodeContext::encode_info_for_item({:?})", def_id);
1087

1088 1089
        self.encode_ident_span(def_id, item.ident);

1090
        record!(self.tables.kind[def_id] <- match item.kind {
1091 1092
            hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic,
            hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic,
C
csmoe 已提交
1093
            hir::ItemKind::Const(_, body_id) => {
1094
                let qualifs = self.tcx.at(item.span).mir_const_qualif(def_id);
W
Wesley Wiser 已提交
1095
                EntryKind::Const(
1096
                    qualifs,
W
Wesley Wiser 已提交
1097 1098
                    self.encode_rendered_const_for_body(body_id)
                )
1099
            }
1100
            hir::ItemKind::Fn(ref sig, .., body) => {
1101
                let data = FnData {
1102 1103
                    asyncness: sig.header.asyncness,
                    constness: sig.header.constness,
1104
                    param_names: self.encode_fn_param_names_for_body(body),
1105
                };
1106

1107
                EntryKind::Fn(self.lazy(data))
1108
            }
C
csmoe 已提交
1109
            hir::ItemKind::Mod(ref m) => {
1110
                return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis);
1111
            }
C
csmoe 已提交
1112 1113
            hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
            hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
1114
            hir::ItemKind::TyAlias(..) => EntryKind::Type,
V
varkor 已提交
1115
            hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy,
1116
            hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr),
C
csmoe 已提交
1117
            hir::ItemKind::Struct(ref struct_def, _) => {
1118 1119
                let adt_def = self.tcx.adt_def(def_id);
                let variant = adt_def.non_enum_variant();
1120

1121 1122 1123
                // Encode def_ids for each field and method
                // for methods, write all the stuff get_trait_method
                // needs to know
1124
                let ctor = struct_def.ctor_hir_id().map(|ctor_hir_id| {
1125
                    self.tcx.hir().local_def_id(ctor_hir_id).local_def_index
1126
                });
1127

1128
                EntryKind::Struct(self.lazy(VariantData {
1129
                    ctor_kind: variant.ctor_kind,
1130
                    discr: variant.discr,
1131
                    ctor,
1132
                }), adt_def.repr)
1133
            }
C
csmoe 已提交
1134
            hir::ItemKind::Union(..) => {
1135 1136
                let adt_def = self.tcx.adt_def(def_id);
                let variant = adt_def.non_enum_variant();
V
Vadim Petrochenkov 已提交
1137

1138
                EntryKind::Union(self.lazy(VariantData {
1139
                    ctor_kind: variant.ctor_kind,
1140
                    discr: variant.discr,
1141
                    ctor: None,
1142
                }), adt_def.repr)
V
Vadim Petrochenkov 已提交
1143
            }
1144
            hir::ItemKind::Impl { defaultness, .. } => {
1145 1146
                let trait_ref = self.tcx.impl_trait_ref(def_id);
                let polarity = self.tcx.impl_polarity(def_id);
1147
                let parent = if let Some(trait_ref) = trait_ref {
1148
                    let trait_def = self.tcx.trait_def(trait_ref.def_id);
1149 1150 1151 1152 1153 1154 1155
                    trait_def.ancestors(self.tcx, def_id).ok()
                        .and_then(|mut an| an.nth(1).and_then(|node| {
                            match node {
                                specialization_graph::Node::Impl(parent) => Some(parent),
                                _ => None,
                            }
                        }))
1156 1157 1158
                } else {
                    None
                };
1159

1160 1161 1162 1163
                // if this is an impl of `CoerceUnsized`, create its
                // "unsized info", else just store None
                let coerce_unsized_info =
                    trait_ref.and_then(|t| {
1164 1165
                        if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() {
                            Some(self.tcx.at(item.span).coerce_unsized_info(def_id))
1166 1167 1168 1169 1170
                        } else {
                            None
                        }
                    });

1171
                let data = ImplData {
1172 1173
                    polarity,
                    defaultness,
1174
                    parent_impl: parent,
1175
                    coerce_unsized_info,
1176 1177
                };

1178
                EntryKind::Impl(self.lazy(data))
1179
            }
1180
            hir::ItemKind::Trait(..) => {
1181
                let trait_def = self.tcx.trait_def(def_id);
1182
                let data = TraitData {
1183 1184
                    unsafety: trait_def.unsafety,
                    paren_sugar: trait_def.paren_sugar,
1185
                    has_auto_impl: self.tcx.trait_is_auto(def_id),
1186
                    is_marker: trait_def.is_marker,
1187
                    specialization_kind: trait_def.specialization_kind,
1188 1189
                };

1190
                EntryKind::Trait(self.lazy(data))
1191
            }
1192
            hir::ItemKind::TraitAlias(..) => EntryKind::TraitAlias,
C
csmoe 已提交
1193 1194
            hir::ItemKind::ExternCrate(_) |
            hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
1195
        });
1196
        record!(self.tables.visibility[def_id] <-
1197
            ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
1198 1199
        record!(self.tables.span[def_id] <- item.span);
        record!(self.tables.attributes[def_id] <- item.attrs);
1200 1201
        // FIXME(eddyb) there should be a nicer way to do this.
        match item.kind {
1202
            hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <-
1203 1204 1205
                fm.items
                    .iter()
                    .map(|foreign_item| tcx.hir().local_def_id(
1206
                        foreign_item.hir_id).local_def_index)
1207
            ),
1208
            hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
1209 1210 1211 1212 1213
                self.tcx.adt_def(def_id).variants.iter().map(|v| {
                    assert!(v.def_id.is_local());
                    v.def_id.index
                })
            ),
M
Mark Rousskov 已提交
1214
            hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
1215
                record!(self.tables.children[def_id] <-
M
Mark Rousskov 已提交
1216 1217 1218 1219 1220 1221
                    self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
                        assert!(f.did.is_local());
                        f.did.index
                    })
                )
            }
1222
            hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
1223
                let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
1224
                record!(self.tables.children[def_id] <-
1225 1226 1227 1228 1229 1230 1231 1232 1233
                    associated_item_def_ids.iter().map(|&def_id| {
                        assert!(def_id.is_local());
                        def_id.index
                    })
                );
            }
            _ => {}
        }
        self.encode_stability(def_id);
1234
        self.encode_const_stability(def_id);
1235 1236
        self.encode_deprecation(def_id);
        match item.kind {
M
Mark Rousskov 已提交
1237 1238 1239 1240 1241 1242 1243 1244
            hir::ItemKind::Static(..)
            | hir::ItemKind::Const(..)
            | hir::ItemKind::Fn(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::OpaqueTy(..)
            | hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Union(..)
1245
            | hir::ItemKind::Impl { .. } => self.encode_item_type(def_id),
1246 1247
            _ => {}
        }
1248
        if let hir::ItemKind::Fn(..) = item.kind {
1249
            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
1250
        }
1251
        if let hir::ItemKind::Impl { .. } = item.kind {
1252
            if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
1253
                record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
1254 1255
            }
        }
1256 1257
        self.encode_inherent_implementations(def_id);
        match item.kind {
M
Mark Rousskov 已提交
1258 1259 1260 1261
            hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Union(..)
            | hir::ItemKind::Fn(..) => self.encode_variances_of(def_id),
1262 1263 1264
            _ => {}
        }
        match item.kind {
M
Mark Rousskov 已提交
1265 1266 1267 1268 1269 1270 1271
            hir::ItemKind::Static(..)
            | hir::ItemKind::Const(..)
            | hir::ItemKind::Fn(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Union(..)
1272
            | hir::ItemKind::Impl { .. }
M
Mark Rousskov 已提交
1273 1274 1275
            | hir::ItemKind::OpaqueTy(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::TraitAlias(..) => {
1276
                self.encode_generics(def_id);
1277 1278
                self.encode_explicit_predicates(def_id);
                self.encode_inferred_outlives(def_id);
1279 1280 1281
            }
            _ => {}
        }
1282
        match item.kind {
M
Mark Rousskov 已提交
1283
            hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1284 1285 1286 1287
                self.encode_super_predicates(def_id);
            }
            _ => {}
        }
1288

J
John Kåre Alsaker 已提交
1289 1290
        // The following part should be kept in sync with `PrefetchVisitor.visit_item`.

V
varkor 已提交
1291
        let mir = match item.kind {
W
Wesley Wiser 已提交
1292
            hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true,
1293
            hir::ItemKind::Fn(ref sig, ..) => {
W
Wesley Wiser 已提交
1294
                let generics = tcx.generics_of(def_id);
M
Mark Rousskov 已提交
1295 1296 1297
                let needs_inline = (generics.requires_monomorphization(tcx)
                    || tcx.codegen_fn_attrs(def_id).requests_inline())
                    && !self.metadata_output_only();
W
Wesley Wiser 已提交
1298
                let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
1299
                needs_inline || sig.header.constness == hir::Constness::Const || always_encode_mir
W
Wesley Wiser 已提交
1300 1301 1302
            }
            _ => false,
        };
1303
        if mir {
1304 1305
            self.encode_optimized_mir(def_id.expect_local());
            self.encode_promoted_mir(def_id.expect_local());
1306
        }
1307
    }
J
Jeffrey Seyfried 已提交
1308 1309

    /// Serialize the text of exported macros
C
Camille GILLOT 已提交
1310
    fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
1311
        let def_id = self.tcx.hir().local_def_id(macro_def.hir_id).to_def_id();
1312 1313 1314 1315
        record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
        record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
        record!(self.tables.span[def_id] <- macro_def.span);
        record!(self.tables.attributes[def_id] <- macro_def.attrs);
1316
        self.encode_ident_span(def_id, macro_def.ident);
1317 1318
        self.encode_stability(def_id);
        self.encode_deprecation(def_id);
J
Jeffrey Seyfried 已提交
1319
    }
1320

M
Mark Mansi 已提交
1321
    fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) {
1322 1323 1324
        record!(self.tables.kind[def_id] <- kind);
        record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
1325 1326 1327
        if encode_type {
            self.encode_item_type(def_id);
        }
V
varkor 已提交
1328 1329
    }

1330
    fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
1331
        debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
N
Niko Matsakis 已提交
1332

1333 1334
        // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
        // including on the signature, which is inferred in `typeck_tables_of.
1335
        let hir_id = self.tcx.hir().as_local_hir_id(def_id);
1336
        let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id);
1337

1338
        record!(self.tables.kind[def_id.to_def_id()] <- match ty.kind {
M
Mark Mansi 已提交
1339 1340
            ty::Generator(..) => {
                let data = self.tcx.generator_kind(def_id).unwrap();
M
mark 已提交
1341
                EntryKind::Generator(data)
1342 1343
            }

1344
            ty::Closure(..) => EntryKind::Closure,
1345

1346 1347
            _ => bug!("closure that is neither generator nor closure"),
        });
1348 1349 1350 1351
        record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
        record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
        record!(self.tables.attributes[def_id.to_def_id()] <- &self.tcx.get_attrs(def_id.to_def_id())[..]);
        self.encode_item_type(def_id.to_def_id());
1352
        if let ty::Closure(def_id, substs) = ty.kind {
1353
            record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
1354
        }
1355
        self.encode_generics(def_id.to_def_id());
1356 1357
        self.encode_optimized_mir(def_id);
        self.encode_promoted_mir(def_id);
1358
    }
1359

1360
    fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
1361
        debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
1362
        let id = self.tcx.hir().as_local_hir_id(def_id);
1363
        let body_id = self.tcx.hir().body_owned_by(id);
W
Wesley Wiser 已提交
1364
        let const_data = self.encode_rendered_const_for_body(body_id);
1365
        let qualifs = self.tcx.mir_const_qualif(def_id);
1366

1367 1368 1369 1370 1371 1372 1373
        record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Const(qualifs, const_data));
        record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public);
        record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id));
        self.encode_item_type(def_id.to_def_id());
        self.encode_generics(def_id.to_def_id());
        self.encode_explicit_predicates(def_id.to_def_id());
        self.encode_inferred_outlives(def_id.to_def_id());
1374 1375
        self.encode_optimized_mir(def_id);
        self.encode_promoted_mir(def_id);
1376 1377
    }

1378
    fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
1379
        let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1380
        self.lazy(used_libraries.iter().cloned())
1381
    }
1382

1383
    fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
1384
        let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
1385
        self.lazy(foreign_modules.iter().cloned())
1386 1387
    }

1388
    fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> {
1389
        let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
1390
        if is_proc_macro {
1391
            let tcx = self.tcx;
1392
            Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index)))
1393 1394 1395 1396 1397
        } else {
            None
        }
    }

1398
    fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
1399
        let crates = self.tcx.crates();
1400 1401 1402 1403 1404

        let mut deps = crates
            .iter()
            .map(|&cnum| {
                let dep = CrateDep {
1405
                    name: self.tcx.original_crate_name(cnum),
1406
                    hash: self.tcx.crate_hash(cnum),
M
msizanoen 已提交
1407
                    host_hash: self.tcx.crate_host_hash(cnum),
1408
                    kind: self.tcx.dep_kind(cnum),
1409
                    extra_filename: self.tcx.extra_filename(cnum),
1410 1411 1412 1413
                };
                (cnum, dep)
            })
            .collect::<Vec<_>>();
1414

1415
        deps.sort_by_key(|&(cnum, _)| cnum);
1416

1417
        {
1418 1419 1420 1421 1422 1423
            // Sanity-check the crate numbers
            let mut expected_cnum = 1;
            for &(n, _) in &deps {
                assert_eq!(n, CrateNum::new(expected_cnum));
                expected_cnum += 1;
            }
1424 1425
        }

1426 1427 1428 1429
        // We're just going to write a list of crate 'name-hash-version's, with
        // the assumption that they are numbered 1 to n.
        // FIXME (#2166): This is not nearly enough to support correct versioning
        // but is enough to get transitive crate dependencies working.
1430
        self.lazy(deps.iter().map(|&(_, ref dep)| dep))
1431 1432
    }

1433
    fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
V
varkor 已提交
1434 1435
        let tcx = self.tcx;
        let lib_features = tcx.lib_features();
1436
        self.lazy(lib_features.to_vec())
V
varkor 已提交
1437 1438
    }

O
Oliver Scherer 已提交
1439 1440 1441 1442 1443 1444
    fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
        let tcx = self.tcx;
        let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE);
        self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
    }

1445
    fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> {
1446
        let tcx = self.tcx;
1447 1448
        let lang_items = tcx.lang_items();
        let lang_items = lang_items.items().iter();
1449
        self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
1450 1451 1452
            if let Some(def_id) = opt_def_id {
                if def_id.is_local() {
                    return Some((def_id.index, i));
1453
                }
1454 1455
            }
            None
1456
        }))
1457
    }
1458

1459
    fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
1460
        let tcx = self.tcx;
1461
        self.lazy(&tcx.lang_items().missing)
1462
    }
1463

1464
    /// Encodes an index, mapping each trait to its (local) implementations.
1465
    fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
1466
        debug!("EncodeContext::encode_impls()");
1467
        let tcx = self.tcx;
M
Mark Rousskov 已提交
1468
        let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() };
1469
        tcx.hir().krate().visit_all_item_likes(&mut visitor);
1470 1471

        let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
1472

1473
        // Bring everything into deterministic order for hashing
M
Mark Rousskov 已提交
1474
        all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
1475 1476

        let all_impls: Vec<_> = all_impls
1477
            .into_iter()
1478 1479
            .map(|(trait_def_id, mut impls)| {
                // Bring everything into deterministic order for hashing
1480 1481
                impls.sort_by_cached_key(|&index| {
                    tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
1482 1483
                });

1484 1485
                TraitImpls {
                    trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
1486
                    impls: self.lazy(&impls),
1487 1488 1489
                }
            })
            .collect();
1490

1491
        self.lazy(&all_impls)
1492 1493
    }

1494
    // Encodes all symbols exported from this crate into the metadata.
1495 1496 1497 1498 1499
    //
    // This pass is seeded off the reachability list calculated in the
    // middle::reachable module but filters out items that either don't have a
    // symbol associated with them (they weren't translated) or if they're an FFI
    // definition (as that's not defined in this crate).
M
Mark Rousskov 已提交
1500 1501 1502 1503
    fn encode_exported_symbols(
        &mut self,
        exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)],
    ) -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> {
1504 1505 1506 1507
        // The metadata symbol name is special. It should not show up in
        // downstream crates.
        let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));

M
Mark Rousskov 已提交
1508 1509 1510 1511 1512
        self.lazy(
            exported_symbols
                .iter()
                .filter(|&&(ref exported_symbol, _)| match *exported_symbol {
                    ExportedSymbol::NoDefId(symbol_name) => symbol_name != metadata_symbol_name,
1513
                    _ => true,
M
Mark Rousskov 已提交
1514 1515 1516
                })
                .cloned(),
        )
1517
    }
1518

1519
    fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
1520 1521
        let formats = self.tcx.dependency_formats(LOCAL_CRATE);
        for (ty, arr) in formats.iter() {
1522
            if *ty != CrateType::Dylib {
1523
                continue;
1524
            }
M
Mark Rousskov 已提交
1525 1526
            return self.lazy(arr.iter().map(|slot| match *slot {
                Linkage::NotLinked | Linkage::IncludedFromDylib => None,
1527

M
Mark Rousskov 已提交
1528 1529
                Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
                Linkage::Static => Some(LinkagePreference::RequireStatic),
1530
            }));
1531
        }
1532
        Lazy::empty()
1533 1534
    }

M
Mark Rousskov 已提交
1535
    fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) {
1536
        let tcx = self.tcx;
1537

1538
        debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id);
1539

1540
        record!(self.tables.kind[def_id] <- match nitem.kind {
C
csmoe 已提交
1541
            hir::ForeignItemKind::Fn(_, ref names, _) => {
1542
                let data = FnData {
C
csmoe 已提交
1543
                    asyncness: hir::IsAsync::NotAsync,
1544 1545 1546 1547 1548
                    constness: if self.tcx.is_const_fn_raw(def_id) {
                        hir::Constness::Const
                    } else {
                        hir::Constness::NotConst
                    },
1549
                    param_names: self.encode_fn_param_names(names),
1550
                };
1551
                EntryKind::ForeignFn(self.lazy(data))
1552
            }
1553 1554
            hir::ForeignItemKind::Static(_, hir::Mutability::Mut) => EntryKind::ForeignMutStatic,
            hir::ForeignItemKind::Static(_, hir::Mutability::Not) => EntryKind::ForeignImmStatic,
C
csmoe 已提交
1555
            hir::ForeignItemKind::Type => EntryKind::ForeignType,
1556
        });
1557
        record!(self.tables.visibility[def_id] <-
1558
            ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx));
1559 1560
        record!(self.tables.span[def_id] <- nitem.span);
        record!(self.tables.attributes[def_id] <- nitem.attrs);
1561
        self.encode_ident_span(def_id, nitem.ident);
1562
        self.encode_stability(def_id);
1563
        self.encode_const_stability(def_id);
1564 1565 1566
        self.encode_deprecation(def_id);
        self.encode_item_type(def_id);
        if let hir::ForeignItemKind::Fn(..) = nitem.kind {
1567
            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
1568 1569 1570
            self.encode_variances_of(def_id);
        }
        self.encode_generics(def_id);
1571 1572
        self.encode_explicit_predicates(def_id);
        self.encode_inferred_outlives(def_id);
1573 1574
    }
}
1575

1576
// FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
1577
impl Visitor<'tcx> for EncodeContext<'tcx> {
1578 1579
    type Map = Map<'tcx>;

1580 1581
    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::OnlyBodies(self.tcx.hir())
1582
    }
C
Camille GILLOT 已提交
1583
    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
1584
        intravisit::walk_expr(self, ex);
1585
        self.encode_info_for_expr(ex);
1586
    }
B
ben 已提交
1587 1588 1589
    fn visit_anon_const(&mut self, c: &'tcx AnonConst) {
        intravisit::walk_anon_const(self, c);
        let def_id = self.tcx.hir().local_def_id(c.hir_id);
1590
        self.encode_info_for_anon_const(def_id);
B
ben 已提交
1591
    }
C
Camille GILLOT 已提交
1592
    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
1593
        intravisit::walk_item(self, item);
1594
        let def_id = self.tcx.hir().local_def_id(item.hir_id);
V
varkor 已提交
1595
        match item.kind {
M
Mark Rousskov 已提交
1596
            hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these
1597
            _ => self.encode_info_for_item(def_id.to_def_id(), item),
1598
        }
1599
        self.encode_addl_info_for_item(item);
1600
    }
1601
    fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
1602
        intravisit::walk_foreign_item(self, ni);
1603
        let def_id = self.tcx.hir().local_def_id(ni.hir_id);
1604
        self.encode_info_for_foreign_item(def_id.to_def_id(), ni);
1605
    }
C
Camille GILLOT 已提交
1606
    fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
1607
        intravisit::walk_generics(self, generics);
1608
        self.encode_info_for_generics(generics);
1609
    }
C
Camille GILLOT 已提交
1610
    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
1611
        self.encode_info_for_macro_def(macro_def);
1612 1613
    }
}
1614

1615
impl EncodeContext<'tcx> {
1616 1617
    fn encode_fields(&mut self, adt_def: &ty::AdtDef) {
        for (variant_index, variant) in adt_def.variants.iter_enumerated() {
1618
            for (field_index, _field) in variant.fields.iter().enumerate() {
1619
                self.encode_field(adt_def, variant_index, field_index);
1620 1621 1622
            }
        }
    }
1623

C
Camille GILLOT 已提交
1624
    fn encode_info_for_generics(&mut self, generics: &hir::Generics<'tcx>) {
C
Camille GILLOT 已提交
1625
        for param in generics.params {
1626
            let def_id = self.tcx.hir().local_def_id(param.hir_id);
V
varkor 已提交
1627
            match param.kind {
1628 1629
                GenericParamKind::Lifetime { .. } => continue,
                GenericParamKind::Type { ref default, .. } => {
1630
                    self.encode_info_for_generic_param(
1631
                        def_id.to_def_id(),
1632 1633
                        EntryKind::TypeParam,
                        default.is_some(),
1634
                    );
V
varkor 已提交
1635
                }
1636
                GenericParamKind::Const { .. } => {
1637 1638 1639 1640 1641
                    self.encode_info_for_generic_param(
                        def_id.to_def_id(),
                        EntryKind::ConstParam,
                        true,
                    );
V
varkor 已提交
1642
                }
V
varkor 已提交
1643
            }
V
varkor 已提交
1644
        }
1645
    }
1646

C
Camille GILLOT 已提交
1647
    fn encode_info_for_expr(&mut self, expr: &hir::Expr<'_>) {
1648 1649 1650
        if let hir::ExprKind::Closure(..) = expr.kind {
            let def_id = self.tcx.hir().local_def_id(expr.hir_id);
            self.encode_info_for_closure(def_id);
1651 1652 1653
        }
    }

1654
    fn encode_ident_span(&mut self, def_id: DefId, ident: Ident) {
1655
        record!(self.tables.ident_span[def_id] <- ident.span);
1656 1657
    }

1658 1659 1660 1661
    /// In some cases, along with the item itself, we also
    /// encode some sub-items. Usually we want some info from the item
    /// so it's easier to do that here then to wait until we would encounter
    /// normally in the visitor walk.
C
Camille GILLOT 已提交
1662
    fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
1663
        let def_id = self.tcx.hir().local_def_id(item.hir_id);
V
varkor 已提交
1664
        match item.kind {
M
Mark Rousskov 已提交
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675
            hir::ItemKind::Static(..)
            | hir::ItemKind::Const(..)
            | hir::ItemKind::Fn(..)
            | hir::ItemKind::Mod(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::Use(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::OpaqueTy(..)
            | hir::ItemKind::TraitAlias(..) => {
1676 1677
                // no sub-item recording needed in these cases
            }
C
csmoe 已提交
1678
            hir::ItemKind::Enum(..) => {
1679 1680
                let def = self.tcx.adt_def(def_id.to_def_id());
                self.encode_fields(def);
1681

1682
                for (i, variant) in def.variants.iter_enumerated() {
1683
                    self.encode_enum_variant_info(def, i);
1684 1685

                    if let Some(_ctor_def_id) = variant.ctor_def_id {
1686
                        self.encode_enum_variant_ctor(def, i);
1687
                    }
1688
                }
1689
            }
C
csmoe 已提交
1690
            hir::ItemKind::Struct(ref struct_def, _) => {
1691 1692
                let def = self.tcx.adt_def(def_id.to_def_id());
                self.encode_fields(def);
1693

1694
                // If the struct has a constructor, encode it.
1695
                if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
1696
                    let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
1697
                    self.encode_struct_ctor(def, ctor_def_id.to_def_id());
1698 1699
                }
            }
C
csmoe 已提交
1700
            hir::ItemKind::Union(..) => {
1701 1702
                let def = self.tcx.adt_def(def_id.to_def_id());
                self.encode_fields(def);
1703
            }
1704
            hir::ItemKind::Impl { .. } => {
1705 1706 1707
                for &trait_item_def_id in
                    self.tcx.associated_item_def_ids(def_id.to_def_id()).iter()
                {
1708
                    self.encode_info_for_impl_item(trait_item_def_id);
1709 1710
                }
            }
C
csmoe 已提交
1711
            hir::ItemKind::Trait(..) => {
1712
                for &item_def_id in self.tcx.associated_item_def_ids(def_id.to_def_id()).iter() {
1713
                    self.encode_info_for_trait_item(item_def_id);
1714 1715
                }
            }
1716
        }
1717 1718
    }
}
1719

1720
struct ImplVisitor<'tcx> {
1721
    tcx: TyCtxt<'tcx>,
1722 1723 1724
    impls: FxHashMap<DefId, Vec<DefIndex>>,
}

1725
impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
C
Camille GILLOT 已提交
1726
    fn visit_item(&mut self, item: &hir::Item<'_>) {
1727
        if let hir::ItemKind::Impl { .. } = item.kind {
1728
            let impl_id = self.tcx.hir().local_def_id(item.hir_id);
1729 1730
            if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id.to_def_id()) {
                self.impls.entry(trait_ref.def_id).or_default().push(impl_id.local_def_index);
1731 1732 1733 1734
            }
        }
    }

C
Camille GILLOT 已提交
1735
    fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem<'v>) {}
1736

C
Camille GILLOT 已提交
1737
    fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem<'v>) {
1738
        // handled in `visit_item` above
1739 1740 1741
    }
}

1742
/// Used to prefetch queries which will be needed later by metadata encoding.
J
John Kåre Alsaker 已提交
1743
/// Only a subset of the queries are actually prefetched to keep this code smaller.
1744 1745
struct PrefetchVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
1746
    mir_keys: &'tcx FxHashSet<LocalDefId>,
1747 1748 1749
}

impl<'tcx> PrefetchVisitor<'tcx> {
1750
    fn prefetch_mir(&self, def_id: LocalDefId) {
1751
        if self.mir_keys.contains(&def_id) {
1752 1753
            self.tcx.ensure().optimized_mir(def_id);
            self.tcx.ensure().promoted_mir(def_id);
1754 1755 1756 1757 1758 1759
        }
    }
}

impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
    fn visit_item(&self, item: &hir::Item<'_>) {
J
John Kåre Alsaker 已提交
1760
        // This should be kept in sync with `encode_info_for_item`.
1761 1762 1763 1764 1765 1766 1767
        let tcx = self.tcx;
        match item.kind {
            hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
                self.prefetch_mir(tcx.hir().local_def_id(item.hir_id))
            }
            hir::ItemKind::Fn(ref sig, ..) => {
                let def_id = tcx.hir().local_def_id(item.hir_id);
1768
                let generics = tcx.generics_of(def_id.to_def_id());
1769
                let needs_inline = generics.requires_monomorphization(tcx)
1770
                    || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
1771 1772 1773 1774 1775 1776 1777 1778 1779
                if needs_inline || sig.header.constness == hir::Constness::Const {
                    self.prefetch_mir(def_id)
                }
            }
            _ => (),
        }
    }

    fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) {
J
John Kåre Alsaker 已提交
1780
        // This should be kept in sync with `encode_info_for_trait_item`.
1781 1782 1783 1784
        self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id));
    }

    fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
J
John Kåre Alsaker 已提交
1785
        // This should be kept in sync with `encode_info_for_impl_item`.
1786 1787 1788 1789 1790 1791 1792
        let tcx = self.tcx;
        match impl_item.kind {
            hir::ImplItemKind::Const(..) => {
                self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id))
            }
            hir::ImplItemKind::Fn(ref sig, _) => {
                let def_id = tcx.hir().local_def_id(impl_item.hir_id);
1793
                let generics = tcx.generics_of(def_id.to_def_id());
1794
                let needs_inline = generics.requires_monomorphization(tcx)
1795
                    || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
1796 1797 1798 1799 1800
                let is_const_fn = sig.header.constness == hir::Constness::Const;
                if needs_inline || is_const_fn {
                    self.prefetch_mir(def_id)
                }
            }
M
Matthew Jasper 已提交
1801
            hir::ImplItemKind::TyAlias(..) => (),
1802 1803 1804 1805
        }
    }
}

1806 1807 1808 1809 1810 1811
// NOTE(eddyb) The following comment was preserved for posterity, even
// though it's no longer relevant as EBML (which uses nested & tagged
// "documents") was replaced with a scheme that can't go out of bounds.
//
// And here we run into yet another obscure archive bug: in which metadata
// loaded from archives may have trailing garbage bytes. Awhile back one of
1812
// our tests was failing sporadically on the macOS 64-bit builders (both nopt
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
// and opt) by having ebml generate an out-of-bounds panic when looking at
// metadata.
//
// Upon investigation it turned out that the metadata file inside of an rlib
// (and ar archive) was being corrupted. Some compilations would generate a
// metadata file which would end in a few extra bytes, while other
// compilations would not have these extra bytes appended to the end. These
// extra bytes were interpreted by ebml as an extra tag, so they ended up
// being interpreted causing the out-of-bounds.
//
// The root cause of why these extra bytes were appearing was never
// discovered, and in the meantime the solution we're employing is to insert
// the length of the metadata to the start of the metadata. Later on this
// will allow us to slice the metadata to the precise length that we just
// generated regardless of trailing bytes that end up in it.

1829
pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
1830 1831 1832 1833
    // Since encoding metadata is not in a query, and nothing is cached,
    // there's no need to do dep-graph tracking for any of it.
    tcx.dep_graph.assert_ignored();

1834 1835 1836
    join(
        || encode_metadata_impl(tcx),
        || {
1837 1838 1839 1840
            if tcx.sess.threads() == 1 {
                return;
            }
            // Prefetch some queries used by metadata encoding.
J
John Kåre Alsaker 已提交
1841 1842
            // This is not necessary for correctness, but is only done for performance reasons.
            // It can be removed if it turns out to cause trouble or be detrimental to performance.
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
            join(
                || {
                    if !tcx.sess.opts.output_types.should_codegen() {
                        // We won't emit MIR, so don't prefetch it.
                        return;
                    }
                    tcx.hir().krate().par_visit_all_item_likes(&PrefetchVisitor {
                        tcx,
                        mir_keys: tcx.mir_keys(LOCAL_CRATE),
                    });
                },
                || tcx.exported_symbols(LOCAL_CRATE),
            );
1856 1857 1858 1859 1860 1861
        },
    )
    .0
}

fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
1862 1863
    let mut encoder = opaque::Encoder::new(vec![]);
    encoder.emit_raw_bytes(METADATA_HEADER);
1864

1865
    // Will be filled with the root position after encoding everything.
1866
    encoder.emit_raw_bytes(&[0, 0, 0, 0]);
1867

1868 1869 1870
    let mut ecx = EncodeContext {
        opaque: encoder,
        tcx,
1871
        tables: Default::default(),
1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
        lazy_state: LazyState::NoNode,
        type_shorthands: Default::default(),
        predicate_shorthands: Default::default(),
        source_file_cache: tcx.sess.source_map().files()[0].clone(),
        interpret_allocs: Default::default(),
        interpret_allocs_inverse: Default::default(),
    };

    // Encode the rustc version string in a predictable location.
    rustc_version().encode(&mut ecx).unwrap();

    // Encode all the entries and extra information in the crate,
    // culminating in the `CrateRoot` which points to all of it.
    let root = ecx.encode_crate_root();

    let mut result = ecx.opaque.into_inner();
1888

1889 1890
    // Encode the root position.
    let header = METADATA_HEADER.len();
1891
    let pos = root.position.get();
1892 1893
    result[header + 0] = (pos >> 24) as u8;
    result[header + 1] = (pos >> 16) as u8;
1894 1895
    result[header + 2] = (pos >> 8) as u8;
    result[header + 3] = (pos >> 0) as u8;
G
Graydon Hoare 已提交
1896

1897
    EncodedMetadata { raw_data: result }
1898
}